Added code
This commit is contained in:
parent
80d55f25b0
commit
2d4a3fba3e
151
lab_2/main.c
Normal file
151
lab_2/main.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* GccApplication1.c
|
||||
*
|
||||
* Created: 10/8/2019 2:07:13 PM
|
||||
* Author : lenfesty
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
|
||||
uint8_t play_flag = 0;
|
||||
uint8_t button_flag = 0;
|
||||
|
||||
ISR(INT0_vect) {
|
||||
// Disable interrupts
|
||||
cli();
|
||||
|
||||
// Notify of button press
|
||||
button_flag = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pin Definitions:
|
||||
* PB2 -> OC0A output
|
||||
* PB3 -> OC1A output
|
||||
* PB0 -> Switch Input
|
||||
*/
|
||||
void gpio_init() {
|
||||
// Piezo Out
|
||||
DDRB |= (1 << DDB2) | (1 << DDB3);
|
||||
|
||||
// Switch Input Setup
|
||||
DDRD &= ~(1 << DDD2);
|
||||
PORTD |= (1 << PORTD2);
|
||||
|
||||
// Configure Interrupt Stuff
|
||||
// Set falling edge for INT0
|
||||
MCUCR |= (1 << ISC01) | (0 << ISC00);
|
||||
|
||||
// Enable INT0
|
||||
GIMSK |= (1 << INT0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
gpio_init();
|
||||
timer_init();
|
||||
|
||||
sei();
|
||||
|
||||
/* Replace with your application code */
|
||||
while (1)
|
||||
{
|
||||
if (play_flag) {
|
||||
play_beat();
|
||||
}
|
||||
|
||||
if (button_flag) {
|
||||
button_flag = 0;
|
||||
|
||||
beat_t beat = {
|
||||
.note = rest,
|
||||
};
|
||||
play_note(beat, 0);
|
||||
play_note(beat, 1);
|
||||
_delay_ms(100);
|
||||
sei();
|
||||
}
|
||||
|
||||
if ( bit_is_clear(PIND, PIND2) && (play_flag == 0)) {
|
||||
cli();
|
||||
play_flag = 1;
|
||||
_delay_ms(100);
|
||||
sei();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
42
lab_2/main.h
Normal file
42
lab_2/main.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef MAIN_H_
|
||||
#define MAIN_H_
|
||||
|
||||
#define F_CPU 8000000UL
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "notes.h"
|
||||
|
||||
#define TEMPO (120 * 4) // Tempo of song (bpm)
|
||||
#define REST_FRACTION 0.3 // Fraction of the beat to stay silent between notes
|
||||
#define BEAT_LENGTH 60000 / TEMPO // Length of each note (ms)
|
||||
|
||||
|
||||
#define OCTAVES 2
|
||||
#define NOTES_PER_OCTAVE 12
|
||||
#define SPEAKER0_LEN 38
|
||||
#define SPEAKER1_LEN 96
|
||||
|
||||
typedef enum {
|
||||
a = 0, b, c, d, e, f, g,
|
||||
A, C, D, F, G,
|
||||
rest
|
||||
} note_t;
|
||||
|
||||
typedef struct {
|
||||
note_t note;
|
||||
uint8_t duration:7;
|
||||
uint8_t octave:1;
|
||||
} beat_t;
|
||||
|
||||
extern const uint8_t PROGMEM notes[OCTAVES][NOTES_PER_OCTAVE];
|
||||
|
||||
extern const beat_t PROGMEM song_speaker0[SPEAKER0_LEN];
|
||||
extern const beat_t PROGMEM song_speaker1[SPEAKER1_LEN];
|
||||
|
||||
void play_note(beat_t note, uint8_t speaker);
|
||||
|
||||
#endif
|
58
lab_2/notes.c
Normal file
58
lab_2/notes.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "main.h"
|
||||
|
||||
/*
|
||||
const uint8_t PROGMEM notes[OCTAVES][NOTES_PER_OCTAVE] = {
|
||||
{ 140, 62, 118, 106, 94, 88, 79, 64, 112, 98, , 37 }, // 1024 prescaler octave 2
|
||||
{ 141, 126, 238, 212, 188, 178, 158, 133, 225, 200, 168, 150 } // 64 prescaler octave 4
|
||||
};
|
||||
*/
|
||||
|
||||
const uint8_t PROGMEM notes[OCTAVES][NOTES_PER_OCTAVE] = {
|
||||
{ 35, 31, 59, 53, 47, 44, 39, 32, 56, 49, 41, 37 }, // 1024 prescaler octave 2
|
||||
{ 141, 126, 238, 212, 188, 178, 158, 133, 225, 200, 168, 150 } // 64 prescaler octave 4
|
||||
};
|
||||
|
||||
|
||||
void play_note(beat_t note, uint8_t speaker) {
|
||||
if (note.note == rest) { // Handle special rest case
|
||||
if (speaker == 0) {
|
||||
// Turn off timer clock source, disabling
|
||||
TCCR0B &= ~( (1 << CS02) | (1 << CS01) | (1 << CS00));
|
||||
// Turn off output pin
|
||||
PORTB &= ~(1 << PORTB2);
|
||||
} else {
|
||||
// turn off timer clock source, disabling
|
||||
TCCR1B &= ~( (1 << CS12) | (1 << CS11) | (1 << CS10));
|
||||
// turn off output pin
|
||||
PORTB &= ~(1 << PORTB3);
|
||||
}
|
||||
} else {
|
||||
// Set up so note changes always happen after rests,
|
||||
// so we know CS[2:0] = 0
|
||||
// See pages 86 and 114
|
||||
uint8_t prescale = 0;
|
||||
if (note.octave == 0) {
|
||||
// set prescaler to 1024
|
||||
prescale = 4;
|
||||
} else {
|
||||
// set prescaler to 64
|
||||
prescale = 3;
|
||||
}
|
||||
|
||||
// Get value to write to output compare
|
||||
uint8_t period = pgm_read_byte((PGM_P*) ¬es[note.octave][note.note]);
|
||||
|
||||
// Actually set clock source
|
||||
if (speaker == 0) {
|
||||
TCNT0 = 0; // reset counter
|
||||
OCR0A = period; // set note period
|
||||
TCCR0B |= prescale;
|
||||
} else {
|
||||
TCNT1H = 0; // reset counter
|
||||
TCNT1L = 0;
|
||||
OCR1AL = period; // set note period
|
||||
OCR1AH = period >> 8;
|
||||
TCCR1B |= prescale;
|
||||
}
|
||||
}
|
||||
}
|
141
lab_2/song.c
Normal file
141
lab_2/song.c
Normal file
@ -0,0 +1,141 @@
|
||||
#include "main.h"
|
||||
|
||||
const beat_t PROGMEM song_speaker0[SPEAKER0_LEN] = {
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 6, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = g, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = f, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = d, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
{.note = c, .duration = 4, .octave = 0 },
|
||||
};
|
||||
|
||||
const beat_t PROGMEM song_speaker1[SPEAKER1_LEN] = {
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = A, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = A, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 3, .octave = 1 },
|
||||
{.note = e, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = A, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = A, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = A, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 2, .octave = 1 },
|
||||
{.note = g, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = d, .duration = 2, .octave = 1 },
|
||||
{.note = d, .duration = 1, .octave = 1 },
|
||||
{.note = a, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 2, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = c, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 2, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1 },
|
||||
{.note = f, .duration = 1, .octave = 1 },
|
||||
{.note = e, .duration = 1, .octave = 1},
|
||||
};
|
Loading…
Reference in New Issue
Block a user