/********************************************************** * Joel Ong (jyo2), Frank Chen (flc23), Justin Leow (jl574) * ECE 4760 Final Project * Synthesizer * Friday Lab **********************************************************/ #include #include #include #include #include #include #include // Timeout values #define t1 1 #define t2 50 #define mSec 20 #define clockFreq 20000 #define cooldown 50 // Debounce States #define NoPluck 0 #define Plucked 1 #define MaybeNoPluck 2 // Subroutines void debounce(void); void modulate(void); void initialize(void); void pluck(unsigned char); void stop(unsigned char); unsigned char getFret(unsigned char); // Task scheduling timeout counters volatile unsigned char time1; volatile unsigned char time2; volatile unsigned char msCount; // States unsigned char state[6]; unsigned char cdCount[6]; // Karplus Strong, DDS and ADC Variables #define p 256 unsigned char delayLength[6][5]; volatile unsigned char sr[6][p]; volatile unsigned char in[6]; volatile unsigned char out[6]; volatile unsigned char signal[6]; unsigned char noise[p]; unsigned char fret[6]; unsigned char Ain; //raw A to D number unsigned char threshold[] = {150,150,150,150,150,150}; double freq[6][5]= {{82.41, 87.31, 92.50, 98.00, 103.83}, {110.0, 116.54, 123.47, 130.81, 138.59}, {146.83,155.56, 164.81, 174.61, 185.00}, {196.0, 207.65, 220.00, 233.08, 246.94}, {246.94,261.63, 277.18, 293.66, 311.13}, {329.63,349.23, 369.99, 392.00, 415.30}}; /********************************************************** * Timer 1 Compare Match ISR **********************************************************/ ISR (TIMER1_COMPA_vect) { // Karplus-Strong algorithm iteration for each string for (unsigned char str=0; str<6; str++) { sr[str][in[str]] = ((sr[str][in[str]]+sr[str][out[str]]))>>1; unsigned char length = delayLength[str][fret[str]]; if (++in[str]==length-1) in[str]=0; if (++out[str]==length-1) out[str]=0; signal[str] = sr[str][in[str]]; } unsigned int output = 0; for (unsigned char i=0; i<6; i++) { output+=signal[i]; } OCR0A = output>>3; } /********************************************************** * Timer 2 Compare Match ISR **********************************************************/ ISR (TIMER2_COMPA_vect) { if (time1) time1--; if (time2) time2--; } /********************************************************** * Entry Point and Task Scheduler Loop **********************************************************/ int main(void) { initialize(); while(1) { if (!time1) { time1=t1; debounce(); } if (!time2) { time2=t2; modulate(); } } } /********************************************************** * Debounce Task - debounces signals from vibration sensors **********************************************************/ void debounce(void) { ADMUX = 0b01100000; for (unsigned char str=0; str<6; str++) { ADCSRA |= (1<threshold[str]; // Determine next debounce state switch (state[str]) { case NoPluck: if (asserted) { pluck(str); state[str]=Plucked; cdCount[str] = cooldown; } break; case Plucked: if (!asserted) state[str]=MaybeNoPluck; if (cdCount[str]) cdCount[str]--; break; case MaybeNoPluck: if (asserted) state[str]=Plucked; else if (!cdCount[str]) state[str]=NoPluck; else cdCount[str]--; break; } Ain=0; ADMUX++; } } /********************************************************** * Pitch Modulation Task **********************************************************/ void modulate(void) { for (unsigned char str=0; str<6; str++) { // Sample fretted button fret[str] = getFret(str); } } /********************************************************** * Returns the fretted button (0-4) on the specified string **********************************************************/ unsigned char getFret(unsigned char str) { switch (str) { case 0: if (PIND & 0x08) return 4; else if (PINA & 0x40) return 3; else if (PIND & 0x02) return 2; else if (PIND & 0x01) return 1; break; case 1: for (unsigned char f = 4; f>=1; f--) if (PIND & 0x10<<(f-1)) return f; break; case 2: for (unsigned char f = 4; f>=1; f--) if (PINC & 0x01<<(f-1)) return f; break; case 3: for (unsigned char f = 4; f>=1; f--) if (PINC & 0x10<<(f-1)) return f; break; case 4: if (PINA & 0x80) return 4; else if (PINB & 0x04) return 3; else if (PINB & 0x02) return 2; else if (PINB & 0x01) return 1; break; case 5: for (unsigned char f = 4; f>=1; f--) if (PINB & 0x10<<(f-1)) return f; break; } return 0; } /********************************************************** * Pluck string **********************************************************/ void pluck(unsigned char str) { fret[str] = getFret(str); // Sample fretted button // Recycle noise generated in initialization for (int i=0; i