USBMIDI sampled pipe organ uses real pipe organ samples to produce a realistic sound with 16 note polyphony. A serial output will drive external TPIC6A596 shift registers that could be used to drive pipe organ magnets (Solenoid valves)

Dependencies:   TextLCD USBDevice mbed

Committer:
djbottrill
Date:
Fri Nov 20 23:01:29 2015 +0000
Revision:
30:f7aa90a1e443
Parent:
28:753d70280c19
Further tidy up of comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
djbottrill 0:4d06e0867376 1 /*
djbottrill 0:4d06e0867376 2 Program to drive organ magnets from a MIDI input
djbottrill 0:4d06e0867376 3 From Midi note 36 the notes are send to a 96 bit shift register organ magnet driver board based on 12 x TPIC6B595 shift registers
djbottrill 16:d2694fb530c3 4 The program uses the DAC to generate 16 sampled audio channel outputs at up to 44.1Khz that mirror the solenoid outputs, but also run from
djbottrill 0:4d06e0867376 5 MIDI note 24 so the bottom 16' octave can be generated electronically if 16' pipes are not feasible.
djbottrill 0:4d06e0867376 6 In fact the sampled output could be tailored to fill in any missing note ranges,
djbottrill 0:4d06e0867376 7 Repeated pressing sw3 cycles through a number of display modes.
djbottrill 28:753d70280c19 8 Pressing sw1 switches between two sound samples Bourdon and Montre only one rank is availble at any one time.
djbottrill 28:753d70280c19 9 This program is currently only compatible with the K64F as it's one of the few MBED boards that has sufficient speed, Flash ROM storage
djbottrill 28:753d70280c19 10 and of course a DAC.
djbottrill 30:f7aa90a1e443 11 The sounds samples are derived from the Jeux D'Orgue 2 sample set http://www.jeuxdorgues.com and are used with permission.
djbottrill 0:4d06e0867376 12 */
djbottrill 0:4d06e0867376 13 #include "mbed.h"
djbottrill 0:4d06e0867376 14
djbottrill 21:04febed27b55 15 #include "Bourdon.h"
djbottrill 20:b4c61f856346 16 #include "Montre.h"
djbottrill 27:98dad49081ff 17
djbottrill 27:98dad49081ff 18 /*
djbottrill 27:98dad49081ff 19 As the ticker cannot be accurately controlled it is necessary to apply a fine adjustment capability
djbottrill 27:98dad49081ff 20 hence the fine tune below that is used to multiply the step index as read from freqtab.
djbottrill 27:98dad49081ff 21 freqtab is based on the assumption the ticker is running at exactly 44.1Khz
djbottrill 27:98dad49081ff 22 */
djbottrill 27:98dad49081ff 23 const float sample_rate = 22.68; //44.1KHz
djbottrill 27:98dad49081ff 24 const float freqfine=0.970;
djbottrill 21:04febed27b55 25 const float freqtab[] = {1, 1.0596, 1.1227, 1.1893, 1.2599, 1.3348, 1.4144, 1.4985, 1.5872, 1.6819, 1.782, 1.888, 2};
djbottrill 17:7f27f4921305 26
djbottrill 0:4d06e0867376 27 #include "USBMIDI.h"
djbottrill 0:4d06e0867376 28
djbottrill 0:4d06e0867376 29 #include "TextLCD.h"
djbottrill 0:4d06e0867376 30 //For Linksprite LCD Shield
djbottrill 0:4d06e0867376 31 //TextLCD lcd(PTC12, D9, D4, D5, D6, D7); // rs, e, d4-d7
djbottrill 0:4d06e0867376 32 //DigitalOut bl(D10);
djbottrill 0:4d06e0867376 33 //D8 is wrong on K64F definition it is actually PTC12 not PTA0
djbottrill 0:4d06e0867376 34
djbottrill 0:4d06e0867376 35 //For Midas 2x16 OLED Display
djbottrill 0:4d06e0867376 36 TextLCD lcd (D2, D3, D4, D5,D6, D7, TextLCD::LCD16x2, NC, NC, TextLCD::WS0010 ); // 4bit bus: RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=WS0010
djbottrill 0:4d06e0867376 37
djbottrill 0:4d06e0867376 38 //Serial pc(USBTX, USBRX); // tx, rx
djbottrill 0:4d06e0867376 39
djbottrill 0:4d06e0867376 40 AnalogOut Aout(DAC0_OUT);
djbottrill 0:4d06e0867376 41
djbottrill 0:4d06e0867376 42 DigitalOut redled(LED1);
djbottrill 0:4d06e0867376 43 DigitalOut greenled(LED2);
djbottrill 0:4d06e0867376 44 DigitalOut blueled(LED3);
djbottrill 0:4d06e0867376 45
djbottrill 0:4d06e0867376 46 DigitalOut diag(D15);
djbottrill 0:4d06e0867376 47 DigitalOut diag2(D14);
djbottrill 0:4d06e0867376 48
djbottrill 0:4d06e0867376 49 DigitalIn sw1(PTC6);
djbottrill 0:4d06e0867376 50 DigitalIn sw3(PTA4);
djbottrill 0:4d06e0867376 51
djbottrill 28:753d70280c19 52 //Stop switches mommentary connection to 0V will toggle on and off. 8' pitch defaults to on at power up.
djbottrill 15:c1854904f0d7 53 DigitalIn p1 (PTB2); //16'
djbottrill 15:c1854904f0d7 54 DigitalIn p2 (PTB3); //8'
djbottrill 15:c1854904f0d7 55 DigitalIn p3 (PTB10); //4'
djbottrill 15:c1854904f0d7 56 DigitalIn p4 (PTB11); //2 2/3'
djbottrill 15:c1854904f0d7 57 DigitalIn p5 (PTC11); //2'
djbottrill 12:74b52900cddb 58
djbottrill 0:4d06e0867376 59 //Wi-Fi connector J6 note pin 3 is incorrectly idenifed in the documentation as PTC12
djbottrill 9:b0f110c02b1b 60 //Connects the shift register solenoid driver board
djbottrill 0:4d06e0867376 61 DigitalOut SRCK(PTD7); //Shift Register clock
djbottrill 0:4d06e0867376 62 DigitalOut RCK(PTD5); //Shift Register latch
djbottrill 0:4d06e0867376 63 DigitalOut SER1(PTB20); //Shift Register serial data outout
djbottrill 0:4d06e0867376 64
djbottrill 0:4d06e0867376 65
djbottrill 9:b0f110c02b1b 66 Ticker output_ticker; //Ticker for sound generation
djbottrill 0:4d06e0867376 67
djbottrill 28:753d70280c19 68 unsigned char keybuf[128]= {}; //Note buffer
djbottrill 28:753d70280c19 69 unsigned char oldkeybuf[128]= {}; //Last note buffer
djbottrill 16:d2694fb530c3 70 int keyidx=0; //Key index
djbottrill 0:4d06e0867376 71
djbottrill 30:f7aa90a1e443 72 //Received MIDI note variables
djbottrill 28:753d70280c19 73 int key=0;
djbottrill 0:4d06e0867376 74 int velocity=0;
djbottrill 0:4d06e0867376 75 int chan=0;
djbottrill 0:4d06e0867376 76 int onoff=0;
djbottrill 0:4d06e0867376 77
djbottrill 0:4d06e0867376 78 unsigned int audio_out; //Audio output value accumulator
djbottrill 0:4d06e0867376 79
djbottrill 0:4d06e0867376 80 //OLELD display bar graph characters
djbottrill 0:4d06e0867376 81 const char udc0[] = {0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00};
djbottrill 0:4d06e0867376 82 const char udc1[] = {0x15, 0x10, 0x10, 0x10, 0x10, 0x10, 0x15, 0x00};
djbottrill 0:4d06e0867376 83 const char udc2[] = {0x15, 0x04, 0x04, 0x04, 0x04, 0x04, 0x15, 0x00};
djbottrill 0:4d06e0867376 84 const char udc3[] = {0x15, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x00};
djbottrill 0:4d06e0867376 85 const char udc4[] = {0x15, 0x01, 0x01, 0x01, 0x01, 0x01, 0x15, 0x00};
djbottrill 0:4d06e0867376 86 const char udc5[] = {0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x00};
djbottrill 0:4d06e0867376 87 const char udc6[] = {0x15, 0x05, 0x05, 0x05, 0x05, 0x05, 0x15, 0x00};
djbottrill 0:4d06e0867376 88 const char udc7[] = {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00};
djbottrill 0:4d06e0867376 89
djbottrill 0:4d06e0867376 90 //Variables for LCD/OLED display
djbottrill 0:4d06e0867376 91 unsigned long int lcd_stat=0;
djbottrill 0:4d06e0867376 92 unsigned long int lcd_stat_old=1;
djbottrill 0:4d06e0867376 93 char display[2][16]; //Display Buffer
djbottrill 0:4d06e0867376 94 char display_old[2][16]; //Old Display Buffer
djbottrill 0:4d06e0867376 95 int pos=0; //Display Position counter
djbottrill 0:4d06e0867376 96 int row=0;
djbottrill 0:4d06e0867376 97 int tval=0;
djbottrill 12:74b52900cddb 98 int tval1=0;
djbottrill 0:4d06e0867376 99 int keyidx_t=0;
djbottrill 0:4d06e0867376 100 int lcdmode=0; //LCD Display Mode
djbottrill 8:df5f305aab22 101 int x =0;
djbottrill 8:df5f305aab22 102 int x1=1;
djbottrill 9:b0f110c02b1b 103
djbottrill 28:753d70280c19 104 //Button and stop variables
djbottrill 23:31cb90fa661f 105 unsigned int swi;
djbottrill 23:31cb90fa661f 106 unsigned int pressed;
djbottrill 23:31cb90fa661f 107 unsigned int sw[8];
djbottrill 23:31cb90fa661f 108 unsigned int sw_count[8]; //Switch de-bounce counter
djbottrill 23:31cb90fa661f 109 unsigned int sw_phase[8];
djbottrill 28:753d70280c19 110 unsigned int sw_status[8]= {0,1,0,0,0,0,0,0}; //Stop status 8' on by default
djbottrill 23:31cb90fa661f 111 unsigned int sw_old[8];
djbottrill 16:d2694fb530c3 112 int oldstops=1;
djbottrill 0:4d06e0867376 113
djbottrill 0:4d06e0867376 114 //Sound generator variables
djbottrill 17:7f27f4921305 115 int sampleset=0;
djbottrill 0:4d06e0867376 116 int tempidx=0;
djbottrill 0:4d06e0867376 117 int freqidx=45;
djbottrill 0:4d06e0867376 118 float synth[16];
djbottrill 0:4d06e0867376 119 float synthidx[16];
djbottrill 0:4d06e0867376 120 int synth_old[16];
djbottrill 0:4d06e0867376 121 int synthtab[16]= {};
djbottrill 0:4d06e0867376 122 int synthstat[16]= {};
djbottrill 4:9f63e68b548e 123 unsigned char synthoctave[16]= {};
djbottrill 4:9f63e68b548e 124 unsigned char synthnote[16]= {};
djbottrill 12:74b52900cddb 125 int sucess=0;
djbottrill 0:4d06e0867376 126 int noteidx=0;
djbottrill 0:4d06e0867376 127 int i;
djbottrill 0:4d06e0867376 128 int ii;
djbottrill 9:b0f110c02b1b 129 int cl;
djbottrill 0:4d06e0867376 130
djbottrill 0:4d06e0867376 131 /*
djbottrill 0:4d06e0867376 132 Ticker routine to calculate and output the audio signal.
djbottrill 30:f7aa90a1e443 133 As the DAC is 12 bit this allows for 16 concurrent 8 bit samples running with no additional loss of precision.
djbottrill 0:4d06e0867376 134 The samples should be normalised to maximise the 8 bit range as only one sample is used there is no need to generate sounds with different amplitude.
djbottrill 5:13a1e5e4494d 135 Sound Generation is in 4 states stored in synthstat:
djbottrill 0:4d06e0867376 136 0 = Synth Channel idle
djbottrill 0:4d06e0867376 137 1 = Attack / Sustain phase note running and looping if necessary
djbottrill 30:f7aa90a1e443 138 2 = Signal to start release this may be delayed until the sound is paat the initial attack/decay point typically 100-200 mS
djbottrill 28:753d70280c19 139 3 = Sample is in the release phase.
djbottrill 0:4d06e0867376 140
djbottrill 0:4d06e0867376 141 */
djbottrill 0:4d06e0867376 142 void aout()
djbottrill 0:4d06e0867376 143 {
djbottrill 30:f7aa90a1e443 144 //The lines below are commented out and actually add to much time to the ticker routine each command adds around 1 uS which is significant
djbottrill 30:f7aa90a1e443 145 //when the whole routine only takes around 16uS and is repeated every 23mS
djbottrill 15:c1854904f0d7 146 // diag=1; //Pulse DIAG Pin for Scoping purposes IE pin high
djbottrill 15:c1854904f0d7 147 // redled=0; //Pulse Red LED to indicate Ticker working
djbottrill 0:4d06e0867376 148 audio_out=0; //Clear Audio Accumulator
djbottrill 17:7f27f4921305 149 if (sampleset==0) {
djbottrill 19:4cec60669626 150 for (i =0; i<16; i++) { //Do 16 channels
djbottrill 17:7f27f4921305 151 switch (synthstat[i]) {
djbottrill 17:7f27f4921305 152 case 1: //Sustain phase
djbottrill 19:4cec60669626 153 if (synth[i]>sample1_loop_end[synthoctave[i]]) { //Got to end of buffer?
djbottrill 19:4cec60669626 154 synth[i]=sample1_loop_start[synthoctave[i]]; //Wrap around back to start
djbottrill 17:7f27f4921305 155 }
djbottrill 17:7f27f4921305 156 break;
djbottrill 17:7f27f4921305 157 case 2: //Note off demand state
djbottrill 19:4cec60669626 158 if (synth[i]>=sample1_attack[synthoctave[i]]) { //Delay decay phase if not past end of attack
djbottrill 0:4d06e0867376 159 //Check if the waveform is close to zero crossing this helps eliminate clicks looks for rising edge approaching 0x80
djbottrill 17:7f27f4921305 160 tempidx=synth[i];
djbottrill 17:7f27f4921305 161 if (sample1[synthoctave[i]][tempidx]<128 & sample1[synthoctave[i]][tempidx]>120) {
djbottrill 17:7f27f4921305 162 if (sample1[synthoctave[i]][tempidx]>synth_old[i]) {
djbottrill 28:753d70280c19 163 synth[i]=sample1_loop_off[synthoctave[i]]; //Jump to start of release
djbottrill 28:753d70280c19 164 synthstat[i]=3; //Say note in release
djbottrill 17:7f27f4921305 165 }
djbottrill 0:4d06e0867376 166 }
djbottrill 0:4d06e0867376 167 }
djbottrill 17:7f27f4921305 168 break;
djbottrill 17:7f27f4921305 169 case 3: //Check if decay has completed
djbottrill 28:753d70280c19 170 if (synth[i]>=sample1_len[synthoctave[i]]) { //End of release?
djbottrill 19:4cec60669626 171 synthstat[i]=0; //say channel free
djbottrill 19:4cec60669626 172 synth[i]=0; //Set sample pointer to 0
djbottrill 19:4cec60669626 173 synthidx[i]=0; //Set sample index to 0
djbottrill 19:4cec60669626 174 synthtab[i]=255; //Set to invalid
djbottrill 17:7f27f4921305 175 }
djbottrill 17:7f27f4921305 176 break ;
djbottrill 17:7f27f4921305 177 }
djbottrill 4:9f63e68b548e 178
djbottrill 4:9f63e68b548e 179 //get sample and add to Audio Accumulator
djbottrill 19:4cec60669626 180 synth_old[i]=sample1[synthoctave[i]][(int)(synth[i])]; //Get and save old sample
djbottrill 20:b4c61f856346 181 audio_out=audio_out+synth_old[i]; //add sample to audio out accumulator
djbottrill 19:4cec60669626 182 synth[i]=synth[i]+synthidx[i]; //Get next sample pointer
djbottrill 17:7f27f4921305 183
djbottrill 19:4cec60669626 184 } //Next Note
djbottrill 17:7f27f4921305 185 } else {
djbottrill 17:7f27f4921305 186
djbottrill 17:7f27f4921305 187 //Sample Set 2
djbottrill 16:d2694fb530c3 188
djbottrill 19:4cec60669626 189 for (i =0; i<16; i++) { //Do 16 channels
djbottrill 17:7f27f4921305 190 switch (synthstat[i]) {
djbottrill 17:7f27f4921305 191 case 1: //Sustain phase
djbottrill 19:4cec60669626 192 if (synth[i]>sample2_loop_end[synthoctave[i]]) { //Got to end of buffer?
djbottrill 19:4cec60669626 193 synth[i]=sample2_loop_start[synthoctave[i]]; //Wrap around back to start
djbottrill 17:7f27f4921305 194 }
djbottrill 17:7f27f4921305 195 break;
djbottrill 17:7f27f4921305 196 case 2: //Note off demand state
djbottrill 28:753d70280c19 197 if (synth[i]>=sample2_attack[synthoctave[i]]) { //Delay release phase if not past end of attack
djbottrill 17:7f27f4921305 198 //Check if the waveform is close to zero crossing this helps eliminate clicks looks for rising edge approaching 0x80
djbottrill 17:7f27f4921305 199 tempidx=synth[i];
djbottrill 17:7f27f4921305 200 if (sample2[synthoctave[i]][tempidx]<128 & sample2[synthoctave[i]][tempidx]>120) {
djbottrill 17:7f27f4921305 201 if (sample2[synthoctave[i]][tempidx]>synth_old[i]) {
djbottrill 28:753d70280c19 202 synth[i]=sample2_loop_off[synthoctave[i]]; //Jump to start of release
djbottrill 28:753d70280c19 203 synthstat[i]=3; //Say note in release
djbottrill 17:7f27f4921305 204 }
djbottrill 17:7f27f4921305 205 }
djbottrill 17:7f27f4921305 206 }
djbottrill 17:7f27f4921305 207 break;
djbottrill 28:753d70280c19 208 case 3: //Check if release has completed
djbottrill 28:753d70280c19 209 if (synth[i]>=sample2_len[synthoctave[i]]) { //End of release?
djbottrill 19:4cec60669626 210 synthstat[i]=0; //say channel free
djbottrill 19:4cec60669626 211 synth[i]=0; //Set sample pointer to 0
djbottrill 19:4cec60669626 212 synthidx[i]=0; //Set sample index to 0
djbottrill 19:4cec60669626 213 synthtab[i]=255; //Set to invalid
djbottrill 17:7f27f4921305 214 }
djbottrill 17:7f27f4921305 215 break ;
djbottrill 17:7f27f4921305 216 }
djbottrill 17:7f27f4921305 217
djbottrill 17:7f27f4921305 218 //get sample and add to Audio Accumulator
djbottrill 19:4cec60669626 219 synth_old[i]=sample2[synthoctave[i]][(int)(synth[i])]; //Get and save old sample
djbottrill 19:4cec60669626 220 audio_out=audio_out+synth_old[i]; //add sample to audio out accumulator
djbottrill 19:4cec60669626 221 synth[i]=synth[i]+synthidx[i]; //Get next sample pointer
djbottrill 17:7f27f4921305 222
djbottrill 19:4cec60669626 223 } //Next Note
djbottrill 17:7f27f4921305 224 }
djbottrill 17:7f27f4921305 225
djbottrill 8:df5f305aab22 226
djbottrill 0:4d06e0867376 227 //Output to DAC
djbottrill 0:4d06e0867376 228 Aout.write_u16(audio_out*16);
djbottrill 7:e1ea1623c6c2 229
djbottrill 15:c1854904f0d7 230 // redled=1;
djbottrill 15:c1854904f0d7 231 // diag=0;
djbottrill 0:4d06e0867376 232 }
djbottrill 0:4d06e0867376 233
djbottrill 0:4d06e0867376 234 /*
djbottrill 30:f7aa90a1e443 235 Interrupt routine to receive MIDI on/off message
djbottrill 30:f7aa90a1e443 236 MIDI note on/off events are stored in the note status buffer keytab.
djbottrill 30:f7aa90a1e443 237 the lower 5 bits of keytab represent a note being on or off
djbottrill 30:f7aa90a1e443 238 Bit 0 = 16'
djbottrill 30:f7aa90a1e443 239 Bit 1 = 8'
djbottrill 30:f7aa90a1e443 240 Bit 2 = 4'
djbottrill 30:f7aa90a1e443 241 Bit 3 = 2 2/3' (12th)
djbottrill 30:f7aa90a1e443 242 Bit 4 = 2' (15th)
djbottrill 30:f7aa90a1e443 243 Thus if keytab >0 then the note should be played
djbottrill 30:f7aa90a1e443 244 Currently MIDI note on/off messages are accepted on any channel
djbottrill 0:4d06e0867376 245 */
djbottrill 0:4d06e0867376 246 void get_message(MIDIMessage msg)
djbottrill 0:4d06e0867376 247 {
djbottrill 0:4d06e0867376 248 greenled=0; //Pulse Green LED to indicate MIDI activity
djbottrill 0:4d06e0867376 249 key=msg.key();
djbottrill 0:4d06e0867376 250 velocity=msg.velocity();
djbottrill 0:4d06e0867376 251 chan=msg.channel();
djbottrill 0:4d06e0867376 252 switch (msg.type()) {
djbottrill 0:4d06e0867376 253 case MIDIMessage::NoteOnType: //MIDI note on received
djbottrill 21:04febed27b55 254 if (key >23 & key<120) {
djbottrill 0:4d06e0867376 255 onoff=1;
djbottrill 23:31cb90fa661f 256 if (sw_status[0]==1 & key >35) {
djbottrill 13:decb94698003 257 keybuf[(key-36)]|= 1 << 0; //Store @ 16' pitch
djbottrill 12:74b52900cddb 258 }
djbottrill 23:31cb90fa661f 259 if (sw_status[1]==1) {
djbottrill 13:decb94698003 260 keybuf[(key-24)]|= 1 << 1; //Store @ 8' pitch
djbottrill 15:c1854904f0d7 261 }
djbottrill 23:31cb90fa661f 262 if (sw_status[2]==1& key<108) {
djbottrill 13:decb94698003 263 keybuf[(key)-12]|= 1 << 2; //Store @ 4' pitch
djbottrill 15:c1854904f0d7 264 }
djbottrill 23:31cb90fa661f 265 if (sw_status[3]==1 & key<101) {
djbottrill 13:decb94698003 266 keybuf[(key)-5]|= 1 << 3; //Store @ 2 2/3' pitch
djbottrill 15:c1854904f0d7 267 }
djbottrill 23:31cb90fa661f 268 if (sw_status[4]==1 & key <96) {
djbottrill 13:decb94698003 269 keybuf[(key)]|= 1 << 4; //Store @ 2' pitch
djbottrill 15:c1854904f0d7 270 }
djbottrill 0:4d06e0867376 271 }
djbottrill 6:073e10217962 272
djbottrill 0:4d06e0867376 273 break;
djbottrill 0:4d06e0867376 274
djbottrill 0:4d06e0867376 275 //Process keys off
djbottrill 0:4d06e0867376 276 case MIDIMessage::NoteOffType: //Midi note off received
djbottrill 21:04febed27b55 277 if (key >23 & key<120) {
djbottrill 0:4d06e0867376 278 onoff=0;
djbottrill 21:04febed27b55 279 if (key>35) {
djbottrill 21:04febed27b55 280 keybuf[(key-36)]&= ~(1 << 0); //Kill note @ 16' pitch
djbottrill 21:04febed27b55 281 }
djbottrill 15:c1854904f0d7 282 keybuf[(key-24)]&= ~(1 << 1); //Kill note @ 8' pitch
djbottrill 22:7d4e07edf503 283 if (key<108) {
djbottrill 21:04febed27b55 284 keybuf[(key-12)]&= ~(1 << 2); //Kill note @ 4' pitch
djbottrill 21:04febed27b55 285 }
djbottrill 21:04febed27b55 286 if (key<101) {
djbottrill 21:04febed27b55 287 keybuf[(key-5)]&= ~(1 << 3); //Kill note @ 2 2/3' pitch
djbottrill 21:04febed27b55 288 }
djbottrill 21:04febed27b55 289 if (key<96) {
djbottrill 21:04febed27b55 290 keybuf[(key)]&= ~(1 << 4); //Kill note @ 2' pitch
djbottrill 21:04febed27b55 291 }
djbottrill 0:4d06e0867376 292 }
djbottrill 0:4d06e0867376 293 break;
djbottrill 0:4d06e0867376 294
djbottrill 0:4d06e0867376 295 //Process all notes off command
djbottrill 0:4d06e0867376 296 case MIDIMessage::AllNotesOffType: //Midi all notes off
djbottrill 11:a27a71f7c149 297 for (int it=0; it<108; it++) {
djbottrill 11:a27a71f7c149 298 keybuf[it]=0; //Clear Keybuf
djbottrill 0:4d06e0867376 299 }
djbottrill 0:4d06e0867376 300 break;
djbottrill 4:9f63e68b548e 301
djbottrill 0:4d06e0867376 302 //Any other MIDI Commands just ignore
djbottrill 0:4d06e0867376 303 default:
djbottrill 0:4d06e0867376 304 break;
djbottrill 0:4d06e0867376 305 }
djbottrill 0:4d06e0867376 306 greenled=1;
djbottrill 0:4d06e0867376 307 }
djbottrill 0:4d06e0867376 308
djbottrill 0:4d06e0867376 309
djbottrill 0:4d06e0867376 310 int main()
djbottrill 0:4d06e0867376 311 {
djbottrill 0:4d06e0867376 312 greenled=1;
djbottrill 0:4d06e0867376 313 redled=1;
djbottrill 0:4d06e0867376 314 blueled=1;
djbottrill 0:4d06e0867376 315 SRCK=0; //Serial Clock low
djbottrill 0:4d06e0867376 316 RCK=0; //Latch Clock low
djbottrill 0:4d06e0867376 317
djbottrill 0:4d06e0867376 318 sw1.mode(PullUp);
djbottrill 0:4d06e0867376 319 sw3.mode(PullUp);
djbottrill 15:c1854904f0d7 320 p1.mode(PullUp);
djbottrill 15:c1854904f0d7 321 p2.mode(PullUp);
djbottrill 15:c1854904f0d7 322 p3.mode(PullUp);
djbottrill 15:c1854904f0d7 323 p4.mode(PullUp);
djbottrill 15:c1854904f0d7 324 p5.mode(PullUp);
djbottrill 15:c1854904f0d7 325
djbottrill 28:753d70280c19 326 output_ticker.attach_us(&aout, sample_rate); //Start the ticker
djbottrill 0:4d06e0867376 327
djbottrill 0:4d06e0867376 328 lcd.cls();
djbottrill 0:4d06e0867376 329 wait(0.1);
djbottrill 0:4d06e0867376 330 lcd.setCursor(TextLCD::CurOff_BlkOff);
djbottrill 0:4d06e0867376 331 lcd.cls();
djbottrill 0:4d06e0867376 332 lcd.printf("MIDI Pipe Organ Waiting for USB");
djbottrill 30:f7aa90a1e443 333 /*
djbottrill 30:f7aa90a1e443 334 I couldn't figure out which interrupt is used for the ticker so I lowered the USB interrupt priority so that it didn't
djbottrill 30:f7aa90a1e443 335 interfere with the smooth operation of the sound generation ticker
djbottrill 30:f7aa90a1e443 336 */
djbottrill 0:4d06e0867376 337 NVIC_SetPriority(USB0_IRQn, 99); //Reduce Interrupt priority of USB
djbottrill 0:4d06e0867376 338
djbottrill 0:4d06e0867376 339 USBMIDI midi; //Start up MIDI
djbottrill 0:4d06e0867376 340 midi.attach(get_message); //callback for MIDI messages received
djbottrill 0:4d06e0867376 341
djbottrill 0:4d06e0867376 342 lcd.cls();
djbottrill 0:4d06e0867376 343 lcd.printf("MIDI Pipe Organ");
djbottrill 0:4d06e0867376 344 wait(1);
djbottrill 0:4d06e0867376 345 lcd.cls();
djbottrill 0:4d06e0867376 346 lcd.printf("On Chan Note Vel");
djbottrill 0:4d06e0867376 347 key=0;
djbottrill 0:4d06e0867376 348 velocity=0;
djbottrill 0:4d06e0867376 349 chan=0;
djbottrill 0:4d06e0867376 350 onoff=0;
djbottrill 0:4d06e0867376 351
djbottrill 0:4d06e0867376 352 //Main Loop
djbottrill 0:4d06e0867376 353 while(1) {
djbottrill 0:4d06e0867376 354
djbottrill 28:753d70280c19 355
djbottrill 11:a27a71f7c149 356 //Process notes off
djbottrill 30:f7aa90a1e443 357 for (ii=0; ii<16; ii++) { //Scan through 16 channels
djbottrill 30:f7aa90a1e443 358 if (synthstat[ii]==1 & keybuf[synthtab[ii]]==0) { //Note currently playing but should be off
djbottrill 30:f7aa90a1e443 359 synthstat[ii]=2; //Set Start release
djbottrill 11:a27a71f7c149 360 }
djbottrill 11:a27a71f7c149 361 }
djbottrill 11:a27a71f7c149 362 //Process keys on
djbottrill 11:a27a71f7c149 363 //Find a free note generator and start the note playing, if no slots available just ignore the note
djbottrill 12:74b52900cddb 364 for (keyidx=95; keyidx>=0; keyidx--) {
djbottrill 15:c1854904f0d7 365 if (keybuf[keyidx]>0 & oldkeybuf[keyidx]==0) { //Key is pressed
djbottrill 12:74b52900cddb 366 //Find and use any channel that is free
djbottrill 12:74b52900cddb 367 sucess=0;
djbottrill 11:a27a71f7c149 368 ii=0;
djbottrill 11:a27a71f7c149 369 while (ii<16) { //Find available synth channel
djbottrill 11:a27a71f7c149 370 if (synthstat[ii]==0) { //Is synth channel free?
djbottrill 11:a27a71f7c149 371 synthtab[ii]=keyidx; //Store note value
djbottrill 11:a27a71f7c149 372 synthoctave[ii]=synthtab[ii]/12; //Store the octave
djbottrill 16:d2694fb530c3 373 //Uncomment the following lines if you want to wrap around the top octave
djbottrill 16:d2694fb530c3 374 // if (synthoctave[ii]==7) { //Wrap around the top octave
djbottrill 15:c1854904f0d7 375 // synthoctave[ii]--;
djbottrill 15:c1854904f0d7 376 // }
djbottrill 11:a27a71f7c149 377 synthnote[ii]= synthtab[ii]%12; //Note within the octave
djbottrill 11:a27a71f7c149 378 synthstat[ii]=1; //Set status to playing
djbottrill 27:98dad49081ff 379 synthidx[ii]=freqtab[synthnote[ii]]*freqfine; //Set the frequency
djbottrill 12:74b52900cddb 380 sucess=1;
djbottrill 11:a27a71f7c149 381 ii=16; //exit loop
djbottrill 11:a27a71f7c149 382 } //Next Synth slot
djbottrill 11:a27a71f7c149 383 ii++;
djbottrill 11:a27a71f7c149 384 }
djbottrill 28:753d70280c19 385 //As a last resort find any channel that is in release
djbottrill 12:74b52900cddb 386 if (sucess==0) {
djbottrill 12:74b52900cddb 387 ii=0;
djbottrill 15:c1854904f0d7 388 while (ii<16) { //Find available synth channel
djbottrill 26:7b9267a5b3c3 389 if (synthstat[ii]==3) { //Is synth channel free?
djbottrill 15:c1854904f0d7 390 synthtab[ii]=keyidx; //Store note value
djbottrill 15:c1854904f0d7 391 synthoctave[ii]=synthtab[ii]/12; //Store the octave
djbottrill 15:c1854904f0d7 392 synthnote[ii]= synthtab[ii]%12; //Note within the octave
djbottrill 15:c1854904f0d7 393 synthstat[ii]=1; //Set status to playing
djbottrill 27:98dad49081ff 394 synthidx[ii]=freqtab[synthnote[ii]]*freqfine; //Set the frequency
djbottrill 12:74b52900cddb 395 sucess=1;
djbottrill 15:c1854904f0d7 396 ii=16; //exit loop
djbottrill 15:c1854904f0d7 397 } //Next Synth slot
djbottrill 12:74b52900cddb 398 ii++;
djbottrill 12:74b52900cddb 399 }
djbottrill 12:74b52900cddb 400 }
djbottrill 11:a27a71f7c149 401 }
djbottrill 12:74b52900cddb 402 if (sucess==1) {
djbottrill 16:d2694fb530c3 403 oldkeybuf[keyidx]=keybuf[keyidx]; //Store old value if note sucessfull
djbottrill 30:f7aa90a1e443 404 } //If not sucessfull try on the next scan
djbottrill 11:a27a71f7c149 405 }
djbottrill 15:c1854904f0d7 406
djbottrill 15:c1854904f0d7 407
djbottrill 30:f7aa90a1e443 408 //Output to Shift register pallet magnet driver board
djbottrill 15:c1854904f0d7 409 for (keyidx=107; keyidx>11; keyidx--) {
djbottrill 15:c1854904f0d7 410 if (keybuf[keyidx]>0) {
djbottrill 15:c1854904f0d7 411 SER1=1;
djbottrill 15:c1854904f0d7 412 } else {
djbottrill 15:c1854904f0d7 413 SER1=0;
djbottrill 15:c1854904f0d7 414 }
djbottrill 15:c1854904f0d7 415 SRCK=1; //Pulse Serial clock
djbottrill 15:c1854904f0d7 416 wait_us(4);
djbottrill 15:c1854904f0d7 417 SRCK=0;
djbottrill 15:c1854904f0d7 418 wait_us(4);
djbottrill 15:c1854904f0d7 419 } //Next bit
djbottrill 15:c1854904f0d7 420
djbottrill 15:c1854904f0d7 421 RCK=1; //Transfer data to outputs
djbottrill 15:c1854904f0d7 422 wait_us(4);
djbottrill 15:c1854904f0d7 423 RCK=0;
djbottrill 15:c1854904f0d7 424 wait_us(4);
djbottrill 15:c1854904f0d7 425
djbottrill 28:753d70280c19 426 //Read Stop inputs and onboard switches
djbottrill 23:31cb90fa661f 427 sw[0]=p1;
djbottrill 23:31cb90fa661f 428 sw[1]=p2;
djbottrill 23:31cb90fa661f 429 sw[2]=p3;
djbottrill 23:31cb90fa661f 430 sw[3]=p4;
djbottrill 23:31cb90fa661f 431 sw[4]=p5;
djbottrill 23:31cb90fa661f 432 sw[6]=sw1;
djbottrill 23:31cb90fa661f 433 sw[7]=sw3;
djbottrill 30:f7aa90a1e443 434 /*
djbottrill 30:f7aa90a1e443 435 code to de-bounce the K64F onboard and external switches using multiple loops to de-bounce; has 3 states:
djbottrill 30:f7aa90a1e443 436 0 - Button not pressed
djbottrill 30:f7aa90a1e443 437 1 - Button pressed waiting for de-bounce count of 5 loops
djbottrill 30:f7aa90a1e443 438 2 - Button press stable, this status can be read as the de-bounced status indicating the button press is clean
djbottrill 30:f7aa90a1e443 439 sw_status is toggled by each sucessive key press 0 / 1
djbottrill 30:f7aa90a1e443 440 */
djbottrill 23:31cb90fa661f 441 pressed=0;
djbottrill 28:753d70280c19 442 for (swi=0; swi<8; swi++) { //Process 8 push switches
djbottrill 23:31cb90fa661f 443 if (sw_phase[swi]==0 & sw[swi]==0) { //Button just been pressed
djbottrill 23:31cb90fa661f 444 sw_phase[swi]=1;
djbottrill 26:7b9267a5b3c3 445 sw_count[swi]=5;
djbottrill 23:31cb90fa661f 446 }
djbottrill 23:31cb90fa661f 447 if (sw_phase[swi]==1 & sw_count[swi]==0 & sw[swi]==0) { //Button still pressed after de-bounce period
djbottrill 23:31cb90fa661f 448 sw_phase[swi]=2;
djbottrill 23:31cb90fa661f 449 pressed++; //Inc button pressed count
djbottrill 23:31cb90fa661f 450 sw_status[swi]=!sw_status[swi]; //Toggle switch status
djbottrill 23:31cb90fa661f 451 }
djbottrill 23:31cb90fa661f 452 if (sw_phase[swi]==1 & sw_count[swi]==0 & sw[swi]==1) { //Button no longer pressed after de-bounce period
djbottrill 23:31cb90fa661f 453 sw_phase[swi]=0;
djbottrill 23:31cb90fa661f 454 }
djbottrill 23:31cb90fa661f 455 if (sw_phase[swi]==2 & sw[swi]==1) { //Button released
djbottrill 23:31cb90fa661f 456 sw_phase[swi]=0;
djbottrill 23:31cb90fa661f 457 }
djbottrill 23:31cb90fa661f 458 sw_count[swi]--;
djbottrill 6:073e10217962 459 }
djbottrill 23:31cb90fa661f 460 //light blue LED if any button presed
djbottrill 23:31cb90fa661f 461 if (pressed>0) {
djbottrill 0:4d06e0867376 462 blueled=0;
djbottrill 0:4d06e0867376 463 } else {
djbottrill 0:4d06e0867376 464 blueled=1;
djbottrill 0:4d06e0867376 465 }
djbottrill 0:4d06e0867376 466
djbottrill 0:4d06e0867376 467
djbottrill 17:7f27f4921305 468 //Button 1 will clear all playing notes & switch sampleset
djbottrill 23:31cb90fa661f 469 if (sw_status[6] != sw_old[6]) {
djbottrill 9:b0f110c02b1b 470 for (cl=0; cl<108; cl++) {
djbottrill 17:7f27f4921305 471 keybuf[cl]=0; //Clear Keybuf
djbottrill 17:7f27f4921305 472 }
djbottrill 23:31cb90fa661f 473 sampleset=sw_status[6];
djbottrill 17:7f27f4921305 474 oldstops=255; //Force a display refresh
djbottrill 23:31cb90fa661f 475 sw_old[6]=sw_status[6];
djbottrill 9:b0f110c02b1b 476 }
djbottrill 22:7d4e07edf503 477
djbottrill 21:04febed27b55 478
djbottrill 0:4d06e0867376 479 //Check for display mode button being presed
djbottrill 23:31cb90fa661f 480 if (sw_status[7] != sw_old[7]) { //Mode Switch pressed
djbottrill 0:4d06e0867376 481 lcdmode++;
djbottrill 16:d2694fb530c3 482 if (lcdmode>4) {
djbottrill 0:4d06e0867376 483 lcdmode=0;
djbottrill 0:4d06e0867376 484 }
djbottrill 0:4d06e0867376 485 lcd.cls();
djbottrill 0:4d06e0867376 486 if (lcdmode==0) {
djbottrill 0:4d06e0867376 487 lcd.printf("On Chan Note Vel");
djbottrill 0:4d06e0867376 488 }
djbottrill 0:4d06e0867376 489 if (lcdmode==1) {
djbottrill 28:753d70280c19 490 //Initialise bar graph display
djbottrill 28:753d70280c19 491 //Program user defined characters into OLED display for bar graph
djbottrill 10:fa2dee836ceb 492 lcd.setUDC(0, (char *) udc0);
djbottrill 10:fa2dee836ceb 493 lcd.setUDC(1, (char *) udc1);
djbottrill 10:fa2dee836ceb 494 lcd.setUDC(2, (char *) udc2);
djbottrill 10:fa2dee836ceb 495 lcd.setUDC(3, (char *) udc3);
djbottrill 10:fa2dee836ceb 496 lcd.setUDC(4, (char *) udc4);
djbottrill 10:fa2dee836ceb 497 lcd.setUDC(5, (char *) udc5);
djbottrill 10:fa2dee836ceb 498 lcd.setUDC(6, (char *) udc6);
djbottrill 10:fa2dee836ceb 499 lcd.setUDC(7, (char *) udc7);
djbottrill 0:4d06e0867376 500 for (row=0; row<2; row++) {
djbottrill 0:4d06e0867376 501 for (pos=0; pos<16; pos++) {
djbottrill 0:4d06e0867376 502 display[row][pos]=0;
djbottrill 0:4d06e0867376 503 display_old[row][pos]=1;
djbottrill 0:4d06e0867376 504 }
djbottrill 0:4d06e0867376 505 }
djbottrill 0:4d06e0867376 506 }
djbottrill 0:4d06e0867376 507 if (lcdmode==2) {
djbottrill 28:753d70280c19 508 //Initilise synth channel status display
djbottrill 0:4d06e0867376 509 lcd.locate(0,1);
djbottrill 0:4d06e0867376 510 lcd.printf("0123456789ABCDEF");
djbottrill 0:4d06e0867376 511 }
djbottrill 28:753d70280c19 512 //Initialise synth channel unilisation
djbottrill 8:df5f305aab22 513 if (lcdmode==3) {
djbottrill 8:df5f305aab22 514 lcd.cls();
djbottrill 8:df5f305aab22 515 lcd.locate(0,0);
djbottrill 8:df5f305aab22 516 lcd.printf("Utilisation:");
djbottrill 28:753d70280c19 517 }
djbottrill 16:d2694fb530c3 518 if (lcdmode==4) {
djbottrill 28:753d70280c19 519 //Initialise Stops selection display
djbottrill 16:d2694fb530c3 520 oldstops=255; //Force a refresh
djbottrill 16:d2694fb530c3 521 }
djbottrill 23:31cb90fa661f 522 sw_old[7]=sw_status[7];
djbottrill 0:4d06e0867376 523 }
djbottrill 22:7d4e07edf503 524
djbottrill 0:4d06e0867376 525
djbottrill 0:4d06e0867376 526
djbottrill 0:4d06e0867376 527
djbottrill 0:4d06e0867376 528 // OLED MIDI Status display
djbottrill 0:4d06e0867376 529 if (lcdmode==0) {
djbottrill 0:4d06e0867376 530 lcd_stat=key+(128*velocity)+(16384*chan)+(262144*onoff);
djbottrill 0:4d06e0867376 531 if (lcd_stat!=lcd_stat_old) {
djbottrill 0:4d06e0867376 532
djbottrill 0:4d06e0867376 533 lcd.locate(0,1);
djbottrill 0:4d06e0867376 534 lcd.printf("%1d %2d %3d %3d", onoff, chan, key, velocity);
djbottrill 0:4d06e0867376 535 lcd_stat_old=lcd_stat;
djbottrill 0:4d06e0867376 536 }
djbottrill 0:4d06e0867376 537 }
djbottrill 0:4d06e0867376 538
djbottrill 0:4d06e0867376 539 // OLED MIDI Bar Display
djbottrill 0:4d06e0867376 540 if (lcdmode==1) {
djbottrill 0:4d06e0867376 541 keyidx=0;
djbottrill 0:4d06e0867376 542 for (row=1; row>=0; row--) {
djbottrill 0:4d06e0867376 543 for (pos=0; pos<16; pos++) {
djbottrill 0:4d06e0867376 544 keyidx_t=keyidx*2;
djbottrill 0:4d06e0867376 545 if(keyidx_t>94) {
djbottrill 0:4d06e0867376 546 keyidx_t=keyidx_t-95;
djbottrill 0:4d06e0867376 547 }
djbottrill 15:c1854904f0d7 548 tval=keybuf[keyidx_t];
djbottrill 12:74b52900cddb 549 if(tval>0) {
djbottrill 12:74b52900cddb 550 tval=1;
djbottrill 12:74b52900cddb 551 }
djbottrill 0:4d06e0867376 552 keyidx++;
djbottrill 0:4d06e0867376 553 keyidx_t=keyidx*2;
djbottrill 0:4d06e0867376 554 if(keyidx_t>94) {
djbottrill 0:4d06e0867376 555 keyidx_t=keyidx_t-95;
djbottrill 0:4d06e0867376 556 }
djbottrill 15:c1854904f0d7 557 tval1=keybuf[keyidx_t];
djbottrill 12:74b52900cddb 558 if (tval1>0) {
djbottrill 12:74b52900cddb 559 tval1=1;
djbottrill 12:74b52900cddb 560 }
djbottrill 12:74b52900cddb 561 tval=tval+(2*tval1);
djbottrill 0:4d06e0867376 562 keyidx++;
djbottrill 0:4d06e0867376 563
djbottrill 0:4d06e0867376 564 keyidx_t=keyidx*2;
djbottrill 0:4d06e0867376 565 if(keyidx_t>94) {
djbottrill 0:4d06e0867376 566 keyidx_t=keyidx_t-95;
djbottrill 0:4d06e0867376 567 }
djbottrill 15:c1854904f0d7 568 tval1=keybuf[keyidx_t];
djbottrill 12:74b52900cddb 569 if (tval1>0) {
djbottrill 12:74b52900cddb 570 tval1=1;
djbottrill 12:74b52900cddb 571 }
djbottrill 12:74b52900cddb 572 tval=tval+(4*tval1);
djbottrill 0:4d06e0867376 573 keyidx++;
djbottrill 0:4d06e0867376 574 display[row][pos]=tval;
djbottrill 0:4d06e0867376 575
djbottrill 0:4d06e0867376 576 if(display[row][pos]!=display_old[row][pos]) {
djbottrill 0:4d06e0867376 577 lcd.locate(pos,row);
djbottrill 0:4d06e0867376 578 lcd.putc(display[row][pos]);
djbottrill 0:4d06e0867376 579 display_old[row][pos]=display[row][pos];
djbottrill 0:4d06e0867376 580 }
djbottrill 0:4d06e0867376 581 }
djbottrill 0:4d06e0867376 582 }
djbottrill 0:4d06e0867376 583 }
djbottrill 0:4d06e0867376 584
djbottrill 0:4d06e0867376 585 //Display status of the Synth channels
djbottrill 0:4d06e0867376 586 if (lcdmode==2) {
djbottrill 0:4d06e0867376 587 lcd.locate(0,0);
djbottrill 0:4d06e0867376 588 for (noteidx=0; noteidx<16; noteidx++) {
djbottrill 0:4d06e0867376 589 lcd.putc((synthstat[noteidx]+48));
djbottrill 0:4d06e0867376 590 }
djbottrill 0:4d06e0867376 591 }
djbottrill 4:9f63e68b548e 592
djbottrill 8:df5f305aab22 593 //Display utilisation bar graph
djbottrill 8:df5f305aab22 594 if (lcdmode==3) {
djbottrill 8:df5f305aab22 595 x=0;
djbottrill 8:df5f305aab22 596 for (noteidx=0; noteidx<16; noteidx++) {
djbottrill 8:df5f305aab22 597 if (synthstat[noteidx] >0) {
djbottrill 8:df5f305aab22 598 x++;
djbottrill 8:df5f305aab22 599 }
djbottrill 8:df5f305aab22 600 }
djbottrill 8:df5f305aab22 601 for (pos=0; pos<x; pos++) {
djbottrill 8:df5f305aab22 602 display[1][pos]=0xff;
djbottrill 8:df5f305aab22 603 }
djbottrill 8:df5f305aab22 604 while(pos<16) {
djbottrill 8:df5f305aab22 605 display[1][pos]=0x20;
djbottrill 8:df5f305aab22 606 pos++;
djbottrill 8:df5f305aab22 607 }
djbottrill 8:df5f305aab22 608 row=1;
djbottrill 8:df5f305aab22 609 for (pos=0; pos<16; pos++) {
djbottrill 8:df5f305aab22 610 if (x!=x1) {
djbottrill 8:df5f305aab22 611 lcd.locate(13,0);
djbottrill 8:df5f305aab22 612 lcd.printf("%2d", x);
djbottrill 8:df5f305aab22 613 x1=x;
djbottrill 8:df5f305aab22 614 }
djbottrill 8:df5f305aab22 615 if(display[row][pos]!=display_old[row][pos]) {
djbottrill 8:df5f305aab22 616 lcd.locate(pos,row);
djbottrill 8:df5f305aab22 617 lcd.putc(display[row][pos]);
djbottrill 8:df5f305aab22 618 display_old[row][pos]=display[row][pos];
djbottrill 8:df5f305aab22 619 }
djbottrill 8:df5f305aab22 620 }
djbottrill 8:df5f305aab22 621 }
djbottrill 16:d2694fb530c3 622 //Stop display
djbottrill 16:d2694fb530c3 623 if (lcdmode==4) {
djbottrill 23:31cb90fa661f 624 pos=sw_status[0] + sw_status[1]+sw_status[2]+sw_status[3]+sw_status[4];
djbottrill 16:d2694fb530c3 625 if (oldstops != pos) {
djbottrill 17:7f27f4921305 626 oldstops=pos;
djbottrill 16:d2694fb530c3 627 lcd.cls();
djbottrill 16:d2694fb530c3 628 for (pos=0; pos<16; pos++) {
djbottrill 16:d2694fb530c3 629 lcd.locate(pos,0);
djbottrill 17:7f27f4921305 630 if (sampleset==0) {
djbottrill 17:7f27f4921305 631 lcd.putc(stopname1[pos]);
djbottrill 17:7f27f4921305 632 } else {
djbottrill 17:7f27f4921305 633 lcd.putc(stopname2[pos]);
djbottrill 17:7f27f4921305 634 }
djbottrill 16:d2694fb530c3 635 }
djbottrill 16:d2694fb530c3 636 lcd.locate(0,1);
djbottrill 23:31cb90fa661f 637 if (sw_status[0]==1) {
djbottrill 16:d2694fb530c3 638 lcd.printf("16 ");
djbottrill 16:d2694fb530c3 639 }
djbottrill 16:d2694fb530c3 640
djbottrill 23:31cb90fa661f 641 if (sw_status[1]==1) {
djbottrill 16:d2694fb530c3 642 lcd.printf("8 ");
djbottrill 16:d2694fb530c3 643 }
djbottrill 16:d2694fb530c3 644
djbottrill 23:31cb90fa661f 645 if (sw_status[2]==1) {
djbottrill 16:d2694fb530c3 646 lcd.printf("4 ");
djbottrill 16:d2694fb530c3 647 }
djbottrill 16:d2694fb530c3 648
djbottrill 23:31cb90fa661f 649 if (sw_status[3]==1) {
djbottrill 16:d2694fb530c3 650 lcd.printf("2-2/3 ");
djbottrill 16:d2694fb530c3 651 }
djbottrill 16:d2694fb530c3 652
djbottrill 23:31cb90fa661f 653 if (sw_status[4]==1) {
djbottrill 16:d2694fb530c3 654 lcd.printf("2");
djbottrill 16:d2694fb530c3 655 }
djbottrill 16:d2694fb530c3 656 }
djbottrill 16:d2694fb530c3 657 }
djbottrill 8:df5f305aab22 658
djbottrill 0:4d06e0867376 659 } //End of main loop
djbottrill 0:4d06e0867376 660 } //End of program
djbottrill 0:4d06e0867376 661
djbottrill 0:4d06e0867376 662
djbottrill 0:4d06e0867376 663
djbottrill 0:4d06e0867376 664