From ec4860cd8ce31feaf8b8a3eb924e5e3cdd18cea5 Mon Sep 17 00:00:00 2001 From: baobrien Date: Thu, 4 Feb 2016 08:12:34 +0000 Subject: [PATCH] Started extracting important bits from mancyfsk.m for C port git-svn-id: https://svn.code.sf.net/p/freetel/code@2681 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/fmfsk.m | 134 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 codec2-dev/octave/fmfsk.m diff --git a/codec2-dev/octave/fmfsk.m b/codec2-dev/octave/fmfsk.m new file mode 100644 index 00000000..156ce2b6 --- /dev/null +++ b/codec2-dev/octave/fmfsk.m @@ -0,0 +1,134 @@ +% +% fmfsk.m +% Author: Brady O'Brien 3 Feb 2016 +% Copyright 2016 David Rowe +% +% All rights reserved. +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU Lesser General Public License veRbion 2, as +% published by the Free Software Foundation. This program is +% distributed in the hope that it will be useful, but WITHOUT ANY +% WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU Lesser General Public License +% along with this program; if not, see . + +% mancyfsk.m modem, extracted and made suitable for C implementation + + +1; + +% Init fmfsk modem +%Fs is sample frequency +%Rb is pre-manchester bit rate +function states = fmfsk_init(Fs,Rb) + assert(floor(Fs/(Rb*2))==(Fs/(Rb*2))); + assert(mod(Fs,Rb*2)==0); + + states.Rb = Rb; + states.Rs = Rb*2; % Manchester-encoded bitrate + states.Fs = Fs; + states.Ts = Fs/states.Rs; + % Processing buffer size. about 40ms here + states.N = floor(states.Rs*.040)*states.Ts; + states.nin = states.N; % Samples in the next demod cycle + states.nstash = states.Ts*2; % How many samples to stash away between proc cycles for timing adjust + states.nmem = states.N+(4*states.Ts); + states.nsym = floor(states.Rs*.040) + %Old sample memory + %states.oldsamps = zeros(1,states.nstash); + + states.oldsamps = zeros(1,states.nmem); + + %Last sampled-stream output, for odd bitstream generation + states.lastint = 0; + + %Some stats + states.norm_rx_timing = 0; + +endfunction + +%Generate a stream of manchester-coded bits to be sent +% to any ordinary FM modulator or VCO or something +function tx = fmfsk_mod(states,inbits) + Ts = states.Ts; + tx = zeros(1,length(inbits)*2); + for ii = 1:length(inbits) + st = 1 + (ii-1)*Ts*2; + md = st+Ts-1; + en = md+Ts; + if inbits(ii)==0 + tx(st:md) = -ones(1,Ts); + tx(md+1:en) = ones(1,Ts); + else + tx(st:md) = ones(1,Ts); + tx(md+1:en) = -ones(1,Ts); + end + end +endfunction + +%Demodulate a bag of bits from the output of an FM demodulator +% This function produces nbits output bits and takes states.nin samples +function [rx_bits states] = fmfsk_demod(states,rx) + Ts = states.Ts; + Fs = states.Fs; + Rs = states.Rs; + nin = states.nin; + N = states.N; + nsym = states.nsym; + nbits = states.nsym/2; + nmem = states.nmem; + nstash = states.nstash; + + nold = nmem-nin; + ssamps = states.oldsamps; + + %Shift in nin samples + ssamps(1:nold) = ssamps(nmem-nold+1:nmem); + ssamps(nold+1:nmem) = rx; + stats.oldsamps = ssamps; + + rx_filt = zeros(1,nsym*Ts); + %Integrate Ts input samples at every offset + %This is the same thing as filtering with a filter of all ones + % out to Ts. + % It's implemented like this for ease of C-porting + for ii=(1:(nsym+1)*Ts) + st = ii; + en = st+Ts-1; + rx_filt(ii) = sum(ssamps(st:en)); + end + + % Fine timing estimation ------------------------------------------------------ + + % Estimate fine timing using line at Rs/2 that Manchester encoding provides + % We need this to sync up to Manchester codewords. + Np = length(rx_filt); + w = 2*pi*(Rs)/Fs; + x = (rx_filt .^ 2) * exp(-j*w*(0:Np-1))'; + norm_rx_timing = angle(x)/(2*pi) - 0.42 + rx_timing = round(norm_rx_timing*Ts) + + %If rx timing is too far out, ask for more or less sample the next time + % around to even it all out + next_nin = N; + if norm_rx_timing > 0.25 + next_nin += Ts/2; + end + if norm_rx_timing < -0.25; + next_nin -= Ts/2; + end + states.nin = next_nin; + + % Sample rx_filt at the optimum inst, as figured by rx_timing + rx_symsamp = rx_filt((Ts/2)+Ts+rx_timing:Ts:length(rx_filt)); + length(rx_symsamp) + + rx_bits = zeros(1,nbits); + + +endfunction + -- 2.25.1