USB MIDI?
Rick Murray (539) 13851 posts |
I will shortly receive a Yamaha PSR E333 keyboard. It comes with a (sort of) MIDI interface. I say “sort of” as I believe it can do a few Yamaha-specific things as well. Not a lot of detail, but the implementation level of MIDI is here: http://download.yamaha.com/api/asset/file/?language=en&site=my.yamaha.com&asset_id=46415 People who understand how USB works will probably understand the official USB-MIDI spec: http://www.usb.org/developers/devclass_docs/midi10.pdf So – question is – will this work with RISC OS? |
Tim Rowledge (1742) 170 posts |
I’ll be interested to know how to drive midi too – it’s one of the Squeak interfaces I’ve never even tried to make work. |
nemo (145) 2556 posts |
Yes. All you have to do is write the USBMIDI driver, and interface that to an emulation of the MIDI Module to provide the same API all the existing software is expecting. Let us know how you get on. ;-)
Most manufacturers use SysEx messages to do the more outlandish stuff, but Yamaha is very good at mapping as much as possible to the usual MIDI controls. Having said that, the 333 is extremely simple so that’s not going to be a problem anyway. The USB connection might support other functionality in addition to USBMIDI of course (eg DAW controls which aren’t always done through MIDI) but that’s not likely in Yamaha’s case. |
Rick Murray (539) 13851 posts |
And the documentation of the USB system is where ? The USBMIDI spec talks about endpoints and such. It looks like there is a pipe for incoming data, and one for outgoing. Maybe more, but that’s the basics. As the USBMIDI mapping is necessarily similar to traditional MIDI, surely it shouldn’t be too much more than:
Something along those lines, right? ;-) I’ll leave it to you to point out that something simple (“this is a USBMIDI device, open it”) will require twenty pages of code and reference seventeen obscure APIs… …ditto, I might point out, Bluetooth. As a USB dongle. But where is the information on USB? This ? There was a document on Castle’s site, but Castle’s site is mostly gone these days. There is also http://www.iyonix.com/32bit/USBDevFS.shtml which may work, but does it apply to our flavour of RISC OS?
GM System Level 1 [ wiki link ] There is also an (undisclosed) protocol for transferring songs and styles to the keyboard. |
nemo (145) 2556 posts |
Trick question – which one?! Oh Castle’s, the expected place I suppose. I’ve not written any USB stuff, because I had a Simtec development board in a RiscPC (which never did anything useful) and only had a Kinetic prototype for a while before the launch (and the two are incompatible).
It already IS MIDI ‘packets’ (by which you mean two or three bytes, usually), just with a single byte logical cable number and type header. It had to be trivial to get manufacturers to adopt it.
No, that’s SysEx, and Yamaha are very good at documenting their SysEx’s (or someone has reverse engineered them). Anyway, there are third party style editors. |
Rick Murray (539) 13851 posts |
I am reviving this thread as the talk about USB devices seems off-topic in “Bounties:Would like to receive half a bounty” [Jeez, Bounties are so small these days – I remember when they used to be big and nice but now you just get two mini-sized ones in a regular pack. Still, kudos to whoever thought of making a coconut paste and wrapping chocolate around it… ;-) ] Dave Higton wrote:
I can understand the first possibly being a problem for applications, but a module wouldn’t get paged out. This leads on to another issue. If USB uses DeviceFS – why would a transfer block? Can’t DeviceFS buffer? And how does this whole shebang work anyway? If you are using an abstraction like DeviceFS this implies there is no sort of servicecall or other mechanism to alert you to the presence of data. So how is this done – do you need to sit on the centisecond ticker and check if the file you have opened has changed size over and over and over or something? Does anybody have some code (pref. in BASIC) that talks to something simple like perhaps one of those radio tuners – so I can see how it is supposed to work? |
john evans (1898) 63 posts |
“Does anybody have some code (pref. in BASIC) that talks to something simple like perhaps one of those radio tuners – so I can see how it is supposed to work?” I have a book (& it comes with code on CD) reference which may be useful, although it’s getting on a bit so you may already be aware of it? ISBN 096508193-1 “USB Complete” by Jan Axelson. “Visual Basic” is used for the examples so I imagine you could relate to those. There’s also some useful USB source available via Github I think from a chap at University of Cambridge, who has a useful on line “bare metal” programming course called “Baking Pi”. |
Rick Murray (539) 13851 posts |
John, thank you for the reference, however Visual Basic != BBC BASIC. I’m writing something now; just thought “what the hell” and plugged the keyboard in – so you will shortly see what I am talking about… |
Rick Murray (539) 13851 posts |
As mentioned, I decided to try the Suck-It-And-See approach. There is good news and bad news. The overall synopsis is that it still doesn’t work. Good news. I can bash keys on the keyboard and see stuff changing on-screen. Bad news. Whether I use BGET# or OS_BGet; the device returns null bytes (in lieu of actual data) as fast as I can read them. Looking at OS_BGet, the processor flags are always ‘4’; whether a zero byte or something else. As a result of this, I am not able to determine what is a real zero byte and what is just a phantom. Help! Here’s my code:
The result is:
If I knock out all the zero bytes, the sequence is 15,248 repeating regularly with 15,254 every so often. When I press a key, the result is 9,something,something[,something?]. The 15,xxx is a “SingleByte” command. Codes 248 and 254 are not defined in USBMIDI spec, maybe it is Yamaha specific? I modified the program to only print non-zero bytes then did the ol’ swipe down the keys thing; so I can see there is definitely data being received:
The thing I’m stuck on is telling which bytes received are real ! Can anybody suggest an idea to help here? |
john evans (1898) 63 posts |
Rick, " however Visual Basic != BBC BASIC" Yes, I realise that, just clutching at straws really :-) has some updates re’ the book, & something there may be of interest, e.g., the “Debugging usb firmware”? |
john evans (1898) 63 posts |
Rick, I’ve just plugged in my wife’s “M-audio” midi keyboard to RPi (it plugs into an iPad no problem so power very low) to see if I can replicate what you get. I’m using !USBInfo. Are you using a different tool? I’ve copied your Basic code from NetSurf to the clipboard, but can’t seem to paste it into a task window where I’ve invoked BASIC. Should I be able to? |
Rick Murray (539) 13851 posts |
John, Sorry for the delay. I was cycling the rubbish up the (~half mile) lane. The wind is bitter. I’m nursing a large cup of tea right now. I am using !USBInfo. That display is what appears when you click Menu on the USBInfo window and select I don’t browse under RISC OS (not connected to any network), so I can’t help with cut’n’paste. I just retyped the program here; for you it is probably just as quick to type it. You’ll see that the processor flags are always “4”. OS_BGet is supposed to return Carry Clear when there is a byte available; but if I read as fast as I can, or if I insert a time delay, it reads different amounts of data and as carry (bit 1) is not set, it is indicating that this is all valid data…… Obviously recording this (with and without the zero bytes) and spitting it back to the keyboard on the other endpoint does…nothing at all. Meh. |
Rick Murray (539) 13851 posts |
I’m pulling my hair out here. :-/ Here’s the code:
Here is whe result. I apologise for the length, however I can’t figure out what the hell the “free bytes in buffer” is supposed to represent. It jumps all over the place.
Oh, and a small observation. My keyboard started randomly auto-repeating, missing keys, etc. Far worse than its usual quirky self. |
Peter van der Vos (95) 115 posts |
Rick, it looks like MIDI to me. For MIDI the first byte has to have it high bit set (so bigger than 127) and then one or two bytes < 128. More info on the midi site |
Rick Murray (539) 13851 posts |
Peter, I had determined it was MIDI; but since the only way to get something sensible has been to ignore zero bytes, I don’t know if it is complete or not. I have been looking at http://www.midi.org/techspecs/midimessages.php to match things up (it looks like the periodic stuff is active sensing). There are, however, some anomalies in the received data: 248, 9, 144, 93, 43, 15, 248, 15, 248, 9, 144, 95, 9, 144, 91, 51, 15, 248, 15, 248, 9. From what I can determine, MIDI messages start with the high bit set; perhaps this could be an alternative way to filter if I can’t get the byte read to work correctly? Parsing the above: 248 = Timing clock, takes no parameters. |
Peter van der Vos (95) 115 posts |
Rick, looking at your data I see a 248 followed by a 9 or 15, which seems strange. If I look at it I don’t think the 9 / 15 are part of the midi message. In the message where you are pulling out your hair you can see the 15 is just in front of a valid midi command. Looking again, you can see a 9 before the note message and a 15 before timing clock message. Maybe it is a start of midi message with a size in it or something like that. |
Peter van der Vos (95) 115 posts |
Looking good at hair pulling message :-)
Looks good midi to me. |
Dave Higton (1515) 3534 posts |
A question that has a less than satisfactory answer. But it does. Or, alternatively, it returns padding instead. You have to decide which is worse.
Congratulations. You have discovered the nightmare that padding is. DeviceFS is predicated on a stream model. That’s OK on condition that it doesn’t block and doesn’t return bytes other than what you asked for. A stream model for interrupt IN endpoints isn’t so bad, because any incoming bytes should be requested automatically by the OS and put into the buffer. That means you don’t have to ask for a specific number to be transferred; whatever is available is transferred automatically and buffered for you. You can ask how many bytes the buffer holds and request just that number. Bulk IN is an entirely different story. Bytes coming in have to be requested. This implies that you know in advance (a) that some are ready, so that the transfer won’t block, and (b) how many there are, so that the transfer won’t block or pad if you ask for too many. USB MIDI uses bulk, but when you’re reading bytes from an input, you have no idea how many there will be – or even whether there will be any at all. Perhaps now you can understand how poorly the stream model matches the general case of USB bulk IN. |
Rick Murray (539) 13851 posts |
So “15” means some sort of status follows, and “9” means a note follows? A USBMIDI thing? [rummage – found it. It is a “Code Index Number” specific to USBMIDI] I think in my parser I’m going to search for those bytes, then the data bytes that follow, then ignore everything else. If I can bother you some more – there is no embedded time coding, just clock ticks. What would these ticks represent? Bars? Beats? I’m wondering how a [[[hemi]demi]semi]quaver might be represented if the tick is per beat.
Whoa – wait… This is by design !?!?!? Aaaargh! |
Dave Higton (1515) 3534 posts |
Yes.
Yes. |
Dave Higton (1515) 3534 posts |
Perhaps now you see why we have so few USB drivers. There isn’t a problem with USB Mass Storage devices because every bulk IN transaction is a consequence of a previous request, via a different endpoint, for exactly that number of bytes to be sent via bulk IN. You know exactly how many bytes are coming and when they’re coming. Bytes are never sent unexpectedly. There isn’t a problem with keyboard and mouse because they are interrupt IN, so you can wait and see how many bytes are in the buffer before asking for them. There isn’t a problem with USB toys, radios, etc. because communication is via control and interrupt IN. It’s an absolute nightmare with USB MIDI, as you’ve seen. It’s currently impossible with PTP and Bluetooth on the Iyonix and BB because of a bug in the stack which makes RISC OS fail to see some transfers. |
Peter van der Vos (95) 115 posts |
Ah yes indeed. So 15 means ‘single byte’ and 9 means ‘note on’.
The ticks are pulses per quarter note. You can find some more information on wiki Maybe, to avoid the stuffing bytes you can read until you find a non zero byte. Because the following message is always 32 bits and the baudrate of MIDI is 31250 bps you have to wait 24/31250 = 0.768 msec. On the other hand, if you read a Code Index Number, maybe the following bytes are valid (always 4 bytes in a USB-MIDI Event packet). If this is true you could read a character every msec (for example) and see if there is any non zero value. Then use the CIN to find the size of the midi message and send that to the midi interface. |
Rick Murray (539) 13851 posts |
I’m saying nothing……. Okay. Using what I have learned today [ ;-) ] I have put together a program that will ATTEMPT to detect a USB MIDI device. It looks for class 1 (audio) subclass 3 (streaming MIDI). If your hardware is different, you’ll need to hack the code. When the device has been found, the messages will be reported. Unused bytes, padding bytes, and anything the program doesn’t recognise will be discarded. There is a fair amount of parsing to make it human-readable; a MIDI gateway would just need to transfer the data and not interpret it. THE PROGRAM HAS NOT BEEN TESTED any further than starting it and pressing some keys on the keyboard (picture below). This is because mom has turned her bloody LW radio on and the keyboard interferes with reception. Well, so does the computer, but I think that noise is out of her hearing range (lucky escape!). If it crashes, etc, don’t blame me. Blame the lack of Radio Four on FM in the middle of rural France. ;-) Therefore – DO NOT USE THIS PROGRAM if you can’t handle fixing BASIC programs. The note on/off and basic status messages work. The command/control and program stuff didn’t get tested. Some of it is kinda complicated so may not be perfect. The program (voice selection) ought to be okay. I couldn’t be bothered parsing the instruments so I simply reported the instrument ID instead. Okay – program is here. BASIC in a zip file: http://www.heyrick.co.uk/random/miditest.zip And when run, it clears to MODE 28 and starts interpreting what it sees, like this: Right-o. I’m now going to watch Deadball (Japanese NSFW (comically OTT gorefest, yay!)) and pretend I didn’t spend hours trying to work out why all those “padding” bytes were there. Maybe if the penny had dropped sooner, I’d have finished the thing already. :-P |
john evans (1898) 63 posts |
Ok Rick, just ran your code (kept getting syntax errors with yesterday’s code & I couldn’t find any info on your arguments to OPENIN to indicate what was wrong). Pressing keys on wife’s M-audio keyboard produces similar to your posted pic’ :-) I’m off to a Raspberry Jam shortly, so if I have net access there (iffy) I’ll see if you’ve posted back with anything else to try, else it’ll be after lunch (I cycle to there on my Brompton) when I can re-check. If nothing else, your BASIC is useful to learn from (for me anyway) & maybe I can fix the tiny bug that doesn’t restore the screen res’ if no midi device is found :-) |
john evans (1898) 63 posts |
Rick, you wanted to know about “known devices” for your growing list? My initial test producing similar output to your Yamaha was with an M-audio Keystation 88-es. I’ve just done another test with M-Audio Uno 1×1 USB MIDI Interface which I plugged into an old MK-149 Evolution midi keyboard. Identified device: USB3 was the output from MidiTest, so I cheated & hard coded endpoint 1. MidiTest then didn’t complain, producing: [Active Sense] Hopefully that’s some use? I installed “Zap”, & the “syntax errors” as reported by edit & StrongEd for your BASIC programs vanished. I have no idea why those editors do that. |