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
Filesbranchesbootloader | |
---|---|
.. | |
bootloader.cc | |
makefile |
bootloader.cc// Copyright 2013 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/>. // // ----------------------------------------------------------------------------- // // Simple FSK bootloader #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/fsk/decoder.h" using namespace avrlib; using namespace avr_audio_bootloader; Gpio<PortD, 1> led_1_a; Gpio<PortD, 2> led_1_k; Gpio<PortB, 1> led_2_a; Gpio<PortB, 0> led_2_k; Gpio<PortD, 4> in_1; Gpio<PortC, 3> switch_1; Decoder decoder; uint16_t page = 0; uint8_t rx_buffer[SPM_PAGESIZE + 4]; int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9"))); inline void Init() { cli(); switch_1.set_mode(DIGITAL_INPUT); switch_1.High(); led_1_a.set_mode(DIGITAL_OUTPUT); led_1_k.set_mode(DIGITAL_OUTPUT); led_2_a.set_mode(DIGITAL_OUTPUT); led_2_k.set_mode(DIGITAL_OUTPUT); in_1.set_mode(DIGITAL_INPUT); in_1.High(); } 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 FlashLeds(bool error) { for (uint8_t i = 0; i < 8; ++i) { _delay_ms(20); if (error) { led_1_a.High(); led_1_k.Low(); } else { led_1_a.Low(); led_1_k.High(); } _delay_ms(20); led_1_a.Low(); led_1_k.Low(); } } uint32_t crc32 (uint32_t crc, uint8_t* buffer, uint8_t length) { crc = crc ^ ~0UL; for (uint8_t i = 0; i < length; ++i) { crc = crc ^ *buffer++; for (uint8_t j = 0; j < 8; j++) { if (crc & 1) { crc = (crc >> 1) ^ 0xEDB88320; } else { crc = crc >> 1; } } } crc = crc ^ ~0UL; return crc; } inline void LoaderLoop() { uint8_t page_byte = 0; decoder.Init(); decoder.Sync(); decoder.set_packet_destination(rx_buffer); page = 0; TCCR2A = 0; TCCR2B = 2; while (1) { // Sample the clock input at 15625 Hz and feed to the FSK decoder. if (TCNT2 >= (8000000 / 8 / 15625 - 1)) { TCNT2 = 0; led_2_a.set_value(page_byte & 1); led_2_k.set_value(!(page_byte & 1)); switch (decoder.PushSample(in_1.value())) { case DECODER_STATE_ERROR_SYNC: FlashLeds(true); decoder.Sync(); break; case DECODER_STATE_END_OF_TRANSMISSION: return; break; case DECODER_STATE_PACKET_RECEIVED: { #ifdef DO_NOT_CHECK_CRC uint32_t crc = 0; uint32_t expected_crc = 0; #else 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); #endif // DO_NOT_CHECK_CRC if (crc == expected_crc) { WriteBufferToFlash(); page += SPM_PAGESIZE; ++page_byte; } else { FlashLeds(true); } } decoder.Sync(); break; default: break; } } } } int main(void) { ResetWatchdog(); Init(); if (!switch_1.value()) { FlashLeds(false); LoaderLoop(); FlashLeds(false); } void (*main_entry_point)(void) = 0x0000; main_entry_point(); }