}
fmfsk->oldsamps = oldsamps;
+ fmfsk->stats = NULL;
return 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
*
/* 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);
}
#define __C2FMFSK_H
#include <stdint.h>
#include "comp.h"
+#include "modem_stats.h"
/*
* fm-me-2fsk state
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;
};
/*
*/
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
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;
/* 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) {
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
int nin = freedv_nin(f);
int n_ascii;
char ascii_out;
- float Rs;
assert(nin <= f->n_max_modem_samples);
}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)){
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
\*---------------------------------------------------------------------------*/
// 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;}
{
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);
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);
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
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
#include <stdio.h>
#include "freedv_api.h"
+#include "modem_stats.h"
struct my_callback_state {
FILE *ftxt;
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;
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]);
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