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.

Dependencies:   mbed

Committer:
djbottrill
Date:
Sat Sep 14 21:32:06 2013 +0000
Revision:
0:aac55e1fc12f
V1.0 MIDI Stop Controller

Who changed what in which revision?

UserRevisionLine numberNew contents of line
djbottrill 0:aac55e1fc12f 1 #include "mbed.h"
djbottrill 0:aac55e1fc12f 2 #include "USBMIDI.h"
djbottrill 0:aac55e1fc12f 3 // MIDI Stop Controller V1.0
djbottrill 0:aac55e1fc12f 4 // USB MIDI Stop switch controller, suitable for driving stops and piston on PCs and MACs running Hauptwerk digital organ software.
djbottrill 0:aac55e1fc12f 5 // This code has been written for the KL25Z but should work on other MBED boards.
djbottrill 0:aac55e1fc12f 6 // Drives up to 16 illuminated pushbuttons using one bit for both the LED output and switch input.
djbottrill 0:aac55e1fc12f 7 // LED connected to +V via ballast resistor, switch shorts output to gnd which is read when the bus is in input mode.
djbottrill 0:aac55e1fc12f 8 // 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.
djbottrill 0:aac55e1fc12f 9 // The above values provide the maximum current that a KL25Z can sink namely 4mA per output.
djbottrill 0:aac55e1fc12f 10 // Every 2ms the LED bus is switched to input in order to read the switch status then immediately switched back,
djbottrill 0:aac55e1fc12f 11 // this is not noticeable as a flicker on the LEDs. Buttons need to be pressed for 2 scans to de-bounce.
djbottrill 0:aac55e1fc12f 12 // The program will toggle the LEDs sending MIDI on/off messages, if Matching MIDI on / off data is received this data will be used
djbottrill 0:aac55e1fc12f 13 // instaed to drive the LEDs.
djbottrill 0:aac55e1fc12f 14 // The blue LED on the KL25Z will light while the USB port is initialing
djbottrill 0:aac55e1fc12f 15 // The green LED on the KL25Z will flash as MIDI messages are received.
djbottrill 0:aac55e1fc12f 16
djbottrill 0:aac55e1fc12f 17 DigitalOut blueled (LED1);
djbottrill 0:aac55e1fc12f 18 DigitalOut greenled (LED2);
djbottrill 0:aac55e1fc12f 19 DigitalOut redled (LED3);
djbottrill 0:aac55e1fc12f 20
djbottrill 0:aac55e1fc12f 21 //Pins allocated for stop switches J9 and J10 headers
djbottrill 0:aac55e1fc12f 22 BusInOut led(PTE5,PTE4,PTE3,PTE2,PTB11,PTB10,PTB9,PTB8,PTE30,PTE29,PTE23,PTE22,PTE21,PTE20,PTB1,PTB0);
djbottrill 0:aac55e1fc12f 23 //Alternative set of pins using J1 header
djbottrill 0:aac55e1fc12f 24 //BusInOut led(PTC7,PTC0,PTC3,PTC4,PTC5,PTC6,PTC10,PTC11,PTA1,PTA2,PTD4,PTA12,PTA4,PTA5,PTC8,PTC9);
djbottrill 0:aac55e1fc12f 25
djbottrill 0:aac55e1fc12f 26 //Global variables
djbottrill 0:aac55e1fc12f 27 extern unsigned int rx_ledstate=0; //LED recieved status buffer
djbottrill 0:aac55e1fc12f 28 extern int rx_flag=0; //MIDI receive flag
djbottrill 0:aac55e1fc12f 29
djbottrill 0:aac55e1fc12f 30 //Interrupt routine to receive MIDI on/off message and set LED status accordingly
djbottrill 0:aac55e1fc12f 31 void get_message(MIDIMessage msg)
djbottrill 0:aac55e1fc12f 32 {
djbottrill 0:aac55e1fc12f 33 rx_flag=1; //Set MIDI received status flag
djbottrill 0:aac55e1fc12f 34 greenled=0; //Green LED on
djbottrill 0:aac55e1fc12f 35 switch (msg.type()) {
djbottrill 0:aac55e1fc12f 36 case MIDIMessage::NoteOnType: //MIDI note on received
djbottrill 0:aac55e1fc12f 37 rx_ledstate |= 1 << (msg.key()-36); //Set interrupt LED status on
djbottrill 0:aac55e1fc12f 38 break;
djbottrill 0:aac55e1fc12f 39 case MIDIMessage::NoteOffType: //Midi note off received
djbottrill 0:aac55e1fc12f 40 rx_ledstate ^= 1 << (msg.key()-36); //Set received LED status off
djbottrill 0:aac55e1fc12f 41 break;
djbottrill 0:aac55e1fc12f 42 case MIDIMessage::AllNotesOffType: //Midi all notes off
djbottrill 0:aac55e1fc12f 43 rx_ledstate=0; //Set status for all LEDs to off
djbottrill 0:aac55e1fc12f 44 default:
djbottrill 0:aac55e1fc12f 45 rx_ledstate=0; //Any other midi command then clear all LEDs
djbottrill 0:aac55e1fc12f 46 }
djbottrill 0:aac55e1fc12f 47 }
djbottrill 0:aac55e1fc12f 48
djbottrill 0:aac55e1fc12f 49 BusOut linksout (PTD0, PTC13); //Channel config links outputs
djbottrill 0:aac55e1fc12f 50 BusInOut linksin (PTC16, PTD5); //Channel config links inputs
djbottrill 0:aac55e1fc12f 51 BusOut matrixout (PTD3, PTC17); //Matrix config links outputs
djbottrill 0:aac55e1fc12f 52 BusInOut matrixin (PTA16, PTD2); //Matrix config links inputs
djbottrill 0:aac55e1fc12f 53
djbottrill 0:aac55e1fc12f 54
djbottrill 0:aac55e1fc12f 55 //Main Program
djbottrill 0:aac55e1fc12f 56 int main()
djbottrill 0:aac55e1fc12f 57 {
djbottrill 0:aac55e1fc12f 58 blueled=0; //Blue LED on
djbottrill 0:aac55e1fc12f 59 redled=1; //Red LED off
djbottrill 0:aac55e1fc12f 60 greenled=1; //Green LED off
djbottrill 0:aac55e1fc12f 61 USBMIDI midi; //Open USB MIDI
djbottrill 0:aac55e1fc12f 62 blueled=1; //Turn blue LED off when MIDI has initialised
djbottrill 0:aac55e1fc12f 63
djbottrill 0:aac55e1fc12f 64 //Variables
djbottrill 0:aac55e1fc12f 65 unsigned int ledstate=0; //LED status buffer
djbottrill 0:aac55e1fc12f 66 unsigned int pins; //Button read buffer
djbottrill 0:aac55e1fc12f 67 unsigned int bit=0; //Button bitmask
djbottrill 0:aac55e1fc12f 68 unsigned int colidx=0; //Button index
djbottrill 0:aac55e1fc12f 69 int sw[16]= {}; //Switch status array
djbottrill 0:aac55e1fc12f 70 int velocity = 127; //Note velocity
djbottrill 0:aac55e1fc12f 71 int note = 0; //Midi note buffer
djbottrill 0:aac55e1fc12f 72
djbottrill 0:aac55e1fc12f 73 //Read jumpers to set MIDI channel number
djbottrill 0:aac55e1fc12f 74 // 1 2 3 4 5 6 7
djbottrill 0:aac55e1fc12f 75 // [PTC13] [PTC16] 0 0 0 0 0 0 0 0 0 0 0-0 0-0
djbottrill 0:aac55e1fc12f 76 // | | | |
djbottrill 0:aac55e1fc12f 77 // [PTD5 ] [PTD0 ] 0 0 0 0 0 0 0 0 0-0 0 0 0-0
djbottrill 0:aac55e1fc12f 78
djbottrill 0:aac55e1fc12f 79 const unsigned char tjumpers[]= {0,1,4,0,5,0,6,0,2,3}; //Jumper settings mode translate table (0 to 6)
djbottrill 0:aac55e1fc12f 80 unsigned char jumpers[2]; //Status of the channel config jumper links
djbottrill 0:aac55e1fc12f 81 int chan = 0 ; //Base Midi channel
djbottrill 0:aac55e1fc12f 82 linksin.mode(PullUp); //Setup Pull Up for chan Jumpers input pins
djbottrill 0:aac55e1fc12f 83 linksout=2; //Set first jumper output pin low
djbottrill 0:aac55e1fc12f 84 jumpers[0]=3&(~linksin); //Read first jumper bits
djbottrill 0:aac55e1fc12f 85 linksout=1; //Set second jumper output pin low
djbottrill 0:aac55e1fc12f 86 jumpers[1]=3&(~linksin); //Read second jumper bits
djbottrill 0:aac55e1fc12f 87 jumpers[0]=jumpers[0]+(4*jumpers[1]); //Combine into a 4 bit code
djbottrill 0:aac55e1fc12f 88 chan=tjumpers[jumpers[0]]; //Set midi channel using the tjumpers translate table
djbottrill 0:aac55e1fc12f 89
djbottrill 0:aac55e1fc12f 90 midi.attach(get_message); //call back for MIDI messages received
djbottrill 0:aac55e1fc12f 91 led.mode(PullUp); //Bus pullup mode
djbottrill 0:aac55e1fc12f 92 led.output(); //Set bus to output
djbottrill 0:aac55e1fc12f 93
djbottrill 0:aac55e1fc12f 94 //Main loop
djbottrill 0:aac55e1fc12f 95 while(1) {
djbottrill 0:aac55e1fc12f 96 led.input(); //Set Bus to input
djbottrill 0:aac55e1fc12f 97 pins=~led; //Read buttons
djbottrill 0:aac55e1fc12f 98 led.output(); //Set Bus to output
djbottrill 0:aac55e1fc12f 99 //Process button status
djbottrill 0:aac55e1fc12f 100 bit=1; //Starting bitmask
djbottrill 0:aac55e1fc12f 101 for (colidx=1; colidx<17; colidx++) { //Scan 16 buttons
djbottrill 0:aac55e1fc12f 102 note=colidx+35;
djbottrill 0:aac55e1fc12f 103 if ((pins&bit)>0) { //Button pressed
djbottrill 0:aac55e1fc12f 104 if (sw[colidx]<3) { //De-bounce reached?
djbottrill 0:aac55e1fc12f 105 sw[colidx]++; //Inc De-bounce
djbottrill 0:aac55e1fc12f 106 if (sw[colidx]==2) { //De-Bounce reached?
djbottrill 0:aac55e1fc12f 107 sw[colidx]=3; //Set on status
djbottrill 0:aac55e1fc12f 108 if ((ledstate & bit)==0) {
djbottrill 0:aac55e1fc12f 109 midi.write(MIDIMessage::NoteOn(note,velocity,chan)); //Send midi on
djbottrill 0:aac55e1fc12f 110 ledstate |= 1 << (colidx-1); //Set LED on
djbottrill 0:aac55e1fc12f 111 } else {
djbottrill 0:aac55e1fc12f 112 midi.write(MIDIMessage::NoteOff(note,velocity,chan)); //Send midi off
djbottrill 0:aac55e1fc12f 113 ledstate ^= 1 << (colidx-1); //Set LED off
djbottrill 0:aac55e1fc12f 114 }
djbottrill 0:aac55e1fc12f 115 }
djbottrill 0:aac55e1fc12f 116 }
djbottrill 0:aac55e1fc12f 117 }
djbottrill 0:aac55e1fc12f 118 if ((pins&bit)==0) { //Is button released?
djbottrill 0:aac55e1fc12f 119 sw[colidx]=0; //Button released so reset de-bounce counter
djbottrill 0:aac55e1fc12f 120 }
djbottrill 0:aac55e1fc12f 121 bit=bit*2; //Shift bitmask
djbottrill 0:aac55e1fc12f 122 } //Next button
djbottrill 0:aac55e1fc12f 123 if (rx_flag==1) { //If midi received use receive buffer
djbottrill 0:aac55e1fc12f 124 ledstate=rx_ledstate; //instead of the switch status
djbottrill 0:aac55e1fc12f 125 rx_flag=0; //Reset MIDI receive flag
djbottrill 0:aac55e1fc12f 126 greenled=1; //Turn green LED off
djbottrill 0:aac55e1fc12f 127 }
djbottrill 0:aac55e1fc12f 128 led=~ledstate; //Update LEDs
djbottrill 0:aac55e1fc12f 129 wait(0.002); //De-bounce delay
djbottrill 0:aac55e1fc12f 130 } //end of main loop
djbottrill 0:aac55e1fc12f 131 } //End of program