int g_split;
int g_tx;
float g_snr;
-char g_txid[MAX_TXID];
+
+// sending and receiving data
+struct FIFO *g_txDataInFifo;
+struct VARICODE_DEC g_varicode_dec_states;
// tx/rx processing states
int g_nRxIn = FDMDV_NOM_SAMPLES_PER_FRAME;
COMP g_TxFreqOffsetPhaseRect;
COMP g_TxFreqOffsetFreqRect;
-// DRs debug variables, will be cleaned up eventually
-int cb_cnt, cb1, cb2;
-int mute_mic = 0;
-int sc1, sc2;
-int g_outfifo2_empty;
-
// experimental mutex to make sound card callbacks mutually exclusive
// TODO: review code and see if we need this any more, as fifos should
// now be thread safe
g_tx = 0;
g_split = 0;
+ // data states
+
+ g_txDataInFifo = fifo_create(MAX_TXID*VARICODE_MAX_BITS);
+ varicode_decode_init(&g_varicode_dec_states);
+
}
//-------------------------------------------------------------------------
void MainFrame::OnTogBtnTxID(wxCommandEvent& event)
{
wxString txid = m_txtCtrlTx->GetValue();
- strncpy(g_txid, (const char*) txid.mb_str(wxConvUTF8), MAX_TXID-1);
- printf("MainFrame::OnTogBtnTxID, sending: %s\n", g_txid);
+ char txid2[MAX_TXID];
+ strncpy(txid2, (const char*) txid.mb_str(wxConvUTF8), MAX_TXID-1);
+
+ // varicode encode and write to tx data fifo
+
+ short varicode[MAX_TXID*VARICODE_MAX_BITS];
+ int nout = varicode_encode(varicode, txid2, MAX_TXID*VARICODE_MAX_BITS, strlen(txid2));
+ printf("tx varicode: ");
+ for(int i=0; i<nout; i++)
+ printf("%d", varicode[i]);
+ printf("\n");
+ int ret = fifo_write(g_txDataInFifo, varicode, nout);
+ printf("MainFrame::OnTogBtnTxID, sending: %s nout: %d ret: %d\n", txid2, nout, ret);
+
event.Skip();
}
int inputChannels1, inputChannels2;
if(!m_RxRunning) {
- cb_cnt = 0;
- sc1 = sc2 = 0;
- g_outfifo2_empty = 0;
-
m_RxRunning = true;
if(Pa_Initialize())
wxMutexLocker lock(g_mutexProtectingCallbackData);
- if (cb_cnt)
- printf("cb1: already in a callback\n");
- cb_cnt++;
if (statusFlags)
printf("cb1 statusFlags: 0x%x\n", (int)statusFlags);
wptr[1] = 0;
}
}
- cb_cnt--;
return paContinue;
}
int rx_bits[FDMDV_BITS_PER_FRAME];
unsigned char packed_bits[BYTES_PER_CODEC_FRAME];
float rx_spec[FDMDV_NSPEC];
- int i;
+ int i,j;
int nin_prev;
int bit;
int byte;
}
if(sync_bit == 1)
{
+ int data_flag_index;
+
// second half of frame of codec bits
memcpy(&codec_bits[FDMDV_BITS_PER_FRAME], rx_bits, FDMDV_BITS_PER_FRAME*sizeof(int));
- // pack bits, MSB received first
- bit = 7;
- byte = 0;
- memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
- for(i = 0; i < BITS_PER_CODEC_FRAME; i++)
- {
- packed_bits[byte] |= (codec_bits[i] << bit);
- bit--;
- if(bit < 0)
- {
- bit = 7;
- byte++;
+
+ // lets see if this is a data frame
+
+ data_flag_index = codec2_get_spare_bit_index(c2);
+ assert(data_flag_index != -1); // not supported for all rates
+
+ if (codec_bits[data_flag_index]) {
+ //printf("data_flag_index: %d\n", data_flag_index);
+ //printf("rx data bits: ");
+ //for(i=0; i<BITS_PER_CODEC_FRAME; i++)
+ // printf("%d",codec_bits[i]);
+ //printf("\n");
+
+ // if data construct data frame, varicode decode, write to fifo, send event
+
+ short varicode[BITS_PER_CODEC_FRAME - 1];
+ char ascii_out[MAX_TXID];
+ int n_ascii;
+
+ for(i=0,j=0; i<data_flag_index; i++,j++)
+ varicode[j] = codec_bits[i];
+ for(i=data_flag_index+1; i<BITS_PER_CODEC_FRAME; i++,j++)
+ varicode[j] = codec_bits[i];
+ n_ascii = varicode_decode(&g_varicode_dec_states, ascii_out, varicode, MAX_TXID, BITS_PER_CODEC_FRAME-1);
+
+ if (n_ascii) {
+ ascii_out[n_ascii] = 0;
+ printf("%d ascii received: %s\n", n_ascii, ascii_out);
}
}
- assert(byte == BYTES_PER_CODEC_FRAME);
+ else {
+
+ // if voice reconstruct missing bit we steal for data flag and decode
+
+ codec2_rebuild_spare_bit(c2, codec_bits);
- // add decoded speech to end of output buffer
+ // pack bits, MSB received first
- assert(codec2_samples_per_frame(c2) == (2*N8));
+ bit = 7;
+ byte = 0;
+ memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
+ for(i = 0; i < BITS_PER_CODEC_FRAME; i++)
+ {
+ packed_bits[byte] |= (codec_bits[i] << bit);
+ bit--;
+ if(bit < 0)
+ {
+ bit = 7;
+ byte++;
+ }
+ }
+ assert(byte == BYTES_PER_CODEC_FRAME);
- codec2_decode(c2, output_buf, packed_bits);
- fifo_write(output_fifo, output_buf, codec2_samples_per_frame(c2));
+ // add decoded speech to end of output buffer
+ assert(codec2_samples_per_frame(c2) == (2*N8));
+
+ codec2_decode(c2, output_buf, packed_bits);
+ fifo_write(output_fifo, output_buf, codec2_samples_per_frame(c2));
+ }
}
break;
}
COMP tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME];
COMP tx_fdm_offset[2*FDMDV_NOM_SAMPLES_PER_FRAME];
int sync_bit;
- int i, bit, byte;
+ int i, bit, byte, data_flag_index;
+ unsigned int nread;
+ short peak, abit;
- codec2_encode(c2, packed_bits, input_buf);
+ // detect silence (todo: or maybe once every 5-10 secs?)
- /* unpack bits, MSB first */
+ peak = 0.0;
+ for(i=0; i<2*N8; i++) {
+ if (input_buf[i] > peak)
+ peak = input_buf[i];
+ }
+
+ // voice/data flag is a spare bit in 1400 bit/s frame that
+ // codec defines
+
+ data_flag_index = codec2_get_spare_bit_index(c2);
+ assert(data_flag_index != -1); // not supported for all rates
+
+ // if there is low speech energy and data to send, then send data frame
+
+ if ((peak < SILENCE_THRESHOLD) && fifo_used(g_txDataInFifo)) {
+ printf("sending data ...\n");
+
+ // we have to handle the case where we might not have a whole
+ // frame of data to send, in that case pad with zeros
+
+ for(i=0; i<data_flag_index; i++) {
+ nread = fifo_read(g_txDataInFifo, &abit, 1);
+ //printf("nread: %d abit: %d\n", nread, abit);
+ if (nread)
+ bits[i] = 0;
+ else
+ bits[i] = abit;
+ }
+ bits[data_flag_index] = 1; // signals a data frame
+ for(i=data_flag_index+1; i<BITS_PER_CODEC_FRAME; i++) {
+ nread = fifo_read(g_txDataInFifo, &abit, 1);
+ if (nread)
+ bits[i] = 0;
+ else
+ bits[i] = abit;
+ }
- bit = 7; byte = 0;
- for(i=0; i<BITS_PER_CODEC_FRAME; i++) {
- bits[i] = (packed_bits[byte] >> bit) & 0x1;
- bit--;
- if (bit < 0) {
- bit = 7;
- byte++;
+ //printf("tx data bits: ");
+ //for(i=0; i<BITS_PER_CODEC_FRAME; i++)
+ // printf("%d",bits[i]);
+ //printf("\n");
}
+ else {
+ codec2_encode(c2, packed_bits, input_buf);
+
+ /* unpack bits, MSB first */
+
+ bit = 7; byte = 0;
+ for(i=0; i<BITS_PER_CODEC_FRAME; i++) {
+ bits[i] = (packed_bits[byte] >> bit) & 0x1;
+ bit--;
+ if (bit < 0) {
+ bit = 7;
+ byte++;
+ }
+ }
+ assert(byte == BYTES_PER_CODEC_FRAME);
+
+ bits[data_flag_index] = 0;
}
- assert(byte == BYTES_PER_CODEC_FRAME);
/* modulate even and odd frames */
wxMutexLocker lock(g_mutexProtectingCallbackData);
- if (cb_cnt)
- printf("cb2: already in a callback\n");
- cb_cnt++;
if (statusFlags)
printf("cb2 statusFlags: 0x%x\n", (int)statusFlags);
}
}
#endif
- //printf("end cb2\n");
- cb_cnt--;
return paContinue;
}
#include "varicode.h"
#include "varicode_table.h"
-#define VARICODE_MAX_BITS (10+2) /* 10 bits for code plus 2 0 bits for inter-character space */
/*
output is an unpacked array of bits of maximum size max_out. Note
unpacked arrays are a more suitable form for modulator input.
*/
-int varicode_encode(int varicode_out[], char ascii_in[], int max_out, int n_in) {
+int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in) {
int n_out, index, n_zeros, v_len;
unsigned short byte1, byte2, packed;
void varicode_decode_init(struct VARICODE_DEC *dec_states)
{
+ dec_states->state = 0;
dec_states->n_zeros = 0;
dec_states->v_len = 0;
dec_states->packed = 0;
}
-static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, int varicode_in)
+static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short varicode_in)
{
int found, i;
unsigned short byte1, byte2;
- if (varicode_in) {
- s->packed |= (0x8000 >> s->v_len);
- s->n_zeros = 0;
- }
- else {
- s->n_zeros++;
+ //printf("decode_one_bit : state: %d varicode_in: %d packed: 0x%x n_zeros: %d\n",
+ // s->state, varicode_in, s->packed, s->n_zeros);
+
+ if (s->state == 0) {
+ if (!varicode_in)
+ return 0;
+ else
+ s->state = 1;
}
- s->v_len++;
- found = 0;
+ if (s->state == 1) {
+ if (varicode_in) {
+ s->packed |= (0x8000 >> s->v_len);
+ s->n_zeros = 0;
+ }
+ else {
+ s->n_zeros++;
+ }
+ s->v_len++;
+
+ found = 0;
- /* end of character code */
+ /* end of character code */
- if (s->n_zeros == 2) {
- if (s->v_len) {
- byte1 = s->packed >> 8;
- byte2 = s->packed & 0xff;
+ if (s->n_zeros == 2) {
+ if (s->v_len) {
+ byte1 = s->packed >> 8;
+ byte2 = s->packed & 0xff;
- /* run thru table but note with bit errors means we might
- not actually find a match */
+ /* run thru table but note with bit errors means we might
+ not actually find a match */
- for(i=0; i<128; i++) {
- if ((byte1 == varicode_table[2*i]) && (byte2 == varicode_table[2*i+1])) {
- found = 1;
- *single_ascii = i;
+ for(i=0; i<128; i++) {
+ if ((byte1 == varicode_table[2*i]) && (byte2 == varicode_table[2*i+1])) {
+ found = 1;
+ *single_ascii = i;
+ }
}
}
+ varicode_decode_init(s);
}
- varicode_decode_init(s);
- }
- /* code can run too long if we have a bit error */
+ /* code can run too long if we have a bit error */
+
+ if (s->v_len > VARICODE_MAX_BITS)
+ varicode_decode_init(s);
+ }
- if (s->v_len > VARICODE_MAX_BITS)
- varicode_decode_init(s);
-
return found;
}
-int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], int varicode_in[], int max_out, int n_in) {
+int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in) {
int output, n_out;
char single_ascii;
n_out = 0;
- printf("varicode_decode: n_in: %d\n", n_in);
+ //printf("varicode_decode: n_in: %d\n", n_in);
while(n_in && (n_out < max_out)) {
output = decode_one_bit(dec_states, &single_ascii, *varicode_in);
#ifdef VARICODE_UNITTEST
int main(void) {
char *ascii_in;
- int *varicode;
+ short *varicode;
int i, n_varicode_bits_out, n_ascii_chars_out, length, half;
char *ascii_out;
struct VARICODE_DEC dec_states;
length = sizeof(varicode_table)/2;
ascii_in = (char*)malloc(length);
- varicode = (int*)malloc(VARICODE_MAX_BITS*sizeof(int)*length);
+ varicode = (short*)malloc(VARICODE_MAX_BITS*sizeof(short)*length);
ascii_out = (char*)malloc(length);
+ // 1. test all Varicode codes -------------------------------------------------------------
+
for(i=0; i<length; i++)
ascii_in[i] = (char)i;
n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, length);
- printf("n_varicode_bits_out: %d\n", n_varicode_bits_out);
+ //printf("n_varicode_bits_out: %d\n", n_varicode_bits_out);
+
+ // split decode in half to test how it preseves state between calls
varicode_decode_init(&dec_states);
half = n_varicode_bits_out/2;
n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, half);
- printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
+ //printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
n_ascii_chars_out += varicode_decode(&dec_states, &ascii_out[n_ascii_chars_out],
&varicode[half], length-n_ascii_chars_out, n_varicode_bits_out - half);
- printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
+ //printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
assert(n_ascii_chars_out == length);
//}
//printf("ascii_out: %s\n", ascii_out);
+
if (memcmp(ascii_in, ascii_out, length) == 0)
- printf("Pass\n");
+ printf("Test 1 Pass\n");
else
- printf("Fail\n");
+ printf("Test 1 Fail\n");
+
+ // 2. Test some ascii with a run of zeros -----------------------------------------------------
+
+ sprintf(ascii_in, "CQ CQ CQ, this is VK5DGR");
+ assert(strlen(ascii_in) < length);
+
+ for(i=0; i<3; i++) {
+ n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, strlen(ascii_in));
+ n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, n_varicode_bits_out);
+ ascii_out[n_ascii_chars_out] = 0;
+
+ printf("ascii_out: %s\n", ascii_out);
+ if (strcmp(ascii_in, ascii_out) == 0)
+ printf("Test 2 Pass\n");
+ else
+ printf("Test 2 Fail\n");
+
+ memset(varicode, 0, sizeof(short)*20);
+ n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, 20);
+ assert(n_ascii_chars_out == 0);
+ }
free(ascii_in);
free(ascii_out);