Started extracting important bits from mancyfsk.m for C port
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 4 Feb 2016 08:12:34 +0000 (08:12 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 4 Feb 2016 08:12:34 +0000 (08:12 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2681 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fmfsk.m [new file with mode: 0644]

diff --git a/codec2-dev/octave/fmfsk.m b/codec2-dev/octave/fmfsk.m
new file mode 100644 (file)
index 0000000..156ce2b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+% 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
+