/* * GccApplication1.c * * Created: 10/8/2019 2:07:13 PM * Author : lenfesty */ #include "main.h" /* * Pin Definitions: * PB2 -> OC0A output * PB3 -> OC1A output * PD2 -> Switch Input */ void gpio_init() { // Piezo Out DDRB |= (1 << DDB2) | (1 << DDB3); // Switch Input Setup DDRD &= ~(1 << DDD2); PORTD |= (1 << PORTD2); } void timer_init( ) { /* --- Timer 0 (8 bit) --- */ // Set Compare mode A to toggle, and waveform generation mode to CTC TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00); // Nothing else relevant here, without setting notes /* --- Timer 1 (16 bit) --- */ // Set compare mode A to toggle TCCR1A = (0 << COM1A1) | (1 << COM1A0); // Set waveform gen mode to CTC TCCR1B = (1 << WGM12); } // Returns true for a "successful" note, false for end of song. bool play_beat() { static uint8_t duration_left[2] = {0}; static uint16_t song_location[2] = {0}; // If at end of song, restart if (song_location[0] == SPEAKER0_LEN) { song_location[0] = 0; song_location[1] = 0; return false; } // Set note for (uint8_t speaker = 0; speaker < 2; speaker++) { if (duration_left[speaker] == 0) { // Move to next note // Read in next note from program memory uint16_t beat; beat_t* p_beat; // Select from correct song if (speaker == 0) { beat = pgm_read_word((PGM_P*) &song_speaker0[song_location[speaker]]); } else { beat = pgm_read_word((PGM_P*) &song_speaker1[song_location[speaker]]); } p_beat = (beat_t*) &beat; // Set duration left after this beat duration_left[speaker] = p_beat->duration - 1; // Increment song location for next note song_location[speaker]++; // actually set note play_note(*p_beat, speaker); } else { // Keep handling current note // do nothing, it is set correctly duration_left[speaker]--; } } _delay_ms(BEAT_LENGTH * (1 - REST_FRACTION)); // Play note // Rest note if at the end of the interval for (uint8_t speaker = 0; speaker < 2; speaker++) { if (duration_left[speaker] == 0) { // End of note, pause here beat_t beat = { .note = rest, .duration = 0, .octave = 0, // octave doesn't matter, its a rest }; play_note(beat, speaker); } else { // Note does not end, change nothing } } _delay_ms(BEAT_LENGTH * REST_FRACTION); return true; } int main(void) { // Run initialisation functionality gpio_init(); timer_init(); while (1) { // Wait for button press if (bit_is_clear(PIND, PIND2)) { // Play song until the end while(play_beat()); // Turn off speakers once song is over beat_t beat = { .note = rest, .duration = 0, .octave = 0, // octave doesn't matter, its a rest }; play_note(beat, 0); play_note(beat, 1); } } }