/* * EEL4746C - AVR Piano - Speaker Section * speaker is connected to PD2 and ground * 15 buttons are connected to PD3-7, PC0-4, PB0-4 * the LCD Arduino UNO is connected to TX/RX (PD0/1) */ #include #include #define T1_PRESCALAR 8 #define FREQ(f) (16e6 / f / T1_PRESCALAR / 2) #define P_RX 0 #define P_TX 1 #define P_SPKR 2 unsigned short freqs[] = { FREQ(100), FREQ(200), FREQ(250), FREQ(300), FREQ(350), FREQ(400), FREQ(500), FREQ(600), FREQ(700), FREQ(750), FREQ(1000), FREQ(1250), FREQ(1500), FREQ(1750), FREQ(2000), FREQ(3000), FREQ(4000), FREQ(5000), FREQ(6000), FREQ(7000), FREQ(8000), [255] = 0 // used as a 'silent' note }; unsigned char note = 0; ISR (PCINT0_vect) { // check if any button in the whole port is pressed for (unsigned char i = 0; i <= 5; i++) { if (PINB & (1 << i)) { note = i + 5; break; } } } ISR (PCINT1_vect) { // check if any button in the whole port is pressed for (unsigned char i = 0; i <= 5; i++) { if (PINC & (1 << i)) { note = i + 5 + 6; break; } } } ISR (PCINT2_vect) { // check if any button in the whole port is pressed for (unsigned char i = 3; i <= 7; i++) { if (PIND & (1 << i)) { note = i - 3; break; } } } int main(void) { // Data Direction for Buttons, UART, Speaker DDRB = 0x00; DDRC = 0x00; DDRD = (1 << P_TX) | (1 << P_SPKR); // Enabling Pin Change Interrupt for All Buttons PCMSK0 = 0b00011111; PCMSK1 = 0b00011111; PCMSK2 = 0b11111000; PCICR = (1 << PCIE0) | (1 << PCIE1) | (1 << PCIE2); TCCR1A = 0x00; // use timer1 CTC mode TCCR1B = 1 << WGM12; // already prescaled by 8 in table sei(); // Sends Square wave to the Speaker When a Button is Pressed for (unsigned char n = 0;; n = (n + 1) % 2) { // check if any buttons are pressed, otherwise don't play a note if (((PINB & PCMSK0) | (PINC & PCMSK1) | (PIND & PCMSK2)) == 0) continue; // Prepare Timer/Counter TCNT1 = 1; OCR1A = freqs[note]; TCCR1B |= 1 << CS11; while ((TIFR1 & (1 << OCF1A)) == 0); // Monitor OutPut Compare Flag // Toggles port For Speaker PORTD ^= 1 << P_SPKR; TIFR1 |= 1 << OCF1A; TCCR1B &= ~(1 << CS11); } }