Files
-
blinds / hardware_design / pcb / blinds_v60.brd
-
blinds / hardware_design / pcb / blinds_v60.sch
-
braids / hardware_design / pcb / braids_v50.brd
-
braids / hardware_design / pcb / braids_v50.sch
-
branches / hardware_design / pcb / branches_v40.brd
-
branches / hardware_design / pcb / branches_v40.sch
-
clouds / hardware_design / pcb / clouds_v30.brd
-
clouds / hardware_design / pcb / clouds_v30.sch
-
ears / hardware_design / panel / ears_panel_v30.brd
-
ears / hardware_design / panel / ears_panel_v30.sch
-
ears / hardware_design / pcb / ears_v40.brd
-
ears / hardware_design / pcb / ears_v40.sch
-
edges / hardware_design / pcb / edges_expander_v01.brd
-
edges / hardware_design / pcb / edges_expander_v01.sch
-
edges / hardware_design / pcb / edges_v20.brd
-
edges / hardware_design / pcb / edges_v20.sch
-
elements / hardware_design / pcb / elements_v02.brd
-
elements / hardware_design / pcb / elements_v02.sch
-
frames / hardware_design / pcb / frames_v03.brd
-
frames / hardware_design / pcb / frames_v03.sch
-
grids / hardware_design / pcb / grids_v02.brd
-
grids / hardware_design / pcb / grids_v02.sch
-
kinks / hardware_design / pcb / kinks_v41.brd
-
kinks / hardware_design / pcb / kinks_v41.sch
-
links / hardware_design / pcb / links_v40.brd
-
links / hardware_design / pcb / links_v40.sch
-
marbles / hardware_design / pcb / marbles_v70.brd
-
marbles / hardware_design / pcb / marbles_v70.sch
-
peaks / hardware_design / pcb / peaks_v30.brd
-
peaks / hardware_design / pcb / peaks_v30.sch
-
plaits / hardware_design / pcb / plaits_v50.brd
-
plaits / hardware_design / pcb / plaits_v50.sch
-
rings / hardware_design / pcb / rings_v30.brd
-
rings / hardware_design / pcb / rings_v30.sch
-
ripples / hardware_design / pcb / ripples_v40.brd
-
ripples / hardware_design / pcb / ripples_v40.sch
-
shades / hardware_design / pcb / shades_v30.brd
-
shades / hardware_design / pcb / shades_v30.sch
-
shelves / hardware_design / pcb / shelves_expander_v10.brd
-
shelves / hardware_design / pcb / shelves_expander_v10.sch
-
shelves / hardware_design / pcb / shelves_v05.brd
-
shelves / hardware_design / pcb / shelves_v05.sch
-
stages / hardware_design / pcb / stages_v70.brd
-
stages / hardware_design / pcb / stages_v70.sch
-
streams / hardware_design / pcb / streams_v02_bargraph.brd
-
streams / hardware_design / pcb / streams_v02_bargraph.sch
-
streams / hardware_design / pcb / streams_v05.brd
-
streams / hardware_design / pcb / streams_v05.sch
-
tides / hardware_design / pcb / tides_v40.brd
-
tides / hardware_design / pcb / tides_v40.sch
-
veils / hardware_design / pcb / veils_v40.brd
-
veils / hardware_design / pcb / veils_v40.sch
-
volts / hardware_design / pcb / volts_v01.brd
-
volts / hardware_design / pcb / volts_v01.sch
-
warps / hardware_design / pcb / warps_v30.brd
-
warps / hardware_design / pcb / warps_v30.sch
-
yarns / hardware_design / pcb / yarns_v03.brd
-
yarns / hardware_design / pcb / yarns_v03.sch
Last update 6 years 1 month
by
Olivier Gillet
Filesgridsbootloader | |
---|---|
.. | |
bootloader.cc | |
makefile |
bootloader.cc// Copyright 2011 Olivier Gillet. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // ----------------------------------------------------------------------------- // // Bootloader supporting MIDI SysEx update. // // Caveat: assumes the firmware flashing is always done from first to last // block, in increasing order. Random access flashing is not supported! #include <avr/boot.h> #include <avr/pgmspace.h> #include <avr/delay.h> #include "avrlib/gpio.h" #include "avrlib/serial.h" #include "avrlib/watchdog_timer.h" #include "avr_audio_bootloader/crc32.h" #include "avr_audio_bootloader/fsk/decoder.h" #include "grids/hardware_config.h" using namespace avrlib; using namespace grids; using namespace avr_audio_bootloader; MidiInput midi; Inputs inputs; Leds leds; Decoder decoder; uint16_t page = 0; uint8_t rx_buffer[SPM_PAGESIZE + 4]; void (*main_entry_point)(void) = 0x0000; inline void Init() { cli(); leds.set_mode(DIGITAL_OUTPUT); inputs.set_mode(DIGITAL_INPUT); inputs.EnablePullUpResistors(); } void WriteBufferToFlash() { uint16_t i; const uint8_t* p = rx_buffer; eeprom_busy_wait(); boot_page_erase(page); boot_spm_busy_wait(); for (i = 0; i < SPM_PAGESIZE; i += 2) { uint16_t w = *p++; w |= (*p++) << 8; boot_page_fill(page + i, w); } boot_page_write(page); boot_spm_busy_wait(); boot_rww_enable(); } void FlashLedsOk() { for (uint8_t i = 0; i < 8; ++i) { _delay_ms(50); leds.Write(0xf); _delay_ms(50); leds.Write(LED_CLOCK); } } void FlashLedsError() { for (uint8_t i = 0; i < 5; ++i) { _delay_ms(120); leds.Write(0xf); _delay_ms(120); leds.Write(0x0); } } // MIDI loader ----------------------------------------------------------------- static const uint8_t sysex_header[] = { 0xf0, // <SysEx> 0x00, 0x21, 0x02, // Mutable instruments manufacturer id. 0x00, 0x09, // Product ID for Grids. }; enum SysExReceptionState { MATCHING_HEADER = 0, READING_COMMAND = 1, READING_DATA = 2, }; inline void LoaderLoop() { uint8_t byte; uint16_t bytes_read = 0; uint16_t rx_buffer_index; uint8_t state = MATCHING_HEADER; uint8_t checksum; uint8_t sysex_commands[2]; uint8_t status = 0; uint8_t page_byte = 0; midi.Init(); decoder.Init(); decoder.Sync(); decoder.set_packet_destination(rx_buffer); page = 0; TCCR2A = 0; TCCR2B = 2; while (1) { leds.Write(LED_CLOCK | (LED_BD >> ((page_byte + 3) & 0x3))); // Sample the clock input at 20kHz and feed to the FSK decoder. if (TCNT2 >= (F_CPU / 8 / 40000 - 1)) { TCNT2 = 0; switch (decoder.PushSample(inputs.Read() & INPUT_CLOCK)) { case DECODER_STATE_ERROR_SYNC: FlashLedsError(); decoder.Sync(); break; case DECODER_STATE_END_OF_TRANSMISSION: return; break; case DECODER_STATE_PACKET_RECEIVED: { uint32_t crc = crc32(0, rx_buffer, SPM_PAGESIZE); uint32_t expected_crc = \ (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 0]) << 24) | \ (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 1]) << 16) | \ (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 2]) << 8) | \ (static_cast<uint32_t>(rx_buffer[SPM_PAGESIZE + 3]) << 0); if (crc == expected_crc) { WriteBufferToFlash(); page += SPM_PAGESIZE; ++page_byte; } else { FlashLedsError(); } } decoder.Sync(); break; default: break; } } // Poll the MIDI input. if (midi.readable()) { byte = midi.ImmediateRead(); if (byte > 0xf0 && byte != 0xf7) { continue; } 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; } 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; status = 0; bytes_read = 0; } break; case READING_DATA: if (byte < 0x80) { if (bytes_read & 1) { rx_buffer[rx_buffer_index] |= byte & 0xf; if (rx_buffer_index < SPM_PAGESIZE) { 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) { // Reset. return; } else if (rx_buffer_index == SPM_PAGESIZE + 1 && sysex_commands[0] == 0x7e && sysex_commands[1] == 0x00 && rx_buffer[rx_buffer_index - 1] == checksum) { // Block write. WriteBufferToFlash(); page += SPM_PAGESIZE; ++page_byte; } else { FlashLedsError(); } state = MATCHING_HEADER; bytes_read = 0; } break; } } } } int main(void) { ResetWatchdog(); Init(); _delay_ms(40); if (!(inputs.Read() & INPUT_SW_RESET)) { FlashLedsOk(); LoaderLoop(); FlashLedsOk(); FlashLedsOk(); } main_entry_point(); }