1 // Copyright 2014 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 
25 #include <stm32f10x_conf.h>
26 #include <string.h>
27 
28 #include "stmlib/utils/dsp.h"
29 #include "stmlib/utils/ring_buffer.h"
30 #include "stmlib/system/bootloader_utils.h"
31 #include "stmlib/system/flash_programming.h"
32 #include "stmlib/system/system_clock.h"
33 
34 #include "stm_audio_bootloader/qpsk/packet_decoder.h"
35 #include "stm_audio_bootloader/qpsk/demodulator.h"
36 
37 #include "streams/drivers/adc.h"
38 #include "streams/drivers/switches.h"
39 #include "streams/drivers/leds.h"
40 #include "streams/drivers/system.h"
41 
42 using namespace streams;
43 using namespace stmlib;
44 using namespace stm_audio_bootloader;
45 
46 const double kSampleRate = 48000.0;
47 const double kModulationRate = 6000.0;
48 const double kBitRate = 12000.0;
49 
50 const uint32_t kStartAddress = 0x08004000;
51 
52 Adc adc;
53 System sys;
54 Leds leds;
55 Switches switches;
56 PacketDecoder decoder;
57 Demodulator demodulator;
58 
59 
60 const int16_t wav_db[] = {
61   -32768, -32768, -24576, -19783,
62   -16384, -13746, -11591,  -9770,
63    -8192,  -6799,  -5554,  -4428,
64    -3399,  -2453,  -1578,   -762,
65        0,    716,   1392,   2031,
66     2637,   3213,   3763,   4289,
67     4792,   5274,   5738,   6184,
68     6613,   7028,   7429,   7816,
69     8192,   8555,   8908,   9251,
70     9584,   9907,  10223,  10530,
71    10829,  11121,  11405,  11683,
72    11955,  12221,  12481,  12735,
73    12984,  13227,  13466,  13700,
74    13930,  14155,  14376,  14592,
75    14805,  15015,  15220,  15422,
76    15621,  15816,  16008,  16197,
77    16384,  16567,  16747,  16925,
78    17100,  17273,  17443,  17610,
79    17776,  17939,  18099,  18258,
80    18415,  18569,  18722,  18872,
81    19021,  19168,  19313,  19456,
82    19597,  19737,  19875,  20012,
83    20147,  20281,  20413,  20543,
84    20673,  20800,  20927,  21052,
85    21176,  21298,  21419,  21539,
86    21658,  21776,  21892,  22007,
87    22122,  22235,  22347,  22458,
88    22568,  22676,  22784,  22891,
89    22997,  23102,  23207,  23310,
90    23412,  23514,  23614,  23714,
91    23813,  23911,  24008,  24105,
92    24200,  24295,  24389,  24483,
93    24576,  24667,  24759,  24849,
94    24939,  25028,  25117,  25205,
95    25292,  25379,  25465,  25550,
96    25635,  25719,  25802,  25885,
97    25968,  26049,  26131,  26211,
98    26291,  26371,  26450,  26529,
99    26607,  26684,  26761,  26838,
100    26914,  26989,  27064,  27139,
101    27213,  27286,  27360,  27432,
102    27505,  27576,  27648,  27719,
103    27789,  27860,  27929,  27999,
104    28067,  28136,  28204,  28272,
105    28339,  28406,  28473,  28539,
106    28605,  28670,  28735,  28800,
107    28865,  28929,  28992,  29056,
108    29119,  29181,  29244,  29306,
109    29368,  29429,  29490,  29551,
110    29611,  29671,  29731,  29791,
111    29850,  29909,  29968,  30026,
112    30084,  30142,  30199,  30257,
113    30314,  30370,  30427,  30483,
114    30539,  30594,  30650,  30705,
115    30760,  30814,  30868,  30923,
116    30976,  31030,  31083,  31136,
117    31189,  31242,  31294,  31347,
118    31399,  31450,  31502,  31553,
119    31604,  31655,  31706,  31756,
120    31806,  31856,  31906,  31955,
121    32005,  32054,  32103,  32152,
122    32200,  32248,  32297,  32345,
123    32392,  32440,  32487,  32534,
124    32581,  32628,  32675,  32721,
125    32721,
126 };
127 
128 extern "C" {
129 
HardFault_Handler(void)130 void HardFault_Handler(void) { while (1); }
MemManage_Handler(void)131 void MemManage_Handler(void) { while (1); }
BusFault_Handler(void)132 void BusFault_Handler(void) { while (1); }
UsageFault_Handler(void)133 void UsageFault_Handler(void) { while (1); }
NMI_Handler(void)134 void NMI_Handler(void) { }
SVC_Handler(void)135 void SVC_Handler(void) { }
DebugMon_Handler(void)136 void DebugMon_Handler(void) { }
PendSV_Handler(void)137 void PendSV_Handler(void) { }
138 
139 }
140 
141 extern "C" {
142 
143 enum UiState {
144   UI_STATE_WAITING,
145   UI_STATE_RECEIVING,
146   UI_STATE_ERROR,
147   UI_STATE_PACKET_OK
148 };
149 
150 volatile bool switch_released = false;
151 volatile UiState ui_state;
152 int32_t peak = 0;
153 int32_t gain = 0;
154 
UpdateLeds()155 inline void UpdateLeds() {
156   leds.Clear();
157 
158   // Show vu-meter on right side.
159   int32_t rectified_sample = adc.cv(0) - 32768;
160   rectified_sample = rectified_sample * gain >> 4;
161   if (rectified_sample < 0) {
162     rectified_sample = -rectified_sample;
163   }
164   if (rectified_sample > peak) {
165     peak = rectified_sample;
166   } else {
167     peak += (rectified_sample - peak) * 130 >> 15;
168   }
169   leds.PaintPositiveBar(1, wav_db[peak >> 7] + 8192);
170 
171   // Show status info on left side (or whole display in case of error).
172   switch (ui_state) {
173     case UI_STATE_WAITING:
174       {
175         bool on = system_clock.milliseconds() & 128;
176         if (on) {
177           for (uint8_t i = 0; i < 4; ++i) {
178             leds.set(i, 255, 255);
179           }
180         }
181       }
182       break;
183 
184     case UI_STATE_RECEIVING:
185       {
186         uint8_t stage = (system_clock.milliseconds() >> 7) & 3;
187         leds.set(stage, 0, 255);
188       }
189       break;
190 
191     case UI_STATE_ERROR:
192       {
193         bool on = system_clock.milliseconds() & 256;
194         for (uint8_t i = 0; i < 4; ++i) {
195           leds.set(i, on ? 255 : 0, 0);
196         }
197       }
198       break;
199 
200     case UI_STATE_PACKET_OK:
201       {
202         for (uint8_t i = 0; i < 4; ++i) {
203           leds.set(i, 0, 255);
204         }
205       }
206       break;
207   }
208   leds.Write();
209 }
210 
SysTick_Handler()211 void SysTick_Handler() {
212   static uint8_t divider = 0;
213 
214   // SysTick is at 4kHz to get a fast bargraph refresh.
215   ++divider;
216   if ((divider & 3) == 0) {
217     system_clock.Tick();
218     system_clock.Tick();  // Tick global ms counter.
219     switches.Debounce();
220     if (switches.released(0)) {
221       switch_released = true;
222     }
223     adc.ScanPots();
224     gain = adc.pot(0) >> 11;
225     UpdateLeds();
226   }
227 }
228 
229 uint16_t discard_samples = 8000;
230 
TIM2_IRQHandler(void)231 void TIM2_IRQHandler(void) {
232   if (TIM_GetITStatus(TIM2, TIM_IT_Update) == RESET) {
233     return;
234   }
235 
236   TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
237 
238   if (!discard_samples) {
239     int32_t sample = adc.cv(0);
240     sample -= 32768;
241     sample = sample * gain >> 4;
242     sample = (sample >> 4) + 2048;
243     if (sample < 0) {
244       sample = 0;
245     } else if (sample > 4095) {
246       sample = 4095;
247     }
248     demodulator.PushSample(sample);
249   } else {
250     --discard_samples;
251   }
252 }
253 
254 }
255 
256 static uint32_t current_address;
257 static uint16_t packet_index;
258 
ProgramPage(const uint8_t * data,size_t size)259 void ProgramPage(const uint8_t* data, size_t size) {
260   FLASH_Unlock();
261   FLASH_ErasePage(current_address);
262   const uint32_t* words = static_cast<const uint32_t*>(
263       static_cast<const void*>(data));
264   for (size_t written = 0; written < size; written += 4) {
265     FLASH_ProgramWord(current_address, *words++);
266     current_address += 4;
267   }
268 }
269 
Init()270 void Init() {
271   sys.Init(false);
272   system_clock.Init();
273   adc.Init(true, NULL);
274   switches.Init();
275   leds.Init();
276   sys.StartTimers();
277   adc.Start();
278   TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
279 }
280 
InitializeReception()281 void InitializeReception() {
282   decoder.Init();
283   demodulator.Init(
284       kModulationRate / kSampleRate * 4294967296.0,
285       kSampleRate / kModulationRate,
286       2.0 * kSampleRate / kBitRate);
287   demodulator.SyncCarrier(true);
288   decoder.Reset();
289   current_address = kStartAddress;
290   packet_index = 0;
291   ui_state = UI_STATE_WAITING;
292 }
293 
294 uint8_t rx_buffer[PAGE_SIZE];
295 const uint16_t kPacketsPerPage = PAGE_SIZE / kPacketSize;
296 
main(void)297 int main(void) {
298   Init();
299   InitializeReception();
300 
301   bool exit_updater = !switches.pressed_immediate(0);
302   while (!exit_updater) {
303     bool error = false;
304 
305     if (demodulator.state() == DEMODULATOR_STATE_OVERFLOW) {
306       error = true;
307     } else {
308       demodulator.ProcessAtLeast(32);
309     }
310 
311     while (demodulator.available() && !error && !exit_updater) {
312       uint8_t symbol = demodulator.NextSymbol();
313       PacketDecoderState state = decoder.ProcessSymbol(symbol);
314       switch (state) {
315         case PACKET_DECODER_STATE_OK:
316           {
317             ui_state = UI_STATE_RECEIVING;
318             memcpy(
319                 rx_buffer + (packet_index % kPacketsPerPage) * kPacketSize,
320                 decoder.packet_data(),
321                 kPacketSize);
322             ++packet_index;
323             if ((packet_index % kPacketsPerPage) == 0) {
324               ui_state = UI_STATE_PACKET_OK;
325               ProgramPage(rx_buffer, PAGE_SIZE);
326               decoder.Reset();
327               demodulator.SyncCarrier(false);
328               ui_state = UI_STATE_RECEIVING;
329             } else {
330               decoder.Reset();
331               demodulator.SyncDecision();
332             }
333           }
334           break;
335         case PACKET_DECODER_STATE_ERROR_SYNC:
336         case PACKET_DECODER_STATE_ERROR_CRC:
337           error = true;
338           break;
339         case PACKET_DECODER_STATE_END_OF_TRANSMISSION:
340           exit_updater = true;
341           break;
342         default:
343           break;
344       }
345     }
346     if (error) {
347       ui_state = UI_STATE_ERROR;
348       switch_released = false;
349       while (!switch_released);  // Polled in ISR
350       InitializeReception();
351     }
352   }
353 
354   adc.DeInit();
355   Uninitialize();
356   JumpTo(kStartAddress);
357   while (1) { }
358 }
359