Zumo32U4 library
PololuBuzzer.cpp
1// Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2
3#include <avr/interrupt.h>
4#include "PololuBuzzer.h"
5
6#ifdef __AVR_ATmega32U4__
7
8// PD7 (OC4D)
9#define BUZZER_DDR DDRD
10#define BUZZER (1 << PORTD7)
11
12#define TIMER4_CLK_8 0x4 // 2 MHz
13
14#define ENABLE_TIMER_INTERRUPT() TIMSK4 = (1 << TOIE4)
15#define DISABLE_TIMER_INTERRUPT() TIMSK4 = 0
16
17#else // 168P or 328P
18
19// PD3 (OC2B)
20#define BUZZER_DDR DDRD
21#define BUZZER (1 << PORTD3)
22
23#define TIMER2_CLK_32 0x3 // 500 kHz
24
25static const unsigned int cs2_divider[] = {0, 1, 8, 32, 64, 128, 256, 1024};
26
27#define ENABLE_TIMER_INTERRUPT() TIMSK2 = (1 << TOIE2)
28#define DISABLE_TIMER_INTERRUPT() TIMSK2 = 0
29
30#endif
31
32unsigned char buzzerInitialized = 0;
33volatile unsigned char buzzerFinished = 1; // flag: 0 while playing
34const char * volatile buzzerSequence = 0;
35
36// declaring these globals as static means they won't conflict
37// with globals in other .cpp files that share the same name
38static volatile unsigned int buzzerTimeout = 0; // tracks buzzer time limit
39static volatile char play_mode_setting = PLAY_AUTOMATIC;
40
41extern volatile unsigned char buzzerFinished; // flag: 0 while playing
42extern const char * volatile buzzerSequence;
43
44
45static volatile unsigned char use_program_space; // boolean: true if we should
46 // use program space
47
48// music settings and defaults
49static volatile unsigned char octave = 4; // the current octave
50static volatile unsigned int whole_note_duration = 2000; // the duration of a whole note
51static volatile unsigned int note_type = 4; // 4 for quarter, etc
52static volatile unsigned int duration = 500; // the duration of a note in ms
53static volatile unsigned int volume = 15; // the note volume
54static volatile unsigned char staccato = 0; // true if playing staccato
55
56// staccato handling
57static volatile unsigned char staccato_rest_duration; // duration of a staccato rest,
58 // or zero if it is time to play a note
59
60static void nextNote();
61
62#ifdef __AVR_ATmega32U4__
63
64// Timer4 overflow interrupt
65ISR (TIMER4_OVF_vect)
66{
67 if (buzzerTimeout-- == 0)
68 {
69 DISABLE_TIMER_INTERRUPT();
70 sei(); // re-enable global interrupts (nextNote() is very slow)
71 TCCR4B = (TCCR4B & 0xF0) | TIMER4_CLK_8; // select IO clock
72 unsigned int top = (F_CPU/16) / 1000; // set TOP for freq = 1 kHz:
73 TC4H = top >> 8; // top 2 bits... (TC4H temporarily stores top 2 bits of 10-bit accesses)
74 OCR4C = top; // and bottom 8 bits
75 TC4H = 0; // 0% duty cycle: top 2 bits...
76 OCR4D = 0; // and bottom 8 bits
77 buzzerFinished = 1;
78 if (buzzerSequence && (play_mode_setting == PLAY_AUTOMATIC))
79 nextNote();
80 }
81}
82
83#else
84
85// Timer2 overflow interrupt
86ISR (TIMER2_OVF_vect)
87{
88 if (buzzerTimeout-- == 0)
89 {
90 DISABLE_TIMER_INTERRUPT();
91 sei(); // re-enable global interrupts (nextNote() is very slow)
92 TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32; // select IO clock
93 OCR2A = (F_CPU/64) / 1000; // set TOP for freq = 1 kHz
94 OCR2B = 0; // 0% duty cycle
95 buzzerFinished = 1;
96 if (buzzerSequence && (play_mode_setting == PLAY_AUTOMATIC))
97 nextNote();
98 }
99}
100
101#endif
102
103// this is called by playFrequency()
104inline void PololuBuzzer::init()
105{
106 if (!buzzerInitialized)
107 {
108 buzzerInitialized = 1;
109 init2();
110 }
111}
112
113// initializes timer4 (32U4) or timer2 (328P) for buzzer control
114void PololuBuzzer::init2()
115{
116 DISABLE_TIMER_INTERRUPT();
117
118#ifdef __AVR_ATmega32U4__
119 TCCR4A = 0x00; // bits 7 and 6 clear: normal port op., OC4A disconnected
120 // bits 5 and 4 clear: normal port op., OC4B disconnected
121 // bit 3 clear: no force output compare for channel A
122 // bit 2 clear: no force output compare for channel B
123 // bit 1 clear: disable PWM for channel A
124 // bit 0 clear: disable PWM for channel B
125
126 TCCR4B = 0x04; // bit 7 clear: disable PWM inversion
127 // bit 6 clear: no prescaler reset
128 // bits 5 and 4 clear: dead time prescaler 1
129 // bit 3 clear, 2 set, 1-0 clear: timer clock = CK/8
130
131 TCCR4C = 0x09; // bits 7 and 6 clear: normal port op., OC4A disconnected
132 // bits 5 and 4 clear: normal port op., OC4B disconnected
133 // bit 3 set, 2 clear: clear OC4D on comp match when upcounting,
134 // set OC4D on comp match when downcounting
135 // bit 1 clear: no force output compare for channel D
136 // bit 0 set: enable PWM for channel 4
137
138 TCCR4D = 0x01; // bit 7 clear: disable fault protection interrupt
139 // bit 6 clear: disable fault protection mode
140 // bit 5 clear: disable fault protection noise canceler
141 // bit 4 clear: falling edge triggers fault
142 // bit 3 clear: disable fault protection analog comparator
143 // bit 2 clear: fault protection interrupt flag
144 // bit 1 clear, 0 set: select waveform generation mode,
145 // phase- and frequency-correct PWM, TOP = OCR4C,
146 // OCR4D set at BOTTOM, TOV4 flag set at BOTTOM
147
148 // This sets timer 4 to run in phase- and frequency-correct PWM mode,
149 // where TOP = OCR4C, OCR4D is updated at BOTTOM, TOV1 Flag is set on BOTTOM.
150 // OC4D is cleared on compare match when upcounting, set on compare
151 // match when downcounting; OC4A and OC4B are disconnected.
152
153 unsigned int top = (F_CPU/16) / 1000; // set TOP for freq = 1 kHz:
154 TC4H = top >> 8; // top 2 bits...
155 OCR4C = top; // and bottom 8 bits
156 TC4H = 0; // 0% duty cycle: top 2 bits...
157 OCR4D = 0; // and bottom 8 bits
158#else
159 TCCR2A = 0x21; // bits 7 and 6 clear: normal port op., OC4A disconnected
160 // bit 5 set, 4 clear: clear OC2B on comp match when upcounting,
161 // set OC2B on comp match when downcounting
162 // bits 3 and 2: not used
163 // bit 1 clear, 0 set: combine with bit 3 of TCCR2B...
164
165 TCCR2B = 0x0B; // bit 7 clear: no force output compare for channel A
166 // bit 6 clear: no force output compare for channel B
167 // bits 5 and 4: not used
168 // bit 3 set: combine with bits 1 and 0 of TCCR2A to
169 // select waveform generation mode 5, phase-correct PWM,
170 // TOP = OCR2A, OCR2B set at TOP, TOV2 flag set at BOTTOM
171 // bit 2 clear, 1-0 set: timer clock = clkT2S/32
172
173 // This sets timer 2 to run in phase-correct PWM mode, where TOP = OCR2A,
174 // OCR2B is updated at TOP, TOV2 Flag is set on BOTTOM. OC2B is cleared
175 // on compare match when upcounting, set on compare match when downcounting;
176 // OC2A is disconnected.
177 // Note: if the PWM frequency and duty cycle are changed, the first
178 // cycle of the new frequency will be at the old duty cycle, since
179 // the duty cycle (OCR2B) is not updated until TOP.
180
181
182 OCR2A = (F_CPU/64) / 1000; // set TOP for freq = 1 kHz
183 OCR2B = 0; // 0% duty cycle
184#endif
185
186 BUZZER_DDR |= BUZZER; // buzzer pin set as an output
187 sei();
188}
189
190
191// Set up the timer to play the desired frequency (in Hz or .1 Hz) for the
192// the desired duration (in ms). Allowed frequencies are 40 Hz to 10 kHz.
193// volume controls buzzer volume, with 15 being loudest and 0 being quietest.
194// Note: frequency*duration/1000 must be less than 0xFFFF (65535). This
195// means that you can't use a max duration of 65535 ms for frequencies
196// greater than 1 kHz. For example, the max duration you can use for a
197// frequency of 10 kHz is 6553 ms. If you use a duration longer than this,
198// you will cause an integer overflow that produces unexpected behavior.
199void PololuBuzzer::playFrequency(unsigned int freq, unsigned int dur,
200 unsigned char volume)
201{
202 init(); // initializes the buzzer if necessary
203 buzzerFinished = 0;
204
205 unsigned int timeout;
206 unsigned char multiplier = 1;
207
208 if (freq & DIV_BY_10) // if frequency's DIV_BY_10 bit is set
209 { // then the true frequency is freq/10
210 multiplier = 10; // (gives higher resolution for small freqs)
211 freq &= ~DIV_BY_10; // clear DIV_BY_10 bit
212 }
213
214 unsigned char min = 40 * multiplier;
215 if (freq < min) // min frequency allowed is 40 Hz
216 freq = min;
217 if (multiplier == 1 && freq > 10000)
218 freq = 10000; // max frequency allowed is 10kHz
219
220#ifdef __AVR_ATmega32U4__
221 unsigned long top;
222 unsigned char dividerExponent = 0;
223
224 // calculate necessary clock source and counter top value to get freq
225 top = (unsigned int)(((F_CPU/2 * multiplier) + (freq >> 1))/ freq);
226
227 while (top > 1023)
228 {
229 dividerExponent++;
230 top = (unsigned int)((((F_CPU/2 >> (dividerExponent)) * multiplier) + (freq >> 1))/ freq);
231 }
232#else
233 unsigned int top;
234 unsigned char newCS2 = 2; // try prescaler divider of 8 first (minimum necessary for 10 kHz)
235 unsigned int divider = cs2_divider[newCS2];
236
237 // calculate necessary clock source and counter top value to get freq
238 top = (unsigned int)(((F_CPU/16 * multiplier) + (freq >> 1))/ freq);
239
240 while (top > 255)
241 {
242 divider = cs2_divider[++newCS2];
243 top = (unsigned int)(((F_CPU/2/divider * multiplier) + (freq >> 1))/ freq);
244 }
245#endif
246
247 // set timeout (duration):
248 if (multiplier == 10)
249 freq = (freq + 5) / 10;
250
251 if (freq == 1000)
252 timeout = dur; // duration for silent notes is exact
253 else
254 timeout = (unsigned int)((long)dur * freq / 1000);
255
256 if (volume > 15)
257 volume = 15;
258
259 DISABLE_TIMER_INTERRUPT(); // disable interrupts while writing to registers
260
261#ifdef __AVR_ATmega32U4__
262 TCCR4B = (TCCR4B & 0xF0) | (dividerExponent + 1); // select timer 4 clock prescaler: divider = 2^n if CS4 = n+1
263 TC4H = top >> 8; // set timer 4 pwm frequency: top 2 bits...
264 OCR4C = top; // and bottom 8 bits
265 unsigned int width = top >> (16 - volume); // set duty cycle (volume):
266 TC4H = width >> 8; // top 2 bits...
267 OCR4D = width; // and bottom 8 bits
268 buzzerTimeout = timeout; // set buzzer duration
269
270 TIFR4 |= 0xFF; // clear any pending t4 overflow int.
271#else
272 TCCR2B = (TCCR2B & 0xF8) | newCS2; // select timer 2 clock prescaler
273 OCR2A = top; // set timer 2 pwm frequency
274 OCR2B = top >> (16 - volume); // set duty cycle (volume)
275 buzzerTimeout = timeout; // set buzzer duration
276
277 TIFR2 |= 0xFF; // clear any pending t2 overflow int.
278#endif
279
280 ENABLE_TIMER_INTERRUPT();
281}
282
283
284
285// Determine the frequency for the specified note, then play that note
286// for the desired duration (in ms). This is done without using floats
287// and without having to loop. volume controls buzzer volume, with 15 being
288// loudest and 0 being quietest.
289// Note: frequency*duration/1000 must be less than 0xFFFF (65535). This
290// means that you can't use a max duration of 65535 ms for frequencies
291// greater than 1 kHz. For example, the max duration you can use for a
292// frequency of 10 kHz is 6553 ms. If you use a duration longer than this,
293// you will cause an integer overflow that produces unexpected behavior.
294void PololuBuzzer::playNote(unsigned char note, unsigned int dur,
295 unsigned char volume)
296{
297 // note = key + octave * 12, where 0 <= key < 12
298 // example: A4 = A + 4 * 12, where A = 9 (so A4 = 57)
299 // A note is converted to a frequency by the formula:
300 // Freq(n) = Freq(0) * a^n
301 // where
302 // Freq(0) is chosen as A4, which is 440 Hz
303 // and
304 // a = 2 ^ (1/12)
305 // n is the number of notes you are away from A4.
306 // One can see that the frequency will double every 12 notes.
307 // This function exploits this property by defining the frequencies of the
308 // 12 lowest notes allowed and then doubling the appropriate frequency
309 // the appropriate number of times to get the frequency for the specified
310 // note.
311
312 // if note = 16, freq = 41.2 Hz (E1 - lower limit as freq must be >40 Hz)
313 // if note = 57, freq = 440 Hz (A4 - central value of ET Scale)
314 // if note = 111, freq = 9.96 kHz (D#9 - upper limit, freq must be <10 kHz)
315 // if note = 255, freq = 1 kHz and buzzer is silent (silent note)
316
317 // The most significant bit of freq is the "divide by 10" bit. If set,
318 // the units for frequency are .1 Hz, not Hz, and freq must be divided
319 // by 10 to get the true frequency in Hz. This allows for an extra digit
320 // of resolution for low frequencies without the need for using floats.
321
322 unsigned int freq = 0;
323 unsigned char offset_note = note - 16;
324
325 if (note == SILENT_NOTE || volume == 0)
326 {
327 freq = 1000; // silent notes => use 1kHz freq (for cycle counter)
328 playFrequency(freq, dur, 0);
329 return;
330 }
331
332 if (note <= 16)
333 offset_note = 0;
334 else if (offset_note > 95)
335 offset_note = 95;
336
337 unsigned char exponent = offset_note / 12;
338
339 // frequency table for the lowest 12 allowed notes
340 // frequencies are specified in tenths of a Hertz for added resolution
341 switch (offset_note - exponent * 12) // equivalent to (offset_note % 12)
342 {
343 case 0: // note E1 = 41.2 Hz
344 freq = 412;
345 break;
346 case 1: // note F1 = 43.7 Hz
347 freq = 437;
348 break;
349 case 2: // note F#1 = 46.3 Hz
350 freq = 463;
351 break;
352 case 3: // note G1 = 49.0 Hz
353 freq = 490;
354 break;
355 case 4: // note G#1 = 51.9 Hz
356 freq = 519;
357 break;
358 case 5: // note A1 = 55.0 Hz
359 freq = 550;
360 break;
361 case 6: // note A#1 = 58.3 Hz
362 freq = 583;
363 break;
364 case 7: // note B1 = 61.7 Hz
365 freq = 617;
366 break;
367 case 8: // note C2 = 65.4 Hz
368 freq = 654;
369 break;
370 case 9: // note C#2 = 69.3 Hz
371 freq = 693;
372 break;
373 case 10: // note D2 = 73.4 Hz
374 freq = 734;
375 break;
376 case 11: // note D#2 = 77.8 Hz
377 freq = 778;
378 break;
379 }
380
381 if (exponent < 7)
382 {
383 freq = freq << exponent; // frequency *= 2 ^ exponent
384 if (exponent > 1) // if the frequency is greater than 160 Hz
385 freq = (freq + 5) / 10; // we don't need the extra resolution
386 else
387 freq += DIV_BY_10; // else keep the added digit of resolution
388 }
389 else
390 freq = (freq * 64 + 2) / 5; // == freq * 2^7 / 10 without int overflow
391
392 if (volume > 15)
393 volume = 15;
394 playFrequency(freq, dur, volume); // set buzzer this freq/duration
395}
396
397
398
399// Returns 1 if the buzzer is currently playing, otherwise it returns 0
401{
402 return !buzzerFinished || buzzerSequence != 0;
403}
404
405
406// Plays the specified sequence of notes. If the play mode is
407// PLAY_AUTOMATIC, the sequence of notes will play with no further
408// action required by the user. If the play mode is PLAY_CHECK,
409// the user will need to call playCheck() in the main loop to initiate
410// the playing of each new note in the sequence. The play mode can
411// be changed while the sequence is playing.
412// This is modeled after the PLAY commands in GW-BASIC, with just a
413// few differences.
414//
415// The notes are specified by the characters C, D, E, F, G, A, and
416// B, and they are played by default as "quarter notes" with a
417// length of 500 ms. This corresponds to a tempo of 120
418// beats/min. Other durations can be specified by putting a number
419// immediately after the note. For example, C8 specifies C played as an
420// eighth note, with half the duration of a quarter note. The special
421// note R plays a rest (no sound).
422//
423// Various control characters alter the sound:
424// '>' plays the next note one octave higher
425//
426// '<' plays the next note one octave lower
427//
428// '+' or '#' after a note raises any note one half-step
429//
430// '-' after a note lowers any note one half-step
431//
432// '.' after a note "dots" it, increasing the length by
433// 50%. Each additional dot adds half as much as the
434// previous dot, so that "A.." is 1.75 times the length of
435// "A".
436//
437// 'O' followed by a number sets the octave (default: O4).
438//
439// 'T' followed by a number sets the tempo (default: T120).
440//
441// 'L' followed by a number sets the default note duration to
442// the type specified by the number: 4 for quarter notes, 8
443// for eighth notes, 16 for sixteenth notes, etc.
444// (default: L4)
445//
446// 'V' followed by a number from 0-15 sets the music volume.
447// (default: V15)
448//
449// 'MS' sets all subsequent notes to play staccato - each note is played
450// for 1/2 of its allotted time, followed by an equal period
451// of silence.
452//
453// 'ML' sets all subsequent notes to play legato - each note is played
454// for its full length. This is the default setting.
455//
456// '!' resets all persistent settings to their defaults.
457//
458// The following plays a c major scale up and back down:
459// play("L16 V8 cdefgab>cbagfedc");
460//
461// Here is an example from Bach:
462// play("T240 L8 a gafaeada c+adaeafa <aa<bac#ada c#adaeaf4");
463void PololuBuzzer::play(const char *notes)
464{
465 DISABLE_TIMER_INTERRUPT(); // prevent this from being interrupted
466 buzzerSequence = notes;
467 use_program_space = 0;
468 staccato_rest_duration = 0;
469 nextNote(); // this re-enables the timer interrupt
470}
471
472void PololuBuzzer::playFromProgramSpace(const char *notes_p)
473{
474 DISABLE_TIMER_INTERRUPT(); // prevent this from being interrupted
475 buzzerSequence = notes_p;
476 use_program_space = 1;
477 staccato_rest_duration = 0;
478 nextNote(); // this re-enables the timer interrupt
479}
480
481
482// stop all sound playback immediately
484{
485 DISABLE_TIMER_INTERRUPT(); // disable interrupts
486
487#ifdef __AVR_ATmega32U4__
488 TCCR4B = (TCCR4B & 0xF0) | TIMER4_CLK_8; // select IO clock
489 unsigned int top = (F_CPU/16) / 1000; // set TOP for freq = 1 kHz:
490 TC4H = top >> 8; // top 2 bits... (TC4H temporarily stores top 2 bits of 10-bit accesses)
491 OCR4C = top; // and bottom 8 bits
492 TC4H = 0; // 0% duty cycle: top 2 bits...
493 OCR4D = 0; // and bottom 8 bits
494#else
495 TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32; // select IO clock
496 OCR2A = (F_CPU/64) / 1000; // set TOP for freq = 1 kHz
497 OCR2B = 0; // 0% duty cycle
498#endif
499
500 buzzerFinished = 1;
501 buzzerSequence = 0;
502}
503
504// Gets the current character, converting to lower-case and skipping
505// spaces. For any spaces, this automatically increments sequence!
506static char currentCharacter()
507{
508 char c = 0;
509 do
510 {
511 if(use_program_space)
512 c = pgm_read_byte(buzzerSequence);
513 else
514 c = *buzzerSequence;
515
516 if(c >= 'A' && c <= 'Z')
517 c += 'a'-'A';
518 } while(c == ' ' && (buzzerSequence ++));
519
520 return c;
521}
522
523// Returns the numerical argument specified at buzzerSequence[0] and
524// increments sequence to point to the character immediately after the
525// argument.
526static unsigned int getNumber()
527{
528 unsigned int arg = 0;
529
530 // read all digits, one at a time
531 char c = currentCharacter();
532 while(c >= '0' && c <= '9')
533 {
534 arg *= 10;
535 arg += c-'0';
536 buzzerSequence ++;
537 c = currentCharacter();
538 }
539
540 return arg;
541}
542
543static void nextNote()
544{
545 unsigned char note = 0;
546 unsigned char rest = 0;
547 unsigned char tmp_octave = octave; // the octave for this note
548 unsigned int tmp_duration; // the duration of this note
549 unsigned int dot_add;
550
551 char c; // temporary variable
552
553 // if we are playing staccato, after every note we play a rest
554 if(staccato && staccato_rest_duration)
555 {
556 PololuBuzzer::playNote(SILENT_NOTE, staccato_rest_duration, 0);
557 staccato_rest_duration = 0;
558 return;
559 }
560
561 parse_character:
562
563 // Get current character
564 c = currentCharacter();
565 buzzerSequence ++;
566
567 // Interpret the character.
568 switch(c)
569 {
570 case '>':
571 // shift the octave temporarily up
572 tmp_octave ++;
573 goto parse_character;
574 case '<':
575 // shift the octave temporarily down
576 tmp_octave --;
577 goto parse_character;
578 case 'a':
579 note = NOTE_A(0);
580 break;
581 case 'b':
582 note = NOTE_B(0);
583 break;
584 case 'c':
585 note = NOTE_C(0);
586 break;
587 case 'd':
588 note = NOTE_D(0);
589 break;
590 case 'e':
591 note = NOTE_E(0);
592 break;
593 case 'f':
594 note = NOTE_F(0);
595 break;
596 case 'g':
597 note = NOTE_G(0);
598 break;
599 case 'l':
600 // set the default note duration
601 note_type = getNumber();
602 duration = whole_note_duration/note_type;
603 goto parse_character;
604 case 'm':
605 // set music staccato or legato
606 if(currentCharacter() == 'l')
607 staccato = false;
608 else
609 {
610 staccato = true;
611 staccato_rest_duration = 0;
612 }
613 buzzerSequence ++;
614 goto parse_character;
615 case 'o':
616 // set the octave permanently
617 octave = tmp_octave = getNumber();
618 goto parse_character;
619 case 'r':
620 // Rest - the note value doesn't matter.
621 rest = 1;
622 break;
623 case 't':
624 // set the tempo
625 whole_note_duration = 60*400/getNumber()*10;
626 duration = whole_note_duration/note_type;
627 goto parse_character;
628 case 'v':
629 // set the volume
630 volume = getNumber();
631 goto parse_character;
632 case '!':
633 // reset to defaults
634 octave = 4;
635 whole_note_duration = 2000;
636 note_type = 4;
637 duration = 500;
638 volume = 15;
639 staccato = 0;
640 // reset temp variables that depend on the defaults
641 tmp_octave = octave;
642 tmp_duration = duration;
643 goto parse_character;
644 default:
645 buzzerSequence = 0;
646 return;
647 }
648
649 note += tmp_octave*12;
650
651 // handle sharps and flats
652 c = currentCharacter();
653 while(c == '+' || c == '#')
654 {
655 buzzerSequence ++;
656 note ++;
657 c = currentCharacter();
658 }
659 while(c == '-')
660 {
661 buzzerSequence ++;
662 note --;
663 c = currentCharacter();
664 }
665
666 // set the duration of just this note
667 tmp_duration = duration;
668
669 // If the input is 'c16', make it a 16th note, etc.
670 if(c > '0' && c < '9')
671 tmp_duration = whole_note_duration/getNumber();
672
673 // Handle dotted notes - the first dot adds 50%, and each
674 // additional dot adds 50% of the previous dot.
675 dot_add = tmp_duration/2;
676 while(currentCharacter() == '.')
677 {
678 buzzerSequence ++;
679 tmp_duration += dot_add;
680 dot_add /= 2;
681 }
682
683 if(staccato)
684 {
685 staccato_rest_duration = tmp_duration / 2;
686 tmp_duration -= staccato_rest_duration;
687 }
688
689 // this will re-enable the timer overflow interrupt
690 PololuBuzzer::playNote(rest ? SILENT_NOTE : note, tmp_duration, volume);
691}
692
693
694// This puts play() into a mode where instead of advancing to the
695// next note in the sequence automatically, it waits until the
696// function playCheck() is called. The idea is that you can
697// put playCheck() in your main loop and avoid potential
698// delays due to the note sequence being checked in the middle of
699// a time sensitive calculation. It is recommended that you use
700// this function if you are doing anything that can't tolerate
701// being interrupted for more than a few microseconds.
702// Note that the play mode can be changed while a sequence is being
703// played.
704//
705// Usage: playMode(PLAY_AUTOMATIC) makes it automatic (the
706// default), playMode(PLAY_CHECK) sets it to a mode where you have
707// to call playCheck().
708void PololuBuzzer::playMode(unsigned char mode)
709{
710 play_mode_setting = mode;
711
712 // We want to check to make sure that we didn't miss a note if we
713 // are going out of play-check mode.
714 if(mode == PLAY_AUTOMATIC)
715 playCheck();
716}
717
718
719// Checks whether it is time to start another note, and starts
720// it if so. If it is not yet time to start the next note, this method
721// returns without doing anything. Call this as often as possible
722// in your main loop to avoid delays between notes in the sequence.
723//
724// Returns true if it is still playing.
726{
727 if(buzzerFinished && buzzerSequence != 0)
728 nextNote();
729 return buzzerSequence != 0;
730}
#define DIV_BY_10
frequency bit that indicates Hz/10 e.g. frequency = (445 | DIV_BY_10) gives a frequency of 44....
Definition: PololuBuzzer.h:86
#define PLAY_AUTOMATIC
Specifies that the sequence of notes will play with no further action required by the user.
Definition: PololuBuzzer.h:42
#define SILENT_NOTE
silences buzzer for the note duration
Definition: PololuBuzzer.h:81
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().