From: baobrien Date: Sun, 21 Feb 2016 07:53:40 +0000 (+0000) Subject: began work on api extension to support protocol bits X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=f9c5d727522219c54599f864621a374e2dc81ad7;p=freetel-svn-tracking.git began work on api extension to support protocol bits git-svn-id: https://svn.code.sf.net/p/freetel/code@2707 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/src/fmfsk.c b/codec2-dev/src/fmfsk.c index 93f377c0..17e64216 100644 --- a/codec2-dev/src/fmfsk.c +++ b/codec2-dev/src/fmfsk.c @@ -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); } diff --git a/codec2-dev/src/fmfsk.h b/codec2-dev/src/fmfsk.h index 1573f248..abf0c92c 100644 --- a/codec2-dev/src/fmfsk.h +++ b/codec2-dev/src/fmfsk.h @@ -30,6 +30,7 @@ #define __C2FMFSK_H #include #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 diff --git a/codec2-dev/src/freedv_api.c b/codec2-dev/src/freedv_api.c index 0c20ba32..0ebd06bb 100644 --- a/codec2-dev/src/freedv_api.c +++ b/codec2-dev/src/freedv_api.c @@ -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); diff --git a/codec2-dev/src/freedv_api.h b/codec2-dev/src/freedv_api.h index 9ec745c9..80521a08 100644 --- a/codec2-dev/src/freedv_api.h +++ b/codec2-dev/src/freedv_api.h @@ -45,39 +45,48 @@ 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 diff --git a/codec2-dev/src/freedv_api_internal.h b/codec2-dev/src/freedv_api_internal.h index 76b4c9d7..0b577529 100644 --- a/codec2-dev/src/freedv_api_internal.h +++ b/codec2-dev/src/freedv_api_internal.h @@ -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 diff --git a/codec2-dev/src/freedv_rx.c b/codec2-dev/src/freedv_rx.c index 3e4b514e..3380a50d 100644 --- a/codec2-dev/src/freedv_rx.c +++ b/codec2-dev/src/freedv_rx.c @@ -40,6 +40,7 @@ #include #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