Further work on freedv 2400A/B
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 20 Feb 2016 06:09:25 +0000 (06:09 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 20 Feb 2016 06:09:25 +0000 (06:09 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2704 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/octave/fmfsk.m
codec2-dev/src/fmfsk.c
codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_vhf_framing.c

index 1d3cfabbe58882292b8fd021bdc142281200fcc1..5f1e64fe43d7723688a872135de319f34fc76813 100644 (file)
@@ -123,10 +123,10 @@ function [rx_bits states] = fmfsk_demod(states,rx)
     %If rx timing is too far out, ask for more or less sample the next time
     % around to even it all out
     next_nin = N;
-    if norm_rx_timing > .5;
+    if norm_rx_timing > 0;
        next_nin += Ts/2;
     end
-    if norm_rx_timing < -.5;
+    if norm_rx_timing < -.8;
        next_nin -= Ts/2;
     end
 
index a80ad9659f690dd016ba66ca1a54a937ce515beb..8e6b8ca3970e09c308b877f371e8ed3c13121da4 100644 (file)
@@ -215,9 +215,9 @@ void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]){
     /* Request fewer or greater samples next time, if fine timing is far
      * enough off. This also makes it possible to tolerate clock offsets */
     next_nin = N;
-    if(norm_rx_timing > .5)
+    if(norm_rx_timing > 0)
         next_nin += Ts/2;
-    if(norm_rx_timing < -.5)
+    if(norm_rx_timing < -.8)
         next_nin -= Ts/2;
     fmfsk->nin = next_nin;
     
index 29671bc7cc648630e23c330662cb21fd976fa184..f3362350958334a3ab4ec4852f27854b5f14ab65 100644 (file)
@@ -268,6 +268,12 @@ void freedv_close(struct freedv *freedv) {
 #ifndef CORTEX_M4
     if (freedv->mode == FREEDV_MODE_700)
         cohpsk_destroy(freedv->cohpsk);
+        
+    if (freedv->mode == FREEDV_MODE_2400A)
+        fsk_destroy(freedv->fsk);
+    
+    if (freedv->mode == FREEDV_MODE_2400B)
+        fmfsk_destroy(freedv->fmfsk);
 #endif
     codec2_destroy(freedv->codec2);
     if (freedv->ptFilter8000to7500) {
@@ -328,6 +334,7 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
     COMP tx_fdm[f->n_nom_modem_samples];
     int  i;
     float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */
+    uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */
     
     assert((f->mode == FREEDV_MODE_1600) || (f->mode == FREEDV_MODE_700) || 
            (f->mode == FREEDV_MODE_700B) || (f->mode == FREEDV_MODE_2400A) || 
@@ -339,8 +346,31 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
     if((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
         codec2_encode(f->codec2, f->packed_codec_bits, speech_in);
         
-        /* TODO: add varicode/protocol insertion */
-        fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),NULL,NULL);
+        /* Get varicode bits for TX and possibly ask for a new char */
+        /* 2 bits per 2400A/B frame, so this has to be done twice */
+        for(i=0;i<2;i++){
+            if (f->nvaricode_bits) {
+                vc_bits[i] = f->tx_varicode_bits[f->varicode_bit_index++];
+                f->nvaricode_bits--;
+            }
+
+            if (f->nvaricode_bits == 0) {
+                /* get new char and encode */
+                char s[2];
+                if (f->freedv_get_next_tx_char != NULL) {
+                    s[0] = (*f->freedv_get_next_tx_char)(f->callback_state);
+                    f->nvaricode_bits = varicode_encode(f->tx_varicode_bits, s, VARICODE_MAX_BITS, 1, 1);
+                    f->varicode_bit_index = 0;
+                }
+            }
+        }
+        
+        /* If the API user hasn't set up message callbacks, don't bother with varicode bits */
+        if(f->freedv_get_next_tx_char == NULL){
+            fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),NULL,NULL);
+        }else{
+            fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),NULL,vc_bits);
+        }
         
         /* Allocate floating point buffer for FSK mod */
         tx_float = alloca(sizeof(float)*f->n_nom_modem_samples);
@@ -615,7 +645,6 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
     int nin = freedv_nin(f);
 
     assert(nin <= f->n_max_modem_samples);
-    
     /* FSK RX happens in real floats, so convert to those and call their demod here */
     if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) ){
         for(i=0; i<nin; i++) {
@@ -650,6 +679,8 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
         if(f->mode == FREEDV_MODE_2400A){
             fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_in);
             f->nin = fsk_nin(f->fsk);
+            f->stats.snr_est = f->fsk->EbNodB;
+            f->stats.clock_offset = f->fsk->ppm;
         }else{            
             fmfsk_demod(f->fmfsk,(uint8_t*)f->tx_bits,demod_in);
             f->nin = fmfsk_nin(f->fmfsk);
@@ -659,11 +690,14 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
             /* Decode the codec data */
             codec2_decode(f->codec2,speech_out,f->packed_codec_bits);
             f->sync = 1;
+            f->stats.sync = 1;
         } else {
             /* Fill with silence */
             for(i=0;i<f->n_speech_samples;i++){
                 speech_out[i] = 0;
             }
+            f->sync = 0;
+            f->stats.sync = 0;
         }
         return f->n_speech_samples;
     }else { 
index d4a9ced7cdc76b6662b220c870b7cf370ad30404..5e839c3fc30ab266d0970d2d195f8c4e60415b81 100644 (file)
@@ -279,7 +279,7 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
     /* Possibly set up frame-specific params here */
     if(frame_type == FREEDV_VHF_FRAME_A){
         uw_first_tol = 1;   /* The UW bit-error tolerance for the first frame */
-        uw_sync_tol = 1;    /* The UW bit error tolerance for frames after sync */
+        uw_sync_tol = 2;    /* The UW bit error tolerance for frames after sync */
         miss_tol = 5;       /* How many UWs may be missed before going into the de-synced state */
     }else{
         return 0;