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__ 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;
506 static char currentCharacter()
511 if(use_program_space)
512 c = pgm_read_byte(buzzerSequence);
516 if(c >=
'A' && c <=
'Z')
518 }
while(c ==
' ' && (buzzerSequence ++));
526 static unsigned int getNumber()
528 unsigned int arg = 0;
531 char c = currentCharacter();
532 while(c >=
'0' && c <=
'9')
537 c = currentCharacter();
543 static 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 SILENT_NOTE
silences buzzer for the note duration
static void playMode(unsigned char mode)
Controls whether play() sequence is played automatically or must be driven with playCheck().
#define PLAY_AUTOMATIC
Specifies that the sequence of notes will play with no further action required by the user.
static void playNote(unsigned char note, unsigned int duration, unsigned char volume)
Plays the specified note for the specified duration.
static unsigned char playCheck()
Starts the next note in a sequence, if necessary, in PLAY_CHECK mode.
static void playFromProgramSpace(const char *sequence)
Plays the specified sequence of notes from program space.
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 stopPlaying()
Stops any note, frequency, or melody being played.
static void play(const char *sequence)
Plays the specified sequence of notes.