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
main.cpp@30:f7aa90a1e443, 2015-11-20 (annotated)
- 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?
User | Revision | Line number | New 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 |