|
- // Copyright 2014 Olivier Gillet.
- //
- // Author: Olivier Gillet (ol.gillet@gmail.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- // See http://creativecommons.org/licenses/MIT/ for more information.
-
- #include <stm32f10x_conf.h>
- #include <string.h>
-
- #include "stmlib/utils/dsp.h"
- #include "stmlib/utils/ring_buffer.h"
- #include "stmlib/system/bootloader_utils.h"
- #include "stmlib/system/flash_programming.h"
- #include "stmlib/system/system_clock.h"
-
- #include "stm_audio_bootloader/qpsk/packet_decoder.h"
- #include "stm_audio_bootloader/qpsk/demodulator.h"
-
- #include "streams/drivers/adc.h"
- #include "streams/drivers/switches.h"
- #include "streams/drivers/leds.h"
- #include "streams/drivers/system.h"
-
- using namespace streams;
- using namespace stmlib;
- using namespace stm_audio_bootloader;
-
- const double kSampleRate = 48000.0;
- const double kModulationRate = 6000.0;
- const double kBitRate = 12000.0;
-
- const uint32_t kStartAddress = 0x08004000;
-
- Adc adc;
- System sys;
- Leds leds;
- Switches switches;
- PacketDecoder decoder;
- Demodulator demodulator;
-
-
- const int16_t wav_db[] = {
- -32768, -32768, -24576, -19783,
- -16384, -13746, -11591, -9770,
- -8192, -6799, -5554, -4428,
- -3399, -2453, -1578, -762,
- 0, 716, 1392, 2031,
- 2637, 3213, 3763, 4289,
- 4792, 5274, 5738, 6184,
- 6613, 7028, 7429, 7816,
- 8192, 8555, 8908, 9251,
- 9584, 9907, 10223, 10530,
- 10829, 11121, 11405, 11683,
- 11955, 12221, 12481, 12735,
- 12984, 13227, 13466, 13700,
- 13930, 14155, 14376, 14592,
- 14805, 15015, 15220, 15422,
- 15621, 15816, 16008, 16197,
- 16384, 16567, 16747, 16925,
- 17100, 17273, 17443, 17610,
- 17776, 17939, 18099, 18258,
- 18415, 18569, 18722, 18872,
- 19021, 19168, 19313, 19456,
- 19597, 19737, 19875, 20012,
- 20147, 20281, 20413, 20543,
- 20673, 20800, 20927, 21052,
- 21176, 21298, 21419, 21539,
- 21658, 21776, 21892, 22007,
- 22122, 22235, 22347, 22458,
- 22568, 22676, 22784, 22891,
- 22997, 23102, 23207, 23310,
- 23412, 23514, 23614, 23714,
- 23813, 23911, 24008, 24105,
- 24200, 24295, 24389, 24483,
- 24576, 24667, 24759, 24849,
- 24939, 25028, 25117, 25205,
- 25292, 25379, 25465, 25550,
- 25635, 25719, 25802, 25885,
- 25968, 26049, 26131, 26211,
- 26291, 26371, 26450, 26529,
- 26607, 26684, 26761, 26838,
- 26914, 26989, 27064, 27139,
- 27213, 27286, 27360, 27432,
- 27505, 27576, 27648, 27719,
- 27789, 27860, 27929, 27999,
- 28067, 28136, 28204, 28272,
- 28339, 28406, 28473, 28539,
- 28605, 28670, 28735, 28800,
- 28865, 28929, 28992, 29056,
- 29119, 29181, 29244, 29306,
- 29368, 29429, 29490, 29551,
- 29611, 29671, 29731, 29791,
- 29850, 29909, 29968, 30026,
- 30084, 30142, 30199, 30257,
- 30314, 30370, 30427, 30483,
- 30539, 30594, 30650, 30705,
- 30760, 30814, 30868, 30923,
- 30976, 31030, 31083, 31136,
- 31189, 31242, 31294, 31347,
- 31399, 31450, 31502, 31553,
- 31604, 31655, 31706, 31756,
- 31806, 31856, 31906, 31955,
- 32005, 32054, 32103, 32152,
- 32200, 32248, 32297, 32345,
- 32392, 32440, 32487, 32534,
- 32581, 32628, 32675, 32721,
- 32721,
- };
-
- extern "C" {
-
- void HardFault_Handler(void) { while (1); }
- void MemManage_Handler(void) { while (1); }
- void BusFault_Handler(void) { while (1); }
- void UsageFault_Handler(void) { while (1); }
- void NMI_Handler(void) { }
- void SVC_Handler(void) { }
- void DebugMon_Handler(void) { }
- void PendSV_Handler(void) { }
-
- }
-
- extern "C" {
-
- enum UiState {
- UI_STATE_WAITING,
- UI_STATE_RECEIVING,
- UI_STATE_ERROR,
- UI_STATE_PACKET_OK
- };
-
- volatile bool switch_released = false;
- volatile UiState ui_state;
- int32_t peak = 0;
- int32_t gain = 0;
-
- inline void UpdateLeds() {
- leds.Clear();
-
- // Show vu-meter on right side.
- int32_t rectified_sample = adc.cv(0) - 32768;
- rectified_sample = rectified_sample * gain >> 4;
- if (rectified_sample < 0) {
- rectified_sample = -rectified_sample;
- }
- if (rectified_sample > peak) {
- peak = rectified_sample;
- } else {
- peak += (rectified_sample - peak) * 130 >> 15;
- }
- leds.PaintPositiveBar(1, wav_db[peak >> 7] + 8192);
-
- // Show status info on left side (or whole display in case of error).
- switch (ui_state) {
- case UI_STATE_WAITING:
- {
- bool on = system_clock.milliseconds() & 128;
- if (on) {
- for (uint8_t i = 0; i < 4; ++i) {
- leds.set(i, 255, 255);
- }
- }
- }
- break;
-
- case UI_STATE_RECEIVING:
- {
- uint8_t stage = (system_clock.milliseconds() >> 7) & 3;
- leds.set(stage, 0, 255);
- }
- break;
-
- case UI_STATE_ERROR:
- {
- bool on = system_clock.milliseconds() & 256;
- for (uint8_t i = 0; i < 4; ++i) {
- leds.set(i, on ? 255 : 0, 0);
- }
- }
- break;
-
- case UI_STATE_PACKET_OK:
- {
- for (uint8_t i = 0; i < 4; ++i) {
- leds.set(i, 0, 255);
- }
- }
- break;
- }
- leds.Write();
- }
-
- void SysTick_Handler() {
- static uint8_t divider = 0;
-
- // SysTick is at 4kHz to get a fast bargraph refresh.
- ++divider;
- if ((divider & 3) == 0) {
- system_clock.Tick();
- system_clock.Tick(); // Tick global ms counter.
- switches.Debounce();
- if (switches.released(0)) {
- switch_released = true;
- }
- adc.ScanPots();
- gain = adc.pot(0) >> 11;
- UpdateLeds();
- }
- }
-
- uint16_t discard_samples = 8000;
-
- void TIM2_IRQHandler(void) {
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) == RESET) {
- return;
- }
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
-
- if (!discard_samples) {
- int32_t sample = adc.cv(0);
- sample -= 32768;
- sample = sample * gain >> 4;
- sample = (sample >> 4) + 2048;
- if (sample < 0) {
- sample = 0;
- } else if (sample > 4095) {
- sample = 4095;
- }
- demodulator.PushSample(sample);
- } else {
- --discard_samples;
- }
- }
-
- }
-
- static uint32_t current_address;
- static uint16_t packet_index;
-
- void ProgramPage(const uint8_t* data, size_t size) {
- FLASH_Unlock();
- FLASH_ErasePage(current_address);
- const uint32_t* words = static_cast<const uint32_t*>(
- static_cast<const void*>(data));
- for (size_t written = 0; written < size; written += 4) {
- FLASH_ProgramWord(current_address, *words++);
- current_address += 4;
- }
- }
-
- void Init() {
- sys.Init(false);
- system_clock.Init();
- adc.Init(true, NULL);
- switches.Init();
- leds.Init();
- sys.StartTimers();
- adc.Start();
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
- }
-
- void InitializeReception() {
- decoder.Init();
- demodulator.Init(
- kModulationRate / kSampleRate * 4294967296.0,
- kSampleRate / kModulationRate,
- 2.0 * kSampleRate / kBitRate);
- demodulator.SyncCarrier(true);
- decoder.Reset();
- current_address = kStartAddress;
- packet_index = 0;
- ui_state = UI_STATE_WAITING;
- }
-
- uint8_t rx_buffer[PAGE_SIZE];
- const uint16_t kPacketsPerPage = PAGE_SIZE / kPacketSize;
-
- int main(void) {
- Init();
- InitializeReception();
-
- bool exit_updater = !switches.pressed_immediate(0);
- while (!exit_updater) {
- bool error = false;
-
- if (demodulator.state() == DEMODULATOR_STATE_OVERFLOW) {
- error = true;
- } else {
- demodulator.ProcessAtLeast(32);
- }
-
- while (demodulator.available() && !error && !exit_updater) {
- uint8_t symbol = demodulator.NextSymbol();
- PacketDecoderState state = decoder.ProcessSymbol(symbol);
- switch (state) {
- case PACKET_DECODER_STATE_OK:
- {
- ui_state = UI_STATE_RECEIVING;
- memcpy(
- rx_buffer + (packet_index % kPacketsPerPage) * kPacketSize,
- decoder.packet_data(),
- kPacketSize);
- ++packet_index;
- if ((packet_index % kPacketsPerPage) == 0) {
- ui_state = UI_STATE_PACKET_OK;
- ProgramPage(rx_buffer, PAGE_SIZE);
- decoder.Reset();
- demodulator.SyncCarrier(false);
- ui_state = UI_STATE_RECEIVING;
- } else {
- decoder.Reset();
- demodulator.SyncDecision();
- }
- }
- break;
- case PACKET_DECODER_STATE_ERROR_SYNC:
- case PACKET_DECODER_STATE_ERROR_CRC:
- error = true;
- break;
- case PACKET_DECODER_STATE_END_OF_TRANSMISSION:
- exit_updater = true;
- break;
- default:
- break;
- }
- }
- if (error) {
- ui_state = UI_STATE_ERROR;
- switch_released = false;
- while (!switch_released); // Polled in ISR
- InitializeReception();
- }
- }
-
- adc.DeInit();
- Uninitialize();
- JumpTo(kStartAddress);
- while (1) { }
- }
|