| CODE |
#pragma regalloc- #pragma optsize- #include <Mega32.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <delay.h> #define lineTime 1018 // a general counter #define treshold 50 #define zero 0x00 #define one 0xff #define muxdelay 15 // time to switch channel in capacitive sensor #define th1 20 // treshold for the keys #define th2 60 #define th3 100 #define th4 140 #define range 20 #define begin { #define end } #pragma regalloc+ int LineCount; char Ain0; //raw A to D number char Ain1; char lastAin0[5]; //array to store previous 5 ADC values char lastAin1[5]; int lcdnotes[4]; //array to store previous 4 notes pressed char lcd_buffer[5]; //string used for lcd display unsigned char t_index; //current string index unsigned char t_ready; //flag for transmit done unsigned char t_char; //current character //variables for midi encoding int ntt; //note time int nt; //note int nton; //note on/off status int lastnt; //previous note int lastnton; //previous note on/off status int index; //general index int preindex; int muxcounter; //counter for switching channel int time; //time int c1pressed; //channel 1 pressed int c2pressed; //channel 2 pressed //variables for calibration int calibration;//boolean for calibration mode int caltime; //counter for calibration int caltemp; //temperory value for calibration int calnote[8]; //array for tresholds after calibration int i; //used for loops int octave; //1 = high octave, 0 = low octave #asm .equ __lcd_port=0x15 #endasm #include <lcd.h> // LCD driver routines //Musical note values //C below middle C to C above middle C //zeros are rests flash char notes[] = {0,240,212,188,180,160,142,126,120,106,94,90,80,71,63,60}; char note, musicT; char channel; //********************************************************** // -- nonblocking print: initializes ISR-driven // transmit. This routine merely sets up the ISR, then //send one character, The ISR does all the work. void puts_int(void) begin t_ready=0; t_index=0; UCSRB.5=1; end /**********************************************************/ //UART xmit-empty ISR interrupt [USART_DRE] void uart_send(void) begin UDR = t_char; //send the char UCSRB.5=0; //kill isr t_ready=1; //transmit done end //================================== //This is the sync generator and raster generator. It MUST be entered from //sleep mode to get accurate timing of the sync pulses interrupt [TIM1_COMPA] void t1_cmpA(void) begin //update the curent scanline number LineCount ++; //start new frame after line 262 if (LineCount==263) { time++; caltime++; LineCount = 1; } end //================================= //a fucntion to encode time value to be stored in midi format void WriteVarLen (long value) { long buffer; buffer = value & 0x7f; while ((value >>= 7) > 0) { buffer <<= 8; buffer |= 0x80; buffer += (value & 0x7f); } while (1) { char output; output = buffer&0xff; if(output == 0) output = zero; while(t_ready == 0) {;} t_char = output; puts_int(); if (buffer & 0x80) buffer >>= 8; else break; } } //================================== //function for lighting LED void light(int note) { if(note == 1) PORTB.0 = 1; else PORTB.0 = 0; if(note == 2) PORTB.1 = 1; else PORTB.1 = 0; if(note == 3) PORTB.2 = 1; else PORTB.2 = 0; if(note == 4) PORTB.4 = 1; else PORTB.4 = 0; if(note == 5) PORTB.5 = 1; else PORTB.5 = 0; if(note == 6) PORTB.6 = 1; else PORTB.6 = 0; if(note == 7) PORTB.7 = 1; else PORTB.7 = 0; } //========================= //function to send the appropriate encoded characters //after each note press void shownote() { char t,ton; if(nt == 0) t = 0x3c; else if (nt == 1) t = 0x3c; else if (nt == 2) t = 0x3e; else if (nt == 3) t = 0x40; else if (nt == 4) t = 0x41; else if (nt == 5) t = 0x43; else if (nt == 6) t = 0x45; else if (nt == 7) t = 0x47; else if (nt == 8) t = 0x48; if(octave == 0) { t -= 0x0c; } if(nton == 0) ton = zero; else ton = 0x40; WriteVarLen(ntt); while(t_ready == 0){;} t_char = 0x90; puts_int(); while(t_ready == 0){;} t_char = t; puts_int(); while(t_ready == 0){;} t_char = ton; puts_int(); } //================================== // print note on LCD void printlcd(int i) { if(i == 1) lcd_putsf("C"); if(i == 2) lcd_putsf("D"); if(i == 3) lcd_putsf("E"); if(i == 4) lcd_putsf("F"); if(i == 5) lcd_putsf("G"); if(i == 6) lcd_putsf("A"); if(i == 7) lcd_putsf("B"); if(i == 8) lcd_putsf("C"); if(i == 0) lcd_putsf("X"); } //================================== // set up the ports and timers void main(void) { DDRA=0xf8; DDRD=0x0f; DDRB=0xff; PORTC = channel; //enable ADC ADMUX = 0b11100000; ADCSR = 0b11000111; UCSRB = 0x18; UBRRL = 103; //init timer 1 to generate sync OCR1A = lineTime; //One NTSC line TCCR1B = 9; //full speed; clear-on-match TCCR1A = 0x00; //turn off pwm and oc lines TIMSK = 0x10; //enable interrupt T1 cmp //initialize synch constants LineCount = 1; lcd_init(16); //initialize the display lcd_clear(); //clear the display //init musical scale note = 0; musicT = 0; //use OC0 (pin B.3) for music DDRB.3 = 1; t_ready=1; t_char = 250; time = 0; index = 1; preindex = 0; calibration = 1; lastnt = 0; lastnton = 0; muxcounter = 0; channel = 0x01; lastAin0[0] = 0; lastAin0[1] = 0; lastAin0[2] = 0; lastAin0[3] = 0; lastAin0[4] = 0; lastAin1[0] = 0; lastAin1[1] = 0; lastAin1[2] = 0; lastAin1[3] = 0; lastAin1[4] = 0; Ain0 = 255; Ain1 = 255; #asm ("sei"); lcd_putsf("line 3"); //string from flash //calibration for the 8 keys for(i=0; i<8;i++) { lcd_clear(); lcd_gotoxy(0,1); lcd_putsf("Calibrating"); caltime = 0; while(caltime < 50) { lcd_gotoxy(0,0); lcd_putsf("Ready"); } lcd_gotoxy(0,0); if(i == 0) { channel = 0x01; lcd_putsf("Press C"); } if(i == 1) lcd_putsf("Press D"); if(i == 2) lcd_putsf("Press E"); if(i == 3) lcd_putsf("Press F"); if(i == 4) { channel = 0x02; lcd_putsf("Press G"); } if(i == 5) lcd_putsf("Press A"); if(i == 6) lcd_putsf("Press B"); if(i == 7) lcd_putsf("Press C"); PORTA.3 = 0; PORTA.4 = 0; PORTA.5 = 0; PORTA.6 = channel & 0x02; PORTA.7 = channel & 0x01; caltime = 0; caltemp = 120-(i%4)*30; while(caltime < 200) { if (LineCount==231) { Ain0 = ADCH; if(Ain0 < 10) sprintf(lcd_buffer,"00%d",Ain0); else if(Ain0 < 100) sprintf(lcd_buffer,"0%d",Ain0); else sprintf(lcd_buffer,"%d",Ain0); lcd_gotoxy(12,0); lcd_puts(lcd_buffer); caltemp = (caltemp + Ain0)/2; //gets average value if(caltemp < 10) sprintf(lcd_buffer,"00%d",caltemp); else if(caltemp < 100) sprintf(lcd_buffer,"0%d",caltemp); else sprintf(lcd_buffer,"%d",caltemp); lcd_gotoxy(12,1); lcd_puts(lcd_buffer); ADCSR.6=1; } if(caltime < 40) { //do nothing } else if(caltime < 80) { lcd_gotoxy(7,0); lcd_putsf("."); } else if(caltime < 120) { lcd_gotoxy(8,0); lcd_putsf("."); } else if(caltime < 160) { lcd_gotoxy(9,0); lcd_putsf("."); } else if(caltime < 200) { lcd_gotoxy(10,0); lcd_putsf("."); } } calnote[i] = caltemp; } lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Notes:"); //the main loop while(1) { if (LineCount==231) { //Play a note //TCCR0 bits: //bit 7 no force: //bit 3 CTC on: //bit 5,4 toggle OC0 pin //bit 6 no PWM //bit 2-0 prescaler 256 so 1 tick is 16 microsec musicT = 0; TCCR0 = 0; if(notes[note] != 0) TCCR0 = 0b00011100; OCR0 = notes[note+7*octave]; //get the appropriate octave value //codes for channel 3 //channel 3 is used for switching between high and low octave if(channel == 0x03 && muxcounter > muxdelay-5) { if(ADCH > 50) { octave = 1; lcd_gotoxy(14,0); lcd_putsf("H"); } else { octave = 0; lcd_gotoxy(14,0); lcd_putsf("L"); } } //codes for channel 1 //channel 1 is used for input of the first 4 notes if(channel == 0x01 && muxcounter > muxdelay-5) { lastAin0[4]=lastAin0[3]; lastAin0[3]=lastAin0[2]; lastAin0[2]=lastAin0[1]; lastAin0[1]=lastAin0[0]; lastAin0[0]=ADCH; if(lastAin0[0] < lastAin0[1] && lastAin0[1] < lastAin0[2] && lastAin0[2] < lastAin0[3]) { //do nothing } else if(lastAin0[0] > lastAin0[1] && lastAin0[1] > lastAin0[2] && lastAin0[2] > lastAin0[3]) { //do nothing } else { Ain0 = lastAin0[0]; if(Ain0 < 10) sprintf(lcd_buffer,"00%d",Ain0); else if(Ain0 < 100) sprintf(lcd_buffer,"0%d",Ain0); else sprintf(lcd_buffer,"%d",Ain0); lcd_gotoxy(10,0); lcd_puts(lcd_buffer); } if(0<Ain0 && Ain0<(calnote[3]+calnote[2])/2) { note=4; c1pressed = 1; } else if((calnote[3]+calnote[2])/2<Ain0 && Ain0<(calnote[2]+calnote[1])/2) { note=3; c1pressed = 1; } else if((calnote[2]+calnote[1])/2<Ain0 && Ain0<(calnote[1]+calnote[0])/2) { note=2; c1pressed = 1; } else if((calnote[1]+calnote[0])/2<Ain0 && Ain0<200) { note=1; c1pressed = 1; } else { c1pressed = 0; } } //codes for channel 2 //channel 2 is used for input of the last 4 keys if(channel == 0x02 && muxcounter > muxdelay-5) { lastAin1[4]=lastAin1[3]; lastAin1[3]=lastAin1[2]; lastAin1[2]=lastAin1[1]; lastAin1[1]=lastAin1[0]; lastAin1[0]=ADCH; if(lastAin1[0] < lastAin1[1] && lastAin1[1] < lastAin1[2] && lastAin1[2] < lastAin1[3]) { //do nothing } else if(lastAin1[0] > lastAin1[1] && lastAin1[1] > lastAin1[2] && lastAin1[2] > lastAin1[3]) { //do nothing } else { Ain1 = lastAin1[0]; if(Ain1 < 10) sprintf(lcd_buffer,"00%d",Ain1); else if(Ain1 < 100) sprintf(lcd_buffer,"0%d",Ain1); else sprintf(lcd_buffer,"%d",Ain1); lcd_gotoxy(10,0); lcd_puts(lcd_buffer); } if(0<Ain1 && Ain1<(calnote[7]+calnote[6])/2) { note=8; c2pressed = 1; } else if((calnote[7]+calnote[6])/2<Ain1 && Ain1<(calnote[6]+calnote[5])/2) { note=7; c2pressed = 1; } else if((calnote[6]+calnote[5])/2<Ain1 && Ain1<(calnote[5]+calnote[4])/2) { note=6; c2pressed = 1; } else if((calnote[5]+calnote[4])/2<Ain1 && Ain1<200) { note=5; c2pressed = 1; } else { c2pressed = 0; } } if(c1pressed == 0 && c2pressed == 0) note = 0; light(note); //display lights on LED panel //the following codes determine whether notes have to be sent to serial //comm. for midi endocing if(note == 0) { if(lastnton == 0) { //do nothing } else { ntt = time; nt = lastnt; nton = 0; lastnton = 0; lastnt = nt; shownote(); time = 0; } } else { if(lastnt == note && lastnton == 1) { //do nothing } else { ntt = time; nt = lastnt; nton = 0; shownote(); time = 0; ntt = time; nt = note; nton = 1; lastnton = 1; lastnt = note; shownote(); time = 0; lcdnotes[3] = lcdnotes[2]; lcdnotes[2] = lcdnotes[1]; lcdnotes[1] = lcdnotes[0]; lcdnotes[0] = note; lcd_gotoxy(2,1); printlcd(lcdnotes[3]); lcd_gotoxy(4,1); printlcd(lcdnotes[2]); lcd_gotoxy(6,1); printlcd(lcdnotes[1]); lcd_gotoxy(8,1); printlcd(note); } } //increment timer for channel switching muxcounter++; //start another conversion ADCSR.6=1; } //line 231 if(muxcounter == muxdelay) { muxcounter = 0; channel += 0x01; if(channel > 0x03) channel = 0x01; //set appropriate values for capacitive sensor channel selection PORTA.3 = 0; PORTA.4 = 0; PORTA.5 = 0; PORTA.6 = channel & 0x02; PORTA.7 = channel & 0x01; } } //while } //main |