First working codebase with modes 2400A and 2400B. More cleanup and api work needs...
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 16 Feb 2016 01:10:50 +0000 (01:10 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 16 Feb 2016 01:10:50 +0000 (01:10 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2702 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/CMakeLists.txt
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/freedv_tx.c
codec2-dev/src/freedv_vhf_framing.c
codec2-dev/src/fsk.c

index b79d6df3dfee77407c6913aa564251975b3540f2..34f893043198e328931a0d61da49b152cea2cd9c 100644 (file)
@@ -159,6 +159,7 @@ set(CODEC2_SRCS
     codebookge.c
     golay23.c
     freedv_api.c
+    freedv_vhf_framing.c
     varicode.c
     modem_stats.c
 )
index f3d2d0630127d2dc6813174dacb318f78aaed65b..90f335c58e9e8399f7b545f5809682b8fd09349e 100644 (file)
 
 #include <assert.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
 
+
+#include "fsk.h"
+#include "fmfsk.h"
 #include "codec2.h"
 #include "codec2_fdmdv.h"
 #include "fdmdv_internal.h"
@@ -39,6 +43,7 @@
 #include "varicode.h"
 #include "freedv_api.h"
 #include "freedv_api_internal.h"
+#include "freedv_vhf_framing.h"
 #include "comp_prim.h"
 
 #define VERSION     11    /* The API version number.  The first version
@@ -70,7 +75,9 @@ struct freedv *freedv_open(int mode) {
     struct freedv *f;
     int            Nc, codec2_mode, nbit, nbyte;
 
-    if ((mode != FREEDV_MODE_1600) && (mode != FREEDV_MODE_700) && (mode != FREEDV_MODE_700B))
+    if ((mode != FREEDV_MODE_1600) && (mode != FREEDV_MODE_700) && 
+        (mode != FREEDV_MODE_700B) && (mode != FREEDV_MODE_2400A) &&
+        (mode != FREEDV_MODE_2400B))
         return NULL;
 
     f = (struct freedv*)malloc(sizeof(struct freedv));
@@ -131,6 +138,56 @@ struct freedv *freedv_open(int mode) {
             return NULL;
         f->sz_error_pattern = cohpsk_error_pattern_size();
     }
+    
+    if ((mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B)){
+        /* Create the framer|deframer */
+        f->deframer = fvhff_create_deframer(FREEDV_VHF_FRAME_A);
+        if(f->deframer == NULL)
+            return NULL;
+        
+        /* Set up the C2 mode */
+        codec2_mode = CODEC2_MODE_1300;
+    }
+    
+    if (mode == FREEDV_MODE_2400A) {
+        f->fsk = fsk_create_hbr(48000,1200,10,4,1200,1200);
+        
+        /* 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 = 48000;
+        /* Malloc something to appease freedv_init and freedv_destroy */
+        f->codec_bits = malloc(1);
+    }
+    
+    if (mode == FREEDV_MODE_2400B) {
+        f->fmfsk = fmfsk_create(48000,2400);
+         
+        if(f->fmfsk == NULL){
+            fvhff_destroy_deframer(f->deframer);
+            return NULL;
+        }
+        /* Note: fsk expects tx/rx bits as an array of uint8_ts, not ints */
+        f->tx_bits = (int*)malloc(f->fmfsk->nbit*sizeof(uint8_t));
+        
+        f->n_nom_modem_samples = f->fmfsk->N;
+        f->n_max_modem_samples = f->fmfsk->N + (f->fmfsk->Ts);
+        f->n_nat_modem_samples = f->fmfsk->N;
+        f->nin = fmfsk_nin(f->fmfsk);
+        f->modem_sample_rate = 48000;
+        /* Malloc something to appease freedv_init and freedv_destroy */
+        f->codec_bits = malloc(1);
+    }
+    
 #endif
 
     f->test_frame_sync_state = 0;
@@ -140,10 +197,11 @@ struct freedv *freedv_open(int mode) {
     f->codec2 = codec2_create(codec2_mode);
     if (f->codec2 == NULL)
         return NULL;
-    if (mode == FREEDV_MODE_1600)
+    if ((mode == FREEDV_MODE_1600) || (mode == FREEDV_MODE_2400A) || (mode == FREEDV_MODE_2400B))
         f->n_speech_samples = codec2_samples_per_frame(f->codec2);
     if ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B))
         f->n_speech_samples = 2*codec2_samples_per_frame(f->codec2);
+    
     f->prev_rx_bits = (float*)malloc(sizeof(float)*2*codec2_bits_per_frame(f->codec2));
     if (f->prev_rx_bits == NULL)
         return NULL;
@@ -155,7 +213,8 @@ struct freedv *freedv_open(int mode) {
         f->codec_bits = (int*)malloc(nbit*sizeof(int));
     if ((mode == FREEDV_MODE_700) || (mode == FREEDV_MODE_700B))
         f->codec_bits = (int*)malloc(COHPSK_BITS_PER_FRAME*sizeof(int));
-
+    
+    /* Note: VHF Framer/deframer goes directly from packed codec/vc/proto bits to filled frame */
     if ((f->packed_codec_bits == NULL) || (f->codec_bits == NULL))
         return NULL;
 
@@ -262,11 +321,42 @@ 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;
-
-    freedv_comptx(f, tx_fdm, speech_in);
-
-    for(i=0; i<f->n_nom_modem_samples; i++)
-        mod_out[i] = tx_fdm[i].real;
+    float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */
+    
+    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));
+    
+    /* 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)){
+        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);
+        
+        /* 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){
+            fsk_mod(f->fsk,tx_float,(uint8_t*)(f->tx_bits));
+        
+        /* do me-fsk mod */
+        }else if(f->mode == FREEDV_MODE_2400B){
+            fmfsk_mod(f->fmfsk,tx_float,(uint8_t*)(f->tx_bits));
+        }
+        
+        /* Convert float samps to short */
+        for(i=0; i<f->n_nom_modem_samples; i++){
+            mod_out[i] = (short)(tx_float[i]*FDMDV_SCALE);
+        }
+    }else{
+        freedv_comptx(f, tx_fdm, speech_in);
+        for(i=0; i<f->n_nom_modem_samples; i++)
+            mod_out[i] = tx_fdm[i].real;
+    }
 }
 
 /* complex valued output, useful for suitable for single sided freq shifting */
@@ -277,8 +367,11 @@ void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) {
     int    bits_per_codec_frame, bits_per_modem_frame;
     int    data, codeword1, data_flag_index, nspare;
     COMP   tx_fdm[f->n_nat_modem_samples];
+    short  tx_real[f->n_nom_modem_samples];
 
-    assert((f->mode == FREEDV_MODE_1600) || (f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B));
+    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));
 
     if (f->mode == FREEDV_MODE_1600) {
         bits_per_codec_frame = codec2_bits_per_frame(f->codec2);
@@ -439,6 +532,15 @@ void freedv_comptx(struct freedv *f, COMP mod_out[], short speech_in[]) {
         //assert(i == f->n_nom_modem_samples);
         // Caution: assert fails if f->n_nat_modem_samples * 16.0 / 15.0 is not an integer
     }
+    /* 2400 A and B are handled by the real-mode TX */
+    if((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
+        freedv_tx(f,tx_real,speech_in);
+        /* Convert to complex-mode */
+        for(i=0; i<f->n_nom_modem_samples; i++){
+            mod_out[i].real = (float) tx_real[i];
+            mod_out[i].imag = 0;
+        }
+    }
 #endif
 }
 
@@ -502,17 +604,28 @@ int freedv_nin(struct freedv *f) {
 int freedv_rx(struct freedv *f, short speech_out[], short demod_in[]) {
     assert(f != NULL);
     COMP rx_fdm[f->n_max_modem_samples];
+    float rx_float[f->n_max_modem_samples];
     int i;
     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++) {
+            rx_float[i] = ((float)demod_in[i]);
+        }
+        return freedv_floatrx(f,speech_out,rx_float);
+    }else { /* FDM RX happens with complex samps, so do that */
 
-    for(i=0; i<nin; i++) {
-        rx_fdm[i].real = (float)demod_in[i];
-        rx_fdm[i].imag = 0.0;
+        for(i=0; i<nin; i++) {
+            rx_fdm[i].real = (float)demod_in[i];
+            rx_fdm[i].imag = 0.0;
+        }
+        
+        return freedv_comprx(f, speech_out, rx_fdm);
     }
-
-    return freedv_comprx(f, speech_out, rx_fdm);
+    return 0; /* should never get here */
 }
 
 
@@ -525,13 +638,37 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
     int nin = freedv_nin(f);
 
     assert(nin <= f->n_max_modem_samples);
-
-    for(i=0; i<nin; i++) {
-        rx_fdm[i].real = demod_in[i];
-        rx_fdm[i].imag = 0;
+    
+    /* FSK RX happens in real floats, so demod for those goes here */
+    if( (f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B) ){
+        if(f->mode == FREEDV_MODE_2400A){
+            fsk_demod(f->fsk,(uint8_t*)f->tx_bits,demod_in);
+            f->nin = fsk_nin(f->fsk);
+        }else{            
+            fmfsk_demod(f->fmfsk,(uint8_t*)f->tx_bits,demod_in);
+            f->nin = fmfsk_nin(f->fmfsk);
+        }
+        /* TODO: Protocol and varicode bits */
+        if(fvhff_deframe_bits(f->deframer,f->packed_codec_bits,NULL,NULL,(uint8_t*)f->tx_bits)){
+            /* Decode the codec data */
+            codec2_decode(f->codec2,speech_out,f->packed_codec_bits);
+            f->sync = 1;
+        } else {
+            /* Fill with silence */
+            for(i=0;i<f->n_speech_samples;i++){
+                speech_out[i] = 0;
+            }
+            f->sync = 0;
+        }
+        return f->n_speech_samples;
+    }else { 
+        for(i=0; i<nin; i++) {
+            rx_fdm[i].real = demod_in[i];
+            rx_fdm[i].imag = 0;
+        }
+        return freedv_comprx(f, speech_out, rx_fdm);
     }
-
-    return freedv_comprx(f, speech_out, rx_fdm);
+    return 0; //should never get here
 }
 
 // complex input samples version
index 05f860b2e7f7b97b453b1e4c69f2047f4217502f..9ec745c9e9229ab5f91dd3dce515cc2237871a1d 100644 (file)
@@ -40,6 +40,8 @@
 #define FREEDV_MODE_1600        0
 #define FREEDV_MODE_700         1
 #define FREEDV_MODE_700B        2
+#define FREEDV_MODE_2400A       3
+#define FREEDV_MODE_2400B       4
 
 struct freedv;
 
index bd52683dd9d77f4ba48a01535b6967a97702186b..76b4c9d7d74153514ce7ec0618e22cb91036f779 100644 (file)
@@ -38,6 +38,8 @@
 #ifndef __FREEDV__
 
 #include "varicode.h"
+#include "fsk.h"
+#include "fmfsk.h"
 #include "codec2_fdmdv.h"
 #include "codec2_cohpsk.h"
 
@@ -63,6 +65,10 @@ struct freedv {
     struct FDMDV        *fdmdv;
     struct MODEM_STATS   stats;
     struct COHPSK       *cohpsk;
+    struct FSK          *fsk;
+    struct FMFSK        *fmfsk;
+    
+    struct freedv_vhf_deframer * deframer;      //Extracts frames from VHF stream
 
     struct quisk_cfFilter * ptFilter7500to8000;     // Filters to change to/from 7500 and 8000 sps
     struct quisk_cfFilter * ptFilter8000to7500;
index f88189f1bdf1c12873741378b3f16807790e7802..da3e7d68b0d6ef5469e497acd7b7313721f7998d 100644 (file)
@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
     int                        n_max_modem_samples;
 
     if (argc < 4) {
-       printf("usage: %s 1600|700|700B InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
+       printf("usage: %s 1600|700|700B|2400A|2400B InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
        printf("e.g    %s 1600 hts1a_fdmdv.raw hts1a_out.raw txtLogFile\n", argv[0]);
        exit(1);
     }
@@ -80,6 +80,10 @@ int main(int argc, char *argv[]) {
         mode = FREEDV_MODE_700;
     if (!strcmp(argv[1],"700B"))
         mode = FREEDV_MODE_700B;
+    if (!strcmp(argv[1],"2400A"))
+        mode = FREEDV_MODE_2400A;
+    if (!strcmp(argv[1],"2400B"))
+        mode = FREEDV_MODE_2400B;
     assert(mode != -1);
 
     if (strcmp(argv[2], "-")  == 0) fin = stdin;
index cf050bcf9bdd9d557711117cea8060dd0c205cb5..ff4d31e0cd69fe65469c01ba79742fb18d446b80 100644 (file)
@@ -60,7 +60,7 @@ int main(int argc, char *argv[]) {
     int                       n_nom_modem_samples;
 
     if (argc < 4) {
-       printf("usage: %s 1600|700|700B InputRawSpeechFile OutputModemRawFile [--testframes]\n", argv[0]);
+       printf("usage: %s 1600|700|700B|2400A|2400B InputRawSpeechFile OutputModemRawFile [--testframes]\n", argv[0]);
        printf("e.g    %s 1600 hts1a.raw hts1a_fdmdv.raw\n", argv[0]);
        exit(1);
     }
@@ -72,6 +72,10 @@ int main(int argc, char *argv[]) {
         mode = FREEDV_MODE_700;
     if (!strcmp(argv[1],"700B"))
         mode = FREEDV_MODE_700B;
+    if (!strcmp(argv[1],"2400A"))
+        mode = FREEDV_MODE_2400A;
+    if (!strcmp(argv[1],"2400B"))
+        mode = FREEDV_MODE_2400B;
     assert(mode != -1);
 
     if (strcmp(argv[2], "-")  == 0) fin = stdin;
index f5a580346b02eb9833990fcf1548ecc5c672a0c6..d397f526cbbfd52baa7b1cb69a8ce22adae39eca 100644 (file)
@@ -46,8 +46,8 @@
 static const uint8_t A_uw[] =      {0,1,1,0,0,1,1,1,
                                     1,0,1,0,1,1,0,1};
 /* Blank VHF type A frame */
-static const uint8_t A_blank[] =   {0,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3]   */
-                                    0,0,1,0,0,1,1,1, /* Proto[4:11]               */
+static const uint8_t A_blank[] =   {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3]   */
+                                    1,0,1,0,0,1,1,1, /* Proto[4:11]               */
                                     0,0,0,0,0,0,0,0, /* Voice[0:7]                */
                                     0,0,0,0,0,0,0,0, /* Voice[8:15]               */
                                     0,0,0,0,0,0,0,0, /* Voice[16:23]              */
@@ -151,14 +151,15 @@ void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){
     free(def);
 }
 
+int fvhff_synchronized(struct freedv_vhf_deframer * def){
+    return (def->state) == ST_SYNC;
+}
+
 /* See if the UW is where it should be, to within a tolerance, in a bit buffer */
 static int fvhff_match_uw(struct freedv_vhf_deframer * def,int tol){
     uint8_t * bits  = def->bits;
     int frame_type  = def->ftype;
-    int state       = def->state;
     int bitptr      = def->bitptr;
-    int last_uw     = def->last_uw;
-    int miss_cnt    = def->miss_cnt;
     int frame_size  = def->frame_size;
     int iuw,ibit;
     const uint8_t * uw;
@@ -190,10 +191,7 @@ static int fvhff_match_uw(struct freedv_vhf_deframer * def,int tol){
 static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[]){
     uint8_t * bits  = def->bits;
     int frame_type  = def->ftype;
-    int state       = def->state;
     int bitptr      = def->bitptr;
-    int last_uw     = def->last_uw;
-    int miss_cnt    = def->miss_cnt;
     int frame_size  = def->frame_size;
     int iframe,ibit;
     
@@ -268,13 +266,13 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
     int uw_first_tol;   
     int uw_sync_tol;
     int miss_tol;
-    int extracted_frame;
+    int extracted_frame = 0;
     
     /* 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 = 0;    /* The UW bit error tolerance for frames after sync */
-        miss_tol = 3;       /* How many UWs may be missed before going into the de-synced state */
+        uw_first_tol = 2;   /* The UW bit-error tolerance for the first frame */
+        uw_sync_tol = 1;    /* The UW bit error tolerance for frames after sync */
+        miss_tol = 2;       /* How many UWs may be missed before going into the de-synced state */
     }else{
         return 0;
     }
@@ -302,6 +300,7 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
                 if(miss_cnt>miss_tol)
                     state = ST_NOSYNC;
                 /* Extract the bits */
+                extracted_frame = 1;
                 fvhff_extract_frame(def,codec2_out,proto_out,vc_out);
             }
         /* Not yet sunk */
@@ -321,31 +320,3 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin
     def->miss_cnt = miss_cnt;
     return extracted_frame;
 }
-
-/* Ugly test function, to be removed */
-int main(){
-    uint8_t bitbuf[96];
-    uint8_t c2buf[7];
-    uint8_t protobuf[3];
-    FILE * out = fopen("frame_test_out","w");
-    struct freedv_vhf_deframer * def = fvhff_create_deframer(FREEDV_VHF_FRAME_A);
-    
-    srand(5);
-    def->bitptr = 47;
-    for(int i=0;i<30;i++){
-        snprintf(c2buf,7,"%d TEST",i);
-        snprintf(protobuf,3,"%d",i);
-        for(int j=0;j<96;j++)
-            bitbuf[j] = rand()&0x1;
-        
-        fvhff_frame_bits(FREEDV_VHF_FRAME_A,bitbuf,c2buf,NULL,NULL);
-        fwrite(bitbuf,sizeof(uint8_t),96,out);
-        memset(c2buf,0,7);
-        
-        if(fvhff_deframe_bits(def,c2buf,NULL,NULL,bitbuf)){
-            printf("deframed codec2 %s protocol %s\n",c2buf,protobuf);
-        }
-    }
-    fclose(out);
-    fvhff_destroy_deframer(def);
-}
index 86e72ffadafa6f7bea3cd333690eec3cfffa3e9b..e285ebd1d2da007a59fd4526da777b7a6d68619f 100644 (file)
@@ -133,8 +133,9 @@ struct FSK * fsk_create_hbr(int Fs, int Rs,int P,int M, int tx_f1, int tx_fs)
     int Ndft = 0;
     
     /* Number of symbols in a processing frame */
-    int nsyms = 192;
-    
+    //int nsyms = 24;
+    //int nsyms = 192;
+    int nsyms = 48;
     /* Check configuration validity */
     assert(Fs > 0 );
     assert(Rs > 0 );
@@ -178,7 +179,7 @@ struct FSK * fsk_create_hbr(int Fs, int Rs,int P,int M, int tx_f1, int tx_fs)
     
     fsk->est_max = (Fs/2)-Rs;
     
-    fsk->est_space = (Rs/2)-(Rs/10);
+    fsk->est_space = Rs;
     
     /* Set up rx state */
     fsk->phi1_c = comp_exp_j(0);
@@ -463,7 +464,7 @@ void fsk_demod_freq_est(struct FSK *fsk, float fsk_in[],float *freqs,int M){
        /* My favorite sort of sort*/
        i = 1;
        while(i<M){
-               if(freqi[i] > freqi[i-1]) i++;
+               if(freqi[i] >= freqi[i-1]) i++;
                else{
                        j = freqi[i];
                        freqi[i] = freqi[i-1];