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:
Tue Nov 10 15:50:18 2015 +0000
Revision:
15:c1854904f0d7
Parent:
13:decb94698003
Child:
16:d2694fb530c3
Added a new Bourdon sample at 44.1Khz, removed diagnostic LED and scope outputs from the Ticker routine and moved the serial output to the main loop to reduced the execution time of the ticker.

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 9:b0f110c02b1b 4 The program uses the DAC to generate 16 sampled audio channel outputs at up to 32Khz 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 15:c1854904f0d7 15 //#include "Bourdon_32.h" //This is the best sample 32Khz
djbottrill 15:c1854904f0d7 16 #include "Bourdon_44.h"
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 0:4d06e0867376 62 int keyidx=0; //Key index //Polyphony counter
djbottrill 15:c1854904f0d7 63 //int outidx=96; //Serial output 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 0:4d06e0867376 102
djbottrill 0:4d06e0867376 103 //Sound generator variables
djbottrill 0:4d06e0867376 104 int tempidx=0;
djbottrill 0:4d06e0867376 105 int freqidx=45;
djbottrill 0:4d06e0867376 106 float synth[16];
djbottrill 0:4d06e0867376 107 float synthidx[16];
djbottrill 0:4d06e0867376 108 int synth_old[16];
djbottrill 0:4d06e0867376 109 int synthtab[16]= {};
djbottrill 0:4d06e0867376 110 int synthstat[16]= {};
djbottrill 4:9f63e68b548e 111 unsigned char synthoctave[16]= {};
djbottrill 4:9f63e68b548e 112 unsigned char synthnote[16]= {};
djbottrill 12:74b52900cddb 113 int sucess=0;
djbottrill 0:4d06e0867376 114 int noteidx=0;
djbottrill 0:4d06e0867376 115 int i;
djbottrill 0:4d06e0867376 116 int ii;
djbottrill 9:b0f110c02b1b 117 int cl;
djbottrill 0:4d06e0867376 118
djbottrill 0:4d06e0867376 119 /*
djbottrill 0:4d06e0867376 120 Ticker routine to calculate and output the audio signal.
djbottrill 0:4d06e0867376 121 As the DAC is 12 bit this allows for 16 concurrennt 8 bit samples running with no additional loss of precision.
djbottrill 0:4d06e0867376 122 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 123 Sound Generation is in 4 states stored in synthstat:
djbottrill 0:4d06e0867376 124 0 = Synth Channel idle
djbottrill 0:4d06e0867376 125 1 = Attack / Sustain phase note running and looping if necessary
djbottrill 5:13a1e5e4494d 126 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 127 3 = Sample is in the decay phase.
djbottrill 0:4d06e0867376 128
djbottrill 5:13a1e5e4494d 129 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 130 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 131 All 96 bits are clocked out in around 4.4mS.
djbottrill 0:4d06e0867376 132 */
djbottrill 0:4d06e0867376 133 void aout()
djbottrill 0:4d06e0867376 134 {
djbottrill 15:c1854904f0d7 135 // diag=1; //Pulse DIAG Pin for Scoping purposes IE pin high
djbottrill 15:c1854904f0d7 136 // redled=0; //Pulse Red LED to indicate Ticker working
djbottrill 0:4d06e0867376 137 audio_out=0; //Clear Audio Accumulator
djbottrill 0:4d06e0867376 138
djbottrill 0:4d06e0867376 139 for (i =0; i<16; i++) { //Do 16 channels
djbottrill 4:9f63e68b548e 140 switch (synthstat[i]) {
djbottrill 4:9f63e68b548e 141 case 1: //Sustain phase
djbottrill 4:9f63e68b548e 142 if (synth[i]>sample_loop_end[synthoctave[i]]) { //Got to end of buffer?
djbottrill 4:9f63e68b548e 143 synth[i]=sample_loop_start[synthoctave[i]]; //Wrap around back to start
djbottrill 4:9f63e68b548e 144 }
djbottrill 4:9f63e68b548e 145 break;
djbottrill 5:13a1e5e4494d 146 case 2: //Note off demand state
djbottrill 0:4d06e0867376 147 if (synth[i]>=sample_attack[synthoctave[i]]) { //Delay decay phase if not past end of attack
djbottrill 0:4d06e0867376 148 //Check if the waveform is close to zero crossing this helps eliminate clicks looks for rising edge approaching 0x80
djbottrill 0:4d06e0867376 149 tempidx=synth[i];
djbottrill 5:13a1e5e4494d 150 if (sample[synthoctave[i]][tempidx]<128 & sample[synthoctave[i]][tempidx]>120) {
djbottrill 0:4d06e0867376 151 if (sample[synthoctave[i]][tempidx]>synth_old[i]) {
djbottrill 7:e1ea1623c6c2 152 synth[i]=sample_loop_off[synthoctave[i]]; //Jump to start of decay
djbottrill 7:e1ea1623c6c2 153 synthstat[i]=3; //Say note in decay
djbottrill 0:4d06e0867376 154 }
djbottrill 0:4d06e0867376 155 }
djbottrill 0:4d06e0867376 156 }
djbottrill 4:9f63e68b548e 157 break;
djbottrill 7:e1ea1623c6c2 158 case 3: //Check if decay has completed
djbottrill 8:df5f305aab22 159 if (synth[i]>=sample_len[synthoctave[i]]) { //End of decay?
djbottrill 8:df5f305aab22 160 synthstat[i]=0; //say channel free
djbottrill 8:df5f305aab22 161 synth[i]=0; //Set sample pointer to 0
djbottrill 8:df5f305aab22 162 synthidx[i]=0; //Set sample index to 0
djbottrill 8:df5f305aab22 163 synthtab[i]=255; //Set to invalid
djbottrill 7:e1ea1623c6c2 164 }
djbottrill 7:e1ea1623c6c2 165 break ;
djbottrill 0:4d06e0867376 166 }
djbottrill 4:9f63e68b548e 167
djbottrill 4:9f63e68b548e 168 //get sample and add to Audio Accumulator
djbottrill 8:df5f305aab22 169 synth_old[i]=sample[synthoctave[i]][(int)(synth[i])]; //Get and save old sample
djbottrill 0:4d06e0867376 170 audio_out=audio_out+synth_old[i]; //add sample to audio out accumulator
djbottrill 0:4d06e0867376 171 synth[i]=synth[i]+synthidx[i]; //Get next sample pointer
djbottrill 15:c1854904f0d7 172
djbottrill 0:4d06e0867376 173 } //Next Note
djbottrill 8:df5f305aab22 174
djbottrill 0:4d06e0867376 175 //Output to DAC
djbottrill 0:4d06e0867376 176 Aout.write_u16(audio_out*16);
djbottrill 7:e1ea1623c6c2 177
djbottrill 15:c1854904f0d7 178 // redled=1;
djbottrill 15:c1854904f0d7 179 // diag=0;
djbottrill 0:4d06e0867376 180 }
djbottrill 0:4d06e0867376 181
djbottrill 0:4d06e0867376 182 /*
djbottrill 0:4d06e0867376 183 Interrupt routine to receive MIDI on/off message and set LED status accordingly
djbottrill 0:4d06e0867376 184 MIDI note on/off events directly start/stop the synth channels and store the note status in keytab.
djbottrill 0:4d06e0867376 185 */
djbottrill 0:4d06e0867376 186 void get_message(MIDIMessage msg)
djbottrill 0:4d06e0867376 187 {
djbottrill 0:4d06e0867376 188 greenled=0; //Pulse Green LED to indicate MIDI activity
djbottrill 0:4d06e0867376 189 key=msg.key();
djbottrill 0:4d06e0867376 190 velocity=msg.velocity();
djbottrill 0:4d06e0867376 191 chan=msg.channel();
djbottrill 0:4d06e0867376 192 switch (msg.type()) {
djbottrill 0:4d06e0867376 193 case MIDIMessage::NoteOnType: //MIDI note on received
djbottrill 15:c1854904f0d7 194 if (key >35 & key<97) {
djbottrill 0:4d06e0867376 195 onoff=1;
djbottrill 15:c1854904f0d7 196 if (p1==0) {
djbottrill 13:decb94698003 197 keybuf[(key-36)]|= 1 << 0; //Store @ 16' pitch
djbottrill 12:74b52900cddb 198 }
djbottrill 15:c1854904f0d7 199 if (p2==0) {
djbottrill 13:decb94698003 200 keybuf[(key-24)]|= 1 << 1; //Store @ 8' pitch
djbottrill 15:c1854904f0d7 201 }
djbottrill 15:c1854904f0d7 202 if (p3==0) {
djbottrill 13:decb94698003 203 keybuf[(key)-12]|= 1 << 2; //Store @ 4' pitch
djbottrill 15:c1854904f0d7 204 }
djbottrill 15:c1854904f0d7 205 if (p4==0) {
djbottrill 13:decb94698003 206 keybuf[(key)-5]|= 1 << 3; //Store @ 2 2/3' pitch
djbottrill 15:c1854904f0d7 207 }
djbottrill 15:c1854904f0d7 208 if (p5==0) {
djbottrill 13:decb94698003 209 keybuf[(key)]|= 1 << 4; //Store @ 2' pitch
djbottrill 15:c1854904f0d7 210 }
djbottrill 0:4d06e0867376 211 }
djbottrill 6:073e10217962 212
djbottrill 0:4d06e0867376 213 break;
djbottrill 0:4d06e0867376 214
djbottrill 0:4d06e0867376 215 //Process keys off
djbottrill 0:4d06e0867376 216 case MIDIMessage::NoteOffType: //Midi note off received
djbottrill 15:c1854904f0d7 217 if (key >35 & key<97) {
djbottrill 0:4d06e0867376 218 onoff=0;
djbottrill 15:c1854904f0d7 219 keybuf[(key-36)]&= ~(1 << 0); //Kill note @ 16' pitch
djbottrill 15:c1854904f0d7 220 keybuf[(key-24)]&= ~(1 << 1); //Kill note @ 8' pitch
djbottrill 15:c1854904f0d7 221 keybuf[(key-12)]&= ~(1 << 2); //Kill note @ 4' pitch
djbottrill 15:c1854904f0d7 222 keybuf[(key-5)]&= ~(1 << 3); //Kill note @ 2 2/3' pitch
djbottrill 15:c1854904f0d7 223 keybuf[(key)]&= ~(1 << 4); //Kill note @ 2' pitch
djbottrill 0:4d06e0867376 224 }
djbottrill 0:4d06e0867376 225 break;
djbottrill 0:4d06e0867376 226
djbottrill 0:4d06e0867376 227 //Process all notes off command
djbottrill 0:4d06e0867376 228 case MIDIMessage::AllNotesOffType: //Midi all notes off
djbottrill 11:a27a71f7c149 229 for (int it=0; it<108; it++) {
djbottrill 11:a27a71f7c149 230 keybuf[it]=0; //Clear Keybuf
djbottrill 0:4d06e0867376 231 }
djbottrill 0:4d06e0867376 232 break;
djbottrill 4:9f63e68b548e 233
djbottrill 0:4d06e0867376 234 //Any other MIDI Commands just ignore
djbottrill 0:4d06e0867376 235 default:
djbottrill 0:4d06e0867376 236 break;
djbottrill 0:4d06e0867376 237 }
djbottrill 0:4d06e0867376 238 greenled=1;
djbottrill 0:4d06e0867376 239 }
djbottrill 0:4d06e0867376 240
djbottrill 0:4d06e0867376 241
djbottrill 0:4d06e0867376 242 int main()
djbottrill 0:4d06e0867376 243 {
djbottrill 0:4d06e0867376 244 greenled=1;
djbottrill 0:4d06e0867376 245 redled=1;
djbottrill 0:4d06e0867376 246 blueled=1;
djbottrill 0:4d06e0867376 247 SRCK=0; //Serial Clock low
djbottrill 0:4d06e0867376 248 RCK=0; //Latch Clock low
djbottrill 0:4d06e0867376 249
djbottrill 0:4d06e0867376 250 sw1.mode(PullUp);
djbottrill 0:4d06e0867376 251 sw3.mode(PullUp);
djbottrill 15:c1854904f0d7 252 p1.mode(PullUp);
djbottrill 15:c1854904f0d7 253 p2.mode(PullUp);
djbottrill 15:c1854904f0d7 254 p3.mode(PullUp);
djbottrill 15:c1854904f0d7 255 p4.mode(PullUp);
djbottrill 15:c1854904f0d7 256 p5.mode(PullUp);
djbottrill 15:c1854904f0d7 257
djbottrill 0:4d06e0867376 258 output_ticker.attach(&aout, sample_rate); //Set Sample frequency
djbottrill 0:4d06e0867376 259
djbottrill 0:4d06e0867376 260 lcd.cls();
djbottrill 0:4d06e0867376 261 wait(0.1);
djbottrill 0:4d06e0867376 262 lcd.setCursor(TextLCD::CurOff_BlkOff);
djbottrill 0:4d06e0867376 263 lcd.cls();
djbottrill 0:4d06e0867376 264 lcd.printf("MIDI Pipe Organ Waiting for USB");
djbottrill 0:4d06e0867376 265
djbottrill 0:4d06e0867376 266 NVIC_SetPriority(USB0_IRQn, 99); //Reduce Interrupt priority of USB
djbottrill 0:4d06e0867376 267
djbottrill 0:4d06e0867376 268 USBMIDI midi; //Start up MIDI
djbottrill 0:4d06e0867376 269 midi.attach(get_message); //callback for MIDI messages received
djbottrill 0:4d06e0867376 270
djbottrill 0:4d06e0867376 271 lcd.cls();
djbottrill 0:4d06e0867376 272 lcd.printf("MIDI Pipe Organ");
djbottrill 0:4d06e0867376 273 wait(1);
djbottrill 0:4d06e0867376 274 lcd.cls();
djbottrill 0:4d06e0867376 275 lcd.printf("On Chan Note Vel");
djbottrill 0:4d06e0867376 276
djbottrill 0:4d06e0867376 277 key=0;
djbottrill 0:4d06e0867376 278 velocity=0;
djbottrill 0:4d06e0867376 279 chan=0;
djbottrill 0:4d06e0867376 280 onoff=0;
djbottrill 0:4d06e0867376 281
djbottrill 0:4d06e0867376 282 //Main Loop
djbottrill 0:4d06e0867376 283 while(1) {
djbottrill 0:4d06e0867376 284
djbottrill 11:a27a71f7c149 285 diag2=1;
djbottrill 11:a27a71f7c149 286 //Process notes off
djbottrill 11:a27a71f7c149 287 for (ii=0; ii<16; ii++) {
djbottrill 11:a27a71f7c149 288 if (synthstat[ii]==1 & keybuf[synthtab[ii]]==0) { //Note currently playing
djbottrill 11:a27a71f7c149 289 synthstat[ii]=2; //Set Start decay
djbottrill 11:a27a71f7c149 290 }
djbottrill 11:a27a71f7c149 291 }
djbottrill 11:a27a71f7c149 292 //Process keys on
djbottrill 11:a27a71f7c149 293 //Find a free note generator and start the note playing, if no slots available just ignore the note
djbottrill 12:74b52900cddb 294 for (keyidx=95; keyidx>=0; keyidx--) {
djbottrill 15:c1854904f0d7 295 if (keybuf[keyidx]>0 & oldkeybuf[keyidx]==0) { //Key is pressed
djbottrill 12:74b52900cddb 296 //Find and use any channel that is free
djbottrill 12:74b52900cddb 297 sucess=0;
djbottrill 11:a27a71f7c149 298 ii=0;
djbottrill 11:a27a71f7c149 299 while (ii<16) { //Find available synth channel
djbottrill 11:a27a71f7c149 300 if (synthstat[ii]==0) { //Is synth channel free?
djbottrill 11:a27a71f7c149 301 synthtab[ii]=keyidx; //Store note value
djbottrill 11:a27a71f7c149 302 synthoctave[ii]=synthtab[ii]/12; //Store the octave
djbottrill 15:c1854904f0d7 303 // if (synthoctave[ii]==7) {
djbottrill 15:c1854904f0d7 304 // synthoctave[ii]--;
djbottrill 15:c1854904f0d7 305 // }
djbottrill 11:a27a71f7c149 306 synthnote[ii]= synthtab[ii]%12; //Note within the octave
djbottrill 11:a27a71f7c149 307 synthstat[ii]=1; //Set status to playing
djbottrill 11:a27a71f7c149 308 synthidx[ii]=freqtab[synthnote[ii]]; //Set the frequency
djbottrill 12:74b52900cddb 309 sucess=1;
djbottrill 11:a27a71f7c149 310 ii=16; //exit loop
djbottrill 11:a27a71f7c149 311 } //Next Synth slot
djbottrill 11:a27a71f7c149 312 ii++;
djbottrill 11:a27a71f7c149 313 }
djbottrill 12:74b52900cddb 314 //As a last resort find any channel that is in decay
djbottrill 12:74b52900cddb 315 if (sucess==0) {
djbottrill 12:74b52900cddb 316 ii=0;
djbottrill 15:c1854904f0d7 317 while (ii<16) { //Find available synth channel
djbottrill 15:c1854904f0d7 318 if (synthstat[ii]>1) { //Is synth channel free?
djbottrill 15:c1854904f0d7 319 synthtab[ii]=keyidx; //Store note value
djbottrill 15:c1854904f0d7 320 synthoctave[ii]=synthtab[ii]/12; //Store the octave
djbottrill 15:c1854904f0d7 321 synthnote[ii]= synthtab[ii]%12; //Note within the octave
djbottrill 15:c1854904f0d7 322 synthstat[ii]=1; //Set status to playing
djbottrill 15:c1854904f0d7 323 synthidx[ii]=freqtab[synthnote[ii]]; //Set the frequency
djbottrill 12:74b52900cddb 324 sucess=1;
djbottrill 15:c1854904f0d7 325 ii=16; //exit loop
djbottrill 15:c1854904f0d7 326 } //Next Synth slot
djbottrill 12:74b52900cddb 327 ii++;
djbottrill 12:74b52900cddb 328 }
djbottrill 12:74b52900cddb 329 }
djbottrill 11:a27a71f7c149 330 }
djbottrill 12:74b52900cddb 331 if (sucess==1) {
djbottrill 12:74b52900cddb 332 oldkeybuf[keyidx]=keybuf[keyidx]; //Store old value if note scuessfull
djbottrill 12:74b52900cddb 333 }
djbottrill 11:a27a71f7c149 334 }
djbottrill 11:a27a71f7c149 335 diag2=0;
djbottrill 11:a27a71f7c149 336 wait_ms(1);
djbottrill 15:c1854904f0d7 337
djbottrill 15:c1854904f0d7 338
djbottrill 15:c1854904f0d7 339 //Output to Shift register
djbottrill 15:c1854904f0d7 340 for (keyidx=107; keyidx>11; keyidx--) {
djbottrill 15:c1854904f0d7 341 if (keybuf[keyidx]>0) {
djbottrill 15:c1854904f0d7 342 SER1=1;
djbottrill 15:c1854904f0d7 343 } else {
djbottrill 15:c1854904f0d7 344 SER1=0;
djbottrill 15:c1854904f0d7 345 }
djbottrill 15:c1854904f0d7 346 SRCK=1; //Pulse Serial clock
djbottrill 15:c1854904f0d7 347 wait_us(4);
djbottrill 15:c1854904f0d7 348 SRCK=0;
djbottrill 15:c1854904f0d7 349 wait_us(4);
djbottrill 15:c1854904f0d7 350 } //Next bit
djbottrill 15:c1854904f0d7 351
djbottrill 15:c1854904f0d7 352 RCK=1; //Transfer data to outputs
djbottrill 15:c1854904f0d7 353 wait_us(4);
djbottrill 15:c1854904f0d7 354 RCK=0;
djbottrill 15:c1854904f0d7 355 wait_us(4);
djbottrill 15:c1854904f0d7 356
djbottrill 15:c1854904f0d7 357
djbottrill 15:c1854904f0d7 358
djbottrill 15:c1854904f0d7 359 /*
djbottrill 15:c1854904f0d7 360 Additional code to de-bounce the K64F onboard switches again using multiple loops to de-bounce; has 3 states:
djbottrill 15:c1854904f0d7 361 0 - Button not pressed
djbottrill 15:c1854904f0d7 362 1 - Button pressed waiting for de-bounce count of 10 loops
djbottrill 15:c1854904f0d7 363 2 - Button press stable, this status can be read as the de-bounced status indicating the button press is clean
djbottrill 15:c1854904f0d7 364 */
djbottrill 6:073e10217962 365 // De-bounce SW1
djbottrill 9:b0f110c02b1b 366 if (sw1_phase==0 & sw1==0) { //Button just been pressed
djbottrill 6:073e10217962 367 sw1_phase=1;
djbottrill 6:073e10217962 368 sw1_count=10;
djbottrill 6:073e10217962 369 }
djbottrill 9:b0f110c02b1b 370 if (sw1_phase==1 & sw1_count==0 & sw1==0) { //Button still pressed after de-bounce period
djbottrill 6:073e10217962 371 sw1_phase=2;
djbottrill 6:073e10217962 372 }
djbottrill 9:b0f110c02b1b 373 if (sw1_phase==2 & sw1==1) { //Button released
djbottrill 6:073e10217962 374 sw1_phase=0;
djbottrill 6:073e10217962 375 }
djbottrill 6:073e10217962 376 sw1_count--;
djbottrill 15:c1854904f0d7 377 // De-bounce SW3
djbottrill 9:b0f110c02b1b 378 if (sw3_phase==0 & sw3==0) { //Button just been pressed
djbottrill 7:e1ea1623c6c2 379 sw3_phase=1;
djbottrill 7:e1ea1623c6c2 380 sw3_count=10;
djbottrill 7:e1ea1623c6c2 381 }
djbottrill 9:b0f110c02b1b 382 if (sw3_phase==1 & sw3_count==0 & sw3==0) { //Button still pressed after de-bounce period
djbottrill 7:e1ea1623c6c2 383 sw3_phase=2;
djbottrill 7:e1ea1623c6c2 384 }
djbottrill 6:073e10217962 385
djbottrill 9:b0f110c02b1b 386 if (sw3_phase==2 & sw3==1) { //Button released
djbottrill 7:e1ea1623c6c2 387 sw3_phase=0;
djbottrill 7:e1ea1623c6c2 388 }
djbottrill 7:e1ea1623c6c2 389 sw3_count--;
djbottrill 6:073e10217962 390
djbottrill 6:073e10217962 391
djbottrill 6:073e10217962 392
djbottrill 6:073e10217962 393
djbottrill 0:4d06e0867376 394 if (sw1_phase==2 | sw3_phase==2) {
djbottrill 0:4d06e0867376 395 blueled=0;
djbottrill 0:4d06e0867376 396 } else {
djbottrill 0:4d06e0867376 397 blueled=1;
djbottrill 0:4d06e0867376 398 }
djbottrill 0:4d06e0867376 399
djbottrill 0:4d06e0867376 400
djbottrill 9:b0f110c02b1b 401 //Button 1 will clear all playing notes
djbottrill 9:b0f110c02b1b 402 if (sw1_phase != sw1_old) {
djbottrill 9:b0f110c02b1b 403 if(sw1_phase==2) {
djbottrill 9:b0f110c02b1b 404 for (cl=0; cl<108; cl++) {
djbottrill 12:74b52900cddb 405 keybuf[cl]=0; //Clear Keybuf
djbottrill 9:b0f110c02b1b 406 }
djbottrill 9:b0f110c02b1b 407 }
djbottrill 9:b0f110c02b1b 408 }
djbottrill 9:b0f110c02b1b 409
djbottrill 0:4d06e0867376 410 //Check for display mode button being presed
djbottrill 9:b0f110c02b1b 411 if (sw3_phase != sw3_old) { //Mode Switch pressed
djbottrill 0:4d06e0867376 412 if(sw3_phase==2) {
djbottrill 0:4d06e0867376 413 lcdmode++;
djbottrill 8:df5f305aab22 414 if (lcdmode>3) {
djbottrill 0:4d06e0867376 415 lcdmode=0;
djbottrill 0:4d06e0867376 416 }
djbottrill 0:4d06e0867376 417 lcd.cls();
djbottrill 0:4d06e0867376 418 if (lcdmode==0) {
djbottrill 0:4d06e0867376 419 lcd.printf("On Chan Note Vel");
djbottrill 0:4d06e0867376 420 }
djbottrill 0:4d06e0867376 421 if (lcdmode==1) {
djbottrill 0:4d06e0867376 422 //Initialise bar graph display
djbottrill 10:fa2dee836ceb 423 //Program user defined characters into OLED display for bar graph
djbottrill 10:fa2dee836ceb 424 lcd.setUDC(0, (char *) udc0);
djbottrill 10:fa2dee836ceb 425 lcd.setUDC(1, (char *) udc1);
djbottrill 10:fa2dee836ceb 426 lcd.setUDC(2, (char *) udc2);
djbottrill 10:fa2dee836ceb 427 lcd.setUDC(3, (char *) udc3);
djbottrill 10:fa2dee836ceb 428 lcd.setUDC(4, (char *) udc4);
djbottrill 10:fa2dee836ceb 429 lcd.setUDC(5, (char *) udc5);
djbottrill 10:fa2dee836ceb 430 lcd.setUDC(6, (char *) udc6);
djbottrill 10:fa2dee836ceb 431 lcd.setUDC(7, (char *) udc7);
djbottrill 0:4d06e0867376 432 for (row=0; row<2; row++) {
djbottrill 0:4d06e0867376 433 for (pos=0; pos<16; pos++) {
djbottrill 0:4d06e0867376 434 display[row][pos]=0;
djbottrill 0:4d06e0867376 435 display_old[row][pos]=1;
djbottrill 0:4d06e0867376 436 }
djbottrill 0:4d06e0867376 437 }
djbottrill 0:4d06e0867376 438 }
djbottrill 0:4d06e0867376 439 if (lcdmode==2) {
djbottrill 0:4d06e0867376 440 lcd.locate(0,1);
djbottrill 0:4d06e0867376 441 lcd.printf("0123456789ABCDEF");
djbottrill 0:4d06e0867376 442 }
djbottrill 8:df5f305aab22 443 if (lcdmode==3) {
djbottrill 8:df5f305aab22 444 lcd.cls();
djbottrill 8:df5f305aab22 445 lcd.locate(0,0);
djbottrill 8:df5f305aab22 446 lcd.printf("Utilisation:");
djbottrill 8:df5f305aab22 447 }
djbottrill 0:4d06e0867376 448 }
djbottrill 0:4d06e0867376 449 }
djbottrill 0:4d06e0867376 450 sw3_old=sw3_phase;
djbottrill 0:4d06e0867376 451
djbottrill 0:4d06e0867376 452
djbottrill 0:4d06e0867376 453
djbottrill 0:4d06e0867376 454 // OLED MIDI Status display
djbottrill 0:4d06e0867376 455 if (lcdmode==0) {
djbottrill 0:4d06e0867376 456 lcd_stat=key+(128*velocity)+(16384*chan)+(262144*onoff);
djbottrill 0:4d06e0867376 457 if (lcd_stat!=lcd_stat_old) {
djbottrill 0:4d06e0867376 458
djbottrill 0:4d06e0867376 459 lcd.locate(0,1);
djbottrill 0:4d06e0867376 460 lcd.printf("%1d %2d %3d %3d", onoff, chan, key, velocity);
djbottrill 0:4d06e0867376 461 lcd_stat_old=lcd_stat;
djbottrill 0:4d06e0867376 462 }
djbottrill 0:4d06e0867376 463 }
djbottrill 0:4d06e0867376 464
djbottrill 0:4d06e0867376 465 // OLED MIDI Bar Display
djbottrill 0:4d06e0867376 466 if (lcdmode==1) {
djbottrill 0:4d06e0867376 467 keyidx=0;
djbottrill 0:4d06e0867376 468 for (row=1; row>=0; row--) {
djbottrill 0:4d06e0867376 469 for (pos=0; pos<16; pos++) {
djbottrill 0:4d06e0867376 470 keyidx_t=keyidx*2;
djbottrill 0:4d06e0867376 471 if(keyidx_t>94) {
djbottrill 0:4d06e0867376 472 keyidx_t=keyidx_t-95;
djbottrill 0:4d06e0867376 473 }
djbottrill 15:c1854904f0d7 474 tval=keybuf[keyidx_t];
djbottrill 12:74b52900cddb 475 if(tval>0) {
djbottrill 12:74b52900cddb 476 tval=1;
djbottrill 12:74b52900cddb 477 }
djbottrill 0:4d06e0867376 478 keyidx++;
djbottrill 0:4d06e0867376 479 keyidx_t=keyidx*2;
djbottrill 0:4d06e0867376 480 if(keyidx_t>94) {
djbottrill 0:4d06e0867376 481 keyidx_t=keyidx_t-95;
djbottrill 0:4d06e0867376 482 }
djbottrill 15:c1854904f0d7 483 tval1=keybuf[keyidx_t];
djbottrill 12:74b52900cddb 484 if (tval1>0) {
djbottrill 12:74b52900cddb 485 tval1=1;
djbottrill 12:74b52900cddb 486 }
djbottrill 12:74b52900cddb 487 tval=tval+(2*tval1);
djbottrill 0:4d06e0867376 488 keyidx++;
djbottrill 0:4d06e0867376 489
djbottrill 0:4d06e0867376 490 keyidx_t=keyidx*2;
djbottrill 0:4d06e0867376 491 if(keyidx_t>94) {
djbottrill 0:4d06e0867376 492 keyidx_t=keyidx_t-95;
djbottrill 0:4d06e0867376 493 }
djbottrill 15:c1854904f0d7 494 tval1=keybuf[keyidx_t];
djbottrill 12:74b52900cddb 495 if (tval1>0) {
djbottrill 12:74b52900cddb 496 tval1=1;
djbottrill 12:74b52900cddb 497 }
djbottrill 12:74b52900cddb 498 tval=tval+(4*tval1);
djbottrill 0:4d06e0867376 499 keyidx++;
djbottrill 0:4d06e0867376 500 display[row][pos]=tval;
djbottrill 0:4d06e0867376 501
djbottrill 0:4d06e0867376 502 if(display[row][pos]!=display_old[row][pos]) {
djbottrill 0:4d06e0867376 503 lcd.locate(pos,row);
djbottrill 0:4d06e0867376 504 lcd.putc(display[row][pos]);
djbottrill 0:4d06e0867376 505 display_old[row][pos]=display[row][pos];
djbottrill 0:4d06e0867376 506 }
djbottrill 0:4d06e0867376 507 }
djbottrill 0:4d06e0867376 508 }
djbottrill 0:4d06e0867376 509 }
djbottrill 0:4d06e0867376 510
djbottrill 0:4d06e0867376 511 //Display status of the Synth channels
djbottrill 0:4d06e0867376 512 if (lcdmode==2) {
djbottrill 0:4d06e0867376 513 lcd.locate(0,0);
djbottrill 0:4d06e0867376 514 for (noteidx=0; noteidx<16; noteidx++) {
djbottrill 0:4d06e0867376 515 lcd.putc((synthstat[noteidx]+48));
djbottrill 0:4d06e0867376 516 }
djbottrill 0:4d06e0867376 517 }
djbottrill 4:9f63e68b548e 518
djbottrill 8:df5f305aab22 519 //Display utilisation bar graph
djbottrill 8:df5f305aab22 520 if (lcdmode==3) {
djbottrill 8:df5f305aab22 521 x=0;
djbottrill 8:df5f305aab22 522 for (noteidx=0; noteidx<16; noteidx++) {
djbottrill 8:df5f305aab22 523 if (synthstat[noteidx] >0) {
djbottrill 8:df5f305aab22 524 x++;
djbottrill 8:df5f305aab22 525 }
djbottrill 8:df5f305aab22 526 }
djbottrill 8:df5f305aab22 527 for (pos=0; pos<x; pos++) {
djbottrill 8:df5f305aab22 528 display[1][pos]=0xff;
djbottrill 8:df5f305aab22 529 }
djbottrill 8:df5f305aab22 530 while(pos<16) {
djbottrill 8:df5f305aab22 531 display[1][pos]=0x20;
djbottrill 8:df5f305aab22 532 pos++;
djbottrill 8:df5f305aab22 533 }
djbottrill 8:df5f305aab22 534 row=1;
djbottrill 8:df5f305aab22 535 for (pos=0; pos<16; pos++) {
djbottrill 8:df5f305aab22 536 if (x!=x1) {
djbottrill 8:df5f305aab22 537 lcd.locate(13,0);
djbottrill 8:df5f305aab22 538 lcd.printf("%2d", x);
djbottrill 8:df5f305aab22 539 x1=x;
djbottrill 8:df5f305aab22 540 }
djbottrill 8:df5f305aab22 541 if(display[row][pos]!=display_old[row][pos]) {
djbottrill 8:df5f305aab22 542 lcd.locate(pos,row);
djbottrill 8:df5f305aab22 543 lcd.putc(display[row][pos]);
djbottrill 8:df5f305aab22 544 display_old[row][pos]=display[row][pos];
djbottrill 8:df5f305aab22 545 }
djbottrill 8:df5f305aab22 546 }
djbottrill 8:df5f305aab22 547 }
djbottrill 8:df5f305aab22 548
djbottrill 8:df5f305aab22 549
djbottrill 8:df5f305aab22 550
djbottrill 0:4d06e0867376 551 } //End of main loop
djbottrill 0:4d06e0867376 552 } //End of program
djbottrill 0:4d06e0867376 553
djbottrill 0:4d06e0867376 554
djbottrill 0:4d06e0867376 555
djbottrill 0:4d06e0867376 556