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:
Thu Nov 12 23:46:17 2015 +0000
Revision:
18:472954b6b711
Parent:
17:7f27f4921305
Child:
19:4cec60669626
This version has two switchable samples: Bourdon and Montre; Need to re-sample the Montre with a bit more decay.

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