fsk expect_bits
This commit is contained in:
parent
613f4ec5bd
commit
fd0546d80d
140
src/fsk.c
140
src/fsk.c
|
@ -24,6 +24,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "fsk.h"
|
#include "fsk.h"
|
||||||
|
|
||||||
|
@ -136,37 +137,20 @@ fsk_bit_analyze( fsk_plan *fskp, float *samples, unsigned int bit_nsamples,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* returns confidence value [0.0 to 1.0] */
|
|
||||||
static void
|
|
||||||
fsk_bits_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
|
||||||
unsigned int *bits_outp, float *bit_strengths_outp )
|
|
||||||
{
|
|
||||||
unsigned int bit_nsamples = (float)(samples_per_bit + 0.5);
|
|
||||||
unsigned int nbits = fskp->n_data_bits;
|
|
||||||
|
|
||||||
unsigned int bits_out = 0;
|
|
||||||
int i;
|
|
||||||
for ( i=0; i<nbits; i++ ) {
|
|
||||||
unsigned int begin_databit = (float)(samples_per_bit * i + 0.5);
|
|
||||||
unsigned int bit;
|
|
||||||
debug_log("\t\tdata begin_data_bit=%u ", begin_databit);
|
|
||||||
fsk_bit_analyze(fskp, samples+begin_databit, bit_nsamples,
|
|
||||||
&bit, &bit_strengths_outp[i]);
|
|
||||||
bits_out |= bit << i;
|
|
||||||
}
|
|
||||||
*bits_outp = bits_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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,
|
||||||
unsigned int *bits_outp )
|
unsigned int *bits_outp )
|
||||||
{
|
{
|
||||||
float v = 0;
|
int n_bits = fskp->n_frame_bits;
|
||||||
|
// char *expect_bit_string = "10dddddddd1";
|
||||||
unsigned int bit_nsamples = (float)(samples_per_bit + 0.5);
|
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
|
// 0123456789A
|
||||||
// isddddddddp i == idle bit (a.k.a. prev_stop bit)
|
// isddddddddp i == idle bit (a.k.a. prev_stop bit)
|
||||||
// s == start bit
|
// s == start bit
|
||||||
|
@ -174,32 +158,37 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
||||||
// p == stop bit
|
// p == stop bit
|
||||||
// MSddddddddM <-- expected mark/space framing pattern
|
// MSddddddddM <-- expected mark/space framing pattern
|
||||||
|
|
||||||
unsigned int begin_idlebit = 0;
|
unsigned int bit_nsamples = (float)(samples_per_bit + 0.5);
|
||||||
unsigned int begin_startbit = (float)(samples_per_bit * 1 + 0.5);
|
|
||||||
unsigned int begin_databits = (float)(samples_per_bit * 2 + 0.5);
|
|
||||||
unsigned int begin_stopbit = (float)(samples_per_bit * (fskp->n_data_bits+2) + 0.5);
|
|
||||||
|
|
||||||
/*
|
unsigned int bit_values[32];
|
||||||
* To optimize performance for a streaming scenario, check start bit first,
|
float bit_strengths[32];
|
||||||
* then stop, then idle bits... we're "searching" for start, must validate
|
unsigned int bit_begin_sample;
|
||||||
* stop, and finally we want to to collect idle's v value. After all that
|
int bitnum;
|
||||||
* collect the n_data_bits
|
|
||||||
*/
|
|
||||||
|
|
||||||
float s_str, p_str, i_str;
|
float v = 0;
|
||||||
unsigned int bit;
|
|
||||||
|
|
||||||
debug_log("\t\tstart ");
|
char *expect_bits = expect_bit_string;
|
||||||
fsk_bit_analyze(fskp, samples+begin_startbit, bit_nsamples, &bit, &s_str);
|
|
||||||
if ( bit != 0 )
|
|
||||||
return 0.0;
|
|
||||||
v += s_str;
|
|
||||||
|
|
||||||
debug_log("\t\tstop ");
|
/* pass #1 - process and check only the "required" (1/0) expect_bits */
|
||||||
fsk_bit_analyze(fskp, samples+begin_stopbit, bit_nsamples, &bit, &p_str);
|
for ( bitnum=0; bitnum<n_bits; bitnum++ ) {
|
||||||
if ( bit != 1 )
|
if ( expect_bits[bitnum] == 'd' )
|
||||||
return 0.0;
|
continue;
|
||||||
v += p_str;
|
assert( expect_bits[bitnum] == '1' || expect_bits[bitnum] == '0' );
|
||||||
|
|
||||||
|
bit_begin_sample = (float)(samples_per_bit * bitnum + 0.5);
|
||||||
|
debug_log( " bit# %2u @ %u: ", bitnum, bit_begin_sample);
|
||||||
|
fsk_bit_analyze(fskp, samples+bit_begin_sample, bit_nsamples,
|
||||||
|
&bit_values[bitnum], &bit_strengths[bitnum]);
|
||||||
|
|
||||||
|
if ( (expect_bits[bitnum] - '0') != bit_values[bitnum] )
|
||||||
|
return 0.0; /* does not match expected; abort frame analysis. */
|
||||||
|
|
||||||
|
v += bit_strengths[bitnum];
|
||||||
|
}
|
||||||
|
|
||||||
|
// float i_str = bit_strengths[0];
|
||||||
|
float s_str = bit_strengths[1];
|
||||||
|
float p_str = bit_strengths[fskp->n_data_bits + 2];
|
||||||
|
|
||||||
#define AVOID_TRANSIENTS 0.7
|
#define AVOID_TRANSIENTS 0.7
|
||||||
#ifdef AVOID_TRANSIENTS
|
#ifdef AVOID_TRANSIENTS
|
||||||
|
@ -208,32 +197,31 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
||||||
* 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". */
|
||||||
if ( fabs(s_str-p_str) > (s_str * AVOID_TRANSIENTS) ) {
|
if ( fabs(s_str-p_str) > (s_str * AVOID_TRANSIENTS) ) {
|
||||||
debug_log("avoid_transient\n");
|
debug_log(" avoid transient\n");
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
debug_log("\t\tidle ");
|
/* pass #2 - process only the dontcare ('d') expect_bits */
|
||||||
fsk_bit_analyze(fskp, samples+begin_idlebit, bit_nsamples, &bit, &i_str);
|
for ( bitnum=0; bitnum<n_bits; bitnum++ ) {
|
||||||
if ( bit != 1 )
|
if ( expect_bits[bitnum] != 'd' )
|
||||||
return 0.0;
|
continue;
|
||||||
v += i_str;
|
bit_begin_sample = (float)(samples_per_bit * bitnum + 0.5);
|
||||||
|
debug_log( " bit# %2u @ %u: ", bitnum, bit_begin_sample);
|
||||||
|
fsk_bit_analyze(fskp, samples+bit_begin_sample, bit_nsamples,
|
||||||
|
&bit_values[bitnum], &bit_strengths[bitnum]);
|
||||||
|
v += bit_strengths[bitnum];
|
||||||
|
}
|
||||||
|
|
||||||
// Analyze the actual data payload bits
|
/* compute average bit strength 'v' */
|
||||||
float databit_strengths[32];
|
v /= n_bits;
|
||||||
fsk_bits_analyze(fskp, samples+begin_databits, samples_per_bit,
|
|
||||||
bits_outp, databit_strengths);
|
|
||||||
|
|
||||||
// compute average bit strength 'v'
|
|
||||||
int i;
|
|
||||||
for ( i=0; i<fskp->n_data_bits; i++ )
|
|
||||||
v += databit_strengths[i];
|
|
||||||
v /= (fskp->n_data_bits + 3);
|
|
||||||
|
|
||||||
#define FSK_MIN_STRENGTH 0.005
|
#define FSK_MIN_STRENGTH 0.005
|
||||||
if ( v < FSK_MIN_STRENGTH )
|
if ( v < FSK_MIN_STRENGTH )
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
#define CONFIDENCE_ALGO 2
|
#define CONFIDENCE_ALGO 2
|
||||||
|
|
||||||
#if ( CONFIDENCE_ALGO == 1 )
|
#if ( CONFIDENCE_ALGO == 1 )
|
||||||
|
@ -249,15 +237,19 @@ fsk_frame_analyze( fsk_plan *fskp, float *samples, float samples_per_bit,
|
||||||
#elif ( CONFIDENCE_ALGO == 2 )
|
#elif ( CONFIDENCE_ALGO == 2 )
|
||||||
|
|
||||||
float confidence = 0;
|
float confidence = 0;
|
||||||
confidence += i_str;
|
for ( i=0; i<n_bits; i++ )
|
||||||
confidence += s_str;
|
confidence += bit_strengths[i];
|
||||||
confidence += p_str;
|
confidence /= n_bits;
|
||||||
for ( i=0; i<fskp->n_data_bits; i++ )
|
|
||||||
confidence += databit_strengths[i];
|
|
||||||
confidence /= (fskp->n_data_bits + 3);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
*bits_outp = 0;
|
||||||
|
// FIXME: databits at hardcoded offset of +2
|
||||||
|
// for ( i=0; i<fskp->n_data_bits; i++ )
|
||||||
|
// *bits_outp |= bit_values[i+2] << i;
|
||||||
|
for ( i=0; i<n_bits; i++ )
|
||||||
|
*bits_outp |= bit_values[i] << i;
|
||||||
|
|
||||||
debug_log(" frame confidence (algo #%u) = %f\n",
|
debug_log(" frame confidence (algo #%u) = %f\n",
|
||||||
CONFIDENCE_ALGO, confidence);
|
CONFIDENCE_ALGO, confidence);
|
||||||
return confidence;
|
return confidence;
|
||||||
|
@ -296,16 +288,18 @@ fsk_find_frame( fsk_plan *fskp, float *samples, unsigned int frame_nsamples,
|
||||||
|
|
||||||
float confidence = best_c;
|
float confidence = best_c;
|
||||||
|
|
||||||
|
// 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",
|
debug_log("FSK_FRAME datum='%c' (0x%02x) c=%f t=%d\n",
|
||||||
isprint(best_bits)||isspace(best_bits) ? best_bits : '.',
|
isprint(bitchar)||isspace(bitchar) ? bitchar : '.',
|
||||||
best_bits,
|
bitchar,
|
||||||
confidence, best_t);
|
confidence, best_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
return confidence;
|
return confidence;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <assert.h> // FIXME
|
|
||||||
|
|
||||||
// #define FSK_AUTODETECT_MIN_FREQ 600
|
// #define FSK_AUTODETECT_MIN_FREQ 600
|
||||||
// #define FSK_AUTODETECT_MAX_FREQ 5000
|
// #define FSK_AUTODETECT_MAX_FREQ 5000
|
||||||
|
|
||||||
|
|
|
@ -595,6 +595,12 @@ main( int argc, char*argv[] )
|
||||||
&frame_start_sample
|
&frame_start_sample
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// FIXME: hardcoded chop off framing bits
|
||||||
|
if ( fskp->n_data_bits == 5 )
|
||||||
|
bits = ( bits >> 2 ) & 0x1F;
|
||||||
|
else
|
||||||
|
bits = ( bits >> 2 ) & 0xFF;
|
||||||
|
|
||||||
#define FSK_MIN_CONFIDENCE 0.05
|
#define FSK_MIN_CONFIDENCE 0.05
|
||||||
#define FSK_MAX_NOCONFIDENCE_BITS 20
|
#define FSK_MAX_NOCONFIDENCE_BITS 20
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue