|
- // Copyright 2013 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/system/bootloader_utils.h"
- #include "stmlib/system/flash_programming.h"
- #include "stmlib/system/system_clock.h"
- #include "stmlib/utils/ring_buffer.h"
-
- #include "yarns/drivers/display.h"
- #include "yarns/drivers/encoder.h"
- #include "yarns/drivers/midi_io.h"
- #include "yarns/drivers/system.h"
-
- using namespace yarns;
- using namespace stmlib;
-
- System sys;
- Display display;
- Encoder encoder;
- MidiIO midi_io;
- RingBuffer<uint8_t, 128> midi_in_buffer;
-
- 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" {
-
- void SysTick_Handler() {
- static uint8_t counter;
- if ((++counter & 7) == 0) {
- system_clock.Tick(); // Tick global ms counter.
- uint32_t ms_clock = system_clock.milliseconds();
- if ((ms_clock & 0x3f) == 0 && display.mutable_buffer()[0] >= '\x98') {
- display.mutable_buffer()[0] = '\x98' + ((ms_clock >> 6) & 7);
- }
- display.RefreshSlow();
- encoder.Debounce();
- }
- display.RefreshFast();
-
- // Try to read some MIDI input.
- if (midi_io.readable()) {
- midi_in_buffer.Overwrite(midi_io.ImmediateRead());
- }
- }
-
- }
-
- void PrintByte(uint8_t byte) {
- char str[] = "00";
- str[0] += byte / 10;
- str[1] += byte % 10;
- display.Print(str);
- }
-
- static uint32_t current_address;
-
- 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;
- }
- }
-
- enum SysExReceptionState {
- MATCHING_HEADER = 0,
- READING_COMMAND = 1,
- READING_DATA = 2,
- };
-
- enum SysExReturnCode {
- SYSEX_RESULT_ERROR = 0,
- SYSEX_RESULT_OK = 1,
- SYSEX_RESULT_PAGE_WRITTEN = 2,
- SYSEX_RESULT_DONE = 3
- };
-
- static const uint8_t sysex_header[] = {
- 0xf0, // <SysEx>
- 0x00, 0x21, 0x02, // Mutable instruments manufacturer id.
- 0x00, 0x0b, // Product ID for Yarns.
- };
-
- static uint32_t bytes_read = 0;
- static uint16_t rx_buffer_index = 0;
- static SysExReceptionState state = MATCHING_HEADER;
- static uint8_t checksum;
- static uint8_t sysex_commands[2];
- static uint8_t page_index = 0;
- static uint8_t rx_buffer[PAGE_SIZE + 1];
- static uint8_t total_bytes = 0;
-
- const uint32_t kStartAddress = 0x08001000;
-
- void PrepareReception() {
- bytes_read = 0;
- rx_buffer_index = 0;
- state = MATCHING_HEADER;
- page_index = 0;
- current_address = kStartAddress;
- midi_in_buffer.Init();
-
- display.Print("\x98 ");
- }
-
- SysExReturnCode ProcessSysExByte(uint8_t byte) {
- if (byte > 0xf0 && byte != 0xf7) {
- return SYSEX_RESULT_OK;
- }
- ++total_bytes;
- switch (state) {
- case MATCHING_HEADER:
- if (byte == sysex_header[bytes_read]) {
- ++bytes_read;
- if (bytes_read == sizeof(sysex_header)) {
- bytes_read = 0;
- state = READING_COMMAND;
- }
- } else {
- bytes_read = 0;
- return SYSEX_RESULT_ERROR;
- }
- break;
-
- case READING_COMMAND:
- if (byte < 0x80) {
- sysex_commands[bytes_read++] = byte;
- if (bytes_read == 2) {
- bytes_read = 0;
- rx_buffer_index = 0;
- checksum = 0;
- state = READING_DATA;
- }
- } else {
- state = MATCHING_HEADER;
- bytes_read = 0;
- return SYSEX_RESULT_ERROR;
- }
- break;
-
- case READING_DATA:
- if (byte < 0x80) {
- if (bytes_read & 1) {
- rx_buffer[rx_buffer_index] |= byte & 0xf;
- if (rx_buffer_index < PAGE_SIZE) {
- checksum += rx_buffer[rx_buffer_index];
- }
- ++rx_buffer_index;
- } else {
- rx_buffer[rx_buffer_index] = (byte << 4);
- }
- ++bytes_read;
- } else if (byte == 0xf7) {
- if (sysex_commands[0] == 0x7f &&
- sysex_commands[1] == 0x00 &&
- bytes_read == 0) {
- return SYSEX_RESULT_DONE;
- } else if (rx_buffer_index == PAGE_SIZE + 1 &&
- sysex_commands[0] == 0x7e &&
- sysex_commands[1] == 0x00 &&
- rx_buffer[rx_buffer_index - 1] == checksum) {
- // Block write.
- ProgramPage(rx_buffer, PAGE_SIZE);
- ++page_index;
- }
- state = MATCHING_HEADER;
- bytes_read = 0;
- return SYSEX_RESULT_PAGE_WRITTEN;
- }
- break;
- }
- return SYSEX_RESULT_OK;
- }
-
- void Init() {
- SystemInit();
-
- RCC_APB2PeriphClockCmd(
- RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
- RCC_APB2Periph_TIM1 | RCC_APB2Periph_USART1, ENABLE);
-
- system_clock.Init();
- encoder.Init();
- display.Init();
- midi_io.Init();
-
- SysTick_Config(F_CPU / 8000);
- }
-
- int main(void) {
- Init();
- PrepareReception();
- bool exit_updater = !encoder.pressed_immediate();
- while (!exit_updater) {
- while (midi_in_buffer.readable() && !exit_updater) {
- SysExReturnCode result = ProcessSysExByte(midi_in_buffer.ImmediateRead());
- switch (result) {
- case SYSEX_RESULT_DONE:
- {
- display.Print("OK");
- system_clock.Delay(1000);
- exit_updater = true;
- }
- break;
-
- case SYSEX_RESULT_PAGE_WRITTEN:
- {
- PrintByte(page_index);
- }
- break;
-
- case SYSEX_RESULT_OK:
- break;
-
- case SYSEX_RESULT_ERROR:
- display.Print("Er");
- system_clock.Delay(1000);
- PrepareReception();
- break;
- }
- }
- }
- Uninitialize();
- JumpTo(kStartAddress);
- while (1) { }
- }
|