You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
7.2KB

  1. // Copyright 2016 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. #include <stm32f37x_conf.h>
  25. #include <cstring>
  26. #include "stmlib/system/bootloader_utils.h"
  27. #include "stmlib/system/flash_programming.h"
  28. #include "stmlib/system/system_clock.h"
  29. #include "stm_audio_bootloader/qpsk/packet_decoder.h"
  30. #include "stm_audio_bootloader/qpsk/demodulator.h"
  31. #include "plaits/drivers/audio_dac.h"
  32. #include "plaits/drivers/firmware_update_adc.h"
  33. #include "plaits/drivers/leds.h"
  34. #include "plaits/drivers/switches.h"
  35. extern "C" {
  36. void NMI_Handler() { }
  37. void HardFault_Handler() { while (1); }
  38. void MemManage_Handler() { while (1); }
  39. void BusFault_Handler() { while (1); }
  40. void UsageFault_Handler() { while (1); }
  41. void SVC_Handler() { }
  42. void DebugMon_Handler() { }
  43. void PendSV_Handler() { }
  44. }
  45. using namespace plaits;
  46. using namespace std;
  47. using namespace stm_audio_bootloader;
  48. using namespace stmlib;
  49. const double kSampleRate = 48000.0;
  50. const double kModulationRate = 6000.0;
  51. const double kBitRate = 12000.0;
  52. const uint32_t kStartAddress = 0x08008000;
  53. const uint16_t kPacketsPerPage = PAGE_SIZE / kPacketSize;
  54. enum UiState {
  55. UI_STATE_WAITING,
  56. UI_STATE_RECEIVING,
  57. UI_STATE_ERROR,
  58. UI_STATE_WRITING
  59. };
  60. AudioDac audio_dac;
  61. FirmwareUpdateAdc adc;
  62. Leds leds;
  63. Switches switches;
  64. PacketDecoder decoder;
  65. Demodulator demodulator;
  66. int discard_samples = 8000;
  67. int32_t peak = 0;
  68. int32_t gain_pot = 0;
  69. uint32_t current_address;
  70. uint16_t packet_index;
  71. uint8_t rx_buffer[PAGE_SIZE];
  72. volatile bool switch_released = false;
  73. volatile UiState ui_state;
  74. inline void UpdateLeds() {
  75. leds.Clear();
  76. // Show bargraph on the upper 4 LEDs.
  77. int32_t pwm = system_clock.milliseconds() & 15;
  78. leds.set(3, (peak >> 9) > pwm ? LED_COLOR_GREEN : 0);
  79. leds.set(2, ((peak - 8192) >> 9) >= pwm ? LED_COLOR_GREEN : 0);
  80. leds.set(1, ((peak - 16384) >> 9) >= pwm ? LED_COLOR_YELLOW : 0);
  81. leds.set(0, ((peak - 16384 - 8192) >> 9) >= pwm ? LED_COLOR_RED : 0);
  82. // Show status info on the lower 4 LEDs.
  83. switch (ui_state) {
  84. case UI_STATE_WAITING:
  85. {
  86. bool on = system_clock.milliseconds() & 128;
  87. for (int i = 4; i < 8; ++i) {
  88. leds.set(i, on ? LED_COLOR_YELLOW : LED_COLOR_OFF);
  89. }
  90. }
  91. break;
  92. case UI_STATE_RECEIVING:
  93. {
  94. int stage = (system_clock.milliseconds() >> 7) & 3;
  95. leds.set(stage + 4, LED_COLOR_GREEN);
  96. }
  97. break;
  98. case UI_STATE_ERROR:
  99. {
  100. bool on = system_clock.milliseconds() & 256;
  101. for (int i = 0; i < 8; ++i) {
  102. leds.set(i, on ? LED_COLOR_RED : LED_COLOR_OFF);
  103. }
  104. }
  105. break;
  106. case UI_STATE_WRITING:
  107. {
  108. for (uint8_t i = 4; i < 8; ++i) {
  109. leds.set(i, LED_COLOR_GREEN);
  110. }
  111. }
  112. break;
  113. }
  114. leds.Write();
  115. }
  116. extern "C" {
  117. void SysTick_Handler() {
  118. system_clock.Tick();
  119. switches.Debounce();
  120. if (switches.released(Switch(0))) {
  121. switch_released = true;
  122. }
  123. UpdateLeds();
  124. }
  125. }
  126. void ProgramPage(const uint8_t* data, size_t size) {
  127. FLASH_Unlock();
  128. FLASH_ErasePage(current_address);
  129. const uint32_t* words = static_cast<const uint32_t*>(
  130. static_cast<const void*>(data));
  131. for (size_t written = 0; written < size; written += 4) {
  132. FLASH_ProgramWord(current_address, *words++);
  133. current_address += 4;
  134. }
  135. }
  136. void FillBuffer(AudioDac::Frame* output, size_t size) {
  137. gain_pot = (adc.gain_pot() + 4095 * gain_pot) >> 12;
  138. int32_t sample = 32768 - static_cast<int32_t>(adc.sample());
  139. adc.Convert();
  140. int32_t gain = ((gain_pot >> 1) * gain_pot >> 21) + 128;
  141. sample = sample * gain >> 8;
  142. CONSTRAIN(sample, -32767, 32767)
  143. int32_t rect = abs(sample);
  144. peak = rect > peak ? rect : (rect + 32767 * peak) >> 15;
  145. if (!discard_samples) {
  146. demodulator.PushSample(2048 + (sample >> 4));
  147. } else {
  148. --discard_samples;
  149. }
  150. output->l = -sample;
  151. output->r = -sample;
  152. }
  153. void InitializeReception() {
  154. decoder.Init(1000, true);
  155. demodulator.Init(
  156. kModulationRate / kSampleRate * 4294967296.0,
  157. kSampleRate / kModulationRate,
  158. 2.0 * kSampleRate / kBitRate);
  159. demodulator.SyncCarrier(true);
  160. decoder.Reset();
  161. current_address = kStartAddress;
  162. packet_index = 0;
  163. ui_state = UI_STATE_WAITING;
  164. }
  165. void Init() {
  166. adc.Init();
  167. leds.Init();
  168. switches.Init();
  169. audio_dac.Init(48000, 1);
  170. audio_dac.Start(&FillBuffer);
  171. SysTick_Config(F_CPU / 1000);
  172. }
  173. int main(void) {
  174. Init();
  175. InitializeReception();
  176. bool exit_updater = !switches.pressed_immediate(Switch(0));
  177. while (!exit_updater) {
  178. bool error = false;
  179. if (demodulator.state() == DEMODULATOR_STATE_OVERFLOW) {
  180. error = true;
  181. } else {
  182. demodulator.ProcessAtLeast(32);
  183. }
  184. while (demodulator.available() && !error && !exit_updater) {
  185. uint8_t symbol = demodulator.NextSymbol();
  186. PacketDecoderState state = decoder.ProcessSymbol(symbol);
  187. switch (state) {
  188. case PACKET_DECODER_STATE_OK:
  189. {
  190. ui_state = UI_STATE_RECEIVING;
  191. memcpy(
  192. rx_buffer + (packet_index % kPacketsPerPage) * kPacketSize,
  193. decoder.packet_data(),
  194. kPacketSize);
  195. ++packet_index;
  196. if ((packet_index % kPacketsPerPage) == 0) {
  197. ui_state = UI_STATE_WRITING;
  198. ProgramPage(rx_buffer, PAGE_SIZE);
  199. decoder.Reset();
  200. demodulator.SyncCarrier(false);
  201. ui_state = UI_STATE_RECEIVING;
  202. } else {
  203. decoder.Reset();
  204. demodulator.SyncDecision();
  205. }
  206. }
  207. break;
  208. case PACKET_DECODER_STATE_ERROR_CRC:
  209. case PACKET_DECODER_STATE_ERROR_SYNC:
  210. error = true;
  211. break;
  212. break;
  213. case PACKET_DECODER_STATE_END_OF_TRANSMISSION:
  214. exit_updater = true;
  215. break;
  216. default:
  217. break;
  218. }
  219. }
  220. if (error) {
  221. ui_state = UI_STATE_ERROR;
  222. switch_released = false;
  223. while (!switch_released); // Polled in ISR
  224. InitializeReception();
  225. }
  226. }
  227. adc.DeInit();
  228. audio_dac.Stop();
  229. Uninitialize();
  230. JumpTo(kStartAddress);
  231. while (1) { }
  232. }