move set_output() in main loop
[beacon-rx-433.git] / filter_avr.rst
1 Beacon RX
2 =========
3
4 Main design
5 -----------
6
7 We use a DRA886RX that receives the signal transmitted by the TX
8 beacon. The output of this component is a digital signal that could be
9 used to drive a buzze through a transistor. Doing this will be a
10 punishment for our ears because if there is no signal, we will output
11 a digital noise.
12
13 To detect the presence of the signal, we will use a microcontroler. It
14 will have 2 modes:
15
16 - bypass mode: in this case, the input is copied on the output, there
17   is no filtering.
18 - filter mode: the microcontroler will apply some filters on the input
19   signal and detect the square signal sent by the TX beacon. If it is
20   detected, a pure square signal is transmitted on the output, else
21   the output port stays to 0.
22
23 Filter details
24 --------------
25
26 To detect a 500 Hz square signal, we could use a FFT... but the AVR is
27 clearly too slow to do this in real time. So we decided to use 3
28 filters (FIR) running in parallel on specific frequencies.  We know
29 from its Fourier decomposition that a square signal is composed of
30 odd-integer harmonic frequencies (of the form 2π(2k-1)f). The power of
31 the first harmonic (n=3) is one third of the power of the fondamental
32 frequency.
33
34 ::
35   
36                +----------+       +----------+
37                |          |       |          |
38          +-----> fondamen.+-------> mean     +---------+
39          |     | bandpass |       | filter   |         |
40          |     |          |       |          |         |
41          |     +----------+       +----------+         |
42          |                                             |
43          |                                             v
44          |     +----------+       +----------+       +----------+
45          |     |          |       |          |       | is it the|
46   +------+-----> harm1    +-------> mean     +-------> signal we|
47          |     | bandpass |       | fiter    |       | are looking
48          |     |          |       |          |       | for ?    |
49          |     +----------+       +----------+       +----------+
50          |                                             ^
51          |                                             |
52          |     +----------+       +----------+         |
53          |     |          |       |          |         |
54          +-----> otherfreq+-------> mean     +---------+
55                | bandpass |       | filter   |
56                |          |       |          |
57                +----------+       +----------+
58
59
60 Generation of filter parameters
61 -------------------------------
62
63 We use a python script and the pylab module. This module contains a
64 function to generate the parameters of a simple low pass FIR from its
65 cutoff frequency and its order. We added some code done by Matti
66 Pastell found on the Internet to calculate the parameters of a
67 bandpass filter.
68
69 The script is ``fir.py``. It generates a graph of the filters, and a
70 function to be copied in the AVR code. This function has the loop
71 unrolled and all parameters in the code to enhance speed and memory
72 consumption.
73
74 .. figure:: filter.png
75    :width: 75%
76
77    Output of fir.py
78
79 The script assumes Fe=5Khz, Ffond=500hz, Fharm1=1500hz, Fother=850hz
80 but this can be modified. The order of the filter is 32. Run the
81 script as following::
82
83   python fir.py [filename]
84
85 Listen and view the result
86 --------------------------
87
88 The code can be compiled on a host. Thanks to this, we can try the
89 effect of the filter on a real audio input.  Four wav files have been
90 generated. They are sampled at 5Khz 16 bits, but each sample is
91 either -32768 or 32767, simulating a 1 bit sampling (like the output
92 of the DRA886RX):
93
94 - tone.wav: the perfect tone at 500 hz
95 - tone-lownoise.wav: the tone plus some noise
96 - tone-highnoise.wav: the tone plus a lot of noise
97 - noise.wav: only noise
98
99 These files are our reference test inputs.
100
101 Depending on how the code is compiled, it will use one of these files::
102
103   make H=1 WAV=WAV_TONE
104   make H=1 WAV=WAV_TONE_LOWNOISE
105   make H=1 WAV=WAV_TONE_HIGHNOISE
106   make H=1 WAV=WAV_NOISE
107
108 A script ``output_to_audio.py`` is used to display the result, and save
109 the output of each filter (fond, harm1 and other) in a separate wave
110 file.
111
112 In the figures below, the top graph represents the output power of
113 each filter. In blue "fond1", in green "harm1" and in red "other". The
114 bottom graph displays the output of the "signal detector". When the
115 green line is 500, the signal is detected.
116
117 To generate the images, start ``gen-img.sh``.
118
119 .. figure:: tone.png
120    :width: 75%
121
122    Filtering the pure tone
123
124 .. figure:: lownoise.png
125    :width: 75%
126
127    Filtering the tone with some noise
128
129 .. figure:: highnoise.png
130    :width: 75%
131
132    Filtering the tone wich a lot of noise
133
134 .. figure:: noise.png
135    :width: 75%
136
137    Filtering pure noise
138
139 Performance Test
140 ----------------
141
142 We can check that the program will run correctly on an AVR by using a
143 simulator. We use an atmega128 on the simulator because ATtiny45 is
144 not supported::
145
146   make
147   simulavr -g -p 1234 -d atmega128 -F binary main.bin
148
149 Then launch gdb::
150
151   avr-gdb main.elf
152   (gdb) target remote 127.0.0.1:1234
153   Remote debugging using 127.0.0.1:1234
154   0x00000000 in __vectors ()
155   (gdb) b main
156   (gdb) c
157   Continuing.
158   Breakpoint 1, main () at /home/zer0/projects/zavr/projects/fir/main.c:371
159   371
160    if ((pow_fond/3) > (pow_harm1/2) &&
161
162 Then add a breakpoint somewhere in the loop, and do several
163 "cont". The simulator displays the cycle value each time we go in a
164 breakpoint.
165
166 We measure between 450 and 750 cycles for one loop iteration, so it's
167 large enough to have Fe=5Khz !