137 lines
2.8 KiB
C
137 lines
2.8 KiB
C
/*
|
|
* GccApplication1.c
|
|
*
|
|
* Created: 10/8/2019 2:07:13 PM
|
|
* Author : lenfesty
|
|
*/
|
|
|
|
#include "main.h"
|
|
|
|
bool play_flag = 0;
|
|
|
|
/*
|
|
* 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)
|
|
{
|
|
gpio_init();
|
|
timer_init();
|
|
|
|
beat_t beat = {
|
|
.note = a,
|
|
.duration = 20,
|
|
.octave = 0,
|
|
};
|
|
play_note(beat, 1);
|
|
|
|
while (1)
|
|
{
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
}
|
|
}
|