began work on api extension to support protocol bits
authorbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 21 Feb 2016 07:53:40 +0000 (07:53 +0000)
committerbaobrien <baobrien@01035d8c-6547-0410-b346-abe4f91aad63>
Sun, 21 Feb 2016 07:53:40 +0000 (07:53 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2707 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/fmfsk.c
codec2-dev/src/fmfsk.h
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

index 93f377c0b41c0b850816646818b5fa772736cac4..17e64216bc97ce32542217cee151a9a1e375c128 100644 (file)
@@ -78,6 +78,7 @@ struct FMFSK * fmfsk_create(int Fs,int Rb){
     }
     
     fmfsk->oldsamps = oldsamps;
+    fmfsk->stats = NULL;
     
     return fmfsk;
 }
@@ -98,6 +99,10 @@ uint32_t fmfsk_nin(struct FMFSK *fmfsk){
     return (uint32_t)fmfsk->nin;
 }
 
+void fmfsk_setup_modem_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats){
+    fmfsk->stats = stats;
+}
+
 /*
  * Modulates nbit bits into N samples to be sent through an FM radio
  * 
@@ -272,6 +277,20 @@ void fmfsk_demod(struct FMFSK *fmfsk, uint8_t rx_bits[],float fmfsk_in[]){
     /* Save last sample of int stream for next demod round */
     fmfsk->lodd = lastv;
     
+    /* Save demod statistics */
+    if(fmfsk->stats != NULL){
+        fmfsk->stats->Nc = 0;
+        fmfsk->stats->nr = 0;
+        
+        /* Clock offset and RX timing are all we know here */
+        fmfsk->stats->clock_offset = fmfsk->ppm;
+        fmfsk->stats->rx_timing = (float)rx_timing;
+        
+        /* Zero out all of the other things */
+        fmfsk->stats->foff = 0;
+        fmfsk->stats->snr_est = 0;
+    }
+    
     modem_probe_samp_f("t_norm_rx_timing",&norm_rx_timing,1);
     modem_probe_samp_f("t_rx_filt",rx_filt,(nsym+1)*Ts);
 }
index 1573f248bbc1b52d1dbf1731d5869f7386f26333..abf0c92c4dd67b81587eee33c86b917480dd2003 100644 (file)
@@ -30,6 +30,7 @@
 #define __C2FMFSK_H
 #include <stdint.h>
 #include "comp.h"
+#include "modem_stats.h"
 
 /* 
  * fm-me-2fsk state
@@ -54,7 +55,8 @@ struct FMFSK{
     float norm_rx_timing; /* RX Timing, used to calculate clock offset */
     int ppm;                   /* Clock offset in parts-per-million */
     
-    
+    /* Modem stat structure */
+    struct MODEM_STATS * stats;
 };
 
 /*
@@ -71,6 +73,11 @@ struct FMFSK * fmfsk_create(int Fs,int Rb);
  */
 void fmfsk_destroy(struct FMFSK *fmfsk);
 
+/*
+ * Set a MODEM_STATS struct in which to deposit demod statistics
+ */
+void fmfsk_setup_modem_stats(struct FMFSK *fmfsk,struct MODEM_STATS *stats);
+
 /*
  * Returns the number of samples that must be fed to fmfsk_demod the next
  * cycle
index 0c20ba32f2edbbd6e561d1f6db05593f6ce6dc73..0ebd06bb9a4c3e2fac961ca8d5b178f5fe5a7819 100644 (file)
@@ -88,6 +88,7 @@ struct freedv *freedv_open(int mode) {
     f->test_frames = f->smooth_symbols = 0;
     f->freedv_put_error_pattern = NULL;
     f->error_pattern_callback_state = NULL;
+    f->n_protocol_bits = 0;
 
     if (mode == FREEDV_MODE_1600) {
         f->snr_squelch_thresh = 2.0;
@@ -143,6 +144,8 @@ struct freedv *freedv_open(int mode) {
       
         /* Set up the C2 mode */
         codec2_mode = CODEC2_MODE_1300;
+        /* Set the number of protocol bits */
+        f->n_protocol_bits = 20;
     }
     
     if (mode == FREEDV_MODE_2400A) {
@@ -195,6 +198,9 @@ struct freedv *freedv_open(int mode) {
         f->modem_sample_rate = 48000;
         /* Malloc something to appease freedv_init and freedv_destroy */
         f->codec_bits = malloc(1);
+        
+        /* Set up the stats */
+        fmfsk_setup_modem_stats(f->fmfsk,&(f->stats));
     }
     
 #endif
@@ -677,7 +683,6 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
     int nin = freedv_nin(f);    
     int n_ascii;
     char ascii_out;
-    float Rs;
     
     assert(nin <= f->n_max_modem_samples);
     
@@ -689,7 +694,6 @@ int freedv_floatrx(struct freedv *f, short speech_out[], float demod_in[]) {
         }else{            
             fmfsk_demod(f->fmfsk,(uint8_t*)f->tx_bits,demod_in);
             f->nin = fmfsk_nin(f->fmfsk);
-            f->stats.clock_offset = f->fsk->ppm;
         }
         /* TODO: Protocol bits */
         if(fvhff_deframe_bits(f->deframer,f->packed_codec_bits,NULL,vc_bits,(uint8_t*)f->tx_bits)){
@@ -1063,6 +1067,28 @@ void freedv_set_callback_txt(struct freedv *f, freedv_callback_rx rx, freedv_cal
     f->callback_state = state;
 }
 
+/*---------------------------------------------------------------------------*\
+
+  FUNCTION....: freedv_set_callback_protocol
+  AUTHOR......: Brady OBrien
+  DATE CREATED: 21 February 2016
+
+  Set the callback functions and callback pointer that will be used for the
+  protocol data channel. freedv_callback_protorx will be called when a frame
+  containing protocol data arrives. freedv_callback_prototx will be called
+  when a frame containing protocol information is being generated. Protocol
+  information is intended to be used to develop protocols and fancy features
+  atop VHF freedv, much like those present in DMR.
+   Protocol bits are to be passed in an msb-first char array
+   The number of protocol bits are findable with freedv_get_protocol_bits
+\*---------------------------------------------------------------------------*/
+
+void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state){
+    f->freedv_put_next_proto = rx;
+    f->freedv_get_next_proto = tx;
+    f->proto_callback_state = callback_state;
+}
+
 /*---------------------------------------------------------------------------*\
 
   FUNCTION....: freedv_get_modem_stats
@@ -1126,6 +1152,7 @@ void freedv_set_callback_error_pattern    (struct freedv *f, freedv_calback_erro
 \*---------------------------------------------------------------------------*/
 
 // Get integers
+int freedv_get_protocol_bits              (struct freedv *f) {return  f->n_protocol_bits;}
 int freedv_get_mode                       (struct freedv *f) {return f->mode;}
 int freedv_get_test_frames                (struct freedv *f) {return f->test_frames;}
 int freedv_get_n_speech_samples           (struct freedv *f) {return f->n_speech_samples;}
@@ -1144,6 +1171,9 @@ void freedv_get_modem_extended_stats(struct freedv *f, struct MODEM_STATS *stats
 {
     if (f->mode == FREEDV_MODE_1600)
         fdmdv_get_demod_stats(f->fdmdv, stats);
+    if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){
+        memcpy(stats,&(f->stats),sizeof(struct MODEM_STATS));
+    }
 #ifndef CORTEX_M4
     if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B))
         cohpsk_get_demod_stats(f->cohpsk, stats);
index 9ec745c9e9229ab5f91dd3dce515cc2237871a1d..80521a0879ba95a58eee94f364a3b22cf9304826 100644 (file)
 
 struct freedv;
 
+/* Called when text message char is decoded */
 typedef void (*freedv_callback_rx)(void *, char);
+/* Called when new text message char is needed */
 typedef char (*freedv_callback_tx)(void *);
 typedef void (*freedv_calback_error_pattern)
        (void *error_pattern_callback_state, short error_pattern[], int sz_error_pattern);
 
+/* Protocol bits are packed MSB-first */
+/* Called when a frame containing protocol data is decoded */
+typedef void (*freedv_callback_protorx)(void *, char *);
+/* Called when a frame containing protocol data is to be sent */
+typedef char * (*freedv_callback_prototx)(void *);
+
 // FreeDV API functions:
 // open, close
 struct freedv *freedv_open(int mode);
-void freedv_close(struct freedv *freedv);
+void freedv_close   (struct freedv *freedv);
 // Transmit
-void freedv_tx(struct freedv *freedv, short mod_out[], short speech_in[]);
-void freedv_comptx(struct freedv *freedv, COMP mod_out[], short speech_in[]);
+void freedv_tx      (struct freedv *freedv, short mod_out[], short speech_in[]);
+void freedv_comptx  (struct freedv *freedv, COMP  mod_out[], short speech_in[]);
 // Receive
-int freedv_nin(struct freedv *freedv);
-int freedv_rx(struct freedv *freedv, short speech_out[], short demod_in[]);
-int freedv_floatrx(struct freedv *freedv, short speech_out[], float demod_in[]);
-int freedv_comprx(struct freedv *freedv, short speech_out[], COMP demod_in[]);
+int freedv_nin      (struct freedv *freedv);
+int freedv_rx       (struct freedv *freedv, short speech_out[], short demod_in[]);
+int freedv_floatrx  (struct freedv *freedv, short speech_out[], float demod_in[]);
+int freedv_comprx   (struct freedv *freedv, short speech_out[], COMP  demod_in[]);
 // Set parameters
-void freedv_set_callback_txt(struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
-void freedv_set_test_frames                    (struct freedv *freedv, int test_frames);
-void freedv_set_smooth_symbols         (struct freedv *freedv, int smooth_symbols);
-void freedv_set_squelch_en                     (struct freedv *freedv, int squelch_en);
-void freedv_set_snr_squelch_thresh     (struct freedv *freedv, float snr_squelch_thresh);
+void freedv_set_callback_txt            (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);
+void freedv_set_callback_protocol       (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);
+void freedv_set_test_frames                        (struct freedv *freedv, int test_frames);
+void freedv_set_smooth_symbols             (struct freedv *freedv, int smooth_symbols);
+void freedv_set_squelch_en                         (struct freedv *freedv, int squelch_en);
+void freedv_set_snr_squelch_thresh         (struct freedv *freedv, float snr_squelch_thresh);
 void freedv_set_clip                   (struct freedv *freedv, int val);
-void freedv_set_total_bit_errors       (struct freedv *freedv, int val);
+void freedv_set_total_bit_errors       (struct freedv *freedv, int val);
 void freedv_set_total_bits              (struct freedv *freedv, int val);
 void freedv_set_callback_error_pattern  (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);
 void freedv_set_varicode_code_num       (struct freedv *freedv, int val);
 
 // Get parameters
 int freedv_get_version(void);
-int freedv_get_mode                     (struct freedv *freedv);
-void freedv_get_modem_stats(struct freedv *freedv, int *sync, float *snr_est);
+int freedv_get_mode                 (struct freedv *freedv);
+void freedv_get_modem_stats         (struct freedv *freedv, int *sync, float *snr_est);
 void freedv_get_modem_extended_stats(struct freedv *freedv, struct MODEM_STATS *stats);
 int freedv_get_test_frames                     (struct freedv *freedv);
 int freedv_get_n_speech_samples                (struct freedv *freedv);
@@ -86,9 +95,10 @@ int freedv_get_n_max_modem_samples   (struct freedv *freedv);
 int freedv_get_n_nom_modem_samples     (struct freedv *freedv);
 int freedv_get_total_bits                      (struct freedv *freedv);
 int freedv_get_total_bit_errors                (struct freedv *freedv);
-int freedv_get_sync                    (struct freedv *freedv);
+int freedv_get_sync                        (struct freedv *freedv);
 struct CODEC2 *freedv_get_codec2       (struct freedv *freedv);
-int freedv_get_sz_error_pattern         (struct freedv *freedv);
+int freedv_get_sz_error_pattern     (struct freedv *freedv);
+int freedv_get_protocol_bits        (struct freedv *freedv);
 #endif
 
 #ifdef __cplusplus
index 76b4c9d7d74153514ce7ec0618e22cb91036f779..0b5775297efbce747bd33dd573235ec5cd2b298f 100644 (file)
@@ -122,9 +122,14 @@ struct freedv {
 
     char (*freedv_get_next_tx_char)(void *callback_state);
     void (*freedv_put_next_rx_char)(void *callback_state, char c);
-
     void                *callback_state;
-
+    
+    /* user defined functions to produce and consume protocol bits */
+    /* Protocol bits are packed MSB-first */
+    void (*freedv_put_next_proto)(void *callback_state, char *proto_bits_packed);
+    void (*freedv_get_next_proto)(void *callback_state);
+    void *proto_callback_state;
+    int n_protocol_bits;
 };
 
 // FIR filter suitable for changing rates 7500 to/from 8000
index 3e4b514e7b72d8d2ece89c04a48a078dac28237c..3380a50de3dc8f8308d247eddfaa3729528e06f5 100644 (file)
@@ -40,6 +40,7 @@
 #include <stdio.h>
 
 #include "freedv_api.h"
+#include "modem_stats.h"
 
 struct my_callback_state {
     FILE *ftxt;
@@ -59,6 +60,7 @@ int main(int argc, char *argv[]) {
     struct freedv             *freedv;
     int                        nin, nout, frame = 0;
     struct my_callback_state   my_cb_state;
+    struct MODEM_STATS         stats;
     int                        mode;
     int                        sync;
     int                        total_bits;
@@ -66,6 +68,7 @@ int main(int argc, char *argv[]) {
     float                      snr_est;
     int                        n_speech_samples;
     int                        n_max_modem_samples;
+    float                      clock_offset;
 
     if (argc < 4) {
        printf("usage: %s 1600|700|700B|2400A|2400B InputModemSpeechFile OutputSpeechRawFile [--test_frames]\n", argv[0]);
@@ -135,13 +138,15 @@ int main(int argc, char *argv[]) {
 
         fwrite(speech_out, sizeof(short), nout, fout);
         freedv_get_modem_stats(freedv, &sync, &snr_est);
+        freedv_get_modem_extended_stats(freedv,&stats);
         total_bit_errors = freedv_get_total_bit_errors(freedv);
+        clock_offset = stats.clock_offset;
 
         /* log some side info to the txt file */
 
         if (ftxt != NULL) {
-            fprintf(ftxt, "frame: %d  demod sync: %d  nin:%d demod snr: %3.2f dB  bit errors: %d\n",
-                    frame, sync, nin, snr_est, total_bit_errors);
+            fprintf(ftxt, "frame: %d  demod sync: %d  nin:%d demod snr: %3.2f dB  bit errors: %d clock_offset: %f\n",
+                    frame, sync, nin, snr_est, total_bit_errors, clock_offset);
         }
 
        /* if this is in a pipeline, we probably don't want the usual