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