MIDI Stop Controller V1.0 suitable for driving Hauptwerk digital organ software. Written for the KL25Z uses BusInOut and will drive up to 16 illuminated push buttons each switch uses a single I/O pin to both drive the LED and act as a switch input. Pressing a button will alternately send MIDI note on / off messages and turn the LED on or off. If corresponding MIDI note on/off messages are received these will be used to drive the LEDs in preference to the locally generated LED signals. The MIDI channel used to send can be selected by jumpers on 4 pins of the J2 header.
main.cpp
- Committer:
- djbottrill
- Date:
- 2013-09-14
- Revision:
- 0:aac55e1fc12f
File content as of revision 0:aac55e1fc12f:
#include "mbed.h" #include "USBMIDI.h" // MIDI Stop Controller V1.0 // USB MIDI Stop switch controller, suitable for driving stops and piston on PCs and MACs running Hauptwerk digital organ software. // This code has been written for the KL25Z but should work on other MBED boards. // Drives up to 16 illuminated pushbuttons using one bit for both the LED output and switch input. // LED connected to +V via ballast resistor, switch shorts output to gnd which is read when the bus is in input mode. // White LEDs need a 390ohm resistor to +5v other LEDs can be driven from 3.3V via 220 ohm resistor or 5V via 680 ohm. // The above values provide the maximum current that a KL25Z can sink namely 4mA per output. // Every 2ms the LED bus is switched to input in order to read the switch status then immediately switched back, // this is not noticeable as a flicker on the LEDs. Buttons need to be pressed for 2 scans to de-bounce. // The program will toggle the LEDs sending MIDI on/off messages, if Matching MIDI on / off data is received this data will be used // instaed to drive the LEDs. // The blue LED on the KL25Z will light while the USB port is initialing // The green LED on the KL25Z will flash as MIDI messages are received. DigitalOut blueled (LED1); DigitalOut greenled (LED2); DigitalOut redled (LED3); //Pins allocated for stop switches J9 and J10 headers BusInOut led(PTE5,PTE4,PTE3,PTE2,PTB11,PTB10,PTB9,PTB8,PTE30,PTE29,PTE23,PTE22,PTE21,PTE20,PTB1,PTB0); //Alternative set of pins using J1 header //BusInOut led(PTC7,PTC0,PTC3,PTC4,PTC5,PTC6,PTC10,PTC11,PTA1,PTA2,PTD4,PTA12,PTA4,PTA5,PTC8,PTC9); //Global variables extern unsigned int rx_ledstate=0; //LED recieved status buffer extern int rx_flag=0; //MIDI receive flag //Interrupt routine to receive MIDI on/off message and set LED status accordingly void get_message(MIDIMessage msg) { rx_flag=1; //Set MIDI received status flag greenled=0; //Green LED on switch (msg.type()) { case MIDIMessage::NoteOnType: //MIDI note on received rx_ledstate |= 1 << (msg.key()-36); //Set interrupt LED status on break; case MIDIMessage::NoteOffType: //Midi note off received rx_ledstate ^= 1 << (msg.key()-36); //Set received LED status off break; case MIDIMessage::AllNotesOffType: //Midi all notes off rx_ledstate=0; //Set status for all LEDs to off default: rx_ledstate=0; //Any other midi command then clear all LEDs } } BusOut linksout (PTD0, PTC13); //Channel config links outputs BusInOut linksin (PTC16, PTD5); //Channel config links inputs BusOut matrixout (PTD3, PTC17); //Matrix config links outputs BusInOut matrixin (PTA16, PTD2); //Matrix config links inputs //Main Program int main() { blueled=0; //Blue LED on redled=1; //Red LED off greenled=1; //Green LED off USBMIDI midi; //Open USB MIDI blueled=1; //Turn blue LED off when MIDI has initialised //Variables unsigned int ledstate=0; //LED status buffer unsigned int pins; //Button read buffer unsigned int bit=0; //Button bitmask unsigned int colidx=0; //Button index int sw[16]= {}; //Switch status array int velocity = 127; //Note velocity int note = 0; //Midi note buffer //Read jumpers to set MIDI channel number // 1 2 3 4 5 6 7 // [PTC13] [PTC16] 0 0 0 0 0 0 0 0 0 0 0-0 0-0 // | | | | // [PTD5 ] [PTD0 ] 0 0 0 0 0 0 0 0 0-0 0 0 0-0 const unsigned char tjumpers[]= {0,1,4,0,5,0,6,0,2,3}; //Jumper settings mode translate table (0 to 6) unsigned char jumpers[2]; //Status of the channel config jumper links int chan = 0 ; //Base Midi channel linksin.mode(PullUp); //Setup Pull Up for chan Jumpers input pins linksout=2; //Set first jumper output pin low jumpers[0]=3&(~linksin); //Read first jumper bits linksout=1; //Set second jumper output pin low jumpers[1]=3&(~linksin); //Read second jumper bits jumpers[0]=jumpers[0]+(4*jumpers[1]); //Combine into a 4 bit code chan=tjumpers[jumpers[0]]; //Set midi channel using the tjumpers translate table midi.attach(get_message); //call back for MIDI messages received led.mode(PullUp); //Bus pullup mode led.output(); //Set bus to output //Main loop while(1) { led.input(); //Set Bus to input pins=~led; //Read buttons led.output(); //Set Bus to output //Process button status bit=1; //Starting bitmask for (colidx=1; colidx<17; colidx++) { //Scan 16 buttons note=colidx+35; if ((pins&bit)>0) { //Button pressed if (sw[colidx]<3) { //De-bounce reached? sw[colidx]++; //Inc De-bounce if (sw[colidx]==2) { //De-Bounce reached? sw[colidx]=3; //Set on status if ((ledstate & bit)==0) { midi.write(MIDIMessage::NoteOn(note,velocity,chan)); //Send midi on ledstate |= 1 << (colidx-1); //Set LED on } else { midi.write(MIDIMessage::NoteOff(note,velocity,chan)); //Send midi off ledstate ^= 1 << (colidx-1); //Set LED off } } } } if ((pins&bit)==0) { //Is button released? sw[colidx]=0; //Button released so reset de-bounce counter } bit=bit*2; //Shift bitmask } //Next button if (rx_flag==1) { //If midi received use receive buffer ledstate=rx_ledstate; //instead of the switch status rx_flag=0; //Reset MIDI receive flag greenled=1; //Turn green LED off } led=~ledstate; //Update LEDs wait(0.002); //De-bounce delay } //end of main loop } //End of program