Add attenuation histogram output ()

This commit is contained in:
Christian W. Zuckschwerdt 2020-07-04 21:58:33 +02:00 committed by GitHub
commit 1f1468702c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 174 additions and 10 deletions

View file

@ -44,6 +44,46 @@ void magnitude_true_cs16(int16_t const *iq_buf, uint16_t *y_buf, uint32_t len);
#define DB_TO_AMP_F(x) ((int)(0.5 + _exp10f((x) / 10.0f)))
#define DB_TO_MAG_F(x) ((int)(0.5 + _exp10f((x) / 20.0f)))
/*
tabulated magnitude and amplitude values:
10^(( 3 + 84.2884) / 20) = 23143 10^(( 3 + 42.1442) / 10) = 32690
10^(( 2 + 84.2884) / 20) = 20626 10^(( 2 + 42.1442) / 10) = 25967
10^(( 1 + 84.2884) / 20) = 18383 10^(( 1 + 42.1442) / 10) = 20626
10^(( 0 + 84.2884) / 20) = 16384 10^(( 0 + 42.1442) / 10) = 16384
10^((-1 + 84.2884) / 20) = 14602 10^((-1 + 42.1442) / 10) = 13014
10^((-2 + 84.2884) / 20) = 13014 10^((-2 + 42.1442) / 10) = 10338
10^((-3 + 84.2884) / 20) = 11599 10^((-3 + 42.1442) / 10) = 8211
10^((-4 + 84.2884) / 20) = 10338 10^((-4 + 42.1442) / 10) = 6523
10^((-5 + 84.2884) / 20) = 9213 10^((-5 + 42.1442) / 10) = 5181
10^((-6 + 84.2884) / 20) = 8211 10^((-6 + 42.1442) / 10) = 4115
10^((-7 + 84.2884) / 20) = 7318 10^((-7 + 42.1442) / 10) = 3269
10^((-8 + 84.2884) / 20) = 6523 10^((-8 + 42.1442) / 10) = 2597
10^((-9 + 84.2884) / 20) = 5813 10^((-9 + 42.1442) / 10) = 2063
10^((-10 + 84.2884) / 20) = 5181 10^((-10 + 42.1442) / 10) = 1638
10^((-11 + 84.2884) / 20) = 4618 10^((-11 + 42.1442) / 10) = 1301
10^((-12 + 84.2884) / 20) = 4115 10^((-12 + 42.1442) / 10) = 1034
10^((-13 + 84.2884) / 20) = 3668 10^((-13 + 42.1442) / 10) = 821
10^((-14 + 84.2884) / 20) = 3269 10^((-14 + 42.1442) / 10) = 652
10^((-15 + 84.2884) / 20) = 2914 10^((-15 + 42.1442) / 10) = 518
10^((-16 + 84.2884) / 20) = 2597 10^((-16 + 42.1442) / 10) = 412
10^((-17 + 84.2884) / 20) = 2314 10^((-17 + 42.1442) / 10) = 327
10^((-18 + 84.2884) / 20) = 2063 10^((-18 + 42.1442) / 10) = 260
10^((-19 + 84.2884) / 20) = 1838 10^((-19 + 42.1442) / 10) = 206
10^((-20 + 84.2884) / 20) = 1638 10^((-20 + 42.1442) / 10) = 164
10^((-21 + 84.2884) / 20) = 1460 10^((-21 + 42.1442) / 10) = 130
10^((-22 + 84.2884) / 20) = 1301 10^((-22 + 42.1442) / 10) = 103
10^((-23 + 84.2884) / 20) = 1160 10^((-23 + 42.1442) / 10) = 82
10^((-24 + 84.2884) / 20) = 1034 10^((-24 + 42.1442) / 10) = 65
10^((-25 + 84.2884) / 20) = 921 10^((-25 + 42.1442) / 10) = 52
10^((-26 + 84.2884) / 20) = 821 10^((-26 + 42.1442) / 10) = 41
10^((-27 + 84.2884) / 20) = 732 10^((-27 + 42.1442) / 10) = 33
10^((-28 + 84.2884) / 20) = 652 10^((-28 + 42.1442) / 10) = 26
10^((-29 + 84.2884) / 20) = 581 10^((-29 + 42.1442) / 10) = 21
10^((-30 + 84.2884) / 20) = 518 10^((-30 + 42.1442) / 10) = 16
10^((-31 + 84.2884) / 20) = 462 10^((-31 + 42.1442) / 10) = 13
10^((-32 + 84.2884) / 20) = 412 10^((-32 + 42.1442) / 10) = 10
*/
#define FILTER_ORDER 1
/// Filter state buffer.

View file

@ -107,7 +107,8 @@ void pulse_detect_free(pulse_detect_t *pulse_detect);
/// @param fixed_high_level Manual high level override, default is 0 (auto)
/// @param min_high_level Minimum high level, default is -12 dB
/// @param high_low_ratio Minimum signal noise ratio, default is 9 dB
void pulse_detect_set_levels(pulse_detect_t *pulse_detect, int use_mag_est, float fixed_high_level, float min_high_level, float high_low_ratio);
/// @param verbosity Debug output verbosity, 0=None, 1=Levels, 2=Histograms
void pulse_detect_set_levels(pulse_detect_t *pulse_detect, int use_mag_est, float fixed_high_level, float min_high_level, float high_low_ratio, int verbosity);
/// Demodulate On/Off Keying (OOK) and Frequency Shift Keying (FSK) from an envelope signal.
///

View file

@ -21,6 +21,7 @@ struct dm_state {
float min_level;
float min_snr;
int use_mag_est;
int detect_verbosity;
int16_t am_buf[MAXIMAL_BUF_LENGTH]; // AM demodulated signal (for OOK decoding)
union {

View file

@ -192,6 +192,7 @@ void pulse_data_dump(FILE *file, pulse_data_t *data)
/// Internal state data for pulse_pulse_package()
struct pulse_detect {
int use_mag_est; ///< Wether the envelope data is an amplitude or magnitude.
int ook_fixed_high_level; ///< Manual detection level override, 0 = auto.
int ook_min_high_level; ///< Minimum estimate of high level (-12 dB: 1000 amp, 4000 mag).
int ook_high_low_ratio; ///< Default ratio between high and low (noise) level (9 dB: x8 amp, 11 dB: x3.6 mag).
@ -202,14 +203,16 @@ struct pulse_detect {
PD_OOK_STATE_GAP_START = 2,
PD_OOK_STATE_GAP = 3
} ook_state;
int pulse_length; // Counter for internal pulse detection
int max_pulse; // Size of biggest pulse detected
int pulse_length; ///< Counter for internal pulse detection
int max_pulse; ///< Size of biggest pulse detected
int data_counter; // Counter for how much of data chunk is processed
int lead_in_counter; // Counter for allowing initial noise estimate to settle
int data_counter; ///< Counter for how much of data chunk is processed
int lead_in_counter; ///< Counter for allowing initial noise estimate to settle
int ook_low_estimate; // Estimate for the OOK low level (base noise level) in the envelope data
int ook_high_estimate; // Estimate for the OOK high level
int ook_low_estimate; ///< Estimate for the OOK low level (base noise level) in the envelope data
int ook_high_estimate; ///< Estimate for the OOK high level
int verbosity; ///< Debug output verbosity, 0=None, 1=Levels, 2=Histograms
pulse_FSK_state_t FSK_state;
};
@ -222,7 +225,7 @@ pulse_detect_t *pulse_detect_create()
return NULL;
}
pulse_detect_set_levels(pulse_detect, 0, 0.0, -12.1442, 9.0);
pulse_detect_set_levels(pulse_detect, 0, 0.0, -12.1442, 9.0, 0);
return pulse_detect;
}
@ -232,8 +235,9 @@ void pulse_detect_free(pulse_detect_t *pulse_detect)
free(pulse_detect);
}
void pulse_detect_set_levels(pulse_detect_t *pulse_detect, int use_mag_est, float fixed_high_level, float min_high_level, float high_low_ratio)
void pulse_detect_set_levels(pulse_detect_t *pulse_detect, int use_mag_est, float fixed_high_level, float min_high_level, float high_low_ratio, int verbosity)
{
pulse_detect->use_mag_est = use_mag_est;
if (use_mag_est) {
pulse_detect->ook_fixed_high_level = fixed_high_level < 0.0 ? DB_TO_MAG(fixed_high_level) : 0;
pulse_detect->ook_min_high_level = DB_TO_MAG(min_high_level);
@ -244,6 +248,7 @@ void pulse_detect_set_levels(pulse_detect_t *pulse_detect, int use_mag_est, floa
pulse_detect->ook_min_high_level = DB_TO_AMP(min_high_level);
pulse_detect->ook_high_low_ratio = DB_TO_AMP_F(high_low_ratio);
}
pulse_detect->verbosity = verbosity;
//fprintf(stderr, "fixed_high_level %.1f (%d), min_high_level %.1f (%d), high_low_ratio %.1f (%d)\n",
// fixed_high_level, pulse_detect->ook_fixed_high_level,
@ -251,9 +256,100 @@ void pulse_detect_set_levels(pulse_detect_t *pulse_detect, int use_mag_est, floa
// high_low_ratio, pulse_detect->ook_high_low_ratio);
}
/// convert amplitude (16384 FS) to attenuation in (integer) dB, offset by 3.
static inline int amp_to_att(int a)
{
if (a > 32690) return 0; // = 10^(( 3 + 42.1442) / 10)
if (a > 25967) return 1; // = 10^(( 2 + 42.1442) / 10)
if (a > 20626) return 2; // = 10^(( 1 + 42.1442) / 10)
if (a > 16383) return 3; // = 10^(( 0 + 42.1442) / 10)
if (a > 13014) return 4; // = 10^((-1 + 42.1442) / 10)
if (a > 10338) return 5; // = 10^((-2 + 42.1442) / 10)
if (a > 8211) return 6; // = 10^((-3 + 42.1442) / 10)
if (a > 6523) return 7; // = 10^((-4 + 42.1442) / 10)
if (a > 5181) return 8; // = 10^((-5 + 42.1442) / 10)
if (a > 4115) return 9; // = 10^((-6 + 42.1442) / 10)
if (a > 3269) return 10; // = 10^((-7 + 42.1442) / 10)
if (a > 2597) return 11; // = 10^((-8 + 42.1442) / 10)
if (a > 2063) return 12; // = 10^((-9 + 42.1442) / 10)
if (a > 1638) return 13; // = 10^((-10 + 42.1442) / 10)
if (a > 1301) return 14; // = 10^((-11 + 42.1442) / 10)
if (a > 1034) return 15; // = 10^((-12 + 42.1442) / 10)
if (a > 821) return 16; // = 10^((-13 + 42.1442) / 10)
if (a > 652) return 17; // = 10^((-14 + 42.1442) / 10)
if (a > 518) return 18; // = 10^((-15 + 42.1442) / 10)
if (a > 412) return 19; // = 10^((-16 + 42.1442) / 10)
if (a > 327) return 20; // = 10^((-17 + 42.1442) / 10)
if (a > 260) return 21; // = 10^((-18 + 42.1442) / 10)
if (a > 206) return 22; // = 10^((-19 + 42.1442) / 10)
if (a > 164) return 23; // = 10^((-20 + 42.1442) / 10)
if (a > 130) return 24; // = 10^((-21 + 42.1442) / 10)
if (a > 103) return 25; // = 10^((-22 + 42.1442) / 10)
if (a > 82) return 26; // = 10^((-23 + 42.1442) / 10)
if (a > 65) return 27; // = 10^((-24 + 42.1442) / 10)
if (a > 52) return 28; // = 10^((-25 + 42.1442) / 10)
if (a > 41) return 29; // = 10^((-26 + 42.1442) / 10)
if (a > 33) return 30; // = 10^((-27 + 42.1442) / 10)
if (a > 26) return 31; // = 10^((-28 + 42.1442) / 10)
if (a > 21) return 32; // = 10^((-29 + 42.1442) / 10)
if (a > 16) return 33; // = 10^((-30 + 42.1442) / 10)
if (a > 13) return 34; // = 10^((-31 + 42.1442) / 10)
if (a > 10) return 35; // = 10^((-32 + 42.1442) / 10)
return 36;
}
/// convert magnitude (16384 FS) to attenuation in (integer) dB, offset by 3.
static inline int mag_to_att(int m)
{
if (m > 23143) return 0; // = 10^(( 3 + 84.2884) / 20)
if (m > 20626) return 1; // = 10^(( 2 + 84.2884) / 20)
if (m > 18383) return 2; // = 10^(( 1 + 84.2884) / 20)
if (m > 16383) return 3; // = 10^(( 0 + 84.2884) / 20)
if (m > 14602) return 4; // = 10^((-1 + 84.2884) / 20)
if (m > 13014) return 5; // = 10^((-2 + 84.2884) / 20)
if (m > 11599) return 6; // = 10^((-3 + 84.2884) / 20)
if (m > 10338) return 7; // = 10^((-4 + 84.2884) / 20)
if (m > 9213) return 8; // = 10^((-5 + 84.2884) / 20)
if (m > 8211) return 9; // = 10^((-6 + 84.2884) / 20)
if (m > 7318) return 10; // = 10^((-7 + 84.2884) / 20)
if (m > 6523) return 11; // = 10^((-8 + 84.2884) / 20)
if (m > 5813) return 12; // = 10^((-9 + 84.2884) / 20)
if (m > 5181) return 13; // = 10^((-10 + 84.2884) / 20)
if (m > 4618) return 14; // = 10^((-11 + 84.2884) / 20)
if (m > 4115) return 15; // = 10^((-12 + 84.2884) / 20)
if (m > 3668) return 16; // = 10^((-13 + 84.2884) / 20)
if (m > 3269) return 17; // = 10^((-14 + 84.2884) / 20)
if (m > 2914) return 18; // = 10^((-15 + 84.2884) / 20)
if (m > 2597) return 19; // = 10^((-16 + 84.2884) / 20)
if (m > 2314) return 20; // = 10^((-17 + 84.2884) / 20)
if (m > 2063) return 21; // = 10^((-18 + 84.2884) / 20)
if (m > 1838) return 22; // = 10^((-19 + 84.2884) / 20)
if (m > 1638) return 23; // = 10^((-20 + 84.2884) / 20)
if (m > 1460) return 24; // = 10^((-21 + 84.2884) / 20)
if (m > 1301) return 25; // = 10^((-22 + 84.2884) / 20)
if (m > 1160) return 26; // = 10^((-23 + 84.2884) / 20)
if (m > 1034) return 27; // = 10^((-24 + 84.2884) / 20)
if (m > 921) return 28; // = 10^((-25 + 84.2884) / 20)
if (m > 821) return 29; // = 10^((-26 + 84.2884) / 20)
if (m > 732) return 30; // = 10^((-27 + 84.2884) / 20)
if (m > 652) return 31; // = 10^((-28 + 84.2884) / 20)
if (m > 581) return 32; // = 10^((-29 + 84.2884) / 20)
if (m > 518) return 33; // = 10^((-30 + 84.2884) / 20)
if (m > 462) return 34; // = 10^((-31 + 84.2884) / 20)
if (m > 412) return 35; // = 10^((-32 + 84.2884) / 20)
return 36;
}
/// print a simple attenuation histogram.
static void print_att_hist(char const *s, int att_hist[])
{
fprintf(stderr, "\n%s\n", s);
for (int i = 0; i < 37; ++i)
fprintf(stderr, ">%3d dB: %5d smps\n", 3 - i, att_hist[i]);
}
/// Demodulate On/Off Keying (OOK) and Frequency Shift Keying (FSK) from an envelope signal
int pulse_detect_package(pulse_detect_t *pulse_detect, int16_t const *envelope_data, int16_t const *fm_data, int len, uint32_t samp_rate, uint64_t sample_offset, pulse_data_t *pulses, pulse_data_t *fsk_pulses, unsigned fpdm)
{
int att_hist[37] = {0};
int const samples_per_ms = samp_rate / 1000;
pulse_detect_t *s = pulse_detect;
s->ook_high_estimate = MAX(s->ook_high_estimate, pulse_detect->ook_min_high_level); // Be sure to set initial minimum level
@ -268,6 +364,10 @@ int pulse_detect_package(pulse_detect_t *pulse_detect, int16_t const *envelope_d
while (s->data_counter < len) {
// Calculate OOK detection threshold and hysteresis
int16_t const am_n = envelope_data[s->data_counter];
if (pulse_detect->verbosity) {
int att = pulse_detect->use_mag_est ? mag_to_att(am_n) : amp_to_att(am_n);
att_hist[att]++;
}
int16_t ook_threshold = (s->ook_low_estimate + s->ook_high_estimate) / 2;
if (pulse_detect->ook_fixed_high_level != 0)
ook_threshold = pulse_detect->ook_fixed_high_level; // Manual override
@ -363,6 +463,14 @@ int pulse_detect_package(pulse_detect_t *pulse_detect, int16_t const *envelope_d
pulses->end_ago = len - s->data_counter;
fsk_pulses->end_ago = len - s->data_counter;
s->ook_state = PD_OOK_STATE_IDLE; // Ensure everything is reset
if (pulse_detect->verbosity > 1)
print_att_hist("PULSE_DATA_FSK", att_hist);
if (pulse_detect->verbosity)
fprintf(stderr, "Levels low: -%d dB high: -%d dB thres: -%d dB hyst: (-%d to -%d dB)\n",
mag_to_att(s->ook_low_estimate), mag_to_att(s->ook_high_estimate),
mag_to_att(ook_threshold),
mag_to_att(ook_threshold + ook_hysteresis),
mag_to_att(ook_threshold - ook_hysteresis));
return PULSE_DATA_FSK;
}
} // if
@ -388,6 +496,8 @@ int pulse_detect_package(pulse_detect_t *pulse_detect, int16_t const *envelope_d
pulses->ook_low_estimate = s->ook_low_estimate;
pulses->ook_high_estimate = s->ook_high_estimate;
pulses->end_ago = len - s->data_counter;
if (pulse_detect->verbosity > 1)
print_att_hist("PULSE_DATA_OOK MAX_PULSES", att_hist);
return PULSE_DATA_OOK; // End Of Package!!
}
@ -406,6 +516,14 @@ int pulse_detect_package(pulse_detect_t *pulse_detect, int16_t const *envelope_d
pulses->ook_low_estimate = s->ook_low_estimate;
pulses->ook_high_estimate = s->ook_high_estimate;
pulses->end_ago = len - s->data_counter;
if (pulse_detect->verbosity > 1)
print_att_hist("PULSE_DATA_OOK EOP", att_hist);
if (pulse_detect->verbosity)
fprintf(stderr, "Levels low: -%d dB high: -%d dB thres: -%d dB hyst: (-%d to -%d dB)\n",
mag_to_att(s->ook_low_estimate), mag_to_att(s->ook_high_estimate),
mag_to_att(ook_threshold),
mag_to_att(ook_threshold + ook_hysteresis),
mag_to_att(ook_threshold - ook_hysteresis));
return PULSE_DATA_OOK; // End Of Package!!
}
break;
@ -417,6 +535,8 @@ int pulse_detect_package(pulse_detect_t *pulse_detect, int16_t const *envelope_d
} // while
s->data_counter = 0;
if (pulse_detect->verbosity > 2)
print_att_hist("Out of data", att_hist);
return 0; // Out of data
}

View file

@ -1058,6 +1058,8 @@ static void parse_conf_option(r_cfg_t *cfg, int opt, char *arg)
cfg->fsk_pulse_detect_mode = FSK_PULSE_DETECT_NEW;
else if (!strncmp(p, "ampest", 6))
cfg->demod->use_mag_est = 0;
else if (!strncmp(p, "verbose", 7))
cfg->demod->detect_verbosity++;
else if (!strncmp(p, "magest", 6))
cfg->demod->use_mag_est = 1;
else if (!strncasecmp(p, "level", 5))
@ -1195,7 +1197,7 @@ int main(int argc, char **argv) {
add_infile(cfg, argv[optind++]);
}
pulse_detect_set_levels(demod->pulse_detect, demod->use_mag_est, demod->level_limit, demod->min_level, demod->min_snr);
pulse_detect_set_levels(demod->pulse_detect, demod->use_mag_est, demod->level_limit, demod->min_level, demod->min_snr, demod->detect_verbosity);
if (demod->am_analyze) {
demod->am_analyze->level_limit = DB_TO_AMP(demod->level_limit);