|
|
|
|
|
|
|
|
|
|
|
|
|
|
int usb_midi_read(uint32_t channel) |
|
|
int usb_midi_read(uint32_t channel) |
|
|
{ |
|
|
{ |
|
|
uint32_t n, index, ch, type1, type2; |
|
|
|
|
|
|
|
|
uint32_t n, index, ch, type1, type2, b1; |
|
|
|
|
|
|
|
|
if (!rx_packet) { |
|
|
if (!rx_packet) { |
|
|
if (!usb_configuration) return 0; |
|
|
if (!usb_configuration) return 0; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
type1 = n & 15; |
|
|
type1 = n & 15; |
|
|
type2 = (n >> 12) & 15; |
|
|
type2 = (n >> 12) & 15; |
|
|
ch = ((n >> 8) & 15) + 1; |
|
|
|
|
|
|
|
|
b1 = (n >> 8) & 0xFF; |
|
|
|
|
|
ch = (b1 & 15) + 1; |
|
|
usb_midi_msg_cable = (n >> 4) & 15; |
|
|
usb_midi_msg_cable = (n >> 4) & 15; |
|
|
if (type1 >= 0x08 && type1 <= 0x0E) { |
|
|
if (type1 >= 0x08 && type1 <= 0x0E) { |
|
|
if (channel && channel != ch) { |
|
|
if (channel && channel != ch) { |
|
|
|
|
|
|
|
|
usb_midi_msg_data2 = (n >> 24); |
|
|
usb_midi_msg_data2 = (n >> 24); |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
if (type1 == 0x02 || type1 == 0x03 || (type1 == 0x05 && type2 == 0x0F)) { |
|
|
|
|
|
|
|
|
if (type1 == 0x02 || type1 == 0x03 || (type1 == 0x05 && b1 >= 0xF1 && b1 != 0xF7)) { |
|
|
// system common or system realtime message |
|
|
// system common or system realtime message |
|
|
uint8_t type; |
|
|
|
|
|
system_common_or_realtime: |
|
|
system_common_or_realtime: |
|
|
type = n >> 8; |
|
|
|
|
|
switch (type) { |
|
|
|
|
|
|
|
|
switch (b1) { |
|
|
case 0xF1: // usbMIDI.TimeCodeQuarterFrame |
|
|
case 0xF1: // usbMIDI.TimeCodeQuarterFrame |
|
|
if (usb_midi_handleTimeCodeQuarterFrame) { |
|
|
if (usb_midi_handleTimeCodeQuarterFrame) { |
|
|
(*usb_midi_handleTimeCodeQuarterFrame)(n >> 16); |
|
|
(*usb_midi_handleTimeCodeQuarterFrame)(n >> 16); |
|
|
|
|
|
|
|
|
default: |
|
|
default: |
|
|
return 0; // unknown message, ignore it |
|
|
return 0; // unknown message, ignore it |
|
|
} |
|
|
} |
|
|
usb_midi_msg_type = type; |
|
|
|
|
|
|
|
|
usb_midi_msg_type = b1; |
|
|
goto return_message; |
|
|
goto return_message; |
|
|
} |
|
|
} |
|
|
if (type1 == 0x04) { |
|
|
if (type1 == 0x04) { |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
if (type1 >= 0x05 && type1 <= 0x07) { |
|
|
if (type1 >= 0x05 && type1 <= 0x07) { |
|
|
sysex_byte(n >> 8); |
|
|
|
|
|
|
|
|
sysex_byte(b1); |
|
|
if (type1 >= 0x06) sysex_byte(n >> 16); |
|
|
if (type1 >= 0x06) sysex_byte(n >> 16); |
|
|
if (type1 == 0x07) sysex_byte(n >> 24); |
|
|
if (type1 == 0x07) sysex_byte(n >> 24); |
|
|
uint16_t len = usb_midi_msg_sysex_len; |
|
|
uint16_t len = usb_midi_msg_sysex_len; |
|
|
|
|
|
|
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
if (type1 == 0x0F) { |
|
|
if (type1 == 0x0F) { |
|
|
uint8_t b = n >> 8; |
|
|
|
|
|
if (b >= 0xF8) { |
|
|
|
|
|
|
|
|
if (b1 >= 0xF8) { |
|
|
// From Sebastian Tomczak, seb.tomczak at gmail.com |
|
|
// From Sebastian Tomczak, seb.tomczak at gmail.com |
|
|
// http://little-scale.blogspot.com/2011/08/usb-midi-game-boy-sync-for-16.html |
|
|
// http://little-scale.blogspot.com/2011/08/usb-midi-game-boy-sync-for-16.html |
|
|
goto system_common_or_realtime; |
|
|
goto system_common_or_realtime; |
|
|
} |
|
|
} |
|
|
if (usb_midi_msg_sysex_len > 0) { |
|
|
|
|
|
|
|
|
if (b1 == 0xF0 || usb_midi_msg_sysex_len > 0) { |
|
|
// From David Sorlien, dsorlien at gmail.com, http://axe4live.wordpress.com |
|
|
// From David Sorlien, dsorlien at gmail.com, http://axe4live.wordpress.com |
|
|
// OSX sometimes uses Single Byte Unparsed to |
|
|
// OSX sometimes uses Single Byte Unparsed to |
|
|
// send bytes in the middle of a SYSEX message. |
|
|
// send bytes in the middle of a SYSEX message. |
|
|
sysex_byte(n >> 8); |
|
|
|
|
|
|
|
|
sysex_byte(b1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
return 0; |