poly-1-fw/main.cpp

101 lines
3.2 KiB
C++
Raw Normal View History

2022-08-16 00:17:16 +00:00
#include "board.hpp"
2022-08-28 00:03:34 +00:00
#include "midix.hpp"
2022-08-16 00:17:16 +00:00
#include <avrstuff/serial_avrdx.hpp>
#include <avrstuff/bufserial.hpp>
2022-08-28 00:03:34 +00:00
#include <avrstuff/spi_avrdx.hpp>
2022-08-16 00:17:16 +00:00
#include <avr/interrupt.h>
2022-08-28 00:03:34 +00:00
#include <avr/pgmspace.h>
2022-08-16 00:17:16 +00:00
#include <assert.h>
2022-08-28 00:03:34 +00:00
#include <string.h>
2022-08-16 00:17:16 +00:00
static serial_avrdx<2, 8> usbmidi_usart;
2022-08-28 00:03:34 +00:00
static bufserial<64, 64> usbmidi_buf(usbmidi_usart);
static ringbuf<struct midi_message, 4> midi_q;
static midix midi(usbmidi_usart, midi_q);
2022-08-16 00:17:16 +00:00
// 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();
2022-09-03 23:26:48 +00:00
board_peripherals_init();
2022-08-16 00:17:16 +00:00
2022-08-28 00:03:34 +00:00
usbmidi_usart.set_baud(31250);
2022-08-16 00:17:16 +00:00
usbmidi_usart.start(true, true, 'N', false);
2022-08-28 00:03:34 +00:00
usbmidi_buf.init();
2022-08-16 00:17:16 +00:00
sei();
2022-08-28 00:03:34 +00:00
spi_avrdx<0> hspi;
hspi.init(spi_avrdx<0>::clockdiv::div2, true, 0);
2022-08-16 00:17:16 +00:00
for (;;)
{
2022-08-28 00:03:34 +00:00
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);
switch (cmd)
{
case MIDI_ICMD_NOP: sprintf_P(info, PSTR("I NOP ")); break;
case MIDI_ICMD_SYSEX: sprintf_P(info, PSTR("I SYSEX ")); break;
case MIDI_ICMD_SYSEX_OVERFLOW: sprintf_P(info, PSTR("I SYSEX_OVERFLOW ")); break;
case MIDI_CMD_NOTE_OFF: sprintf_P(info, PSTR("NOTE_OFF [%X]"), chan); break;
case MIDI_CMD_NOTE_ON: sprintf_P(info, PSTR("NOTE_ON [%X]"), chan); break;
case MIDI_CMD_AFTERTOUCH: sprintf_P(info, PSTR("AFTERTOUCH [%X]"), chan); break;
case MIDI_CMD_CC: sprintf_P(info, PSTR("CC [%X]"), chan); break;
case MIDI_CMD_PATCH: sprintf_P(info, PSTR("PATCH [%X]"), chan); break;
case MIDI_CMD_PRESSURE: sprintf_P(info, PSTR("PRESSURE [%X]"), chan); break;
case MIDI_CMD_PITCHBEND: sprintf_P(info, PSTR("PITCHBEND [%X]"), chan); break;
case MIDI_CMD_START_SYSEX: sprintf_P(info, PSTR("START_SYSEX ")); break;
case MIDI_CMD_TUNE_REQ: sprintf_P(info, PSTR("TUNE_REQ ")); break;
case MIDI_CMD_END_SYSEX: sprintf_P(info, PSTR("END_SYSEX ")); break;
case MIDI_CMD_SYSRESET: sprintf_P(info, PSTR("SYSRESET ")); break;
default: sprintf_P(info, PSTR("WTF [%02x]"), m.command); break;
}
usbmidi_buf.send_str(info);
if (cmd == MIDI_ICMD_SYSEX)
{
usbmidi_buf.send_str((char const *) m.content);
hspi.transfer_block(m.content, m.content, strlen((char const *) m.content));
hspi.transfer_block(m.content, NULL, strlen((char const *) m.content));
m.source->sysex_release_buffer(m.content);
}
else
{
for (int i = 0; i < midi_num_args(cmd); i++)
{
sprintf_P(info, PSTR(" %02x"), m.arguments[i]);
usbmidi_buf.send_str(info);
}
}
usbmidi_buf.send_str("\r\n");
2022-08-16 00:17:16 +00:00
}
}
void operator delete(void * p, unsigned int sz)
{
assert(false && "ouch!");
for(;;);
}
ISR(USART2_DRE_vect)
{
usbmidi_buf.dre();
}
ISR(USART2_RXC_vect)
{
2022-08-28 00:03:34 +00:00
midi.rxc();
2022-08-16 00:17:16 +00:00
}