From: baobrien Date: Sat, 12 Mar 2016 05:29:44 +0000 (+0000) Subject: Jeroen's data channel patch applied X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=841c048e4fd95d3f215dc4588c28a119d485a529;p=freetel-svn-tracking.git Jeroen's data channel patch applied git-svn-id: https://svn.code.sf.net/p/freetel/code@2729 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/src/CMakeLists.txt b/codec2-dev/src/CMakeLists.txt index 1f605c45..acac63a8 100644 --- a/codec2-dev/src/CMakeLists.txt +++ b/codec2-dev/src/CMakeLists.txt @@ -157,12 +157,13 @@ set(CODEC2_SRCS codebookmel.c codebooklspmelvq.c codebookge.c - golay23.c - freedv_api.c - freedv_vhf_framing.c - varicode.c - modem_stats.c -) + golay23.c + freedv_api.c + freedv_vhf_framing.c + freedv_data_channel.c + varicode.c + modem_stats.c +) set(CODEC2_PUBLIC_HEADERS golay23.h diff --git a/codec2-dev/src/codec2.c b/codec2-dev/src/codec2.c index eed45a95..485d31b1 100644 --- a/codec2-dev/src/codec2.c +++ b/codec2-dev/src/codec2.c @@ -1750,6 +1750,80 @@ void codec2_decode_700b(struct CODEC2 *c2, short speech[], const unsigned char * } #endif +/*---------------------------------------------------------------------------*\ + + FUNCTION....: codec2_get_energy() + AUTHOR......: Jeroen Vreeken + DATE CREATED: 08/03/2016 + + Extract energy value from an encoded frame. + +\*---------------------------------------------------------------------------*/ + +float codec2_get_energy(struct CODEC2 *c2, const unsigned char *bits) +{ + assert(c2 != NULL); + assert( + (c2->mode == CODEC2_MODE_3200) || + (c2->mode == CODEC2_MODE_2400) || + (c2->mode == CODEC2_MODE_1600) || + (c2->mode == CODEC2_MODE_1400) || + (c2->mode == CODEC2_MODE_1300) || + (c2->mode == CODEC2_MODE_1200) || + (c2->mode == CODEC2_MODE_700) || + (c2->mode == CODEC2_MODE_700B) + ); + MODEL model; + float xq_dec[2] = {}; + int e_index, WoE_index; + float e; + unsigned int nbit; + + if (c2->mode == CODEC2_MODE_3200) { + nbit = 1 + 1 + WO_BITS; + e_index = unpack(bits, &nbit, E_BITS); + e = decode_energy(e_index, E_BITS); + } + if (c2->mode == CODEC2_MODE_2400) { + nbit = 1 + 1; + WoE_index = unpack(bits, &nbit, WO_E_BITS); + decode_WoE(&model, &e, xq_dec, WoE_index); + } + if (c2->mode == CODEC2_MODE_1600) { + nbit = 1 + 1 + WO_BITS; + e_index = unpack(bits, &nbit, E_BITS); + e = decode_energy(e_index, E_BITS); + } + if (c2->mode == CODEC2_MODE_1400) { + nbit = 1 + 1; + WoE_index = unpack(bits, &nbit, WO_E_BITS); + decode_WoE(&model, &e, xq_dec, WoE_index); + } + if (c2->mode == CODEC2_MODE_1300) { + nbit = 1 + 1 + 1 + 1 + WO_BITS; + e_index = unpack_natural_or_gray(bits, &nbit, E_BITS, c2->gray); + e = decode_energy(e_index, E_BITS); + } + if (c2->mode == CODEC2_MODE_1200) { + nbit = 1 + 1; + WoE_index = unpack(bits, &nbit, WO_E_BITS); + decode_WoE(&model, &e, xq_dec, WoE_index); + } + if (c2->mode == CODEC2_MODE_700) { + nbit = 1 + 5; + e_index = unpack_natural_or_gray(bits, &nbit, 3, c2->gray); + e = decode_energy(e_index, 3); + } + if (c2->mode == CODEC2_MODE_700B) { + nbit = 1 + 5; + e_index = unpack_natural_or_gray(bits, &nbit, 3, c2->gray); + e = decode_energy(e_index, 3); + } + + return e; +} + + /*---------------------------------------------------------------------------*\ FUNCTION....: synthesise_one_frame() diff --git a/codec2-dev/src/codec2.h b/codec2-dev/src/codec2.h index 8b1cb5b3..a6c608fc 100644 --- a/codec2-dev/src/codec2.h +++ b/codec2-dev/src/codec2.h @@ -54,12 +54,13 @@ int codec2_bits_per_frame(struct CODEC2 *codec2_state); void codec2_set_lpc_post_filter(struct CODEC2 *codec2_state, int enable, int bass_boost, float beta, float gamma); int codec2_get_spare_bit_index(struct CODEC2 *codec2_state); -int codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]); -void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray); -void codec2_set_softdec(struct CODEC2 *c2, float *softdec); - -#endif - +int codec2_rebuild_spare_bit(struct CODEC2 *codec2_state, int unpacked_bits[]); +void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray); +void codec2_set_softdec(struct CODEC2 *c2, float *softdec); +float codec2_get_energy(struct CODEC2 *codec2_state, const unsigned char *bits); + +#endif + #ifdef __cplusplus } #endif diff --git a/codec2-dev/src/fmfsk.h b/codec2-dev/src/fmfsk.h index abf0c92c..cd17505f 100644 --- a/codec2-dev/src/fmfsk.h +++ b/codec2-dev/src/fmfsk.h @@ -29,12 +29,14 @@ #ifndef __C2FMFSK_H #define __C2FMFSK_H #include -#include "comp.h" -#include "modem_stats.h" - -/* - * fm-me-2fsk state - */ +#include "comp.h" +#include "modem_stats.h" + +#define FMFSK_SCALE 32767 + +/* + * fm-me-2fsk state + */ struct FMFSK{ /* Static fmfsk parameters */ int Rb; /* Manchester-encoded bitrate */ diff --git a/codec2-dev/src/freedv_api.c b/codec2-dev/src/freedv_api.c index 70c5be2f..ce6817dc 100644 --- a/codec2-dev/src/freedv_api.c +++ b/codec2-dev/src/freedv_api.c @@ -344,7 +344,7 @@ void freedv_close(struct freedv *freedv) { /* real-valued short sample output, useful for going straight to DAC */ /* TX routines for 2400 FSK modes, after codec2 encoding */ -static void freedv_tx_fsk(struct freedv *f, short mod_out[]) { +static void freedv_tx_fsk_voice(struct freedv *f, short mod_out[]) { int i; float *tx_float; /* To hold on to modulated samps from fsk/fmfsk */ uint8_t vc_bits[2]; /* Varicode bits for 2400 framing */ @@ -382,15 +382,44 @@ static void freedv_tx_fsk(struct freedv *f, short mod_out[]) { /* do 4fsk mod */ if(f->mode == FREEDV_MODE_2400A){ fsk_mod(f->fsk,tx_float,(uint8_t*)(f->tx_bits)); - + /* Convert float samps to short */ + for(i=0; in_nom_modem_samples; i++){ + mod_out[i] = (short)(tx_float[i]*FSK_SCALE); + } /* 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; in_nom_modem_samples; i++){ + mod_out[i] = (short)(tx_float[i]*FMFSK_SCALE); + } } +} + +/* TX routines for 2400 FSK modes, data channel */ +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 */ - /* Convert float samps to short */ - for(i=0; in_nom_modem_samples; i++){ - mod_out[i] = (short)(tx_float[i]*FDMDV_SCALE); + fvhff_frame_data_bits(f->deframer, FREEDV_VHF_FRAME_A,(uint8_t*)(f->tx_bits)); + + /* 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)); + /* Convert float samps to short */ + for(i=0; in_nom_modem_samples; i++){ + mod_out[i] = (short)(tx_float[i]*FSK_SCALE); + } + /* 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; in_nom_modem_samples; i++){ + mod_out[i] = (short)(tx_float[i]*FMFSK_SCALE); + } } } @@ -409,7 +438,7 @@ void freedv_tx(struct freedv *f, short mod_out[], short speech_in[]) { if((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){ codec2_encode(f->codec2, f->packed_codec_bits, speech_in); - freedv_tx_fsk(f, mod_out); + freedv_tx_fsk_voice(f, mod_out); }else{ freedv_comptx(f, tx_fdm, speech_in); for(i=0; in_nom_modem_samples; i++) @@ -653,7 +682,7 @@ void freedv_codectx(struct freedv *f, short mod_out[], unsigned char *packed_cod break; case FREEDV_MODE_2400A: case FREEDV_MODE_2400B: - freedv_tx_fsk(f, mod_out); + freedv_tx_fsk_voice(f, mod_out); return; /* output is already real */ } /* convert complex to real */ @@ -661,6 +690,24 @@ void freedv_codectx(struct freedv *f, short mod_out[], unsigned char *packed_cod mod_out[i] = tx_fdm[i].real; } +void freedv_datatx (struct freedv *f, short mod_out[]){ + assert(f != NULL); + + if (f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_2400B) { + freedv_tx_fsk_data(f, mod_out); + } +} + +int freedv_data_ntxframes (struct freedv *f){ + assert(f != NULL); + + if (f->mode == FREEDV_MODE_2400A || f->mode == FREEDV_MODE_2400B) { + if (f->deframer->fdc) + return freedv_data_get_n_tx_frames(f->deframer->fdc); + } + return 0; +} + int freedv_nin(struct freedv *f) { if ((f->mode == FREEDV_MODE_700) || (f->mode == FREEDV_MODE_700B)) // For mode 700, the input rate is 8000 sps, but the modem rate is 7500 sps @@ -1262,6 +1309,55 @@ void freedv_set_callback_protocol(struct freedv *f, freedv_callback_protorx rx, f->proto_callback_state = callback_state; } +/*---------------------------------------------------------------------------*\ + + FUNCTION....: freedv_set_callback_datarx / freedv_set_callback_datatx + AUTHOR......: Jeroen Vreeken + DATE CREATED: 04 March 2016 + + Set the callback functions and callback pointer that will be used for the + data channel. freedv_callback_datarx will be called when a packet has been + successfully received. freedv_callback_data_tx will be called when + transmission of a new packet can begin. + If the returned size of the datatx callback is zero the data frame is still + generated, but will contain only a header update. +\*---------------------------------------------------------------------------*/ +void freedv_set_callback_data(struct freedv *f, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state) { + if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){ + if (!f->deframer->fdc) + f->deframer->fdc = freedv_data_channel_create(); + if (!f->deframer->fdc) + return; + + freedv_data_set_cb_rx(f->deframer->fdc, datarx, callback_state); + freedv_data_set_cb_tx(f->deframer->fdc, datatx, callback_state); + } +} + +/*---------------------------------------------------------------------------*\ + + FUNCTION....: freedv_set_data_header + AUTHOR......: Jeroen Vreeken + DATE CREATED: 04 March 2016 + + Set the data header for the data channel. + Header compression will be used whenever packets from this header are sent. + The header will also be used for fill packets when a data frame is requested + without a packet available. +\*---------------------------------------------------------------------------*/ +void freedv_set_data_header(struct freedv *f, unsigned char *header) +{ + if ((f->mode == FREEDV_MODE_2400A) || (f->mode == FREEDV_MODE_2400B)){ + if (!f->deframer->fdc) + f->deframer->fdc = freedv_data_channel_create(); + if (!f->deframer->fdc) + return; + + freedv_data_set_header(f->deframer->fdc, header); + } +} + + /*---------------------------------------------------------------------------*\ FUNCTION....: freedv_get_modem_stats diff --git a/codec2-dev/src/freedv_api.h b/codec2-dev/src/freedv_api.h index a9805781..c95de56c 100644 --- a/codec2-dev/src/freedv_api.h +++ b/codec2-dev/src/freedv_api.h @@ -55,38 +55,49 @@ typedef void (*freedv_calback_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); +/* Called when a frame containing protocol data is to be sent */ +typedef char * (*freedv_callback_prototx)(void *); + +/* Data packet callbacks */ +/* Called when a packet has been received */ +typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size); +/* Called when a new packet can be send */ +typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size); + + +// FreeDV API functions: +// open, close +struct freedv *freedv_open(int mode); 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_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits); -// Receive -int freedv_nin (struct freedv *freedv); -int freedv_rx (struct freedv *freedv, short speech_out[], short demod_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[]); +void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits); +void freedv_datatx (struct freedv *f, short mod_out[]); +int freedv_data_ntxframes (struct freedv *freedv); +// 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_codecrx (struct freedv *freedv, unsigned char *packed_codec_bits, short 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_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); +// Set parameters +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_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, 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_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); +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); +void freedv_set_data_header (struct freedv *freedv, unsigned char *header); + +// 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); void freedv_get_modem_extended_stats(struct freedv *freedv, struct MODEM_STATS *stats); diff --git a/codec2-dev/src/freedv_data_channel.c b/codec2-dev/src/freedv_data_channel.c new file mode 100644 index 00000000..723412e4 --- /dev/null +++ b/codec2-dev/src/freedv_data_channel.c @@ -0,0 +1,253 @@ +/*---------------------------------------------------------------------------*\ + + FILE........: freedv_data_channel.c + AUTHOR......: Jeroen Vreeken + DATE CREATED: 03 March 2016 + + Data channel for ethernet like packets in freedv VHF frames. + Currently designed for- + * 2 control bits per frame + * 4 byte counter bits per frame + * 64 bits of data per frame +\*---------------------------------------------------------------------------*/ + +/* + Copyright (C) 2016 Jeroen Vreeken + + All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1, as + published by the Free Software Foundation. This program is + distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + +#include "freedv_data_channel.h" + +#include +#include + +static unsigned char fdc_header_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +/* CCIT CRC table (0x1201 polynomal) */ +static unsigned short fdc_crc_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +static unsigned short fdc_crc(unsigned char *buffer, size_t len) +{ + unsigned short crc = 0xffff; + size_t i; + + for (i = 0; i < len; i++, buffer++) { + crc = (crc >> 8) ^ fdc_crc_table[(crc ^ *buffer) & 0xff]; + } + + return crc ^ 0xffff; +} + +struct freedv_data_channel *freedv_data_channel_create(void) +{ + struct freedv_data_channel *fdc; + + fdc = malloc(sizeof(struct freedv_data_channel)); + if (!fdc) + return NULL; + + fdc->cb_rx = NULL; + + freedv_data_set_header(fdc, fdc_header_bcast); + + memcpy(fdc->rx_header, fdc->tx_header, 8); + + return fdc; +} + +void freedv_data_channel_destroy(struct freedv_data_channel *fdc) +{ + free(fdc); +} + + +void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state) +{ + fdc->cb_rx = cb; + fdc->cb_rx_state = state; +} + +void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state) +{ + fdc->cb_tx = cb; + fdc->cb_tx_state = state; +} + +void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int from_bit, int bcast_bit, int end_bits) +{ + /* New packet? */ + if (fdc->packet_rx_cnt == 0) { + /* Does the packet have a compressed from field? */ + if (from_bit) { + /* Compressed from: take the previously received header */ + memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc->rx_header, 6); + fdc->packet_rx_cnt += 6; + } + if (bcast_bit) { + /* Compressed to: fill in broadcast address */ + memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc_header_bcast, sizeof(fdc_header_bcast)); + fdc->packet_rx_cnt += 6; + } + } + + int copy_bits; + if (end_bits) { + copy_bits = end_bits; + } else { + copy_bits = 8; + } + if (fdc->packet_rx_cnt + copy_bits >= FREEDV_DATA_CHANNEL_PACKET_MAX) { + /* Something went wrong... this can not be a real packet */ + fdc->packet_rx_cnt = 0; + return; + } + + memcpy(fdc->packet_rx + fdc->packet_rx_cnt, data, copy_bits); + fdc->packet_rx_cnt += copy_bits; + + if (end_bits != 0 && fdc->packet_rx_cnt >= 2) { + unsigned short calc_crc = fdc_crc(fdc->packet_rx, fdc->packet_rx_cnt - 2); + unsigned short rx_crc; + rx_crc = fdc->packet_rx[fdc->packet_rx_cnt - 1] << 8; + rx_crc |= fdc->packet_rx[fdc->packet_rx_cnt - 2]; + + if (rx_crc == calc_crc) { + if (fdc->packet_rx_cnt == 8) { + /* It is a single header field, remember it for later */ + memcpy(fdc->rx_header, fdc->packet_rx, 6); + } + + /* callback */ + if (fdc->cb_rx) { + unsigned char tmp[6]; + memcpy(tmp, fdc->packet_rx, 6); + memcpy(fdc->packet_rx, fdc->packet_rx + 6, 6); + memcpy(fdc->packet_rx + 6, tmp, 6); + + size_t size = fdc->packet_rx_cnt - 2; + if (size < 12) + size = 12; + fdc->cb_rx(fdc->cb_rx_state, fdc->packet_rx, size); + } + } + fdc->packet_rx_cnt = 0; + } +} + +void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int *from_bit, int *bcast_bit, int *end_bits) +{ + *from_bit = 0; + *bcast_bit = 0; + + if (!fdc->packet_tx_size) { + fdc->packet_tx_cnt = 0; + + if (fdc->cb_tx) { + fdc->packet_tx_size = FREEDV_DATA_CHANNEL_PACKET_MAX; + fdc->cb_tx(fdc->cb_tx_state, fdc->packet_tx, &fdc->packet_tx_size); + } + if (!fdc->packet_tx_size) { + /* Nothing to send, insert a header frame */ + memcpy(fdc->packet_tx, fdc->tx_header, 8); + fdc->packet_tx_size = 8; + } else { + /* new packet */ + unsigned short crc; + unsigned char tmp[6]; + + memcpy(tmp, fdc->packet_tx, 6); + memcpy(fdc->packet_tx, fdc->packet_tx + 6, 6); + memcpy(fdc->packet_tx + 6, tmp, 6); + + crc = fdc_crc(fdc->packet_tx, fdc->packet_tx_size); + + fdc->packet_tx[fdc->packet_tx_size] = crc & 0xff; + fdc->packet_tx_size++; + fdc->packet_tx[fdc->packet_tx_size] = (crc >> 8) & 0xff; + fdc->packet_tx_size++; + + if (!memcmp(fdc->packet_tx, fdc->tx_header, 6)) { + *from_bit = 1; + fdc->packet_tx_cnt = 6; + + if (!memcmp(fdc->packet_tx + 6, fdc_header_bcast, 6)) { + *bcast_bit = 1; + fdc->packet_tx_cnt += 6; + } + } + } + } + if (fdc->packet_tx_size) { + int copy = fdc->packet_tx_size - fdc->packet_tx_cnt; + + if (copy > 8) { + copy = 8; + *end_bits = 0; + } else { + *end_bits = copy; + fdc->packet_tx_size = 0; + } + memcpy(data, fdc->packet_tx + fdc->packet_tx_cnt, copy); + fdc->packet_tx_cnt += copy; + } +} + +void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header) +{ + unsigned short crc = fdc_crc(header, 6); + + memcpy(fdc->tx_header, header, 6); + fdc->tx_header[6] = crc & 0xff; + fdc->tx_header[7] = (crc >> 8) & 0xff; +} + +int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc) +{ + /* packet will be send in 8 byte frames */ + return (fdc->packet_tx_size + 7) / 8; +} diff --git a/codec2-dev/src/freedv_data_channel.h b/codec2-dev/src/freedv_data_channel.h new file mode 100644 index 00000000..cae25149 --- /dev/null +++ b/codec2-dev/src/freedv_data_channel.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------*\ + + FILE........: freedv_data_channel.h + AUTHOR......: Jeroen Vreeken + DATE CREATED: 03 March 2016 + + Data channel for ethernet like packets in freedv VHF frames. + Currently designed for- + * 2 control bits per frame + * 4 byte counter bits per frame + * 64 bits of data per frame +\*---------------------------------------------------------------------------*/ + +/* + Copyright (C) 2016 Jeroen Vreeken + + All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 2.1, as + published by the Free Software Foundation. This program is + distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + +#ifndef _FREEDV_DATA_CHANNEL_H +#define _FREEDV_DATA_CHANNEL_H + +#include + +#define FREEDV_DATA_CHANNEL_PACKET_MAX 2048 + +typedef void (*freedv_data_callback_rx)(void *, unsigned char *packet, size_t size); +typedef void (*freedv_data_callback_tx)(void *, unsigned char *packet, size_t *size); + +struct freedv_data_channel { + freedv_data_callback_rx cb_rx; + void *cb_rx_state; + freedv_data_callback_tx cb_tx; + void *cb_tx_state; + + unsigned char rx_header[8]; + unsigned char packet_rx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2]; + int packet_rx_cnt; + + unsigned char tx_header[8]; + unsigned char packet_tx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2]; + int packet_tx_cnt; + size_t packet_tx_size; +}; + + +struct freedv_data_channel *freedv_data_channel_create(void); +void freedv_data_channel_destroy(struct freedv_data_channel *fdc); + +void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state); +void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state); + +void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int from_bit, int bcast_bit, int end_bits); +void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int *from_bit, int *bcast_bit, int *end_bits); + +void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header); +int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc); + +#endif /* _FREEDV_DATA_CHANNEL_H */ diff --git a/codec2-dev/src/freedv_vhf_framing.c b/codec2-dev/src/freedv_vhf_framing.c index 66604fdd..4d742521 100644 --- a/codec2-dev/src/freedv_vhf_framing.c +++ b/codec2-dev/src/freedv_vhf_framing.c @@ -39,15 +39,20 @@ #include #include #include - -#include "freedv_vhf_framing.h" - -/* The UW of the VHF type A frame */ -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[] = {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] */ + +#include "freedv_vhf_framing.h" + +/* The voice UW of the VHF type A frame */ +static const uint8_t A_uw_v[] = {0,1,1,0,0,1,1,1, + 1,0,1,0,1,1,0,1}; + +/* The data UW of the VHF type A frame */ +static const uint8_t A_uw_d[] = {1,1,1,1,0,0,0,1, + 1,1,1,1,1,1,0,0}; + +/* Blank VHF type A frame */ +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] */ @@ -63,12 +68,16 @@ static const uint8_t A_blank[] = {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3] #define ST_NOSYNC 0 /* Not synchronized */ #define ST_SYNC 1 /* Synchronized */ -/* Get a single bit out of an MSB-first packed byte array */ -#define UNPACK_BIT_MSBFIRST(bytes,bitidx) ((bytes)[(bitidx)>>3]>>(7-((bitidx)&0x7)))&0x1 - - -/* Place codec and other bits into a frame */ -void fvhff_frame_bits( int frame_type, +/* Get a single bit out of an MSB-first packed byte array */ +#define UNPACK_BIT_MSBFIRST(bytes,bitidx) ((bytes)[(bitidx)>>3]>>(7-((bitidx)&0x7)))&0x1 + +enum frame_payload_type { + FRAME_PAYLOAD_TYPE_VOICE, + FRAME_PAYLOAD_TYPE_DATA, +}; + +/* Place codec and other bits into a frame */ +void fvhff_frame_bits( int frame_type, uint8_t bits_out[], uint8_t codec2_in[], uint8_t proto_in[], @@ -111,12 +120,58 @@ void fvhff_frame_bits( int frame_type, bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit); ibit++; } - } -} - -/* Init and allocate memory for a freedv-vhf framer/deframer */ -struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enable_bit_flip){ - struct freedv_vhf_deframer * deframer; + } +} + +/* Place data and other bits into a frame */ +void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type, + uint8_t bits_out[]){ + int i,ibit; + if(frame_type == FREEDV_VHF_FRAME_A){ + uint8_t data[8]; + int end_bits; + int from_bit; + int bcast_bit; + + /* Fill out frame with blank frame prototype */ + for(i=0; i<4; i++) + bits_out[i] = A_blank[i]; + for(i=92; i<96; i++) + bits_out[i] = A_blank[i]; + + /* UW data */ + for (i=0; i < 16; i++) + bits_out[40 + i] = A_uw_d[i]; + + if (def->fdc) + freedv_data_channel_tx_frame(def->fdc, data, &from_bit, &bcast_bit, &end_bits); + else + return; + + bits_out[4] = from_bit; + bits_out[5] = bcast_bit; + bits_out[6] = 0; /* unused */ + bits_out[7] = 0; /* unused */ + + /* Fill in data bits */ + ibit = 0; + for(i=8; i<40; i++){ /* First half */ + bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit); + ibit++; + } + for(i=56; i<88; i++){ /* Second half */ + bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit); + ibit++; + } + + for (i = 0; i < 4; i++) + bits_out[88 + i] = (end_bits >> (3-i)) & 0x1; + } +} + +/* Init and allocate memory for a freedv-vhf framer/deframer */ +struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enable_bit_flip){ + struct freedv_vhf_deframer * deframer; uint8_t *bits,*invbits; /* It's a Type A frame */ if(frame_type == FREEDV_VHF_FRAME_A){ @@ -145,59 +200,80 @@ struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enabl deframer->state = ST_NOSYNC; deframer->bitptr = 0; deframer->last_uw = 0; - deframer->miss_cnt = 0; - deframer->frame_size = 96; - deframer->on_inv_bits = 0; - return deframer; - } - return NULL; -} - -void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){ - free(def->bits); - free(def); -} + deframer->miss_cnt = 0; + deframer->frame_size = 96; + deframer->on_inv_bits = 0; + + deframer->fdc = NULL; + + return deframer; + } + return NULL; +} + +void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){ + freedv_data_channel_destroy(def->fdc); + free(def->bits); + 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,uint8_t bits[],int tol){ - int frame_type = def->ftype; - int bitptr = def->bitptr; - int frame_size = def->frame_size; - int iuw,ibit; - const uint8_t * uw; - int uw_len; - int uw_offset; - int diff = 0; - - /* Set up parameters for the standard type of frame */ - if(frame_type == FREEDV_VHF_FRAME_A){ - uw = A_uw; - uw_len = 16; - uw_offset = 40; - } else { - return 0; - } - - /* Start bit pointer where UW should be */ - ibit = bitptr + uw_offset; - if(ibit >= frame_size) ibit -= frame_size; - /* Walk through and match bits in frame with bits of UW */ - for(iuw=0; iuw= frame_size) ibit = 0; - } - return diff <= tol; -} - -static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[]){ - int frame_type = def->ftype; - int bitptr = def->bitptr; - int frame_size = def->frame_size; +} + +/* 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,uint8_t bits[],int tol, enum frame_payload_type *pt){ + int frame_type = def->ftype; + int bitptr = def->bitptr; + int frame_size = def->frame_size; + int iuw,ibit; + const uint8_t * uw[2]; + int uw_len; + int uw_offset; + int diff[2] = { 0, 0 }; + int i; + int match[2]; + int r; + + /* Set up parameters for the standard type of frame */ + if(frame_type == FREEDV_VHF_FRAME_A){ + uw[0] = A_uw_v; + uw[1] = A_uw_d; + uw_len = 16; + uw_offset = 40; + } else { + return 0; + } + + /* Check both the voice and data UWs */ + for (i = 0; i < 2; i++) { + /* Start bit pointer where UW should be */ + ibit = bitptr + uw_offset; + if(ibit >= frame_size) ibit -= frame_size; + /* Walk through and match bits in frame with bits of UW */ + for(iuw=0; iuw= frame_size) ibit = 0; + } + match[i] = diff[i] <= tol; + } + /* Pick the best matching UW */ + if (diff[0] < diff[1]) { + r = match[0]; + *pt = FRAME_PAYLOAD_TYPE_VOICE; + } else { + r = match[1]; + *pt = FRAME_PAYLOAD_TYPE_DATA; + } + + return r; +} + +static void fvhff_extract_frame_voice(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[]){ + int frame_type = def->ftype; + int bitptr = def->bitptr; + int frame_size = def->frame_size; int iframe,ibit; if(frame_type == FREEDV_VHF_FRAME_A){ @@ -253,12 +329,79 @@ static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[], } } - } -} - -/* - * Try to find the UW and extract codec/proto/vc bits in def->frame_size bits - */ + } +} + +static void fvhff_extract_frame_data(struct freedv_vhf_deframer * def,uint8_t bits[]){ + int frame_type = def->ftype; + int bitptr = def->bitptr; + int frame_size = def->frame_size; + int iframe,ibit; + + if(frame_type == FREEDV_VHF_FRAME_A){ + uint8_t data[8]; + int end_bits = 0; + int from_bit; + int bcast_bit; + + iframe = bitptr+4; + if(iframe >= frame_size) iframe-=frame_size; + from_bit = bits[iframe]; + iframe++; + if(iframe >= frame_size) iframe-=frame_size; + bcast_bit = bits[iframe]; + + /* Extract data bits */ + memset(data,0,8); + ibit = 0; + /* Extract and pack first half, MSB first */ + iframe = bitptr+8; + if(iframe >= frame_size) iframe-=frame_size; + for(;ibit<32;ibit++){ + data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7)); + iframe++; + if(iframe >= frame_size) iframe=0; + } + + /* Extract and pack last half, MSB first */ + iframe = bitptr+56; + if(iframe >= frame_size) iframe-=frame_size; + for(;ibit<64;ibit++){ + data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7)); + iframe++; + if(iframe >= frame_size) iframe=0; + } + + /* Extract endbits value, MSB first*/ + iframe = bitptr+88; + ibit = 0; + if(iframe >= frame_size) iframe-=frame_size; + for(;ibit<4;ibit++){ + end_bits |= (bits[iframe]&0x1)<<(3-(ibit)); + iframe++; + if(iframe >= frame_size) iframe=0; + } + + if (def->fdc) { + freedv_data_channel_rx_frame(def->fdc, data, from_bit, bcast_bit, end_bits); + } + } +} + +static void fvhff_extract_frame(struct freedv_vhf_deframer * def,uint8_t bits[],uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],enum frame_payload_type pt){ + switch (pt) { + case FRAME_PAYLOAD_TYPE_VOICE: + fvhff_extract_frame_voice(def, bits, codec2_out, proto_out, vc_out); + break; + case FRAME_PAYLOAD_TYPE_DATA: + fvhff_extract_frame_data(def, bits); + break; + } +} + +/* + * Try to find the UW and extract codec/proto/vc bits in def->frame_size bits + */ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]){ uint8_t * strbits = def->bits; uint8_t * invbits = def->invbits; @@ -272,12 +415,13 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin int frame_size = def->frame_size; int i; int uw_first_tol; - int uw_sync_tol; - int miss_tol; - int extracted_frame = 0; - - /* Possibly set up frame-specific params here */ - if(frame_type == FREEDV_VHF_FRAME_A){ + int uw_sync_tol; + int miss_tol; + int extracted_frame = 0; + enum frame_payload_type pt; + + /* 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 = 3; /* The UW bit error tolerance for frames after sync */ miss_tol = 5; /* How many UWs may be missed before going into the de-synced state */ @@ -306,48 +450,49 @@ int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uin } /* UW should be here. We're sunk, so deframe anyway */ if(last_uw == frame_size){ - last_uw = 0; - extracted_frame = 1; - - if(!fvhff_match_uw(def,bits,uw_sync_tol)) - miss_cnt++; - else - miss_cnt=0; + last_uw = 0; + extracted_frame = 1; + + if(!fvhff_match_uw(def,bits,uw_sync_tol, &pt)) + miss_cnt++; + else + miss_cnt=0; /* If we go over the miss tolerance, go into no-sync */ if(miss_cnt>miss_tol){ state = ST_NOSYNC; - } - /* Extract the bits */ - extracted_frame = 1; - fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out); - } - /* Not yet sunk */ - }else{ - /* It's a sync!*/ - if(invbits!=NULL){ - if(fvhff_match_uw(def,invbits,uw_first_tol)){ - state = ST_SYNC; - last_uw = 0; - miss_cnt = 0; - extracted_frame = 1; - on_inv_bits = 1; - fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out); - } - } - if(fvhff_match_uw(def,strbits,uw_first_tol)){ - state = ST_SYNC; - last_uw = 0; - miss_cnt = 0; - extracted_frame = 1; - on_inv_bits = 0; - fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out); - } - } - } + } + /* Extract the bits */ + extracted_frame = 1; + fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out,pt); + } + /* Not yet sunk */ + }else{ + /* It's a sync!*/ + if(invbits!=NULL){ + if(fvhff_match_uw(def,invbits,uw_first_tol, &pt)){ + state = ST_SYNC; + last_uw = 0; + miss_cnt = 0; + extracted_frame = 1; + on_inv_bits = 1; + fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out,pt); + } + } + if(fvhff_match_uw(def,strbits,uw_first_tol, &pt)){ + state = ST_SYNC; + last_uw = 0; + miss_cnt = 0; + extracted_frame = 1; + on_inv_bits = 0; + fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out,pt); + } + } + } def->state = state; - def->last_uw = last_uw; - def->miss_cnt = miss_cnt; - def->on_inv_bits = on_inv_bits; - return extracted_frame; -} + def->last_uw = last_uw; + def->miss_cnt = miss_cnt; + def->on_inv_bits = on_inv_bits; + /* return zero for data frames, they are already handled by callback */ + return extracted_frame && pt == FRAME_PAYLOAD_TYPE_VOICE; +} diff --git a/codec2-dev/src/freedv_vhf_framing.h b/codec2-dev/src/freedv_vhf_framing.h index 7ced7f35..a3843ef3 100644 --- a/codec2-dev/src/freedv_vhf_framing.h +++ b/codec2-dev/src/freedv_vhf_framing.h @@ -33,12 +33,14 @@ along with this program; if not, see . */ -#ifndef _FREEDV_VHF_FRAMING_H -#define _FREEDV_VHF_FRAMING_H - -/* Standard frame type */ -#define FREEDV_VHF_FRAME_A 1 - +#ifndef _FREEDV_VHF_FRAMING_H +#define _FREEDV_VHF_FRAMING_H + +#include "freedv_data_channel.h" + +/* Standard frame type */ +#define FREEDV_VHF_FRAME_A 1 + struct freedv_vhf_deframer { int ftype; /* Type of frame to be looking for */ int state; /* State of deframer */ @@ -47,22 +49,25 @@ struct freedv_vhf_deframer { int bitptr; /* Pointer into circular bit buffer */ int miss_cnt; /* How many UWs have been missed */ - int last_uw; /* How many bits since the last UW? */ - int frame_size; /* How big is a frame? */ - int on_inv_bits; /* Are we using the inverted bits? */ -}; - -/* Init and allocate memory for a freedv-vhf framer/deframer */ + int last_uw; /* How many bits since the last UW? */ + int frame_size; /* How big is a frame? */ + int on_inv_bits; /* Are we using the inverted bits? */ + + struct freedv_data_channel *fdc; +}; + +/* Init and allocate memory for a freedv-vhf framer/deframer */ struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type,int enable_bit_flip); /* Free the memory used by a freedv-vhf framer/deframer */ void fvhff_destroy_deframer(struct freedv_vhf_deframer * def); - -/* Place codec and other bits into a frame */ -void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]); - -/* Find and extract frames from a stream of bits */ -int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]); + +/* Place codec and other bits into a frame */ +void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]); +void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,uint8_t bits_out[]); + +/* Find and extract frames from a stream of bits */ +int fvhff_deframe_bits(struct freedv_vhf_deframer * def,uint8_t codec2_out[],uint8_t proto_out[],uint8_t vc_out[],uint8_t bits_in[]); /* Is the de-framer synchronized? */ int fvhff_synchronized(struct freedv_vhf_deframer * def); diff --git a/codec2-dev/src/fsk.h b/codec2-dev/src/fsk.h index 6e7a7dd5..29563dca 100644 --- a/codec2-dev/src/fsk.h +++ b/codec2-dev/src/fsk.h @@ -33,12 +33,14 @@ #include "kiss_fftr.h" #include "modem_stats.h" -#define MODE_2FSK 2 -#define MODE_4FSK 4 - -struct FSK { - /* Static parameters set up by fsk_init */ - int Ndft; /* buffer size for freq offset est fft */ +#define MODE_2FSK 2 +#define MODE_4FSK 4 + +#define FSK_SCALE 16383 + +struct FSK { + /* Static parameters set up by fsk_init */ + int Ndft; /* buffer size for freq offset est fft */ int Fs; /* sample freq */ int N; /* processing buffer size */ int Rs; /* symbol rate */