|
|
|
#include "board.hpp"
|
|
|
|
#include "midix.hpp"
|
|
|
|
#include "sysex.hpp"
|
|
|
|
#include <avrstuff/serial_avrdx.hpp>
|
|
|
|
#include <avrstuff/spi_avrdx.hpp>
|
|
|
|
#include <avr/interrupt.h>
|
|
|
|
#include <avr/pgmspace.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
static ringbuf<struct midi_message, 4> midi_q;
|
|
|
|
|
|
|
|
static serial_avrdx<2, 8> usbmidi_usart;
|
|
|
|
static midix midi(usbmidi_usart, midi_q);
|
|
|
|
|
|
|
|
// Plan: main pulls from an event queue. Events are generated from the MIDI
|
|
|
|
// receive vectors as well as from other sources (e.g. timers to implement
|
|
|
|
// portamento), in close to raw MIDI format via a struct. "Proprietary"
|
|
|
|
// commands are sent as a SysEx message with an ASCII command string. There is
|
|
|
|
// one global SysEx buffer per MIDI receiver, so a second message may not be
|
|
|
|
// sent until the acknowledge is received.
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
board_pins_init();
|
|
|
|
board_peripherals_init();
|
|
|
|
|
|
|
|
usbmidi_usart.set_baud(31250);
|
|
|
|
usbmidi_usart.start(true, true, 'N', false);
|
|
|
|
sei();
|
|
|
|
|
|
|
|
spi_avrdx<0> hspi;
|
|
|
|
hspi.init(spi_avrdx<0>::clockdiv::div2, true, 0);
|
|
|
|
|
|
|
|
usbmidi_usart.rxcie(true);
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
char info[64];
|
|
|
|
struct midi_message m;
|
|
|
|
if (!midi_q.pop(m))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
uint8_t cmd = MIDI_CMD(m.command);
|
|
|
|
uint8_t chan = MIDI_CMD_CHAN(m.command);
|
|
|
|
|
|
|
|
if (cmd == MIDI_ICMD_SYSEX)
|
|
|
|
{
|
|
|
|
sysex_handle(&m);
|
|
|
|
m.source->sysex_release_buffer(m.content);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void operator delete(void * p, unsigned int sz)
|
|
|
|
{
|
|
|
|
assert(false && "ouch!");
|
|
|
|
for(;;);
|
|
|
|
}
|
|
|
|
|
|
|
|
ISR(USART2_DRE_vect)
|
|
|
|
{
|
|
|
|
midi.dre();
|
|
|
|
}
|
|
|
|
|
|
|
|
ISR(USART2_RXC_vect)
|
|
|
|
{
|
|
|
|
midi.rxc();
|
|
|
|
}
|