support for error pattern logging in freedv api
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 15 Jul 2015 04:42:22 +0000 (04:42 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 15 Jul 2015 04:42:22 +0000 (04:42 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2237 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/codec2.c
codec2-dev/src/codec2_cohpsk.h
codec2-dev/src/codec2_fdmdv.h
codec2-dev/src/cohpsk.c
codec2-dev/src/fdmdv.c
codec2-dev/src/fdmdv_mod.c
codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h

index debb89eb54e901e1e3f01226a4a7a54ec21ffa61..8482fb87e5ae304fa0698622d492052bdc529cd1 100644 (file)
@@ -1396,7 +1396,7 @@ void codec2_encode_700(struct CODEC2 *c2, unsigned char * bits, short speech[])
     e = speech_to_uq_lsps(lsps, ak, c2->Sn, c2->w, LPC_ORD_LOW);
     e_index = encode_energy(e, 3);
     pack_natural_or_gray(bits, &nbit, e_index, 3, c2->gray);
+
     for(i=0; i<LPC_ORD_LOW; i++) {
         f = (4000.0/PI)*lsps[i];
         mel[i] = floor(2595.0*log10(1.0 + f/700.0) + 0.5);
index 126b9760da1f4022fbc0a698dc67d8a05b16a2cd..c7879b86e6cf88752a4958de17f380cf2dfb1440 100644 (file)
@@ -54,6 +54,7 @@ void cohpsk_set_verbose(struct COHPSK *coh, int verbose);
 void cohpsk_get_test_bits(struct COHPSK *coh, int rx_bits[]);
 void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[],
                           int *bit_errors, float rx_bits_sd[]);
+int cohpsk_error_pattern_size(void);
 void cohpsk_set_frame(struct COHPSK *coh, int frame);
 
 #endif
index e440c1df44f257cd5e10754ba40f11e97c697cb8..334696c9cd7e40acef23aa2c5a826ea51e7fef07 100644 (file)
@@ -103,7 +103,7 @@ void           fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff,
 /* debug/development function(s) */
 
 void fdmdv_dump_osc_mags(struct FDMDV *f);
-void fdmdv_simulate_channel(struct FDMDV *f, COMP samples[], int nin, float target_snr);
+void fdmdv_simulate_channel(float *sig_pwr_av, COMP samples[], int nin, float target_snr);
  
 #ifdef __cplusplus
 }
index 0304c8bdbea8190dce4d9e5d4bda25b988d6d5b7..c89f9599865f181cef0e01741e11b622f5d455fb 100644 (file)
@@ -548,7 +548,7 @@ void frame_sync_fine_freq_est(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND],
 
         /* sample correlation over 2D grid of time and fine freq points */
 
-        max_corr = 0;
+        max_corr = max_mag = 0;
         for (f_fine=-20; f_fine<=20; f_fine+=0.25) {
             for (t=0; t<NSYMROWPILOT; t++) {
                 corr_with_pilots(&corr, &mag, coh, t, f_fine);
@@ -818,12 +818,13 @@ void rate_Fs_rx_processing(struct COHPSK *coh, COMP ch_symb[][COHPSK_NC*ND], COM
     COMP  rx_fdm_frame_bb[COHPSK_M+COHPSK_M/P];
     COMP  rx_baseband[COHPSK_NC*ND][COHPSK_M+COHPSK_M/P];
     COMP  rx_filt[COHPSK_NC*ND][P+1];
-    float env[NT*P], __attribute__((unused)) rx_timing;
+    float env[NT*P], rx_timing;
     COMP  rx_onesym[COHPSK_NC*ND];
     float beta, g;
     COMP  adiff, amod_strip, mod_strip;
 
     ch_fdm_frame_index = 0;
+    rx_timing = 0;
 
     for (r=0; r<nsymb; r++) {
         fdmdv_freq_shift_coh(rx_fdm_frame_bb, &ch_fdm_frame[ch_fdm_frame_index], -(*f_est), &fdmdv->fbb_phase_rx, nin);
@@ -958,6 +959,7 @@ void cohpsk_demod(struct COHPSK *coh, float rx_bits[], int *sync_good, COMP rx_f
         /* we can test +/- 20Hz, so we break this up into 3 tests to cover +/- 60Hz */
 
         max_ratio = 0.0;
+        f_est = 0.0;
         for (coh->f_est = FDMDV_FCENTRE-40.0; coh->f_est <= FDMDV_FCENTRE+40.0; coh->f_est += 40.0) {
         
             if (coh->verbose)
@@ -1212,14 +1214,33 @@ void cohpsk_put_test_bits(struct COHPSK *coh, int *state, short error_pattern[],
         }
     }
 
-    if (*state == 1) {
+    /* if 5 frames with large BER reset test frame sync */
+
+    if (*state > 0) {
+        if (*bit_errors > 8) {
+            if (*state == 6)
+                next_state = 0;
+            else
+                next_state = *state+1;
+        }
+        else
+            next_state = 1;
+    }
+
+    if (*state > 0) {
         coh->ptest_bits_coh_rx += COHPSK_BITS_PER_FRAME;
         if (coh->ptest_bits_coh_rx >= coh->ptest_bits_coh_end) {
             coh->ptest_bits_coh_rx = (int*)test_bits_coh;
         }
     }
+   
+    //fprintf(stderr, "state: %d next_state: %d bit_errors: %d\n", *state, next_state, *bit_errors);
 
     *state = next_state;
 }
 
+int cohpsk_error_pattern_size(void) { 
+    return COHPSK_BITS_PER_FRAME;
+}
+
 
index 9feb6b77b736fe882de27b13663bc9490f3616d2..7ff16c597913ef3377d3c0caf233c7fb2301804c 100644 (file)
@@ -1819,12 +1819,15 @@ static float randn() {
   Simple channel simulation function to aid in testing.  Target SNR
   uses noise measured in a 3 kHz bandwidth.  
 
+  Doesn't use fdmdv states so can be called from anywhere, e.g. non
+  fdmdv applications.
+
   TODO: Measured SNR is coming out a few dB higher than target_snr, this
   needs to be fixed.
 
 \*---------------------------------------------------------------------------*/
 
-void fdmdv_simulate_channel(struct FDMDV *f, COMP samples[], int nin, float target_snr) 
+void fdmdv_simulate_channel(float *sig_pwr_av, COMP samples[], int nin, float target_snr) 
 {
     float sig_pwr, target_snr_linear, noise_pwr, noise_pwr_1Hz, noise_pwr_4000Hz, noise_gain;
     int   i;
@@ -1837,12 +1840,12 @@ void fdmdv_simulate_channel(struct FDMDV *f, COMP samples[], int nin, float targ
     
     sig_pwr /= nin;
 
-    f->sig_pwr_av = 0.9*f->sig_pwr_av + 0.1*sig_pwr;
+    *sig_pwr_av = 0.9**sig_pwr_av + 0.1*sig_pwr;
 
     /* det noise to meet target SNR */
 
     target_snr_linear = powf(10.0, target_snr/10.0);
-    noise_pwr = f->sig_pwr_av/target_snr_linear;       /* noise pwr in a 3000 Hz BW     */
+    noise_pwr = *sig_pwr_av/target_snr_linear;       /* noise pwr in a 3000 Hz BW     */
     noise_pwr_1Hz = noise_pwr/3000.0;                  /* noise pwr in a 1 Hz bandwidth */
     noise_pwr_4000Hz = noise_pwr_1Hz*4000.0;           /* noise pwr in a 4000 Hz BW, which 
                                                           due to fs=8000 Hz in our simulation noise BW */
index 662fd80fe75413c153c2c6cd35fa9b68fafb4e6d..5fac650a3161165e7ddde0187608c50d098a4e54 100644 (file)
@@ -130,7 +130,7 @@ int main(int argc, char *argv[])
         /* optional freq shift and channel simulation */
 
         fdmdv_freq_shift(tx_fdm, tx_fdm, foff, &foff_phase_rect, 2*FDMDV_NOM_SAMPLES_PER_FRAME);
-        fdmdv_simulate_channel(fdmdv, tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME, 10.0);
+        fdmdv_simulate_channel(&sig_pwr_av, tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME, 10.0);
         #endif
 
        /* scale and save to disk as shorts */
index 9e846cfc7e55f002062eb28376926f90100cf57f..6baf8d79cfed1188e7e1571ca8c024c42d7e0f74 100644 (file)
@@ -72,6 +72,8 @@ struct freedv *freedv_open(int mode) {
     
     f->mode = mode;
     f->test_frames = f->smooth_symbols = 0;
+    f->freedv_put_error_pattern = NULL;
+    f->error_pattern_callback_state = NULL;
     f->snr_squelch_thresh = 2.0;
     f->squelch_en = 1;
    
@@ -97,6 +99,7 @@ struct freedv *freedv_open(int mode) {
         if ((f->tx_bits == NULL) || (f->rx_bits == NULL))
             return NULL;
         f->evenframe = 0;
+        f->sz_error_pattern = fdmdv_error_pattern_size(f->fdmdv);
     }
 
     if (mode == FREEDV_MODE_700) {
@@ -111,6 +114,7 @@ struct freedv *freedv_open(int mode) {
         f->tx_bits = (int*)malloc(nbit*sizeof(int));
         if (f->tx_bits == NULL)
             return NULL;
+        f->sz_error_pattern = cohpsk_error_pattern_size();
     }
 
     f->test_frame_sync_state = 0;
@@ -578,7 +582,10 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
                             if (f->test_frame_count == 0) {
                                 f->total_bit_errors += bit_errors;
                                 f->total_bits += ntest_bits;
-                            }
+                                if (f->freedv_put_error_pattern != NULL) {
+                                    (*f->freedv_put_error_pattern)(f->error_pattern_callback_state, error_pattern, fdmdv_error_pattern_size(f->fdmdv));
+                                }
+                           }
                             f->test_frame_count++;
                             if (f->test_frame_count == 4)
                                 f->test_frame_count = 0;
@@ -699,11 +706,12 @@ int freedv_comprx(struct freedv *f, short speech_out[], COMP demod_in[]) {
                 /* test data, lets see if we can sync to the test data sequence */
 
                 cohpsk_put_test_bits(f->cohpsk, &f->test_frame_sync_state, error_pattern, &bit_errors, rx_bits);
-                if (f->test_frame_sync_state == 1) {
-                    //for(i=0; i<COHPSK_BITS_PER_FRAME; i++)
-                    //    error_positions_hist[i] += error_pattern[i];
+                if (f->test_frame_sync_state) {
                     f->total_bit_errors += bit_errors;
                     f->total_bits       += COHPSK_BITS_PER_FRAME;
+                    if (f->freedv_put_error_pattern != NULL) {
+                        (*f->freedv_put_error_pattern)(f->error_pattern_callback_state, error_pattern, COHPSK_BITS_PER_FRAME);
+                    }
                 }
 
                 for(i=0; i<f->n_speech_samples; i++)
index eac86c77313c053cdf1c42db9f9359fa01dc4c60..556e01cee0f161b2b5511eb3bd7a1395dbe8a367 100644 (file)
@@ -73,6 +73,12 @@ struct freedv {
     int                  test_frame_count;
     int                  total_bits;
     int                  total_bit_errors;
+    int                  sz_error_pattern;
+
+    /* optional user defined function to pass error pattern when a test frame is received */
+
+    void                *error_pattern_callback_state;
+    void (*freedv_put_error_pattern)(void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
 
     int                  sync;
     int                  evenframe;