Multiple virtual MIDI ports over USB with Teensy 2.0? (Or 3.0?)

Status
Not open for further replies.
I just sent an alpha version of oscuino for Teensy 3.0 to CNMAT's release process.
Oscuino has to be tested on a rather large number of platform/device combinations so if you need a copy earlier
please e-mail me: adrian@cnmat.berkeley.edu.

Update: http://github.com/CNMAT/OSCuino is our release candidate
It runs on Teenys's and all the Arduino's I could lay my hands on except for the Due.

I will get to the Due eventually but Arduino for the Due is still too fragile and slow to build in.
 
Last edited:
Alrighty, sorry about the lack of information. I'd somehow broken the Serial/Debug interface before, and I got busy with something so I didn't have a chance to update it.

Anyway, this one should work for everyone! Serial/Debug connection intact. Some notes!

If you want to change the name of your device, that's in 'usb_private.h' - line 47 (#define STR_PRODUCT). However, as noted in the file, windows (and mac!) cache USB device info - so I've made this have a different product ID than the regular Teensy MIDI setup. If you change the vendor ID, the serial connection will not work. Don't touch it! Changing the product ID seems to work fine, though.

The functionality of this is slightly different than the built-in Teensy MIDI system. (There's probably a better way to do this, but this seems to work OK for me). The usbMIDI.read() function has changed. Instead of calling a read() for each of the 3 virtual ports, you call read on just one of them - doesn't really matter which, but you only need one. Then, you call usbMIDIa.parse(), usbMIDIb.parse(), or usbMIDIc.parse(), which splits all the incoming bits into their correct ports for you.

Essentially, this:
Code:
void loop(){
  usbMIDI.read();
}

has become this:

Code:
void loop(){
usbMIDIa.read();
usbMIDIa.parse();
usbMIDIb.parse();
usbMIDIc.parse();
}

Everything else should work pretty much the same as the normal Teensy MIDI code - although you have to change any instances of usbMIDI to usbMIDIa, b, or c. Otherwise it's all the same - set up different note handlers for each port, whatever you want to do with it. I'll admit I have not tested this extensively, so there could be giant hidden monsters somewhere that I didn't notice.

View attachment usb_midi_3_ports.zip
 
Aaand - already found an issue! Working to resolve it, though I'm not entirely clear on what's happening yet.

Essentially it seems to be possible to overload the system with too much MIDI information, and then it struggles to catch up... So if you're doing something with a large amount of MIDI data sent to the Teensy, don't use this... yet.
 
Fixed! I think. Maybe.

This is what you get when you let a non programmer play with data registers!

For those of you that understand this stuff at this level (Paul?) -

The last version, I was doing this:

Code:
	if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B; //if read/write endpoint not allowed, release the buffer
	SREG = intr_state;

	MIDIdata[0] = UEDATX;
	MIDIdata[1] = UEDATX;
	MIDIdata[2] = UEDATX;
	MIDIdata[3] = UEDATX;

Now I'm doing this:

Code:
	MIDIdata[0] = UEDATX;
	MIDIdata[1] = UEDATX;
	MIDIdata[2] = UEDATX;
	MIDIdata[3] = UEDATX;
	
	if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B; //if read/write endpoint not allowed, release the buffer
	SREG = intr_state;

From my (limited) understanding, I was checking if the buffer was empty (and releasing it if it was) before I actually pulled anything out of the buffer. Then I'd pull stuff out of the buffer - so the buffer would never actually clear (until, I assume, some other failsafe function came along and forcefully cleared it?) Now I pull data out of the buffer, THEN check if it's empty. Seems to work much more smoothly and responsively now.

Paul, if you've got the time, I invite you to pore over it and see if there's anything you might do differently. Due to the way (I think) the USB buffer stuff works, I had to set it up so that you only read from the buffer once, and then parse each 'port' separately - it's basically storing the USB buffer in a global array, and then leaving it up to each of the three MIDI ports to do anything with it. It *feels* ugly to me, but I can't think of a better solution.

As a side note, all this UEINTX and UEDATX and SREG and RWAL stuff makes my head hurt.

View attachment usb_midi_3ports_v2.zip
 
Hi,

first of all, many thanks to Paul and MuShoo, great work.

My problem is that MuShoos' solution does not work under Windows (XP and Win7 tested).

Has anyone solve this?
 
MuShoo - I found the mistake:
in usb_private.h:
Code:
#define NUM_INTERFACE		4 //virtual MIDI in/out pairs, and the debug interface
this is wrong. The count of interfaces is still 2:
Code:
#define NUM_INTERFACE		2
now it works (Windows XP):
Teensy_midi_ox.jpg
 
If I'm correct the teensy 3.0 uses the descriptors in the file ...Arduino\hardware\teensy\cores\teensy3\usb_desc.c . So i replaced the midi descriptors with those that Mushoo provided . Then I changed #define NUM_INTERFACE to 4 and #define NUM_ENDPOINTS to 5 (under USB MIDI in the file usb_desc.h) . But this doen't seem to work ....
 
Sadly, I have no idea how to get this to work on a Teensy 3.0. I haven't used them at all yet. I'm sure I'll be using one eventually (and likely attempt to make multi-port MIDI work on them), but I have no idea when that'll be.
 
My main aim of this thread is not same as my question but I found this thread while googling for TEENSY1.0 and arduino.

I want to build an USB MIDI cable with my TEENSY 1.0 (AT90USB162).

I have installed arduino 1.0.5 and teensyduino_v1.16 but I have not MIDI option in tools->usb
I have changed 'Arduino\hardware\teensy\boards.txt' and I have added these lines
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>
teensy1.menu.usb.midi.name=MIDI
teensy1.menu.usb.midi.build.define0=-DUSB_MIDI
teensy1.menu.usb.midi.fake_serial=teensy_gateway
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< <<<<<<<<<<<<<<
but during compile I got many errors. it seems in file 'Arduino\hardware\teensy\cores\usb_midi\usb_privat e.h' there is not any option for AT90USB162.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>
...
// 0: control
// 1: debug IN
// 2: debug OUT
// 3: midi IN
// 4: midi OUT

#if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)

// Some operating systems, especially Windows, may cache USB device
// info. Changes to the device name may not update on the same
// computer unless the vendor or product ID numbers change, or the
// "bcdDevice" revision code is increased.

#define STR_PRODUCT L"Teensy MIDI"
#define ENDPOINT0_SIZE 64
...
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< <<<<<<<<<<<<<<

Questions :

Did someone use AT90USB162 with USB MIDI in ARDUINO ?
Which files must be changed?
 
PJRC no longer supports any new developments on Teensy 1.0, which hasn't been sold in over 4 years.

If you have one of the original Teensy 1.0 boards purchased from PJRC, please email me directly (paul at pjrc dot com) with your original order number or invoice number, and details of the original order (eg, billing or shipping address). If Robin can look up your original order, I will send you a new board at no charge. I'll even pick up the shipping cost.

If you're using someone else's board or making your own, you are allowed to use the open source software I've published. But it comes with absolutely no technical support for use on non-PJRC products.
 
Reviving this old dead thread, as I'm updating my 3-port MIDI descriptors and code to work on Teensy 3.1, and I'm a little confused.

In Teensy 2.0-land, the code for sending a NoteOff is:

Code:
send_raw(0x08, 0x80 | ((channel - 1) & 0x0F), note & 0x7F, velocity & 0x7F);

But in Teensy 3.1-land, it's:

Code:
usb_midi_write_packed(0x8008 | (((channel - 1) & 0x0F) << 8) | ((note & 0x7F) << 16) | ((velocity & 0x7F) << 24));

Now, obviously the usb_midi_write_packed is the ARM version of sendRaw, but I'm confused as to why the first 16 bytes appear to be reversed in terms of sending order (ie, 0x08,0x80 on the old code, and 0x8008 in the new code).

I ask because my modified Teensy 2.0 code needs to pack the port number into the 0x08 portion of that, and I want to make sure I actually put it in the right place. Actually, early on in this thread, Paul mentions "They all call send_raw() to transmit 4 bytes. That first byte is the one with the cable number and message type. Just put your cable number into the upper 4 bits. Easy, right?" From some research, it looks like 0x80 is the MIDI command (send note off), and that would make the 0x08 be the portion containing the Port number, and... something else. Not sure. Highly confused.
 
Wait, wait... I THINK I get it... maybe. all the << ops should have been a hint to me. essentially, T3 MIDI packs everything... backwards? So instead of, say, 08803C00 (Note Off, note 60, velocity 0) as it is in T2.0 MIDI, it's 003C8008? Which is the opposite of how the MIDI specs I've been reading seem to delineate things. Something something endians?

I'm still a little confused but I think this is right...
 
Hi. Is it safe to directly rewrite contents of the installed usb_midi folder with the one from MuShoo?
I think that there could be some changes done by Paul in those files, since 2013 and I don't want to ruin anything (of cause, I've made a full backup of the original folder).
It would be nice if multiple ports functionality is available by default, as well as midi device + keyboard functionality. Thanks in advance.

UPD. Changed every "usbMIDI" to "usbMIDIa" in my sketch and got this error. I wonder why MuShoo didn't use usbMIDI/usbMIDI2/usbMIDI3 instead of usbMIDIa/usbMIDIb/usbMIDIc. It could be possible to use single port sketches with multiple port configuration without any changes.
w3nNcuE.png
pSmUNvT.png
 
Last edited:
Is there any news on this subject, are there any plans to make multiple virtual midi ports part of the standard distribution?

Before diving into this I'd thought I'd check the status of the developments in this area. I would like to implement multiple ports on a Teensy 3.2 and 3.6. For my current projects two ports would suffice, but it would be great if more a available.
It would be really great if multiple virtual ports would be integrated in the current usbMIDI. As it is the Teensy is already the best option for creating simple to medium complexity MIDI devices. The addition of multiple virtual ports would make it the best choice for MIDI for any type of project as it would open up a whole range of new possibilities.

I may not be able to contribute to the codebase but I'd gladly help where I can, perhaps by writing examples and documentation.

Kind regards,

Gerrit
 
Hi, I have a question regarding the virtual cables and their names. I have an application that sets up MIDI USB interface with three virtual cables. I can see them as "Port 1", "Port 2", and "Port 3" on Mac OS X. I would love to assign "Port 3" a custom name, say "Port CTRL". Any pointers on how to do that and where to look at?

Thanks!

Martin
 
Status
Not open for further replies.
Back
Top