3#include <avr/interrupt.h>
6#ifdef __AVR_ATmega32U4__
10#define BUZZER (1 << PORTD7)
12#define TIMER4_CLK_8 0x4
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
25static 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
32unsigned char buzzerInitialized = 0;
33volatile unsigned char buzzerFinished = 1;
34const char *
volatile buzzerSequence = 0;
38static volatile unsigned int buzzerTimeout = 0;
41extern volatile unsigned char buzzerFinished;
42extern const char *
volatile buzzerSequence;
45static volatile unsigned char use_program_space;
49static volatile unsigned char octave = 4;
50static volatile unsigned int whole_note_duration = 2000;
51static volatile unsigned int note_type = 4;
52static volatile unsigned int duration = 500;
53static volatile unsigned int volume = 15;
54static volatile unsigned char staccato = 0;
57static volatile unsigned char staccato_rest_duration;
60static 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;
104inline void PololuBuzzer::init()
106 if (!buzzerInitialized)
108 buzzerInitialized = 1;
114void 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__
222 unsigned char dividerExponent = 0;
225 top = (
unsigned int)(((F_CPU/2 * multiplier) + (freq >> 1))/ freq);
230 top = (
unsigned int)((((F_CPU/2 >> (dividerExponent)) * multiplier) + (freq >> 1))/ freq);
234 unsigned char newCS2 = 2;
235 unsigned int divider = cs2_divider[newCS2];
238 top = (
unsigned int)(((F_CPU/16 * multiplier) + (freq >> 1))/ freq);
242 divider = cs2_divider[++newCS2];
243 top = (
unsigned int)(((F_CPU/2/divider * multiplier) + (freq >> 1))/ freq);
248 if (multiplier == 10)
249 freq = (freq + 5) / 10;
254 timeout = (
unsigned int)((
long)dur * freq / 1000);
259 DISABLE_TIMER_INTERRUPT();
261#ifdef __AVR_ATmega32U4__
262 TCCR4B = (TCCR4B & 0xF0) | (dividerExponent + 1);
265 unsigned int width = top >> (16 - volume);
268 buzzerTimeout = timeout;
272 TCCR2B = (TCCR2B & 0xF8) | newCS2;
274 OCR2B = top >> (16 - volume);
275 buzzerTimeout = timeout;
280 ENABLE_TIMER_INTERRUPT();
295 unsigned char volume)
322 unsigned int freq = 0;
323 unsigned char offset_note = note - 16;
334 else if (offset_note > 95)
337 unsigned char exponent = offset_note / 12;
341 switch (offset_note - exponent * 12)
383 freq = freq << exponent;
385 freq = (freq + 5) / 10;
390 freq = (freq * 64 + 2) / 5;
402 return !buzzerFinished || buzzerSequence != 0;
465 DISABLE_TIMER_INTERRUPT();
466 buzzerSequence = notes;
467 use_program_space = 0;
468 staccato_rest_duration = 0;
474 DISABLE_TIMER_INTERRUPT();
475 buzzerSequence = notes_p;
476 use_program_space = 1;
477 staccato_rest_duration = 0;
485 DISABLE_TIMER_INTERRUPT();
487#ifdef __AVR_ATmega32U4__
488 TCCR4B = (TCCR4B & 0xF0) | TIMER4_CLK_8;
489 unsigned int top = (F_CPU/16) / 1000;
495 TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32;
496 OCR2A = (F_CPU/64) / 1000;
506static char currentCharacter()
511 if(use_program_space)
512 c = pgm_read_byte(buzzerSequence);
516 if(c >=
'A' && c <=
'Z')
518 }
while(c ==
' ' && (buzzerSequence ++));
526static unsigned int getNumber()
528 unsigned int arg = 0;
531 char c = currentCharacter();
532 while(c >=
'0' && c <=
'9')
537 c = currentCharacter();
543static void nextNote()
545 unsigned char note = 0;
546 unsigned char rest = 0;
547 unsigned char tmp_octave = octave;
548 unsigned int tmp_duration;
549 unsigned int dot_add;
554 if(staccato && staccato_rest_duration)
557 staccato_rest_duration = 0;
564 c = currentCharacter();
573 goto parse_character;
577 goto parse_character;
601 note_type = getNumber();
602 duration = whole_note_duration/note_type;
603 goto parse_character;
606 if(currentCharacter() ==
'l')
611 staccato_rest_duration = 0;
614 goto parse_character;
617 octave = tmp_octave = getNumber();
618 goto parse_character;
625 whole_note_duration = 60*400/getNumber()*10;
626 duration = whole_note_duration/note_type;
627 goto parse_character;
630 volume = getNumber();
631 goto parse_character;
635 whole_note_duration = 2000;
642 tmp_duration = duration;
643 goto parse_character;
649 note += tmp_octave*12;
652 c = currentCharacter();
653 while(c ==
'+' || c ==
'#')
657 c = currentCharacter();
663 c = currentCharacter();
667 tmp_duration = duration;
670 if(c >
'0' && c <
'9')
671 tmp_duration = whole_note_duration/getNumber();
675 dot_add = tmp_duration/2;
676 while(currentCharacter() ==
'.')
679 tmp_duration += dot_add;
685 staccato_rest_duration = tmp_duration / 2;
686 tmp_duration -= staccato_rest_duration;
710 play_mode_setting = mode;
727 if(buzzerFinished && buzzerSequence != 0)
729 return buzzerSequence != 0;
#define DIV_BY_10
frequency bit that indicates Hz/10 e.g. frequency = (445 | DIV_BY_10) gives a frequency of 44....
#define PLAY_AUTOMATIC
Specifies that the sequence of notes will play with no further action required by the user.
#define SILENT_NOTE
silences buzzer for the note duration
static void playFromProgramSpace(const char *sequence)
Plays the specified sequence of notes from program space.
static void play(const char *sequence)
Plays the specified sequence of notes.
static void stopPlaying()
Stops any note, frequency, or melody being played.
static unsigned char playCheck()
Starts the next note in a sequence, if necessary, in PLAY_CHECK mode.
static unsigned char isPlaying()
Checks whether a note, frequency, or sequence is being played.
static void playFrequency(unsigned int freq, unsigned int duration, unsigned char volume)
Plays the specified frequency for the specified duration.
static void playNote(unsigned char note, unsigned int duration, unsigned char volume)
Plays the specified note for the specified duration.
static void playMode(unsigned char mode)
Controls whether play() sequence is played automatically or must be driven with playCheck().