Initial commit of experimental 800 FSK mode
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 13 Apr 2016 05:07:16 +0000 (05:07 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Wed, 13 Apr 2016 05:07:16 +0000 (05:07 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2785 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/freedv_api.c
codec2-dev/src/freedv_api.h
codec2-dev/src/freedv_rx.c
codec2-dev/src/freedv_tx.c
codec2-dev/src/freedv_vhf_framing.c
codec2-dev/src/freedv_vhf_framing.h
codec2-dev/src/fsk.c
codec2-dev/src/fsk.h
codec2-dev/unittest/tdeframer.c

index 7eff7c1f8c3480bd7514b72b5b25de278cb570a2..8489a2c57f36e72d4068b29fbea983cca92aa374 100644 (file)
@@ -77,7 +77,7 @@ struct freedv *freedv_open(int mode) {
 
     if ((mode != FREEDV_MODE_1600) && (mode != FREEDV_MODE_700) && 
         (mode != FREEDV_MODE_700B) && (mode != FREEDV_MODE_2400A) &&
-        (mode != FREEDV_MODE_2400B))
+        (mode != FREEDV_MODE_2400B) && (mode != FREEDV_MODE_800XA))
         return NULL;
 
     f = (struct freedv*)malloc(sizeof(struct freedv));
@@ -203,6 +203,38 @@ struct freedv *freedv_open(int mode) {
         fmfsk_setup_modem_stats(f->fmfsk,&(f->stats));
     }
     
+    if (mode == FREEDV_MODE_800XA) {
+        /* Create the framer|deframer */
+        f->deframer = fvhff_create_deframer(FREEDV_HF_FRAME_B,0);
+        if(f->deframer == NULL)
+            return NULL;
+  
+        f->fsk = fsk_create_hbr(8000,400,10,4,400,400);
+        fsk_set_nsym(f->fsk,32);
+        
+        /* Note: fsk expects tx/rx bits as an array of uint8_ts, not ints */
+        f->tx_bits = (int*)malloc(f->fsk->Nbits*sizeof(uint8_t));
+        
+        if(f->fsk == NULL){
+            fvhff_destroy_deframer(f->deframer);
+            return NULL;
+        }
+        
+        f->n_nom_modem_samples = f->fsk->N;
+        f->n_max_modem_samples = f->fsk->N + (f->fsk->Ts);
+        f->n_nat_modem_samples = f->fsk->N;
+        f->nin = fsk_nin(f->fsk);
+        f->modem_sample_rate = 8000;
+        /* Malloc something to appease freedv_init and freedv_destroy */
+        f->codec_bits = malloc(1);
+        
+        f->n_protocol_bits = 0;
+        codec2_mode = CODEC2_MODE_700B;
+        
+        /* Set up the stats */
+        fsk_setup_modem_stats(f->fsk,&(f->stats));
+    }
+    
 #endif
 
     f->test_frame_sync_state = 0;
@@ -214,12 +246,20 @@ struct freedv *freedv_open(int mode) {
         return NULL;
     if ((mode == FREEDV_MODE_1600) || (mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B)) {
         f->n_speech_samples = codec2_samples_per_frame(f->codec2);
-       f->n_codec_bits = codec2_bits_per_frame(f->codec2);
+        f->n_codec_bits = codec2_bits_per_frame(f->codec2);
         nbit = f->n_codec_bits;
         nbyte = (nbit + 7) / 8;
+    } else if ((mode == FREEDV_MODE_800XA)) {
+        f->n_speech_samples = 2*codec2_samples_per_frame(f->codec2);
+        f->n_codec_bits = codec2_bits_per_frame(f->codec2);
+        nbit = f->n_codec_bits;
+        nbyte = (nbit + 7) / 8;
+        nbyte = nbyte*2;
+        nbit = 8*nbyte;
+        f->n_codec_bits = nbit;
     } else { /* ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B)) */
         f->n_speech_samples = 2*codec2_samples_per_frame(f->codec2);
-       f->n_codec_bits = 2*codec2_bits_per_frame(f->codec2);
+        f->n_codec_bits = 2*codec2_bits_per_frame(f->codec2);
         nbit = f->n_codec_bits;
         nbyte = 2*((codec2_bits_per_frame(f->codec2) + 7) / 8);
     }
@@ -351,40 +391,46 @@ static void freedv_tx_fsk_voice(struct freedv *f, short mod_out[]) {
     uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */
     uint8_t proto_bits[3]; /* Prococol bits for 2400 framing */
         
-    /* 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--;
-        }
+    /* Frame for 2400A/B */
+    if(f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_2400B){
+        /* 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 (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_proto != NULL){
-        (*f->freedv_get_next_proto)(f->proto_callback_state,(char*)proto_bits);
-        fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),proto_bits,vc_bits);
-    }else 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,vc_bits);
-    }else {
-        fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),NULL,NULL);
+            
+        /* If the API user hasn't set up message callbacks, don't bother with varicode bits */
+        if(f->freedv_get_next_proto != NULL){
+            (*f->freedv_get_next_proto)(f->proto_callback_state,(char*)proto_bits);
+            fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),proto_bits,vc_bits);
+        }else 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,vc_bits);
+        }else {
+            fvhff_frame_bits(FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),NULL,NULL);
+        }
+    /* Frame for 800XA */
+    }else if(f->mode == FREEDV_MODE_800XA){
+        fvhff_frame_bits(FREEDV_HF_FRAME_B,(uint8_t*)(f->tx_bits),(uint8_t*)(f->packed_codec_bits),NULL,NULL);
     }
         
     /* Allocate floating point buffer for FSK mod */
     tx_float = alloca(sizeof(float)*f->n_nom_modem_samples);
         
     /* do 4fsk mod */
-    if(f->mode == FREEDV_MODE_2400A){
+    if(f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_800XA){
         fsk_mod(f->fsk,tx_float,(uint8_t*)(f->tx_bits));
         /* Convert float samps to short */
         for(i=0; i<f->n_nom_modem_samples; i++){
@@ -406,7 +452,7 @@ static void freedv_tx_fsk_voice(struct freedv *f, short mod_out[]) {
 static void freedv_tx_fsk_data(struct freedv *f, short mod_out[]) {
     int  i;
     float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */
-        
+    
     fvhff_frame_data_bits(f->deframer, FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits));
         
     /* Allocate floating point buffer for FSK mod */
@@ -434,18 +480,27 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) {
     assert(f != NULL);
     COMP tx_fdm[f->n_nom_modem_samples];
     int  i;
-    
-    assert((f->mode == FREEDV_MODE_1600) || (f->mode == FREEDV_MODE_700) || 
-           (f->mode == FREEDV_MODE_700B) || (f->mode == FREEDV_MODE_2400A) || 
-           (f->mode == FREEDV_MODE_2400B));
+    uint8_t c2_buf[8];
+    assert((f->mode == FREEDV_MODE_1600)  || (f->mode == FREEDV_MODE_700)   || 
+           (f->mode == FREEDV_MODE_700B)  || (f->mode == FREEDV_MODE_2400A) || 
+           (f->mode == FREEDV_MODE_2400B) || (f->mode == FREEDV_MODE_800XA));
     
     /* FSK and MEFSK/FMFSK modems work only on real samples. It's simpler to just 
      * stick them in the real sample tx/rx functions than to add a comp->real converter
      * to comptx */
      
-    if((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
+    if((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) || (f->mode == FREEDV_MODE_800XA)){
 #ifndef CORTEX_M4
-        codec2_encode(f->codec2, f->packed_codec_bits, speech_in);
+        /* 800XA has two codec frames per modem frame */
+        if((f->mode == FREEDV_MODE_800XA)){
+            memset(f->packed_codec_bits,0,8);
+            codec2_encode(f->codec2, &f->packed_codec_bits[0], &speech_in[  0]);
+            codec2_encode(f->codec2, &f->packed_codec_bits[4], &speech_in[320]);
+            uint8_t * cb = &f->packed_codec_bits[0];
+            fprintf(stderr,"%02x%02x%02x%02x %02x%02x%02x%02x\n",cb[0],cb[1],cb[2],cb[3],cb[4],cb[5],cb[6],cb[7]);
+        }else{
+            codec2_encode(f->codec2, f->packed_codec_bits, speech_in);
+        }
         freedv_tx_fsk_voice(f, mod_out);
 #endif
     }else{
@@ -784,7 +839,7 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
     float rx_float[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) ){
+    if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) || (f->mode == FREEDV_MODE_800XA) ){
         for(i=0; i<nin; i++) {
             rx_float[i] = ((float)demod_in[i]);
         }
@@ -805,7 +860,7 @@ int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
 
 // float input samples version
 #ifndef CORTEX_M4
-int freedv_floatrx_fsk_2400(struct freedv *f, float demod_in[], int *valid) {
+int freedv_floatrx_fsk(struct freedv *f, float demod_in[], int *valid) {
     /* Varicode and protocol bits */
     uint8_t vc_bits[2];
     uint8_t proto_bits[3];
@@ -814,7 +869,7 @@ int freedv_floatrx_fsk_2400(struct freedv *f, float demod_in[], int *valid) {
     int n_ascii;
     char ascii_out;
     
-    if(f->mode == FREEDV_MODE_2400A){
+    if(f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_800XA){
         fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_in);
         f->nin = fsk_nin(f->fsk);
     }else{            
@@ -859,9 +914,9 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
     
     /* FSK RX happens in real floats, so demod for those goes here */
     #ifndef CORTEX_M4
-    if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) ){
+    if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) || (f->mode == FREEDV_MODE_800XA)){
         int valid;
-        int nout = freedv_floatrx_fsk_2400(f, demod_in, &valid);
+        int nout = freedv_floatrx_fsk(f, demod_in, &valid);
         if (valid == 0)
             for (i = 0; i < nout; i++)
                 speech_out[i] = 0;
@@ -1253,8 +1308,8 @@ int freedv_codecrx(struct freedv *f, unsigned char *packed_codec_bits, short dem
         freedv_comprx_fdmdv_700(f, rx_fdm, &valid);
     }
     
-    if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) ){
-        freedv_floatrx_fsk_2400(f, rx_float, &valid);
+    if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) || (f->mode == FREEDV_MODE_800XA)){
+        freedv_floatrx_fsk(f, rx_float, &valid);
     }
 #endif
 
index 44bc66a708f64536da27a4af2ae858a2eaaef7d0..5158517e1bb6c556c4b50cd18e01d6a2f524ba16 100644 (file)
@@ -42,6 +42,7 @@
 #define FREEDV_MODE_700B        2
 #define FREEDV_MODE_2400A       3
 #define FREEDV_MODE_2400B       4
+#define FREEDV_MODE_800XA       5
 
 struct freedv;
 
index 210ff4fab8ab27b62b05481492f3b7851a9563e8..df7207c0ff3ae0593228b6818b3b3fa2dc0c8917 100644 (file)
@@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
     float                      clock_offset;
 
     if (argc < 4) {
-       printf("usage: %s 1600|700|700B|2400A|2400B InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
+       printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
        printf("e.g    %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]);
        exit(1);
     }
@@ -94,6 +94,8 @@ int main(int argc, char *argv[]) {
         mode = FREEDV_MODE_2400A;
     if (!strcmp(argv[1],"2400B"))
         mode = FREEDV_MODE_2400B;
+    if (!strcmp(argv[1],"800XA"))
+        mode = FREEDV_MODE_800XA;
     assert(mode != -1);
 
     if (strcmp(argv[2], "-")  == 0) fin = stdin;
index 5a6aeaafd4086be28cedc919868f3ca0437eecbf..b96103dac85982f1480b8f1fa77412107773852f 100644 (file)
@@ -67,7 +67,7 @@ int main(int argc, char *argv[]) {
     int                       n_nom_modem_samples;
 
     if (argc < 4) {
-        printf("usage: %s 1600|700|700B|2400A|2400B InputRawSpeechFile OutputModemRawFile [--testframes]\n", argv[0]);
+        printf("usage: %s 1600|700|700B|2400A|2400B|800XA InputRawSpeechFile OutputModemRawFile [--testframes]\n", argv[0]);
         printf("e.g    %s 1600 hts1a.raw hts1a_fdmdv.raw\n", argv[0]);
         exit(1);
     }
@@ -83,6 +83,8 @@ int main(int argc, char *argv[]) {
         mode = FREEDV_MODE_2400A;
     if (!strcmp(argv[1],"2400B"))
         mode = FREEDV_MODE_2400B;
+    if (!strcmp(argv[1],"800XA"))
+        mode = FREEDV_MODE_800XA;
     assert(mode != -1);
 
     if (strcmp(argv[2], "-")  == 0) fin = stdin;
index 14f54c1b8bc923bf4e1c5d9be4a0aee63da2638b..63757f6f30e118a65f3a40081cafbe01ccf09695 100644 (file)
@@ -251,7 +251,12 @@ struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enabl
     deframer->frame_size = frame_size;
     deframer->uw_size = uw_size;
     deframer->on_inv_bits = 0;
+    deframer->sym_size = 1;
+    
     deframer->ber_est = 0;
+    deframer->total_uw_bits = 0;
+    deframer->total_uw_err = 0;
+    
     deframer->fdc = NULL;
 
     return deframer;
@@ -555,14 +560,16 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
     }else{
         return 0;
     }
+    /* Skip N bits for multi-bit symbol modems */
     for(i=0; i<frame_size; i++){
         /* Put a bit in the buffer */
         strbits[bitptr] = bits_in[i];
         /* If we're checking the inverted bitstream, put a bit in it */
         if(invbits!=NULL)
             invbits[bitptr] = bits_in[i]?0:1;
+        
         bitptr++;
-        if(bitptr >= frame_size) bitptr = 0;
+        if(bitptr >= frame_size) bitptr -= frame_size;
         def->bitptr = bitptr;
         /* Enter state machine */
         if(state==ST_SYNC){
@@ -594,7 +601,9 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
                 fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out,pt);
                 
                 /* Update BER estimate */
-                def->ber_est = (.99*def->ber_est) + (.01*((float)uw_diff)/((float)uw_size));
+                def->ber_est = (.995*def->ber_est) + (.005*((float)uw_diff)/((float)uw_size));
+                def->total_uw_bits += uw_size;
+                def->total_uw_err += uw_diff;
             }
         /* Not yet sunk */
         }else{
@@ -608,7 +617,9 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
                     on_inv_bits = 1;
                     fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out,pt);
                     /* Update BER estimate */
-                    def->ber_est = (.99*def->ber_est) + (.01*((float)uw_diff)/((float)uw_size));
+                    def->ber_est = (.995*def->ber_est) + (.005*((float)uw_diff)/((float)uw_size));
+                    def->total_uw_bits += uw_size;
+                    def->total_uw_err += uw_diff;
                 }
             }
             if(fvhff_match_uw(def,strbits,uw_first_tol, &uw_diff, &pt)){
@@ -619,7 +630,9 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
                 on_inv_bits = 0;
                 fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out,pt);
                 /* Update BER estimate */
-                def->ber_est = (.98*def->ber_est) + (.02*((float)uw_diff)/((float)uw_size));
+                def->ber_est = (.995*def->ber_est) + (.005*((float)uw_diff)/((float)uw_size));
+                def->total_uw_bits += uw_size;
+                def->total_uw_err += uw_diff;
             }
         }
     }
index c41e801b1caca70c382d40d1057d2debda53d8d7..877d6bfe9a8fd7b633102133407cdb296fd54a08 100644 (file)
@@ -53,9 +53,12 @@ struct freedv_vhf_deframer {
     int last_uw;        /* How many bits since the last UW? */\r
     int frame_size;     /* How big is a frame? */
     int uw_size;        /* How big is the UW */\r
-    int on_inv_bits;    /* Are we using the inverted bits? */\r
+    int on_inv_bits;    /* Are we using the inverted bits? */
+    int sym_size;       /* How many bits in a modem symbol */ \r
 
     float ber_est;      /* Bit error rate estimate */
+    int total_uw_bits;  /* Total RX-ed bits of UW */
+    int total_uw_err;   /* Total errors in UW bits */
 \r
     struct freedv_data_channel *fdc;\r
 };\r
index a7053e986f41ca95778b2de199d637110c74d807..dc2ea95607084b26d07648fcba532b8689cab607 100644 (file)
@@ -346,6 +346,37 @@ struct FSK * fsk_create(int Fs, int Rs,int M, int tx_f1, int tx_fs)
     return fsk;
 }
 
+
+void fsk_set_nsym(struct FSK *fsk,int nsyms){
+    assert(nsyms>0);
+    int Ndft,i;
+    Ndft = 0;
+    
+    /* Set constant config parameters */
+    fsk->N = fsk->Ts*nsyms;
+    fsk->Nsym = nsyms;
+    fsk->Nmem = fsk->N+(2*fsk->Ts);
+    fsk->nin = fsk->N;
+    fsk->Nbits = fsk->mode==2 ? fsk->Nsym : fsk->Nsym*2;
+    
+    /* Find smallest 2^N value that fits Fs for efficient FFT */
+    /* It would probably be better to use KISS-FFt's routine here */
+    for(i=1; i; i<<=1)
+        if((fsk->N)&i)
+            Ndft = i;
+    
+    fsk->Ndft = Ndft;
+    
+    free(fsk->fft_cfg);
+    free(fsk->fft_est);
+    
+    fsk->fft_cfg = kiss_fftr_alloc(Ndft,0,NULL,NULL);
+    fsk->fft_est = (float*)malloc(sizeof(float)*fsk->Ndft/2);
+    
+    for(i=0;i<Ndft/2;i++)fsk->fft_est[i] = 0;
+    
+}
+
 uint32_t fsk_nin(struct FSK *fsk){
     return (uint32_t)fsk->nin;
 }
index 29563dca596171a2cce52e6a041f253eb0471f4f..a0a75ba9fe1735301462598e7d1aba7ce56f8cdd 100644 (file)
@@ -109,6 +109,11 @@ struct FSK * fsk_create(int Fs, int Rs, int M, int tx_f1, int tx_fs);
  */
 struct FSK * fsk_create_hbr(int Fs, int Rs, int P, int M, int tx_f1, int tx_fs);
 
+/* 
+ * Set a new number of symbols per processing frame
+ */
+void fsk_set_nsym(struct FSK *fsk,int nsym);
+
 /*
  * Set a MODEM_STATS struct in which to deposit demod statistics
  */
index b1fe759765cc2b57a52c7274211bcdb31d03ece4..03e8bb141c7684e7218a22a1281882b932a2e91e 100644 (file)
 #define TESTBER 0.01
 
 /* Frame count */
-#define FRCNT 15000
+#define FRCNT 1500
 
 /* Random bits leading frame */
-#define LRCNT 55
+#define LRCNT 44
 
 #include <stdio.h>
 #include <math.h>
@@ -135,6 +135,7 @@ int main(int argc,char *argv[]){
     printf("Extracted %d frames of %d, %f hit rate\n",total_extract,FRCNT,((float)total_extract/(float)FRCNT));
     printf("Bit error rate %f measured from golay code\n",measured_ber);
     printf("Bit error rate %f measured by deframer\n",fvd->ber_est);
+    printf("Bit error rate %f measured by deframer\n",(float)fvd->total_uw_err/(float)fvd->total_uw_bits);
     /* Check test condition */
     if(first_extract<first_tol){
         printf("Test passed at test BER of %f!\n",TESTBER);
@@ -143,4 +144,5 @@ int main(int argc,char *argv[]){
         printf("** Test failed at test BER of %f!\n",TESTBER);
         exit(1);
     }
+    fvhff_destroy_deframer(fvd);
 }