#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-\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
+
+#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] */
#define ST_NOSYNC 0 /* Not synchronized */
#define ST_SYNC 1 /* Synchronized */
-/* 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
+/* 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[],
bits_out[i] = UNPACK_BIT_MSBFIRST(codec2_in,ibit);
ibit++;
}
- }\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
+ }
+}
+
+/* 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){
deframer->state = ST_NOSYNC;
deframer->bitptr = 0;
deframer->last_uw = 0;
- 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
+ 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;
-}\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
+}
+
+/* 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<uw_len; iuw++){
+ if(bits[ibit] != uw[i][iuw]) diff[i]++;
+ ibit++;
+ if(ibit >= 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){
}
}
- }\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
+ }
+}
+
+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;
int frame_size = def->frame_size;
int i;
int uw_first_tol;
- 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
+ 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 */
for(i=0; i<frame_size; i++){
/* Put a bit in the buffer */
strbits[bitptr] = bits_in[i];
+ /* If we're checking the inverted bitstream, put a bit in it */
if(invbits!=NULL)
invbits[bitptr] = bits_in[i]?0:1;
bitptr++;
}
/* UW should be here. We're sunk, so deframe anyway */
if(last_uw == frame_size){
- 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
+ last_uw = 0;
+
+ 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;
- }\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
+ }
+ /* 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;\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
+ 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;
+}