notes.c (5097B)
1 /* 2 * EEL4746C - AVR Piano - Speaker Section 3 * speaker is connected to PD2 and ground 4 * 15 buttons are connected to PD3-7, PC0-4, PB0-4 5 * the LCD Arduino UNO is connected to TX/RX (PD0/1) 6 */ 7 8 #include <avr/io.h> 9 #include <avr/interrupt.h> 10 11 #define F_CPU 16e6 12 #include <util/delay.h> 13 14 #define T1_PRESCALAR 8 15 #define FREQ(f) (16e6 / f / T1_PRESCALAR / 2) 16 17 #define HIGH(sn) ((sn >> 8) & 0xff) 18 #define LOW(sn) (sn & 0xff) 19 20 #define P_RX 0 21 #define P_TX 1 22 #define P_SPKR 2 23 24 #define MARIO 50 25 26 unsigned short freqs[] = { 27 // PD3-7 28 100, 29 200, 30 250, 31 300, 32 350, 33 // PB0-4 34 400, 35 450, // middle c 36 500, 37 600, 38 700, 39 // PC0-4 40 750, 41 800, 42 850, 43 900, 44 950, 45 46 // notes 47 [MARIO] = 131, // C3 48 262, // C4 49 110, // A2 50 220, // A3 51 117, // Bb2 52 233, // Bb3 53 54 87, 55 175, 56 73, 57 147, 58 78, 59 156, 60 61 156, 62 147, 63 139, 64 131, 65 156, 66 147, 67 104, 68 98, 69 139, 70 71 156, 72 185, 73 175, 74 165, 75 233, 76 220, 77 208, 78 156, 79 123, 80 123, 81 110, 82 104, 83 84 ['"'] = 16000, 85 86 [255] = 0 // used as a 'silent' note 87 }; 88 89 unsigned short t_freqs[] = { 90 // PD3-7 91 FREQ(100), 92 FREQ(200), 93 FREQ(250), 94 FREQ(300), 95 FREQ(350), 96 // PB0-4 97 FREQ(400), 98 FREQ(450), // middle c 99 FREQ(500), 100 FREQ(600), 101 FREQ(700), 102 // PC0-4 103 FREQ(750), 104 FREQ(800), 105 FREQ(850), 106 FREQ(900), 107 FREQ(950), 108 109 // notes 110 [MARIO] = FREQ(131), // C3 111 FREQ(262), // C4 112 FREQ(110), // A2 113 FREQ(220), // A3 114 FREQ(117), // Bb2 115 FREQ(233), // Bb3 116 117 FREQ(87), 118 FREQ(175), 119 FREQ(73), 120 FREQ(147), 121 FREQ(78), 122 FREQ(156), 123 124 FREQ(156), 125 FREQ(147), 126 FREQ(139), 127 FREQ(131), 128 FREQ(156), 129 FREQ(147), 130 FREQ(104), 131 FREQ(98), 132 FREQ(139), 133 134 FREQ(156), 135 FREQ(185), 136 FREQ(175), 137 FREQ(165), 138 FREQ(233), 139 FREQ(220), 140 FREQ(208), 141 FREQ(156), 142 FREQ(123), 143 FREQ(123), 144 FREQ(110), 145 FREQ(104), 146 147 ['"'] = FREQ(16000), 148 149 [255] = 0 // used as a 'silent' note 150 }; 151 unsigned char note = 0; 152 // 0 = normal/piano mode 153 // 1 = recording mode 154 // 2 = mario demo 155 unsigned char mode = '0'; 156 157 ISR (PCINT0_vect) 158 { 159 // check if any button in the whole port is pressed 160 for (unsigned char i = 0; i <= 5; i++) { 161 if (PINB & (1 << i)) { 162 note = i + 5; 163 break; 164 } 165 } 166 } 167 168 ISR (PCINT1_vect) 169 { 170 // check if any button in the whole port is pressed 171 for (unsigned char i = 0; i <= 5; i++) { 172 if (PINC & (1 << i)) { 173 note = i + 10; 174 break; 175 } 176 } 177 } 178 179 ISR (PCINT2_vect) 180 { 181 // check if any button in the whole port is pressed 182 for (unsigned char i = 3; i <= 7; i++) { 183 if (PIND & (1 << i)) { 184 note = i - 3; 185 break; 186 } 187 } 188 } 189 190 void 191 usart_init(void) 192 { 193 // 9600 bps, TX enabled 194 UBRR0 = 103; 195 UCSR0B = 1 << TXEN0; 196 UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); 197 } 198 199 void 200 usart_send(unsigned char c) 201 { 202 while (!(UCSR0A & (1 << UDRE0))); 203 UDR0 = c; 204 } 205 206 void 207 usart_send_str(const char *c) 208 { 209 for (unsigned char i = 0; c[i] != '\0'; i++) 210 usart_send(c[i]); 211 } 212 213 unsigned char 214 usart_read(void) 215 { 216 while (!(UCSR0A & (1 << RXC0))); 217 return UDR0; 218 } 219 220 void 221 playtone(void) 222 { 223 // Prepare Timer/Counter 224 TCNT1 = 1; 225 OCR1A = t_freqs[note]; 226 TCCR1B |= 1 << CS11; 227 228 // Monitor OutPut Compare Flag 229 while ((TIFR1 & (1 << OCF1A)) == 0); 230 231 // Toggles port For Speaker 232 PORTD ^= 1 << P_SPKR; 233 TIFR1 |= 1 << OCF1A; 234 TCCR1B &= ~(1 << CS11); 235 } 236 237 void 238 play_note(unsigned char _note, unsigned short _cycles) 239 { 240 note = _note; 241 242 usart_send(note); 243 244 for (unsigned short i = 0; i < _cycles; i++) 245 playtone(); 246 247 _delay_ms(25); 248 } 249 250 int 251 main(void) 252 { 253 // Data Direction for Buttons, UART, Speaker 254 DDRB = 0x00; 255 DDRC = 0x00; 256 DDRD = (1 << P_TX) | (1 << P_SPKR); 257 258 // Enabling Pin Change Interrupt for All Buttons 259 PCMSK0 = 0b00011111; 260 PCMSK1 = 0b00011111; 261 PCMSK2 = 0b11111000; 262 PCICR = (1 << PCIE0) | (1 << PCIE1) | (1 << PCIE2); 263 264 TCCR1A = 0x00; // use timer1 CTC mode 265 TCCR1B = 1 << WGM12; // already prescaled by 8 in table 266 267 sei(); 268 269 usart_init(); 270 271 // Sends Square wave to the Speaker When a Button is Pressed 272 unsigned short cycles = 0; 273 unsigned char tmp = 0; 274 for (unsigned char n = 0;; n = (n + 1) % 2) { 275 if (PINC & _BV(5)) 276 mode = '2'; 277 else if (PINB & _BV(5)) 278 mode = '3'; 279 else 280 mode = '0'; 281 282 // check if any buttons are pressed, otherwise don't play a note 283 if (mode == '0' && ((PINB & PCMSK0) | (PINC & PCMSK1) | (PIND & PCMSK2)) == 0) { 284 // if a button was released, then send note and cycles played 285 if (cycles > 0) { 286 usart_send(tmp); 287 cycles = 0; 288 } 289 continue; 290 } 291 292 if (mode == '0') { 293 tmp = note; 294 295 playtone(); 296 297 cycles = (cycles + 1) % 0xffff; 298 } else if (mode == '1') { 299 300 } else if (mode == '3') { 301 for (unsigned char i = 0; i < 2; i++) { 302 for (unsigned char j = 0; j <= 5; j++) 303 play_note(MARIO + j, freqs[MARIO + j] * 0.3); 304 _delay_ms(1800); 305 } 306 307 for (unsigned char i = 0; i < 2; i++) { 308 for (unsigned char j = 6; j <= 11; j++) 309 play_note(MARIO + j, freqs[MARIO + j] * 0.3); 310 _delay_ms(1800); 311 } 312 313 for (unsigned char i = 12; i <= 14; i++) 314 play_note(MARIO + i, freqs[MARIO + i] * 0.3); 315 for (unsigned char i = 15; i <= 20; i++) 316 play_note(MARIO + i, freqs[MARIO + i] * 0.6); 317 318 for (unsigned char i = 21; i <= 26; i++) 319 play_note(MARIO + i, freqs[MARIO + i] * 0.3); 320 for (unsigned char i = 27; i <= 32; i++) 321 play_note(MARIO + i, freqs[MARIO + i] * 0.6); 322 } 323 } 324 }