MIDI Receiver with SX/B
Jon Williams
Posts: 6,491
A lot of folks are interested in MIDI and have used BASIC Stamp 2 modules to send MIDI data.· The trouble with receiving it with the BASIC Stamp, though, is that a lot of data can be in the stream, and things can get a bit tricky.· In a *simple* MIDI system, to turn a note on and then off, we would like to get these messages:
$90·$3C·$64·· ·' middle C on
$80 $3C $00·· ·' middle C off
The *problem* for us using the BASIC Stamp is that most MIDI instruments actually take advantage of what is called Running Status, so the way the sequence above is typically transmitted is like this:
$90·$3C·$64·· ·' middle C on
$3C $00········' middle C off
Running Status means that the receiver must keep track of the last valid status (command)·byte and when a data byte shows up before another status byte, the last status (running status) gets used.· In this case, an Note On ($90) command of $00 is used to turn the note off.· The reason this strategy is used is that is saves a byte in the stream -- and that's precious time since MIDI serial is not that fast (31.25 kBaud).
Another thing that happens is system commands.· For example, I have·keyboard that constantly sends Active Sensing ($FE) bytes.· I did some analysis and saw that the output looked something like this:
FE FE FE FE 90 3C 64 FE FE FE 3C 00 B0 7B 00 FE FE ...
You can see the Note On and running status Note Off commands, as well as a Controller ($B0) message of All Notes Off ($7B).
After creating an LED modulator using the new SX/B compiler I decided to update that code to receive and buffer MIDI data, then create a MIDI framework for processing the data.· In the attached code and schematic I am simply controlling IO pins with Note On and Note Off commands, as well as the Controller All Notes Off and System Reset.· The framework is in place, however, for handling other MIDI messages.·
The attached project will control one octave (C, C#, D ... A, A#,·B --·12 notes) of outputs.· Two sets of switches are used: a 4-position DIP switch selects the MIDI channel, a 3-position DIP switch sets the device octave; control output 1 will respond to note C in that octave.· In my tests I'm simply controlling LEDs, but the outputs could easily be sent to ULN2x03s or similar devices to drive high-current components like relays and solenoids.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA
Post Edited (Jon Williams) : 4/17/2005 4:23:05 PM GMT
$90·$3C·$64·· ·' middle C on
$80 $3C $00·· ·' middle C off
The *problem* for us using the BASIC Stamp is that most MIDI instruments actually take advantage of what is called Running Status, so the way the sequence above is typically transmitted is like this:
$90·$3C·$64·· ·' middle C on
$3C $00········' middle C off
Running Status means that the receiver must keep track of the last valid status (command)·byte and when a data byte shows up before another status byte, the last status (running status) gets used.· In this case, an Note On ($90) command of $00 is used to turn the note off.· The reason this strategy is used is that is saves a byte in the stream -- and that's precious time since MIDI serial is not that fast (31.25 kBaud).
Another thing that happens is system commands.· For example, I have·keyboard that constantly sends Active Sensing ($FE) bytes.· I did some analysis and saw that the output looked something like this:
FE FE FE FE 90 3C 64 FE FE FE 3C 00 B0 7B 00 FE FE ...
You can see the Note On and running status Note Off commands, as well as a Controller ($B0) message of All Notes Off ($7B).
After creating an LED modulator using the new SX/B compiler I decided to update that code to receive and buffer MIDI data, then create a MIDI framework for processing the data.· In the attached code and schematic I am simply controlling IO pins with Note On and Note Off commands, as well as the Controller All Notes Off and System Reset.· The framework is in place, however, for handling other MIDI messages.·
The attached project will control one octave (C, C#, D ... A, A#,·B --·12 notes) of outputs.· Two sets of switches are used: a 4-position DIP switch selects the MIDI channel, a 3-position DIP switch sets the device octave; control output 1 will respond to note C in that octave.· In my tests I'm simply controlling LEDs, but the outputs could easily be sent to ULN2x03s or similar devices to drive high-current components like relays and solenoids.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA
Post Edited (Jon Williams) : 4/17/2005 4:23:05 PM GMT
PDF
275K
Comments
good thing you dont work with nuclear technology too.
:P
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
**************
daniel woolston
Teksystems Inc.
www.danwoolston.com
**************
When I took my military entry exams for the Navy, the results were very good. The recruiter smiled and said, "Congratulations, Jon, we're going to make you a nuclear engineer on a submarine." To which I replied, "No, thanks, I'm going to go see the folks in the Air Force." That was one of the smarter moves of my life. That said, my expertise in radar and jamming techiques (I was an electronics countermeasures specialist) did not help me talk my way out of a speeding ticket a couple years ago....
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA
Post Edited (Paul Baker) : 5/16/2005 2:02:55 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA
Post Edited (Jon Williams) : 4/18/2005 6:34:48 PM GMT
Check out my thread on the SX applications forum. (SX/B serin problems) I have designed a 64 note MIDI decoder-driver for pipe organ applications. I tried to make things work without using interrupts or inserting assy language routines for the UART function, insteasd using serin, and all works well as long as there is a short time intercval between bytes in the midi on or off string. I need to adapt my program to work with an interrupt driven UART subroutine to allow time for processing the midi messages and outputing them to the buffers, but I do not yet understand how to code for this. Any help you can give me would be appreciated.
Jim Willis
If you take a few minutes with the code it will become quite easy to adapt -- so long as you use the same frequency the interrupt code is steady and will put recieved characters into a 16-byte circular buffer for you to recieve and decode. There's really nothing magic about the process, and using the buffer allows you to process complex messages while other characters are coming in.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA
I have gone over the code and it is straightforward. I have been working with ASSY language since the days of the
DEC pdp-8 and the intel 8008, but SX/B and the interface between SX/B basic and SX assy subroutines is new. Gunther has been helpful. I have a handfull of 50 MHz resonators and perhaps one 20 MHz. Can you give me the constant values for 50 MHz or is 20 MHz necessary for stable operation?
Thanks
Jim Willis
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Dallas, TX· USA
Thanks Again
Jim Willis
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
I've prototyped the jon's midi receiver project on the prodeveloper board and fixed a few hardware bugs. Now I'm going to drag my powerbook with logic over to my windows machine and start spitting MIDI at it. I'll make a test file that sweeps through 4 octaves pretty quickly on an "omni" channel setting. This should give me the ability to see the midi data I'm sending and if there is any response from the device.
Another very simple question first. in the schematics there are dip switches to set the channel and octave. (I KNOW THIS IS A STUPID QUESTION, but I really am just learning). but short of using my sequencer to "sweep" through different channels and test for a response. Does anybody know how to set the dip switches to determine the channel?
Like I said I feel kind of silly asking all of these simple questions. I read the Nutz and Voltz article on the "Joy's of experimenting" and I agree completely. I am prepared to use the sequencer and work backwards to figure it out. However, understanding the underlying concept would be great.
thanks in advance
Studying the code (hint, hint...) will answer your questions. The channel switch is read with this routine:
' Use: GETCHANNEL
' -- reads channel inputs and refreshes 'channel'
GETCHANNEL:
· channel = ~CtrlHi············· ' get channel number
· SWAP channel
· channel = channel & $0F
· RETURN
Note that the switches get inverted (~ operator does that) -- so a closed switch is a "1" bit. All switches open then, is 0 (MIDI channel 1); all switches closed is 15 (MIDI channel 16).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
thanks for the hints
first: somehow I have managed to get it to work in an "omni" mode. The Dip switches for the Octaves clearly work. However, unless I'm misunderstanding the code. The channel DIP switches are supposed to allow you to select a SPECIFIC channel. Now I i know that the mistake is mine, just looking for clarity on a few points.
When establishing a breakpoint at line 366 in the code in the NOTEON subroutine (IF temp1 = channel THEN). If only the first (channel) dip switch is closed I get 00000001 in the W register (01) and F in the M register. That is dec 1 or midi channel 2. The strange thing is, if I play a keyboard on any channel when it is configured this way, as long as the notes are with in range, I get note ons. (?)
And yet,
if I set any other DIP combination (as an example): first two channel dip switches closed, second two open. I get 00000011 in the W register (03) and F in the M register. That should be Decimal 3, or midi channel 4. THE POINT IS WITH ANY OTHER COMBINATION OF DIP SWITCHES I GET NO REACTION (no Note ons).
I realize (i think) that the program initially reads the the DIP channel setting in the GETCHANNEL subroutine so:
When establishing a breakpoint at line 506 in the code in the GETCHANNEL subroutine ( MOV W,/Ctrl1Hi). If only the first (channel) dip switch is closed I get 00011111 in the W register (1F) and F in the M register. that would be(?) decimal 31 or midi channel 32.(?) So it appears as if the dip switches are being read.
side note: I've been sending midi messages through both Logic and a very simple midi keyboard. I have been monitoring their output to confirm there channel settings
I realize that I've been shooting questions left and right. I'm just really excited about this stuff and trying to learn. THANKS!
For specifics on BASIC Stamp coding your should post these kinds of question in that forum.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
btw my final goal is a midi transformer device, so i also need to add midi output vp/uart to this code, so if anyone reading this has already done that, please share!!
You are correct. The internal pull-ups could have been used instead.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cheap 4-digit LED display with driver IC·www.hc4led.com
Low power SD Data Logger www.sddatalogger.com
"The meaning of life, is to give life meaning" Unknown.
·
' patch already in midiDB2
after some 'clever' thinking, I assume Jon means midiDB1...?
greetings
Vinnie