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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 Program to drive organ magnets from a MIDI input
00003 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
00004 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
00005 MIDI note 24 so the bottom 16' octave can be generated electronically if 16' pipes are not feasible.
00006 In fact the sampled output could be tailored to fill in any missing note ranges,
00007 Repeated pressing sw3 cycles through a number of display modes.
00008 Pressing sw1 switches between two sound samples Bourdon and Montre only one rank is availble at any one time.
00009 This program is currently only compatible with the K64F as it's one of the few MBED boards that has sufficient speed, Flash ROM storage 
00010 and of course a DAC.
00011 The sounds samples are derived from the Jeux D'Orgue 2 sample set http://www.jeuxdorgues.com and are used with permission.
00012 */
00013 #include "mbed.h"
00014 
00015 #include "Bourdon.h"
00016 #include "Montre.h"
00017 
00018 /*
00019 As the ticker cannot be accurately controlled it is necessary to apply a fine adjustment capability
00020 hence the fine tune below that is used to multiply the step index as read from freqtab.
00021 freqtab is based on the assumption the ticker is running at exactly 44.1Khz
00022 */
00023 const float sample_rate = 22.68;                                                                        //44.1KHz
00024 const float freqfine=0.970;
00025 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};
00026 
00027 #include "USBMIDI.h"
00028 
00029 #include "TextLCD.h"
00030 //For Linksprite LCD Shield
00031 //TextLCD lcd(PTC12, D9, D4, D5, D6, D7); // rs, e, d4-d7
00032 //DigitalOut bl(D10);
00033 //D8 is wrong on K64F definition it is actually PTC12 not PTA0
00034 
00035 //For Midas 2x16 OLED Display
00036 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
00037 
00038 //Serial pc(USBTX, USBRX); // tx, rx
00039 
00040 AnalogOut Aout(DAC0_OUT);
00041 
00042 DigitalOut redled(LED1);
00043 DigitalOut greenled(LED2);
00044 DigitalOut blueled(LED3);
00045 
00046 DigitalOut diag(D15);
00047 DigitalOut diag2(D14);
00048 
00049 DigitalIn sw1(PTC6);
00050 DigitalIn sw3(PTA4);
00051 
00052 //Stop switches mommentary connection to 0V will toggle on and off. 8' pitch defaults to on at power up.
00053 DigitalIn p1 (PTB2);                                                                                    //16'
00054 DigitalIn p2 (PTB3);                                                                                    //8'
00055 DigitalIn p3 (PTB10);                                                                                   //4'
00056 DigitalIn p4 (PTB11);                                                                                   //2 2/3'
00057 DigitalIn p5 (PTC11);                                                                                   //2'
00058 
00059 //Wi-Fi connector J6 note pin 3 is incorrectly idenifed in the documentation as PTC12
00060 //Connects the shift register solenoid driver board
00061 DigitalOut SRCK(PTD7);                                                                                  //Shift Register clock
00062 DigitalOut RCK(PTD5);                                                                                   //Shift Register latch
00063 DigitalOut SER1(PTB20);                                                                                 //Shift Register serial data outout
00064 
00065 
00066 Ticker output_ticker;                                                                                   //Ticker for sound generation
00067 
00068 unsigned char keybuf[128]= {};                                                                          //Note buffer
00069 unsigned char oldkeybuf[128]= {};                                                                       //Last note buffer        
00070 int keyidx=0;                                                                                           //Key index
00071 
00072 //Received MIDI note variables
00073 int key=0;                                                                          
00074 int velocity=0;
00075 int chan=0;
00076 int onoff=0;
00077 
00078 unsigned int audio_out;                                                                                 //Audio output value accumulator
00079 
00080 //OLELD display bar graph characters
00081 const char udc0[] = {0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00};
00082 const char udc1[] = {0x15, 0x10, 0x10, 0x10, 0x10, 0x10, 0x15, 0x00};
00083 const char udc2[] = {0x15, 0x04, 0x04, 0x04, 0x04, 0x04, 0x15, 0x00};
00084 const char udc3[] = {0x15, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x00};
00085 const char udc4[] = {0x15, 0x01, 0x01, 0x01, 0x01, 0x01, 0x15, 0x00};
00086 const char udc5[] = {0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x15, 0x00};
00087 const char udc6[] = {0x15, 0x05, 0x05, 0x05, 0x05, 0x05, 0x15, 0x00};
00088 const char udc7[] = {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00};
00089 
00090 //Variables for LCD/OLED display
00091 unsigned long int lcd_stat=0;
00092 unsigned long int lcd_stat_old=1;
00093 char display[2][16];                                                                                    //Display Buffer
00094 char display_old[2][16];                                                                                //Old Display Buffer
00095 int pos=0;                                                                                              //Display Position counter
00096 int row=0;
00097 int tval=0;
00098 int tval1=0;
00099 int keyidx_t=0;
00100 int lcdmode=0;                                                                                          //LCD Display Mode
00101 int x =0;
00102 int x1=1;
00103 
00104 //Button and stop variables
00105 unsigned int swi;
00106 unsigned int pressed;
00107 unsigned int sw[8];
00108 unsigned int sw_count[8];                                                                               //Switch de-bounce counter
00109 unsigned int sw_phase[8];
00110 unsigned int sw_status[8]= {0,1,0,0,0,0,0,0};                                                           //Stop status 8' on by default
00111 unsigned int sw_old[8];
00112 int oldstops=1;
00113 
00114 //Sound generator variables
00115 int sampleset=0;
00116 int tempidx=0;
00117 int freqidx=45;
00118 float synth[16];
00119 float synthidx[16];
00120 int synth_old[16];
00121 int synthtab[16]= {};
00122 int synthstat[16]= {};
00123 unsigned char synthoctave[16]= {};
00124 unsigned char synthnote[16]= {};
00125 int sucess=0;
00126 int noteidx=0;
00127 int i;
00128 int ii;
00129 int cl;
00130 
00131 /*
00132 Ticker routine to calculate and output the audio signal.
00133 As the DAC is 12 bit this allows for 16 concurrent 8 bit samples running with no additional loss of precision.
00134 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.
00135 Sound Generation is in 4 states stored in synthstat:
00136 0 = Synth Channel idle
00137 1 = Attack / Sustain phase note running and looping if necessary
00138 2 = Signal to start release this may be delayed until the sound is paat the initial attack/decay point typically 100-200 mS
00139 3 = Sample is in the release phase.
00140 
00141 */
00142 void aout()
00143 {
00144 //The lines below are commented out and actually add to much time to the ticker routine each command adds around  1 uS which is significant
00145 //when the whole routine only takes around 16uS and is repeated every 23mS    
00146 //    diag=1;                                                                                             //Pulse DIAG Pin for Scoping purposes IE pin high
00147 //    redled=0;                                                                                           //Pulse Red LED to indicate Ticker working
00148     audio_out=0;                                                                                        //Clear Audio Accumulator
00149     if (sampleset==0) {
00150         for (i =0; i<16; i++) {                                                                         //Do 16 channels
00151             switch (synthstat[i]) {
00152                 case 1:     //Sustain phase
00153                     if (synth[i]>sample1_loop_end[synthoctave[i]]) {                                    //Got to end of buffer?
00154                         synth[i]=sample1_loop_start[synthoctave[i]];                                    //Wrap around back to start
00155                     }
00156                     break;
00157                 case 2:     //Note off demand state
00158                     if (synth[i]>=sample1_attack[synthoctave[i]]) {                                     //Delay decay phase if not past end of attack
00159 //Check if the waveform is close to zero crossing this helps eliminate clicks looks for rising edge approaching 0x80
00160                         tempidx=synth[i];
00161                         if (sample1[synthoctave[i]][tempidx]<128 & sample1[synthoctave[i]][tempidx]>120) {
00162                             if (sample1[synthoctave[i]][tempidx]>synth_old[i]) {
00163                                 synth[i]=sample1_loop_off[synthoctave[i]];                              //Jump to start of release
00164                                 synthstat[i]=3;                                                         //Say note in release
00165                             }
00166                         }
00167                     }
00168                     break;
00169                 case 3:    //Check if decay has completed
00170                     if (synth[i]>=sample1_len[synthoctave[i]]) {                                        //End of release?
00171                         synthstat[i]=0;                                                                 //say channel free
00172                         synth[i]=0;                                                                     //Set sample pointer to 0
00173                         synthidx[i]=0;                                                                  //Set sample index to 0
00174                         synthtab[i]=255;                                                                //Set to invalid
00175                     }
00176                     break ;
00177             }
00178 
00179 //get sample and add to Audio Accumulator
00180             synth_old[i]=sample1[synthoctave[i]][(int)(synth[i])];                                      //Get and save old sample
00181             audio_out=audio_out+synth_old[i];                                                           //add sample to audio out accumulator
00182             synth[i]=synth[i]+synthidx[i];                                                              //Get next sample pointer
00183 
00184         }                                                                                               //Next Note
00185     } else {
00186 
00187 //Sample Set 2
00188 
00189         for (i =0; i<16; i++) {                                                                         //Do 16 channels
00190             switch (synthstat[i]) {
00191                 case 1:     //Sustain phase
00192                     if (synth[i]>sample2_loop_end[synthoctave[i]]) {                                    //Got to end of buffer?
00193                         synth[i]=sample2_loop_start[synthoctave[i]];                                    //Wrap around back to start
00194                     }
00195                     break;
00196                 case 2:     //Note off demand state
00197                     if (synth[i]>=sample2_attack[synthoctave[i]]) {                                     //Delay release phase if not past end of attack
00198 //Check if the waveform is close to zero crossing this helps eliminate clicks looks for rising edge approaching 0x80
00199                         tempidx=synth[i];
00200                         if (sample2[synthoctave[i]][tempidx]<128 & sample2[synthoctave[i]][tempidx]>120) {
00201                             if (sample2[synthoctave[i]][tempidx]>synth_old[i]) {
00202                                 synth[i]=sample2_loop_off[synthoctave[i]];                              //Jump to start of release
00203                                 synthstat[i]=3;                                                         //Say note in release
00204                             }
00205                         }
00206                     }
00207                     break;
00208                 case 3:    //Check if release has completed
00209                     if (synth[i]>=sample2_len[synthoctave[i]]) {                                        //End of release?
00210                         synthstat[i]=0;                                                                 //say channel free
00211                         synth[i]=0;                                                                     //Set sample pointer to 0
00212                         synthidx[i]=0;                                                                  //Set sample index to 0
00213                         synthtab[i]=255;                                                                //Set to invalid
00214                     }
00215                     break ;
00216             }
00217 
00218 //get sample and add to Audio Accumulator
00219             synth_old[i]=sample2[synthoctave[i]][(int)(synth[i])];                                      //Get and save old sample
00220             audio_out=audio_out+synth_old[i];                                                           //add sample to audio out accumulator
00221             synth[i]=synth[i]+synthidx[i];                                                              //Get next sample pointer
00222 
00223         }                                                                                               //Next Note
00224     }
00225 
00226 
00227 //Output to DAC
00228     Aout.write_u16(audio_out*16);
00229 
00230 //    redled=1;
00231 //    diag=0;
00232 }
00233 
00234 /*
00235 Interrupt routine to receive MIDI on/off message
00236 MIDI note on/off events are stored in the note status buffer keytab.
00237 the lower 5 bits of keytab represent a note being on or off
00238 Bit 0 = 16'
00239 Bit 1 = 8'
00240 Bit 2 = 4'
00241 Bit 3 = 2 2/3' (12th)
00242 Bit 4 = 2' (15th)
00243 Thus if keytab >0 then the note should be played
00244 Currently MIDI note on/off messages are accepted on any channel
00245 */
00246 void get_message(MIDIMessage msg)
00247 {
00248     greenled=0;                                                                                         //Pulse Green LED to indicate MIDI activity
00249     key=msg.key();
00250     velocity=msg.velocity();
00251     chan=msg.channel();
00252     switch (msg.type()) {
00253         case MIDIMessage::NoteOnType:                                                                   //MIDI note on received
00254             if (key >23 & key<120) {
00255                 onoff=1;
00256                 if (sw_status[0]==1 & key >35) {
00257                     keybuf[(key-36)]|= 1 << 0;                                                          //Store @ 16' pitch
00258                 }
00259                 if (sw_status[1]==1) {
00260                     keybuf[(key-24)]|= 1 << 1;                                                          //Store @ 8' pitch
00261                 }
00262                 if (sw_status[2]==1& key<108) {
00263                     keybuf[(key)-12]|= 1 << 2;                                                          //Store @ 4' pitch
00264                 }
00265                 if (sw_status[3]==1 & key<101) {
00266                     keybuf[(key)-5]|= 1 << 3;                                                           //Store @ 2 2/3' pitch
00267                 }
00268                 if (sw_status[4]==1 & key <96) {
00269                     keybuf[(key)]|= 1 << 4;                                                             //Store @ 2' pitch
00270                 }
00271             }
00272 
00273             break;
00274 
00275 //Process keys off
00276         case MIDIMessage::NoteOffType:                                                                  //Midi note off received
00277             if (key >23 & key<120) {
00278                 onoff=0;
00279                 if (key>35) {
00280                     keybuf[(key-36)]&= ~(1 << 0);                                                       //Kill note @ 16' pitch
00281                 }
00282                 keybuf[(key-24)]&= ~(1 << 1);                                                           //Kill note @ 8' pitch
00283                 if (key<108) {
00284                     keybuf[(key-12)]&= ~(1 << 2);                                                       //Kill note @ 4' pitch
00285                 }
00286                 if (key<101) {
00287                     keybuf[(key-5)]&= ~(1 << 3);                                                        //Kill note @ 2 2/3' pitch
00288                 }
00289                 if (key<96) {
00290                     keybuf[(key)]&= ~(1 << 4);                                                          //Kill note @ 2' pitch
00291                 }
00292             }
00293             break;
00294 
00295 //Process all notes off command
00296         case MIDIMessage::AllNotesOffType:                                                              //Midi all notes off
00297             for (int it=0; it<108; it++) {
00298                 keybuf[it]=0;                                                                           //Clear Keybuf
00299             }
00300             break;
00301 
00302 //Any other MIDI Commands just ignore
00303         default:
00304             break;
00305     }
00306     greenled=1;
00307 }
00308 
00309 
00310 int main()
00311 {
00312     greenled=1;
00313     redled=1;
00314     blueled=1;
00315     SRCK=0;                                                                                             //Serial Clock low
00316     RCK=0;                                                                                              //Latch Clock low
00317 
00318     sw1.mode(PullUp);
00319     sw3.mode(PullUp);
00320     p1.mode(PullUp);
00321     p2.mode(PullUp);
00322     p3.mode(PullUp);
00323     p4.mode(PullUp);
00324     p5.mode(PullUp);
00325 
00326     output_ticker.attach_us(&aout, sample_rate);                                                        //Start the ticker
00327 
00328     lcd.cls();
00329     wait(0.1);
00330     lcd.setCursor(TextLCD::CurOff_BlkOff);
00331     lcd.cls();
00332     lcd.printf("MIDI Pipe Organ Waiting for USB");
00333 /*
00334 I couldn't figure out which interrupt is used for the ticker so I lowered the USB interrupt priority so that it didn't
00335 interfere with the smooth operation of the sound generation ticker
00336 */
00337     NVIC_SetPriority(USB0_IRQn, 99);                                                                    //Reduce Interrupt priority of USB
00338 
00339     USBMIDI midi;                                                                                       //Start up MIDI
00340     midi.attach(get_message);                                                                           //callback for MIDI messages received
00341 
00342     lcd.cls();
00343     lcd.printf("MIDI Pipe Organ");
00344     wait(1);
00345     lcd.cls();
00346     lcd.printf("On Chan Note Vel");
00347     key=0;
00348     velocity=0;
00349     chan=0;
00350     onoff=0;
00351 
00352 //Main Loop
00353     while(1)  {
00354 
00355 
00356 //Process notes off
00357         for (ii=0; ii<16; ii++) {                                                                       //Scan through 16 channels
00358             if (synthstat[ii]==1 & keybuf[synthtab[ii]]==0) {                                           //Note currently playing but should be off
00359                 synthstat[ii]=2;                                                                        //Set Start release
00360             }
00361         }
00362 //Process keys on
00363 //Find a free note generator and start the note playing, if no slots available just ignore the note
00364         for (keyidx=95; keyidx>=0; keyidx--) {
00365             if (keybuf[keyidx]>0 & oldkeybuf[keyidx]==0) {                                              //Key is pressed
00366 //Find and use any channel that is free
00367                 sucess=0;
00368                 ii=0;
00369                 while (ii<16) {                                                                         //Find available synth channel
00370                     if (synthstat[ii]==0) {                                                             //Is synth channel free?
00371                         synthtab[ii]=keyidx;                                                            //Store note value
00372                         synthoctave[ii]=synthtab[ii]/12;                                                //Store the octave
00373 //Uncomment the following lines if you want to wrap around the top octave
00374 //                        if (synthoctave[ii]==7) {                                                       //Wrap around the top octave
00375 //                            synthoctave[ii]--;
00376 //                        }
00377                         synthnote[ii]= synthtab[ii]%12;                                                 //Note within the octave
00378                         synthstat[ii]=1;                                                                //Set status to playing
00379                         synthidx[ii]=freqtab[synthnote[ii]]*freqfine;                                   //Set the frequency
00380                         sucess=1;
00381                         ii=16;                                                                          //exit loop
00382                     }                                                                                   //Next Synth slot
00383                     ii++;
00384                 }
00385 //As a last resort find any channel that is in release
00386                 if (sucess==0) {
00387                     ii=0;
00388                     while (ii<16) {                                                                     //Find available synth channel
00389                         if (synthstat[ii]==3) {                                                         //Is synth channel free?
00390                             synthtab[ii]=keyidx;                                                        //Store note value
00391                             synthoctave[ii]=synthtab[ii]/12;                                            //Store the octave
00392                             synthnote[ii]= synthtab[ii]%12;                                             //Note within the octave
00393                             synthstat[ii]=1;                                                            //Set status to playing
00394                             synthidx[ii]=freqtab[synthnote[ii]]*freqfine;                               //Set the frequency
00395                             sucess=1;
00396                             ii=16;                                                                      //exit loop
00397                         }                                                                               //Next Synth slot
00398                         ii++;
00399                     }
00400                 }
00401             }
00402             if (sucess==1) {
00403                 oldkeybuf[keyidx]=keybuf[keyidx];                                                       //Store old value if note sucessfull
00404             }                                                                                           //If not sucessfull try on the next scan    
00405         }
00406 
00407 
00408 //Output to Shift register pallet magnet driver board
00409         for (keyidx=107; keyidx>11; keyidx--) {
00410             if (keybuf[keyidx]>0) {
00411                 SER1=1;
00412             } else {
00413                 SER1=0;
00414             }
00415             SRCK=1;                                                                                     //Pulse Serial clock
00416             wait_us(4);
00417             SRCK=0;
00418             wait_us(4);
00419         }                                                                                               //Next bit
00420 
00421         RCK=1;                                                                                          //Transfer data to outputs
00422         wait_us(4);
00423         RCK=0;
00424         wait_us(4);
00425 
00426 //Read Stop inputs and onboard switches
00427         sw[0]=p1;
00428         sw[1]=p2;
00429         sw[2]=p3;
00430         sw[3]=p4;
00431         sw[4]=p5;
00432         sw[6]=sw1;
00433         sw[7]=sw3;
00434 /*
00435 code to de-bounce the K64F onboard and external switches using multiple loops to de-bounce; has 3 states:
00436 0 - Button not pressed
00437 1 - Button pressed waiting for de-bounce count of 5 loops
00438 2 - Button press stable, this status can be read as the de-bounced status indicating the button press is clean
00439 sw_status is toggled by each sucessive key press 0 / 1
00440 */
00441         pressed=0;
00442         for (swi=0; swi<8; swi++) {                                                                     //Process 8 push switches
00443             if (sw_phase[swi]==0 & sw[swi]==0) {                                                        //Button just been pressed
00444                 sw_phase[swi]=1;
00445                 sw_count[swi]=5;
00446             }
00447             if (sw_phase[swi]==1 & sw_count[swi]==0 & sw[swi]==0) {                                     //Button still pressed after de-bounce period
00448                 sw_phase[swi]=2;
00449                 pressed++;                                                                              //Inc button pressed count
00450                 sw_status[swi]=!sw_status[swi];                                                         //Toggle switch status
00451             }
00452             if (sw_phase[swi]==1 & sw_count[swi]==0 & sw[swi]==1) {                                     //Button no longer pressed after de-bounce period
00453                 sw_phase[swi]=0;
00454             }
00455             if (sw_phase[swi]==2 & sw[swi]==1) {                                                        //Button  released
00456                 sw_phase[swi]=0;
00457             }
00458             sw_count[swi]--;
00459         }
00460 //light blue LED if any button presed
00461         if (pressed>0) {
00462             blueled=0;
00463         } else {
00464             blueled=1;
00465         }
00466 
00467 
00468 //Button 1 will clear all playing notes & switch sampleset
00469         if (sw_status[6] != sw_old[6]) {
00470                 for (cl=0; cl<108; cl++) {
00471                     keybuf[cl]=0;                                                                       //Clear Keybuf
00472                 }
00473                 sampleset=sw_status[6];
00474                 oldstops=255;                                                                           //Force a display refresh
00475             sw_old[6]=sw_status[6];
00476         }
00477 
00478 
00479 //Check for display mode button being presed
00480         if (sw_status[7] != sw_old[7]) {                                                                //Mode Switch pressed
00481                 lcdmode++;
00482                 if (lcdmode>4) {
00483                     lcdmode=0;
00484                 }
00485                 lcd.cls();
00486                 if (lcdmode==0) {
00487                     lcd.printf("On Chan Note Vel");
00488                 }
00489                 if (lcdmode==1) {
00490 //Initialise bar graph display
00491 //Program user defined characters into OLED display for bar graph
00492                     lcd.setUDC(0, (char *) udc0);
00493                     lcd.setUDC(1, (char *) udc1);
00494                     lcd.setUDC(2, (char *) udc2);
00495                     lcd.setUDC(3, (char *) udc3);
00496                     lcd.setUDC(4, (char *) udc4);
00497                     lcd.setUDC(5, (char *) udc5);
00498                     lcd.setUDC(6, (char *) udc6);
00499                     lcd.setUDC(7, (char *) udc7);
00500                     for (row=0; row<2; row++) {
00501                         for (pos=0; pos<16; pos++) {
00502                             display[row][pos]=0;
00503                             display_old[row][pos]=1;
00504                         }
00505                     }
00506                 }
00507                 if (lcdmode==2) {
00508 //Initilise synth channel status display                    
00509                     lcd.locate(0,1);
00510                     lcd.printf("0123456789ABCDEF");
00511                 }
00512 //Initialise synth channel unilisation                
00513                 if (lcdmode==3) {
00514                     lcd.cls();
00515                     lcd.locate(0,0);
00516                     lcd.printf("Utilisation:");
00517                 }                
00518                 if (lcdmode==4) {
00519 //Initialise Stops selection display                    
00520                     oldstops=255;                                                                       //Force a refresh
00521                 }
00522             sw_old[7]=sw_status[7];
00523         }
00524 
00525 
00526 
00527 
00528 // OLED MIDI Status display
00529         if (lcdmode==0) {
00530             lcd_stat=key+(128*velocity)+(16384*chan)+(262144*onoff);
00531             if (lcd_stat!=lcd_stat_old) {
00532 
00533                 lcd.locate(0,1);
00534                 lcd.printf("%1d   %2d  %3d  %3d", onoff, chan, key, velocity);
00535                 lcd_stat_old=lcd_stat;
00536             }
00537         }
00538 
00539 // OLED MIDI Bar Display
00540         if (lcdmode==1) {
00541             keyidx=0;
00542             for (row=1; row>=0; row--) {
00543                 for (pos=0; pos<16; pos++) {
00544                     keyidx_t=keyidx*2;
00545                     if(keyidx_t>94) {
00546                         keyidx_t=keyidx_t-95;
00547                     }
00548                     tval=keybuf[keyidx_t];
00549                     if(tval>0) {
00550                         tval=1;
00551                     }
00552                     keyidx++;
00553                     keyidx_t=keyidx*2;
00554                     if(keyidx_t>94) {
00555                         keyidx_t=keyidx_t-95;
00556                     }
00557                     tval1=keybuf[keyidx_t];
00558                     if (tval1>0) {
00559                         tval1=1;
00560                     }
00561                     tval=tval+(2*tval1);
00562                     keyidx++;
00563 
00564                     keyidx_t=keyidx*2;
00565                     if(keyidx_t>94) {
00566                         keyidx_t=keyidx_t-95;
00567                     }
00568                     tval1=keybuf[keyidx_t];
00569                     if (tval1>0) {
00570                         tval1=1;
00571                     }
00572                     tval=tval+(4*tval1);
00573                     keyidx++;
00574                     display[row][pos]=tval;
00575 
00576                     if(display[row][pos]!=display_old[row][pos]) {
00577                         lcd.locate(pos,row);
00578                         lcd.putc(display[row][pos]);
00579                         display_old[row][pos]=display[row][pos];
00580                     }
00581                 }
00582             }
00583         }
00584 
00585 //Display status of the Synth channels
00586         if (lcdmode==2) {
00587             lcd.locate(0,0);
00588             for (noteidx=0; noteidx<16; noteidx++) {
00589                 lcd.putc((synthstat[noteidx]+48));
00590             }
00591         }
00592 
00593 //Display utilisation bar graph
00594         if (lcdmode==3) {
00595             x=0;
00596             for (noteidx=0; noteidx<16; noteidx++) {
00597                 if (synthstat[noteidx] >0) {
00598                     x++;
00599                 }
00600             }
00601             for (pos=0; pos<x; pos++) {
00602                 display[1][pos]=0xff;
00603             }
00604             while(pos<16) {
00605                 display[1][pos]=0x20;
00606                 pos++;
00607             }
00608             row=1;
00609             for (pos=0; pos<16; pos++) {
00610                 if (x!=x1) {
00611                     lcd.locate(13,0);
00612                     lcd.printf("%2d", x);
00613                     x1=x;
00614                 }
00615                 if(display[row][pos]!=display_old[row][pos]) {
00616                     lcd.locate(pos,row);
00617                     lcd.putc(display[row][pos]);
00618                     display_old[row][pos]=display[row][pos];
00619                 }
00620             }
00621         }
00622 //Stop display
00623         if (lcdmode==4) {
00624             pos=sw_status[0] + sw_status[1]+sw_status[2]+sw_status[3]+sw_status[4];
00625             if (oldstops != pos) {
00626                 oldstops=pos;
00627                 lcd.cls();
00628                 for (pos=0; pos<16; pos++) {
00629                     lcd.locate(pos,0);
00630                     if (sampleset==0) {
00631                         lcd.putc(stopname1[pos]);
00632                     } else {
00633                         lcd.putc(stopname2[pos]);
00634                     }
00635                 }
00636                 lcd.locate(0,1);
00637                 if (sw_status[0]==1) {
00638                     lcd.printf("16 ");
00639                 }
00640 
00641                 if (sw_status[1]==1) {
00642                     lcd.printf("8 ");
00643                 }
00644 
00645                 if (sw_status[2]==1) {
00646                     lcd.printf("4 ");
00647                 }
00648 
00649                 if (sw_status[3]==1) {
00650                     lcd.printf("2-2/3 ");
00651                 }
00652 
00653                 if (sw_status[4]==1) {
00654                     lcd.printf("2");
00655                 }
00656             }
00657         }
00658 
00659     }                                                                                                   //End of main loop
00660 }                                                                                                       //End of program
00661 
00662 
00663 
00664