better freq offset estimation and sync, but still has some false sync states, ofdm_mo...
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 8 May 2018 10:46:02 +0000 (10:46 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 8 May 2018 10:46:02 +0000 (10:46 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@3585 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h
codec2-dev/src/freedv_api_internal.h
codec2-dev/src/freedv_rx.c
codec2-dev/src/interldpc.c
codec2-dev/src/ofdm.c
codec2-dev/src/ofdm_demod.c
codec2-dev/src/ofdm_internal.h
codec2-dev/src/ofdm_mod.c

index 74c8d7d381d9ca8ee76800100cde3a0d79fac505..b8f4dc2cbfab145e0080fbf2836479fae3a82812 100644 (file)
@@ -108,6 +108,7 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) {
         return NULL;
 
     f->mode = mode;
+    f->verbose = 0;
     f->test_frames = f->smooth_symbols = 0;
     f->freedv_put_error_pattern = NULL;
     f->error_pattern_callback_state = NULL;
@@ -1810,12 +1811,12 @@ static int freedv_comprx_700d(struct freedv *f, COMP demod_in_8kHz[], int *valid
     //fprintf(stderr, "nin: %d\n", ofdm_get_nin(ofdm));
     ofdm_sync_state_machine(ofdm, rx_uw);
 
-    /*
-    fprintf(stderr, "%3d st: %-6s euw: %2d %1d f: %5.1f ist: %-6s %2d eraw: %3d ecdd: %3d iter: %3d pcc: %3d vld: %d, nout: %4d\n",
-                    0, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter, ofdm->foff_est_hz,
-                    ofdm->last_sync_state_interleaver, ofdm->frame_count_interleaver,
-            Nerrs_raw, Nerrs_coded, iter, parityCheckCount, *valid, nout);
-    */
+    if (f->verbose) {
+        fprintf(stderr, "%3d st: %-6s euw: %2d %1d f: %5.1f ist: %-6s %2d eraw: %3d ecdd: %3d iter: %3d pcc: %3d vld: %d, nout: %4d\n",
+                0, ofdm->last_sync_state, ofdm->uw_errors, ofdm->sync_counter, ofdm->foff_est_hz,
+                ofdm->last_sync_state_interleaver, ofdm->frame_count_interleaver,
+                Nerrs_raw, Nerrs_coded, iter, parityCheckCount, *valid, nout);
+    }
     
     /* no valid FreeDV signal - squelch output */
     
@@ -2112,6 +2113,13 @@ void freedv_set_total_bits_coded          (struct freedv *f, int val) {f->total_
 void freedv_set_clip                      (struct freedv *f, int val) {f->clip = val;}
 void freedv_set_varicode_code_num         (struct freedv *f, int val) {varicode_set_code_num(&f->varicode_dec_states, val);}
 
+void freedv_set_verbose(struct freedv *f, int verbosity) {
+    f->verbose = verbosity;
+    if (f->mode == FREEDV_MODE_700D) {
+        ofdm_set_verbose(f->ofdm, f->verbose);
+    }
+}
+
 // Set floats
 void freedv_set_snr_squelch_thresh        (struct freedv *f, float val) {f->snr_squelch_thresh = val;}
 
index 179d20539757919702e2b52bc41d11205dd3da82..7809fe7fe7439fd1db4673c093a437d32a6536e1 100644 (file)
@@ -129,6 +129,7 @@ void freedv_set_data_header             (struct freedv *freedv, unsigned char *h
 int  freedv_set_alt_modem_samp_rate     (struct freedv *freedv, int samp_rate);
 void freedv_set_carrier_ampl            (struct freedv *freedv, int c, float ampl);
 void freedv_set_sync                    (struct freedv *freedv, int sync_cmd);
+void freedv_set_verbose                 (struct freedv *freedv, int verbosity);
 
 // Get parameters -------------------------------------------------------------------------
 
index 9d2a0e86df9f182481259ede993d2b409af20327..f7686e1b083e4d4492710bf776d7cf5255e20127 100644 (file)
@@ -125,7 +125,8 @@ struct freedv {
     float                snr_squelch_thresh;
     int                  squelch_en;
     int                  nin;
-
+    int                  verbose;
+    
     /* Varicode txt channel states ----------------------------------------------------------------------*/
     
     struct VARICODE_DEC  varicode_dec_states;
index 2c73dfa2d27ad8507e58a873c620d95e8686eb8b..5d47d941810eeff7dc24df933df793c6b726f693 100644 (file)
@@ -93,14 +93,14 @@ int main(int argc, char *argv[]) {
     int                        sync;
     float                      snr_est;
     float                      clock_offset;
-    int                        use_codecrx, use_testframes, interleave_frames;
+    int                        use_codecrx, use_testframes, interleave_frames, verbose;
     struct CODEC2             *c2 = NULL;
     int                        i;
 
 
     if (argc < 4) {
        printf("usage: %s 1600|700|700B|700C|700D|2400A|2400B|800XA InputModemSpeechFile OutputSpeechRawFile\n"
-               " [--testframes] [--interleaver depth] [--codecrx]\n", argv[0]);
+               " [--testframes] [--interleaver depth] [--codecrx] [-v]\n", argv[0]);
        printf("e.g    %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]);
        exit(1);
     }
@@ -138,7 +138,7 @@ int main(int argc, char *argv[]) {
        exit(1);
     }
 
-    use_codecrx = 0; use_testframes = 0; interleave_frames = 1;
+    use_codecrx = 0; use_testframes = 0; interleave_frames = 1; verbose = 0;
 
     if (argc > 4) {
         for (i = 4; i < argc; i++) {
@@ -164,6 +164,9 @@ int main(int argc, char *argv[]) {
             if (strcmp(argv[i], "--interleave") == 0) {
                 interleave_frames = atoi(argv[i+1]);
             }
+            if (strcmp(argv[i], "-v") == 0) {
+                verbose = 1;
+            }
         }
     }
 
@@ -178,6 +181,7 @@ int main(int argc, char *argv[]) {
     assert(freedv != NULL);
 
     freedv_set_test_frames(freedv, use_testframes);
+    freedv_set_verbose(freedv, verbose);
 
     freedv_set_snr_squelch_thresh(freedv, -100.0);
     freedv_set_squelch_en(freedv, 0);
index e3da534cb1c89cc0bff6aa9ac34f73a8f1a8ccaa..718452810ec10f3ab64ca3d2099325d324800047 100644 (file)
@@ -128,7 +128,7 @@ void interleaver_sync_state_machine(struct OFDM *ofdm,
         //    fprintf(stderr,"%d ", out_char[i]);
         //fprintf(stderr,"\n");
         //fprintf(stderr, "     iter: %d pcc: %d Nerrs: %d\n", iter[0], parityCheckCount[0], Nerrs_coded[0]);
-        if ((Nerrs_coded[0] == 0) && (iter[0] <= 5)) {
+        if ((Nerrs_coded[0] < 10) || (interleave_frames == 1)) {
             /* sucessful decode! */
             strcpy(next_sync_state_interleaver, "synced");
             ofdm->frame_count_interleaver = interleave_frames;
index 75d8db8ccb33b908381968504d4f18b207d4e70b..562991b3d643f75c49d1979d6ee7503b47aae92d 100644 (file)
@@ -51,7 +51,6 @@ const struct OFDM_CONFIG  * OFDM_CONFIG_700D = &OFDM_CONFIG_700D_C;
 static void dft(struct OFDM *, complex float *, complex float *);
 static void idft(struct OFDM *, complex float *, complex float *);
 static complex float vector_sum(complex float *, int);
-static int coarse_sync(struct OFDM *, complex float *, int, float *);
 
 /* Defines */
 
@@ -169,6 +168,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
     ofdm->timing_mx = 0.0f;
     ofdm->nin = OFDM_SAMPLESPERFRAME;
     ofdm->mean_amp = 0.0f;
+    ofdm->foff_metric = 0.0f + 0.0f * I;
     
     /* sync state machine */
 
@@ -196,13 +196,15 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
     idft(ofdm, temp, ofdm->pilots);
 
     /*
-     * pilot_samples is 160 samples, as we copy the last 16 to the front
+     * pilot_samples is 160 samples, but timing and freq offset est
+     * were found by experiment to work better without a cyclic
+     * prefix, so we uses zeroes instead.
      */
 
-    /* first copy the last Cyclic Prefix (CP) values */
+    /* zero out Cyclic Prefix (CP) values */
 
     for (i = 0, j = (OFDM_M - OFDM_NCP); i < OFDM_NCP; i++, j++) {
-        ofdm->pilot_samples[i] = temp[j];
+        ofdm->pilot_samples[i] = 0.0f + 0.0f * I;;
     }
         
     // From Octave: states.timing_norm = Npsam*(rate_fs_pilot_samples*rate_fs_pilot_samples');
@@ -218,8 +220,8 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) {
     float acc = 0.0f;
 
     for (i = 0; i < (OFDM_M + OFDM_NCP); i++) {
-        acc += (crealf(ofdm->pilot_samples[i]) * crealf(ofdm->pilot_samples[i]) +
-            cimagf(ofdm->pilot_samples[i]) * cimagf(ofdm->pilot_samples[i]));
+        acc += crealf(ofdm->pilot_samples[i]) * crealf(ofdm->pilot_samples[i]) +
+               cimagf(ofdm->pilot_samples[i]) * cimagf(ofdm->pilot_samples[i]);
     }
 
     ofdm->timing_norm = (OFDM_M + OFDM_NCP) * acc;
@@ -298,19 +300,17 @@ static complex float vector_sum(complex float *a, int num_elements) {
  * samples to determine the most likely timing offset.  Combines two
  * frames pilots so we need at least Nsamperframe+M+Ncp samples in rx.
  *
- * Also estimates coarse frequency offset based on sampling the pilots
- * phase at half symbol intervales.
- * 
+ * Can be used for acquisition (coarse timing), and fine timing.
+ *
  * Unlike Octave version use states to return a few values.
  */
 
-static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length, float *foff_est) {
-    complex float csam, csam1, csam2;
+static int est_timing(struct OFDM *ofdm, complex float *rx, int length) {
+    complex float csam;
     int Ncorr = length - (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP));
-    int Fs = OFDM_FS;
     int SFrame = OFDM_SAMPLESPERFRAME;
     float corr[Ncorr];
-    int i, j, k;
+    int i, j;
 
     float acc = 0.0f;
 
@@ -349,11 +349,36 @@ static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length, float *
     ofdm->timing_valid = timing_mx > OFDM_TIMING_MX_THRESH;
 
     if (ofdm->verbose > 1) {
-        fprintf(stderr, "   max: %f timing_est: %d timing_valid: %d\n", ofdm->timing_mx, timing_est, ofdm->timing_valid);
+        fprintf(stderr, "  av_level: %f  max: %f timing_est: %d timing_valid: %d\n", av_level, ofdm->timing_mx, timing_est, ofdm->timing_valid);
     }
     
-    /* Coarse frequency estimation - note this isn't always used, some CPU could be saved
-       buy putting this in another function */
+    return timing_est;
+}
+
+
+/*
+ * Determines frequency offset at current timing estimate, used for
+ * coarse freq offset estimation during acquisition.
+ *
+ * Freq offset is based on an averaged statistic that was found to be
+ * necessary to generate good quality estimates.
+ *
+ * Keep calling it when in trial or actual sync to keep statistic
+ * updated, in case we lose sync.
+ */
+
+ static float est_freq_offset(struct OFDM *ofdm, complex float *rx, int length, int timing_est) {
+    complex float csam1, csam2;
+    int Fs = OFDM_FS;
+    int SFrame = OFDM_SAMPLESPERFRAME;
+    int j, k;
+    float foff_est;
+    
+    /*
+      Freq offset can be considered as change in phase over two halves
+      of pilot symbols.  We average this statistic over this and next
+      frames pilots.
+    */
 
     complex float p1, p2, p3, p4;
     p1 = p2 = p3 = p4 =  0.0f + 0.0f * I;
@@ -385,11 +410,17 @@ static int coarse_sync(struct OFDM *ofdm, complex float *rx, int length, float *
        improve estimate.  Small real 1E-12 term to prevent instability
        with 0 inputs. */
 
-    *foff_est = Fs1 * cargf(conjf(p1) * p2 + conjf(p3) * p4 + 1E-12f) / TAU;
+    ofdm->foff_metric = 0.9*ofdm->foff_metric + 0.1*(conjf(p1) * p2 + conjf(p3) * p4);
+    foff_est = Fs1 * cargf( ofdm->foff_metric + 1E-12f) / TAU;
 
-    return timing_est;
+    if (ofdm->verbose > 1) {
+        fprintf(stderr, "  foff_metric: %f %f foff_est: %f\n", crealf(ofdm->foff_metric), cimagf(ofdm->foff_metric), foff_est);
+    }
+    
+    return foff_est;
 }
 
+
 /*
  * ----------------------------------------------
  * ofdm_txframe - modulates one frame of symbols
@@ -562,8 +593,9 @@ int ofdm_sync_search(struct OFDM *ofdm, COMP *rxbuf_in)
 
     int st = OFDM_M + OFDM_NCP + OFDM_SAMPLESPERFRAME;
     int en = st + 2*OFDM_SAMPLESPERFRAME; 
-    int ct_est = coarse_sync(ofdm,  &ofdm->rxbuf[st], (en - st), &ofdm->coarse_foff_est_hz);
-
+    int ct_est = est_timing(ofdm,  &ofdm->rxbuf[st], (en - st));
+    ofdm->coarse_foff_est_hz = est_freq_offset(ofdm,  &ofdm->rxbuf[st], (en - st), ct_est);
+   
     if (ofdm->verbose) {
         fprintf(stderr, "   ct_est: %4d foff_est: %3.1f timing_valid: %d timing_mx: %f\n",
                 ct_est, ofdm->coarse_foff_est_hz, ofdm->timing_valid, ofdm->timing_mx);
@@ -641,9 +673,16 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) {
 
         /* note coarse sync just used for timing est, we dont use coarse_foff_est in this call */
         
-        ft_est = coarse_sync(ofdm, work, (en - st), &ofdm->coarse_foff_est_hz);
+        ft_est = est_timing(ofdm, work, (en - st));
         ofdm->timing_est += (ft_est - ceilf(OFDM_FTWINDOWWIDTH / 2));
 
+        /* keep the freq est statistic updated in case we lose sync,
+           note we supply it with uncorrected rxbuf, note
+           ofdm->coarse_fest_off_hz is unused in normal operation,
+           but stored for use in tofdm.c */
+    
+        ofdm->coarse_foff_est_hz = est_freq_offset(ofdm, &ofdm->rxbuf[st], (en-st), ft_est);
+        
         if (ofdm->verbose > 1) {
             fprintf(stderr, "  ft_est: %2d timing_est: %2d sample_point: %2d\n", ft_est, ofdm->timing_est, ofdm->sample_point);
         }
@@ -1020,34 +1059,13 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) {
 
 void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw) {
     char next_state[OFDM_STATE_STR];
-    int  i, j;
+    int  i;
     
     strcpy(next_state, ofdm->sync_state);    
     ofdm->sync_start = ofdm->sync_end = 0;
   
     if (strcmp(ofdm->sync_state,"search") == 0) { 
         if (ofdm->timing_valid) {
-
-            /* freq offset est has some bias, but this refinement step fixes bias */
-
-            int st = OFDM_M + OFDM_NCP + OFDM_SAMPLESPERFRAME;
-            int en = st + 2 * OFDM_SAMPLESPERFRAME; 
-            float woff_est = TAU * ofdm->foff_est_hz / OFDM_FS;
-
-            complex float work[(en - st)];
-
-            for (i = st, j = 0; i < en; i++, j++) {
-                work[j] = ofdm->rxbuf[i] * cexpf(-I * woff_est * i);
-            }
-
-            float foff_est;
-            coarse_sync(ofdm, work, (en - st), &foff_est);
-
-            if (ofdm->verbose) {
-                fprintf(stderr, "  coarse_foff: %4.1f refine: %4.1f combined: %4.1f\n", ofdm->foff_est_hz, foff_est, ofdm->foff_est_hz+foff_est);
-            }
-
-            ofdm->foff_est_hz += foff_est;
             ofdm->frame_count = 0;
             ofdm->sync_counter = 0;
             ofdm->sync_start = 1;
@@ -1100,7 +1118,7 @@ void ofdm_sync_state_machine(struct OFDM *ofdm, int *rx_uw) {
                 ofdm->sync_counter = 0;
             }
                 
-            if ((ofdm->sync_mode == OFDM_SYNC_AUTO) && (ofdm->sync_counter == 6)) {
+            if ((ofdm->sync_mode == OFDM_SYNC_AUTO) && (ofdm->sync_counter == 12)) {
                 /* run of consective bad frames ... drop sync */
                 strcpy(next_state, "search");
                 strcpy(ofdm->sync_state_interleaver, "search");
index c5e268897af0da680e548226ce8bbddf113a8841..0ee5f0d445e6ac9823ebda475799fed9de00bf49 100644 (file)
@@ -169,6 +169,9 @@ int main(int argc, char *argv[])
     if ((arg = opt_exists(argv, argc, "-v")) != 0) {
         ofdm_set_verbose(ofdm, 1);
     }
+    if ((arg = opt_exists(argv, argc, "-vv")) != 0) {
+        ofdm_set_verbose(ofdm, 2);
+    }
 
     int Nbitsperframe = ofdm_get_bits_per_frame(ofdm);
     int Nmaxsamperframe = ofdm_get_max_samples_per_frame();
@@ -206,7 +209,7 @@ int main(int argc, char *argv[])
         if (strcmp(ofdm->sync_state,"search") == 0) {
             ofdm_sync_search(ofdm, rxbuf_in);
         }
-    
+        
         if ((strcmp(ofdm->sync_state,"synced") == 0) || (strcmp(ofdm->sync_state,"trial") == 0) ) {
             ofdm_demod(ofdm, rx_bits, rxbuf_in);
             
index a52d8c3340ec0fb0c92a5b377a63f373bef55706..119dd51359a880061dce4e17eda4469051f659b9 100644 (file)
@@ -78,7 +78,7 @@ extern "C" {
 #define OFDM_MAX_SAMPLESPERFRAME (OFDM_SAMPLESPERFRAME + (OFDM_M + OFDM_NCP)/4)
 #define OFDM_RXBUF               (3 * OFDM_SAMPLESPERFRAME + 3 * (OFDM_M + OFDM_NCP))
 
-#define OFDM_TIMING_MX_THRESH    0.3
+#define OFDM_TIMING_MX_THRESH    0.25
 
 /* reserve 4 bits/frame for auxillary text information */
 
@@ -128,6 +128,7 @@ struct OFDM {
     float sig_var;
     float noise_var;
     float mean_amp;
+    complex float foff_metric;
     
     /* modem sync state machine */
 
index adc265e1ccdf0fec68f9d325610517c426065cf0..2c398390afd0e452a0cc3f34fe5f563b243f61ea 100644 (file)
@@ -70,7 +70,7 @@ int main(int argc, char *argv[])
     if (argc < 3) {
         fprintf(stderr, "\n");
        fprintf(stderr, "usage: %s InputOneCharPerBitFile OutputModemRawFile [--lpdc] [--interleaver depth]\n\n", argv[0]);
-        fprintf(stderr, "  --testframe Nsecs   Transmit test frames (adjusts test frames for raw and LDPC modes)\n");
+        fprintf(stderr, "  --testframes Nsecs  Transmit test frames (adjusts test frames for raw and LDPC modes)\n");
         fprintf(stderr, "  --ldpc              Run (%d,%d) LDPC decoder.  This forces 112, one char/bit output values\n"
                         "                      per frame.  In testframe mode (-t) raw and coded errors will be counted\n",
                                                coded_bits_per_frame, data_bits_per_frame);
@@ -126,7 +126,7 @@ int main(int argc, char *argv[])
    
     testframes = 0;
     int Nframes = 0;
-    if ((arg = (opt_exists(argv, argc, "-t")))) {
+    if ((arg = (opt_exists(argv, argc, "--testframes")))) {
         testframes = 1;
         int Nsec, Nrows;
         Nsec = atoi(argv[arg+1]);