use macros to read/write ports
[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 static void set_output(int16_t i)
348 {
349         int8_t detected = 0;
350
351         if (cpt_filter > 250)
352                 detected = 1;
353
354 #ifdef HOST_VERSION
355         printf("%d fil_fond=%d fil_harm1=%d fil_other=%d\n",
356                i, fil_fond, fil_harm1, fil_other);
357         printf("%d pow_fond=%d pow_harm1=%d pow_other=%d cpt_filter=%d detected=%d\n",
358                i, pow_fond, pow_harm1, pow_other, cpt_filter, detected);
359 #else
360         if (detected)
361                 LED_ON();
362         else
363                 LED_OFF();
364
365         /* when we receive, output a square signal at 625 hz */
366         if ((detected == 1) && (i & 4))
367                 BUZZER_ON();
368         else
369                 BUZZER_OFF();
370 #endif
371 }
372
373 /*
374   The CPU runs at 8Mhz.
375   Fe = 5Khz
376   Ffond = 500 hz
377   Fharm1 = 1500 hz
378   Fother = 1000 hz
379  */
380 int main(void)
381 {
382         int16_t i;
383
384         /* led and buzzer are outputs */
385 #if defined(__AVR_ATtiny45__)
386         DDRB |= (1 << LED_BIT) | (1 << BUZZER_BIT);
387 #endif
388
389         i = 0;
390         init_timer();
391
392         while (1) {
393
394                 wait_period();
395
396                 /* push one bit in bitfield */
397                 bitfield <<= 1UL;
398                 bitfield |= (uint32_t)get_input(i);
399
400                 apply_filters();
401                 mean_pow(&pow_fond, fil_fond);
402                 mean_pow(&pow_harm1, fil_harm1);
403                 mean_pow(&pow_other, fil_other);
404
405                 /* cpt_filter is increased when we consider that we are
406                  * receiving the signal */
407                 if ((pow_fond/3) > (pow_harm1/2) &&
408                     (pow_fond/2) > pow_other &&
409                     cpt_filter < MAX_CPT_FILTER)
410                         cpt_filter += 2;
411                 else if (cpt_filter > 0)
412                         cpt_filter--;
413
414                 set_output(i);
415
416                 i ++;
417 #ifdef HOST_VERSION
418                 if (i >= sizeof(x))
419                         break;
420 #endif
421         }
422
423         return 0;
424 }