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:
parent
6bb683a90b
commit
501ee25c7d
52
src/fsk.c
52
src/fsk.c
|
@ -35,8 +35,7 @@ fsk_plan_new(
|
|||
float sample_rate,
|
||||
float f_mark,
|
||||
float f_space,
|
||||
float filter_bw,
|
||||
unsigned int n_data_bits
|
||||
float filter_bw
|
||||
)
|
||||
{
|
||||
fsk_plan *fskp = malloc(sizeof(fsk_plan));
|
||||
|
@ -46,10 +45,6 @@ fsk_plan_new(
|
|||
fskp->sample_rate = sample_rate;
|
||||
fskp->f_mark = f_mark;
|
||||
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
|
||||
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] */
|
||||
static float
|
||||
fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
||||
int n_bits, const char *expect_bits_string,
|
||||
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_values[32];
|
||||
|
@ -208,7 +188,7 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
|||
unsigned int bit_begin_sample;
|
||||
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 */
|
||||
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
|
||||
//
|
||||
#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
|
||||
* a transient as a start bit, as often results in a single false
|
||||
* character when the mark "leader" tone begins. Require that the
|
||||
* diff between start bit and stop bit strength not be "large". */
|
||||
float s_mag = bit_sig_mags[1];
|
||||
float p_mag = bit_sig_mags[fskp->n_data_bits + 2];
|
||||
float s_mag = bit_sig_mags[1]; // start bit
|
||||
float p_mag = bit_sig_mags[n_bits-1]; // stop bit
|
||||
if ( fabs(s_mag-p_mag) > (s_mag * AVOID_TRANSIENTS) ) {
|
||||
debug_log(" avoid transient\n");
|
||||
return 0.0;
|
||||
|
@ -397,6 +381,8 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
|||
#endif /* CONFIDENCE_ALGO */
|
||||
|
||||
|
||||
// least significant bit first ... reverse the bits as we place them
|
||||
// into the bits_outp word.
|
||||
*bits_outp = 0;
|
||||
for ( bitnum=0; bitnum<n_bits; 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_step_nsamples,
|
||||
float try_confidence_search_limit,
|
||||
const char *expect_bits_string,
|
||||
unsigned int *bits_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
|
||||
|
||||
|
@ -441,7 +430,8 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
|
|||
float c;
|
||||
unsigned int bits_out = 0;
|
||||
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 ) {
|
||||
best_t = t;
|
||||
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
|
||||
#ifdef FSK_DEBUG
|
||||
unsigned char bitchar = ( best_bits >> 2 ) & 0xFF;
|
||||
debug_log("FSK_FRAME datum='%c' (0x%02x) c=%f t=%d\n",
|
||||
unsigned char bitchar = ( *bits_outp >> 2 ) & 0xFF;
|
||||
|
||||
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 : '.',
|
||||
bitchar,
|
||||
confidence, best_t);
|
||||
|
|
|
@ -32,9 +32,7 @@ struct fsk_plan {
|
|||
float f_mark;
|
||||
float f_space;
|
||||
float filter_bw;
|
||||
unsigned int n_data_bits;
|
||||
|
||||
unsigned int n_frame_bits;
|
||||
#ifdef USE_FFT
|
||||
int fftsize;
|
||||
unsigned int nbands;
|
||||
|
@ -53,8 +51,7 @@ fsk_plan_new(
|
|||
float sample_rate,
|
||||
float f_mark,
|
||||
float f_space,
|
||||
float filter_bw,
|
||||
unsigned int n_data_bits
|
||||
float filter_bw
|
||||
);
|
||||
|
||||
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_step_nsamples,
|
||||
float try_confidence_search_limit,
|
||||
const char *expect_bits_string,
|
||||
unsigned int *bits_outp,
|
||||
unsigned int *frame_start_outp
|
||||
);
|
||||
|
|
|
@ -198,22 +198,23 @@ report_no_carrier( fsk_plan *fskp,
|
|||
float bfsk_data_rate,
|
||||
float nsamples_per_bit,
|
||||
unsigned int nframes_decoded,
|
||||
unsigned long long nbits_decoded,
|
||||
size_t carrier_nsamples,
|
||||
float confidence_total )
|
||||
{
|
||||
unsigned long long nbits_total = nframes_decoded * (fskp->n_data_bits+2);
|
||||
#if 0
|
||||
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, "nsamples_per_bit=%f\n", nsamples_per_bit);
|
||||
#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",
|
||||
nframes_decoded,
|
||||
confidence_total / nframes_decoded,
|
||||
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");
|
||||
} else {
|
||||
float throughput_skew = (throughput_rate - bfsk_data_rate)
|
||||
|
@ -696,8 +697,7 @@ main( int argc, char*argv[] )
|
|||
*/
|
||||
|
||||
fsk_plan *fskp;
|
||||
fskp = fsk_plan_new(sample_rate, bfsk_mark_f, bfsk_space_f,
|
||||
band_width, bfsk_n_data_bits);
|
||||
fskp = fsk_plan_new(sample_rate, bfsk_mark_f, bfsk_space_f, band_width);
|
||||
if ( !fskp ) {
|
||||
fprintf(stderr, "fsk_plan_new() failed\n");
|
||||
return 1;
|
||||
|
@ -728,6 +728,7 @@ main( int argc, char*argv[] )
|
|||
int carrier = 0;
|
||||
float confidence_total = 0;
|
||||
unsigned int nframes_decoded = 0;
|
||||
unsigned long long nbits_decoded = 0;
|
||||
size_t carrier_nsamples = 0;
|
||||
|
||||
unsigned int noconfidence = 0;
|
||||
|
@ -839,9 +840,38 @@ main( int argc, char*argv[] )
|
|||
|
||||
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;
|
||||
|
||||
// try_max_nsamples = nsamples_per_bit + nsamples_overscan;
|
||||
|
@ -877,20 +907,18 @@ main( int argc, char*argv[] )
|
|||
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_max_nsamples,
|
||||
try_step_nsamples,
|
||||
try_confidence_search_limit,
|
||||
expect_bits_string,
|
||||
&bits,
|
||||
&frame_start_sample
|
||||
);
|
||||
|
||||
// FIXME: hardcoded chop off framing bits
|
||||
if ( fskp->n_data_bits == 5 )
|
||||
bits = ( bits >> 2 ) & 0x1F;
|
||||
else
|
||||
bits = ( bits >> 2 ) & 0xFF;
|
||||
// chop off framing bits
|
||||
bits = ( bits >> frame_bits_shift ) & frame_bits_mask;
|
||||
|
||||
#define FSK_MAX_NOCONFIDENCE_BITS 20
|
||||
|
||||
|
@ -903,12 +931,13 @@ main( int argc, char*argv[] )
|
|||
if ( carrier ) {
|
||||
if ( !quiet_mode )
|
||||
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 = 0;
|
||||
carrier_nsamples = 0;
|
||||
confidence_total = 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
|
||||
carrier_nsamples += nsamples_per_bit * (fskp->n_data_bits + 2);
|
||||
carrier_nsamples += frame_nsamples;
|
||||
|
||||
if ( carrier ) {
|
||||
|
||||
|
@ -944,27 +973,21 @@ main( int argc, char*argv[] )
|
|||
bfsk_framebits_decode(0, 0, 0); /* reset the frame processor */
|
||||
}
|
||||
|
||||
|
||||
confidence_total += confidence;
|
||||
nframes_decoded++;
|
||||
nbits_decoded += frame_n_bits;
|
||||
noconfidence = 0;
|
||||
|
||||
/* Advance the sample stream forward past the decoded frame
|
||||
* but not past the stop bit, since we want it to appear as
|
||||
* the prev_stop bit of the next frame, so ...
|
||||
*
|
||||
* advance = 1 prev_stop + 1 start + N data bits == n_data_bits+2
|
||||
*
|
||||
* 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;
|
||||
// Advance the sample stream forward past the junk before the
|
||||
// frame starts (frame_start_sample), and then past decoded frame
|
||||
// (see also NOTE about frame_n_bits and expect_n_bits)...
|
||||
// But actually advance just a bit less than that to allow
|
||||
// for tracking slightly fast signals, hence - nsamples_overscan.
|
||||
advance = frame_start_sample + frame_nsamples - nsamples_overscan;
|
||||
|
||||
debug_log("@ nsamples_per_bit=%.3f n_data_bits=%u "
|
||||
" frame_start=%u advance=%u\n",
|
||||
nsamples_per_bit, fskp->n_data_bits,
|
||||
nsamples_per_bit, bfsk_n_data_bits,
|
||||
frame_start_sample, advance);
|
||||
|
||||
|
||||
|
@ -998,7 +1021,7 @@ main( int argc, char*argv[] )
|
|||
if ( carrier ) {
|
||||
if ( !quiet_mode )
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue