fsk: expect_bits_string param, no start/stop bits required

fsk_find_frame() takes expect_bits_string  (e.g. "10dddddddd1"), as a
parameter supplied by the caller allowing for encodings which don't use
any start/stop bits (e.g. just "dddddddd").
This commit is contained in:
Kamal Mostafa 2012-08-24 13:20:20 -07:00
parent 6bb683a90b
commit 501ee25c7d
3 changed files with 79 additions and 64 deletions

View File

@ -35,8 +35,7 @@ fsk_plan_new(
float sample_rate, float sample_rate,
float f_mark, float f_mark,
float f_space, float f_space,
float filter_bw, float filter_bw
unsigned int n_data_bits
) )
{ {
fsk_plan *fskp = malloc(sizeof(fsk_plan)); fsk_plan *fskp = malloc(sizeof(fsk_plan));
@ -46,10 +45,6 @@ fsk_plan_new(
fskp->sample_rate = sample_rate; fskp->sample_rate = sample_rate;
fskp->f_mark = f_mark; fskp->f_mark = f_mark;
fskp->f_space = f_space; fskp->f_space = f_space;
fskp->n_data_bits = n_data_bits;
/* 1 prev_stop + n_data_bits + 1 start + 1 stop == n_data_bits + 3 */
fskp->n_frame_bits = fskp->n_data_bits + 3;
#ifdef USE_FFT #ifdef USE_FFT
fskp->band_width = filter_bw; fskp->band_width = filter_bw;
@ -182,24 +177,9 @@ fsk_bit_analyze( fsk_plan *fskp, float *samples, unsigned int bit_nsamples,
/* returns confidence value [0.0 to 1.0] */ /* returns confidence value [0.0 to 1.0] */
static float static float
fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit, fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
int n_bits, const char *expect_bits_string,
unsigned int *bits_outp ) unsigned int *bits_outp )
{ {
int n_bits = fskp->n_frame_bits;
// char *expect_bit_string = "10dddddddd1";
char expect_bit_string[32];
memset(expect_bit_string, 'd', 32);
expect_bit_string[0] = '1';
expect_bit_string[1] = '0';
expect_bit_string[fskp->n_data_bits + 2] = '1';
// example...
// 0123456789A
// isddddddddp i == idle bit (a.k.a. prev_stop bit)
// s == start bit
// d == data bits
// p == stop bit
// MSddddddddM <-- expected mark/space framing pattern
unsigned int bit_nsamples = (float)(samples_per_bit + 0.5); unsigned int bit_nsamples = (float)(samples_per_bit + 0.5);
unsigned int bit_values[32]; unsigned int bit_values[32];
@ -208,7 +188,7 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
unsigned int bit_begin_sample; unsigned int bit_begin_sample;
int bitnum; int bitnum;
char *expect_bits = expect_bit_string; const char *expect_bits = expect_bits_string;
/* pass #1 - process and check only the "required" (1/0) expect_bits */ /* pass #1 - process and check only the "required" (1/0) expect_bits */
for ( bitnum=0; bitnum<n_bits; bitnum++ ) { for ( bitnum=0; bitnum<n_bits; bitnum++ ) {
@ -242,12 +222,16 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
#define AVOID_TRANSIENTS 0.7 #define AVOID_TRANSIENTS 0.7
// //
#ifdef AVOID_TRANSIENTS #ifdef AVOID_TRANSIENTS
// FIXME: fsk_frame_analyze shouldn't care about start/stop bits,
// and this really is only correct for "10dd..dd1" format frames anyway:
// FIXME: this is totally defective, if the checked bits weren't
// even calculated in pass #1 (e.g. if there are no pass #1 expect bits).
/* Compare strength of stop bit and start bit, to avoid detecting /* Compare strength of stop bit and start bit, to avoid detecting
* a transient as a start bit, as often results in a single false * a transient as a start bit, as often results in a single false
* character when the mark "leader" tone begins. Require that the * character when the mark "leader" tone begins. Require that the
* diff between start bit and stop bit strength not be "large". */ * diff between start bit and stop bit strength not be "large". */
float s_mag = bit_sig_mags[1]; float s_mag = bit_sig_mags[1]; // start bit
float p_mag = bit_sig_mags[fskp->n_data_bits + 2]; float p_mag = bit_sig_mags[n_bits-1]; // stop bit
if ( fabs(s_mag-p_mag) > (s_mag * AVOID_TRANSIENTS) ) { if ( fabs(s_mag-p_mag) > (s_mag * AVOID_TRANSIENTS) ) {
debug_log(" avoid transient\n"); debug_log(" avoid transient\n");
return 0.0; return 0.0;
@ -397,6 +381,8 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
#endif /* CONFIDENCE_ALGO */ #endif /* CONFIDENCE_ALGO */
// least significant bit first ... reverse the bits as we place them
// into the bits_outp word.
*bits_outp = 0; *bits_outp = 0;
for ( bitnum=0; bitnum<n_bits; bitnum++ ) for ( bitnum=0; bitnum<n_bits; bitnum++ )
*bits_outp |= bit_values[bitnum] << bitnum; *bits_outp |= bit_values[bitnum] << bitnum;
@ -413,11 +399,14 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
unsigned int try_max_nsamples, unsigned int try_max_nsamples,
unsigned int try_step_nsamples, unsigned int try_step_nsamples,
float try_confidence_search_limit, float try_confidence_search_limit,
const char *expect_bits_string,
unsigned int *bits_outp, unsigned int *bits_outp,
unsigned int *frame_start_outp unsigned int *frame_start_outp
) )
{ {
float samples_per_bit = (float)frame_nsamples / fskp->n_frame_bits; int expect_n_bits = strlen(expect_bits_string);
float samples_per_bit = (float)frame_nsamples / expect_n_bits;
// try_step_nsamples = 1; // pedantic TEST // try_step_nsamples = 1; // pedantic TEST
@ -441,7 +430,8 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
float c; float c;
unsigned int bits_out = 0; unsigned int bits_out = 0;
debug_log("try fsk_frame_analyze at t=%d\n", t); debug_log("try fsk_frame_analyze at t=%d\n", t);
c = fsk_frame_analyze(fskp, samples+t, samples_per_bit, &bits_out); c = fsk_frame_analyze(fskp, samples+t, samples_per_bit,
expect_n_bits, expect_bits_string, &bits_out);
if ( best_c < c ) { if ( best_c < c ) {
best_t = t; best_t = t;
best_c = c; best_c = c;
@ -463,8 +453,12 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
// FIXME? hardcoded chop off framing bits for debug // FIXME? hardcoded chop off framing bits for debug
#ifdef FSK_DEBUG #ifdef FSK_DEBUG
unsigned char bitchar = ( best_bits >> 2 ) & 0xFF; unsigned char bitchar = ( *bits_outp >> 2 ) & 0xFF;
debug_log("FSK_FRAME datum='%c' (0x%02x) c=%f t=%d\n",
debug_log("FSK_FRAME bits='");
for ( j=0; j<expect_n_bits; j++ )
debug_log("%c", ( *bits_outp >> j ) & 1 ? '1' : '0' );
debug_log("' datum='%c' (0x%02x) c=%f t=%d\n",
isprint(bitchar)||isspace(bitchar) ? bitchar : '.', isprint(bitchar)||isspace(bitchar) ? bitchar : '.',
bitchar, bitchar,
confidence, best_t); confidence, best_t);

View File

@ -32,9 +32,7 @@ struct fsk_plan {
float f_mark; float f_mark;
float f_space; float f_space;
float filter_bw; float filter_bw;
unsigned int n_data_bits;
unsigned int n_frame_bits;
#ifdef USE_FFT #ifdef USE_FFT
int fftsize; int fftsize;
unsigned int nbands; unsigned int nbands;
@ -53,8 +51,7 @@ fsk_plan_new(
float sample_rate, float sample_rate,
float f_mark, float f_mark,
float f_space, float f_space,
float filter_bw, float filter_bw
unsigned int n_data_bits
); );
void void
@ -67,6 +64,7 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
unsigned int try_max_nsamples, unsigned int try_max_nsamples,
unsigned int try_step_nsamples, unsigned int try_step_nsamples,
float try_confidence_search_limit, float try_confidence_search_limit,
const char *expect_bits_string,
unsigned int *bits_outp, unsigned int *bits_outp,
unsigned int *frame_start_outp unsigned int *frame_start_outp
); );

View File

@ -198,22 +198,23 @@ report_no_carrier( fsk_plan *fskp,
float bfsk_data_rate, float bfsk_data_rate,
float nsamples_per_bit, float nsamples_per_bit,
unsigned int nframes_decoded, unsigned int nframes_decoded,
unsigned long long nbits_decoded,
size_t carrier_nsamples, size_t carrier_nsamples,
float confidence_total ) float confidence_total )
{ {
unsigned long long nbits_total = nframes_decoded * (fskp->n_data_bits+2);
#if 0 #if 0
fprintf(stderr, "nframes_decoded=%u\n", nframes_decoded); fprintf(stderr, "nframes_decoded=%u\n", nframes_decoded);
fprintf(stderr, "nbits_total=%llu\n", nbits_total); fprintf(stderr, "nbits_decoded=%llu\n", nbits_decoded);
fprintf(stderr, "carrier_nsamples=%lu\n", carrier_nsamples); fprintf(stderr, "carrier_nsamples=%lu\n", carrier_nsamples);
fprintf(stderr, "nsamples_per_bit=%f\n", nsamples_per_bit); fprintf(stderr, "nsamples_per_bit=%f\n", nsamples_per_bit);
#endif #endif
float throughput_rate = nbits_total * sample_rate / (float)carrier_nsamples; float throughput_rate =
nbits_decoded * sample_rate / (float)carrier_nsamples;
fprintf(stderr, "### NOCARRIER ndata=%u confidence=%.3f throughput=%.2f", fprintf(stderr, "### NOCARRIER ndata=%u confidence=%.3f throughput=%.2f",
nframes_decoded, nframes_decoded,
confidence_total / nframes_decoded, confidence_total / nframes_decoded,
throughput_rate); throughput_rate);
if ( (size_t)(nbits_total * nsamples_per_bit + 0.5) == carrier_nsamples ) { if ( (size_t)(nbits_decoded * nsamples_per_bit + 0.5) == carrier_nsamples ) {
fprintf(stderr, " (rate perfect) ###\n"); fprintf(stderr, " (rate perfect) ###\n");
} else { } else {
float throughput_skew = (throughput_rate - bfsk_data_rate) float throughput_skew = (throughput_rate - bfsk_data_rate)
@ -696,8 +697,7 @@ main( int argc, char*argv[] )
*/ */
fsk_plan *fskp; fsk_plan *fskp;
fskp = fsk_plan_new(sample_rate, bfsk_mark_f, bfsk_space_f, fskp = fsk_plan_new(sample_rate, bfsk_mark_f, bfsk_space_f, band_width);
band_width, bfsk_n_data_bits);
if ( !fskp ) { if ( !fskp ) {
fprintf(stderr, "fsk_plan_new() failed\n"); fprintf(stderr, "fsk_plan_new() failed\n");
return 1; return 1;
@ -728,6 +728,7 @@ main( int argc, char*argv[] )
int carrier = 0; int carrier = 0;
float confidence_total = 0; float confidence_total = 0;
unsigned int nframes_decoded = 0; unsigned int nframes_decoded = 0;
unsigned long long nbits_decoded = 0;
size_t carrier_nsamples = 0; size_t carrier_nsamples = 0;
unsigned int noconfidence = 0; unsigned int noconfidence = 0;
@ -839,9 +840,38 @@ main( int argc, char*argv[] )
debug_log( "--------------------------\n"); debug_log( "--------------------------\n");
unsigned int frame_nsamples = nsamples_per_bit * fskp->n_frame_bits; // example expect_bits_string
// 0123456789A
// isddddddddp i == idle bit (a.k.a. prev_stop bit)
// s == start bit d == data bits p == stop bit
// ebs = "10dddddddd1" <-- expected mark/space framing pattern
//
// NOTE! expect_n_bits ends up being (frame_n_bits+1), because
// we expect the prev_stop bit in addition to this frame's own
// (start + n_data_bits + stop) bits. But for each decoded frame,
// we will advance just frame_n_bits worth of samples, leaving us
// pointing at our stop bit -- it becomes the next frame's prev_stop.
//
// prev_stop--v
// start--v v--stop
// char *expect_bits_string = "10dddddddd1";
//
char expect_bits_string[33] = "10dddddddddddddddddddddddddddddd";
expect_bits_string[bfsk_n_data_bits + 2] = '1';
expect_bits_string[bfsk_n_data_bits + 3] = 0;
unsigned int frame_n_bits = bfsk_n_data_bits + 2;
unsigned int frame_bits_shift = 2; // prev_stop + start
// FIXME - weird hardcode:
unsigned int frame_bits_mask = 0xFF;
if ( bfsk_n_data_bits == 5 )
frame_bits_mask = 0x1F;
if ( samples_nvalid < frame_nsamples ) unsigned int frame_nsamples = nsamples_per_bit * frame_n_bits;
unsigned int expect_n_bits = strlen(expect_bits_string);
unsigned int expect_nsamples = nsamples_per_bit * expect_n_bits;
if ( samples_nvalid < expect_nsamples )
break; break;
// try_max_nsamples = nsamples_per_bit + nsamples_overscan; // try_max_nsamples = nsamples_per_bit + nsamples_overscan;
@ -877,20 +907,18 @@ main( int argc, char*argv[] )
try_confidence_search_limit = INFINITY; try_confidence_search_limit = INFINITY;
} }
confidence = fsk_find_frame(fskp, samplebuf, frame_nsamples, confidence = fsk_find_frame(fskp, samplebuf, expect_nsamples,
try_first_sample, try_first_sample,
try_max_nsamples, try_max_nsamples,
try_step_nsamples, try_step_nsamples,
try_confidence_search_limit, try_confidence_search_limit,
expect_bits_string,
&bits, &bits,
&frame_start_sample &frame_start_sample
); );
// FIXME: hardcoded chop off framing bits // chop off framing bits
if ( fskp->n_data_bits == 5 ) bits = ( bits >> frame_bits_shift ) & frame_bits_mask;
bits = ( bits >> 2 ) & 0x1F;
else
bits = ( bits >> 2 ) & 0xFF;
#define FSK_MAX_NOCONFIDENCE_BITS 20 #define FSK_MAX_NOCONFIDENCE_BITS 20
@ -903,12 +931,13 @@ main( int argc, char*argv[] )
if ( carrier ) { if ( carrier ) {
if ( !quiet_mode ) if ( !quiet_mode )
report_no_carrier(fskp, sample_rate, bfsk_data_rate, report_no_carrier(fskp, sample_rate, bfsk_data_rate,
nsamples_per_bit, nframes_decoded, nsamples_per_bit, nframes_decoded, nbits_decoded,
carrier_nsamples, confidence_total); carrier_nsamples, confidence_total);
carrier = 0; carrier = 0;
carrier_nsamples = 0; carrier_nsamples = 0;
confidence_total = 0; confidence_total = 0;
nframes_decoded = 0; nframes_decoded = 0;
nbits_decoded = 0;
} }
} }
@ -921,7 +950,7 @@ main( int argc, char*argv[] )
} }
// Add a frame's worth of samples to the sample count // Add a frame's worth of samples to the sample count
carrier_nsamples += nsamples_per_bit * (fskp->n_data_bits + 2); carrier_nsamples += frame_nsamples;
if ( carrier ) { if ( carrier ) {
@ -944,27 +973,21 @@ main( int argc, char*argv[] )
bfsk_framebits_decode(0, 0, 0); /* reset the frame processor */ bfsk_framebits_decode(0, 0, 0); /* reset the frame processor */
} }
confidence_total += confidence; confidence_total += confidence;
nframes_decoded++; nframes_decoded++;
nbits_decoded += frame_n_bits;
noconfidence = 0; noconfidence = 0;
/* Advance the sample stream forward past the decoded frame // Advance the sample stream forward past the junk before the
* but not past the stop bit, since we want it to appear as // frame starts (frame_start_sample), and then past decoded frame
* the prev_stop bit of the next frame, so ... // (see also NOTE about frame_n_bits and expect_n_bits)...
* // But actually advance just a bit less than that to allow
* advance = 1 prev_stop + 1 start + N data bits == n_data_bits+2 // for tracking slightly fast signals, hence - nsamples_overscan.
* advance = frame_start_sample + frame_nsamples - nsamples_overscan;
* but actually advance just a bit less than that to allow
* for tracking slightly fast signals, hence - nsamples_overscan.
*/
advance = frame_start_sample
+ nsamples_per_bit * (float)(fskp->n_data_bits + 2)
- nsamples_overscan;
debug_log("@ nsamples_per_bit=%.3f n_data_bits=%u " debug_log("@ nsamples_per_bit=%.3f n_data_bits=%u "
" frame_start=%u advance=%u\n", " frame_start=%u advance=%u\n",
nsamples_per_bit, fskp->n_data_bits, nsamples_per_bit, bfsk_n_data_bits,
frame_start_sample, advance); frame_start_sample, advance);
@ -998,7 +1021,7 @@ main( int argc, char*argv[] )
if ( carrier ) { if ( carrier ) {
if ( !quiet_mode ) if ( !quiet_mode )
report_no_carrier(fskp, sample_rate, bfsk_data_rate, report_no_carrier(fskp, sample_rate, bfsk_data_rate,
nsamples_per_bit, nframes_decoded, nsamples_per_bit, nframes_decoded, nbits_decoded,
carrier_nsamples, confidence_total); carrier_nsamples, confidence_total);
} }