mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
Merge pull request #258 from versioduo/midi-packets
MIDI packet interface
This commit is contained in:
commit
f9262007ac
@ -56,11 +56,15 @@ typedef struct
|
|||||||
osal_mutex_def_t tx_ff_mutex;
|
osal_mutex_def_t tx_ff_mutex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We need to pack messages into words before queueing their transmission so buffer across write
|
// Messages are always 4 bytes long, queue them for reading and writing so the
|
||||||
// calls.
|
// callers can use the Stream interface with single-byte read/write calls.
|
||||||
uint8_t message_buffer[4];
|
uint8_t write_buffer[4];
|
||||||
uint8_t message_buffer_length;
|
uint8_t write_buffer_length;
|
||||||
uint8_t message_target_length;
|
uint8_t write_target_length;
|
||||||
|
|
||||||
|
uint8_t read_buffer[4];
|
||||||
|
uint8_t read_buffer_length;
|
||||||
|
uint8_t read_target_length;
|
||||||
|
|
||||||
// Endpoint Transfer buffer
|
// Endpoint Transfer buffer
|
||||||
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE];
|
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EPSIZE];
|
||||||
@ -93,24 +97,14 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id)
|
|||||||
uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize)
|
uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize)
|
||||||
{
|
{
|
||||||
(void) jack_id;
|
(void) jack_id;
|
||||||
return tu_fifo_read_n(&_midid_itf[itf].rx_ff, buffer, bufsize);
|
midid_interface_t* midi = &_midid_itf[itf];
|
||||||
}
|
|
||||||
|
|
||||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
|
// Fill empty buffer
|
||||||
{
|
if (midi->read_buffer_length == 0) {
|
||||||
(void) jack_id;
|
if (!tud_midi_n_receive(itf, midi->read_buffer))
|
||||||
tu_fifo_clear(&_midid_itf[itf].rx_ff);
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
|
uint8_t code_index = midi->read_buffer[0] & 0x0f;
|
||||||
if (bufsize % 4 != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(uint32_t i=0; i<bufsize; i += 4) {
|
|
||||||
uint8_t header = buffer[i];
|
|
||||||
// uint8_t cable_number = (header & 0xf0) >> 4;
|
|
||||||
uint8_t code_index = header & 0x0f;
|
|
||||||
// We always copy over the first byte.
|
// We always copy over the first byte.
|
||||||
uint8_t count = 1;
|
uint8_t count = 1;
|
||||||
// Ignore subsequent bytes based on the code.
|
// Ignore subsequent bytes based on the code.
|
||||||
@ -120,10 +114,40 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu
|
|||||||
count = 3;
|
count = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tu_fifo_write_n(&midi->rx_ff, &buffer[i + 1], count);
|
|
||||||
|
midi->read_buffer_length = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t n = midi->read_buffer_length - midi->read_target_length;
|
||||||
|
if (bufsize < n)
|
||||||
|
n = bufsize;
|
||||||
|
|
||||||
|
// Skip the header in the buffer
|
||||||
|
memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n);
|
||||||
|
midi->read_target_length += n;
|
||||||
|
|
||||||
|
if (midi->read_target_length == midi->read_buffer_length) {
|
||||||
|
midi->read_buffer_length = 0;
|
||||||
|
midi->read_target_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
|
||||||
|
{
|
||||||
|
(void) jack_id;
|
||||||
|
tu_fifo_clear(&_midid_itf[itf].rx_ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4])
|
||||||
|
{
|
||||||
|
return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
|
||||||
|
tu_fifo_write_n(&midi->rx_ff, buffer, bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// WRITE API
|
// WRITE API
|
||||||
@ -154,62 +178,59 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
|
|||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while (i < bufsize) {
|
while (i < bufsize) {
|
||||||
uint8_t data = buffer[i];
|
uint8_t data = buffer[i];
|
||||||
if (midi->message_buffer_length == 0) {
|
if (midi->write_buffer_length == 0) {
|
||||||
uint8_t msg = data >> 4;
|
uint8_t msg = data >> 4;
|
||||||
midi->message_buffer[1] = data;
|
midi->write_buffer[1] = data;
|
||||||
midi->message_buffer_length = 2;
|
midi->write_buffer_length = 2;
|
||||||
// Check to see if we're still in a SysEx transmit.
|
// Check to see if we're still in a SysEx transmit.
|
||||||
if (midi->message_buffer[0] == 0x4) {
|
if (midi->write_buffer[0] == 0x4) {
|
||||||
if (data == 0xf7) {
|
if (data == 0xf7) {
|
||||||
midi->message_buffer[0] = 0x5;
|
midi->write_buffer[0] = 0x5;
|
||||||
} else {
|
} else {
|
||||||
midi->message_buffer_length = 4;
|
midi->write_buffer_length = 4;
|
||||||
}
|
}
|
||||||
} else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
|
} else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
|
||||||
midi->message_buffer[0] = jack_id << 4 | msg;
|
midi->write_buffer[0] = jack_id << 4 | msg;
|
||||||
midi->message_target_length = 4;
|
midi->write_target_length = 4;
|
||||||
} else if (msg == 0xC || msg == 0xD) {
|
|
||||||
midi->message_buffer[0] = jack_id << 4 | msg;
|
|
||||||
midi->message_target_length = 3;
|
|
||||||
} else if (msg == 0xf) {
|
} else if (msg == 0xf) {
|
||||||
if (data == 0xf0) {
|
if (data == 0xf0) {
|
||||||
midi->message_buffer[0] = 0x4;
|
midi->write_buffer[0] = 0x4;
|
||||||
midi->message_target_length = 4;
|
midi->write_target_length = 4;
|
||||||
} else if (data == 0xf1 || data == 0xf3) {
|
} else if (data == 0xf1 || data == 0xf3) {
|
||||||
midi->message_buffer[0] = 0x2;
|
midi->write_buffer[0] = 0x2;
|
||||||
midi->message_target_length = 3;
|
midi->write_target_length = 3;
|
||||||
} else if (data == 0xf2) {
|
} else if (data == 0xf2) {
|
||||||
midi->message_buffer[0] = 0x3;
|
midi->write_buffer[0] = 0x3;
|
||||||
midi->message_target_length = 4;
|
midi->write_target_length = 4;
|
||||||
} else {
|
} else {
|
||||||
midi->message_buffer[0] = 0x5;
|
midi->write_buffer[0] = 0x5;
|
||||||
midi->message_target_length = 2;
|
midi->write_target_length = 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Pack individual bytes if we don't support packing them into words.
|
// Pack individual bytes if we don't support packing them into words.
|
||||||
midi->message_buffer[0] = jack_id << 4 | 0xf;
|
midi->write_buffer[0] = jack_id << 4 | 0xf;
|
||||||
midi->message_buffer[2] = 0;
|
midi->write_buffer[2] = 0;
|
||||||
midi->message_buffer[3] = 0;
|
midi->write_buffer[3] = 0;
|
||||||
midi->message_buffer_length = 2;
|
midi->write_buffer_length = 2;
|
||||||
midi->message_target_length = 2;
|
midi->write_target_length = 2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
midi->message_buffer[midi->message_buffer_length] = data;
|
midi->write_buffer[midi->write_buffer_length] = data;
|
||||||
midi->message_buffer_length += 1;
|
midi->write_buffer_length += 1;
|
||||||
// See if this byte ends a SysEx.
|
// See if this byte ends a SysEx.
|
||||||
if (midi->message_buffer[0] == 0x4 && data == 0xf7) {
|
if (midi->write_buffer[0] == 0x4 && data == 0xf7) {
|
||||||
midi->message_buffer[0] = 0x4 + (midi->message_buffer_length - 1);
|
midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1);
|
||||||
midi->message_target_length = midi->message_buffer_length;
|
midi->write_target_length = midi->write_buffer_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (midi->message_buffer_length == midi->message_target_length) {
|
if (midi->write_buffer_length == midi->write_target_length) {
|
||||||
uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->message_buffer, 4);
|
uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4);
|
||||||
if (written < 4) {
|
if (written < 4) {
|
||||||
TU_ASSERT( written == 0 );
|
TU_ASSERT( written == 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
midi->message_buffer_length = 0;
|
midi->write_buffer_length = 0;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -218,6 +239,22 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4])
|
||||||
|
{
|
||||||
|
midid_interface_t* midi = &_midid_itf[itf];
|
||||||
|
if (midi->itf_num == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tu_fifo_remaining(&midi->tx_ff) < 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
tu_fifo_write_n(&midi->tx_ff, packet, 4);
|
||||||
|
maybe_transmit(midi, itf);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// USBD Driver API
|
// USBD Driver API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -62,6 +62,9 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buf
|
|||||||
static inline
|
static inline
|
||||||
uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||||
|
|
||||||
|
bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]);
|
||||||
|
bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]);
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Application API (Interface0)
|
// Application API (Interface0)
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@ -71,6 +74,8 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize);
|
|||||||
static inline void tud_midi_read_flush (void);
|
static inline void tud_midi_read_flush (void);
|
||||||
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
||||||
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||||
|
static inline bool tud_midi_receive (uint8_t packet[4]);
|
||||||
|
static inline bool tud_midi_send (uint8_t const packet[4]);
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Application Callback API (weak is optional)
|
// Application Callback API (weak is optional)
|
||||||
@ -118,6 +123,16 @@ static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b
|
|||||||
return tud_midi_write(jack_id, msg, 3);
|
return tud_midi_write(jack_id, msg, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool tud_midi_receive (uint8_t packet[4])
|
||||||
|
{
|
||||||
|
return tud_midi_n_receive(0, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool tud_midi_send (uint8_t const packet[4])
|
||||||
|
{
|
||||||
|
return tud_midi_n_send(0, packet);
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Internal Class Driver API
|
// Internal Class Driver API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
Loading…
x
Reference in New Issue
Block a user