/****************************** ECE 476: Final Project John Del Gaizo(jcd44) Thidanun Saensuksopa(ts295) ******************************/ #include #include #include #include #include // for sine #include #include #include #include #include #include #include #include #include //********NON BLOCKING PRINTING AND STORING VARIABLES ******************** //RXC ISR variables unsigned char r_index =0; //current string index unsigned char r_buffer[16]; //input string unsigned char r_ready; //flag for receive done unsigned char r_char; //current character //TX empth ISR variables unsigned char t_index; //current string index unsigned char t_buffer[16]; //output string unsigned char t_ready; //flag for transmit done unsigned char t_char; //current character unsigned char nonote; //*************************DDS VARIABLES******************************** unsigned long accumulator @0x200; unsigned char highbyte @0x203; //the HIGH byte of the accumulator variable unsigned long increment; //note will eventually come from user char sineTable[256] @0x100; //need loc to avoid glitch unsigned long time, timeriff, absolutetime, filtertime; //time = time of the program char amp, count; int numnote, numnoteplay; char saveriff[2]; char builtin; unsigned int startnote[100], finnote[100], freq[100]; unsigned int length; unsigned char riff[100], octave[100]; unsigned char user_input[15]; //*********************FILTER VARIABLES************************ float fIn, cIn ; //an input float char fInString[16]; unsigned char numsample, findex; int cInFix, fInFix, prod, macprod, junk; long filtvariable; float rmsout, rmsin, rmsin1; float out; float ratio, ratios, ratiob; char sample, its_time, dontsample; int Ain[128]; //raw A to D number int temp; int ms, led; char flag, samplef; //************************DATA VARIABLES******************** char validinput, choose_song, fail, noterest; int index, notedisplay; enum filternote {evlow,fvlow,fsvlow,gvlow,gsvlow,avlow,asvlow,bvlow,cvlow,csvlow,dvlow,dsvlow, elow,flow,fslow,glow,gslow,alow,aslow,blow,clow,cslow,dlow,dslow, emed,fmed,fsmed,gmed,gsmed,amed,asmed,bmed,cmed,csmed,dmed,dsmed, ehi,fhi,fshi,ghi}note; enum songtoplay {song1, song2}song; enum programstate {toriff, tofilter, tobackground}pstate; enum songmode {slow, beat}mode; char nonote_count, wrongnote_count, rightnote_count, numnotefilter; //***************End of Test Variables**************************** //****INITIALIZE SUBROUTINE************ void initialize(void); void getbackground(void); void getriff(void); void getfreq(void); void gets_int(void); void puts_int(void); //***************ISR******************************** interrupt [TIM0_OVF] void sgen(void) begin //the DDR code and scaling accumulator = accumulator + increment ; OCR0 = 128 + sineTable[highbyte] >> amp ; //generate rising amplitude // 62 counts is about 1 mSec if(count > 0) count--; if (0 == count ) begin count=countMS; time++; //in mSec absolutetime++; end end //end ISR //************************************************************ interrupt [TIM1_OVF] void voicegen(void) begin if(note == evlow || note == fvlow ) samplef = 38; else if(note == fsvlow) samplef = 36; else if(note == gvlow || note == gsvlow) samplef = 30; else if(note == avlow) samplef = 26; else if(note == aslow || note == bvlow) samplef = 20; else if(note == glow) samplef = 16; else if(note == gslow || note == cvlow ||note == csvlow ||note == dvlow || note == dsvlow || note == elow ||note == flow || note == fslow) samplef = 15; else if(note == alow ||note == aslow ||note == blow) samplef = 13; else if(note == clow) samplef = 12; else if(note == cslow) samplef = 11; else if(note == dlow) samplef = 10; else if(note == dslow || note == emed) samplef = 9; else if(note == fmed || note == fsmed ||note == gmed || note == gsmed || note == amed) samplef = 8; else if(note == asmed) samplef = 7; else if(note == bmed ||note == cmed ||note == csmed) samplef = 6; else if(note == dmed ||note == dsmed ||note == ehi) samplef = 5; else if(note == fhi ||note == fshi ||note == ghi) samplef = 4; ms++; if(ms==8) begin ms=0; filtertime++; end if(its_time) sample++; if(sample==samplef && its_time) //8-976.5 hz, 4-1953 begin sample=0; //start another conversion temp = ADCH; ADCSR.6=1 ; if(!dontsample) Ain[numsample]=temp>>2; numsample++; if(numsample==128) begin flag=1; numsample=0; end //end if "i==128" thing end end //ISR //********************************************************** interrupt [USART_RXC] void uart_rec(void) begin r_char=UDR; //get a char UDR=r_char; //then print it //build the input string if (r_char != '\r') r_buffer[r_index++]=r_char; else begin putchar('\n'); //use putchar to avoid overwrite r_buffer[r_index]=0x00; //zero terminate r_ready=1; //signal cmd processor UCSRB.7=0; //stop rec ISR end end //******************************************************** //*****UART xmit-empty ISR interrupt [USART_DRE] void uart_send(void) begin t_char = t_buffer[++t_index]; if (t_char == 0) begin UCSRB.5=0; //kill isr t_ready=1; //transmit done end else UDR = t_char ; //send the char end //*********************************************************** //-- non-blocking keyboard check initializes ISR-driven //receive. This routine merely sets up the ISR, which then //does all the work of getting a command. void gets_int(void) begin r_ready=0; r_index=0; UCSRB.7=1; end //************************************************************ // -- 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; if (t_buffer[0]>0) begin putchar(t_buffer[0]); UCSRB.5=1; end end //*********************************************************** //IIR stuff #pragma regalloc- int b1,b2,b3,a2,a3,xn, xn_1, xn_2, yn, yn_1, yn_2 ; #pragma regalloc+ //======================================================== //second order IIR -- "Direct Form II Transposed" // y(n) = b(1)*x(n) + b(2)*x(n-1) + b(3)*x(n-2) // - a(2)*y(n-1) - a(3)*y(n-2) //assumes a(1)=1 // a's and b's need to be global, in RAM and set to fixed point values // also input and output history values //example: // #pragma regalloc- // int b1,b2,b3,a2,a3, xn_1, xn_2, yn_1, yn_2 ; // #pragma regalloc+ // b1=0x0010; // a1=float2fix(-(value from matlab)) // // The following ASM code is equivalent to: // yy=0; yy = macfix(b1,xx,yy); // yy = macfix(b2,xn_1,yy); // yy = macfix(b3,xn_2,yy); // yy = macfix(-a2,yn_1,yy); // yy = macfix(-a3,yn_2,yy); // //update the state variables // xn_2 = xn_1; // xn_1 = xx; // yn_2 = yn_1; // yn_1 = yy; // return yy; int IIR2(int xx) // xx is the current input signal sample // returns the current filtered output sample begin #asm .macro mult_acc ;r31:r30:r24 += r23:r22 * r21:r20 muls r23, r21 ; (signed)ah * (signed)bh add r31, r0 mul r22, r20 ; al * bl add r24, r0 adc r30, r1 adc r31, r27 mulsu r23, r20 ; (signed)ah * bl add r30, r0 adc r31, r1 mulsu r21, r22 ; (signed)bh * al add r30, r0 adc r31, r1 .endm push r20 ;save parameter regs push r21 clr r27 ;permanent zero clr r24 ;clear 24 bit result reg; msb to lsb => r31:r30:r24 clr r30 clr r31 lds R22, _b1 ;load b1 from RAM lds R23, _b1+1 ld R20, Y ;load input parameter xx from stack ldd R21, Y+1 mult_acc ; b1*xx lds R22, _b2 ;load b2 from RAM lds R23, _b2+1 lds R20, _xn_1 ;load x(n-1) from RAM lds R21, _xn_1+1 mult_acc ; b2*x(n-1) lds R22, _b3 ;load b3 from RAM lds R23, _b3+1 lds R20, _xn_2 ;load x(n-2) from RAM lds R21, _xn_2+1 mult_acc ; b3*x(n-2) lds R22, _a2 ;load -a2 from RAM lds R23, _a2+1 lds R20, _yn_1 ;load y(n-1) from RAM lds R21, _yn_1+1 mult_acc ; -a2*y(n-1) lds R22, _a3 ;load -a3 from RAM lds R23, _a3+1 lds R20, _yn_2 ;load y(n-2) from RAM lds R21, _yn_2+1 mult_acc ; -a3*y(n-2) lds R20, _xn_1 ;load x(n-1) from RAM lds R21, _xn_1+1 sts _xn_2, r20 ;store x(n-2) to RAM sts _xn_2+1, R21 ld R20, Y ;load input parameter xx from stack ldd R21, Y+1 sts _xn_1, r20 ;store x(n-1) to RAM sts _xn_1+1, R21 lds R20, _yn_1 ;load y(n-1) from RAM lds R21, _yn_1+1 sts _yn_2, R20 ;store y(n-2) to RAM sts _yn_2+1, R21 sts _yn_1, r30 ;store new output as y(n-1) to RAM sts _yn_1+1, r31 pop r21 ;restore parameter regs pop r20 #endasm end #pragma warn+ //************************************************************ void filter(void) begin while(!flag); dontsample=1; //************************* //for Ab //2-pole butterworth bandpass, fs=976.5, filter cutoff 202-214; for Ab which is 208 hz b1 = float2fix(coeff[index++]); b2 = float2fix(coeff[index++]); b3 = float2fix(coeff[index++]); a2 = float2fix(coeff[index++]); //negate from input a3 = float2fix(coeff[index++]); //negate from input */ //------------- for (findex=10;findex<128;findex++) begin dontsample=1; filtvariable=int2fix(Ain[findex]); out = IIR2(filtvariable); out=fix2float(out); if(out<0) out=-out; rmsout=out+rmsout; rmsin1=Ain[findex]-31; if(rmsin1<0) rmsin1=-rmsin1; rmsin=rmsin1+rmsin; end if(rmsin<40) nonote=1; else nonote=0; ratiob=rmsout; rmsin=0; rmsout=0; numsample=0; //************************************ //for A //2-pole butterworth bandpass, fs=976.5, filter cutoff 214-226; for A which is 220 hz b1 = float2fix(coeff[index++]); b2 = float2fix(coeff[index++]); b3 = float2fix(coeff[index++]); a2 = float2fix(coeff[index++]); //negate from input a3 = float2fix(coeff[index++]); //negate from input //--------- for (findex=10;findex<128;findex++) begin dontsample=1; filtvariable=int2fix(Ain[findex]); out = IIR2(filtvariable); out=fix2float(out); if(out<0) out=-out; rmsout=out+rmsout; rmsin1=Ain[findex]-31; if(rmsin1<0) rmsin1=-rmsin1; rmsin=rmsin1+rmsin; end //printf("rmsin : %f\r\n", rmsin); ratio=rmsout; rmsin=0; rmsout=0; numsample=0; //************************** //for A# //2-pole butterworth bandpass, fs=976.5, filter cutoff 227-239; for A# which is 233 hz b1 = float2fix(coeff[index++]); b2 = float2fix(coeff[index++]); b3 = float2fix(coeff[index++]); a2 = float2fix(coeff[index++]); //negate from input a3 = float2fix(coeff[index++]); //negate from input //---------------- for (findex=10;findex<128;findex++) begin dontsample=1; filtvariable=int2fix(Ain[findex]); out = IIR2(filtvariable); out=fix2float(out); if(out<0) out=-out; rmsout=out+rmsout; rmsin1=Ain[findex]-31; if(rmsin1<0) rmsin1=-rmsin1; rmsin=rmsin1+rmsin; end ratios=rmsout; rmsin=0; rmsout=0; numsample=0; //******************************* if(nonote) begin printf("no note played\n\r"); nonote_count++; end else if(ratio>ratiob && ratio>ratios) begin printf("count it\n\r"); rightnote_count++; end else if(ratiob>ratio && ratiob>ratios) begin printf("low\n\r"); wrongnote_count++; end else if(ratios>ratio && ratios>ratiob) begin printf("high\n\r"); wrongnote_count++; end //************************** //in here make sure it doesn't sample again until doing the next two //put bs and as for one fret above and below and run filter set dontsample to 0 after all of it dontsample=0; numnotefilter++; end //*************************************************************** void main(void) begin int n, i, j, k; initialize(); //********************************** //MAKE YOUR OWN RIFF while(1) begin switch (pstate) begin case toriff: if(choose_song) begin while (!validinput) begin printf("Choose a song(1, 2): "); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == '1') begin validinput = 1; song = song1; notedisplay = 97; end //end song 1 else if(user_input[0] == '2') begin validinput = 1; song = song2; notedisplay = 48; end //end song 1 else begin validinput = 0; printf("Sorry, only song (1, 2)...\r\n"); end end //end while !validinput validinput = 0; end getriff(); printf("The riff: "); if(song == song1) begin for (n = 0; n (rightnote_count + wrongnote_count)) begin printf("PLAY LOUDER or ON BEAT\r\n"); fail = 1; end else if ((rightnote_count >3* wrongnote_count)) begin printf("CONGRATS!!\r\n"); fail = 0; end else if (rightnote_count < 3*wrongnote_count) begin printf("TRY AGAIN...\r\n"); fail = 1; end nonote_count = 0; rightnote_count = 0; wrongnote_count = 0; numnotefilter = 0; if (!fail) begin while (!validinput) begin printf("Play with background music?(y/n): "); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == 'y') begin validinput = 1; pstate = tobackground; end else if(user_input[0] == 'n') begin validinput = 1; printf("Choose a new song(n), hear the riff(h), or test the riff(t)?:"); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == 'n') begin pstate = toriff; choose_song = 1; end else if (user_input[0] == 'h') begin pstate = toriff; choose_song = 0; end else if (user_input[0] == 't') begin pstate = tofilter; end else begin validinput = 0; printf("Sorry, invalid input...\r\n"); end end else begin validinput = 0; printf("Sorry, only yes(y) or no(n)...\r\n"); end end //end while !validinput validinput = 0; end else begin while(!validinput) begin printf("Do you want to choose a new song?(y/n): "); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == 'y') begin validinput = 1; choose_song = 1; pstate = toriff; end else if(user_input[0] == 'n') begin validinput = 1; printf("Hear the riff again(h) or Test the riff again(t): "); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == 'h') begin pstate = toriff; choose_song = 0; end else if (user_input[0] == 't') begin pstate = tofilter; end else begin validinput = 0; printf("Sorry, invalid input...\r\n"); end end else begin validinput = 0; printf("Sorry, only yes(y) or no(n)...\r\n"); end end //end while(!validinput) validinput = 0; end //===============outputting the background========== TIMSK = 0b00000001; TCCR0 = 0b00000001 ; //turn off pwm break; //break case tofilter //=============================================================== case tobackground: TIMSK = 0b00000001; TCCR0 = 0b00000001 ; //turn off pwm getbackground(); j = 0; time = 0; absolutetime = 0; while(absolutetime < timeriff) begin increment =(long)freq[j] * 68719L; //doing the relationship between burst f and increment; if (time == startnote[j]) begin //phase lock the sine gen and timer accumulator = 0; TCNT0 = 0; OCR0 = 0; //generate the amplitude scaling -- start with divide by 2^7 amp = 7; //turn on pwm TCCR0 = 0b01101001 ; end //if (time == beginnote[j]) //*******PWM OUTPUT***************** if (time == startnote[j]+1) amp=6; //ramp up if (time == startnote[j]+2) amp=5; if (time == startnote[j]+3) amp=4; if (time == startnote[j]+4) amp=3; if (time == startnote[j]+5) amp=2; if (time == startnote[j]+6) amp=1; if (time == startnote[j]+7) amp=0; //ramp up if (time == finnote[j]-7) amp=1; if (time == finnote[j]-6) amp=2; //ramp down if (time == finnote[j]-5) amp=3; if (time == finnote[j]-4) amp=4; if (time == finnote[j]-3) amp=5; if (time == finnote[j]-2) amp=6; //ramp down if (time == finnote[j]-1) amp=7; //*******END PWM OUTPUT***************** if (time == finnote[j]) begin j++; if (j == numnote) begin j = 0; time = 0; end end end // end while (aboslutetime< 16000) TIMSK = 0b00000001; TCCR0 = 0b00000001 ; //turn off pwm while (!validinput) begin printf("Play with background music again?(y/n): "); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == 'y') begin validinput = 1; pstate = tobackground; end else if(user_input[0] == 'n') begin validinput = 1; printf("Choose a new song(n), hear the riff(h), or test the riff(t)?:"); scanf("%s", user_input); printf("%s\r\n", user_input); if(user_input[0] == 'n') begin pstate = toriff; choose_song = 1; end else if (user_input[0] == 'h') begin pstate = toriff; choose_song = 0; end else if (user_input[0] == 't') begin pstate = tofilter; end else begin validinput = 0; printf("Sorry, invalid input...\r\n"); end end else begin validinput = 0; printf("Sorry, only yes(y) or no(n)...\r\n"); end end //end while !validinput validinput = 0; break; //break case tobackground end //end switch end //end while(1) end //end main //************************************************************* void getbackground(void) begin int m, count; count = 0; if (song == song1) begin numnote = 32; for(m = 0; m= 0 && count < 8)) begin riff[m] = d; octave[m] = verylow; count++; end else if((count >= 8 && count < 16)) begin riff[m] = a; octave[m] = verylow; count++; end else if((count >= 16 && count < 24)) begin riff[m] = b; octave[m] = verylow; count++; end else if((count >= 24 && count < 32)) begin riff[m] = g; octave[m] = verylow; count++; end if(m == 0) startnote[0] = 1; startnote[m] = finnote[m-1] + 1; finnote[m] = startnote[m] + quarter - 1; end //end for //=========================================== end//end song1 else if (song == song2) begin numnote = 4; for(m = 0; m