most rx filtering working in C, next step add coarse timing (frame snyc) in C
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 19 Mar 2015 09:37:06 +0000 (09:37 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Thu, 19 Mar 2015 09:37:06 +0000 (09:37 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2083 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/autotest.m
codec2-dev/octave/fdmdv.m
codec2-dev/octave/gmsk.m
codec2-dev/octave/tcohpsk.m
codec2-dev/src/fdmdv.c
codec2-dev/unittest/tcohpsk.c
codec2-dev/unittest/tfdmdv.c

index 9901535b72539265953ce921cd35c176fb214507..38e99903ff0c776b58e73f2c16a0c80253da56d1 100644 (file)
@@ -44,10 +44,14 @@ function plot_sig_and_error(plotnum, subplotnum, sig, error, titlestr, axisvec)
 endfunction
 
 
-function check(a, b, test_name)
+function check(a, b, test_name, tol)
   global passes;
   global fails;
 
+  if nargin == 3
+    tol = 1E-3;
+  end
+
   [m n] = size(a);
   printf("%s", test_name);
   for i=1:(25-length(test_name))
@@ -55,8 +59,8 @@ function check(a, b, test_name)
   end
   printf(": ");  
   
-  e = sum(abs(a - b))/n;
-  if e < 1E-3
+  e = sum(sum(abs(a - b))/n);
+  if e < tol
     printf("OK\n");
     passes++;
   else
index 4fcdc153e40a63e6fc6dfe1abfe6e5ddb0900596..c91d6034dadf2d4ceb6af48dac8f26c97998e716 100644 (file)
@@ -263,6 +263,11 @@ function [rx_baseband fdmdv] = fdm_downconvert(fdmdv, rx_fdm, nin)
       end
   end
 
+  for c=1:Nc+1
+    mag = abs(phase_rx(c));
+    phase_rx(c) /= mag;
+  end
+
   fdmdv.phase_rx = phase_rx;
 endfunction
 
index 0549c338992c87301ff5cd33576afc3f2e3314cf..40cd0cda618280a7e40fe8146cfa8248395d6852 100644 (file)
@@ -884,7 +884,7 @@ function gmsk_rx(rx_file_name, err_file_name)
   rx_power_dB = 10*log10(rx_power);
   figure;
   subplot(211)
-  plot(rx_filt(1000:5*Fs));
+  plot(rx_filt(1000:length(rx_filt)));
   title('GMSK Power (narrow filter)');
   subplot(212)
   plot(rx_power_dB);
@@ -923,7 +923,6 @@ function gmsk_rx(rx_file_name, err_file_name)
 
     printf("Estimated S: %3.1f N: %3.1f Nbw: %4.0f Hz SNR: %3.1f CNo: %3.1f EbNo: %3.1f BER theory: %f\n",
            signal, noise, Fs*noise_bw, snr, CNo, EbNo, ber_theory);
-  end
 
   % FM signal is centred on 12 kHz and 16 kHz wide so lets also work out noise there
 
@@ -953,6 +952,7 @@ function gmsk_rx(rx_file_name, err_file_name)
   grid("minor")
   legend("boxoff");
   title('FM C/No');
+  end
 
   % spectrum of a chunk of GMSK signal just after preamble
 
@@ -1014,5 +1014,5 @@ endfunction
 %gmsk_rx("ssb25db.wav")
 %gmsk_rx("~/Desktop/ssb_fm_gmsk_high.wav")
 %gmsk_rx("~/Desktop/test_gmsk_28BER.raw")
-gmsk_rx("~/Desktop/gmsk_rec1.wav")
+gmsk_rx("~/Desktop/gmsk_rec_reverse.wav")
 
index 57906e4ff3645ec54b778bcecaf07208eaba07f3..bc76eee65030dae4429fcbfe2a12c447b2904f45 100644 (file)
@@ -104,10 +104,11 @@ fdmdv.rx_filter_memory = zeros(fdmdv.Nc+1, fdmdv.Nfilter);
 rx_filt_log = [];
 rx_fdm_filter_log = [];
 rx_baseband_log = [];
+rx_fdm_log = [];
 
 fbb_phase_rx = 1;
 
-% frame of just pilots ofr coarse sync
+% frame of just pilots for coarse sync
 
 tx_bits = zeros(1,framesize);
 [tx_symb_pilot tx_bits prev_tx_sym] = bits_to_qpsk_symbols(sim_in, tx_bits, [], []);
@@ -117,6 +118,7 @@ end
 
 ct_symb_buf = zeros(2*sim_in.Nsymbrowpilot, sim_in.Nc);
 
+prev_tx_bits = [];
 % main loop --------------------------------------------------------------------
 
 for i=1:frames
@@ -142,6 +144,10 @@ for i=1:frames
   end
   tx_fdm_log = [tx_fdm_log tx_fdm_frame];
 
+  %
+  % Demod ----------------------------------------------------------------------
+  %
+
   nin = M;
 
   % shift frame down to complex baseband
@@ -153,6 +159,7 @@ for i=1:frames
   end
   mag = abs(fbb_phase_rx);
   fbb_phase_rx /= mag;
+  rx_fdm_log = [rx_fdm_log rx_fdm_frame_bb];
 
   ch_symb = zeros(sim_in.Nsymbrowpilot, Nc);
   for r=1:sim_in.Nsymbrowpilot
@@ -213,21 +220,31 @@ end
   end
   prev_tx_bits2 = prev_tx_bits;
   prev_tx_bits = tx_bits;
+
 end
 
 stem_sig_and_error(1, 111, tx_bits_log_c(1:n), tx_bits_log(1:n) - tx_bits_log_c(1:n), 'tx bits', [1 n -1.5 1.5])
 stem_sig_and_error(2, 211, real(tx_symb_log_c(1:n)), real(tx_symb_log(1:n) - tx_symb_log_c(1:n)), 'tx symb re', [1 n -1.5 1.5])
 stem_sig_and_error(2, 212, imag(tx_symb_log_c(1:n)), imag(tx_symb_log(1:n) - tx_symb_log_c(1:n)), 'tx symb im', [1 n -1.5 1.5])
-stem_sig_and_error(3, 211, real(ch_symb_log_c(1:n)), real(ch_symb_log(1:n) - ch_symb_log_c(1:n)), 'ch symb re', [1 n -1.5 1.5])
-stem_sig_and_error(3, 212, imag(ch_symb_log_c(1:n)), imag(ch_symb_log(1:n) - ch_symb_log_c(1:n)), 'ch symb im', [1 n -1.5 1.5])
-stem_sig_and_error(4, 211, rx_amp_log_c(1:n), rx_amp_log(1:n) - rx_amp_log_c(1:n), 'Amp Est', [1 n -1.5 1.5])
-stem_sig_and_error(4, 212, rx_phi_log_c(1:n), rx_phi_log(1:n) - rx_phi_log_c(1:n), 'Phase Est', [1 n -4 4])
-stem_sig_and_error(5, 211, real(rx_symb_log_c(1:n)), real(rx_symb_log(1:n) - rx_symb_log_c(1:n)), 'rx symb re', [1 n -1.5 1.5])
-stem_sig_and_error(5, 212, imag(rx_symb_log_c(1:n)), imag(rx_symb_log(1:n) - rx_symb_log_c(1:n)), 'rx symb im', [1 n -1.5 1.5])
-stem_sig_and_error(6, 111, rx_bits_log_c(1:n), rx_bits_log(1:n) - rx_bits_log_c(1:n), 'rx bits', [1 n -1.5 1.5])
+
+stem_sig_and_error(3, 211, real(tx_fdm_log_c(1:n)), real(tx_fdm_log(1:n) - tx_fdm_log_c(1:n)), 'tx fdm re', [1 n -10 10])
+stem_sig_and_error(3, 212, imag(tx_fdm_log_c(1:n)), imag(tx_fdm_log(1:n) - tx_fdm_log_c(1:n)), 'tx fdm im', [1 n -10 10])
+
+stem_sig_and_error(4, 211, real(ch_symb_log_c(1:n)), real(ch_symb_log(1:n) - ch_symb_log_c(1:n)), 'ch symb re', [1 n -2 2])
+stem_sig_and_error(4, 212, imag(ch_symb_log_c(1:n)), imag(ch_symb_log(1:n) - ch_symb_log_c(1:n)), 'ch symb im', [1 n -2 2])
+stem_sig_and_error(5, 211, rx_amp_log_c(1:n), rx_amp_log(1:n) - rx_amp_log_c(1:n), 'Amp Est', [1 n -1.5 1.5])
+stem_sig_and_error(5, 212, rx_phi_log_c(1:n), rx_phi_log(1:n) - rx_phi_log_c(1:n), 'Phase Est', [1 n -4 4])
+stem_sig_and_error(6, 211, real(rx_symb_log_c(1:n)), real(rx_symb_log(1:n) - rx_symb_log_c(1:n)), 'rx symb re', [1 n -1.5 1.5])
+stem_sig_and_error(6, 212, imag(rx_symb_log_c(1:n)), imag(rx_symb_log(1:n) - rx_symb_log_c(1:n)), 'rx symb im', [1 n -1.5 1.5])
+stem_sig_and_error(7, 111, rx_bits_log_c(1:n), rx_bits_log(1:n) - rx_bits_log_c(1:n), 'rx bits', [1 n -1.5 1.5])
 
 check(tx_bits_log, tx_bits_log_c, 'tx_bits');
 check(tx_symb_log, tx_symb_log_c, 'tx_symb');
+check(tx_fdm_log, tx_fdm_log_c, 'tx_fdm');
+check(rx_fdm_log, rx_fdm_log_c, 'rx_fdm');
+check(rx_baseband_log, rx_baseband_log_c, 'rx_baseband',0.01);
+check(rx_filt_log, rx_filt_log_c, 'rx_filt');
+check(ch_symb_log, ch_symb_log_c, 'ch_symb',0.01);
 check(rx_amp_log, rx_amp_log_c, 'rx_amp_log');
 check(rx_phi_log, rx_phi_log_c, 'rx_phi_log');
 check(rx_symb_log, rx_symb_log_c, 'rx_symb');
index 931adabe7be303897588d3b067191bd7dd8a444d..1d5cf986dc0253df34d697cf7ab610ac27106071 100644 (file)
@@ -400,8 +400,8 @@ void tx_filter(COMP tx_baseband[NC+1][M], int Nc, COMP tx_symbols[], COMP tx_fil
   AUTHOR......: David Rowe                           
   DATE CREATED: 13 August 2014
 
-  Given Nc*NB bits construct M samples (1 symbol) of Nc+1 filtered
-  symbols streams.
+  Given Nc symbols construct M samples (1 symbol) of Nc+1 filtered
+  and upconverted symbols.
 
 \*---------------------------------------------------------------------------*/
 
@@ -878,30 +878,14 @@ void fdm_downconvert(COMP rx_baseband[NC+1][M+M/P], int Nc, COMP rx_fdm[], COMP
 
     assert(nin <= (M+M/P));
 
-    /* Nc/2 tones below centre freq */
+    /* downconvert */
   
-    for (c=0; c<Nc/2; c++) 
-       for (i=0; i<nin; i++) {
-           phase_rx[c] = cmult(phase_rx[c], freq[c]);
-           rx_baseband[c][i] = cmult(rx_fdm[i], cconj(phase_rx[c]));
-       }
-
-    /* Nc/2 tones above centre freq */
-
-    for (c=Nc/2; c<Nc; c++) 
+    for (c=0; c<Nc+1; c++) 
        for (i=0; i<nin; i++) {
            phase_rx[c] = cmult(phase_rx[c], freq[c]);
            rx_baseband[c][i] = cmult(rx_fdm[i], cconj(phase_rx[c]));
        }
 
-    /* centre pilot tone  */
-
-    c = Nc;
-    for (i=0; i<nin; i++) {
-       phase_rx[c] = cmult(phase_rx[c],  freq[c]);
-       rx_baseband[c][i] = cmult(rx_fdm[i], cconj(phase_rx[c]));
-    }
-
     /* normalise digital oscilators as the magnitude can drift over time */
 
     for (c=0; c<Nc+1; c++) {
index 13665c33b1822f744f9fe15e9bc5cac40408c1fd..024f80f0013ca78913c9ae48a9cb179f9096e895 100644 (file)
@@ -1,10 +1,10 @@
 /*---------------------------------------------------------------------------*\
                                                                              
-  FILE........: tcopskv.c
+  FILE........: tcohpsk.c
   AUTHOR......: David Rowe  
   DATE CREATED: March 2015
                                                                              
-  Tests for the C version of the cohernet PSK FDM modem.  This program
+  Tests for the C version of the coherent PSK FDM modem.  This program
   outputs a file of Octave vectors that are loaded and automatically
   tested against the Octave version of the modem by the Octave script
   tcohpsk.m
@@ -42,7 +42,7 @@
 #include "test_bits_coh.h"
 #include "octave.h"
 #include "comp_prim.h"
-#include "noise_samples.h"
+//#include "noise_samples.h"
 
 #define FRAMES 35
 #define RS     50
@@ -53,11 +53,15 @@ int main(int argc, char *argv[])
     struct COHPSK *coh;
     int            tx_bits[COHPSK_BITS_PER_FRAME];
     COMP           tx_symb[NSYMROWPILOT][PILOTS_NC];
+    COMP           tx_fdm[M*NSYMROWPILOT];
+    COMP           rx_fdm[M*NSYMROWPILOT];
     COMP           ch_symb[NSYMROWPILOT][PILOTS_NC];
     int            rx_bits[COHPSK_BITS_PER_FRAME];
     
     int            tx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES];
     COMP           tx_symb_log[NSYMROWPILOT*FRAMES][PILOTS_NC];
+    COMP           tx_fdm_log[M*NSYMROWPILOT*FRAMES];
+    COMP           rx_fdm_log[M*NSYMROWPILOT*FRAMES];
     COMP           ch_symb_log[NSYMROWPILOT*FRAMES][PILOTS_NC];
 
     float          rx_amp_log[NSYMROW*FRAMES][PILOTS_NC];
@@ -66,9 +70,24 @@ int main(int argc, char *argv[])
     int            rx_bits_log[COHPSK_BITS_PER_FRAME*FRAMES];
                                           
     FILE          *fout;
-    int            f, r, c, log_r, log_data_r, noise_r;
+    int            f, r, c, log_r, log_data_r, noise_r, i;
     COMP           phase, freq;
     int           *ptest_bits_coh, *ptest_bits_coh_end;
+    float           freq_hz;
+
+    struct FDMDV  *fdmdv;
+    COMP           rx_baseband[PILOTS_NC][M+M/P];
+    int            nin;
+    COMP           rx_filt[PILOTS_NC][P+1];
+    COMP           rx_filt_log[PILOTS_NC][(P+1)*NSYMROWPILOT*FRAMES];
+    int            rx_filt_log_col_index = 0;
+    float          env[NT*P];
+    COMP           rx_filter_memory[PILOTS_NC][NFILTER];
+    float          rx_timing;
+    COMP           tx_onesym[PILOTS_NC];
+    COMP           rx_onesym[PILOTS_NC];
+    int            rx_baseband_log_col_index = 0;
+    COMP           rx_baseband_log[PILOTS_NC][(M+M/P)*NSYMROWPILOT*FRAMES];
 
     coh = cohpsk_create();
     assert(coh != NULL);
@@ -82,10 +101,31 @@ int main(int argc, char *argv[])
     phase.real = 1.0; phase.imag = 0.0; 
     freq.real = cos(2.0*M_PI*FOFF/RS); freq.imag = sin(2.0*M_PI*FOFF/RS);
 
+    /* set up fdmdv states so we can use those modem functions */
+
+    fdmdv = fdmdv_create(PILOTS_NC - 1);
+    for(c=0; c<PILOTS_NC; c++) {
+       fdmdv->phase_tx[c].real = 1.0;
+       fdmdv->phase_tx[c].imag = 0.0;
+
+        freq_hz = fdmdv->fsep*( -PILOTS_NC/2 - 0.5 + c + 1.0 );
+       fdmdv->freq[c].real = cosf(2.0*M_PI*freq_hz/FS);
+       fdmdv->freq[c].imag = sinf(2.0*M_PI*freq_hz/FS);
+       fdmdv->freq_pol[c]  = 2.0*M_PI*freq_hz/FS;
+
+        //printf("c: %d %f %f\n",c,freq_hz,fdmdv->freq_pol[c]);
+        for(i=0; i<NFILTER; i++) {
+            rx_filter_memory[c][i].real = 0.0;
+            rx_filter_memory[c][i].imag = 0.0;
+        }
+    }
+
+    /* Main Loop ---------------------------------------------------------------------*/
+
     for(f=0; f<FRAMES; f++) {
         
        /* --------------------------------------------------------*\
-                                 Modem
+                                 Mod
        \*---------------------------------------------------------*/
 
         memcpy(tx_bits, ptest_bits_coh, sizeof(int)*COHPSK_BITS_PER_FRAME);
@@ -94,6 +134,14 @@ int main(int argc, char *argv[])
             ptest_bits_coh = (int*)test_bits_coh;
        bits_to_qpsk_symbols(tx_symb, (int*)tx_bits, COHPSK_BITS_PER_FRAME);
 
+        for(r=0; r<NSYMROWPILOT; r++) {
+           for(c=0; c<PILOTS_NC; c++) 
+              tx_onesym[c] = tx_symb[r][c];         
+          tx_filter_and_upconvert(&tx_fdm[r*M], fdmdv->Nc , tx_onesym, fdmdv->tx_filter_memory, 
+                                  fdmdv->phase_tx, fdmdv->freq, &fdmdv->fbb_phase_tx, fdmdv->fbb_rect);
+        }
+
+        #ifdef TMP
         for(r=0; r<NSYMROWPILOT; r++,noise_r++) {
             phase = cmult(phase,freq);
             for(c=0; c<PILOTS_NC; c++) {
@@ -103,14 +151,52 @@ int main(int argc, char *argv[])
              }
         }
         phase = fcmult(1.0/cabsolute(phase), phase);
+        #endif
+
+        memcpy(rx_fdm, tx_fdm, sizeof(COMP)*M*NSYMROWPILOT);
 
+       /* --------------------------------------------------------*\
+                                 Demod
+       \*---------------------------------------------------------*/
+
+        nin = M;
+        for (r=0; r<NSYMROWPILOT; r++) {
+          fdmdv_freq_shift(&rx_fdm[r*M], &rx_fdm[r*M], -FDMDV_FCENTRE, &fdmdv->fbb_phase_rx, nin);
+          fdm_downconvert(rx_baseband, fdmdv->Nc, &rx_fdm[r*M], fdmdv->phase_rx, fdmdv->freq, nin);
+          rx_filter(rx_filt, fdmdv->Nc, rx_baseband, rx_filter_memory, nin);
+         rx_timing = rx_est_timing(rx_onesym, fdmdv->Nc, rx_filt, fdmdv->rx_filter_mem_timing, env, nin);
+          
+          for(c=0; c<PILOTS_NC; c++) {
+             ch_symb[r][c] = rx_onesym[c];
+          }
+          
+         for(c=0; c<PILOTS_NC; c++) {       
+            for(i=0; i<nin; i++) {
+              rx_baseband_log[c][rx_baseband_log_col_index + i] = rx_baseband[c][i]; 
+            }
+         }
+         rx_baseband_log_col_index += nin;        
+
+         //if (f == 3)
+          //    exit(0);
+         for(c=0; c<PILOTS_NC; c++) {       
+            for(i=0; i<P; i++) {
+              rx_filt_log[c][rx_filt_log_col_index + i] = rx_filt[c][i]; 
+            }
+         }
+         rx_filt_log_col_index += P;        
+
+        }
         qpsk_symbols_to_bits(coh, rx_bits, ch_symb);
+
        /* --------------------------------------------------------*\
                               Log each vector 
        \*---------------------------------------------------------*/
 
        memcpy(&tx_bits_log[COHPSK_BITS_PER_FRAME*f], tx_bits, sizeof(int)*COHPSK_BITS_PER_FRAME);
+       memcpy(&tx_fdm_log[M*NSYMROWPILOT*f], tx_fdm, sizeof(COMP)*M*NSYMROWPILOT);
+               memcpy(&rx_fdm_log[M*NSYMROWPILOT*f], rx_fdm, sizeof(COMP)*M*NSYMROWPILOT);
+
        for(r=0; r<NSYMROWPILOT; r++, log_r++) {
             for(c=0; c<PILOTS_NC; c++) {
                tx_symb_log[log_r][c] = tx_symb[r][c]; 
@@ -132,6 +218,7 @@ int main(int argc, char *argv[])
        assert(log_data_r <= NSYMROW*FRAMES);
     }
 
+
     /*---------------------------------------------------------*\
                Dump logs to Octave file for evaluation 
                       by tcohpsk.m Octave script
@@ -142,6 +229,10 @@ int main(int argc, char *argv[])
     fprintf(fout, "# Created by tcohpsk.c\n");
     octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, COHPSK_BITS_PER_FRAME*FRAMES);
     octave_save_complex(fout, "tx_symb_log_c", (COMP*)tx_symb_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC);  
+    octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M*NSYMROWPILOT*FRAMES, M*NSYMROWPILOT*FRAMES);  
+    octave_save_complex(fout, "rx_fdm_log_c", (COMP*)rx_fdm_log, 1, M*NSYMROWPILOT*FRAMES, M*NSYMROWPILOT*FRAMES);  
+    octave_save_complex(fout, "rx_baseband_log_c", (COMP*)rx_baseband_log, PILOTS_NC, rx_baseband_log_col_index, (M+M/P)*FRAMES*NSYMROWPILOT);  
+    octave_save_complex(fout, "rx_filt_log_c", (COMP*)rx_filt_log, PILOTS_NC, rx_filt_log_col_index, (P+1)*FRAMES*NSYMROWPILOT);  
     octave_save_complex(fout, "ch_symb_log_c", (COMP*)ch_symb_log, NSYMROWPILOT*FRAMES, PILOTS_NC, PILOTS_NC);  
     octave_save_float(fout, "rx_amp_log_c", (float*)rx_amp_log, NSYMROW*FRAMES, PILOTS_NC, PILOTS_NC);  
     octave_save_float(fout, "rx_phi_log_c", (float*)rx_phi_log, NSYMROW*FRAMES, PILOTS_NC, PILOTS_NC);  
@@ -149,6 +240,7 @@ int main(int argc, char *argv[])
     octave_save_int(fout, "rx_bits_log_c", rx_bits_log, 1, COHPSK_BITS_PER_FRAME*FRAMES);
     fclose(fout);
 
+    fdmdv_destroy(fdmdv);
     cohpsk_destroy(coh);
 
     return 0;
index 8ae5ccaa83aed9d6b13460f91fec5977f6e7f6a0..447d654a5d1633cef07a373c89633e6756a5a667 100644 (file)
@@ -258,7 +258,7 @@ int main(int argc, char *argv[])
     fprintf(fout, "# Created by tfdmdv.c\n");
     octave_save_int(fout, "tx_bits_log_c", tx_bits_log, 1, FDMDV_BITS_PER_FRAME*FRAMES);
     octave_save_complex(fout, "tx_symbols_log_c", tx_symbols_log, 1, (FDMDV_NC+1)*FRAMES, (FDMDV_NC+1)*FRAMES);  
-octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M*FRAMES, M*FRAMES);  
+    octave_save_complex(fout, "tx_fdm_log_c", (COMP*)tx_fdm_log, 1, M*FRAMES, M*FRAMES);  
     octave_save_complex(fout, "pilot_lut_c", (COMP*)fdmdv->pilot_lut, 1, NPILOT_LUT, NPILOT_LUT);  
     octave_save_complex(fout, "pilot_baseband1_log_c", pilot_baseband1_log, 1, NPILOTBASEBAND*FRAMES, NPILOTBASEBAND*FRAMES);  
     octave_save_complex(fout, "pilot_baseband2_log_c", pilot_baseband2_log, 1, NPILOTBASEBAND*FRAMES, NPILOTBASEBAND*FRAMES);