1 /** @file
2     AM signal analyzer.
3 
4     Copyright (C) 2018 Christian Zuckschwerdt
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 <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #include "bitbuffer.h"
17 #include "samp_grab.h"
18 #include "fatal.h"
19 
20 #include "am_analyze.h"
21 
22 #define FRAME_END_MIN 50000 /* minimum sample count to detect frame end */
23 #define FRAME_PAD 10000 /* number of samples to pad both frame start and end */
24 
am_analyze_create(void)25 am_analyze_t *am_analyze_create(void)
26 {
27     am_analyze_t *a;
28     a = calloc(1, sizeof(am_analyze_t));
29     if (!a)
30         WARN_CALLOC("am_analyze_create()");
31     return a; // NOTE: returns NULL on alloc failure.
32 }
33 
am_analyze_free(am_analyze_t * a)34 void am_analyze_free(am_analyze_t *a)
35 {
36     free(a);
37 }
38 
am_analyze_skip(am_analyze_t * a,unsigned n_samples)39 void am_analyze_skip(am_analyze_t *a, unsigned n_samples)
40 {
41     a->counter += n_samples;
42     a->signal_start = 0;
43 }
44 
am_analyze(am_analyze_t * a,int16_t * am_buf,unsigned n_samples,int debug_output,samp_grab_t * g)45 void am_analyze(am_analyze_t *a, int16_t *am_buf, unsigned n_samples, int debug_output, samp_grab_t *g)
46 {
47     unsigned int i;
48     int threshold = (a->level_limit ? a->level_limit : 8000);  // Does not support auto level. Use old default instead.
49 
50     for (i = 0; i < n_samples; i++) {
51         if (am_buf[i] > threshold) {
52             if (!a->signal_start)
53                 a->signal_start = a->counter;
54             if (a->print) {
55                 a->pulses_found++;
56                 a->pulse_start = a->counter;
57                 a->signal_pulse_data[a->signal_pulse_counter][0] = a->counter;
58                 a->signal_pulse_data[a->signal_pulse_counter][1] = -1;
59                 a->signal_pulse_data[a->signal_pulse_counter][2] = -1;
60                 if (debug_output) {
61                     fprintf(stderr, "pulse_distance %u\n", a->counter - a->pulse_end);
62                     fprintf(stderr, "pulse_start distance %u\n", a->pulse_start - a->prev_pulse_start);
63                     fprintf(stderr, "pulse_start[%u] found at sample %u, value = %d\n", a->pulses_found, a->counter, am_buf[i]);
64                 }
65                 a->prev_pulse_start = a->pulse_start;
66                 a->print = 0;
67                 a->print2 = 1;
68             }
69         }
70         a->counter++;
71         if (am_buf[i] < threshold) {
72             if (a->print2) {
73                 a->pulse_avg += a->counter - a->pulse_start;
74                 if (debug_output) {
75                     fprintf(stderr, "pulse_end  [%u] found at sample %u, pulse length = %u, pulse avg length = %u\n",
76                             a->pulses_found, a->counter, a->counter - a->pulse_start, (a->pulses_found) ? (a->pulse_avg / a->pulses_found) : 0);
77                 }
78                 a->pulse_end = a->counter;
79                 a->print2 = 0;
80                 a->signal_pulse_data[a->signal_pulse_counter][1] = a->counter;
81                 a->signal_pulse_data[a->signal_pulse_counter][2] = a->counter - a->pulse_start;
82                 a->signal_pulse_counter++;
83                 if (a->signal_pulse_counter >= PULSE_DATA_SIZE) {
84                     a->signal_pulse_counter = 0;
85                     fprintf(stderr, "Too many pulses detected, probably bad input data or input parameters\n");
86                     return;
87                 }
88             }
89             a->print = 1;
90             if (a->signal_start && (a->pulse_end + FRAME_END_MIN < a->counter)) {
91                 unsigned padded_start = a->signal_start - FRAME_PAD;
92                 unsigned padded_end   = a->counter - FRAME_END_MIN + FRAME_PAD;
93                 unsigned padded_len   = padded_end - padded_start;
94                 fprintf(stderr, "*** signal_start = %u, signal_end = %u, signal_len = %u, pulses_found = %u\n",
95                         padded_start, padded_end, padded_len, a->pulses_found);
96 
97                 am_analyze_classify(a); // clears signal_pulse_data
98                 a->pulses_found = 0;
99 
100                 if (g) {
101                     samp_grab_write(g, padded_len, n_samples - i - 1);
102                 }
103                 a->signal_start = 0;
104             }
105         }
106     }
107 }
108 
109 
am_analyze_classify(am_analyze_t * aa)110 void am_analyze_classify(am_analyze_t *aa)
111 {
112     unsigned int i, k, max = 0, min = 1000000, t;
113     unsigned int delta, p_limit;
114     unsigned int a[3], b[2], a_cnt[3], a_new[3];
115     unsigned int signal_distance_data[PULSE_DATA_SIZE] = {0};
116     bitbuffer_t bits = {0};
117     unsigned int signal_type;
118 
119     if (!aa->signal_pulse_data[0][0])
120         return;
121 
122     for (i = 0; i < aa->signal_pulse_counter; i++) {
123         if (aa->signal_pulse_data[i][0] > 0) {
124             //fprintf(stderr, "[%03d] s: %d\t  e:\t %d\t l:%d\n",
125             //i, aa->signal_pulse_data[i][0], aa->signal_pulse_data[i][1],
126             //aa->signal_pulse_data[i][2]);
127             if (aa->signal_pulse_data[i][2] > max)
128                 max = aa->signal_pulse_data[i][2];
129             if (aa->signal_pulse_data[i][2] <= min)
130                 min = aa->signal_pulse_data[i][2];
131         }
132     }
133     t = (max + min) / 2;
134     //fprintf(stderr, "\n\nMax: %d, Min: %d  t:%d\n", max, min, t);
135 
136     delta = (max - min)*(max - min);
137 
138     //TODO use Lloyd-Max quantizer instead
139     k = 1;
140     while ((k < 10) && (delta > 0)) {
141         unsigned min_new = 0;
142         unsigned count_min = 0;
143         unsigned max_new = 0;
144         unsigned count_max = 0;
145 
146         for (i = 0; i < aa->signal_pulse_counter; i++) {
147             if (aa->signal_pulse_data[i][0] > 0) {
148                 if (aa->signal_pulse_data[i][2] < t) {
149                     min_new = min_new + aa->signal_pulse_data[i][2];
150                     count_min++;
151                 } else {
152                     max_new = max_new + aa->signal_pulse_data[i][2];
153                     count_max++;
154                 }
155             }
156         }
157         if (count_min != 0 && count_max != 0) {
158             min_new = min_new / count_min;
159             max_new = max_new / count_max;
160         }
161 
162         delta = (min - min_new)*(min - min_new) + (max - max_new)*(max - max_new);
163         min = min_new;
164         max = max_new;
165         t = (min + max) / 2;
166 
167         fprintf(stderr, "Iteration %u. t: %u    min: %u (%u)    max: %u (%u)    delta %u\n", k, t, min, count_min, max, count_max, delta);
168         k++;
169     }
170 
171     for (i = 0; i < aa->signal_pulse_counter; i++) {
172         if (aa->signal_pulse_data[i][0] > 0) {
173             //fprintf(stderr, "%d\n", aa->signal_pulse_data[i][1]);
174         }
175     }
176     /* 50% decision limit */
177     if (min != 0 && max / min > 1) {
178         fprintf(stderr, "Pulse coding: Short pulse length %u - Long pulse length %u\n", min, max);
179         signal_type = 2;
180     } else {
181         fprintf(stderr, "Distance coding: Pulse length %u\n", (min + max) / 2);
182         signal_type = 1;
183     }
184     p_limit = (max + min) / 2;
185 
186     /* Initial guesses */
187     a[0] = 1000000;
188     a[2] = 0;
189     for (i = 1; i < aa->signal_pulse_counter; i++) {
190         if (aa->signal_pulse_data[i][0] > 0) {
191             //               fprintf(stderr, "[%03d] s: %d\t  e:\t %d\t l:%d\t  d:%d\n",
192             //               i, aa->signal_pulse_data[i][0], aa->signal_pulse_data[i][1],
193             //               aa->signal_pulse_data[i][2], aa->signal_pulse_data[i][0]-aa->signal_pulse_data[i-1][1]);
194             signal_distance_data[i - 1] = aa->signal_pulse_data[i][0] - aa->signal_pulse_data[i - 1][1];
195             if (signal_distance_data[i - 1] > a[2])
196                 a[2] = signal_distance_data[i - 1];
197             if (signal_distance_data[i - 1] <= a[0])
198                 a[0] = signal_distance_data[i - 1];
199         }
200     }
201     min = a[0];
202     max = a[2];
203     a[1] = (a[0] + a[2]) / 2;
204     //    for (i=0 ; i<1 ; i++) {
205     //        b[i] = (a[i]+a[i+1])/2;
206     //    }
207     b[0] = (a[0] + a[1]) / 2;
208     b[1] = (a[1] + a[2]) / 2;
209     //     fprintf(stderr, "a[0]: %d\t a[1]: %d\t a[2]: %d\t\n",a[0],a[1],a[2]);
210     //     fprintf(stderr, "b[0]: %d\t b[1]: %d\n",b[0],b[1]);
211 
212     k = 1;
213     delta = 10000000;
214     while ((k < 10) && (delta > 0)) {
215         for (i = 0; i < 3; i++) {
216             a_new[i] = 0;
217             a_cnt[i] = 0;
218         }
219 
220         for (i = 0; i < aa->signal_pulse_counter; i++) {
221             if (signal_distance_data[i] > 0) {
222                 if (signal_distance_data[i] < b[0]) {
223                     a_new[0] += signal_distance_data[i];
224                     a_cnt[0]++;
225                 } else if (signal_distance_data[i] < b[1] && signal_distance_data[i] >= b[0]) {
226                     a_new[1] += signal_distance_data[i];
227                     a_cnt[1]++;
228                 } else if (signal_distance_data[i] >= b[1]) {
229                     a_new[2] += signal_distance_data[i];
230                     a_cnt[2]++;
231                 }
232             }
233         }
234 
235         //         fprintf(stderr, "Iteration %d.", k);
236         delta = 0;
237         for (i = 0; i < 3; i++) {
238             if (a_cnt[i])
239                 a_new[i] /= a_cnt[i];
240             delta += (a[i] - a_new[i])*(a[i] - a_new[i]);
241             //             fprintf(stderr, "\ta[%d]: %d (%d)", i, a_new[i], a[i]);
242             a[i] = a_new[i];
243         }
244         //         fprintf(stderr, " delta %d\n", delta);
245 
246         if (a[0] < min) {
247             a[0] = min;
248             //             fprintf(stderr, "Fixing a[0] = %d\n", min);
249         }
250         if (a[2] > max) {
251             a[0] = max;
252             //             fprintf(stderr, "Fixing a[2] = %d\n", max);
253         }
254         //         if (a[1] == 0) {
255         //             a[1] = (a[2]+a[0])/2;
256         //             fprintf(stderr, "Fixing a[1] = %d\n", a[1]);
257         //         }
258 
259         //         fprintf(stderr, "Iteration %d.", k);
260         for (i = 0; i < 2; i++) {
261             //             fprintf(stderr, "\tb[%d]: (%d) ", i, b[i]);
262             b[i] = (a[i] + a[i + 1]) / 2;
263             //             fprintf(stderr, "%d  ", b[i]);
264         }
265         //         fprintf(stderr, "\n");
266         k++;
267     }
268 
269     if (aa->override_short) {
270         p_limit = aa->override_short;
271         a[0] = aa->override_short;
272     }
273 
274     if (aa->override_long) {
275         a[1] = aa->override_long;
276     }
277 
278     fprintf(stderr, "\nShort distance: %u, long distance: %u, packet distance: %u\n", a[0], a[1], a[2]);
279     fprintf(stderr, "\np_limit: %u\n", p_limit);
280 
281     bitbuffer_clear(&bits);
282     if (signal_type == 1) {
283         for (i = 0; i < aa->signal_pulse_counter; i++) {
284             if (signal_distance_data[i] > 0) {
285                 if (signal_distance_data[i] < (a[0] + a[1]) / 2) {
286                     //                     fprintf(stderr, "0 [%d] %d < %d\n",i, signal_distance_data[i], (a[0]+a[1])/2);
287                     bitbuffer_add_bit(&bits, 0);
288                 } else if ((signal_distance_data[i] > (a[0] + a[1]) / 2) && (signal_distance_data[i] < (a[1] + a[2]) / 2)) {
289                     //                     fprintf(stderr, "0 [%d] %d > %d\n",i, signal_distance_data[i], (a[0]+a[1])/2);
290                     bitbuffer_add_bit(&bits, 1);
291                 } else if (signal_distance_data[i] > (a[1] + a[2]) / 2) {
292                     //                     fprintf(stderr, "0 [%d] %d > %d\n",i, signal_distance_data[i], (a[1]+a[2])/2);
293                     bitbuffer_add_row(&bits);
294                 }
295 
296             }
297 
298         }
299         bitbuffer_print(&bits);
300     }
301     if (signal_type == 2) {
302         for (i = 0; i < aa->signal_pulse_counter; i++) {
303             if (aa->signal_pulse_data[i][2] > 0) {
304                 if (aa->signal_pulse_data[i][2] < p_limit) {
305                     //                     fprintf(stderr, "0 [%d] %d < %d\n",i, aa->signal_pulse_data[i][2], p_limit);
306                     bitbuffer_add_bit(&bits, 0);
307                 } else {
308                     //                     fprintf(stderr, "1 [%d] %d > %d\n",i, aa->signal_pulse_data[i][2], p_limit);
309                     bitbuffer_add_bit(&bits, 1);
310                 }
311                 if ((signal_distance_data[i] >= (a[1] + a[2]) / 2)) {
312                     //                     fprintf(stderr, "\\n [%d] %d > %d\n",i, signal_distance_data[i], (a[1]+a[2])/2);
313                     bitbuffer_add_row(&bits);
314                 }
315 
316 
317             }
318         }
319         bitbuffer_print(&bits);
320     }
321 
322     // clear signal_pulse_data
323     aa->signal_pulse_counter = 0;
324 }
325