Further cleanup and documentation of FSK modem
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 22 Jan 2016 02:40:37 +0000 (02:40 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 22 Jan 2016 02:40:37 +0000 (02:40 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2640 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fsk_horus_2fsk.m
codec2-dev/octave/tfsk.m
codec2-dev/src/fsk.c
codec2-dev/src/fsk.h
codec2-dev/src/modem_probe.c
codec2-dev/src/modem_probe.h
codec2-dev/unittest/tfsk.c

index 49637c21147dd5d4f17225fd231b51e0031c65bf..4b92a00af6c59fc77497e9d972f61a74421db09d 100644 (file)
@@ -203,7 +203,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf)
   states.f1 = f1;
   states.f2 = f2;
 
-  %printf("ESTF - f1 = %d, f2 = %d, twist = %f \n",f1,f2,twist);
   if bitand(verbose,0x1)
     printf("centre: %4.0f shift: %4.0f twist: %3.1f dB\n", (f2+f1)/2, f2-f1, twist);
   end
@@ -248,8 +247,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf)
   % symbols so we have extra samples for the fine timing re-sampler at either
   % end of the array.
 
-
-  length(f1_dc);
   rx_bits = zeros(1, (nsym+1)*P);
   for i=1:(nsym+1)*P
     st = 1 + (i-1)*Ts/P;
@@ -259,7 +256,7 @@ function [rx_bits states] = fsk_horus_demod(states, sf)
   end
   states.f1_int = f1_int;
   states.f2_int = f2_int;
-  length(f1_dc);
+
   % fine timing estimation -----------------------------------------------
 
   % Non linearity has a spectral line at Rs, with a phase
@@ -270,10 +267,7 @@ function [rx_bits states] = fsk_horus_demod(states, sf)
  
   Np = length(f1_int);
   w = 2*pi*(Rs)/(P*Rs);
-
-  %%# same as sum of ((abs(f1_int)-abs(f2_int)).^2) .* exp(-j*w*(0:Np-1))
   x = ((abs(f1_int)-abs(f2_int)).^2) * exp(-j*w*(0:Np-1))';
-  
   norm_rx_timing = angle(x)/(2*pi);
   rx_timing = norm_rx_timing*P;
 
@@ -329,8 +323,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf)
     %f1_int_resample(i) = f1_int(st+1);
     %f2_int_resample(i) = f2_int(st+1);
     rx_bits(i) = abs(f2_int_resample(i)) > abs(f1_int_resample(i));
-    
-    
     rx_bits_sd(i) = abs(f2_int_resample(i)) - abs(f1_int_resample(i));
  end
 
@@ -342,7 +334,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf)
 
   x = abs(abs(f1_int_resample) - abs(f2_int_resample));
   states.EbNodB = 20*log10(1E-6+mean(x)/(1E-6+std(x)));
- % printf("EbNodB %f\n",states.EbNodB);
 endfunction
 
 
@@ -350,7 +341,7 @@ endfunction
 % UW found Sometimes there may be several matches, returns the
 % position of the best match to UW.
 
-function [uw_start best_corr] = find_uw(states, start_bit, rx_bits)
+function uw_start = find_uw(states, start_bit, rx_bits)
   uw = states.uw;
 
   mapped_rx_bits = 2*rx_bits - 1;
@@ -494,21 +485,19 @@ function extract_and_print_rtty_packets(states, rx_bits_log, rx_bits_sd_log)
 
       if crc_ok == 0
         [str_flipped crc_flipped_ok rx_bits_log] = sd_bit_flipping(states.rtty, rx_bits_log, rx_bits_sd_log, uw_loc, uw_loc+states.rtty.max_packet_len); 
+        if crc_flipped_ok
+          str = sprintf("%s fixed", str_flipped);
+        end
       end
 
       % update memory of previous packet, we use this to guess where errors may be
       if crc_ok || crc_flipped_ok
         states.prev_pkt = rx_bits_log(uw_loc+length(states.rtty.uw):uw_loc+states.rtty.max_packet_len);
       end
-
       if crc_ok
         str = sprintf("%s CRC OK", str);
       else
-        if crc_flipped_ok
-          str = sprintf("%s fixed", str_flipped);
-        else
-          str = sprintf("%s CRC BAD", str);
-        end
+        str = sprintf("%s CRC BAD", str);
       end
       printf("%s\n", str);
     end
@@ -522,7 +511,7 @@ function extract_and_print_rtty_packets(states, rx_bits_log, rx_bits_sd_log)
 endfunction
  
 
-% Extract as many binary packets as we can from a great big buffer of bits,
+% Extract as many ASCII packets as we can from a great big buffer of bits,
 % and send them to the C decoder for FEC decoding.
 % horus_l2 can be compiled a bunch of different ways.  You need to
 % compile with:
@@ -641,7 +630,6 @@ function run_sim(test_frame_mode)
     states.f1_tx = 1200;
     states.f2_tx = 1600;
     states.tx_bits_file = "horus_tx_bits_rtty.txt"; % Octave file of bits we FSK modulate
-    
   end
                                
   if test_frame_mode == 5
@@ -649,8 +637,7 @@ function run_sim(test_frame_mode)
     states = fsk_horus_init(8000, 100);
     states.f1_tx = 1200;
     states.f2_tx = 1600;
-    %%%states.tx_bits_file = "horus_tx_bits_binary.txt"; % Octave file of bits we FSK modulate
-       states.tx_bits_file = "horus_payload_rtty.txt"
+    states.tx_bits_file = "horus_tx_bits_binary.txt"; % Octave file of bits we FSK modulate
   end
 
   % ----------------------------------------------------------------------
@@ -845,7 +832,7 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot)
     uwstates = fsk_horus_init_binary_uw;
   end
 
-  states.verbose = 0x1;
+  states.verbose = 0x1 + 0x8;
 
   N = states.N;
   P = states.P;
@@ -863,8 +850,6 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot)
   f2_int_resample_log = [];
   EbNodB_log = [];
   ppm_log = [];
-  f1_log = [];
-  f2_log = [];
   rx_bits_buf = zeros(1,2*nsym);
 
   % First extract raw bits from samples ------------------------------------------------------
@@ -902,8 +887,6 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot)
       f2_int_resample_log = [f2_int_resample_log abs(states.f2_int_resample)];
       EbNodB_log = [EbNodB_log states.EbNodB];
       ppm_log = [ppm_log states.ppm];
-      f1_log = [f1_log states.f1];
-      f2_log = [f2_log states.f2];
 
       if test_frame_mode == 1
         states = ber_counter(states, test_frame, rx_bits_buf);
@@ -921,18 +904,12 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot)
     printf("plotting...\n");
 
     figure(1);
-    plot(f1_log);
-    hold on;
-    plot(f2_log,'g');
-    hold off;
-
-    figure(2);
     plot(f1_int_resample_log,'+')
     hold on;
     plot(f2_int_resample_log,'g+')
     hold off;
 
-    figure(3)
+    figure(2)
     clf
     subplot(211)
     plot(norm_rx_timing_log)
@@ -943,29 +920,28 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot)
     plot(states.nerr_log)
     title('num bit errors each frame')
  
-    figure(4)
+    figure(3)
     clf
     plot(EbNodB_log);
     title('Eb/No estimate')
 
-    figure(5)
+    figure(4)
     clf
-    rx_nowave = rx(1000:length(rx));
     subplot(211)
-    plot(rx_nowave(1:states.Fs));
+    plot(rx(1:states.Fs));
     title('input signal to demod (1 sec)')
     xlabel('Time (samples)');
     axis([1 states.Fs -35000 35000])
 
-    % normalise spectrum to 0dB full scale with a 32767 sine wave input
+    % normalise spectrum to 0dB full scale witha 32767 sine wave input
 
     subplot(212)
-    RxdBFS = 20*log10(abs(fft(rx_nowave(1:states.Fs)))) - 20*log10((states.Fs/2)*32767);
+    RxdBFS = 20*log10(abs(fft(rx(1:states.Fs)))) - 20*log10((states.Fs/2)*32767);
     plot(RxdBFS)
     axis([1 states.Fs/2 -80 0])
     xlabel('Frequency (Hz)');
 
-    figure(6);
+    figure(5);
     clf
     plot(ppm_log)
     title('Sample clock (baud rate) offset in PPM');
@@ -987,14 +963,10 @@ endfunction
 % run test functions from here during development
 
 if exist("fsk_horus_as_a_lib") == 0
-  run_sim(5);
+  %run_sim(5);
   %rx_bits = demod_file("horus.raw",4);
   %rx_bits = demod_file("fsk_horus_100bd_binary.raw",5);
-  %rx_bits = demod_file("~/Desktop/phorus_binary_ascii.wav",4);
-  %rx_bits = demod_file("~/Desktop/binary/horus_160102_binary_rtty_2.wav",4);
-  
-  
-  %rx_bits = demod_file("~/Desktop/horus_160102_vk5ei_capture2.wav",4);
+  rx_bits = demod_file("~/Desktop/phorus_binary_ascii.wav",4);
   %rx_bits = demod_file("~/Desktop/horus_rtty_binary.wav",4);
   %rx_bits = demod_file("t.raw",5);
   %rx_bits = demod_file("~/Desktop/fsk_horus_10dB_1000ppm.wav",4);
index 220529acf0b9be6b240cb85e4167062dcef85952..0ad7a477eb23a60ea419fade9020a91d1a87d31b 100644 (file)
@@ -1,6 +1,24 @@
 % tfsk.m
-% Brady O'Brien 8 January 2016
+% Author: Brady O'Brien 8 January 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 version 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/>.
+
+
 % Octave script to check c port of fsk_horus against the fsk_horus.m
 %
 % [X] - Functions to wrap around fsk_mod and fsk_demod executables
 %       same dataset, compare outputs, and give clear go/no-go
 %     [X] - fsk_mod_test
 %     [X] - fsk_demod_test
-% [.] - Port of run_sim and EbNodB curve test battery
-% [ ] - Extract and compare more parameters from demod
-% [ ] - Run some tests in parallel
+% [X] - Port of run_sim and EbNodB curve test battery
+% [X] - Extract and compare more parameters from demod
+% [X] - Run some tests in parallel
+
+%
+% FSK Modem test instructions --
+% 1 - Compile tfsk.c and fm_mod.c
+%     - tfsk.c is in unittest/, so build must not be configured for release
+% 2 - Change tfsk_location and fsk_mod_location to point to tfsk and fsk_mod
+% 3 - Ensure octave packages signal and parallel are installed
+% 4 - run tfsk.m. It will take care of the rest.
+%
+
+
+global tfsk_location = '../build/unittest/tfsk';
+global fsk_mod_location = '../build/src/fsk_mod';
+
 
 fsk_horus_as_a_lib = 1; % make sure calls to test functions at bottom are disabled
 fsk_horus_2fsk;  
 pkg load signal;
-
+pkg load parallel;
 graphics_toolkit('gnuplot');
 
 
 global mod_pass_fail_maxdiff = 1e-3/50000;
-global demod_pass_fail_maxdiff = .01;
 
 function mod = fsk_mod_c(Fs,Rs,f1,f2,bits)
     %Name of executable containing the modulator
@@ -45,34 +76,6 @@ function mod = fsk_mod_c(Fs,Rs,f1,f2,bits)
     
 endfunction
 
-function bits = fsk_demod_c(Fs,Rs,f1,f2,mod)
-    %Name of executable containing the modulator
-    fsk_demod_ex_file = '../build/unittest/tfsk';
-    modvecfilename = sprintf('fsk_demod_ut_modvec_%d',getpid());
-    bitvecfilename = sprintf('fsk_demod_ut_bitvec_%d',getpid());
-    tvecfilename = sprintf('fsk_demod_ut_tracevec_%d.txt',getpid());
-    
-    %command to be run by system to launch the demod
-    command = sprintf('%s %d %d %d %d %s %s %s',fsk_demod_ex_file,Fs,Rs,f1,f2,modvecfilename,bitvecfilename,tvecfilename);
-    
-    %save modulated input into a file
-    modvecfile = fopen(modvecfilename,'wb+');
-    fwrite(modvecfile,mod,'single');
-    fclose(modvecfile);
-    
-    %run the modulator
-    system(command);
-    
-    bitvecfile = fopen(bitvecfilename,'rb');
-    bits = fread(bitvecfile,'uint8');
-    fclose(bitvecfile);
-    bits = bits!=0;
-    
-    %Clean up files
-    delete(bitvecfilename);
-    delete(modvecfilename);
-    %delete(tvecfilename);
-endfunction
 
 %Compare 2 vectors, fail if they are not close enough
 function pass = vcompare(va,vb,vname,tname,tol)
@@ -138,12 +141,12 @@ function test_stats = fsk_demod_xt(Fs,Rs,f1,f2,mod,tname)
     delete(modvecfilename);
     delete(tvecfilename);
     
-    
     o_f1_dc = [];
     o_f2_dc = [];
     o_f1_int = [];
     o_f2_int = [];
     o_EbNodB = [];
+    o_ppm = [];
     o_rx_timing = [];
     %Run octave demod, dump some test vectors
     states = fsk_horus_init(Fs,Rs);
@@ -167,15 +170,17 @@ function test_stats = fsk_demod_xt(Fs,Rs,f1,f2,mod,tname)
         o_f1_int = [o_f1_int states.f1_int];
         o_f2_int = [o_f2_int states.f2_int];
         o_EbNodB = [o_EbNodB states.EbNodB];
+        o_ppm = [o_ppm states.ppm];
         o_rx_timing = [o_rx_timing states.rx_timing];
     end
     
     pass =         vcompare(o_rx_timing,  t_rx_timing,'rx_timing',tname,.011);
     pass = pass && vcompare(o_EbNodB,     t_EbNodB,   'EbNodB',   tname,.15);
+    pass = pass && vcompare(o_ppm   ,     t_ppm,      'ppm',      tname,.011);
     pass = pass && vcompare(o_f1_int,     t_f1_int,   'f1_int',   tname,.011);
     pass = pass && vcompare(o_f2_int,     t_f2_int,   'f2_int',   tname,.011);
-    pass = pass && vcompare(o_f1_dc(1:length(t_f1_dc)),  t_f1_dc,    'f1_dc',    tname,.001);
-    pass = pass && vcompare(o_f2_dc(1:length(t_f1_dc)),  t_f2_dc,    'f2_dc',    tname,.001);
+    pass = pass && vcompare(o_f1_dc,      t_f1_dc,    'f1_dc',    tname,.001);
+    pass = pass && vcompare(o_f2_dc,      t_f2_dc,    'f2_dc',    tname,.001);
     
     diffpass = sum(xor(obits,bits'))<3
     
@@ -213,39 +218,6 @@ function [dmod,cmod,omod,pass] = fsk_mod_test(Fs,Rs,f1,f2,bits,tname)
     end
 endfunction
 
-function [cbits,obits,pass] = fsk_demod_test(Fs,Rs,f1,f2,mod,tname)
-    global pass_fail_maxdiff;
-    %Run the C demodulator
-    cbits = fsk_demod_c(Fs,Rs,f1,f2,mod)';
-    %Set up and run the octave demodulator
-    states = fsk_horus_init(Fs,Rs);
-    states.f1_tx = f1;
-    states.f2_tx = f2;
-    states.dA = 1;
-    states.dF = 0;
-    
-    modin = mod;
-    obits = [];
-    while length(modin)>=states.nin
-        ninold = states.nin;
-        [bitbuf,states] = fsk_horus_demod(states, modin(1:states.nin));
-        modin=modin(ninold+1:length(modin));
-        obits = [obits bitbuf];
-    end
-    
-    diff = sum(xor(obits,cbits))
-    
-    %Allow 2 bit difference between model and C
-    pass = diff < 3
-    if !pass
-        printf('Demod failed test %s!\n',tname);
-        figure(10);
-        plot((1:length(obits)),obits,(1:length(cbits)),cbits);
-        figure(11);
-        plot(xor(obits,cbits));
-    end
-endfunction
-
 % Random bit modulator test
 % Pass random bits through the modulators and compare
 function pass = test_mod_horuscfg_randbits
@@ -432,3 +404,5 @@ function pass = test_fsk_battery()
         printf("***** All tests passed! *****\n");
     end
 endfunction
+
+test_fsk_battery
index f767cc103f081cd25e93657c073f67d68750c561..d37e7e747ae47a5459006758923bda576aeb7cbb 100644 (file)
@@ -113,8 +113,6 @@ struct FSK * fsk_create(int Fs, int Rs, int tx_f1,int tx_f2)
     fsk->nin = fsk->N;
     
     /* Set up rx state */
-    fsk->phi1_d = 0;
-    fsk->phi2_d = 0;
     fsk->phi1_c.real = 1;
     fsk->phi1_c.imag = 0;
     fsk->phi2_c.real = 1;
@@ -141,7 +139,6 @@ struct FSK * fsk_create(int Fs, int Rs, int tx_f1,int tx_f2)
     fsk->norm_rx_timing = 0;
     
     /* Set up tx state */
-    fsk->tx_phase = 0;
     fsk->tx_phase_c.imag = 0;
     fsk->tx_phase_c.real = 1;
     
@@ -269,7 +266,6 @@ void fsk_demod_freq_est(struct FSK *fsk, float fsk_in[],float *f1_est,float *f2_
     *f1_est = (float)m1*(float)Fs/(float)Ndft;
     *f2_est = (float)m2*(float)Fs/(float)Ndft;
     *twist = 20*log10f(m1v/m2v);
-    //printf("ESTF - f1 = %f, f2 = %f, twist = %f \n",*f1_est,*f2_est,*twist);
 
 }
 
@@ -330,12 +326,12 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
     COMP t1,t2;
     COMP phi1_c = fsk->phi1_c;
     COMP phi2_c = fsk->phi2_c;
-    COMP phi_ft;                 /* Phase of fine timing estimator */
+    COMP phi_ft;
     int nold = Nmem-nin;
     COMP dphi1,dphi2;
     COMP dphift;
     float f1,f2;
-    float rx_timing,norm_rx_timing;//,old_norm_rx_timing;//,d_norm_rx_timing;
+    float rx_timing,norm_rx_timing,old_norm_rx_timing,d_norm_rx_timing,appm;
     int using_old_samps;
     float *sample_src;
     COMP *f1_intbuf,*f2_intbuf;
@@ -417,12 +413,7 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
         if(cbuf_i>=Ts) cbuf_i = 0;
         
         /* Integrate over the integration buffers, save samples */
-        /* This uses Kahan summation to reduce floating point funnyness */
         t1 = t2 = comp0();
-        f1_strc = f1_stic = 0;
-        f2_strc = f2_stic = 0;
-        f1_strs = f1_stis = 0;
-        f2_strs = f2_stis = 0;
         for(j=0; j<Ts; j++){
             t1 = cadd(t1,f1_intbuf[j]);
             t2 = cadd(t2,f2_intbuf[j]);
@@ -442,9 +433,6 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
     /* Apply magic nonlinearity to f1_int and f2_int, shift down to 0, 
      * exract angle */
      
-    float ft_rc,ft_rs,ft_ic,ft_is;
-    ft_rc = ft_rs = 0;
-    ft_ic = ft_is = 0;
     /* Figure out how much to spin the oscillator to extract magic spectral line */
     dphift = comp_exp_j(-2*M_PI*((float)(Rs)/(float)(P*Rs)));
     phi_ft.real = 1;
@@ -458,24 +446,27 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
         /* Add and square 'em */
         ft1 = ft1-ft2;
         ft1 = ft1*ft1;
-        /* Spin the oscillator for the magic line shift */
         /* Down shift and accumulate magic line */
         t1 = cadd(t1,fcmult(ft1,phi_ft));
 
+        /* Spin the oscillator for the magic line shift */
         phi_ft = cmult(phi_ft,dphift);
     }
     /* Get the magic angle */
     norm_rx_timing =  -atan2f(t1.imag,t1.real)/(2*M_PI);
     rx_timing = norm_rx_timing*(float)P;
     
-    //old_norm_rx_timing = fsk->norm_rx_timing;
+    old_norm_rx_timing = fsk->norm_rx_timing;
     fsk->norm_rx_timing = norm_rx_timing;
     
     /* Estimate sample clock offset */
-    //d_norm_rx_timing = norm_rx_timing - old_norm_rx_timing;
+    d_norm_rx_timing = norm_rx_timing - old_norm_rx_timing;
     
     /* Filter out big jumps in due to nin change */
-    //if(fabsf(d_norm_rx_timing) < .2){
+    if(fabsf(d_norm_rx_timing) < .2){
+        appm = 1e6*d_norm_rx_timing/(float)nsym;
+        fsk->ppm = .9*fsk->ppm + .1*appm;
+    }
     
     /* Figure out how many samples are needed the next modem cycle */
     if(norm_rx_timing > 0.25)
@@ -494,6 +485,7 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
     
     #ifdef EST_EBNO
     meanebno = 0;
+    stdebno = 0;
     #endif
   
     /* FINALLY, THE BITS */
@@ -506,11 +498,14 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
         t2 = cadd(t2,fcmult(  fract,f2_int[st+high_sample]));
         
         /* Accumulate resampled int magnitude for EbNodB estimation */
+        /* Standard deviation is calculated by algorithm devised by crafty soviets */
         #ifdef EST_EBNO
+        
         ft1 = sqrtf(t1.real*t1.real + t1.imag*t1.imag);
         ft2 = sqrtf(t2.real*t2.real + t2.imag*t2.imag);
         ft1 = fabsf(ft1-ft2);
         meanebno += ft1;
+        
         #endif
         
         /* THE BIT! */
@@ -546,6 +541,7 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
     
     /* Dump some internal samples */
     modem_probe_samp_f("t_EbNodB",&(fsk->EbNodB),1);
+    modem_probe_samp_f("t_ppm",&(fsk->ppm),1);
     modem_probe_samp_f("t_f1",&f1,1);
     modem_probe_samp_f("t_f2",&f2,1);
     modem_probe_samp_c("t_f1_int",f1_int,(nsym+1)*P);
@@ -553,42 +549,6 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){
     modem_probe_samp_f("t_rx_timing",&(rx_timing),1);;
 }
 
-
-void fsk_mod_realphase(struct FSK *fsk,float fsk_out[],uint8_t tx_bits[]){
-    float tx_phase = fsk->tx_phase; /* current TX phase */
-    int f1_tx = fsk->f1_tx;         /* '0' frequency */
-    int f2_tx = fsk->f2_tx;         /* '1' frequency */
-    int Ts = fsk->Ts;               /* samples-per-symbol */
-    int Fs = fsk->Fs;               /* sample freq */
-    int i,j;
-    uint8_t bit;
-    
-    /* delta-phase per cycle for both symbol freqs */
-    float dph_f1 = 2*M_PI*((float)(f1_tx)/(float)(Fs));
-    float dph_f2 = 2*M_PI*((float)(f2_tx)/(float)(Fs));
-
-    /* Note: Right now, this mirrors fm.c and fsk_horus.m, but it
-     * ought to be possible to make it more efficent (one complex mul per
-     * cycle) by using a complex number for the phase. */
-     
-    /* Outer loop through bits */
-    for(i=0; i<fsk->Nsym; i++){
-        bit = tx_bits[i];
-        for(j=0; j<Ts; j++){
-            /* Nudge phase forward a bit */
-            tx_phase += (bit==0)?dph_f1:dph_f2;
-            /* Make sure phase stays on [0,2pi] */
-            if(tx_phase>2*M_PI)
-                tx_phase -= 2*M_PI;
-            fsk_out[i*Ts+j] = 2*cosf(tx_phase);
-        }
-    }
-    
-    /* save TX phase */
-    fsk->tx_phase = tx_phase;
-    
-}
-
 void fsk_mod(struct FSK *fsk,float fsk_out[],uint8_t tx_bits[]){
     COMP tx_phase_c = fsk->tx_phase_c; /* Current complex TX phase */
     int f1_tx = fsk->f1_tx;         /* '0' frequency */
index 35ef7b132f74af63e3dc54a33633f57b2df82be6..90dcdfd2391839d4166f97bdb7602dff398daaf7 100644 (file)
@@ -46,20 +46,17 @@ struct FSK {
     int f2_tx;              /* f2 for modulator */
     
     /*  Parameters used by demod */
-    float phi1_d;           /* f1 oscillator for demod */
-    float phi2_d;           /* f2 oscillator for demod */
     COMP phi1_c;
     COMP phi2_c;
     kiss_fftr_cfg fft_cfg;  /* Config for KISS FFT, used in freq est */
     float norm_rx_timing;   /* Normalized RX timing */
     
-    float *samp_old;        /* Ass end of last batch of samples */
+    float *samp_old;        /* Tail end of last batch of samples */
     int nstash;             /* How many elements are in there */
     
     /* Memory used by demod but not important between demod frames */
     
     /*  Parameters used by mod */
-    float tx_phase;         /* phase of modulator */
     COMP tx_phase_c;        /* TX phase, but complex */ 
     
     /*  Statistics generated by demod */
@@ -67,28 +64,58 @@ struct FSK {
     float f1_est;           /* Estimated f1 freq. */
     float f2_est;           /* Estimated f2 freq. */
     float twist_est;        /* Estimaged 'twist' from freq est */
+    float ppm;              /* Estimated PPM clock offset */
     
     /*  Parameters used by mod/demod and driving code */
     int nin;                /* Number of samples to feed the next demod cycle */
     
 };
 
+/*
+ * Create an FSK config/state struct from a set of config parameters
+ * 
+ * int Fs - Sample frequency
+ * int Rs - Symbol rate
+ * int tx_f1 - '0' frequency
+ * int tx_f2 - '1' frequency
+ */
 struct FSK * fsk_create(int Fs, int Rs, int tx_f1, int tx_f2);
+
+/*
+ * Destroy an FSK state struct and free it's memory
+ * 
+ * struct FSK *fsk - FSK config/state struct to be destroyed
+ */
 void fsk_destroy(struct FSK *fsk);
 
-void fsk_mod(struct FSK *fsk, 
-             float fsk_out[],   /* N float output modulated FSK samples */
-             uint8_t tx_bits[]  /* Nsym unpacked input bits in LSB  */
-             );
+/*
+ * Modulates Nsym bits into N samples
+ * 
+ * struct FSK *fsk - FSK config/state struct, set up by fsk_create
+ * float fsk_out[] - Buffer for N samples of modulated FSK
+ * uint8_t tx_bits[] - Buffer containing Nsym unpacked bits
+ */
+void fsk_mod(struct FSK *fsk, float fsk_out[], uint8_t tx_bits[]);
 
-/* number of input samples required for next call to fsk_demod() */
 
+/*
+ * Returns the number of samples needed for the next fsk_demod() cycle
+ *
+ * struct FSK *fsk - FSK config/state struct, set up by fsk_create
+ * returns - number of samples to be fed into fsk_demod next cycle 
+ */
 uint32_t fsk_nin(struct FSK *fsk);
 
-void fsk_demod(struct FSK *fsk, 
-               uint8_t rx_bits[],     /* Nsym unpacked output demodulated rx bits in each LSB */
-               float fsk_in[]         /* N input float modulated FSK samples */
-               );
+
+/*
+ * Demodulate some number of FSK samples. The number of samples to be 
+ *  demodulated can be found by calling fsk_nin().
+ * 
+ * struct FSK *fsk - FSK config/state struct, set up by fsk_create
+ * uint8_t rx_bits[] - Buffer for Nsym unpacked bits to be written
+ * float fsk_in[] - nin samples of modualted FSK
+ */
+void fsk_demod(struct FSK *fsk, uint8_t rx_bits[],float fsk_in[]);
 
 
 
index 612d33505087670b64f5c69f2adc614359e78654..884a1a8566b7e9b4ef42ceebae7ff986f7f619bc 100644 (file)
@@ -4,7 +4,8 @@
   AUTHOR......: Brady O'Brien
   DATE CREATED: 9 January 2016
 
-  Library to easily extract debug traces from modems during development
+  Library to easily extract debug traces from modems during development and
+  verification
 
 \*---------------------------------------------------------------------------*/
 
@@ -110,7 +111,7 @@ void modem_probe_close_int(){
                switch(cur->type){
                        case TRACE_I:
                                octave_save_int(dumpfile,cur->name,(int32_t*)dbuf,1,len/sizeof(int32_t));
-                               break;
+                       break;
                        case TRACE_F:
                                octave_save_float(dumpfile,cur->name,(float*)dbuf,1,len/sizeof(float),10);
                                break;
index 320acaaee741e9ebd4ae16bd290147e47513415d..2faada13115ec457b4c481dd616bd3ccf35d1884 100644 (file)
@@ -34,6 +34,7 @@
 
 #ifdef MODEMPROBE_ENABLE
 
+/* Internal functions */
 void modem_probe_init_int(char *modname, char *runname);
 void modem_probe_close_int();
 
@@ -41,48 +42,72 @@ void modem_probe_samp_i_int(char * tracename,int samp[],size_t cnt);
 void modem_probe_samp_f_int(char * tracename,float samp[],size_t cnt);
 void modem_probe_samp_c_int(char * tracename,COMP samp[],size_t cnt);
 
-
+/* 
+ * Init the probe library.
+ * char *modname - Name of the modem under test
+ * char *runname - Name/path of the file data is dumped to
+ */
 static inline void modem_probe_init(char *modname,char *runname){
-       modem_probe_init_int(modname,runname);
+        modem_probe_init_int(modname,runname);
 }
 
+/*
+ * Dump traces to a file and clean up
+ */
 static inline void modem_probe_close(){
-       modem_probe_close_int();
+        modem_probe_close_int();
 }
 
+/*
+ * Save some number of int samples to a named trace
+ * char *tracename - name of trace being saved to
+ * int samp[] - int samples
+ * size_t cnt - how many samples to save
+ */
 static inline void modem_probe_samp_i(char *tracename,int samp[],size_t cnt){
-       modem_probe_samp_i_int(tracename,samp,cnt);
+        modem_probe_samp_i_int(tracename,samp,cnt);
 }
 
-
+/*
+ * Save some number of float samples to a named trace
+ * char *tracename - name of trace being saved to
+ * float samp[] - int samples
+ * size_t cnt - how many samples to save
+ */
 static inline void modem_probe_samp_f(char *tracename,float samp[],size_t cnt){
-       modem_probe_samp_f_int(tracename,samp,cnt);
-}      
+        modem_probe_samp_f_int(tracename,samp,cnt);
+}       
 
+/*
+ * Save some number of complex samples to a named trace
+ * char *tracename - name of trace being saved to
+ * COMP samp[] - int samples
+ * size_t cnt - how many samples to save
+ */
 static inline void modem_probe_samp_c(char *tracename,COMP samp[],size_t cnt){
-       modem_probe_samp_c_int(tracename,samp,cnt);
+        modem_probe_samp_c_int(tracename,samp,cnt);
 }
 
 #else
 
 static inline void modem_probe_init(char *modname,char *runname){
-       return;
+        return;
 }
 
 static inline void modem_probe_close(){
-       return;
+        return;
 }
 
 static inline void modem_probe_samp_i(char *name,int samp[],size_t sampcnt){
-       return;
+        return;
 }
 
 static inline void modem_probe_samp_f(char *name,float samp[],size_t cnt){
-       return;
+        return;
 }
 
 static inline void modem_probe_samp_c(char *name,COMP samp[],size_t cnt){
-       return;
+        return;
 }
 
 #endif
index ae852423e65ecd19f42322b34565ad9acb2df33e..c31996c1836e85696ccf2bf82c93ef41e33472a6 100644 (file)
@@ -6,7 +6,7 @@
 
   C test driver for fsk_mod and fsk_demod in fsk.c. Reads a file with input
   bits/rf and spits out modulated/demoduladed samples and a dump of internal
-  state 
+  state. To run unit test, see octave/tfsk.m
 
 \*---------------------------------------------------------------------------*/