Skip to content

Commit 648da7b

Browse files
author
pichenettes
committed
Added MIDI bootloader
1 parent 25a56e7 commit 648da7b

File tree

6 files changed

+247
-1
lines changed

6 files changed

+247
-1
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "avrlib"]
22
path = avrlib
33
url = [email protected]:pichenettes/avril.git
4+
[submodule "tools"]
5+
path = tools
6+
url = [email protected]:pichenettes/avril-firmware_tools.git

bootloader/bootloader.cc

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright 2011 Olivier Gillet.
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
// This program is distributed in the hope that it will be useful,
8+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
// GNU General Public License for more details.
11+
// You should have received a copy of the GNU General Public License
12+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
13+
//
14+
// -----------------------------------------------------------------------------
15+
//
16+
// Bootloader supporting MIDI SysEx update.
17+
//
18+
// Caveat: assumes the firmware flashing is always done from first to last
19+
// block, in increasing order. Random access flashing is not supported!
20+
21+
#include <avr/boot.h>
22+
#include <avr/pgmspace.h>
23+
24+
#include "module_tester/hardware_config.h"
25+
#include "avrlib/devices/shift_register.h"
26+
#include "avrlib/gpio.h"
27+
#include "avrlib/serial.h"
28+
29+
using namespace avrlib;
30+
using namespace module_tester;
31+
32+
ShiftRegisterOutput<IOEnableLine, IOClockLine, IOOutputLine, 8, MSB_FIRST> status_leds;
33+
EncoderClickLine click;
34+
MidiIO midi;
35+
36+
uint16_t page = 0;
37+
uint8_t rx_buffer[2 * (SPM_PAGESIZE + 1)];
38+
39+
void (*main_entry_point)(void) = 0x0000;
40+
41+
inline void Init() {
42+
cli();
43+
click.set_mode(DIGITAL_INPUT);
44+
click.High();
45+
status_leds.Init();
46+
}
47+
48+
void WriteBufferToFlash() {
49+
uint16_t i;
50+
const uint8_t* p = rx_buffer;
51+
eeprom_busy_wait();
52+
53+
boot_page_erase(page);
54+
boot_spm_busy_wait();
55+
56+
for (i = 0; i < SPM_PAGESIZE; i += 2) {
57+
uint16_t w = *p++;
58+
w |= (*p++) << 8;
59+
boot_page_fill(page + i, w);
60+
}
61+
62+
boot_page_write(page);
63+
boot_spm_busy_wait();
64+
boot_rww_enable();
65+
}
66+
67+
static const uint8_t sysex_header[] = {
68+
0xf0, // <SysEx>
69+
0x00, 0x21, 0x02, // Manufacturer ID for Mutable instruments.
70+
0x00, 0x7f, // Product ID for other product.
71+
};
72+
73+
enum SysExReceptionState {
74+
MATCHING_HEADER = 0,
75+
READING_COMMAND = 1,
76+
READING_DATA = 2,
77+
};
78+
79+
inline void MidiLoop() {
80+
uint8_t byte;
81+
uint16_t bytes_read = 0;
82+
uint16_t rx_buffer_index;
83+
uint8_t state = MATCHING_HEADER;
84+
uint8_t checksum;
85+
uint8_t sysex_commands[2];
86+
uint8_t current_led = 1;
87+
uint8_t status = 0;
88+
uint8_t progress_counter = 0;
89+
90+
midi.Init();
91+
page = 0;
92+
status_leds.Write(0x55);
93+
while (1) {
94+
byte = midi.Read();
95+
// In case we see a realtime message in the stream, safely ignore it.
96+
if (byte > 0xf0 && byte != 0xf7) {
97+
continue;
98+
}
99+
status_leds.Write(status);
100+
switch (state) {
101+
case MATCHING_HEADER:
102+
if (byte == sysex_header[bytes_read]) {
103+
++bytes_read;
104+
if (bytes_read == sizeof(sysex_header)) {
105+
bytes_read = 0;
106+
state = READING_COMMAND;
107+
}
108+
} else {
109+
bytes_read = 0;
110+
}
111+
break;
112+
113+
case READING_COMMAND:
114+
if (byte < 0x80) {
115+
sysex_commands[bytes_read++] = byte;
116+
if (bytes_read == 2) {
117+
bytes_read = 0;
118+
rx_buffer_index = 0;
119+
checksum = 0;
120+
state = READING_DATA;
121+
}
122+
} else {
123+
state = MATCHING_HEADER;
124+
current_led = 1;
125+
status = 0;
126+
bytes_read = 0;
127+
}
128+
break;
129+
130+
case READING_DATA:
131+
if (byte < 0x80) {
132+
if (bytes_read & 1) {
133+
rx_buffer[rx_buffer_index] |= byte & 0xf;
134+
if (rx_buffer_index < SPM_PAGESIZE) {
135+
checksum += rx_buffer[rx_buffer_index];
136+
}
137+
++rx_buffer_index;
138+
} else {
139+
rx_buffer[rx_buffer_index] = (byte << 4);
140+
}
141+
++bytes_read;
142+
} else if (byte == 0xf7) {
143+
if (sysex_commands[0] == 0x7f &&
144+
sysex_commands[1] == 0x00 &&
145+
bytes_read == 0) {
146+
// Reset.
147+
return;
148+
} else if (rx_buffer_index == SPM_PAGESIZE + 1 &&
149+
sysex_commands[0] == 0x7e &&
150+
sysex_commands[1] == 0x00 &&
151+
rx_buffer[rx_buffer_index - 1] == checksum) {
152+
// Block write.
153+
WriteBufferToFlash();
154+
page += SPM_PAGESIZE;
155+
++progress_counter;
156+
if (progress_counter == 32) {
157+
status |= current_led;
158+
current_led <<= 1;
159+
if (current_led == 0) {
160+
current_led = 1;
161+
status = 0;
162+
}
163+
progress_counter = 0;
164+
}
165+
status ^= current_led;
166+
} else {
167+
current_led = 1;
168+
status = 0;
169+
}
170+
state = MATCHING_HEADER;
171+
bytes_read = 0;
172+
}
173+
break;
174+
}
175+
}
176+
}
177+
178+
int main(void) {
179+
uint8_t watchdog_status = MCUSR;
180+
MCUSR = 0;
181+
WDTCSR |= _BV(WDCE) | _BV(WDE);
182+
WDTCSR = 0;
183+
184+
Init();
185+
if (!click.value()) {
186+
MidiLoop();
187+
}
188+
status_leds.Write(0xaa);
189+
main_entry_point();
190+
}

bootloader/makefile

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2009 Olivier Gillet.
2+
#
3+
# This program is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
# This program is distributed in the hope that it will be useful,
8+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
# GNU General Public License for more details.
11+
# You should have received a copy of the GNU General Public License
12+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
13+
14+
VERSION = 0.01
15+
MCU_NAME = 644
16+
TARGET = module_tester_bootloader
17+
PACKAGES = bootloader
18+
EXTRA_DEFINES = -DDISABLE_DEFAULT_UART_RX_ISR -funsigned-char -fno-inline-small-functions -fmove-loop-invariants
19+
EXTRA_LD_FLAGS = ,--section-start=.text=0xfc00,--relax
20+
21+
LOCK = 2f
22+
LFUSE = ff
23+
HFUSE = d6
24+
EFUSE = fd
25+
26+
include avrlib/makefile.mk
27+
28+
include $(DEP_FILE)

makefile

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2009 Olivier Gillet.
2+
#
3+
# This program is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
# This program is distributed in the hope that it will be useful,
8+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
# GNU General Public License for more details.
11+
# You should have received a copy of the GNU General Public License
12+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
13+
14+
include module_tester/makefile
15+
16+
FIRMWARE = $(BUILD_DIR)module_tester.hex
17+
BOOTLOADER = $(BUILD_ROOT)module_tester_bootloader/module_tester_bootloader.hex
18+
19+
bootstrap_all: $(FIRMWARE) $(BOOTLOADER)
20+
make -f bootloader/makefile fuses
21+
$(AVRDUDE) -B 1 $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) \
22+
-U flash:w:$(FIRMWARE):i -U flash:w:$(BOOTLOADER):i \
23+
-U lock:w:0x2f:m

module_tester/makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ PACKAGES = avrlib module_tester
1818
RESOURCES = module_tester/resources
1919
EXTRA_DEFINES = -DDISABLE_DEFAULT_UART_RX_ISR
2020
EXTRA_LD_FLAGS = ,-u,vfprintf -lprintf_flt
21+
SYSEX_FLAGS = --page_size=128 --device_id=127
2122

2223
LFUSE = ff
23-
HFUSE = d4
24+
HFUSE = d6
2425
EFUSE = fd
2526
LOCK = 2f
2627

tools

Submodule tools added at 4a3b9a1

0 commit comments

Comments
 (0)