From 630aeab2faf86a47b701ffbecece726c39d0932b Mon Sep 17 00:00:00 2001 From: "Christian W. Zuckschwerdt" Date: Fri, 9 Oct 2020 14:03:38 +0200 Subject: [PATCH] Change width calc from r_device to slicers (#1513) --- include/r_device.h | 10 -- src/pulse_analyzer.c | 96 ++++++------ src/pulse_demod.c | 357 ++++++++++++++++++++++++++++++++----------- src/r_api.c | 22 --- 4 files changed, 319 insertions(+), 166 deletions(-) diff --git a/include/r_device.h b/include/r_device.h index 51641868d..4f793782c 100644 --- a/include/r_device.h +++ b/include/r_device.h @@ -71,16 +71,6 @@ typedef struct r_device { /* private for flex decoder and output callback */ void *decode_ctx; void *output_ctx; - - /* private pulse limits (converted to count of samples) */ - float f_short_width; ///< precision reciprocal for PCM. - float f_long_width; ///< precision reciprocal for PCM. - int s_short_width; - int s_long_width; - int s_reset_limit; - int s_gap_limit; - int s_sync_width; - int s_tolerance; } r_device; #endif /* INCLUDE_R_DEVICE_H_ */ diff --git a/src/pulse_analyzer.c b/src/pulse_analyzer.c index 651838bba..cb169eb69 100644 --- a/src/pulse_analyzer.c +++ b/src/pulse_analyzer.c @@ -269,43 +269,43 @@ void pulse_analyzer(pulse_data_t *data, int package_type) } else if (hist_pulses.bins_count == 1 && hist_gaps.bins_count > 1) { fprintf(stderr, "Pulse Position Modulation with fixed pulse width\n"); - device.modulation = OOK_PULSE_PPM; - device.s_short_width = hist_gaps.bins[0].mean; - device.s_long_width = hist_gaps.bins[1].mean; - device.s_gap_limit = hist_gaps.bins[1].max + 1; // Set limit above next lower gap - device.s_reset_limit = hist_gaps.bins[hist_gaps.bins_count - 1].max + 1; // Set limit above biggest gap + device.modulation = OOK_PULSE_PPM; + device.short_width = to_us * hist_gaps.bins[0].mean; + device.long_width = to_us * hist_gaps.bins[1].mean; + device.gap_limit = to_us * (hist_gaps.bins[1].max + 1); // Set limit above next lower gap + device.reset_limit = to_us * (hist_gaps.bins[hist_gaps.bins_count - 1].max + 1); // Set limit above biggest gap } else if (hist_pulses.bins_count == 2 && hist_gaps.bins_count == 1) { fprintf(stderr, "Pulse Width Modulation with fixed gap\n"); - device.modulation = OOK_PULSE_PWM; - device.s_short_width = hist_pulses.bins[0].mean; - device.s_long_width = hist_pulses.bins[1].mean; - device.s_tolerance = (device.s_long_width - device.s_short_width) * 0.4; - device.s_reset_limit = hist_gaps.bins[hist_gaps.bins_count - 1].max + 1; // Set limit above biggest gap + device.modulation = OOK_PULSE_PWM; + device.short_width = to_us * hist_pulses.bins[0].mean; + device.long_width = to_us * hist_pulses.bins[1].mean; + device.tolerance = (device.long_width - device.short_width) * 0.4; + device.reset_limit = to_us * (hist_gaps.bins[hist_gaps.bins_count - 1].max + 1); // Set limit above biggest gap } else if (hist_pulses.bins_count == 2 && hist_gaps.bins_count == 2 && hist_periods.bins_count == 1) { fprintf(stderr, "Pulse Width Modulation with fixed period\n"); - device.modulation = OOK_PULSE_PWM; - device.s_short_width = hist_pulses.bins[0].mean; - device.s_long_width = hist_pulses.bins[1].mean; - device.s_tolerance = (device.s_long_width - device.s_short_width) * 0.4; - device.s_reset_limit = hist_gaps.bins[hist_gaps.bins_count - 1].max + 1; // Set limit above biggest gap + device.modulation = OOK_PULSE_PWM; + device.short_width = to_us * hist_pulses.bins[0].mean; + device.long_width = to_us * hist_pulses.bins[1].mean; + device.tolerance = (device.long_width - device.short_width) * 0.4; + device.reset_limit = to_us * (hist_gaps.bins[hist_gaps.bins_count - 1].max + 1); // Set limit above biggest gap } else if (hist_pulses.bins_count == 2 && hist_gaps.bins_count == 2 && hist_periods.bins_count == 3) { fprintf(stderr, "Manchester coding\n"); - device.modulation = OOK_PULSE_MANCHESTER_ZEROBIT; - device.s_short_width = MIN(hist_pulses.bins[0].mean, hist_pulses.bins[1].mean); // Assume shortest pulse is half period - device.s_long_width = 0; // Not used - device.s_reset_limit = hist_gaps.bins[hist_gaps.bins_count - 1].max + 1; // Set limit above biggest gap + device.modulation = OOK_PULSE_MANCHESTER_ZEROBIT; + device.short_width = to_us * MIN(hist_pulses.bins[0].mean, hist_pulses.bins[1].mean); // Assume shortest pulse is half period + device.long_width = 0; // Not used + device.reset_limit = to_us * (hist_gaps.bins[hist_gaps.bins_count - 1].max + 1); // Set limit above biggest gap } else if (hist_pulses.bins_count == 2 && hist_gaps.bins_count >= 3) { fprintf(stderr, "Pulse Width Modulation with multiple packets\n"); - device.modulation = (package_type == PULSE_DATA_FSK) ? FSK_PULSE_PWM : OOK_PULSE_PWM; - device.s_short_width = hist_pulses.bins[0].mean; - device.s_long_width = hist_pulses.bins[1].mean; - device.s_gap_limit = hist_gaps.bins[1].max + 1; // Set limit above second gap - device.s_tolerance = (device.s_long_width - device.s_short_width) * 0.4; - device.s_reset_limit = hist_gaps.bins[hist_gaps.bins_count - 1].max + 1; // Set limit above biggest gap + device.modulation = (package_type == PULSE_DATA_FSK) ? FSK_PULSE_PWM : OOK_PULSE_PWM; + device.short_width = to_us * hist_pulses.bins[0].mean; + device.long_width = to_us * hist_pulses.bins[1].mean; + device.gap_limit = to_us * (hist_gaps.bins[1].max + 1); // Set limit above second gap + device.tolerance = (device.long_width - device.short_width) * 0.4; + device.reset_limit = to_us * (hist_gaps.bins[hist_gaps.bins_count - 1].max + 1); // Set limit above biggest gap } else if ((hist_pulses.bins_count >= 3 && hist_gaps.bins_count >= 3) && (abs(hist_pulses.bins[1].mean - 2*hist_pulses.bins[0].mean) <= hist_pulses.bins[0].mean/8) // Pulses are multiples of shortest pulse @@ -314,10 +314,10 @@ void pulse_analyzer(pulse_data_t *data, int package_type) && (abs(hist_gaps.bins[1].mean - 2*hist_pulses.bins[0].mean) <= hist_pulses.bins[0].mean/8) && (abs(hist_gaps.bins[2].mean - 3*hist_pulses.bins[0].mean) <= hist_pulses.bins[0].mean/8)) { fprintf(stderr, "Pulse Code Modulation (Not Return to Zero)\n"); - device.modulation = FSK_PULSE_PCM; - device.s_short_width = hist_pulses.bins[0].mean; // Shortest pulse is bit width - device.s_long_width = hist_pulses.bins[0].mean; // Bit period equal to pulse length (NRZ) - device.s_reset_limit = hist_pulses.bins[0].mean * 1024; // No limit to run of zeros... + device.modulation = FSK_PULSE_PCM; + device.short_width = to_us * hist_pulses.bins[0].mean; // Shortest pulse is bit width + device.long_width = to_us * hist_pulses.bins[0].mean; // Bit period equal to pulse length (NRZ) + device.reset_limit = to_us * hist_pulses.bins[0].mean * 1024; // No limit to run of zeros... } else if (hist_pulses.bins_count == 3) { fprintf(stderr, "Pulse Width Modulation with sync/delimiter\n"); @@ -325,11 +325,11 @@ void pulse_analyzer(pulse_data_t *data, int package_type) histogram_sort_count(&hist_pulses); int p1 = hist_pulses.bins[1].mean; int p2 = hist_pulses.bins[2].mean; - device.modulation = OOK_PULSE_PWM; - device.s_short_width = p1 < p2 ? p1 : p2; // Set to shorter pulse width - device.s_long_width = p1 < p2 ? p2 : p1; // Set to longer pulse width - device.s_sync_width = hist_pulses.bins[0].mean; // Set to lowest count pulse width - device.s_reset_limit = hist_gaps.bins[hist_gaps.bins_count - 1].max + 1; // Set limit above biggest gap + device.modulation = OOK_PULSE_PWM; + device.short_width = to_us * (p1 < p2 ? p1 : p2); // Set to shorter pulse width + device.long_width = to_us * (p1 < p2 ? p2 : p1); // Set to longer pulse width + device.sync_width = to_us * hist_pulses.bins[0].mean; // Set to lowest count pulse width + device.reset_limit = to_us * (hist_gaps.bins[hist_gaps.bins_count - 1].max + 1); // Set limit above biggest gap } else { fprintf(stderr, "No clue...\n"); @@ -415,39 +415,39 @@ void pulse_analyzer(pulse_data_t *data, int package_type) // Demodulate (if detected) if (device.modulation) { fprintf(stderr, "Attempting demodulation... short_width: %.0f, long_width: %.0f, reset_limit: %.0f, sync_width: %.0f\n", - device.s_short_width * to_us, device.s_long_width * to_us, - device.s_reset_limit * to_us, device.s_sync_width * to_us); + device.short_width, device.long_width, + device.reset_limit, device.sync_width); switch (device.modulation) { case FSK_PULSE_PCM: fprintf(stderr, "Use a flex decoder with -X 'n=name,m=FSK_PCM,s=%.0f,l=%.0f,r=%.0f'\n", - device.s_short_width * to_us, device.s_long_width * to_us, device.s_reset_limit * to_us); + device.short_width, device.long_width, device.reset_limit); pulse_demod_pcm(data, &device); break; case OOK_PULSE_PPM: fprintf(stderr, "Use a flex decoder with -X 'n=name,m=OOK_PPM,s=%.0f,l=%.0f,g=%.0f,r=%.0f'\n", - device.s_short_width * to_us, device.s_long_width * to_us, - device.s_gap_limit * to_us, device.s_reset_limit * to_us); - data->gap[data->num_pulses - 1] = device.s_reset_limit + 1; // Be sure to terminate package + device.short_width, device.long_width, + device.gap_limit, device.reset_limit); + data->gap[data->num_pulses - 1] = device.reset_limit / to_us + 1; // Be sure to terminate package pulse_demod_ppm(data, &device); break; case OOK_PULSE_PWM: fprintf(stderr, "Use a flex decoder with -X 'n=name,m=OOK_PWM,s=%.0f,l=%.0f,r=%.0f,g=%.0f,t=%.0f,y=%.0f'\n", - device.s_short_width * to_us, device.s_long_width * to_us, device.s_reset_limit * to_us, - device.s_gap_limit * to_us, device.s_tolerance * to_us, device.s_sync_width * to_us); - data->gap[data->num_pulses - 1] = device.s_reset_limit + 1; // Be sure to terminate package + device.short_width, device.long_width, device.reset_limit, + device.gap_limit, device.tolerance, device.sync_width); + data->gap[data->num_pulses - 1] = device.reset_limit / to_us + 1; // Be sure to terminate package pulse_demod_pwm(data, &device); break; case FSK_PULSE_PWM: fprintf(stderr, "Use a flex decoder with -X 'n=name,m=FSK_PWM,s=%.0f,l=%.0f,r=%.0f,g=%.0f,t=%.0f,y=%.0f'\n", - device.s_short_width * to_us, device.s_long_width * to_us, device.s_reset_limit * to_us, - device.s_gap_limit * to_us, device.s_tolerance * to_us, device.s_sync_width * to_us); - data->gap[data->num_pulses - 1] = device.s_reset_limit + 1; // Be sure to terminate package + device.short_width, device.long_width, device.reset_limit, + device.gap_limit, device.tolerance, device.sync_width); + data->gap[data->num_pulses - 1] = device.reset_limit / to_us + 1; // Be sure to terminate package pulse_demod_pwm(data, &device); break; case OOK_PULSE_MANCHESTER_ZEROBIT: fprintf(stderr, "Use a flex decoder with -X 'n=name,m=OOK_MC_ZEROBIT,s=%.0f,l=%.0f,r=%.0f'\n", - device.s_short_width * to_us, device.s_long_width * to_us, device.s_reset_limit * to_us); - data->gap[data->num_pulses - 1] = device.s_reset_limit + 1; // Be sure to terminate package + device.short_width, device.long_width, device.reset_limit); + data->gap[data->num_pulses - 1] = device.reset_limit / to_us + 1; // Be sure to terminate package pulse_demod_manchester_zerobit(data, &device); break; default: diff --git a/src/pulse_demod.c b/src/pulse_demod.c index 8fe1d6247..e1c85e278 100644 --- a/src/pulse_demod.c +++ b/src/pulse_demod.c @@ -54,28 +54,49 @@ static int account_event(r_device *device, bitbuffer_t *bits, char const *demod_ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + + // precision reciprocals + float f_short = device->short_width > 0.0 ? 1.0 / (device->short_width * samples_per_us) : 0; + float f_long = device->long_width > 0.0 ? 1.0 / (device->long_width * samples_per_us) : 0; + int events = 0; bitbuffer_t bits = {0}; - int const gap_limit = device->s_gap_limit ? device->s_gap_limit : device->s_reset_limit; - int const max_zeros = gap_limit / device->s_long_width; - int tolerance = device->s_tolerance; - if (tolerance <= 0) - tolerance = device->s_long_width / 4; // default tolerance is +-25% of a bit period - - float f_short = device->f_short_width; - float f_long = device->f_long_width; + + int const gap_limit = s_gap ? s_gap : s_reset; + int const max_zeros = gap_limit / s_long; + if (s_tolerance <= 0) + s_tolerance = s_long / 4; // default tolerance is +-25% of a bit period + // if there is a run of bit-wide toggles (preamble) tune the bit period - int min_count = device->s_short_width == device->s_long_width ? 12 : 4; + int min_count = s_short == s_long ? 12 : 4; // RZ - for (unsigned n = 0; device->s_short_width != device->s_long_width && n < pulses->num_pulses; ++n) { + for (unsigned n = 0; s_short != s_long && n < pulses->num_pulses; ++n) { int swidth = 0; int lwidth = 0; int count = 0; while (n < pulses->num_pulses - && pulses->pulse[n] >= device->s_short_width - tolerance - && pulses->pulse[n] <= device->s_short_width + tolerance - && pulses->pulse[n] + pulses->gap[n] >= device->s_long_width - tolerance - && pulses->pulse[n] + pulses->gap[n] <= device->s_long_width + tolerance) { + && pulses->pulse[n] >= s_short - s_tolerance + && pulses->pulse[n] <= s_short + s_tolerance + && pulses->pulse[n] + pulses->gap[n] >= s_long - s_tolerance + && pulses->pulse[n] + pulses->gap[n] <= s_long + s_tolerance) { swidth += pulses->pulse[n]; lwidth += pulses->pulse[n] + pulses->gap[n]; count += 1; @@ -89,18 +110,18 @@ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) if (device->verbose > 1) { float to_us = 1e6 / pulses->sample_rate; fprintf(stderr, "Exact bit width (in us) is %.2f vs %.2f (pulse width %.2f vs %.2f), %d bit preamble\n", - to_us / f_long, to_us * device->s_long_width, - to_us / f_short, to_us * device->s_short_width, count); + to_us / f_long, to_us * s_long, + to_us / f_short, to_us * s_short, count); } } } // NRZ - for (unsigned n = 0; device->s_short_width == device->s_long_width && n < pulses->num_pulses; ++n) { + for (unsigned n = 0; s_short == s_long && n < pulses->num_pulses; ++n) { int width = 0; int count = 0; while (n < pulses->num_pulses - && (int)(pulses->pulse[n] * device->f_short_width + 0.5) == 1 - && (int)(pulses->gap[n] * device->f_long_width + 0.5) == 1) { + && (int)(pulses->pulse[n] * f_short + 0.5) == 1 + && (int)(pulses->gap[n] * f_long + 0.5) == 1) { width += pulses->pulse[n] + pulses->gap[n]; count += 2; n++; @@ -112,7 +133,7 @@ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) if (device->verbose > 1) { float to_us = 1e6 / pulses->sample_rate; fprintf(stderr, "Exact bit width (in us) is %.2f vs %.2f, %d bit preamble\n", - to_us / f_short, to_us * device->s_short_width, count); + to_us / f_short, to_us * s_short, count); } } } @@ -122,7 +143,7 @@ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) int highs = (pulses->pulse[n]) * f_short + 0.5; // Determine number of low bit periods in current gap length (rounded) // for RZ subtract the nominal bit-gap - int lows = (pulses->gap[n] + device->s_short_width - device->s_long_width) * f_long + 0.5; + int lows = (pulses->gap[n] + s_short - s_long) * f_long + 0.5; // Add run of ones (1 for RZ, many for NRZ) for (int i = 0; i < highs; ++i) { @@ -135,8 +156,8 @@ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) } // Validate data - if ((device->s_short_width != device->s_long_width) // Only for RZ coding - && (abs(pulses->pulse[n] - device->s_short_width) > tolerance)) { // Pulse must be within tolerance + if ((s_short != s_long) // Only for RZ coding + && (abs(pulses->pulse[n] - s_short) > s_tolerance)) { // Pulse must be within tolerance // Data is corrupt if (device->verbose > 3) { @@ -148,12 +169,12 @@ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) } // Check for new packet in multipacket - else if (pulses->gap[n] > gap_limit && pulses->gap[n] <= device->s_reset_limit) { + else if (pulses->gap[n] > gap_limit && pulses->gap[n] <= s_reset) { bitbuffer_add_row(&bits); } // End of Message? if (((n == pulses->num_pulses - 1) // No more pulses? (FSK) - || (pulses->gap[n] > device->s_reset_limit)) // Long silence (OOK) + || (pulses->gap[n] > s_reset)) // Long silence (OOK) && (bits.bits_per_row[0] > 0 || bits.num_rows > 1)) { // Only if data has been accumulated events += account_event(device, &bits, __func__); @@ -165,6 +186,26 @@ int pulse_demod_pcm(const pulse_data_t *pulses, r_device *device) int pulse_demod_ppm(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + int events = 0; bitbuffer_t bits = {0}; @@ -173,23 +214,23 @@ int pulse_demod_ppm(const pulse_data_t *pulses, r_device *device) int one_l, one_u; int sync_l = 0, sync_u = 0; - if (device->s_tolerance > 0) { + if (s_tolerance > 0) { // precise - zero_l = device->s_short_width - device->s_tolerance; - zero_u = device->s_short_width + device->s_tolerance; - one_l = device->s_long_width - device->s_tolerance; - one_u = device->s_long_width + device->s_tolerance; - if (device->s_sync_width > 0) { - sync_l = device->s_sync_width - device->s_tolerance; - sync_u = device->s_sync_width + device->s_tolerance; + zero_l = s_short - s_tolerance; + zero_u = s_short + s_tolerance; + one_l = s_long - s_tolerance; + one_u = s_long + s_tolerance; + if (s_sync > 0) { + sync_l = s_sync - s_tolerance; + sync_u = s_sync + s_tolerance; } } else { // no sync, short=0, long=1 zero_l = 0; - zero_u = (device->s_short_width + device->s_long_width) / 2 + 1; + zero_u = (s_short + s_long) / 2 + 1; one_l = zero_u - 1; - one_u = device->s_gap_limit ? device->s_gap_limit : device->s_reset_limit; + one_u = s_gap ? s_gap : s_reset; } for (unsigned n = 0; n < pulses->num_pulses; ++n) { @@ -207,12 +248,12 @@ int pulse_demod_ppm(const pulse_data_t *pulses, r_device *device) } // Check for new packet in multipacket - else if (pulses->gap[n] < device->s_reset_limit) { + else if (pulses->gap[n] < s_reset) { bitbuffer_add_row(&bits); } // End of Message? if (((n == pulses->num_pulses - 1) // No more pulses? (FSK) - || (pulses->gap[n] >= device->s_reset_limit)) // Long silence (OOK) + || (pulses->gap[n] >= s_reset)) // Long silence (OOK) && (bits.bits_per_row[0] > 0 || bits.num_rows > 1)) { // Only if data has been accumulated events += account_event(device, &bits, __func__); @@ -224,6 +265,26 @@ int pulse_demod_ppm(const pulse_data_t *pulses, r_device *device) int pulse_demod_pwm(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + int events = 0; bitbuffer_t bits = {0}; @@ -232,48 +293,48 @@ int pulse_demod_pwm(const pulse_data_t *pulses, r_device *device) int zero_l, zero_u; int sync_l = 0, sync_u = 0; - if (device->s_tolerance > 0) { + if (s_tolerance > 0) { // precise - one_l = device->s_short_width - device->s_tolerance; - one_u = device->s_short_width + device->s_tolerance; - zero_l = device->s_long_width - device->s_tolerance; - zero_u = device->s_long_width + device->s_tolerance; - if (device->s_sync_width > 0) { - sync_l = device->s_sync_width - device->s_tolerance; - sync_u = device->s_sync_width + device->s_tolerance; + one_l = s_short - s_tolerance; + one_u = s_short + s_tolerance; + zero_l = s_long - s_tolerance; + zero_u = s_long + s_tolerance; + if (s_sync > 0) { + sync_l = s_sync - s_tolerance; + sync_u = s_sync + s_tolerance; } } - else if (device->s_sync_width <= 0) { + else if (s_sync <= 0) { // no sync, short=1, long=0 one_l = 0; - one_u = (device->s_short_width + device->s_long_width) / 2 + 1; + one_u = (s_short + s_long) / 2 + 1; zero_l = one_u - 1; zero_u = INT_MAX; } - else if (device->s_sync_width < device->s_short_width) { + else if (s_sync < s_short) { // short=sync, middle=1, long=0 sync_l = 0; - sync_u = (device->s_sync_width + device->s_short_width) / 2 + 1; + sync_u = (s_sync + s_short) / 2 + 1; one_l = sync_u - 1; - one_u = (device->s_short_width + device->s_long_width) / 2 + 1; + one_u = (s_short + s_long) / 2 + 1; zero_l = one_u - 1; zero_u = INT_MAX; } - else if (device->s_sync_width < device->s_long_width) { + else if (s_sync < s_long) { // short=1, middle=sync, long=0 one_l = 0; - one_u = (device->s_short_width + device->s_sync_width) / 2 + 1; + one_u = (s_short + s_sync) / 2 + 1; sync_l = one_u - 1; - sync_u = (device->s_sync_width + device->s_long_width) / 2 + 1; + sync_u = (s_sync + s_long) / 2 + 1; zero_l = sync_u - 1; zero_u = INT_MAX; } else { // short=1, middle=0, long=sync one_l = 0; - one_u = (device->s_short_width + device->s_long_width) / 2 + 1; + one_u = (s_short + s_long) / 2 + 1; zero_l = one_u - 1; - zero_u = (device->s_long_width + device->s_sync_width) / 2 + 1; + zero_u = (s_long + s_sync) / 2 + 1; sync_l = zero_u - 1; sync_u = INT_MAX; } @@ -301,12 +362,12 @@ int pulse_demod_pwm(const pulse_data_t *pulses, r_device *device) // End of Message? if (((n == pulses->num_pulses - 1) // No more pulses? (FSK) - || (pulses->gap[n] > device->s_reset_limit)) // Long silence (OOK) + || (pulses->gap[n] > s_reset)) // Long silence (OOK) && (bits.num_rows > 0)) { // Only if data has been accumulated events += account_event(device, &bits, __func__); bitbuffer_clear(&bits); } - else if (device->s_gap_limit > 0 && pulses->gap[n] > device->s_gap_limit + else if (s_gap > 0 && pulses->gap[n] > s_gap && bits.num_rows > 0 && bits.bits_per_row[bits.num_rows - 1] > 0) { // New packet in multipacket bitbuffer_add_row(&bits); @@ -317,6 +378,26 @@ int pulse_demod_pwm(const pulse_data_t *pulses, r_device *device) int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + int events = 0; int time_since_last = 0; bitbuffer_t bits = {0}; @@ -326,13 +407,13 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, r_device *device) for (unsigned n = 0; n < pulses->num_pulses; ++n) { // The pulse or gap is too long or too short, thus invalid - if (device->s_tolerance > 0 - && (pulses->pulse[n] < device->s_short_width - device->s_tolerance - || pulses->pulse[n] > device->s_short_width * 2 + device->s_tolerance - || pulses->gap[n] < device->s_short_width - device->s_tolerance - || pulses->gap[n] > device->s_short_width * 2 + device->s_tolerance)) { - if (pulses->pulse[n] > device->s_short_width * 1.5 - && pulses->pulse[n] <= device->s_short_width * 2 + device->s_tolerance) { + if (s_tolerance > 0 + && (pulses->pulse[n] < s_short - s_tolerance + || pulses->pulse[n] > s_short * 2 + s_tolerance + || pulses->gap[n] < s_short - s_tolerance + || pulses->gap[n] > s_short * 2 + s_tolerance)) { + if (pulses->pulse[n] > s_short * 1.5 + && pulses->pulse[n] <= s_short * 2 + s_tolerance) { // Long last pulse means with the gap this is a [1]10 transition, add a one bitbuffer_add_bit(&bits, 1); } @@ -341,7 +422,7 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, r_device *device) time_since_last = 0; } // Falling edge is on end of pulse - else if (pulses->pulse[n] + time_since_last > (device->s_short_width * 1.5)) { + else if (pulses->pulse[n] + time_since_last > (s_short * 1.5)) { // Last bit was recorded more than short_width*1.5 samples ago // so this pulse start must be a data edge (falling data edge means bit = 1) bitbuffer_add_bit(&bits, 1); @@ -353,7 +434,7 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, r_device *device) // End of Message? if (((n == pulses->num_pulses - 1) // No more pulses? (FSK) - || (pulses->gap[n] > device->s_reset_limit)) // Long silence (OOK) + || (pulses->gap[n] > s_reset)) // Long silence (OOK) && (bits.num_rows > 0)) { // Only if data has been accumulated events += account_event(device, &bits, __func__); bitbuffer_clear(&bits); @@ -361,7 +442,7 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, r_device *device) time_since_last = 0; } // Rising edge is on end of gap - else if (pulses->gap[n] + time_since_last > (device->s_short_width * 1.5)) { + else if (pulses->gap[n] + time_since_last > (s_short * 1.5)) { // Last bit was recorded more than short_width*1.5 samples ago // so this pulse end is a data edge (rising data edge means bit = 0) bitbuffer_add_bit(&bits, 0); @@ -376,6 +457,26 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, r_device *device) int pulse_demod_dmc(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + int symbol[PD_MAX_PULSES * 2 + 1] = {0}; unsigned int n; @@ -388,11 +489,11 @@ int pulse_demod_dmc(const pulse_data_t *pulses, r_device *device) } for (n = 0; n < pulses->num_pulses * 2; ++n) { - if (abs(symbol[n] - device->s_short_width) < device->s_tolerance) { + if (abs(symbol[n] - s_short) < s_tolerance) { // Short - 1 bitbuffer_add_bit(&bits, 1); - if (abs(symbol[++n] - device->s_short_width) > device->s_tolerance) { - if (symbol[n] >= device->s_reset_limit - device->s_tolerance) { + if (abs(symbol[++n] - s_short) > s_tolerance) { + if (symbol[n] >= s_reset - s_tolerance) { // Don't expect another short gap at end of message n--; } @@ -405,11 +506,11 @@ int pulse_demod_dmc(const pulse_data_t *pulses, r_device *device) } } } - else if (abs(symbol[n] - device->s_long_width) < device->s_tolerance) { + else if (abs(symbol[n] - s_long) < s_tolerance) { // Long - 0 bitbuffer_add_bit(&bits, 0); } - else if (symbol[n] >= device->s_reset_limit - device->s_tolerance + else if (symbol[n] >= s_reset - s_tolerance && bits.num_rows > 0) { // Only if data has been accumulated //END message ? events += account_event(device, &bits, __func__); @@ -421,6 +522,29 @@ int pulse_demod_dmc(const pulse_data_t *pulses, r_device *device) int pulse_demod_piwm_raw(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + + // precision reciprocal + float f_short = device->short_width > 0.0 ? 1.0 / (device->short_width * samples_per_us) : 0; + int symbol[PD_MAX_PULSES * 2]; unsigned int n; int w; @@ -428,22 +552,23 @@ int pulse_demod_piwm_raw(const pulse_data_t *pulses, r_device *device) bitbuffer_t bits = {0}; int events = 0; + for (n = 0; n < pulses->num_pulses; n++) { symbol[n * 2] = pulses->pulse[n]; symbol[n * 2 + 1] = pulses->gap[n]; } for (n = 0; n < pulses->num_pulses * 2; ++n) { - w = symbol[n] * device->f_short_width + 0.5; - if (symbol[n] > device->s_long_width) { + w = symbol[n] * f_short + 0.5; + if (symbol[n] > s_long) { bitbuffer_add_row(&bits); } - else if (abs(symbol[n] - w * device->s_short_width) < device->s_tolerance) { + else if (abs(symbol[n] - w * s_short) < s_tolerance) { // Add w symbols for (; w > 0; --w) bitbuffer_add_bit(&bits, 1 - n % 2); } - else if (symbol[n] < device->s_reset_limit + else if (symbol[n] < s_reset && bits.num_rows > 0 && bits.bits_per_row[bits.num_rows - 1] > 0) { bitbuffer_add_row(&bits); @@ -454,7 +579,7 @@ int pulse_demod_piwm_raw(const pulse_data_t *pulses, r_device *device) } if (((n == pulses->num_pulses * 2 - 1) // No more pulses? (FSK) - || (symbol[n] > device->s_reset_limit)) // Long silence (OOK) + || (symbol[n] > s_reset)) // Long silence (OOK) && (bits.num_rows > 0)) { // Only if data has been accumulated //END message ? events += account_event(device, &bits, __func__); @@ -466,6 +591,26 @@ int pulse_demod_piwm_raw(const pulse_data_t *pulses, r_device *device) int pulse_demod_piwm_dc(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + int symbol[PD_MAX_PULSES * 2]; unsigned int n; @@ -478,15 +623,15 @@ int pulse_demod_piwm_dc(const pulse_data_t *pulses, r_device *device) } for (n = 0; n < pulses->num_pulses * 2; ++n) { - if (abs(symbol[n] - device->s_short_width) < device->s_tolerance) { + if (abs(symbol[n] - s_short) < s_tolerance) { // Short - 1 bitbuffer_add_bit(&bits, 1); } - else if (abs(symbol[n] - device->s_long_width) < device->s_tolerance) { + else if (abs(symbol[n] - s_long) < s_tolerance) { // Long - 0 bitbuffer_add_bit(&bits, 0); } - else if (symbol[n] < device->s_reset_limit + else if (symbol[n] < s_reset && bits.num_rows > 0 && bits.bits_per_row[bits.num_rows - 1] > 0) { bitbuffer_add_row(&bits); @@ -497,7 +642,7 @@ int pulse_demod_piwm_dc(const pulse_data_t *pulses, r_device *device) } if (((n == pulses->num_pulses * 2 - 1) // No more pulses? (FSK) - || (symbol[n] > device->s_reset_limit)) // Long silence (OOK) + || (symbol[n] > s_reset)) // Long silence (OOK) && (bits.num_rows > 0)) { // Only if data has been accumulated //END message ? events += account_event(device, &bits, __func__); @@ -509,9 +654,29 @@ int pulse_demod_piwm_dc(const pulse_data_t *pulses, r_device *device) int pulse_demod_nrzs(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + int events = 0; bitbuffer_t bits = {0}; - int limit = device->s_short_width; + int limit = s_short; for (unsigned n = 0; n < pulses->num_pulses; ++n) { if (pulses->pulse[n] > limit) { @@ -524,7 +689,7 @@ int pulse_demod_nrzs(const pulse_data_t *pulses, r_device *device) } if (n == pulses->num_pulses - 1 - || pulses->gap[n] >= device->s_reset_limit) { + || pulses->gap[n] >= s_reset) { events += account_event(device, &bits, __func__); } @@ -549,13 +714,33 @@ int pulse_demod_nrzs(const pulse_data_t *pulses, r_device *device) int pulse_demod_osv1(const pulse_data_t *pulses, r_device *device) { + float samples_per_us = pulses->sample_rate / 1.0e6; + + int s_short = device->short_width * samples_per_us; + int s_long = device->long_width * samples_per_us; + int s_reset = device->reset_limit * samples_per_us; + int s_gap = device->gap_limit * samples_per_us; + int s_sync = device->sync_width * samples_per_us; + int s_tolerance = device->tolerance * samples_per_us; + + // check for rounding to zero + if ((device->short_width > 0 && s_short <= 0) + || (device->long_width > 0 && s_long <= 0) + || (device->reset_limit > 0 && s_reset <= 0) + || (device->gap_limit > 0 && s_gap <= 0) + || (device->sync_width > 0 && s_sync <= 0) + || (device->tolerance > 0 && s_tolerance <= 0)) { + fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", device->protocol_num, device->name); + return 0; + } + unsigned int n; int preamble = 0; int events = 0; int manbit = 0; bitbuffer_t bits = {0}; - int halfbit_min = device->s_short_width / 2; - int halfbit_max = device->s_short_width * 3 / 2; + int halfbit_min = s_short / 2; + int halfbit_max = s_short * 3 / 2; int sync_min = 2 * halfbit_max; /* preamble */ @@ -600,7 +785,7 @@ int pulse_demod_osv1(const pulse_data_t *pulses, r_device *device) bitbuffer_add_bit(&bits, 1); } if ((n == pulses->num_pulses - 1 - || pulses->gap[n] > device->s_reset_limit) + || pulses->gap[n] > s_reset) && (bits.num_rows > 0)) { // Only if data has been accumulated //END message ? events += account_event(device, &bits, __func__); diff --git a/src/r_api.c b/src/r_api.c index 7b13ee228..1bde31df0 100644 --- a/src/r_api.c +++ b/src/r_api.c @@ -143,28 +143,6 @@ void r_free_cfg(r_cfg_t *cfg) void update_protocol(r_cfg_t *cfg, r_device *r_dev) { - float samples_per_us = cfg->samp_rate / 1.0e6; - - r_dev->f_short_width = r_dev->short_width > 0.0 ? 1.0 / (r_dev->short_width * samples_per_us) : 0; - r_dev->f_long_width = r_dev->long_width > 0.0 ? 1.0 / (r_dev->long_width * samples_per_us) : 0; - r_dev->s_short_width = r_dev->short_width * samples_per_us; - r_dev->s_long_width = r_dev->long_width * samples_per_us; - r_dev->s_reset_limit = r_dev->reset_limit * samples_per_us; - r_dev->s_gap_limit = r_dev->gap_limit * samples_per_us; - r_dev->s_sync_width = r_dev->sync_width * samples_per_us; - r_dev->s_tolerance = r_dev->tolerance * samples_per_us; - - // check for rounding to zero - if ((r_dev->short_width > 0 && r_dev->s_short_width <= 0) - || (r_dev->long_width > 0 && r_dev->s_long_width <= 0) - || (r_dev->reset_limit > 0 && r_dev->s_reset_limit <= 0) - || (r_dev->gap_limit > 0 && r_dev->s_gap_limit <= 0) - || (r_dev->sync_width > 0 && r_dev->s_sync_width <= 0) - || (r_dev->tolerance > 0 && r_dev->s_tolerance <= 0)) { - fprintf(stderr, "sample rate too low for protocol %u \"%s\"\n", r_dev->protocol_num, r_dev->name); - exit(1); - } - r_dev->verbose = cfg->verbosity > 0 ? cfg->verbosity - 1 : 0; r_dev->verbose_bits = cfg->verbose_bits;