Przeglądaj źródła

Support multiple cables on USB MIDI

main
PaulStoffregen 6 lat temu
rodzic
commit
c9d0122505
6 zmienionych plików z 312 dodań i 16 usunięć
  1. +27
    -9
      keywords.txt
  2. +155
    -7
      teensy3/usb_desc.c
  3. +109
    -0
      teensy3/usb_desc.h
  4. +3
    -0
      teensy3/usb_midi.c
  5. +6
    -0
      teensy3/usb_midi.h
  6. +12
    -0
      teensy3/usb_undef.h

+ 27
- 9
keywords.txt Wyświetl plik

@@ -437,8 +437,27 @@ sendProgramChange KEYWORD2
sendAfterTouch KEYWORD2
sendPitchBend KEYWORD2
sendSysEx KEYWORD2
sendRealTime KEYWORD2
sendTimeCodeQuarterFrame KEYWORD2
sendSongPosition KEYWORD2
sendSongSelect KEYWORD2
sendTuneRequest KEYWORD2
beginRpn KEYWORD2
sendRpnValue KEYWORD2
sendRpnValue KEYWORD2
sendRpnIncrement KEYWORD2
sendRpnDecrement KEYWORD2
endRpn KEYWORD2
beginNrpn KEYWORD2
sendNrpnValue KEYWORD2
sendNrpnValue KEYWORD2
sendNrpnIncrement KEYWORD2
sendNrpnDecrement KEYWORD2
endNrpn KEYWORD2
send KEYWORD2
analog2velocity KEYWORD2
getType KEYWORD2
getCable KEYWORD2
getChannel KEYWORD2
getData1 KEYWORD2
getData2 KEYWORD2
@@ -450,15 +469,14 @@ setHandleControlChange KEYWORD2
setHandleProgramChange KEYWORD2
setHandleAfterTouch KEYWORD2
setHandlePitchChange KEYWORD2
setHandlePitchChange KEYWORD2
NoteOff LITERAL1
NoteOn LITERAL1
AfterTouchPoly LITERAL1
ControlChange LITERAL1
ProgramChange LITERAL1
AfterTouchChannel LITERAL1
PitchBend LITERAL1
SystemExclusive LITERAL1
#NoteOff LITERAL1
#NoteOn LITERAL1
#AfterTouchPoly LITERAL1
#ControlChange LITERAL1
#ProgramChange LITERAL1
#AfterTouchChannel LITERAL1
#PitchBend LITERAL1
#SystemExclusive LITERAL1
midiEventPacket_t LITERAL1
MidiUSB KEYWORD1
sendMIDI KEYWORD2

+ 155
- 7
teensy3/usb_desc.c Wyświetl plik

@@ -87,7 +87,11 @@ static uint8_t device_descriptor[] = {
EP0_SIZE, // bMaxPacketSize0
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
0x00, 0x02, // bcdDevice
#ifdef BCD_DEVICE
LSB(BCD_DEVICE), MSB(BCD_DEVICE), // bcdDevice
#else
0x00, 0x02,
#endif
1, // iManufacturer
2, // iProduct
3, // iSerialNumber
@@ -472,7 +476,10 @@ static uint8_t flightsim_report_desc[] = {

#define MIDI_INTERFACE_DESC_POS CDC_DATA_INTERFACE_DESC_POS+CDC_DATA_INTERFACE_DESC_SIZE
#ifdef MIDI_INTERFACE
#define MIDI_INTERFACE_DESC_SIZE 9+7+6+6+9+9+9+5+9+5
#if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16
#error "MIDI_NUM_CABLES must be defined between 1 to 16"
#endif
#define MIDI_INTERFACE_DESC_SIZE 9+7+((6+6+9+9)*MIDI_NUM_CABLES)+(9+4+MIDI_NUM_CABLES)*2
#else
#define MIDI_INTERFACE_DESC_SIZE 0
#endif
@@ -671,7 +678,8 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x24, // bDescriptorType = CS_INTERFACE
0x01, // bDescriptorSubtype = MS_HEADER
0x00, 0x01, // bcdMSC = revision 01.00
0x41, 0x00, // wTotalLength
LSB(7+(6+6+9+9)*MIDI_NUM_CABLES), // wTotalLength
LSB(7+(6+6+9+9)*MIDI_NUM_CABLES),
// MIDI IN Jack Descriptor, B.4.3, Table B-7 (embedded), page 40
6, // bLength
0x24, // bDescriptorType = CS_INTERFACE
@@ -706,6 +714,56 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
1, // BaSourceID(1) = 1
1, // BaSourcePin(1) = first pin
0, // iJack
#if MIDI_NUM_CABLES >= 2
#define MIDI_INTERFACE_JACK_PAIR(a, b, c, d) \
6, 0x24, 0x02, 0x01, (a), 0, \
6, 0x24, 0x02, 0x02, (b), 0, \
9, 0x24, 0x03, 0x01, (c), 1, (b), 1, 0, \
9, 0x24, 0x03, 0x02, (d), 1, (a), 1, 0,
MIDI_INTERFACE_JACK_PAIR(5, 6, 7, 8)
#endif
#if MIDI_NUM_CABLES >= 3
MIDI_INTERFACE_JACK_PAIR(9, 10, 11, 12)
#endif
#if MIDI_NUM_CABLES >= 4
MIDI_INTERFACE_JACK_PAIR(13, 14, 15, 16)
#endif
#if MIDI_NUM_CABLES >= 5
MIDI_INTERFACE_JACK_PAIR(17, 18, 19, 20)
#endif
#if MIDI_NUM_CABLES >= 6
MIDI_INTERFACE_JACK_PAIR(21, 22, 23, 24)
#endif
#if MIDI_NUM_CABLES >= 7
MIDI_INTERFACE_JACK_PAIR(25, 26, 27, 28)
#endif
#if MIDI_NUM_CABLES >= 8
MIDI_INTERFACE_JACK_PAIR(29, 30, 31, 32)
#endif
#if MIDI_NUM_CABLES >= 9
MIDI_INTERFACE_JACK_PAIR(33, 34, 35, 36)
#endif
#if MIDI_NUM_CABLES >= 10
MIDI_INTERFACE_JACK_PAIR(37, 38, 39, 40)
#endif
#if MIDI_NUM_CABLES >= 11
MIDI_INTERFACE_JACK_PAIR(41, 42, 43, 44)
#endif
#if MIDI_NUM_CABLES >= 12
MIDI_INTERFACE_JACK_PAIR(45, 46, 47, 48)
#endif
#if MIDI_NUM_CABLES >= 13
MIDI_INTERFACE_JACK_PAIR(49, 50, 51, 52)
#endif
#if MIDI_NUM_CABLES >= 14
MIDI_INTERFACE_JACK_PAIR(53, 54, 55, 56)
#endif
#if MIDI_NUM_CABLES >= 15
MIDI_INTERFACE_JACK_PAIR(57, 58, 59, 60)
#endif
#if MIDI_NUM_CABLES >= 16
MIDI_INTERFACE_JACK_PAIR(61, 62, 63, 64)
#endif
// Standard Bulk OUT Endpoint Descriptor, B.5.1, Table B-11, pae 42
9, // bLength
5, // bDescriptorType = ENDPOINT
@@ -716,11 +774,56 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0, // bRefresh
0, // bSynchAddress
// Class-specific MS Bulk OUT Endpoint Descriptor, B.5.2, Table B-12, page 42
5, // bLength
4+MIDI_NUM_CABLES, // bLength
0x25, // bDescriptorSubtype = CS_ENDPOINT
0x01, // bJackType = MS_GENERAL
1, // bNumEmbMIDIJack = 1 jack
MIDI_NUM_CABLES, // bNumEmbMIDIJack = number of jacks
1, // BaAssocJackID(1) = jack ID #1
#if MIDI_NUM_CABLES >= 2
5,
#endif
#if MIDI_NUM_CABLES >= 3
9,
#endif
#if MIDI_NUM_CABLES >= 4
13,
#endif
#if MIDI_NUM_CABLES >= 5
17,
#endif
#if MIDI_NUM_CABLES >= 6
21,
#endif
#if MIDI_NUM_CABLES >= 7
25,
#endif
#if MIDI_NUM_CABLES >= 8
29,
#endif
#if MIDI_NUM_CABLES >= 9
33,
#endif
#if MIDI_NUM_CABLES >= 10
37,
#endif
#if MIDI_NUM_CABLES >= 11
41,
#endif
#if MIDI_NUM_CABLES >= 12
45,
#endif
#if MIDI_NUM_CABLES >= 13
49,
#endif
#if MIDI_NUM_CABLES >= 14
53,
#endif
#if MIDI_NUM_CABLES >= 15
57,
#endif
#if MIDI_NUM_CABLES >= 16
61,
#endif
// Standard Bulk IN Endpoint Descriptor, B.5.1, Table B-11, pae 42
9, // bLength
5, // bDescriptorType = ENDPOINT
@@ -731,11 +834,56 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0, // bRefresh
0, // bSynchAddress
// Class-specific MS Bulk IN Endpoint Descriptor, B.5.2, Table B-12, page 42
5, // bLength
4+MIDI_NUM_CABLES, // bLength
0x25, // bDescriptorSubtype = CS_ENDPOINT
0x01, // bJackType = MS_GENERAL
1, // bNumEmbMIDIJack = 1 jack
MIDI_NUM_CABLES, // bNumEmbMIDIJack = number of jacks
3, // BaAssocJackID(1) = jack ID #3
#if MIDI_NUM_CABLES >= 2
7,
#endif
#if MIDI_NUM_CABLES >= 3
11,
#endif
#if MIDI_NUM_CABLES >= 4
15,
#endif
#if MIDI_NUM_CABLES >= 5
19,
#endif
#if MIDI_NUM_CABLES >= 6
23,
#endif
#if MIDI_NUM_CABLES >= 7
27,
#endif
#if MIDI_NUM_CABLES >= 8
31,
#endif
#if MIDI_NUM_CABLES >= 9
35,
#endif
#if MIDI_NUM_CABLES >= 10
39,
#endif
#if MIDI_NUM_CABLES >= 11
43,
#endif
#if MIDI_NUM_CABLES >= 12
47,
#endif
#if MIDI_NUM_CABLES >= 13
51,
#endif
#if MIDI_NUM_CABLES >= 14
55,
#endif
#if MIDI_NUM_CABLES >= 15
59,
#endif
#if MIDI_NUM_CABLES >= 16
63,
#endif
#endif // MIDI_INTERFACE

#ifdef KEYBOARD_INTERFACE

+ 109
- 0
teensy3/usb_desc.h Wyświetl plik

@@ -355,6 +355,37 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2
#define MIDI_INTERFACE 0 // MIDI
#define MIDI_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI_X8)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0485
#define BCD_DEVICE 0x0300
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','8'}
#define PRODUCT_NAME_LEN 13
#define EP0_SIZE 64
#define NUM_ENDPOINTS 4
#define NUM_USB_BUFFERS 16
#define NUM_INTERFACE 2
#define SEREMU_INTERFACE 1 // Serial emulation
#define SEREMU_TX_ENDPOINT 1
#define SEREMU_TX_SIZE 64
#define SEREMU_TX_INTERVAL 1
#define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2
#define MIDI_INTERFACE 0 // MIDI
#define MIDI_NUM_CABLES 8
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
@@ -385,6 +416,40 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI_X8_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0489
#define BCD_DEVICE 0x0300
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','8'}
#define PRODUCT_NAME_LEN 13
#define EP0_SIZE 64
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 3
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 8
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
@@ -575,6 +640,49 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define AUDIO_INTERFACE 3 // Audio (uses 3 consecutive interfaces)
#define AUDIO_TX_ENDPOINT 6
#define AUDIO_TX_SIZE 180
#define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS

#elif defined(USB_MIDI_X8_AUDIO_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x048A
#define BCD_DEVICE 0x0300
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'T','e','e','n','s','y',' ','M','I','D','I','x','8','/','A','u','d','i','o'}
#define PRODUCT_NAME_LEN 17
#define EP0_SIZE 64
#define NUM_ENDPOINTS 8
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 6
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 8
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
@@ -620,6 +728,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 3

+ 3
- 0
teensy3/usb_midi.c Wyświetl plik

@@ -36,10 +36,12 @@
#ifdef MIDI_INTERFACE // defined by usb_dev.h -> usb_desc.h
#if F_CPU >= 20000000

uint8_t usb_midi_msg_cable;
uint8_t usb_midi_msg_channel;
uint8_t usb_midi_msg_type;
uint8_t usb_midi_msg_data1;
uint8_t usb_midi_msg_data2;
// TODO: separate sysex buffers for each cable...
uint8_t usb_midi_msg_sysex[USB_MIDI_SYSEX_MAX];
uint16_t usb_midi_msg_sysex_len;
void (*usb_midi_handleNoteOff)(uint8_t ch, uint8_t note, uint8_t vel) = NULL;
@@ -241,6 +243,7 @@ int usb_midi_read(uint32_t channel)
type1 = n & 15;
type2 = (n >> 12) & 15;
ch = ((n >> 8) & 15) + 1;
usb_midi_msg_cable = (n >> 4) & 15;
if (type1 >= 0x08 && type1 <= 0x0E) {
if (channel && channel != ch) {
// ignore other channels when user wants single channel read

+ 6
- 0
teensy3/usb_midi.h Wyświetl plik

@@ -73,6 +73,7 @@ void usb_midi_flush_output(void);
int usb_midi_read(uint32_t channel);
uint32_t usb_midi_available(void);
uint32_t usb_midi_read_message(void);
extern uint8_t usb_midi_msg_cable;
extern uint8_t usb_midi_msg_channel;
extern uint8_t usb_midi_msg_type;
extern uint8_t usb_midi_msg_data1;
@@ -148,6 +149,7 @@ class usb_midi_class
send(0xE0, value, value >> 7, channel, cable);
};
void sendSysEx(uint32_t length, const uint8_t *data, bool hasTerm=false, uint8_t cable=0) __attribute__((always_inline)) {
if (cable >= MIDI_NUM_CABLES) return;
if (hasTerm) {
if (length > 2) {
usb_midi_send_sysex(data + 1, length - 2, cable);
@@ -231,6 +233,7 @@ class usb_midi_class
sendControlChange(98, 0x7F, channel, cable);
}
void send(uint8_t type, uint8_t data1, uint8_t data2, uint8_t channel, uint8_t cable) __attribute__((always_inline)) {
if (cable >= MIDI_NUM_CABLES) return;
if (type < 0xF0) {
if (type < 0x80) return;
type &= 0xF0;
@@ -252,6 +255,9 @@ class usb_midi_class
inline uint8_t getType(void) __attribute__((always_inline)) {
return usb_midi_msg_type;
};
inline uint8_t getCable(void) __attribute__((always_inline)) {
return usb_midi_msg_cable;
};
inline uint8_t getChannel(void) __attribute__((always_inline)) {
return usb_midi_msg_channel;
};

+ 12
- 0
teensy3/usb_undef.h Wyświetl plik

@@ -56,6 +56,9 @@
#ifdef PRODUCT_ID
#undef PRODUCT_ID
#endif
#ifdef BCD_DEVICE
#undef BCD_DEVICE
#endif
#ifdef DEVICE_CLASS
#undef DEVICE_CLASS
#endif
@@ -168,6 +171,15 @@
#undef CDC_IAD_DESCRIPTOR
#endif
#ifdef MIDI_INTERFACE
#undef MIDI_INTERFACE
#endif
#ifdef MIDI_NUM_CABLES
#undef MIDI_NUM_CABLES
#endif
#ifdef MIDI_INTERFACE_JACK_PAIR
#undef MIDI_INTERFACE_JACK_PAIR
#endif
#ifdef MIDI_TX_ENDPOINT
#undef MIDI_TX_ENDPOINT
#endif
#ifdef MIDI_TX_SIZE

Ładowanie…
Anuluj
Zapisz