Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * TC_Greensleeves.c
- *
- * Created: 11/7/2014 12:31:38 AM
- * Author: grist.carrigafoyl
- Play Greensleeves on a Microbrute Tesla Coil.
- v 1.00 Starting simple using a fixed pulse width.
- */
- #define F_CPU 16000000UL // 16MHz
- // Because I'm sick of crawling the datasheet. These should probably go in a header file.
- #define T0_MODE_CTC _BV(WGM01)
- #define T0_PRESC_1 _BV(CS00)
- #define T0_PRESC_8 _BV(CS01)
- #define T0_PRESC_64 _BV(CS01) | _BV(CS00)
- #define T0_PRESC_256 _BV(CS02)
- #define T0_PRESC_1024 _BV(CS02) | _BV(CS00)
- #define T1_MODE_CTC _BV(WGM12)
- #define T1_PRESC_1 _BV(CS10)
- #define T1_PRESC_8 _BV(CS11)
- #define T1_PRESC_64 _BV(CS11) | _BV(CS10)
- #define T1_PRESC_256 _BV(CS12)
- #define T1_PRESC_1024 _BV(CS12) | _BV(CS12)
- #define T2_MODE_CTC _BV(WGM21)
- #define T2_PRESC_1 _BV(CS20)
- #define T2_PRESC_8 _BV(CS21)
- #define T2_PRESC_32 _BV(CS21) | _BV(CS20)
- #define T2_PRESC_64 _BV(CS22)
- #define T2_PRESC_128 _BV(CS22) | _BV(CS20)
- #define T2_PRESC_256 _BV(CS22) | _BV(CS21)
- #define T2_PRESC_1024 _BV(CS22) | _BV(CS21) | _BV(CS20)
- #include <avr/io.h>
- #include <avr/interrupt.h>
- int pulse_width = 60; // microseconds
- // some notes to test with (C2, D2, E2, D2)
- #define NUM_NOTES 72
- // the notes. Can reach all of these with prescaler 1
- const int notes[NUM_NOTES] = {
- 20407,
- 17160, 15288, 13620, 12134, 13620,
- 15288, 18181, 22907, 20407, 18181,
- 17160, 20407, 20407, 22907, 20407,
- 18181, 22907, 27241, 20407,
- 17160, 15288, 13620, 12134, 13620,
- 15288, 18181, 22907, 20407, 18181,
- 17160, 18181, 20407, 22907, 24269, 22907,
- 20407, 20407,
- 11453, 11453, 12134, 13620,
- 15288, 18181, 22907, 20407, 18181,
- 17160, 20407, 20407, 21621, 20407,
- 18181, 21621, 27241,
- 11453, 11453, 12134, 13620,
- 15288, 18181, 22907, 20407, 18181,
- 17160, 18181, 20407, 22907, 24269, 22907,
- 20407, 20407
- };
- // note durations: 4 = quarter note, 8 = eighth note, etc
- const float noteDurations[NUM_NOTES] = {
- 8,
- 4, 8, 5.3333333333, 16, 8,
- 4, 8, 5.3333333333, 16, 8,
- 4, 8, 5.3333333333, 16, 8,
- 4, 8, 4, 8,
- 4, 8, 5.3333333333, 16, 8,
- 4, 8, 5.3333333333, 16, 8,
- 5, 16, 8, 5.3333333333, 16, 8,
- 2.6666666667, 2.6666666667,
- 2.6666666667, 5.333, 16, 8,
- 4, 8, 5.333, 16, 8,
- 5.3333333333, 16, 8, 5.3333333333, 16, 8,
- 2.6666666667, 2.6666666667,
- 2.6666666667, 5.3333333333, 16, 8,
- 4, 8, 5.3333333333, 16, 8,
- 5.3333333333, 16, 8, 5.3333333333, 16, 8,
- 2.6666666667, 2.6666666667
- };
- volatile int note_playing = 0;
- int main(void)
- {
- int top;
- DDRB |= _BV(PB3); // set pin to output
- // Timer 0 setup. 8 bit, note duration
- TCCR0A = T0_MODE_CTC;
- TIMSK0 |= _BV(OCIE0A);
- OCR0A = 244; // makes a count of 1 pretty close to 1/64th second
- // Timer 1 setup. 16 bit, frequency
- TCCR1B = _BV(WGM12); // ctc mode
- TIMSK1 = _BV(OCIE1A); // Enable Timer 1 COMP A interrupt vector
- // to get OCR1A use F = F_CPU/(2 x Prescaler x (1 + OCR1A))
- //OCR1A = 19261; // have to match with prescaler value
- //TCCR1B |= T1_PRESC_8; // start the frequency timer
- // Timer 2 setup. 8 bit, pulse width.
- TCCR2A = _BV(WGM21); //ctc
- TIMSK2 = _BV(OCIE2A); // enable Timer 2 COMP A interrupt vector
- OCR2A = pulse_width/2; // 16MHz with 32 prescaler
- sei(); // enable global interrupts
- TCCR0B = T0_PRESC_1024; // start the note timer
- while(1)
- {
- for (int i=0; i<NUM_NOTES;i++) {
- OCR1A = notes[i];
- note_playing = 0;
- TCCR1B |= T1_PRESC_1; // start the frequency timer
- top = 128/noteDurations[i];
- while (note_playing < top) {
- // enjoy the melodious tone
- }
- TCCR1B &= ~T1_PRESC_1; // stop the frequency timer
- note_playing = 0; // reset the counter
- while (note_playing < 6) {
- // do nothing
- }
- }
- // a gap between iterations
- note_playing = 0;
- while (note_playing < 300) {
- // A brief pause between tones helps punctuate them.
- }
- }
- }
- // Interrupt service routines
- ISR(TIMER0_COMPA_vect) {
- // Note duration timer
- note_playing++;
- }
- ISR(TIMER1_COMPA_vect) {
- // Turn on the pin and start the timer to turn it off
- PORTB |= _BV(PB3);
- TCCR2B|= _BV(CS20) | _BV(CS21); // prescaler 32, starts the timer
- }
- ISR(TIMER2_COMPA_vect) {
- // Turn off the pin and the timer
- PORTB &= ~_BV(PB3);
- TCNT2 = 0; // reset the counter
- TCCR2B = 0; // WGM22 is the only other bit in this register I care about and it's 0 anyway.
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement