//Final Project //electrical connections: //PORTA -> Microphone input //PORTB -> Output of sine waves for speakers //PORTC -> 2x17 Line LCD disp //PORTD -> 4 buttons (4-7) /* Use an 2x16 alphanumeric LCD connected to PORTC as follows: [LCD pin] [8515] 1 GND - GND 2 +5V - Vcc 3 VLC 10k trimpot wiper (trimpot ends go to +Vcc and GND) 4 RS - PC0 5 RD - PC1 6 EN - PC2 11 D4 - PC4 12 D5 - PC5 13 D6 - PC6 14 D7 - PC7 */ /* PORTD PORTD.4 - Back PORTD.5 - Up PORTD.6 - Down PORTD.7 - Select */ /*PORTA - Microphone input will be run through the internal A to D converter */ /*PORTB Outputs a sine wave which will be converted by an external D to A converter so that it can be played by a set of speakers. */ //Note the pragma to turn off automatic register allocation //in the compiler config dialog so that C variables are //available to the assembler #include #include //for debugging using printf, etc #include #include //tell the lib that the lcd is on port C #asm .equ __lcd_port=0x15 #endasm #include //handles LCD functions //timeout values for each task #define t1 30 #define t2 127 //I like these definitions #define begin { #define end } #define LCDwidth 16 //characters //timer 1 constants #define prescale1 1 #define clear_on_match 8 //Define states for the keypad state machine #define maybePush 1 #define Push 2 #define maybeNoPush 3 #define NoPush 4 //used to determine loud and quiet thresholds, make sure that we are not just reading noise #define loudThreshold 100 //a little bit more than 1000mV, we were unalbe to get the speakers loud enough #define quietThreshold 100 //a little bit more than 100mV #define maxADC 1023 //maximum output for the A to D converter //the subroutines void task1(void); //test for button press void task2(void); //handle user commands void initialize(void); //all the usual mcu stuff void sineWave(unsigned int delayLoops); //mathod used for creating sine waves at given frequencies void Analyze(unsigned char bands); //method used for analyzing the recieved frequencies to determine the frequency response #pragma regalloc- //following variables must not be registers unsigned char reload; //timer 0 reload to set 1 mSec unsigned char time1, time2; //task scheduleing timeout counters #pragma regalloc+ unsigned char displayState; //The current display of the LCD unsigned char debounceState; //Holds the current state for debouncing the keypad unsigned char Button; //Used to determine what action will take place unsigned char useButton; //variable for keeping the debounced input button char lcd_buffer[17]; // LCD display buffer unsigned int delayLoops; //how many times to execute a loop between samples float floatdelayLoops; //used for getting better precision unsigned int frequency; //the frequency to output unsigned char error; //a flag for speakers being too loud or too quiet //unsigned long delay; //do we need this????????? unsigned char adjustindex; //index of the frequency response table unsigned char i; //used for many loops unsigned char temp; //a temporary register used for the buttons unsigned long tempresult; //used for temporarily holding the value of the A to D converter long result; //holds the value of the A to D converter long sumresult; //holds the sum of the 8 A to D samples float meanResponse; //the average of the 8 A to D readings float DCbias; //holds the value of the DC offset of the microphone float DCbiasTemp; //used for temporarily holding the value of the A to D converter when averaging the DC bias //used for debugging char buffer[21]; //used for frequency response float resultTable [31]; //the value of the A to D converter for each frequency reproduced float differenceTable [31]; //holds the value of the result minus the DC offset float adjustTable [31]; //holds the value of the frequency response converted to decibels to aid in adjusting a graphic eq //used for the number of bands unsigned char bands; //the current number of bands being tested unsigned char band_index; //the index to the array of bands //normal number of bands used in graphic eq's flash unsigned char bandtable[5] = {7, 9, 10, 15, 31}; //the frequencies used in each type of graphic equalizer flash unsigned long sevenBands [7] = {60, 200, 560, 1100, 2200, 4500, 10000}; flash unsigned long nineBands [9] = {63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000}; flash unsigned long tenBands [10] = {60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000}; flash unsigned long fifteenBands [15] = {25, 40, 63, 100, 160, 250, 400, 630, 1000, 1600, 2500, 4000, 6300, 10000, 16000}; flash unsigned long thirtyoneBands [31] = {20, 25, 32, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000, 20000}; //tables used to compensate for mic frequency response flash unsigned long micSevenTable [7] = {0, 0, 0, 0, 0, 0, 0}; flash unsigned long micNineTable [9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; flash unsigned long micTenTable [10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; flash unsigned long micFifteenTable [15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; flash unsigned long micThirtyoneTable [31] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //********************************************************** //timer 0 overflow ISR interrupt [TIM0_OVF] void timer0_overflow(void) { //reload to force 1 mSec overflow TCNT0=reload; //Decrement the two times if they are not already zero if (time1>0) --time1; if (time2>0) --time2; } //********************************************************** //timer 1 compare-match A ISR //allows each frequnecy to be played for 1 second interrupt [TIM1_COMPA] void cmpA_overflow(void){ #asm ;shut off timer 1 interrupt ;TCCR1B = 0x00; //stops timer 1 so that the interrupt is triggered only once each time ldi r21, 0x00 out 0x2e, r21 ;stopflag for sine wave ldi r21, 0x01 #endasm }//timer 1 interrupt */ //********************************************************** //Entry point and task scheduler loop void main(void) begin initialize(); while(1) begin if (time1==0) task1(); if (time2==0) task2(); end end //********************************************************** //********************************************************** //Task 1 -- detect a pusbutton void task1(void) { time1 = t1; temp = PIND|0x0f; //we are only using the upper 4 pins for the 4 buttons, thia allows us to disregard the lower 4 //debouncing state machine switch (debounceState) { case maybePush: if(temp != 0xff){ useButton = temp; debounceState = Push; } else debounceState = NoPush; break; case Push: if(temp != 0xff) debounceState = Push; else debounceState = maybeNoPush; break; case maybeNoPush: if(temp != 0xff){ debounceState = Push; } else debounceState = NoPush; break; case NoPush: if(temp != 0xff) debounceState = maybePush; break; }//debounce }//task 1 //********************************************************** //Task 2 -- Handles user input from the buttons void task2(void) { time2 = t2; Button = useButton&0xf0; //eliminate the lower 4 buttons since we only care about the upper 4 switch(Button){ case 0x70: //back break; case 0xb0: //up //scroll upwards through the number of bands available to analyze when at the start menu if(displayState == 0){ if(band_index <4){ //make sure that we are still in the bounds of the table band_index++; bands = bandtable[band_index]; //LCD stuff to display number of bands to test lcd_gotoxy(0,0); lcd_putsf(" "); lcd_gotoxy(0,0); itoa(bands,lcd_buffer); lcd_puts(lcd_buffer); useButton = 0; //resets the action }//inner if }//outer if //if we have finished analyzing and the speakers were at an appropriate level, scroll upwards through the responses of the frequencies else if ((displayState ==1) && (error == 0)){ if(adjustindex <(bands-1)) adjustindex ++; lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); //used to display the appropriate frequency and its response switch(bands){ case 7: ltoa(sevenBands[adjustindex], lcd_buffer); break; case 9: ltoa(nineBands[adjustindex], lcd_buffer); break; case 10: ltoa(tenBands[adjustindex], lcd_buffer); break; case 15: ltoa(fifteenBands[adjustindex], lcd_buffer); break; case 31: ltoa(thirtyoneBands[adjustindex], lcd_buffer); break; }//switch lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf(" "); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); useButton = 0; }//else if break; case 0xd0: //down //scroll downwards through the number of bands available to analyze when at the start menu if(displayState == 0){ if(band_index >0){ band_index--; bands = bandtable[band_index]; //LCD stuff lcd_gotoxy(0,0); lcd_putsf(" "); lcd_gotoxy(0,0); itoa(bands,lcd_buffer); lcd_puts(lcd_buffer); useButton = 0; }//inner if }//outer if //if we have finished analyzing and the speakers were at an appropriate level, scroll downwards through the responses of the frequencies else if ((displayState ==1) && (error == 0)){ if(adjustindex >0) adjustindex --; lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); switch(bands){ case 7: ltoa(sevenBands[adjustindex], lcd_buffer); break; case 9: ltoa(nineBands[adjustindex], lcd_buffer); break; case 10: ltoa(tenBands[adjustindex], lcd_buffer); break; case 15: ltoa(fifteenBands[adjustindex], lcd_buffer); break; case 31: ltoa(thirtyoneBands[adjustindex], lcd_buffer); break; }//switch lcd_puts(lcd_buffer); lcd_gotoxy(0,1); lcd_putsf(" "); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); useButton = 0; }//else if break; case 0xe0: //select if(displayState == 0){ displayState = 1; //enable the display results case lcd_gotoxy(9,0); lcd_putsf(" "); //sample and average values from the A to D converter to get the DC offset for(i=0; i<7; i++){ ADCSR = 0xc0; DCbias = ADCL; DCbiasTemp = ADCH; DCbias = (long)DCbias | ((long)DCbiasTemp <<8); ADCSR = 0x80; }//for DCbias = DCbias/8; //cycle through the frequencies for a given number of bands and analyze the results switch(bands){ case 7: for(i=0; i<7; i++){ frequency = sevenBands[i]; floatdelayLoops = ( 500000.0/(frequency) - 10.0) /7.0; delayLoops = floatdelayLoops; floatdelayLoops -= delayLoops; //used to round the delay time to the nearest integer if (floatdelayLoops >= .5) delayLoops ++; printf("\r\nFrequency:%u\r\n",frequency); printf("\r\nDelay Loops%u\r\n",delayLoops); //turn off timer 0 so that no tasks are run, will just produce and analyze TCCR0 = 0; lcd_gotoxy(0,1); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,1); ltoa(frequency, lcd_buffer); lcd_puts(lcd_buffer); sineWave(delayLoops); resultTable[i] = result; }//for //frequency calculations Analyze(bands); //turn timer 0 back on TCCR0=3; useButton = 0; //if the speakers are not too loud or quiet, display the results if(error == 0){ adjustindex = 0; lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); ltoa(sevenBands[adjustindex], lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); }//if //if the speakers are too loud or soft, tell the user to adjust them and wait for enter to be pressed else{ lcd_clear(); lcd_gotoxy(0,0); if(error = 1) lcd_putsf("Too quiet"); else lcd_putsf("Too loud"); lcd_gotoxy(0,1); lcd_putsf("Press Enter"); }//else break; case 9: for(i=0; i<9; i++){ frequency = nineBands[i]; floatdelayLoops = ( 500000.0/(frequency) - 10.0) /7.0; delayLoops = floatdelayLoops; floatdelayLoops -= delayLoops; //used to round the delay time to the nearest integer if (floatdelayLoops >= .5) delayLoops ++; printf("\r\nFrequency:%u\r\n",frequency); printf("\r\nDelay Loops%u\r\n",delayLoops); TCCR0 = 0; lcd_gotoxy(0,1); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,1); ltoa(frequency, lcd_buffer); lcd_puts(lcd_buffer); sineWave(delayLoops); resultTable[i] = result; }//for //frequency calculations Analyze(bands); //turn timer 0 back on TCCR0=3; useButton = 0; if(error == 0){ adjustindex = 0; lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); ltoa(nineBands[adjustindex], lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); }//if else{ lcd_clear(); lcd_gotoxy(0,0); if(error = 1) lcd_putsf("Too quiet"); else lcd_putsf("Too loud"); lcd_gotoxy(0,1); lcd_putsf("Press Enter"); }//else break; //9 bands case 10: for(i=0; i<10; i++){ frequency = tenBands[i]; floatdelayLoops = ( 500000.0/(frequency) - 10.0) /7.0; delayLoops = floatdelayLoops; floatdelayLoops -= delayLoops; //used to round the delay time to the nearest integer if (floatdelayLoops >= .5) delayLoops ++; printf("\r\nFrequency:%u\r\n",frequency); printf("\r\nDelay Loops%u\r\n",delayLoops); TCCR0 = 0; lcd_gotoxy(0,1); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,1); ltoa(frequency, lcd_buffer); lcd_puts(lcd_buffer); sineWave(delayLoops); resultTable[i] = result; }//for //frequency calculations Analyze(bands); //turn timer 0 back on TCCR0=3; useButton = 0; if(error == 0){ adjustindex = 0; lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); ltoa(tenBands[adjustindex], lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); }//if else{ lcd_clear(); lcd_gotoxy(0,0); if(error = 1) lcd_putsf("Too quiet"); else lcd_putsf("Too loud"); lcd_gotoxy(0,1); lcd_putsf("Press Enter"); }//else break; //10 bands case 15: for(i=0; i<15; i++){ frequency = fifteenBands[i]; floatdelayLoops = ( 500000.0/(frequency) - 10.0) /7.0; delayLoops = floatdelayLoops; floatdelayLoops -= delayLoops; //used to round the delay time to the nearest integer if (floatdelayLoops >= .5) delayLoops ++; TCCR0 = 0; lcd_gotoxy(0,1); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,1); ltoa(frequency, lcd_buffer); lcd_puts(lcd_buffer); sineWave(delayLoops); resultTable[i] = result; }//for //frequency calculations Analyze(bands); //turn timer 0 back on TCCR0=3; useButton = 0; if(error == 0){ adjustindex = 0; lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); ltoa(fifteenBands[adjustindex], lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); }//if else{ lcd_clear(); lcd_gotoxy(0,0); if(error = 1) lcd_putsf("Too quiet"); else lcd_putsf("Too loud"); lcd_gotoxy(0,1); lcd_putsf("Press Enter"); }//else break; //15 bands case 31: for(i=0; i<31; i++){ frequency = thirtyoneBands[i]; floatdelayLoops = ( 500000.0/(frequency) - 10.0) /7.0; delayLoops = floatdelayLoops; floatdelayLoops -= delayLoops; //used to round the delay time to the nearest integer if (floatdelayLoops >= .5) delayLoops ++; TCCR0 = 0; lcd_gotoxy(0,1); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,1); ltoa(frequency, lcd_buffer); lcd_puts(lcd_buffer); sineWave(delayLoops); resultTable[i] = result; }//for //frequency calculations Analyze(bands); //turn timer 0 back on TCCR0=3; useButton = 0; if(error == 0){ adjustindex = 0; lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Freq: Hz"); lcd_gotoxy(6,0); ltoa(thirtyoneBands[adjustindex], lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(0,1); itoa((adjustindex+1), lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf("/"); itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" "); ftoa(adjustTable[adjustindex], 1, lcd_buffer); lcd_puts(lcd_buffer); lcd_putsf(" dB"); }//if else{ lcd_clear(); lcd_gotoxy(0,0); if(error = 1) lcd_putsf("Too quiet"); else lcd_putsf("Too loud"); lcd_gotoxy(0,1); lcd_putsf("Press Enter"); }//else break; //31 bands }//switch }//if //if we have analyzed the reponse, reset the display and get ready for the next selection else if (displayState == 1){ error = 0; displayState = 0; useButton = 0; bands = bandtable[band_index]; lcd_clear(); //clear the display lcd_gotoxy(0,0); //print next stuff at position 0, line 0 itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(3,0); lcd_putsf("Bands (+/-)"); //string from flash lcd_gotoxy(0,1); //position to beginning of bottow row lcd_putsf("Enter begins"); //another string from flash }//else if break; }//switch }//task2 //********************************************************** //infinite loop to create sine wave void sineWave(unsigned int delayLoops){ #asm ;pushing all of the registers onto the stack to save their contents push r0 push r1 push r2 push r3 push r4 push r5 push r6 push r7 push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 push r16 push r17 push r18 push r19 push r20 push r21 push r22 push r23 push r24 push r25 push r28 push r29 push r30 push r31 ;Z=delayLoops ldd r30,y+0 ;R30=LSB a ldd r31,y+1 ;R31=MSB a push r26 push r27 ;load sample values into registers 5-20 to save time ldi r20, 0x80 mov r5, r20 ldi r20, 0xb1 mov r6, r20 ldi r20, 0xda mov r7, r20 ldi r20, 0xf6 mov r8, r20 ldi r20, 0xff mov r9, r20 ldi r20, 0xf6 mov r10, r20 ldi r20, 0xda mov r11, r20 ldi r20, 0xb1 mov r12, r20 ldi r20, 0x80 mov r13, r20 ldi r20, 0x4f mov r14, r20 ldi r20, 0x26 mov r15, r20 ldi r20, 0x0a mov r16, r20 ldi r20, 0x00 mov r17, r20 ldi r20, 0x0a mov r18, r20 ldi r20, 0x26 mov r19, r20 ldi r20, 0x4f ;TCNT1 = 0; //zeroes timer 1 ldi r21, 0x00; ;write hi then lo out 0x2d, r21 ;TCNT1H out 0x2c, r21 ;TCNT1L ;TCCR1B = 0x0c; //start timer 1, use clk/256 and enables timer to reset itself ldi r21, 0x0c out 0x2e, r21 ;TCCR1B ldi r21, 0x00 ;zero this value (the flag to stop producing sinewaves) firstsample: ;sinetable[16]={0x80, 0xb1, 0xda, 0xf6, 0xff, 0xf6, 0xda, 0xb1, 0x80, 0x4f, 0x26, 0x0a, 0x00, 0x0a, 0x26, 0x4f}; ;set portb = sintable[0] use immediate valuse to speed things up out 0x18, r5 ; takes 1 cycle ;delay(delayLoops) waits the calculated time to create the appropriate frequency ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample0loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end0loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample0loop;do while again takes 2 cycles end0loop: ;no ops placed between every sample except the last to make all samples equally spaced nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;the above code is repeated fifteen times and the restarted ;set portb = sintable[1] out 0x18, r6 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample1loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end1loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample1loop;do while again takes 2 cycles end1loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[2] out 0x18, r7 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample2loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end2loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample2loop;do while again takes 2 cycles end2loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[3] out 0x18, r8 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample3loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end3loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample3loop;do while again takes 2 cycles end3loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[4] out 0x18, r9 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample4loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end4loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample4loop;do while again takes 2 cycles end4loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[5] out 0x18, r10 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample5loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end5loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample5loop;do while again takes 2 cycles end5loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[6] out 0x18, r11 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample6loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end6loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample6loop;do while again takes 2 cycles end6loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[7] out 0x18, r12 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample7loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end7loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample7loop;do while again takes 2 cycles end7loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[8] out 0x18, r13 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample8loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end8loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample8loop;do while again takes 2 cycles end8loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[9] out 0x18, r14 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample9loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end9loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample9loop;do while again takes 2 cycles end9loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[10] out 0x18, r15 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample10loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end10loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample10loop;do while again takes 2 cycles end10loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[11] out 0x18, r16 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample11loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end11loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample11loop;do while again takes 2 cycles end11loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[12] out 0x18, r17 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample12loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end12loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample12loop;do while again takes 2 cycles end12loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[13] out 0x18, r18 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample13loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end13loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample13loop;do while again takes 2 cycles end13loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[14] out 0x18, r19 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample14loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end14loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample14loop;do while again takes 2 cycles end14loop: nop; takes 1 cycle nop; takes 1 cycle nop; takes 1 cycle ;set portb = sintable[15] out 0x18, r20 ;takes 1 cycle ;delay(delayLoops) ;set X=0 ldi r26, 0x00 ;lsb takes 1 cycle ldi r27, 0x00 ;msb takes 1 cycle ;while (X!=Z) X++ sample15loop: cp r26, r30 ;compare the lower bits takes 1 cycle cpc r27, r31 ;compare the upper bits takes 1 cycle breq end15loop ;if equal then end takes 1or2 cycles (2 if executed) adiw r26,1 ;increment X by one takes 2 cycles rjmp sample15loop;do while again takes 2 cycles end15loop: ;stopflag ;stop producing sinewave if r21 = 0x01 sbrs r21, 0; skip the next instruction if r21.0 is 1 takes 1or2or3 cycles rjmp firstsample ; takes 2 cycles ;restore registers pop r27 pop r26 pop r31 pop r30 pop r29 pop r28 pop r25 pop r24 pop r23 pop r22 pop r21 pop r20 pop r19 pop r18 pop r17 pop r16 pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop r7 pop r6 pop r5 pop r4 pop r3 pop r2 pop r1 pop r0 #endasm //take 8 samples from the A to D converter and average them to get the raw response sumresult = 0; ADCSR = 0xe0; result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = ADCL; tempresult = ADCH; sumresult = sumresult + (result | (tempresult <<8)); result = sumresult/8; //check if the speakers are too loud if((result + loudThreshold) >= maxADC) error = 2; }//sineWave //********************************************************** //Set it all up void initialize(void) begin //set up the ports DDRD=0x08; // PORT D is an input for keypad PORTD=0xff; //turn on pull-ups DDRB=0xff; // PORT B is an ouput d/a conv DDRC=0xff; //PORT C is an output PORTB=127; //sets the port to the middle value so that there is no jump when the samples begin //serial setop for debugging using printf, etc. UCSRB = 0x10 + 0x08; UBRR = 51; //set up timer 0 reload=256-125; //value for 1 Msec TCNT0=reload; //preload timer 1 so that is interrupts after 1 mSec. TCCR0=3; //prescalar to 64 TIMSK=0x01; //turn on timer 0 overflow ISR //set up timer 1 //1second/256=31250=0x7a12 TCCR1A = 0; //timer control register (no pwm, no output) TIMSK=TIMSK | 0x10; //turn on timer 1 compare match interrupt OCR1A = 0x7a12; //set number to count to (1 sec) TCCR1B = 0x00; //makes timer1 begin in stopped mode TCNT1 = 0; //and zero the timer //set up A to D converter stuff ADCSR = 0b10000000; //turns on AtoD conerter and uses 2 as a prescaler ADMUX = 0b01000000; //use Vcc as reference and write adjust the results and convert from ADC 0 //init the task timers time1=t1; time2=t2; //init program state error = 0; sumresult = 0; band_index = 0; bands = bandtable[band_index]; useButton = 0; debounceState = NoPush; //start the debounce state machine in no push state displayState = 0; // initialize the LCD for 16 char wide lcd_init(LCDwidth); //initialize the display lcd_clear(); lcd_gotoxy(0,0); lcd_putsf("Freq Response"); lcd_gotoxy(0,1); lcd_putsf("Version 1.1"); //display start up message before the normal main menu for(delay=0; delay<500000; delay++); //normal display lcd_clear(); //clear the display lcd_gotoxy(0,0); //print next stuff at position 0, line 0 itoa(bands, lcd_buffer); lcd_puts(lcd_buffer); lcd_gotoxy(3,0); lcd_putsf("Bands (+/-)"); //string from flash lcd_gotoxy(0,1); //position to beginning of bottow row lcd_putsf("Enter begins"); //another string from flash //for debugging purposes putsf("\r\nStart\r\n"); ADCSR = 0xc0; //crank up the ISRs #asm sei #endasm end void Analyze(unsigned char bands){ //putsf("\r\nDCbias\r\n"); //ftoa(DCbias, 1, buffer); //puts(buffer); //putsf("\r\nResult-DC\r\n"); for(i=0; i