fix the button action
[beacon-rx-433.git] / main.c
1 #include <aversive.h>
2 #include <aversive/wait.h>
3
4 #include <string.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <inttypes.h>
8
9 #ifdef HOST_VERSION
10 #if defined(WAV_NOISE)
11 #include "noise.wav.c"
12 #elif defined(WAV_TONE_HIGHNOISE)
13 #include "tone-highnoise.wav.c"
14 #elif defined(WAV_TONE_LOWNOISE)
15 #include "tone-lownoise.wav.c"
16 #elif defined(WAV_TONE)
17 #include "tone.wav.c"
18 #endif
19 #endif
20
21 /* port B */
22 #define BUZZER_BIT    0
23 #define BUZZER_ON()   PORTB |= _BV(BUZZER_BIT)
24 #define BUZZER_OFF()  PORTB &= (~_BV(BUZZER_BIT))
25
26 #define RADIO_BIT  2
27 #define RADIO_READ() (!!(PINB & (_BV(RADIO_BIT))))
28
29 #define BUTTON_BIT 3
30 #define BUTTON_IS_PRESSED()  (!(PINB & (_BV(BUTTON_BIT))))
31
32 #define LED_BIT    4
33 #define LED_ON()   PORTB |= _BV(LED_BIT)
34 #define LED_OFF()  PORTB &= (~_BV(LED_BIT))
35
36 #define MODE_NO_FILTER     0
37 #define MODE_FILTER_THRES1 1
38 #define MODE_FILTER_THRES2 2
39 #define MODE_MAX           3
40
41 static uint32_t bitfield;
42
43 #ifdef HOST_VERSION
44 static int32_t fil_fond = 0;
45 static int32_t fil_harm1 = 0;
46 static int32_t fil_other = 0;
47 #else
48 static int16_t fil_fond = 0;
49 static int16_t fil_harm1 = 0;
50 static int16_t fil_other = 0;
51 #endif
52 static int16_t pow_fond = 0;
53 static int16_t pow_harm1 = 0;
54 static int16_t pow_other = 0;
55 static int16_t cpt_filter = 0;
56
57 #ifdef HOST_VERSION
58 /* when compiled for host, we check that there is no saturation when
59  * applying the filter. This should not happen as the gain of the
60  * filter is 1. */
61 int32_t saturate16(int32_t in)
62 {
63         if (in > 32767L) {
64                 in = 32767;
65                 printf("saturation\n");
66         }
67         if (fil_fond < -32768L) {
68                 in = -32768;
69                 printf("saturation\n");
70         }
71         return in;
72 }
73 #endif
74
75 /* Apply the 3 filters on the bitfield. The results are stored in
76  * fil_fond, fil_harm1 and fil_other. */
77 static void apply_filters(void)
78 {
79         fil_fond = 0;
80         fil_harm1 = 0;
81         fil_other = 0;
82
83         if (bitfield & (1UL << 0)) {
84                 fil_fond += -1781;
85                 fil_harm1 += -1217;
86                 fil_other += -1308;
87         }
88
89         if (bitfield & (1UL << 1)) {
90                 fil_fond += -1737;
91                 fil_harm1 += -1135;
92                 fil_other += -1830;
93         }
94
95         if (bitfield & (1UL << 2)) {
96                 fil_fond += -1024;
97                 fil_harm1 += 1922;
98                 fil_other += -446;
99         }
100
101         if (bitfield & (1UL << 3)) {
102                 fil_fond += 84;
103                 fil_harm1 += -60;
104                 fil_other += 1404;
105         }
106
107         if (bitfield & (1UL << 4)) {
108                 fil_fond += 1162;
109                 fil_harm1 += -1885;
110                 fil_other += 1790;
111         }
112
113         if (bitfield & (1UL << 5)) {
114                 fil_fond += 1791;
115                 fil_harm1 += 1235;
116                 fil_other += 306;
117         }
118
119         if (bitfield & (1UL << 6)) {
120                 fil_fond += 1725;
121                 fil_harm1 += 1113;
122                 fil_other += -1500;
123         }
124
125         if (bitfield & (1UL << 7)) {
126                 fil_fond += 986;
127                 fil_harm1 += -1933;
128                 fil_other += -1736;
129         }
130
131         if (bitfield & (1UL << 8)) {
132                 fil_fond += -141;
133                 fil_harm1 += 100;
134                 fil_other += -144;
135         }
136
137         if (bitfield & (1UL << 9)) {
138                 fil_fond += -1219;
139                 fil_harm1 += 1869;
140                 fil_other += 1605;
141         }
142
143         if (bitfield & (1UL << 10)) {
144                 fil_fond += -1819;
145                 fil_harm1 += -1288;
146                 fil_other += 1654;
147         }
148
149         if (bitfield & (1UL << 11)) {
150                 fil_fond += -1686;
151                 fil_harm1 += -1042;
152                 fil_other += -76;
153         }
154
155         if (bitfield & (1UL << 12)) {
156                 fil_fond += -842;
157                 fil_harm1 += 1972;
158                 fil_other += -1751;
159         }
160
161         if (bitfield & (1UL << 13)) {
162                 fil_fond += 424;
163                 fil_harm1 += -302;
164                 fil_other += -1478;
165         }
166
167         if (bitfield & (1UL << 14)) {
168                 fil_fond += 1660;
169                 fil_harm1 += -1750;
170                 fil_other += 708;
171         }
172
173         if (bitfield & (1UL << 15)) {
174                 fil_fond += 2416;
175                 fil_harm1 += 2399;
176                 fil_other += 2803;
177         }
178
179         if (bitfield & (1UL << 16)) {
180                 fil_fond += 2416;
181                 fil_harm1 += 2399;
182                 fil_other += 2803;
183         }
184
185         if (bitfield & (1UL << 17)) {
186                 fil_fond += 1660;
187                 fil_harm1 += -1750;
188                 fil_other += 708;
189         }
190
191         if (bitfield & (1UL << 18)) {
192                 fil_fond += 424;
193                 fil_harm1 += -302;
194                 fil_other += -1478;
195         }
196
197         if (bitfield & (1UL << 19)) {
198                 fil_fond += -842;
199                 fil_harm1 += 1972;
200                 fil_other += -1751;
201         }
202
203         if (bitfield & (1UL << 20)) {
204                 fil_fond += -1686;
205                 fil_harm1 += -1042;
206                 fil_other += -76;
207         }
208
209         if (bitfield & (1UL << 21)) {
210                 fil_fond += -1819;
211                 fil_harm1 += -1288;
212                 fil_other += 1654;
213         }
214
215         if (bitfield & (1UL << 22)) {
216                 fil_fond += -1219;
217                 fil_harm1 += 1869;
218                 fil_other += 1605;
219         }
220
221         if (bitfield & (1UL << 23)) {
222                 fil_fond += -141;
223                 fil_harm1 += 100;
224                 fil_other += -144;
225         }
226
227         if (bitfield & (1UL << 24)) {
228                 fil_fond += 986;
229                 fil_harm1 += -1933;
230                 fil_other += -1736;
231         }
232
233         if (bitfield & (1UL << 25)) {
234                 fil_fond += 1725;
235                 fil_harm1 += 1113;
236                 fil_other += -1500;
237         }
238
239         if (bitfield & (1UL << 26)) {
240                 fil_fond += 1791;
241                 fil_harm1 += 1235;
242                 fil_other += 306;
243         }
244
245         if (bitfield & (1UL << 27)) {
246                 fil_fond += 1162;
247                 fil_harm1 += -1885;
248                 fil_other += 1790;
249         }
250
251         if (bitfield & (1UL << 28)) {
252                 fil_fond += 84;
253                 fil_harm1 += -60;
254                 fil_other += 1404;
255         }
256
257         if (bitfield & (1UL << 29)) {
258                 fil_fond += -1024;
259                 fil_harm1 += 1922;
260                 fil_other += -446;
261         }
262
263         if (bitfield & (1UL << 30)) {
264                 fil_fond += -1737;
265                 fil_harm1 += -1135;
266                 fil_other += -1830;
267         }
268
269         if (bitfield & (1UL << 31)) {
270                 fil_fond += -1781;
271                 fil_harm1 += -1217;
272                 fil_other += -1308;
273         }
274
275 #ifdef HOST_VERSION
276         fil_fond = saturate16(fil_fond);
277         fil_harm1 = saturate16(fil_harm1);
278         fil_other = saturate16(fil_other);
279 #endif
280 }
281
282 /* Return abs(val) * 0.03125 + prev_out * 0.96875
283  * This is a simple "mean" filter. */
284 static inline void mean_pow(int16_t *state, int16_t val)
285 {
286         uint16_t new;
287
288         if (val > 0)
289                 new = val;
290         else
291                 new = -val;
292
293         new >>= 5;
294
295         /* new += prev_out * 0.96875 */
296         *state >>= 1;
297         new += *state;
298         *state >>= 1;
299         new += *state;
300         *state >>= 1;
301         new += *state;
302         *state >>= 1;
303         new += *state;
304         *state >>= 1;
305         new += *state;
306         *state >>= 1;
307         new += *state;
308
309         /* update state */
310         *state = new;
311 }
312
313 #define MAX_CPT_FILTER 500
314
315 /* init timer (only on real hw, not on simulator which simulates an
316  * ATmega128) */
317 static void init_timer(void)
318 {
319 #if defined(__AVR_ATtiny45__)
320         TCCR0A = 0;
321         TCCR0B = (1 << CS01); /* clk/8 = 1Mhz */
322 #endif
323 }
324
325 /* wait new ech period (only on real hw, not on simulator which
326  * simulates an ATmega128). period=200 -> 5 khz */
327 static void wait_period(void)
328 {
329 #if defined(__AVR_ATtiny45__)
330         static uint8_t prev = 0;
331         uint8_t cur, diff;
332
333         do {
334                 cur = TCNT0;
335                 diff = cur - prev;
336         } while (diff < 200);
337         prev = cur;
338 #endif
339 }
340
341 /* return the input: on host, we use the table generated from the wav
342  * file, on the attiny, we use the real PIN input */
343 static uint8_t get_input(int i)
344 {
345 #ifdef HOST_VERSION
346         return !!x[i];
347 #else
348         return RADIO_READ();
349 #endif
350 }
351
352 #ifndef HOST_VERSION
353 static void beep(void)
354 {
355         uint16_t i;
356
357         for (i = 0; i < 1000; i++) {
358                 if (i < 250 && (i & 1))
359                         BUZZER_ON();
360                 else
361                         BUZZER_OFF();
362                 wait_period();
363         }
364 }
365 #endif
366
367 /*
368   The CPU runs at 8Mhz.
369   Fe = 5Khz
370   Ffond = 500 hz
371   Fharm1 = 1500 hz
372   Fother = 1000 hz
373  */
374 int main(void)
375 {
376         int8_t detected = 0;
377         uint8_t mode = MODE_FILTER_THRES2;
378         int16_t i;
379 #ifndef HOST_VERSION
380         uint8_t button = 0, button_filter = 0;
381 #endif
382
383         /* led and buzzer are outputs */
384 #if defined(__AVR_ATtiny45__)
385         DDRB |= (1 << LED_BIT) | (1 << BUZZER_BIT);
386         PORTB |= (1 << BUTTON_BIT); /* pull up */
387 #endif
388
389         i = 0;
390         init_timer();
391
392         while (1) {
393
394                 /* wait until 200us is elapsed since previous call (5Khz) */
395                 wait_period();
396                 detected = 0;
397
398 #ifndef HOST_VERSION
399                 /* filter button */
400                 button = 0;
401                 if (BUTTON_IS_PRESSED() && button_filter < 10) {
402                         button_filter++;
403                         if (button_filter == 10)
404                                 button = 1;
405                 }
406                 else if (!BUTTON_IS_PRESSED())
407                         button_filter = 0;
408
409                 /* change mode if button is pressed */
410                 if (button) {
411                         uint8_t j;
412
413                         mode ++;
414                         if (mode >= MODE_MAX)
415                                 mode = 0;
416
417                         for (j = 0; j <= mode; j++)
418                                 beep();
419
420                         /* reset input history */
421                         bitfield = 0;
422                 }
423 #endif
424
425                 /* push one bit in bitfield */
426                 bitfield <<= 1UL;
427                 bitfield |= (uint32_t)get_input(i);
428
429                 /* filter the input */
430                 apply_filters();
431                 mean_pow(&pow_fond, fil_fond);
432                 mean_pow(&pow_harm1, fil_harm1);
433                 mean_pow(&pow_other, fil_other);
434
435                 /* cpt_filter is increased when we consider that we are
436                  * receiving the signal */
437                 if ((pow_fond/3) > (pow_harm1/2) &&
438                     (pow_fond/2) > pow_other &&
439                     cpt_filter < MAX_CPT_FILTER)
440                         cpt_filter += 2;
441                 else if (cpt_filter > 0)
442                         cpt_filter--;
443
444                 switch (mode) {
445                         case MODE_NO_FILTER:
446                         case MODE_FILTER_THRES1:
447                                 /* low threshold, some risk of false positive */
448                                 if (cpt_filter > 100)
449                                         detected = 1;
450                                 break;
451                         case MODE_FILTER_THRES2:
452                                 /* high threshold */
453                                 if (cpt_filter > 250)
454                                         detected = 1;
455                                 break;
456                         default:
457                                 break;
458                 }
459
460 #ifdef HOST_VERSION
461                 /* display values */
462                 printf("%d fil_fond=%d fil_harm1=%d fil_other=%d\n",
463                        i, fil_fond, fil_harm1, fil_other);
464                 printf("%d pow_fond=%d pow_harm1=%d pow_other=%d "
465                        "cpt_filter=%d detected=%d\n",
466                        i, pow_fond, pow_harm1, pow_other, cpt_filter, detected);
467 #else
468                 if (detected)
469                         LED_ON();
470                 else
471                         LED_OFF();
472
473                 /* if filtering is disabled, just copy the radio input
474                  * on the buzzer */
475                 if (mode == MODE_NO_FILTER) {
476                         if (RADIO_READ())
477                                 BUZZER_ON();
478                         else
479                                 BUZZER_OFF();
480                 }
481                 /* with filtering enabled, output a square signal at
482                  * 625 hz if beacon is detected */
483                 else {
484                         if ((detected == 1) && (i & 4))
485                                 BUZZER_ON();
486                         else
487                                 BUZZER_OFF();
488                 }
489 #endif
490
491                 i ++;
492
493 #ifdef HOST_VERSION
494                 /* exit when all samples are processed */
495                 if (i >= sizeof(x))
496                         break;
497 #endif
498         }
499
500         return 0;
501 }