Monday, April 13, 2015

Virtual Whammy Bar Part 6

Now that the hardware is complete it's time to program our PIC16F916 chip. In reality, I was actually writing short program snippets for each of the sub-circuits previously covered to verify their operation. After a little work it was all pieced together and tweaked to produce the working software.

So here is the general operation:

Not a whole lot going on here. There isn't even a state machine implemented, though the interrupt routine kinda resembles one.
Maybe a point of interest, when the IR strobe is turned on, the timer is set for a very short time to allow the circuit to settle. The ADC conversion is then started and the timer is then set for a much longer interval, much longer than the conversion takes in fact. It's no big deal to let the ADC result go slightly stale, as it's still too fast to be perceptible. The overall sequence of turning the IR LED on, starting the ADC, and doing something with the result happens around 120 times a second (about 8.33ms). This is actually slightly more frequent than necessary; while you can send about 1000 MIDI messages per second, 100% utilization is unrealistic if you want real-time feel. For example, if you play 100 notes simultaneously from a keyboard, the resultant audio will not be simultaneous as the last note will turn about 100ms later than the first one. And yes, that is quite noticeable. I know that I've played a keyboard thru a PC with 25-30ms latency (delay) and the disconnect between my fingers and ears makes it very difficult maintain tempo and rhythm. But my main point is that firstly you don't want to update the MIDI channel faster than you can send messages across that channel, and secondly it is not preferable to flood the channel with messages as the other side also has to respond to all those messages. Conversely, you don't want to update too slowly due to my little story above. So 8.33ms is fast enough to seem instantaneous, but 10-15 would suffice.
The LED digit displays are driven via a typical though crudely implemented software PWM. Each digit is only active half the time (since I only have one display's worth of output) but at a fast enough rate that they look continuously illuminated. I've also included adjustable brightness, so that while each digit is "active" half the time, they may only be illuminated for a portion of the time they are active, hence a PWM drive. Shown below is "half" brightness.
Not much else of interest software-wise. The buttons are checked on a software maintained timer that is.... loosely consistent. The ADC result is checked against the previous result so as not to continually send the same value if unchanged. Also, only the upper 7 bits of the 10 bit result are used (MIDI values are typically 0-127) so the three LSB's are sorta like a noise filter. I can explain the "User Interface" in a later post, but I've touched on all I've wanted to for now.