3 #include <avr/interrupt.h>
6 #ifdef __AVR_ATmega32U4__
9 #define BUZZER_DDR DDRD
10 #define BUZZER (1 << PORTD7)
12 #define TIMER4_CLK_8 0x4 // 2 MHz
14 #define ENABLE_TIMER_INTERRUPT() TIMSK4 = (1 << TOIE4)
15 #define DISABLE_TIMER_INTERRUPT() TIMSK4 = 0
20 #define BUZZER_DDR DDRD
21 #define BUZZER (1 << PORTD3)
23 #define TIMER2_CLK_32 0x3 // 500 kHz
25 static const unsigned int cs2_divider[] = {0, 1, 8, 32, 64, 128, 256, 1024};
27 #define ENABLE_TIMER_INTERRUPT() TIMSK2 = (1 << TOIE2)
28 #define DISABLE_TIMER_INTERRUPT() TIMSK2 = 0
32 unsigned char buzzerInitialized = 0;
33 volatile unsigned char buzzerFinished = 1;
34 const char *
volatile buzzerSequence = 0;
38 static volatile unsigned int buzzerTimeout = 0;
41 extern volatile unsigned char buzzerFinished;
42 extern const char *
volatile buzzerSequence;
45 static volatile unsigned char use_program_space;
49 static volatile unsigned char octave = 4;
50 static volatile unsigned int whole_note_duration = 2000;
51 static volatile unsigned int note_type = 4;
52 static volatile unsigned int duration = 500;
53 static volatile unsigned int volume = 15;
54 static volatile unsigned char staccato = 0;
57 static volatile unsigned char staccato_rest_duration;
60 static void nextNote();
62 #ifdef __AVR_ATmega32U4__
67 if (buzzerTimeout-- == 0)
69 DISABLE_TIMER_INTERRUPT();
71 TCCR4B = (TCCR4B & 0xF0) | TIMER4_CLK_8;
72 unsigned int top = (F_CPU/16) / 1000;
88 if (buzzerTimeout-- == 0)
90 DISABLE_TIMER_INTERRUPT();
92 TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32;
93 OCR2A = (F_CPU/64) / 1000;
104 inline void PololuBuzzer::init()
106 if (!buzzerInitialized)
108 buzzerInitialized = 1;
114 void PololuBuzzer::init2()
116 DISABLE_TIMER_INTERRUPT();
118 #ifdef __AVR_ATmega32U4__
153 unsigned int top = (F_CPU/16) / 1000;
182 OCR2A = (F_CPU/64) / 1000;
186 BUZZER_DDR |= BUZZER;
200 unsigned char volume)
205 unsigned int timeout;
206 unsigned char multiplier = 1;
214 unsigned char min = 40 * multiplier;
217 if (multiplier == 1 && freq > 10000)
220 #ifdef __AVR_ATmega32U4__
221 uint8_t dividerExponent = 0;
222 uint32_t dividedClk = F_CPU/2;
230 uint32_t overflowClk = ((uint32_t)2047 * freq + multiplier) / 2 / multiplier;
232 while (dividedClk >= overflowClk)
239 uint32_t dividedClk = F_CPU/2 / cs2_divider[newCS2];
247 uint32_t overflowClk = ((uint32_t)511 * freq + multiplier) / 2 / multiplier;
249 while (dividedClk >= overflowClk)
252 dividedClk = F_CPU/2 / cs2_divider[newCS2];
256 uint16_t top = ((dividedClk * multiplier) + (freq >> 1)) / freq;
259 if (multiplier == 10)
260 freq = (freq + 5) / 10;
265 timeout = (
unsigned int)((
long)dur * freq / 1000);
270 DISABLE_TIMER_INTERRUPT();
272 #ifdef __AVR_ATmega32U4__
273 TCCR4B = (TCCR4B & 0xF0) | (dividerExponent + 1);
276 unsigned int width = top >> (16 - volume);
279 buzzerTimeout = timeout;
283 TCCR2B = (TCCR2B & 0xF8) | newCS2;
285 OCR2B = top >> (16 - volume);
286 buzzerTimeout = timeout;
291 ENABLE_TIMER_INTERRUPT();
306 unsigned char volume)
333 unsigned int freq = 0;
334 unsigned char offset_note = note - 16;
345 else if (offset_note > 95)
348 unsigned char exponent = offset_note / 12;
352 switch (offset_note - exponent * 12)
394 freq = freq << exponent;
396 freq = (freq + 5) / 10;
401 freq = (freq * 64 + 2) / 5;
413 return !buzzerFinished || buzzerSequence != 0;
476 DISABLE_TIMER_INTERRUPT();
477 buzzerSequence = notes;
478 use_program_space = 0;
479 staccato_rest_duration = 0;
485 DISABLE_TIMER_INTERRUPT();
486 buzzerSequence = notes_p;
487 use_program_space = 1;
488 staccato_rest_duration = 0;
496 DISABLE_TIMER_INTERRUPT();
498 #ifdef __AVR_ATmega32U4__
499 TCCR4B = (TCCR4B & 0xF0) | TIMER4_CLK_8;
500 unsigned int top = (F_CPU/16) / 1000;
506 TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32;
507 OCR2A = (F_CPU/64) / 1000;
517 static char currentCharacter()
522 if(use_program_space)
523 c = pgm_read_byte(buzzerSequence);
527 if(c >=
'A' && c <=
'Z')
529 }
while(c ==
' ' && (buzzerSequence ++));
537 static unsigned int getNumber()
539 unsigned int arg = 0;
542 char c = currentCharacter();
543 while(c >=
'0' && c <=
'9')
548 c = currentCharacter();
554 static void nextNote()
556 unsigned char note = 0;
557 unsigned char rest = 0;
558 unsigned char tmp_octave = octave;
559 unsigned int tmp_duration;
560 unsigned int dot_add;
565 if(staccato && staccato_rest_duration)
568 staccato_rest_duration = 0;
575 c = currentCharacter();
584 goto parse_character;
588 goto parse_character;
612 note_type = getNumber();
613 duration = whole_note_duration/note_type;
614 goto parse_character;
617 if(currentCharacter() ==
'l')
622 staccato_rest_duration = 0;
625 goto parse_character;
628 octave = tmp_octave = getNumber();
629 goto parse_character;
636 whole_note_duration = 60*400/getNumber()*10;
637 duration = whole_note_duration/note_type;
638 goto parse_character;
641 volume = getNumber();
642 goto parse_character;
646 whole_note_duration = 2000;
653 tmp_duration = duration;
654 goto parse_character;
660 note += tmp_octave*12;
663 c = currentCharacter();
664 while(c ==
'+' || c ==
'#')
668 c = currentCharacter();
674 c = currentCharacter();
678 tmp_duration = duration;
681 if(c >
'0' && c <
'9')
682 tmp_duration = whole_note_duration/getNumber();
686 dot_add = tmp_duration/2;
687 while(currentCharacter() ==
'.')
690 tmp_duration += dot_add;
696 staccato_rest_duration = tmp_duration / 2;
697 tmp_duration -= staccato_rest_duration;
721 play_mode_setting = mode;
738 if(buzzerFinished && buzzerSequence != 0)
740 return buzzerSequence != 0;