codebookmel.c
codebooklspmelvq.c
codebookge.c
- golay23.c
- freedv_api.c
- freedv_vhf_framing.c
- varicode.c
- modem_stats.c
-)
+ golay23.c\r
+ freedv_api.c\r
+ freedv_vhf_framing.c\r
+ freedv_data_channel.c\r
+ varicode.c\r
+ modem_stats.c\r
+)\r
set(CODEC2_PUBLIC_HEADERS
golay23.h
}
#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()
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[]);\r
+void codec2_set_natural_or_gray(struct CODEC2 *codec2_state, int gray);\r
+void codec2_set_softdec(struct CODEC2 *c2, float *softdec);\r
+float codec2_get_energy(struct CODEC2 *codec2_state, const unsigned char *bits);\r
+\r
+#endif\r
+\r
#ifdef __cplusplus
}
#endif
#ifndef __C2FMFSK_H
#define __C2FMFSK_H
#include <stdint.h>
-#include "comp.h"
-#include "modem_stats.h"
-
-/*
- * fm-me-2fsk state
- */
+#include "comp.h"\r
+#include "modem_stats.h"\r
+\r
+#define FMFSK_SCALE 32767\r
+\r
+/* \r
+ * fm-me-2fsk state\r
+ */\r
struct FMFSK{
/* Static fmfsk parameters */
int Rb; /* Manchester-encoded bitrate */
/* 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 */
/* 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; i<f->n_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; i<f->n_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; i<f->n_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; i<f->n_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; i<f->n_nom_modem_samples; i++){
+ mod_out[i] = (short)(tx_float[i]*FMFSK_SCALE);
+ }
}
}
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; i<f->n_nom_modem_samples; i++)
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 */
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
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
/* 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 */\r
+typedef char * (*freedv_callback_prototx)(void *);\r
+\r
+/* Data packet callbacks */\r
+/* Called when a packet has been received */\r
+typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size);\r
+/* Called when a new packet can be send */\r
+typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size);\r
+\r
+\r
+// FreeDV API functions:\r
+// open, close\r
+struct freedv *freedv_open(int mode);\r
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[]);\r
+void freedv_comptx (struct freedv *freedv, COMP mod_out[], short speech_in[]);\r
+void freedv_codectx (struct freedv *f, short mod_out[], unsigned char *packed_codec_bits);\r
+void freedv_datatx (struct freedv *f, short mod_out[]);\r
+int freedv_data_ntxframes (struct freedv *freedv);\r
+// Receive\r
+int freedv_nin (struct freedv *freedv);\r
+int freedv_rx (struct freedv *freedv, short speech_out[], short demod_in[]);\r
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\r
+void freedv_set_callback_txt (struct freedv *freedv, freedv_callback_rx rx, freedv_callback_tx tx, void *callback_state);\r
+void freedv_set_callback_protocol (struct freedv *freedv, freedv_callback_protorx rx, freedv_callback_prototx tx, void *callback_state);\r
+void freedv_set_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state);\r
+void freedv_set_test_frames (struct freedv *freedv, int test_frames);\r
+void freedv_set_smooth_symbols (struct freedv *freedv, int smooth_symbols);\r
+void freedv_set_squelch_en (struct freedv *freedv, int squelch_en);\r
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);\r
+void freedv_set_callback_error_pattern (struct freedv *freedv, freedv_calback_error_pattern cb, void *state);\r
+void freedv_set_varicode_code_num (struct freedv *freedv, int val);\r
+void freedv_set_data_header (struct freedv *freedv, unsigned char *header);\r
+\r
+// Get parameters\r
+int freedv_get_version(void);\r
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);
--- /dev/null
+/*---------------------------------------------------------------------------*\\r
+\r
+ FILE........: freedv_data_channel.c\r
+ AUTHOR......: Jeroen Vreeken\r
+ DATE CREATED: 03 March 2016\r
+\r
+ Data channel for ethernet like packets in freedv VHF frames.\r
+ Currently designed for-\r
+ * 2 control bits per frame\r
+ * 4 byte counter bits per frame\r
+ * 64 bits of data per frame\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+ Copyright (C) 2016 Jeroen Vreeken\r
+\r
+ All rights reserved.\r
+\r
+ This program is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU Lesser General Public License version 2.1, as\r
+ published by the Free Software Foundation. This program is\r
+ distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\r
+ License for more details.\r
+\r
+ You should have received a copy of the GNU Lesser General Public License\r
+ along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#include "freedv_data_channel.h"\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+static unsigned char fdc_header_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\r
+\r
+/* CCIT CRC table (0x1201 polynomal) */\r
+static unsigned short fdc_crc_table[256] = {\r
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,\r
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,\r
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,\r
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,\r
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,\r
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,\r
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,\r
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,\r
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,\r
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,\r
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,\r
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,\r
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,\r
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,\r
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,\r
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,\r
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,\r
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,\r
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,\r
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,\r
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,\r
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,\r
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,\r
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,\r
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,\r
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,\r
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,\r
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,\r
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,\r
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,\r
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,\r
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78\r
+};\r
+\r
+static unsigned short fdc_crc(unsigned char *buffer, size_t len)\r
+{\r
+ unsigned short crc = 0xffff;\r
+ size_t i;\r
+\r
+ for (i = 0; i < len; i++, buffer++) {\r
+ crc = (crc >> 8) ^ fdc_crc_table[(crc ^ *buffer) & 0xff];\r
+ }\r
+\r
+ return crc ^ 0xffff;\r
+}\r
+ \r
+struct freedv_data_channel *freedv_data_channel_create(void)\r
+{\r
+ struct freedv_data_channel *fdc;\r
+ \r
+ fdc = malloc(sizeof(struct freedv_data_channel));\r
+ if (!fdc)\r
+ return NULL;\r
+\r
+ fdc->cb_rx = NULL;\r
+\r
+ freedv_data_set_header(fdc, fdc_header_bcast);\r
+\r
+ memcpy(fdc->rx_header, fdc->tx_header, 8);\r
+ \r
+ return fdc;\r
+}\r
+\r
+void freedv_data_channel_destroy(struct freedv_data_channel *fdc)\r
+{\r
+ free(fdc);\r
+}\r
+\r
+\r
+void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state)\r
+{\r
+ fdc->cb_rx = cb;\r
+ fdc->cb_rx_state = state;\r
+}\r
+\r
+void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state)\r
+{\r
+ fdc->cb_tx = cb;\r
+ fdc->cb_tx_state = state;\r
+}\r
+\r
+void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int from_bit, int bcast_bit, int end_bits)\r
+{\r
+ /* New packet? */\r
+ if (fdc->packet_rx_cnt == 0) {\r
+ /* Does the packet have a compressed from field? */\r
+ if (from_bit) {\r
+ /* Compressed from: take the previously received header */\r
+ memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc->rx_header, 6);\r
+ fdc->packet_rx_cnt += 6; \r
+ }\r
+ if (bcast_bit) {\r
+ /* Compressed to: fill in broadcast address */\r
+ memcpy(fdc->packet_rx + fdc->packet_rx_cnt, fdc_header_bcast, sizeof(fdc_header_bcast));\r
+ fdc->packet_rx_cnt += 6;\r
+ }\r
+ }\r
+ \r
+ int copy_bits;\r
+ if (end_bits) {\r
+ copy_bits = end_bits;\r
+ } else {\r
+ copy_bits = 8;\r
+ }\r
+ if (fdc->packet_rx_cnt + copy_bits >= FREEDV_DATA_CHANNEL_PACKET_MAX) {\r
+ /* Something went wrong... this can not be a real packet */\r
+ fdc->packet_rx_cnt = 0;\r
+ return;\r
+ }\r
+\r
+ memcpy(fdc->packet_rx + fdc->packet_rx_cnt, data, copy_bits);\r
+ fdc->packet_rx_cnt += copy_bits;\r
+ \r
+ if (end_bits != 0 && fdc->packet_rx_cnt >= 2) {\r
+ unsigned short calc_crc = fdc_crc(fdc->packet_rx, fdc->packet_rx_cnt - 2);\r
+ unsigned short rx_crc;\r
+ rx_crc = fdc->packet_rx[fdc->packet_rx_cnt - 1] << 8;\r
+ rx_crc |= fdc->packet_rx[fdc->packet_rx_cnt - 2];\r
+\r
+ if (rx_crc == calc_crc) {\r
+ if (fdc->packet_rx_cnt == 8) {\r
+ /* It is a single header field, remember it for later */\r
+ memcpy(fdc->rx_header, fdc->packet_rx, 6);\r
+ }\r
+\r
+ /* callback */\r
+ if (fdc->cb_rx) {\r
+ unsigned char tmp[6];\r
+ memcpy(tmp, fdc->packet_rx, 6);\r
+ memcpy(fdc->packet_rx, fdc->packet_rx + 6, 6);\r
+ memcpy(fdc->packet_rx + 6, tmp, 6);\r
+ \r
+ size_t size = fdc->packet_rx_cnt - 2;\r
+ if (size < 12)\r
+ size = 12;\r
+ fdc->cb_rx(fdc->cb_rx_state, fdc->packet_rx, size);\r
+ }\r
+ } \r
+ fdc->packet_rx_cnt = 0;\r
+ }\r
+}\r
+\r
+void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int *from_bit, int *bcast_bit, int *end_bits)\r
+{\r
+ *from_bit = 0;\r
+ *bcast_bit = 0;\r
+ \r
+ if (!fdc->packet_tx_size) {\r
+ fdc->packet_tx_cnt = 0;\r
+ \r
+ if (fdc->cb_tx) {\r
+ fdc->packet_tx_size = FREEDV_DATA_CHANNEL_PACKET_MAX;\r
+ fdc->cb_tx(fdc->cb_tx_state, fdc->packet_tx, &fdc->packet_tx_size);\r
+ }\r
+ if (!fdc->packet_tx_size) {\r
+ /* Nothing to send, insert a header frame */\r
+ memcpy(fdc->packet_tx, fdc->tx_header, 8);\r
+ fdc->packet_tx_size = 8;\r
+ } else {\r
+ /* new packet */\r
+ unsigned short crc;\r
+ unsigned char tmp[6];\r
+\r
+ memcpy(tmp, fdc->packet_tx, 6);\r
+ memcpy(fdc->packet_tx, fdc->packet_tx + 6, 6);\r
+ memcpy(fdc->packet_tx + 6, tmp, 6);\r
+\r
+ crc = fdc_crc(fdc->packet_tx, fdc->packet_tx_size);\r
+\r
+ fdc->packet_tx[fdc->packet_tx_size] = crc & 0xff;\r
+ fdc->packet_tx_size++;\r
+ fdc->packet_tx[fdc->packet_tx_size] = (crc >> 8) & 0xff;\r
+ fdc->packet_tx_size++;\r
+ \r
+ if (!memcmp(fdc->packet_tx, fdc->tx_header, 6)) {\r
+ *from_bit = 1;\r
+ fdc->packet_tx_cnt = 6;\r
+ \r
+ if (!memcmp(fdc->packet_tx + 6, fdc_header_bcast, 6)) {\r
+ *bcast_bit = 1;\r
+ fdc->packet_tx_cnt += 6;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (fdc->packet_tx_size) {\r
+ int copy = fdc->packet_tx_size - fdc->packet_tx_cnt;\r
+ \r
+ if (copy > 8) {\r
+ copy = 8;\r
+ *end_bits = 0;\r
+ } else {\r
+ *end_bits = copy;\r
+ fdc->packet_tx_size = 0;\r
+ }\r
+ memcpy(data, fdc->packet_tx + fdc->packet_tx_cnt, copy);\r
+ fdc->packet_tx_cnt += copy;\r
+ }\r
+}\r
+\r
+void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header)\r
+{\r
+ unsigned short crc = fdc_crc(header, 6);\r
+\r
+ memcpy(fdc->tx_header, header, 6);\r
+ fdc->tx_header[6] = crc & 0xff;\r
+ fdc->tx_header[7] = (crc >> 8) & 0xff;\r
+}\r
+\r
+int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc)\r
+{\r
+ /* packet will be send in 8 byte frames */\r
+ return (fdc->packet_tx_size + 7) / 8;\r
+}\r
--- /dev/null
+/*---------------------------------------------------------------------------*\\r
+\r
+ FILE........: freedv_data_channel.h\r
+ AUTHOR......: Jeroen Vreeken\r
+ DATE CREATED: 03 March 2016\r
+\r
+ Data channel for ethernet like packets in freedv VHF frames.\r
+ Currently designed for-\r
+ * 2 control bits per frame\r
+ * 4 byte counter bits per frame\r
+ * 64 bits of data per frame\r
+\*---------------------------------------------------------------------------*/\r
+\r
+/*\r
+ Copyright (C) 2016 Jeroen Vreeken\r
+\r
+ All rights reserved.\r
+\r
+ This program is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU Lesser General Public License version 2.1, as\r
+ published by the Free Software Foundation. This program is\r
+ distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\r
+ License for more details.\r
+\r
+ You should have received a copy of the GNU Lesser General Public License\r
+ along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*/\r
+\r
+#ifndef _FREEDV_DATA_CHANNEL_H\r
+#define _FREEDV_DATA_CHANNEL_H\r
+\r
+#include <stdlib.h>\r
+\r
+#define FREEDV_DATA_CHANNEL_PACKET_MAX 2048\r
+\r
+typedef void (*freedv_data_callback_rx)(void *, unsigned char *packet, size_t size);\r
+typedef void (*freedv_data_callback_tx)(void *, unsigned char *packet, size_t *size);\r
+\r
+struct freedv_data_channel {\r
+ freedv_data_callback_rx cb_rx;\r
+ void *cb_rx_state;\r
+ freedv_data_callback_tx cb_tx;\r
+ void *cb_tx_state;\r
+ \r
+ unsigned char rx_header[8];\r
+ unsigned char packet_rx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];\r
+ int packet_rx_cnt;\r
+ \r
+ unsigned char tx_header[8];\r
+ unsigned char packet_tx[FREEDV_DATA_CHANNEL_PACKET_MAX + 2];\r
+ int packet_tx_cnt;\r
+ size_t packet_tx_size;\r
+};\r
+\r
+\r
+struct freedv_data_channel *freedv_data_channel_create(void);\r
+void freedv_data_channel_destroy(struct freedv_data_channel *fdc);\r
+\r
+void freedv_data_set_cb_rx(struct freedv_data_channel *fdc, freedv_data_callback_rx cb, void *state);\r
+void freedv_data_set_cb_tx(struct freedv_data_channel *fdc, freedv_data_callback_tx cb, void *state);\r
+\r
+void freedv_data_channel_rx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int from_bit, int bcast_bit, int end_bits);\r
+void freedv_data_channel_tx_frame(struct freedv_data_channel *fdc, unsigned char data[8], int *from_bit, int *bcast_bit, int *end_bits);\r
+\r
+void freedv_data_set_header(struct freedv_data_channel *fdc, unsigned char *header);\r
+int freedv_data_get_n_tx_frames(struct freedv_data_channel *fdc);\r
+\r
+#endif /* _FREEDV_DATA_CHANNEL_H */\r
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-
-#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] */
+\r
+#include "freedv_vhf_framing.h"\r
+\r
+/* The voice UW of the VHF type A frame */\r
+static const uint8_t A_uw_v[] = {0,1,1,0,0,1,1,1,\r
+ 1,0,1,0,1,1,0,1};\r
+\r
+/* The data UW of the VHF type A frame */\r
+static const uint8_t A_uw_d[] = {1,1,1,1,0,0,0,1,\r
+ 1,1,1,1,1,1,0,0};\r
+\r
+/* Blank VHF type A frame */\r
+static const uint8_t A_blank[] = {1,0,1,0,0,1,1,1, /* Padding[0:3] Proto[0:3] */\r
+ 1,0,1,0,0,1,1,1, /* Proto[4:11] */\r
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] */
#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 */\r
+#define UNPACK_BIT_MSBFIRST(bytes,bitidx) ((bytes)[(bitidx)>>3]>>(7-((bitidx)&0x7)))&0x1\r
+\r
+enum frame_payload_type {\r
+ FRAME_PAYLOAD_TYPE_VOICE,\r
+ FRAME_PAYLOAD_TYPE_DATA,\r
+};\r
+\r
+/* Place codec and other bits into a frame */\r
+void fvhff_frame_bits( int frame_type,\r
uint8_t bits_out[],
uint8_t codec2_in[],
uint8_t proto_in[],
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;
+ }\r
+}\r
+\r
+/* Place data and other bits into a frame */\r
+void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,\r
+ uint8_t bits_out[]){\r
+ int i,ibit;\r
+ if(frame_type == FREEDV_VHF_FRAME_A){\r
+ uint8_t data[8];\r
+ int end_bits;\r
+ int from_bit;\r
+ int bcast_bit;\r
+\r
+ /* Fill out frame with blank frame prototype */\r
+ for(i=0; i<4; i++)\r
+ bits_out[i] = A_blank[i];\r
+ for(i=92; i<96; i++)\r
+ bits_out[i] = A_blank[i];\r
+ \r
+ /* UW data */\r
+ for (i=0; i < 16; i++)\r
+ bits_out[40 + i] = A_uw_d[i];\r
+ \r
+ if (def->fdc)\r
+ freedv_data_channel_tx_frame(def->fdc, data, &from_bit, &bcast_bit, &end_bits);\r
+ else\r
+ return;\r
+\r
+ bits_out[4] = from_bit;\r
+ bits_out[5] = bcast_bit;\r
+ bits_out[6] = 0; /* unused */\r
+ bits_out[7] = 0; /* unused */\r
+\r
+ /* Fill in data bits */\r
+ ibit = 0;\r
+ for(i=8; i<40; i++){ /* First half */\r
+ bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);\r
+ ibit++;\r
+ }\r
+ for(i=56; i<88; i++){ /* Second half */\r
+ bits_out[i] = UNPACK_BIT_MSBFIRST(data,ibit);\r
+ ibit++;\r
+ }\r
+\r
+ for (i = 0; i < 4; i++)\r
+ bits_out[88 + i] = (end_bits >> (3-i)) & 0x1;\r
+ }\r
+}\r
+\r
+/* Init and allocate memory for a freedv-vhf framer/deframer */\r
+struct freedv_vhf_deframer * fvhff_create_deframer(uint8_t frame_type, int enable_bit_flip){\r
+ struct freedv_vhf_deframer * deframer;\r
uint8_t *bits,*invbits;
/* It's a Type A frame */
if(frame_type == FREEDV_VHF_FRAME_A){
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;\r
+ deframer->frame_size = 96;\r
+ deframer->on_inv_bits = 0;\r
+\r
+ deframer->fdc = NULL;\r
+\r
+ return deframer;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+void fvhff_destroy_deframer(struct freedv_vhf_deframer * def){\r
+ freedv_data_channel_destroy(def->fdc);\r
+ free(def->bits);\r
+ free(def);\r
+}\r
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<uw_len; iuw++){
- if(bits[ibit] != uw[iuw]) diff++;
- ibit++;
- if(ibit >= 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;
+}\r
+\r
+/* See if the UW is where it should be, to within a tolerance, in a bit buffer */\r
+static int fvhff_match_uw(struct freedv_vhf_deframer * def,uint8_t bits[],int tol, enum frame_payload_type *pt){\r
+ int frame_type = def->ftype;\r
+ int bitptr = def->bitptr;\r
+ int frame_size = def->frame_size;\r
+ int iuw,ibit;\r
+ const uint8_t * uw[2];\r
+ int uw_len;\r
+ int uw_offset;\r
+ int diff[2] = { 0, 0 };\r
+ int i;\r
+ int match[2];\r
+ int r;\r
+ \r
+ /* Set up parameters for the standard type of frame */\r
+ if(frame_type == FREEDV_VHF_FRAME_A){\r
+ uw[0] = A_uw_v;\r
+ uw[1] = A_uw_d;\r
+ uw_len = 16;\r
+ uw_offset = 40;\r
+ } else {\r
+ return 0;\r
+ }\r
+ \r
+ /* Check both the voice and data UWs */\r
+ for (i = 0; i < 2; i++) {\r
+ /* Start bit pointer where UW should be */\r
+ ibit = bitptr + uw_offset;\r
+ if(ibit >= frame_size) ibit -= frame_size;\r
+ /* Walk through and match bits in frame with bits of UW */\r
+ for(iuw=0; iuw<uw_len; iuw++){\r
+ if(bits[ibit] != uw[i][iuw]) diff[i]++;\r
+ ibit++;\r
+ if(ibit >= frame_size) ibit = 0;\r
+ }\r
+ match[i] = diff[i] <= tol;\r
+ }\r
+ /* Pick the best matching UW */\r
+ if (diff[0] < diff[1]) {\r
+ r = match[0];\r
+ *pt = FRAME_PAYLOAD_TYPE_VOICE;\r
+ } else {\r
+ r = match[1];\r
+ *pt = FRAME_PAYLOAD_TYPE_DATA;\r
+ }\r
+ \r
+ return r;\r
+}\r
+\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[]){\r
+ int frame_type = def->ftype;\r
+ int bitptr = def->bitptr;\r
+ int frame_size = def->frame_size;\r
int iframe,ibit;
if(frame_type == FREEDV_VHF_FRAME_A){
}
}
- }
-}
-
-/*
- * Try to find the UW and extract codec/proto/vc bits in def->frame_size bits
- */
+ }\r
+}\r
+\r
+static void fvhff_extract_frame_data(struct freedv_vhf_deframer * def,uint8_t bits[]){\r
+ int frame_type = def->ftype;\r
+ int bitptr = def->bitptr;\r
+ int frame_size = def->frame_size;\r
+ int iframe,ibit;\r
+ \r
+ if(frame_type == FREEDV_VHF_FRAME_A){\r
+ uint8_t data[8];\r
+ int end_bits = 0;\r
+ int from_bit;\r
+ int bcast_bit;\r
+ \r
+ iframe = bitptr+4;\r
+ if(iframe >= frame_size) iframe-=frame_size;\r
+ from_bit = bits[iframe];\r
+ iframe++;\r
+ if(iframe >= frame_size) iframe-=frame_size;\r
+ bcast_bit = bits[iframe];\r
+\r
+ /* Extract data bits */\r
+ memset(data,0,8);\r
+ ibit = 0;\r
+ /* Extract and pack first half, MSB first */\r
+ iframe = bitptr+8;\r
+ if(iframe >= frame_size) iframe-=frame_size;\r
+ for(;ibit<32;ibit++){\r
+ data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));\r
+ iframe++;\r
+ if(iframe >= frame_size) iframe=0;\r
+ }\r
+ \r
+ /* Extract and pack last half, MSB first */\r
+ iframe = bitptr+56;\r
+ if(iframe >= frame_size) iframe-=frame_size;\r
+ for(;ibit<64;ibit++){\r
+ data[ibit>>3] |= (bits[iframe]&0x1)<<(7-(ibit&0x7));\r
+ iframe++;\r
+ if(iframe >= frame_size) iframe=0;\r
+ }\r
+\r
+ /* Extract endbits value, MSB first*/\r
+ iframe = bitptr+88;\r
+ ibit = 0;\r
+ if(iframe >= frame_size) iframe-=frame_size;\r
+ for(;ibit<4;ibit++){\r
+ end_bits |= (bits[iframe]&0x1)<<(3-(ibit));\r
+ iframe++;\r
+ if(iframe >= frame_size) iframe=0;\r
+ }\r
+ \r
+ if (def->fdc) {\r
+ freedv_data_channel_rx_frame(def->fdc, data, from_bit, bcast_bit, end_bits);\r
+ }\r
+ }\r
+}\r
+\r
+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){\r
+ switch (pt) {\r
+ case FRAME_PAYLOAD_TYPE_VOICE:\r
+ fvhff_extract_frame_voice(def, bits, codec2_out, proto_out, vc_out);\r
+ break;\r
+ case FRAME_PAYLOAD_TYPE_DATA:\r
+ fvhff_extract_frame_data(def, bits);\r
+ break;\r
+ }\r
+}\r
+\r
+/*\r
+ * Try to find the UW and extract codec/proto/vc bits in def->frame_size bits \r
+ */\r
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;
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;\r
+ int miss_tol;\r
+ int extracted_frame = 0;\r
+ enum frame_payload_type pt;\r
+ \r
+ /* Possibly set up frame-specific params here */\r
+ if(frame_type == FREEDV_VHF_FRAME_A){\r
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 */
}
/* 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;\r
+ extracted_frame = 1;\r
+ \r
+ if(!fvhff_match_uw(def,bits,uw_sync_tol, &pt))\r
+ miss_cnt++;\r
+ else\r
+ miss_cnt=0;\r
/* 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);
- }
- }
- }
+ }\r
+ /* Extract the bits */\r
+ extracted_frame = 1;\r
+ fvhff_extract_frame(def,bits,codec2_out,proto_out,vc_out,pt);\r
+ }\r
+ /* Not yet sunk */\r
+ }else{\r
+ /* It's a sync!*/\r
+ if(invbits!=NULL){\r
+ if(fvhff_match_uw(def,invbits,uw_first_tol, &pt)){\r
+ state = ST_SYNC;\r
+ last_uw = 0;\r
+ miss_cnt = 0;\r
+ extracted_frame = 1;\r
+ on_inv_bits = 1;\r
+ fvhff_extract_frame(def,invbits,codec2_out,proto_out,vc_out,pt);\r
+ }\r
+ }\r
+ if(fvhff_match_uw(def,strbits,uw_first_tol, &pt)){\r
+ state = ST_SYNC;\r
+ last_uw = 0;\r
+ miss_cnt = 0;\r
+ extracted_frame = 1;\r
+ on_inv_bits = 0;\r
+ fvhff_extract_frame(def,strbits,codec2_out,proto_out,vc_out,pt);\r
+ }\r
+ }\r
+ }\r
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;\r
+ def->miss_cnt = miss_cnt;\r
+ def->on_inv_bits = on_inv_bits;\r
+ /* return zero for data frames, they are already handled by callback */\r
+ return extracted_frame && pt == FRAME_PAYLOAD_TYPE_VOICE;\r
+}\r
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _FREEDV_VHF_FRAMING_H
-#define _FREEDV_VHF_FRAMING_H
-
-/* Standard frame type */
-#define FREEDV_VHF_FRAME_A 1
-
+#ifndef _FREEDV_VHF_FRAMING_H\r
+#define _FREEDV_VHF_FRAMING_H\r
+\r
+#include "freedv_data_channel.h"\r
+\r
+/* Standard frame type */\r
+#define FREEDV_VHF_FRAME_A 1\r
+\r
struct freedv_vhf_deframer {
int ftype; /* Type of frame to be looking for */
int state; /* State of 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? */\r
+ int frame_size; /* How big is a frame? */\r
+ int on_inv_bits; /* Are we using the inverted bits? */\r
+\r
+ struct freedv_data_channel *fdc;\r
+};\r
+\r
+/* Init and allocate memory for a freedv-vhf framer/deframer */\r
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[]);
+\r
+/* Place codec and other bits into a frame */\r
+void fvhff_frame_bits(int frame_type,uint8_t bits_out[],uint8_t codec2_in[],uint8_t proto_in[],uint8_t vc_in[]);\r
+void fvhff_frame_data_bits(struct freedv_vhf_deframer * def, int frame_type,uint8_t bits_out[]);\r
+\r
+/* Find and extract frames from a stream of bits */\r
+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[]);\r
/* Is the de-framer synchronized? */
int fvhff_synchronized(struct freedv_vhf_deframer * def);
#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\r
+#define MODE_4FSK 4\r
+\r
+#define FSK_SCALE 16383\r
+\r
+struct FSK {\r
+ /* Static parameters set up by fsk_init */\r
+ int Ndft; /* buffer size for freq offset est fft */\r
int Fs; /* sample freq */
int N; /* processing buffer size */
int Rs; /* symbol rate */