C and Octave versions of fdmdv_demod now exactly the same, and have the same instrume...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 3 May 2012 06:33:49 +0000 (06:33 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 3 May 2012 06:33:49 +0000 (06:33 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@391 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fdmdv_demod.m
codec2-dev/octave/fdmdv_demod_c.m
codec2-dev/src/fdmdv_demod.c
codec2-dev/src/octave.c
codec2-dev/src/octave.h
codec2-dev/unittest/tfdmdv.c

index b30b497c7c32fdecf7b9dca23d36bc5229019c2a..0ef4f6736828540c9d3cf26bc7622c64ce3c28f0 100644 (file)
@@ -166,9 +166,9 @@ function fdmdv_demod(rawfilename, nbits, pngname)
   plot(xt, rx_timing_log)
   title('timing offset (samples)');
   subplot(212)
-  plot(xt, foff_log)
+  plot(xt, foff_log, '-;freq offset;')
   hold on;
-  plot(xt, track_log*75, 'r');
+  plot(xt, track_log*75, 'r;course-fine;');
   hold off;
   title('Freq offset (Hz)');
   grid
@@ -181,11 +181,8 @@ function fdmdv_demod(rawfilename, nbits, pngname)
   plot(xt1, rx_fdm_log);
   title('Rx FDM Signal');
   subplot(212)
-  Nfft=Fs;
-  S=fft(rx_fdm_log,Nfft);
-  SdB=20*log10(abs(S));
-  plot(SdB(1:Fs/4))
-  title('FDM Rx Spectrum');
+  spec(rx_fdm_log,8000);
+  title('FDM Rx Spectrogram');
 
   figure(4)
   clf;
index 09b7e82f208af9a07685eff6f74b84db6481d18c..e83cf3920d2fc88dd2df51bd02cf1b2ba3f44073 100644 (file)
 function fdmdv_demod_c(dumpfilename, bits)
 
   fdmdv; % include modem code
+
   frames = bits/(Nc*Nb);
 
   load(dumpfilename);
 
+  % BER stats
+
+  total_bit_errors = 0;
+  total_bits = 0;
+  bit_errors_log = [];
+  sync_log = [];
+  test_frame_sync_log = [];
+  test_frame_sync_state = 0;
+
+  % Run thru received bits to look for test pattern
+
+  bits_per_frame = Nc*Nb;
+
+  for f=1:frames
+
+    rx_bits = rx_bits_log_c((f-1)*bits_per_frame+1:f*bits_per_frame);
+
+    % count bit errors if we find a test frame
+
+    [test_frame_sync bit_errors] = put_test_bits(rx_bits);
+    if (test_frame_sync == 1)
+      total_bit_errors = total_bit_errors + bit_errors;
+      total_bits = total_bits + Ntest_bits;
+      bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
+    else
+      bit_errors_log = [bit_errors_log 0];
+    end
+
+    % test frame sync state machine, just for more informative plots
+    
+    next_test_frame_sync_state = test_frame_sync_state;
+    if (test_frame_sync_state == 0)
+      if (test_frame_sync == 1)      
+        next_test_frame_sync_state = 1;
+       test_frame_count = 0;
+      end
+    end
+
+    if (test_frame_sync_state == 1)
+      % we only expect another test_frame_sync pulse every 4 symbols
+      test_frame_count++;
+      if (test_frame_count == 4)
+        test_frame_count = 0;
+        if ((test_frame_sync == 0))      
+          next_test_frame_sync_state = 0;
+        end
+      end
+    end
+    test_frame_sync_state = next_test_frame_sync_state;
+    test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
+  end
+
   % ---------------------------------------------------------------------
   % Plots
   % ---------------------------------------------------------------------
@@ -35,11 +88,37 @@ function fdmdv_demod_c(dumpfilename, bits)
   plot(xt, rx_timing_log_c(1:frames))
   title('timing offset (samples)');
   subplot(212)
-  plot(xt, foff_log_c(1:frames))
+  plot(xt, foff_log_c(1:frames), '-;freq offset;')
   hold on;
-  plot(xt, coarse_fine_log_c(1:frames)*75, 'r');
+  plot(xt, coarse_fine_log_c(1:frames)*75, 'r;course-fine;');
   hold off;
   title('Freq offset (Hz)');
   grid
 
+  figure(3)
+  clf;
+  subplot(211)
+  b = M*frames;
+  xt1 = (1:b)/Fs;
+  plot(xt1, rx_fdm_log_c(1:b));
+  title('Rx FDM Signal');
+  subplot(212)
+  spec(rx_fdm_log_c(1:b),8000);
+  title('FDM Rx Spectrogram');
+
+  figure(4)
+  clf;
+  subplot(311)
+  stem(xt, sync_bit_log_c(1:frames))
+  axis([0 secs 0 1.5]);
+  title('BPSK Sync')
+  subplot(312)
+  stem(xt, bit_errors_log);
+  title('Bit Errors for test frames')
+  subplot(313)
+  plot(xt, test_frame_sync_log);
+  axis([0 secs 0 1.5]);
+  title('Test Frame Sync')
+
+
 endfunction
index cfb2667afd06f22f80cf811737b49b1fb94c38de..cfd3132a1aa02820c34fa9e5df739f7c1ba8e185 100644 (file)
@@ -8,6 +8,10 @@
   outputs a file of bits.  The output file is assumed to be arranged
   as codec frames of 56 bits (7 bytes) which are received as two 28
   bit modem frames.
+
+  Demod states can be optionally logged to an Octave file for display
+  using the Octave script fdmdv_demod_c.m.  This is useful for
+  checking demod performance.
                                                                              
 \*---------------------------------------------------------------------------*/
 
@@ -60,13 +64,17 @@ int main(int argc, char *argv[])
     int           sync_bit;
     int           state, next_state;
 
-    int           frames;
+    int           f;
     FILE         *foct = NULL;
     struct FDMDV_STATS stats;
+    float         rx_fdm_log[FDMDV_MAX_SAMPLES_PER_FRAME*MAX_FRAMES];
+    int           rx_fdm_log_col_index;
     COMP          rx_symbols_log[FDMDV_NSYM][MAX_FRAMES];
     int           coarse_fine_log[MAX_FRAMES];
     float         rx_timing_log[MAX_FRAMES];
     float         foff_log[MAX_FRAMES];
+    int           sync_bit_log[MAX_FRAMES];
+    int           rx_bits_log[FDMDV_BITS_PER_FRAME*MAX_FRAMES];
 
     if (argc < 3) {
        printf("usage: %s InputModemRawFile OutputBitFile [OctaveDumpFile]\n", argv[0]);
@@ -89,9 +97,10 @@ int main(int argc, char *argv[])
     }
 
     fdmdv = fdmdv_create();
-    frames = 0;
+    f = 0;
     state = 0;
     nin = FDMDV_NOM_SAMPLES_PER_FRAME;
+    rx_fdm_log_col_index = 0;
 
     while(fread(rx_fdm_scaled, sizeof(short), nin, fin) == nin)
     {
@@ -101,14 +110,23 @@ int main(int argc, char *argv[])
 
        /* log data for optional Octave dump */
 
-       if (frames < MAX_FRAMES) {
+       if (f < MAX_FRAMES) {
            fdmdv_get_demod_stats(fdmdv, &stats);
+
+           /* log modem states for later dumping to Octave log file */
+
+           memcpy(&rx_fdm_log[rx_fdm_log_col_index], rx_fdm, sizeof(float)*nin);
+           rx_fdm_log_col_index += nin;
+
            for(c=0; c<FDMDV_NSYM; c++)
-               rx_symbols_log[c][frames] = stats.rx_symbols[c];
-           foff_log[frames] = stats.foff;
-           rx_timing_log[frames] = stats.rx_timing;
-           coarse_fine_log[frames] = stats.fest_coarse_fine;
-           frames++;
+               rx_symbols_log[c][f] = stats.rx_symbols[c];
+           foff_log[f] = stats.foff;
+           rx_timing_log[f] = stats.rx_timing;
+           coarse_fine_log[f] = stats.fest_coarse_fine;
+           sync_bit_log[f] = sync_bit;
+           memcpy(&rx_bits_log[FDMDV_BITS_PER_FRAME*f], rx_bits, sizeof(int)*FDMDV_BITS_PER_FRAME);
+
+           f++;
        }
        else
            printf("MAX_FRAMES exceed in Octave log, log truncated\n");
@@ -170,10 +188,13 @@ int main(int argc, char *argv[])
                        argv[3], strerror(errno));
                exit(1);
            }
-           octave_save_complex(foct, "rx_symbols_log_c", (COMP*)rx_symbols_log, FDMDV_NSYM, MAX_FRAMES, MAX_FRAMES);  
-           octave_save_float(foct, "foff_log_c", foff_log, 1, MAX_FRAMES);  
-           octave_save_float(foct, "rx_timing_log_c", rx_timing_log, 1, MAX_FRAMES);  
-           octave_save_int(foct, "coarse_fine_log_c", coarse_fine_log, 1, MAX_FRAMES);  
+           octave_save_float(foct, "rx_fdm_log_c", rx_fdm_log, 1, rx_fdm_log_col_index, FDMDV_MAX_SAMPLES_PER_FRAME);  
+           octave_save_complex(foct, "rx_symbols_log_c", (COMP*)rx_symbols_log, FDMDV_NSYM, f, MAX_FRAMES);  
+           octave_save_float(foct, "foff_log_c", foff_log, 1, f, MAX_FRAMES);  
+           octave_save_float(foct, "rx_timing_log_c", rx_timing_log, 1, f, MAX_FRAMES);  
+           octave_save_int(foct, "coarse_fine_log_c", coarse_fine_log, 1, f);  
+           octave_save_int(foct, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*f);
+           octave_save_int(foct, "sync_bit_log_c", sync_bit_log, 1, f);  
            fclose(foct);
        }
     }
index cf4cc20acf1dfbd77a50815612d3e329fab62766..2ff5ad14134dfb9b3727a74640c41a78ebba869b 100644 (file)
@@ -4,8 +4,8 @@
   AUTHOR......: David Rowe  
   DATE CREATED: April 28 2012
                                                                              
-  Functions to save C arrays in Octave matrix format.  the output text
-  file can be directly read into octave using "load filename".
+  Functions to save C arrays in GNU Octave matrix format.  The output text
+  file can be directly read into Octave using "load filename".
 
 \*---------------------------------------------------------------------------*/
 
@@ -48,7 +48,7 @@ void octave_save_int(FILE *f, char name[], int data[], int rows, int cols)
     fprintf(f, "\n\n");
 }
 
-void octave_save_float(FILE *f, char name[], float data[], int rows, int cols)
+void octave_save_float(FILE *f, char name[], float data[], int rows, int cols, int col_len)
 {
     int r,c;
 
@@ -59,7 +59,7 @@ void octave_save_float(FILE *f, char name[], float data[], int rows, int cols)
     
     for(r=0; r<rows; r++) {
        for(c=0; c<cols; c++)
-           fprintf(f, " %f", data[r*cols+c]);
+           fprintf(f, " %f", data[r*col_len+c]);
        fprintf(f, "\n");
     }
 
index d8b85861f3226c9a084b55b15d0383c073a0de1f..be6d8d38521940cc94e8c86318b77d0745c3a3e5 100644 (file)
@@ -33,7 +33,7 @@
 #include "comp.h"
 
 void octave_save_int(FILE *f, char name[], int data[], int rows, int cols);
-void octave_save_float(FILE *f, char name[], float data[], int rows, int cols);
+void octave_save_float(FILE *f, char name[], float data[], int rows, int cols, int col_len);
 void octave_save_complex(FILE *f, char name[], COMP data[], int rows, int cols, int col_len);
 
 #endif
index a592e1350335e76e98f2bbed0af26cc5c09be58e..593b8139f8b9602c61e72c870b5200addfdc4392 100644 (file)
@@ -248,15 +248,15 @@ int main(int argc, char *argv[])
     octave_save_complex(fout, "pilot_lpf2_log_c", pilot_lpf2_log, 1, NPILOTLPF*FRAMES, NPILOTLPF*FRAMES);  
     octave_save_complex(fout, "S1_log_c", S1_log, 1, MPILOTFFT*FRAMES, MPILOTFFT*FRAMES);  
     octave_save_complex(fout, "S2_log_c", S2_log, 1, MPILOTFFT*FRAMES, MPILOTFFT*FRAMES);  
-    octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES);  
-    octave_save_float(fout, "foff_coarse_log_c", foff_coarse_log, 1, FRAMES);  
+    octave_save_float(fout, "foff_log_c", foff_log, 1, FRAMES, FRAMES);  
+    octave_save_float(fout, "foff_coarse_log_c", foff_coarse_log, 1, FRAMES, FRAMES);  
     octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, (NC+1), rx_baseband_log_col_index, (M+M/P)*FRAMES);  
     octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, (NC+1), rx_filt_log_col_index, (P+1)*FRAMES);  
-    octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES);  
-    octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES);  
+    octave_save_float(fout, "env_log_c", env_log, 1, NT*P*FRAMES, NT*P*FRAMES);  
+    octave_save_float(fout, "rx_timing_log_c", rx_timing_log, 1, FRAMES, FRAMES);  
     octave_save_complex(fout, "rx_symbols_log_c", (COMP*)rx_symbols_log, (NC+1), FRAMES, FRAMES);  
     octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES);
-    octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES);  
+    octave_save_float(fout, "foff_fine_log_c", foff_fine_log, 1, FRAMES, FRAMES);  
     octave_save_int(fout, "sync_bit_log_c", sync_bit_log, 1, FRAMES);  
     octave_save_int(fout, "coarse_fine_log_c", coarse_fine_log, 1, FRAMES);  
     octave_save_int(fout, "nin_log_c", nin_log, 1, FRAMES);