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