From c5aa661c892159b2eced9b2e3c1a4a1d8f92b1f6 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 23:54:17 +0700 Subject: [PATCH 01/11] rename tud_midi_receive/send to tud_midi_packet_read/write --- src/class/midi/midi_device.c | 6 +++--- src/class/midi/midi_device.h | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 29019cc1..3772c475 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -127,7 +127,7 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t // Fill empty buffer if (midi->read_buffer_length == 0) { - if (!tud_midi_n_receive(itf, midi->read_buffer)) return 0; + if (!tud_midi_n_packet_read(itf, midi->read_buffer)) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. @@ -166,7 +166,7 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) _prep_out_transaction(p_midi); } -bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4]) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { midid_interface_t* p_midi = &_midid_itf[itf]; uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4); @@ -278,7 +278,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, return i; } -bool tud_midi_n_send (uint8_t itf, uint8_t const packet[4]) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) { midid_interface_t* midi = &_midid_itf[itf]; if (midi->itf_num == 0) { diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 5e7df80a..f76554c7 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -68,8 +68,8 @@ uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* b static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, 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]); +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) @@ -80,8 +80,9 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write24 (uint8_t cable_num, 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]); + +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write(uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application Callback API (weak is optional) @@ -129,14 +130,14 @@ static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t return tud_midi_write(cable_num, msg, 3); } -static inline bool tud_midi_receive (uint8_t packet[4]) +static inline bool tud_midi_packet_read (uint8_t packet[4]) { - return tud_midi_n_receive(0, packet); + return tud_midi_n_packet_read(0, packet); } -static inline bool tud_midi_send (uint8_t const packet[4]) +static inline bool tud_midi_packet_write (uint8_t const packet[4]) { - return tud_midi_n_send(0, packet); + return tud_midi_n_packet_write(0, packet); } //--------------------------------------------------------------------+ From b05084e406b50c6378572974e47d7e2ec15f2045 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Mar 2021 23:56:55 +0700 Subject: [PATCH 02/11] remove tud_midi_read_flush() --- src/class/midi/midi_device.c | 8 -------- src/class/midi/midi_device.h | 7 ------- 2 files changed, 15 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 3772c475..48e5a8e6 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -158,14 +158,6 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t return n; } -void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num) -{ - (void) cable_num; - midid_interface_t* p_midi = &_midid_itf[itf]; - tu_fifo_clear(&p_midi->rx_ff); - _prep_out_transaction(p_midi); -} - bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) { midid_interface_t* p_midi = &_midid_itf[itf]; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index f76554c7..1060fd77 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -62,7 +62,6 @@ bool tud_midi_n_mounted (uint8_t itf); uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); -void tud_midi_n_read_flush (uint8_t itf, uint8_t cable_num); uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline @@ -77,7 +76,6 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); -static inline void tud_midi_read_flush (void); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); @@ -114,11 +112,6 @@ static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) return tud_midi_n_read(0, 0, buffer, bufsize); } -static inline void tud_midi_read_flush (void) -{ - tud_midi_n_read_flush(0, 0); -} - static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { return tud_midi_n_write(0, cable_num, buffer, bufsize); From 949ff791e0222d9d89fe54b7cab036125997b66e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Mar 2021 00:34:09 +0700 Subject: [PATCH 03/11] code format --- src/class/midi/midi_device.c | 133 ++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 48e5a8e6..1ff81c39 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -200,67 +200,90 @@ static uint32_t write_flush(midid_interface_t* midi) uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; - if (midi->itf_num == 0) { - return 0; - } + TU_VERIFY(midi->itf_num, 0); uint32_t i = 0; - while (i < bufsize) { + while ( i < bufsize ) + { uint8_t data = buffer[i]; - if (midi->write_buffer_length == 0) { - uint8_t msg = data >> 4; - midi->write_buffer[1] = data; + if ( midi->write_buffer_length == 0 ) + { + uint8_t msg = data >> 4; + midi->write_buffer[1] = data; + midi->write_buffer_length = 2; + // Check to see if we're still in a SysEx transmit. + if ( midi->write_buffer[0] == 0x4 ) + { + if ( data == 0xf7 ) + { + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; + } + else + { + midi->write_target_length = 4; + } + } + else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) + { + midi->write_buffer[0] = cable_num << 4 | msg; + midi->write_target_length = 4; + } + else if ( msg == 0xf ) + { + if ( data == 0xf0 ) + { + midi->write_buffer[0] = 0x4; + midi->write_target_length = 4; + } + else if ( data == 0xf1 || data == 0xf3 ) + { + midi->write_buffer[0] = 0x2; + midi->write_target_length = 3; + } + else if ( data == 0xf2 ) + { + midi->write_buffer[0] = 0x3; + midi->write_target_length = 4; + } + else + { + midi->write_buffer[0] = 0x5; + midi->write_target_length = 2; + } + } + else + { + // Pack individual bytes if we don't support packing them into words. + midi->write_buffer[0] = cable_num << 4 | 0xf; + midi->write_buffer[2] = 0; + midi->write_buffer[3] = 0; midi->write_buffer_length = 2; - // Check to see if we're still in a SysEx transmit. - if (midi->write_buffer[0] == 0x4) { - if (data == 0xf7) { - midi->write_buffer[0] = 0x5; - midi->write_target_length = 2; - } else { - midi->write_target_length = 4; - } - } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - midi->write_buffer[0] = cable_num << 4 | msg; - midi->write_target_length = 4; - } else if (msg == 0xf) { - if (data == 0xf0) { - midi->write_buffer[0] = 0x4; - midi->write_target_length = 4; - } else if (data == 0xf1 || data == 0xf3) { - midi->write_buffer[0] = 0x2; - midi->write_target_length = 3; - } else if (data == 0xf2) { - midi->write_buffer[0] = 0x3; - midi->write_target_length = 4; - } else { - midi->write_buffer[0] = 0x5; - midi->write_target_length = 2; - } - } else { - // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = cable_num << 4 | 0xf; - midi->write_buffer[2] = 0; - midi->write_buffer[3] = 0; - midi->write_buffer_length = 2; - midi->write_target_length = 2; - } - } else { - midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length += 1; - // See if this byte ends a SysEx. - if (midi->write_buffer[0] == 0x4 && data == 0xf7) { - midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); - midi->write_target_length = midi->write_buffer_length; - } + midi->write_target_length = 2; + } + } + else + { + TU_ASSERT(midi->write_buffer_length < 4, 0); + midi->write_buffer[midi->write_buffer_length] = data; + midi->write_buffer_length += 1; + // See if this byte ends a SysEx. + if ( midi->write_buffer[0] == 0x4 && data == 0xf7 ) + { + midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_target_length = midi->write_buffer_length; + } } - if (midi->write_buffer_length == midi->write_target_length) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); - if (written < 4) { - TU_ASSERT( written == 0 ); - break; - } - midi->write_buffer_length = 0; + if ( midi->write_buffer_length == midi->write_target_length ) + { + uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + if ( written < 4 ) + { + TU_ASSERT(written == 0); + break; + } + midi->write_buffer_length = 0; } i++; } From 080b14b292251e46b43aac9e1cf7807dc2d3eb2c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 13:26:55 +0700 Subject: [PATCH 04/11] fix midi tx fifo overflow cause data corruption rename --- .../device/dynamic_configuration/src/main.c | 2 +- examples/device/midi_test/src/main.c | 8 +- examples/make.mk | 2 +- src/class/midi/midi.h | 45 ++++++++ src/class/midi/midi_device.c | 103 +++++++++++------- src/class/midi/midi_device.h | 16 ++- 6 files changed, 127 insertions(+), 49 deletions(-) diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index acee295f..ce1f752d 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -172,7 +172,7 @@ void midi_task(void) // regardless of these being used or not. Therefore incoming traffic should be read // (possibly just discarded) to avoid the sender blocking in IO uint8_t packet[4]; - while(tud_midi_available()) tud_midi_receive(packet); + while( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms if (board_millis() - start_ms < 286) return; // not enough time diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index 858a096b..af10350d 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -132,7 +132,7 @@ void midi_task(void) // regardless of these being used or not. Therefore incoming traffic should be read // (possibly just discarded) to avoid the sender blocking in IO uint8_t packet[4]; - while(tud_midi_available()) tud_midi_receive(packet); + while ( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms if (board_millis() - start_ms < 286) return; // not enough time @@ -146,10 +146,12 @@ void midi_task(void) if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tud_midi_write24(cable_num, 0x90 | channel, note_sequence[note_pos], 127); + uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; + tud_midi_write(cable_num, note_on, 3); // Send Note Off for previous note. - tud_midi_write24(cable_num, 0x80 | channel, note_sequence[previous], 0); + uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; + tud_midi_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/examples/make.mk b/examples/make.mk index e04a2592..ffcb8ee5 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -103,7 +103,7 @@ CFLAGS += \ # Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -Og + CFLAGS += -O0 else CFLAGS += -Os endif diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index f758b6e1..74dc4174 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -61,6 +61,51 @@ typedef enum MIDI_JACK_EXTERNAL = 0x02 } midi_jack_type_t; +typedef enum +{ + MIDI_CIN_MISC = 0, + MIDI_CIN_CABLE_EVENT = 1, + MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect + MIDI_CIN_SYSCOM_3BYTE = 3, // 3 byte system common message e.g SPP + MIDI_CIN_SYSEX_START = 4, // SysEx starts or continue + MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message + MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data + MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data + MIDI_CIN_NOTE_ON = 8, + MIDI_CIN_NOTE_OFF = 9, + MIDI_CIN_POLY_KEYPRESS = 10, + MIDI_CIN_CONTROL_CHANGE = 11, + MIDI_CIN_PROGRAM_CHANGE = 12, + MIDI_CIN_CHANNEL_PRESSURE = 13, + MIDI_CIN_PITCH_BEND_CHANGE = 14, + MIDI_CIN_1BYTE_DATA = 15 +} midi_code_index_number_t; + +// MIDI 1.0 status byte +enum +{ + //------------- System Exclusive -------------// + MIDI_STATUS_SYSEX_START = 0xF0, + MIDI_STATUS_SYSEX_END = 0xF7, + + //------------- System Common -------------// + MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME = 0xF1, + MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER = 0xF2, + MIDI_STATUS_SYSCOM_SONG_SELECT = 0xF3, + // F4, F5 is undefined + MIDI_STATUS_SYSCOM_TUNE_REQUEST = 0xF6, + + //------------- System RealTime -------------// + MIDI_STATUS_SYSREAL_TIMING_CLOCK = 0xF8, + // 0xF9 is undefined + MIDI_STATUS_SYSREAL_START = 0xFA, + MIDI_STATUS_SYSREAL_CONTINUE = 0xFB, + MIDI_STATUS_SYSREAL_STOP = 0xFC, + // 0xFD is undefined + MIDI_STATUS_SYSREAL_ACTIVE_SENSING = 0xFE, + MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, +}; + /// MIDI Interface Header Descriptor typedef struct TU_ATTR_PACKED { diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 1ff81c39..cba1dcca 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -38,6 +38,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ + typedef struct { uint8_t itf_num; @@ -126,16 +127,19 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t midid_interface_t* midi = &_midid_itf[itf]; // Fill empty buffer - if (midi->read_buffer_length == 0) { - if (!tud_midi_n_packet_read(itf, midi->read_buffer)) return 0; + if ( midi->read_buffer_length == 0 ) + { + if ( !tud_midi_n_packet_read(itf, midi->read_buffer) ) return 0; uint8_t code_index = midi->read_buffer[0] & 0x0f; // We always copy over the first byte. uint8_t count = 1; // Ignore subsequent bytes based on the code. - if (code_index != 0x5 && code_index != 0xf) { + if ( code_index != 0x5 && code_index != 0xf ) + { count = 2; - if (code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd) { + if ( code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd ) + { count = 3; } } @@ -150,7 +154,8 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t 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) { + if ( midi->read_target_length == midi->read_buffer_length ) + { midi->read_buffer_length = 0; midi->read_target_length = 0; } @@ -166,10 +171,6 @@ bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) return (num_read == 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 //--------------------------------------------------------------------+ @@ -185,7 +186,8 @@ static uint32_t write_flush(midid_interface_t* midi) TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); - if (count > 0) + + if (count) { TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, midi->epin_buf, count), 0 ); return count; @@ -202,21 +204,26 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); + uint32_t written = 0; uint32_t i = 0; while ( i < bufsize ) { - uint8_t data = buffer[i]; + uint8_t const data = buffer[i]; + if ( midi->write_buffer_length == 0 ) { - uint8_t msg = data >> 4; + // new packet + + uint8_t const msg = data >> 4; midi->write_buffer[1] = data; midi->write_buffer_length = 2; + // Check to see if we're still in a SysEx transmit. - if ( midi->write_buffer[0] == 0x4 ) + if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START ) { - if ( data == 0xf7 ) + if ( data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = 0x5; + midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; midi->write_target_length = 2; } else @@ -226,29 +233,31 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, } else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { - midi->write_buffer[0] = cable_num << 4 | msg; + // Channel Voice Messages + midi->write_buffer[0] = (cable_num << 4) | msg; midi->write_target_length = 4; } else if ( msg == 0xf ) { - if ( data == 0xf0 ) + // System message + if ( data == MIDI_STATUS_SYSEX_START ) { - midi->write_buffer[0] = 0x4; + midi->write_buffer[0] = MIDI_CIN_SYSEX_START; midi->write_target_length = 4; } - else if ( data == 0xf1 || data == 0xf3 ) + else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) { - midi->write_buffer[0] = 0x2; + midi->write_buffer[0] = MIDI_CIN_SYSCOM_2BYTE; midi->write_target_length = 3; } - else if ( data == 0xf2 ) + else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) { - midi->write_buffer[0] = 0x3; + midi->write_buffer[0] = MIDI_CIN_SYSCOM_3BYTE; midi->write_target_length = 4; } else { - midi->write_buffer[0] = 0x5; + midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; midi->write_target_length = 2; } } @@ -264,33 +273,44 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, } else { + // On-going packet + TU_ASSERT(midi->write_buffer_length < 4, 0); midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length += 1; + midi->write_buffer_length++; + // See if this byte ends a SysEx. - if ( midi->write_buffer[0] == 0x4 && data == 0xf7 ) + if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = 0x4 + (midi->write_buffer_length - 1); + midi->write_buffer[0] = MIDI_CIN_SYSEX_START + (midi->write_buffer_length - 1); midi->write_target_length = midi->write_buffer_length; } } + // Send out packet if ( midi->write_buffer_length == midi->write_target_length ) { - uint16_t written = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); - if ( written < 4 ) - { - TU_ASSERT(written == 0); - break; - } - midi->write_buffer_length = 0; + // zeroes unused bytes + for(uint8_t idx = midi->write_target_length; idx < 4; idx++) midi->write_buffer[idx] = 0; + + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + + // reset buffer + midi->write_buffer_length = midi->write_target_length = 0; + + // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing + if ( count != 4 ) break; + + // updated written if succeeded + written = i; } + i++; } write_flush(midi); - return i; + return written; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) @@ -300,8 +320,7 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) return 0; } - if (tu_fifo_remaining(&midi->tx_ff) < 4) - return false; + if (tu_fifo_remaining(&midi->tx_ff) < 4) return false; tu_fifo_write_n(&midi->tx_ff, packet, 4); write_flush(midi); @@ -347,9 +366,9 @@ void midid_reset(uint8_t rhport) uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); uint16_t drv_len = tu_desc_len(desc_itf); uint8_t const * p_desc = tu_desc_next(desc_itf); @@ -365,9 +384,9 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); tusb_desc_interface_t const * desc_midi = (tusb_desc_interface_t const *) p_desc; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); // Find available interface midid_interface_t * p_midi = NULL; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index 1060fd77..aaceaf62 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -59,16 +59,28 @@ // Application API (Multiple Interfaces) // CFG_TUD_MIDI > 1 //--------------------------------------------------------------------+ + +// Check if midi interface is mounted bool tud_midi_n_mounted (uint8_t itf); + +// Get the number of bytes available for reading uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); + +// Read byte stream (legacy) uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); + +// Write byte Stream (legacy) uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +// Write good-old 3 bytes data, this use write packet static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); + +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) From 6b04efd443c3299131135849b736a2f2ce5877ac Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 13:55:51 +0700 Subject: [PATCH 05/11] refactor midi stream read --- src/class/midi/midi_device.c | 51 +++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index cba1dcca..14748f18 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -39,6 +39,13 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct +{ + uint8_t buffer[4]; + uint8_t index; + uint8_t total; +}midid_stream_t; + typedef struct { uint8_t itf_num; @@ -57,12 +64,15 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif + // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. uint8_t write_buffer[4]; uint8_t write_buffer_length; uint8_t write_target_length; +// midid_stream_t stream_write; + uint8_t read_buffer[4]; uint8_t read_buffer_length; uint8_t read_target_length; @@ -129,26 +139,41 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t // Fill empty buffer if ( midi->read_buffer_length == 0 ) { - if ( !tud_midi_n_packet_read(itf, midi->read_buffer) ) return 0; + TU_VERIFY(tud_midi_n_packet_read(itf, midi->read_buffer), 0); - uint8_t code_index = midi->read_buffer[0] & 0x0f; - // We always copy over the first byte. - uint8_t count = 1; - // Ignore subsequent bytes based on the code. - if ( code_index != 0x5 && code_index != 0xf ) + uint8_t const code_index = midi->read_buffer[0] & 0x0f; + uint8_t count; + + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) { - count = 2; - if ( code_index != 0x2 && code_index != 0x6 && code_index != 0xc && code_index != 0xd ) - { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; + + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + count = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + count = 2; + break; + + default: count = 3; - } + break; } midi->read_buffer_length = count; } - uint32_t n = midi->read_buffer_length - midi->read_target_length; - if (bufsize < n) n = bufsize; + uint32_t n = tu_min32(midi->read_buffer_length - midi->read_target_length, bufsize); // Skip the header in the buffer memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); @@ -204,6 +229,8 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); +// midid_stream_t* stream = &midi->stream_write; + uint32_t written = 0; uint32_t i = 0; while ( i < bufsize ) From 08fe16840fcc39e4cb7c1f55fa56762427734753 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:26:55 +0700 Subject: [PATCH 06/11] refactor midi write into stream --- src/class/midi/midi_device.c | 77 +++++++++++++++++------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 14748f18..49bf2a27 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -67,11 +67,7 @@ typedef struct // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. - uint8_t write_buffer[4]; - uint8_t write_buffer_length; - uint8_t write_target_length; - -// midid_stream_t stream_write; + midid_stream_t stream_write; uint8_t read_buffer[4]; uint8_t read_buffer_length; @@ -229,7 +225,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); -// midid_stream_t* stream = &midi->stream_write; + midid_stream_t* stream = &midi->stream_write; uint32_t written = 0; uint32_t i = 0; @@ -237,93 +233,94 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, { uint8_t const data = buffer[i]; - if ( midi->write_buffer_length == 0 ) + if ( stream->index == 0 ) { - // new packet + // new event packet uint8_t const msg = data >> 4; - midi->write_buffer[1] = data; - midi->write_buffer_length = 2; + + stream->index = 2; + stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START ) + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) { if ( data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - midi->write_target_length = 2; + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } else { - midi->write_target_length = 4; + stream->total = 4; } } else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { // Channel Voice Messages - midi->write_buffer[0] = (cable_num << 4) | msg; - midi->write_target_length = 4; + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 4; } else if ( msg == 0xf ) { // System message if ( data == MIDI_STATUS_SYSEX_START ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_START; - midi->write_target_length = 4; + stream->buffer[0] = MIDI_CIN_SYSEX_START; + stream->total = 4; } else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) { - midi->write_buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - midi->write_target_length = 3; + stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; + stream->total = 3; } else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) { - midi->write_buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - midi->write_target_length = 4; + stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; + stream->total = 4; } else { - midi->write_buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - midi->write_target_length = 2; + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } } else { // Pack individual bytes if we don't support packing them into words. - midi->write_buffer[0] = cable_num << 4 | 0xf; - midi->write_buffer[2] = 0; - midi->write_buffer[3] = 0; - midi->write_buffer_length = 2; - midi->write_target_length = 2; + stream->buffer[0] = cable_num << 4 | 0xf; + stream->buffer[2] = 0; + stream->buffer[3] = 0; + stream->index = 2; + stream->total = 2; } } else { - // On-going packet + // On-going (buffering) packet - TU_ASSERT(midi->write_buffer_length < 4, 0); - midi->write_buffer[midi->write_buffer_length] = data; - midi->write_buffer_length++; + TU_ASSERT(stream->index < 4, written); + stream->buffer[stream->index] = data; + stream->index++; // See if this byte ends a SysEx. - if ( midi->write_buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) { - midi->write_buffer[0] = MIDI_CIN_SYSEX_START + (midi->write_buffer_length - 1); - midi->write_target_length = midi->write_buffer_length; + stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); + stream->total = stream->index; } } // Send out packet - if ( midi->write_buffer_length == midi->write_target_length ) + if ( stream->index == stream->total ) { // zeroes unused bytes - for(uint8_t idx = midi->write_target_length; idx < 4; idx++) midi->write_buffer[idx] = 0; + for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - uint16_t const count = tu_fifo_write_n(&midi->tx_ff, midi->write_buffer, 4); + uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); // reset buffer - midi->write_buffer_length = midi->write_target_length = 0; + stream->index = stream->total = 0; // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing if ( count != 4 ) break; From 99b78e62f2172988ffa3835b7d6bcaaf455cef10 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:34:13 +0700 Subject: [PATCH 07/11] removed tud_midi_write24() --- src/class/midi/midi_device.h | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index aaceaf62..c875748f 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -72,10 +72,6 @@ uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, ui // Write byte Stream (legacy) uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -// Write good-old 3 bytes data, this use write packet -static inline -uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); - // Read event packet (4 bytes) bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); @@ -87,13 +83,26 @@ bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ static inline bool tud_midi_mounted (void); static inline uint32_t tud_midi_available (void); + static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3); static inline bool tud_midi_packet_read (uint8_t packet[4]); static inline bool tud_midi_packet_write(uint8_t const packet[4]); +// TODO remove after 0.10.0 release +TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") +static inline bool tud_midi_send(uint8_t packet[4]) +{ + return tud_midi_packet_write(packet); +} + +TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") +static inline bool tud_midi_receive(uint8_t packet[4]) +{ + return tud_midi_packet_read(packet); +} + //--------------------------------------------------------------------+ // Application Callback API (weak is optional) //--------------------------------------------------------------------+ @@ -103,12 +112,6 @@ TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf); // Inline Functions //--------------------------------------------------------------------+ -static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) -{ - uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_n_write(itf, cable_num, msg, 3); -} - static inline bool tud_midi_mounted (void) { return tud_midi_n_mounted(0); @@ -129,12 +132,6 @@ static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, return tud_midi_n_write(0, cable_num, buffer, bufsize); } -static inline uint32_t tud_midi_write24 (uint8_t cable_num, uint8_t b1, uint8_t b2, uint8_t b3) -{ - uint8_t msg[3] = { b1, b2, b3 }; - return tud_midi_write(cable_num, msg, 3); -} - static inline bool tud_midi_packet_read (uint8_t packet[4]) { return tud_midi_n_packet_read(0, packet); From da59c4ad4434b64691aa7a93e03381702633964d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:43:38 +0700 Subject: [PATCH 08/11] rename midi write()/read() to stream_write() stream_read() also add deprecated for warning and rename hint --- .../device/dynamic_configuration/src/main.c | 6 +- examples/device/midi_test/src/main.c | 4 +- src/class/midi/midi_device.c | 4 +- src/class/midi/midi_device.h | 55 ++++++++++++------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index ce1f752d..4c10f55b 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -186,10 +186,12 @@ void midi_task(void) if (previous < 0) previous = sizeof(note_sequence) - 1; // Send Note On for current position at full velocity (127) on channel 1. - tud_midi_write24(cable_num, 0x90 | channel, note_sequence[note_pos], 127); + uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; + tud_midi_stream_write(cable_num, note_on, 3); // Send Note Off for previous note. - tud_midi_write24(cable_num, 0x80 | channel, note_sequence[previous], 0); + uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; + tud_midi_stream_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index af10350d..9e0e82a1 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -147,11 +147,11 @@ void midi_task(void) // Send Note On for current position at full velocity (127) on channel 1. uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; - tud_midi_write(cable_num, note_on, 3); + tud_midi_stream_write(cable_num, note_on, 3); // Send Note Off for previous note. uint8_t note_off[3] = { 0x80 | channel, note_sequence[previous], 0}; - tud_midi_write(cable_num, note_off, 3); + tud_midi_stream_write(cable_num, note_off, 3); // Increment position note_pos++; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 49bf2a27..e76f01db 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -127,7 +127,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) return tu_fifo_count(&_midid_itf[itf].rx_ff); } -uint32_t tud_midi_n_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; @@ -220,7 +220,7 @@ static uint32_t write_flush(midid_interface_t* midi) } } -uint32_t tud_midi_n_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->itf_num, 0); diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index c875748f..67f03930 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -61,36 +61,51 @@ //--------------------------------------------------------------------+ // Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); +bool tud_midi_n_mounted (uint8_t itf); // Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); +uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); -// Read byte stream (legacy) -uint32_t tud_midi_n_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); +// Read byte stream (legacy) +uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); -// Write byte Stream (legacy) -uint32_t tud_midi_n_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +// Write byte Stream (legacy) +uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); +// Read event packet (4 bytes) +bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +// Write event packet (4 bytes) +bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); //--------------------------------------------------------------------+ // Application API (Single Interface) //--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); +static inline bool tud_midi_mounted (void); +static inline uint32_t tud_midi_available (void); -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write(uint8_t const packet[4]); +static inline bool tud_midi_packet_read (uint8_t packet[4]); +static inline bool tud_midi_packet_write (uint8_t const packet[4]); +//------------- Deprecated API name -------------// // TODO remove after 0.10.0 release + +TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") +static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +{ + return tud_midi_stream_read(buffer, bufsize); +} + +TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") +static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + return tud_midi_stream_write(cable_num, buffer, bufsize); +} + + TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") static inline bool tud_midi_send(uint8_t packet[4]) { @@ -122,14 +137,14 @@ static inline uint32_t tud_midi_available (void) return tud_midi_n_available(0, 0); } -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) { - return tud_midi_n_read(0, 0, buffer, bufsize); + return tud_midi_n_stream_read(0, 0, buffer, bufsize); } -static inline uint32_t tud_midi_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { - return tud_midi_n_write(0, cable_num, buffer, bufsize); + return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); } static inline bool tud_midi_packet_read (uint8_t packet[4]) From 350eb1127755f3ee0dd3dd186cc31e9492916a0c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 14:52:44 +0700 Subject: [PATCH 09/11] refactor midi read buffer to stream --- src/class/midi/midi_device.c | 39 +++++++++++++++++------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index e76f01db..a4cc104a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -68,10 +68,7 @@ typedef struct // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. midid_stream_t stream_write; - - uint8_t read_buffer[4]; - uint8_t read_buffer_length; - uint8_t read_target_length; + midid_stream_t stream_read; // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; @@ -131,14 +128,16 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui { (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; + midid_stream_t* stream = &midi->stream_read; - // Fill empty buffer - if ( midi->read_buffer_length == 0 ) + TU_VERIFY(bufsize, 0); + + // Get new packet from fifo + if ( stream->total == 0 ) { - TU_VERIFY(tud_midi_n_packet_read(itf, midi->read_buffer), 0); + TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0); - uint8_t const code_index = midi->read_buffer[0] & 0x0f; - uint8_t count; + uint8_t const code_index = stream->buffer[0] & 0x0f; // MIDI 1.0 Table 4-1: Code Index Number Classifications switch(code_index) @@ -151,34 +150,32 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui case MIDI_CIN_SYSEX_END_1BYTE: case MIDI_CIN_1BYTE_DATA: - count = 1; + stream->total = 1; break; case MIDI_CIN_SYSCOM_2BYTE : case MIDI_CIN_SYSEX_END_2BYTE : case MIDI_CIN_PROGRAM_CHANGE : case MIDI_CIN_CHANNEL_PRESSURE : - count = 2; + stream->total = 2; break; default: - count = 3; + stream->total = 3; break; } - - midi->read_buffer_length = count; } - uint32_t n = tu_min32(midi->read_buffer_length - midi->read_target_length, bufsize); + uint32_t const n = tu_min32(stream->total - stream->index, bufsize); - // Skip the header in the buffer - memcpy(buffer, midi->read_buffer + 1 + midi->read_target_length, n); - midi->read_target_length += n; + // Skip the header (1st byte) in the buffer + memcpy(buffer, stream->buffer + 1 + stream->index, n); + stream->index += n; - if ( midi->read_target_length == midi->read_buffer_length ) + if ( stream->total == stream->index ) { - midi->read_buffer_length = 0; - midi->read_target_length = 0; + stream->index = 0; + stream->total = 0; } return n; From 48bb96f5072a173189d9076c5c2b1f5066327bf6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 15:08:36 +0700 Subject: [PATCH 10/11] correct midi stream read behavior to read until user buffer is full or no more data from usb fifo --- src/class/midi/midi_device.c | 117 +++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index a4cc104a..9ccbb733 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -52,6 +52,12 @@ typedef struct uint8_t ep_in; uint8_t ep_out; + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midid_stream_t stream_write; + midid_stream_t stream_read; + /*------------- From this point, data is not cleared by bus reset -------------*/ // FIFO tu_fifo_t rx_ff; @@ -64,12 +70,6 @@ typedef struct osal_mutex_def_t tx_ff_mutex; #endif - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; - // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_MIDI_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_MIDI_EP_BUFSIZE]; @@ -127,58 +127,71 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) { (void) cable_num; + TU_VERIFY(bufsize, 0); + + uint8_t* buf8 = (uint8_t*) buffer; + midid_interface_t* midi = &_midid_itf[itf]; midid_stream_t* stream = &midi->stream_read; - TU_VERIFY(bufsize, 0); - - // Get new packet from fifo - if ( stream->total == 0 ) + uint32_t total_read = 0; + while( bufsize ) { - TU_VERIFY(tud_midi_n_packet_read(itf, stream->buffer), 0); - - uint8_t const code_index = stream->buffer[0] & 0x0f; - - // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) + // Get new packet from fifo, then set packet expected bytes + if ( stream->total == 0 ) { - case MIDI_CIN_MISC: - case MIDI_CIN_CABLE_EVENT: - // These are reserved and unused, possibly issue somewhere, skip this packet - return 0; - break; + // return if there is no more data from fifo + if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; - case MIDI_CIN_SYSEX_END_1BYTE: - case MIDI_CIN_1BYTE_DATA: - stream->total = 1; - break; + uint8_t const code_index = stream->buffer[0] & 0x0f; - case MIDI_CIN_SYSCOM_2BYTE : - case MIDI_CIN_SYSEX_END_2BYTE : - case MIDI_CIN_PROGRAM_CHANGE : - case MIDI_CIN_CHANNEL_PRESSURE : - stream->total = 2; - break; + // MIDI 1.0 Table 4-1: Code Index Number Classifications + switch(code_index) + { + case MIDI_CIN_MISC: + case MIDI_CIN_CABLE_EVENT: + // These are reserved and unused, possibly issue somewhere, skip this packet + return 0; + break; - default: - stream->total = 3; - break; + case MIDI_CIN_SYSEX_END_1BYTE: + case MIDI_CIN_1BYTE_DATA: + stream->total = 1; + break; + + case MIDI_CIN_SYSCOM_2BYTE : + case MIDI_CIN_SYSEX_END_2BYTE : + case MIDI_CIN_PROGRAM_CHANGE : + case MIDI_CIN_CHANNEL_PRESSURE : + stream->total = 2; + break; + + default: + stream->total = 3; + break; + } + } + + // Copy data up to bufsize + uint32_t const count = tu_min32(stream->total - stream->index, bufsize); + + // Skip the header (1st byte) in the buffer + memcpy(buf8, stream->buffer + 1 + stream->index, count); + + total_read += count; + stream->index += count; + buf8 += count; + bufsize -= count; + + // complete current event packet, reset stream + if ( stream->total == stream->index ) + { + stream->index = 0; + stream->total = 0; } } - uint32_t const n = tu_min32(stream->total - stream->index, bufsize); - - // Skip the header (1st byte) in the buffer - memcpy(buffer, stream->buffer + 1 + stream->index, n); - stream->index += n; - - if ( stream->total == stream->index ) - { - stream->index = 0; - stream->total = 0; - } - - return n; + return total_read; } bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) @@ -224,7 +237,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* midid_stream_t* stream = &midi->stream_write; - uint32_t written = 0; + uint32_t total_written = 0; uint32_t i = 0; while ( i < bufsize ) { @@ -296,7 +309,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* { // On-going (buffering) packet - TU_ASSERT(stream->index < 4, written); + TU_ASSERT(stream->index < 4, total_written); stream->buffer[stream->index] = data; stream->index++; @@ -316,14 +329,14 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* uint16_t const count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); - // reset buffer + // complete current event packet, reset stream stream->index = stream->total = 0; // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing if ( count != 4 ) break; // updated written if succeeded - written = i; + total_written = i; } i++; @@ -331,7 +344,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* write_flush(midi); - return written; + return total_written; } bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]) From 7582528067fcfc0a4fe6039cfcb00d2f4c702b53 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Apr 2021 15:21:44 +0700 Subject: [PATCH 11/11] revert make optimize flag --- examples/make.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/make.mk b/examples/make.mk index ffcb8ee5..e04a2592 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -103,7 +103,7 @@ CFLAGS += \ # Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -O0 + CFLAGS += -Og else CFLAGS += -Os endif