1 /** @file
2     Pulse detection functions.
3 
4     Copyright (C) 2015 Tommy Vestermark
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 */
11 
12 #include "pulse_detect.h"
13 #include "rfraw.h"
14 #include "pulse_demod.h"
15 #include "pulse_detect_fsk.h"
16 #include "baseband.h"
17 #include "util.h"
18 #include "r_device.h"
19 #include "r_util.h"
20 #include "fatal.h"
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
pulse_data_clear(pulse_data_t * data)26 void pulse_data_clear(pulse_data_t *data)
27 {
28     *data = (pulse_data_t const){0};
29 }
30 
pulse_data_shift(pulse_data_t * data)31 void pulse_data_shift(pulse_data_t *data)
32 {
33     int offs = PD_MAX_PULSES / 2; // shift out half the data
34     memmove(data->pulse, &data->pulse[offs], (PD_MAX_PULSES - offs) * sizeof(*data->pulse));
35     memmove(data->gap, &data->gap[offs], (PD_MAX_PULSES - offs) * sizeof(*data->gap));
36     data->num_pulses -= offs;
37     data->offset += offs;
38 }
39 
pulse_data_print(pulse_data_t const * data)40 void pulse_data_print(pulse_data_t const *data)
41 {
42     fprintf(stderr, "Pulse data: %u pulses\n", data->num_pulses);
43     for (unsigned n = 0; n < data->num_pulses; ++n) {
44         fprintf(stderr, "[%3u] Pulse: %4d, Gap: %4d, Period: %4d\n", n, data->pulse[n], data->gap[n], data->pulse[n] + data->gap[n]);
45     }
46 }
47 
bounded_memset(void * b,int c,int64_t size,int64_t offset,int64_t len)48 static void *bounded_memset(void *b, int c, int64_t size, int64_t offset, int64_t len)
49 {
50     if (offset < 0) {
51         len += offset; // reduce len by negative offset
52         offset = 0;
53     }
54     if (offset + len > size) {
55         len = size - offset; // clip excessive len
56     }
57     if (len > 0)
58         memset((char *)b + offset, c, (size_t)len);
59     return b;
60 }
61 
pulse_data_dump_raw(uint8_t * buf,unsigned len,uint64_t buf_offset,pulse_data_t const * data,uint8_t bits)62 void pulse_data_dump_raw(uint8_t *buf, unsigned len, uint64_t buf_offset, pulse_data_t const *data, uint8_t bits)
63 {
64     int64_t pos = data->offset - buf_offset;
65     for (unsigned n = 0; n < data->num_pulses; ++n) {
66         bounded_memset(buf, 0x01 | bits, len, pos, data->pulse[n]);
67         pos += data->pulse[n];
68         bounded_memset(buf, 0x01, len, pos, data->gap[n]);
69         pos += data->gap[n];
70     }
71 }
72 
chk_ret(int ret)73 static inline void chk_ret(int ret)
74 {
75     if (ret < 0) {
76         perror("File output error");
77         exit(1);
78     }
79 }
80 
pulse_data_print_vcd_header(FILE * file,uint32_t sample_rate)81 void pulse_data_print_vcd_header(FILE *file, uint32_t sample_rate)
82 {
83     char time_str[LOCAL_TIME_BUFLEN];
84     char *timescale;
85     if (sample_rate <= 500000)
86         timescale = "1 us";
87     else
88         timescale = "100 ns";
89     chk_ret(fprintf(file, "$date %s $end\n", format_time_str(time_str, NULL, 0, 0)));
90     chk_ret(fprintf(file, "$version rtl_433 0.1.0 $end\n"));
91     chk_ret(fprintf(file, "$comment Acquisition at %s Hz $end\n", nice_freq(sample_rate)));
92     chk_ret(fprintf(file, "$timescale %s $end\n", timescale));
93     chk_ret(fprintf(file, "$scope module rtl_433 $end\n"));
94     chk_ret(fprintf(file, "$var wire 1 / FRAME $end\n"));
95     chk_ret(fprintf(file, "$var wire 1 ' AM $end\n"));
96     chk_ret(fprintf(file, "$var wire 1 \" FM $end\n"));
97     chk_ret(fprintf(file, "$upscope $end\n"));
98     chk_ret(fprintf(file, "$enddefinitions $end\n"));
99     chk_ret(fprintf(file, "#0 0/ 0' 0\"\n"));
100 }
101 
pulse_data_print_vcd(FILE * file,pulse_data_t const * data,int ch_id)102 void pulse_data_print_vcd(FILE *file, pulse_data_t const *data, int ch_id)
103 {
104     float scale;
105     if (data->sample_rate <= 500000)
106         scale = 1000000 / data->sample_rate; // unit: 1 us
107     else
108         scale = 10000000 / data->sample_rate; // unit: 100 ns
109     uint64_t pos = data->offset;
110     for (unsigned n = 0; n < data->num_pulses; ++n) {
111         if (n == 0)
112             chk_ret(fprintf(file, "#%.f 1/ 1%c\n", pos * scale, ch_id));
113         else
114             chk_ret(fprintf(file, "#%.f 1%c\n", pos * scale, ch_id));
115         pos += data->pulse[n];
116         chk_ret(fprintf(file, "#%.f 0%c\n", pos * scale, ch_id));
117         pos += data->gap[n];
118     }
119     if (data->num_pulses > 0)
120         chk_ret(fprintf(file, "#%.f 0/\n", pos * scale));
121 }
122 
pulse_data_load(FILE * file,pulse_data_t * data,uint32_t sample_rate)123 void pulse_data_load(FILE *file, pulse_data_t *data, uint32_t sample_rate)
124 {
125     char s[1024];
126     int i    = 0;
127     int size = sizeof(data->pulse) / sizeof(*data->pulse);
128 
129     pulse_data_clear(data);
130     data->sample_rate = sample_rate;
131     double to_sample = sample_rate / 1e6;
132     // read line-by-line
133     while (i < size && fgets(s, sizeof(s), file)) {
134         // TODO: we should parse sample rate and timescale
135         if (!strncmp(s, ";freq1", 6)) {
136             data->freq1_hz = strtol(s + 6, NULL, 10);
137         }
138         if (!strncmp(s, ";freq2", 6)) {
139             data->freq2_hz = strtol(s + 6, NULL, 10);
140         }
141         if (*s == ';') {
142             if (i) {
143                 break; // end or next header found
144             }
145             else {
146                 continue; // still reading a header
147             }
148         }
149         if (rfraw_check(s)) {
150             rfraw_parse(data, s);
151             i = data->num_pulses;
152             continue;
153         }
154         // parse two ints.
155         char *p = s;
156         char *endptr;
157         long mark  = strtol(p, &endptr, 10);
158         p          = endptr + 1;
159         long space = strtol(p, &endptr, 10);
160         //fprintf(stderr, "read: mark %ld space %ld\n", mark, space);
161         data->pulse[i] = (int)(to_sample * mark);
162         data->gap[i++] = (int)(to_sample * space);
163     }
164     //fprintf(stderr, "read %d pulses\n", i);
165     data->num_pulses = i;
166 }
167 
pulse_data_print_pulse_header(FILE * file)168 void pulse_data_print_pulse_header(FILE *file)
169 {
170     char time_str[LOCAL_TIME_BUFLEN];
171 
172     chk_ret(fprintf(file, ";pulse data\n"));
173     chk_ret(fprintf(file, ";version 1\n"));
174     chk_ret(fprintf(file, ";timescale 1us\n"));
175     //chk_ret(fprintf(file, ";samplerate %u\n", data->sample_rate));
176     chk_ret(fprintf(file, ";created %s\n", format_time_str(time_str, NULL, 1, 0)));
177 }
178 
pulse_data_dump(FILE * file,pulse_data_t * data)179 void pulse_data_dump(FILE *file, pulse_data_t *data)
180 {
181     if (data->fsk_f2_est) {
182         chk_ret(fprintf(file, ";fsk %u pulses\n", data->num_pulses));
183         chk_ret(fprintf(file, ";freq1 %.0f\n", data->freq1_hz));
184         chk_ret(fprintf(file, ";freq2 %.0f\n", data->freq2_hz));
185     }
186     else {
187         chk_ret(fprintf(file, ";ook %u pulses\n", data->num_pulses));
188         chk_ret(fprintf(file, ";freq1 %.0f\n", data->freq1_hz));
189     }
190     chk_ret(fprintf(file, ";centerfreq %.0f Hz\n", data->centerfreq_hz));
191     chk_ret(fprintf(file, ";samplerate %u Hz\n", data->sample_rate));
192     chk_ret(fprintf(file, ";sampledepth %u bits\n", data->depth_bits));
193     chk_ret(fprintf(file, ";range %.1f dB\n", data->range_db));
194     chk_ret(fprintf(file, ";rssi %.1f dB\n", data->rssi_db));
195     chk_ret(fprintf(file, ";snr %.1f dB\n", data->snr_db));
196     chk_ret(fprintf(file, ";noise %.1f dB\n", data->noise_db));
197 
198     double to_us = 1e6 / data->sample_rate;
199     for (unsigned i = 0; i < data->num_pulses; ++i) {
200         chk_ret(fprintf(file, "%.0f %.0f\n", data->pulse[i] * to_us, data->gap[i] * to_us));
201     }
202     chk_ret(fprintf(file, ";end\n"));
203 }
204 
pulse_data_print_data(pulse_data_t * data)205 data_t *pulse_data_print_data(pulse_data_t *data)
206 {
207     int pulses[2 * PD_MAX_PULSES];
208     double to_us = 1e6 / data->sample_rate;
209     for (unsigned i = 0; i < data->num_pulses; ++i) {
210         pulses[i * 2 + 0] = data->pulse[i] * to_us;
211         pulses[i * 2 + 1] = data->gap[i] * to_us;
212     }
213 
214     /* clang-format off */
215     return data_make(
216             "mod",              "", DATA_STRING, (data->fsk_f2_est) ? "FSK" : "OOK",
217             "count",            "", DATA_INT,    data->num_pulses,
218             "pulses",           "", DATA_ARRAY,  data_array(2 * data->num_pulses, DATA_INT, pulses),
219             "freq1_Hz",         "", DATA_FORMAT, "%u Hz", DATA_INT, (unsigned)data->freq1_hz,
220             "freq2_Hz",         "", DATA_COND,   data->fsk_f2_est, DATA_FORMAT, "%u Hz", DATA_INT, (unsigned)data->freq2_hz,
221             "freq_Hz",          "", DATA_INT,    (unsigned)data->centerfreq_hz,
222             "rate_Hz",          "", DATA_INT,    data->sample_rate,
223             "depth_bits",       "", DATA_INT,    data->depth_bits,
224             "range_dB",         "", DATA_FORMAT, "%.1f dB", DATA_DOUBLE, data->range_db,
225             "rssi_dB",          "", DATA_FORMAT, "%.1f dB", DATA_DOUBLE, data->rssi_db,
226             "snr_dB",           "", DATA_FORMAT, "%.1f dB", DATA_DOUBLE, data->snr_db,
227             "noise_dB",         "", DATA_FORMAT, "%.1f dB", DATA_DOUBLE, data->noise_db,
228             NULL);
229     /* clang-format on */
230 }
231 
232 // OOK adaptive level estimator constants
233 #define OOK_MAX_HIGH_LEVEL  DB_TO_AMP(0)   // Maximum estimate for high level (-0 dB)
234 #define OOK_MAX_LOW_LEVEL   DB_TO_AMP(-15) // Maximum estimate for low level
235 #define OOK_EST_HIGH_RATIO  64          // Constant for slowness of OOK high level estimator
236 #define OOK_EST_LOW_RATIO   1024        // Constant for slowness of OOK low level (noise) estimator (very slow)
237 
238 /// Internal state data for pulse_pulse_package()
239 struct pulse_detect {
240     int use_mag_est;          ///< Whether the envelope data is an amplitude or magnitude.
241     int ook_fixed_high_level; ///< Manual detection level override, 0 = auto.
242     int ook_min_high_level;   ///< Minimum estimate of high level (-12 dB: 1000 amp, 4000 mag).
243     int ook_high_low_ratio;   ///< Default ratio between high and low (noise) level (9 dB: x8 amp, 11 dB: x3.6 mag).
244 
245     enum {
246         PD_OOK_STATE_IDLE      = 0,
247         PD_OOK_STATE_PULSE     = 1,
248         PD_OOK_STATE_GAP_START = 2,
249         PD_OOK_STATE_GAP       = 3
250     } ook_state;
251     int pulse_length; ///< Counter for internal pulse detection
252     int max_pulse;    ///< Size of biggest pulse detected
253 
254     int data_counter;    ///< Counter for how much of data chunk is processed
255     int lead_in_counter; ///< Counter for allowing initial noise estimate to settle
256 
257     int ook_low_estimate;  ///< Estimate for the OOK low level (base noise level) in the envelope data
258     int ook_high_estimate; ///< Estimate for the OOK high level
259 
260     int verbosity; ///< Debug output verbosity, 0=None, 1=Levels, 2=Histograms
261 
262     pulse_FSK_state_t FSK_state;
263 };
264 
pulse_detect_create()265 pulse_detect_t *pulse_detect_create()
266 {
267     pulse_detect_t *pulse_detect = calloc(1, sizeof(pulse_detect_t));
268     if (!pulse_detect) {
269         WARN_CALLOC("pulse_detect_create()");
270         return NULL;
271     }
272 
273     pulse_detect_set_levels(pulse_detect, 0, 0.0, -12.1442, 9.0, 0);
274 
275     return pulse_detect;
276 }
277 
pulse_detect_free(pulse_detect_t * pulse_detect)278 void pulse_detect_free(pulse_detect_t *pulse_detect)
279 {
280     free(pulse_detect);
281 }
282 
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)283 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)
284 {
285     pulse_detect->use_mag_est = use_mag_est;
286     if (use_mag_est) {
287         pulse_detect->ook_fixed_high_level = fixed_high_level < 0.0 ? DB_TO_MAG(fixed_high_level) : 0;
288         pulse_detect->ook_min_high_level   = DB_TO_MAG(min_high_level);
289         pulse_detect->ook_high_low_ratio = DB_TO_MAG_F(high_low_ratio);
290     }
291     else { // amp est
292         pulse_detect->ook_fixed_high_level = fixed_high_level < 0.0 ? DB_TO_AMP(fixed_high_level) : 0;
293         pulse_detect->ook_min_high_level   = DB_TO_AMP(min_high_level);
294         pulse_detect->ook_high_low_ratio = DB_TO_AMP_F(high_low_ratio);
295     }
296     pulse_detect->verbosity = verbosity;
297 
298     //fprintf(stderr, "fixed_high_level %.1f (%d), min_high_level %.1f (%d), high_low_ratio %.1f (%d)\n",
299     //        fixed_high_level, pulse_detect->ook_fixed_high_level,
300     //        min_high_level, pulse_detect->ook_min_high_level,
301     //        high_low_ratio, pulse_detect->ook_high_low_ratio);
302 }
303 
304 /// convert amplitude (16384 FS) to attenuation in (integer) dB, offset by 3.
amp_to_att(int a)305 static inline int amp_to_att(int a)
306 {
307     if (a > 32690) return 0;  // = 10^(( 3 + 42.1442) / 10)
308     if (a > 25967) return 1;  // = 10^(( 2 + 42.1442) / 10)
309     if (a > 20626) return 2;  // = 10^(( 1 + 42.1442) / 10)
310     if (a > 16383) return 3;  // = 10^(( 0 + 42.1442) / 10)
311     if (a > 13014) return 4;  // = 10^((-1 + 42.1442) / 10)
312     if (a > 10338) return 5;  // = 10^((-2 + 42.1442) / 10)
313     if (a >  8211) return 6;  // = 10^((-3 + 42.1442) / 10)
314     if (a >  6523) return 7;  // = 10^((-4 + 42.1442) / 10)
315     if (a >  5181) return 8;  // = 10^((-5 + 42.1442) / 10)
316     if (a >  4115) return 9;  // = 10^((-6 + 42.1442) / 10)
317     if (a >  3269) return 10; // = 10^((-7 + 42.1442) / 10)
318     if (a >  2597) return 11; // = 10^((-8 + 42.1442) / 10)
319     if (a >  2063) return 12; // = 10^((-9 + 42.1442) / 10)
320     if (a >  1638) return 13; // = 10^((-10 + 42.1442) / 10)
321     if (a >  1301) return 14; // = 10^((-11 + 42.1442) / 10)
322     if (a >  1034) return 15; // = 10^((-12 + 42.1442) / 10)
323     if (a >   821) return 16; // = 10^((-13 + 42.1442) / 10)
324     if (a >   652) return 17; // = 10^((-14 + 42.1442) / 10)
325     if (a >   518) return 18; // = 10^((-15 + 42.1442) / 10)
326     if (a >   412) return 19; // = 10^((-16 + 42.1442) / 10)
327     if (a >   327) return 20; // = 10^((-17 + 42.1442) / 10)
328     if (a >   260) return 21; // = 10^((-18 + 42.1442) / 10)
329     if (a >   206) return 22; // = 10^((-19 + 42.1442) / 10)
330     if (a >   164) return 23; // = 10^((-20 + 42.1442) / 10)
331     if (a >   130) return 24; // = 10^((-21 + 42.1442) / 10)
332     if (a >   103) return 25; // = 10^((-22 + 42.1442) / 10)
333     if (a >    82) return 26; // = 10^((-23 + 42.1442) / 10)
334     if (a >    65) return 27; // = 10^((-24 + 42.1442) / 10)
335     if (a >    52) return 28; // = 10^((-25 + 42.1442) / 10)
336     if (a >    41) return 29; // = 10^((-26 + 42.1442) / 10)
337     if (a >    33) return 30; // = 10^((-27 + 42.1442) / 10)
338     if (a >    26) return 31; // = 10^((-28 + 42.1442) / 10)
339     if (a >    21) return 32; // = 10^((-29 + 42.1442) / 10)
340     if (a >    16) return 33; // = 10^((-30 + 42.1442) / 10)
341     if (a >    13) return 34; // = 10^((-31 + 42.1442) / 10)
342     if (a >    10) return 35; // = 10^((-32 + 42.1442) / 10)
343     return 36;
344 }
345 /// convert magnitude (16384 FS) to attenuation in (integer) dB, offset by 3.
mag_to_att(int m)346 static inline int mag_to_att(int m)
347 {
348     if (m > 23143) return 0;  // = 10^(( 3 + 84.2884) / 20)
349     if (m > 20626) return 1;  // = 10^(( 2 + 84.2884) / 20)
350     if (m > 18383) return 2;  // = 10^(( 1 + 84.2884) / 20)
351     if (m > 16383) return 3;  // = 10^(( 0 + 84.2884) / 20)
352     if (m > 14602) return 4;  // = 10^((-1 + 84.2884) / 20)
353     if (m > 13014) return 5;  // = 10^((-2 + 84.2884) / 20)
354     if (m > 11599) return 6;  // = 10^((-3 + 84.2884) / 20)
355     if (m > 10338) return 7;  // = 10^((-4 + 84.2884) / 20)
356     if (m >  9213) return 8;  // = 10^((-5 + 84.2884) / 20)
357     if (m >  8211) return 9;  // = 10^((-6 + 84.2884) / 20)
358     if (m >  7318) return 10; // = 10^((-7 + 84.2884) / 20)
359     if (m >  6523) return 11; // = 10^((-8 + 84.2884) / 20)
360     if (m >  5813) return 12; // = 10^((-9 + 84.2884) / 20)
361     if (m >  5181) return 13; // = 10^((-10 + 84.2884) / 20)
362     if (m >  4618) return 14; // = 10^((-11 + 84.2884) / 20)
363     if (m >  4115) return 15; // = 10^((-12 + 84.2884) / 20)
364     if (m >  3668) return 16; // = 10^((-13 + 84.2884) / 20)
365     if (m >  3269) return 17; // = 10^((-14 + 84.2884) / 20)
366     if (m >  2914) return 18; // = 10^((-15 + 84.2884) / 20)
367     if (m >  2597) return 19; // = 10^((-16 + 84.2884) / 20)
368     if (m >  2314) return 20; // = 10^((-17 + 84.2884) / 20)
369     if (m >  2063) return 21; // = 10^((-18 + 84.2884) / 20)
370     if (m >  1838) return 22; // = 10^((-19 + 84.2884) / 20)
371     if (m >  1638) return 23; // = 10^((-20 + 84.2884) / 20)
372     if (m >  1460) return 24; // = 10^((-21 + 84.2884) / 20)
373     if (m >  1301) return 25; // = 10^((-22 + 84.2884) / 20)
374     if (m >  1160) return 26; // = 10^((-23 + 84.2884) / 20)
375     if (m >  1034) return 27; // = 10^((-24 + 84.2884) / 20)
376     if (m >   921) return 28; // = 10^((-25 + 84.2884) / 20)
377     if (m >   821) return 29; // = 10^((-26 + 84.2884) / 20)
378     if (m >   732) return 30; // = 10^((-27 + 84.2884) / 20)
379     if (m >   652) return 31; // = 10^((-28 + 84.2884) / 20)
380     if (m >   581) return 32; // = 10^((-29 + 84.2884) / 20)
381     if (m >   518) return 33; // = 10^((-30 + 84.2884) / 20)
382     if (m >   462) return 34; // = 10^((-31 + 84.2884) / 20)
383     if (m >   412) return 35; // = 10^((-32 + 84.2884) / 20)
384     return 36;
385 }
386 /// print a simple attenuation histogram.
print_att_hist(char const * s,int att_hist[])387 static void print_att_hist(char const *s, int att_hist[])
388 {
389     fprintf(stderr, "\n%s\n", s);
390     for (int i = 0; i < 37; ++i)
391         fprintf(stderr, ">%3d dB: %5d smps\n", 3 - i, att_hist[i]);
392 }
393 
394 /// Demodulate On/Off Keying (OOK) and Frequency Shift Keying (FSK) from an envelope signal
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)395 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)
396 {
397     int att_hist[37] = {0};
398     int const samples_per_ms = samp_rate / 1000;
399     pulse_detect_t *s = pulse_detect;
400     s->ook_high_estimate = MAX(s->ook_high_estimate, pulse_detect->ook_min_high_level);    // Be sure to set initial minimum level
401 
402     if (s->data_counter == 0) {
403         // age the pulse_data if this is a fresh buffer
404         pulses->start_ago += len;
405         fsk_pulses->start_ago += len;
406     }
407 
408     // Process all new samples
409     while (s->data_counter < len) {
410         // Calculate OOK detection threshold and hysteresis
411         int16_t const am_n    = envelope_data[s->data_counter];
412         if (pulse_detect->verbosity) {
413             int att = pulse_detect->use_mag_est ? mag_to_att(am_n) : amp_to_att(am_n);
414             att_hist[att]++;
415         }
416         int16_t ook_threshold = (s->ook_low_estimate + s->ook_high_estimate) / 2;
417         if (pulse_detect->ook_fixed_high_level != 0)
418             ook_threshold = pulse_detect->ook_fixed_high_level; // Manual override
419         int16_t const ook_hysteresis = ook_threshold / 8; // +-12%
420 
421         // OOK State machine
422         switch (s->ook_state) {
423             case PD_OOK_STATE_IDLE:
424                 if (am_n > (ook_threshold + ook_hysteresis)    // Above threshold?
425                         && s->lead_in_counter > OOK_EST_LOW_RATIO) { // Lead in counter to stabilize noise estimate
426                     // Initialize all data
427                     pulse_data_clear(pulses);
428                     pulse_data_clear(fsk_pulses);
429                     pulses->sample_rate = samp_rate;
430                     fsk_pulses->sample_rate = samp_rate;
431                     pulses->offset = sample_offset + s->data_counter;
432                     fsk_pulses->offset = sample_offset + s->data_counter;
433                     pulses->start_ago = len - s->data_counter;
434                     fsk_pulses->start_ago = len - s->data_counter;
435                     s->pulse_length = 0;
436                     s->max_pulse = 0;
437                     s->FSK_state = (pulse_FSK_state_t){0};
438                     s->FSK_state.var_test_max = INT16_MIN;
439                     s->FSK_state.var_test_min = INT16_MAX;
440                     s->FSK_state.skip_samples = 40;
441                     s->ook_state = PD_OOK_STATE_PULSE;
442                 }
443                 else {    // We are still idle..
444                     // Estimate low (noise) level
445                     int const ook_low_delta = am_n - s->ook_low_estimate;
446                     s->ook_low_estimate += ook_low_delta / OOK_EST_LOW_RATIO;
447                     s->ook_low_estimate += ((ook_low_delta > 0) ? 1 : -1);    // Hack to compensate for lack of fixed-point scaling
448                     // Calculate default OOK high level estimate
449                     s->ook_high_estimate = pulse_detect->ook_high_low_ratio * s->ook_low_estimate; // Default is a ratio of low level
450                     s->ook_high_estimate = MAX(s->ook_high_estimate, pulse_detect->ook_min_high_level);
451                     s->ook_high_estimate = MIN(s->ook_high_estimate, OOK_MAX_HIGH_LEVEL);
452                     if (s->lead_in_counter <= OOK_EST_LOW_RATIO) s->lead_in_counter++;        // Allow initial estimate to settle
453                 }
454                 break;
455             case PD_OOK_STATE_PULSE:
456                 s->pulse_length++;
457                 // End of pulse detected?
458                 if (am_n < (ook_threshold - ook_hysteresis)) {    // Gap?
459                     // Check for spurious short pulses
460                     if (s->pulse_length < PD_MIN_PULSE_SAMPLES) {
461                         s->ook_state = PD_OOK_STATE_IDLE;
462                     }
463                     else {
464                         // Continue with OOK decoding
465                         pulses->pulse[pulses->num_pulses] = s->pulse_length;    // Store pulse width
466                         s->max_pulse = MAX(s->pulse_length, s->max_pulse);    // Find largest pulse
467                         s->pulse_length = 0;
468                         s->ook_state = PD_OOK_STATE_GAP_START;
469                     }
470                 }
471                 // Still pulse
472                 else {
473                     // Calculate OOK high level estimate
474                     s->ook_high_estimate += am_n / OOK_EST_HIGH_RATIO - s->ook_high_estimate / OOK_EST_HIGH_RATIO;
475                     s->ook_high_estimate = MAX(s->ook_high_estimate, pulse_detect->ook_min_high_level);
476                     s->ook_high_estimate = MIN(s->ook_high_estimate, OOK_MAX_HIGH_LEVEL);
477                     // Estimate pulse carrier frequency
478                     pulses->fsk_f1_est += fm_data[s->data_counter] / OOK_EST_HIGH_RATIO - pulses->fsk_f1_est / OOK_EST_HIGH_RATIO;
479                 }
480                 // FSK Demodulation
481                 if (pulses->num_pulses == 0) {    // Only during first pulse
482                     if (fpdm == FSK_PULSE_DETECT_OLD)
483                         pulse_FSK_detect(fm_data[s->data_counter], fsk_pulses, &s->FSK_state);
484                     else
485                         pulse_FSK_detect_mm(fm_data[s->data_counter], fsk_pulses, &s->FSK_state);
486                 }
487                 break;
488             case PD_OOK_STATE_GAP_START:    // Beginning of gap - it might be a spurious gap
489                 s->pulse_length++;
490                 // Pulse detected again already? (This is a spurious short gap)
491                 if (am_n > (ook_threshold + ook_hysteresis)) {    // New pulse?
492                     s->pulse_length += pulses->pulse[pulses->num_pulses];    // Restore counter
493                     s->ook_state = PD_OOK_STATE_PULSE;
494                 }
495                 // Or this gap is for real?
496                 else if (s->pulse_length >= PD_MIN_PULSE_SAMPLES) {
497                     s->ook_state = PD_OOK_STATE_GAP;
498                     // Determine if FSK modulation is detected
499                     if (fsk_pulses->num_pulses > PD_MIN_PULSES) {
500                         // Store last pulse/gap
501                         if (fpdm == FSK_PULSE_DETECT_OLD)
502                             pulse_FSK_wrap_up(fsk_pulses, &s->FSK_state);
503                         // Store estimates
504                         fsk_pulses->fsk_f1_est = s->FSK_state.fm_f1_est;
505                         fsk_pulses->fsk_f2_est = s->FSK_state.fm_f2_est;
506                         fsk_pulses->ook_low_estimate = s->ook_low_estimate;
507                         fsk_pulses->ook_high_estimate = s->ook_high_estimate;
508                         pulses->end_ago = len - s->data_counter;
509                         fsk_pulses->end_ago = len - s->data_counter;
510                         s->ook_state = PD_OOK_STATE_IDLE;    // Ensure everything is reset
511                         if (pulse_detect->verbosity > 1)
512                             print_att_hist("PULSE_DATA_FSK", att_hist);
513                         if (pulse_detect->verbosity)
514                             fprintf(stderr, "Levels low: -%d dB  high: -%d dB  thres: -%d dB  hyst: (-%d to -%d dB)\n",
515                                     mag_to_att(s->ook_low_estimate), mag_to_att(s->ook_high_estimate),
516                                     mag_to_att(ook_threshold),
517                                     mag_to_att(ook_threshold + ook_hysteresis),
518                                     mag_to_att(ook_threshold - ook_hysteresis));
519                         return PULSE_DATA_FSK;
520                     }
521                 } // if
522                 // FSK Demodulation (continue during short gap - we might return...)
523                 if (pulses->num_pulses == 0) {    // Only during first pulse
524                     if (fpdm == FSK_PULSE_DETECT_OLD)
525                         pulse_FSK_detect(fm_data[s->data_counter], fsk_pulses, &s->FSK_state);
526                     else
527                         pulse_FSK_detect_mm(fm_data[s->data_counter], fsk_pulses, &s->FSK_state);
528                 }
529                 break;
530             case PD_OOK_STATE_GAP:
531                 s->pulse_length++;
532                 // New pulse detected?
533                 if (am_n > (ook_threshold + ook_hysteresis)) {    // New pulse?
534                     pulses->gap[pulses->num_pulses] = s->pulse_length;    // Store gap width
535                     pulses->num_pulses++;    // Next pulse
536 
537                     // EOP if too many pulses
538                     if (pulses->num_pulses >= PD_MAX_PULSES) {
539                         s->ook_state = PD_OOK_STATE_IDLE;
540                         // Store estimates
541                         pulses->ook_low_estimate = s->ook_low_estimate;
542                         pulses->ook_high_estimate = s->ook_high_estimate;
543                         pulses->end_ago = len - s->data_counter;
544                         if (pulse_detect->verbosity > 1)
545                             print_att_hist("PULSE_DATA_OOK MAX_PULSES", att_hist);
546                         return PULSE_DATA_OOK;    // End Of Package!!
547                     }
548 
549                     s->pulse_length = 0;
550                     s->ook_state = PD_OOK_STATE_PULSE;
551                 }
552 
553                 // EOP if gap is too long
554                 if (((s->pulse_length > (PD_MAX_GAP_RATIO * s->max_pulse))    // gap/pulse ratio exceeded
555                         && (s->pulse_length > (PD_MIN_GAP_MS * samples_per_ms)))    // Minimum gap exceeded
556                         || (s->pulse_length > (PD_MAX_GAP_MS * samples_per_ms))) {    // maximum gap exceeded
557                     pulses->gap[pulses->num_pulses] = s->pulse_length;    // Store gap width
558                     pulses->num_pulses++;    // Store last pulse
559                     s->ook_state = PD_OOK_STATE_IDLE;
560                     // Store estimates
561                     pulses->ook_low_estimate = s->ook_low_estimate;
562                     pulses->ook_high_estimate = s->ook_high_estimate;
563                     pulses->end_ago = len - s->data_counter;
564                     if (pulse_detect->verbosity > 1)
565                         print_att_hist("PULSE_DATA_OOK EOP", att_hist);
566                     if (pulse_detect->verbosity)
567                         fprintf(stderr, "Levels low: -%d dB  high: -%d dB  thres: -%d dB  hyst: (-%d to -%d dB)\n",
568                                 mag_to_att(s->ook_low_estimate), mag_to_att(s->ook_high_estimate),
569                                 mag_to_att(ook_threshold),
570                                 mag_to_att(ook_threshold + ook_hysteresis),
571                                 mag_to_att(ook_threshold - ook_hysteresis));
572                     return PULSE_DATA_OOK;    // End Of Package!!
573                 }
574                 break;
575             default:
576                 fprintf(stderr, "demod_OOK(): Unknown state!!\n");
577                 s->ook_state = PD_OOK_STATE_IDLE;
578         } // switch
579         s->data_counter++;
580     } // while
581 
582     s->data_counter = 0;
583     if (pulse_detect->verbosity > 2)
584         print_att_hist("Out of data", att_hist);
585     return 0;    // Out of data
586 }
587