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 21:54:14 2015 +0000
Revision:
16:d2694fb530c3
Parent:
15:c1854904f0d7
Child:
17:7f27f4921305
added a new Montre sample

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