Advertisement
grist

Tesla Coil Greensleeves

Nov 14th, 2014
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.35 KB | None | 0 0
  1. /*
  2.  * TC_Greensleeves.c
  3.  *
  4.  * Created: 11/7/2014 12:31:38 AM
  5.  *  Author: grist.carrigafoyl
  6.  
  7.  Play Greensleeves on a Microbrute Tesla Coil.
  8.  
  9.  v 1.00  Starting simple using a fixed pulse width.
  10.  
  11.  */
  12. #define F_CPU 16000000UL // 16MHz
  13.  
  14. // Because I'm sick of crawling the datasheet. These should probably go in a header file.
  15. #define T0_MODE_CTC     _BV(WGM01)
  16. #define T0_PRESC_1      _BV(CS00)
  17. #define T0_PRESC_8      _BV(CS01)
  18. #define T0_PRESC_64     _BV(CS01) | _BV(CS00)
  19. #define T0_PRESC_256    _BV(CS02)
  20. #define T0_PRESC_1024   _BV(CS02) | _BV(CS00)
  21.  
  22. #define T1_MODE_CTC     _BV(WGM12)
  23. #define T1_PRESC_1      _BV(CS10)
  24. #define T1_PRESC_8      _BV(CS11)
  25. #define T1_PRESC_64     _BV(CS11) | _BV(CS10)
  26. #define T1_PRESC_256    _BV(CS12)
  27. #define T1_PRESC_1024   _BV(CS12) | _BV(CS12)
  28.  
  29. #define T2_MODE_CTC     _BV(WGM21)
  30. #define T2_PRESC_1      _BV(CS20)
  31. #define T2_PRESC_8      _BV(CS21)
  32. #define T2_PRESC_32     _BV(CS21) | _BV(CS20)
  33. #define T2_PRESC_64     _BV(CS22)
  34. #define T2_PRESC_128    _BV(CS22) | _BV(CS20)
  35. #define T2_PRESC_256    _BV(CS22) | _BV(CS21)
  36. #define T2_PRESC_1024   _BV(CS22) | _BV(CS21) | _BV(CS20)
  37.  
  38.  
  39. #include <avr/io.h>
  40. #include <avr/interrupt.h>
  41.  
  42. int pulse_width = 60; // microseconds
  43.  
  44. // some notes to test with (C2, D2, E2, D2)
  45. #define NUM_NOTES   72
  46. // the notes. Can reach all of these with prescaler 1
  47. const int notes[NUM_NOTES] = {
  48.     20407,
  49.     17160, 15288, 13620, 12134, 13620,
  50.     15288, 18181, 22907, 20407, 18181,
  51.     17160, 20407, 20407, 22907, 20407,
  52.     18181, 22907, 27241, 20407,
  53.    
  54.     17160, 15288, 13620, 12134, 13620,
  55.     15288, 18181, 22907, 20407, 18181,
  56.     17160, 18181, 20407, 22907, 24269, 22907,
  57.     20407, 20407,
  58.    
  59.     11453, 11453, 12134, 13620,
  60.     15288, 18181, 22907, 20407, 18181,
  61.     17160, 20407, 20407, 21621, 20407,
  62.     18181, 21621, 27241,
  63.    
  64.     11453, 11453, 12134, 13620,
  65.     15288, 18181, 22907, 20407, 18181,
  66.     17160, 18181, 20407, 22907, 24269, 22907,
  67.     20407, 20407
  68.    
  69. };
  70.  
  71. // note durations: 4 = quarter note, 8 = eighth note, etc
  72. const float noteDurations[NUM_NOTES] = {
  73.     8,
  74.     4, 8, 5.3333333333, 16, 8,
  75.     4, 8, 5.3333333333, 16, 8,
  76.     4, 8, 5.3333333333, 16, 8,
  77.     4, 8, 4, 8,
  78.    
  79.     4, 8, 5.3333333333, 16, 8,
  80.     4, 8, 5.3333333333, 16, 8,
  81.     5, 16, 8, 5.3333333333, 16, 8,
  82.     2.6666666667, 2.6666666667,
  83.    
  84.     2.6666666667, 5.333, 16, 8,
  85.     4, 8, 5.333, 16, 8,
  86.     5.3333333333, 16, 8, 5.3333333333, 16, 8,
  87.     2.6666666667, 2.6666666667,
  88.    
  89.     2.6666666667, 5.3333333333, 16, 8,
  90.     4, 8, 5.3333333333, 16, 8,
  91.     5.3333333333, 16, 8, 5.3333333333, 16, 8,
  92.     2.6666666667, 2.6666666667
  93.  
  94. };
  95.  
  96. volatile int note_playing = 0;
  97.  
  98.  
  99. int main(void)
  100. {
  101.     int top;
  102.     DDRB |= _BV(PB3); // set pin to output
  103.    
  104.     // Timer 0 setup. 8 bit, note duration
  105.     TCCR0A = T0_MODE_CTC;
  106.     TIMSK0 |= _BV(OCIE0A);
  107.     OCR0A = 244; // makes a count of 1 pretty close to 1/64th second
  108.    
  109.     // Timer 1 setup. 16 bit, frequency
  110.     TCCR1B = _BV(WGM12); // ctc mode
  111.     TIMSK1 = _BV(OCIE1A); // Enable Timer 1 COMP A interrupt vector
  112.     // to get OCR1A use F = F_CPU/(2 x Prescaler x (1 + OCR1A))
  113.     //OCR1A = 19261; // have to match with prescaler value
  114.     //TCCR1B |= T1_PRESC_8; // start the frequency timer
  115.    
  116.     // Timer 2 setup. 8 bit, pulse width.
  117.     TCCR2A = _BV(WGM21); //ctc
  118.     TIMSK2 = _BV(OCIE2A); // enable Timer 2 COMP A interrupt vector
  119.     OCR2A = pulse_width/2; // 16MHz with 32 prescaler
  120.    
  121.     sei(); // enable global interrupts
  122.    
  123.     TCCR0B = T0_PRESC_1024; // start the note timer
  124.     while(1)
  125.     {
  126.         for (int i=0; i<NUM_NOTES;i++) {
  127.             OCR1A = notes[i];
  128.        
  129.             note_playing = 0;
  130.             TCCR1B |= T1_PRESC_1; // start the frequency timer
  131.             top = 128/noteDurations[i];
  132.             while (note_playing < top) {
  133.                 // enjoy the melodious tone
  134.             }
  135.             TCCR1B &= ~T1_PRESC_1; // stop the frequency timer
  136.             note_playing = 0; // reset the counter
  137.             while (note_playing < 6) {
  138.                 // do nothing
  139.             }      
  140.         }
  141.         // a gap between iterations
  142.         note_playing = 0;
  143.         while (note_playing < 300) {
  144.             // A brief pause between tones helps punctuate them.
  145.         }
  146.     }
  147. }
  148.  
  149.  
  150. // Interrupt service routines
  151. ISR(TIMER0_COMPA_vect) {
  152.     // Note duration timer
  153.     note_playing++;
  154.    
  155. }
  156.  
  157.  
  158.  
  159. ISR(TIMER1_COMPA_vect) {
  160.     // Turn on the pin and start the timer to turn it off
  161.     PORTB |= _BV(PB3);
  162.     TCCR2B|= _BV(CS20) | _BV(CS21); // prescaler 32, starts the timer
  163.  
  164. }
  165.  
  166. ISR(TIMER2_COMPA_vect) {
  167.     // Turn off the pin and the timer
  168.     PORTB &= ~_BV(PB3);
  169.     TCNT2 = 0; // reset the counter
  170.     TCCR2B = 0; // WGM22 is the only other bit in this register I care about and it's 0 anyway.
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement