poly-1-fw/midix.hpp

85 lines
2.2 KiB
C++

// intellectual property is bullshit bgdc
#ifndef MIDIX_HPP
#define MIDIX_HPP
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#include <assert.h>
#include <etl/queue_spsc_locked.h>
#include <avrstuff/serial.hpp>
#include <avrstuff/ringbuf.hpp>
#include "midi.hpp"
#define MIDIX_SYSEX_LEN 64
#define MIDIX_SYSEX_OVERHEAD 2
// Must at least equal LEN + OVERHEAD, should be a power of 2
#define MIDIX_SYSEX_OUT_LEN 128
typedef iringbuf<struct midi_message> midi_iqueue;
// MIDI transceiver. MIDI messages are received from the RXC ISR and placed
// into a queue. Outgoing MIDI messages are transmitted from an internal
// queue.
class midix {
public:
midix(serial & serport, midi_iqueue & mq)
: m_serport(serport)
, m_sysex_buf_avail(true)
, m_message_pos(0)
, m_receiving_sysex(false)
, m_queue(mq)
{
m_message.source = this;
m_message.command = MIDI_ICMD_NOP;
}
// Receive Complete interrupt. Call within the serial port's RXC ISR.
void rxc();
// Data Register Empty interrupt. Call within the port's DRE ISR.
void dre();
// Transmit a raw message. Message is NUL terminated.
void send(uint8_t const * msg);
// Transmit a sysex message, adding the correct guard bytes. Message
// is NUL terminated.
void send_sysex(uint8_t const * msg);
// Release the sysex buffer. When a message is enqueued containing
// sysex content, it contains a reference to this midix's internal
// sysex buffer. This can only be used once, so it must be released
// when no longer needed. If another sysex is received while the buffer
// is held, it is rejected and becomes a MIDI_ICMD_SYSEX_OVERFLOW.
//
// buf: buffer to release. Must be the original buffer given in
// midi_message.content
void sysex_release_buffer(uint8_t * buf);
private:
// Send the current message and initialize it for the next one
void send()
{
m_queue.push(m_message);
m_message_pos = 0;
m_message.command = MIDI_ICMD_NOP;
m_receiving_sysex = false;
}
serial & m_serport;
uint8_t m_sysex_buf[MIDIX_SYSEX_LEN];
bool m_sysex_buf_avail;
struct midi_message m_message;
size_t m_message_pos;
bool m_receiving_sysex;
midi_iqueue & m_queue;
ringbuf<uint8_t, 128> m_outbuf;
};
#endif // !defined(MIDIX_HPP)