Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PololuBuzzer.cpp
00001 #include "PololuBuzzer.h" 00002 #include "mbed.h" 00003 00004 using namespace mbed; 00005 // constructor 00006 /** Create a Beep object connected to the specified PwmOut pin 00007 * 00008 * @param pin PwmOut pin to connect to 00009 */ 00010 00011 BuzzerValues::BuzzerValues(float frequency, float duration, float volume) : freq(frequency), dur(duration), vol(volume) {} 00012 BuzzerValues::BuzzerValues() {} 00013 void BuzzerValues::changeValue(float frequency, float duration, float volume) { 00014 freq = frequency; 00015 dur = duration; 00016 vol = volume; 00017 } 00018 float BuzzerValues::returnFrequency() { 00019 return freq; 00020 } 00021 float BuzzerValues::returnDuration() { 00022 return dur; 00023 } 00024 float BuzzerValues::returnVolume() { 00025 return vol; 00026 } 00027 00028 #define BUZZER_DDR DDRD 00029 #define BUZZER (1 << PORTD3) 00030 00031 #define TIMER2_CLK_32 0x3 // 500 kHz 00032 00033 static const unsigned int cs2_divider[] = {0, 1, 8, 32, 64, 128, 256, 1024}; 00034 00035 #define ENABLE_TIMER_INTERRUPT() TIMSK2 = (1 << TOIE2) 00036 #define DISABLE_TIMER_INTERRUPT() TIMSK2 = 0 00037 00038 unsigned char buzzerInitialized = 0; 00039 volatile unsigned char buzzerFinished = 1; // flag: 0 while playing 00040 const char * volatile buzzerSequence = 0; 00041 00042 // declaring these globals as static means they won't conflict 00043 // with globals in other .cpp files that share the same name 00044 static volatile unsigned int buzzerTimeout = 0; // tracks buzzer time limit 00045 static volatile char play_mode_setting = PLAY_AUTOMATIC; 00046 00047 extern volatile unsigned char buzzerFinished; // flag: 0 while playing 00048 extern const char * volatile buzzerSequence; 00049 00050 00051 static volatile unsigned char use_program_space; // boolean: true if we should 00052 // use program space 00053 00054 // music settings and defaults 00055 static volatile unsigned char octave = 4; // the current octave 00056 static volatile unsigned int whole_note_duration = 2000; // the duration of a whole note 00057 static volatile unsigned int note_type = 4; // 4 for quarter, etc 00058 static volatile unsigned int duration = 500; // the duration of a note in ms 00059 static volatile unsigned int volume = 15; // the note volume 00060 static volatile unsigned char staccato = 0; // true if playing staccato 00061 00062 // staccato handling 00063 static volatile unsigned char staccato_rest_duration; // duration of a staccato rest, 00064 // or zero if it is time to play a note 00065 00066 static void nextNote(); 00067 00068 PololuBuzzer::PololuBuzzer(PinName pin) : _pwm(pin), playing(0) { 00069 _pwm.write(0.0); // after creating it have to be off 00070 } 00071 00072 /** stop the beep instantaneous 00073 * usually not used 00074 */ 00075 void PololuBuzzer::nobeep() { 00076 _pwm.write(0.0); 00077 buzzerFinished = 1; 00078 buzzerSequence = 0; 00079 if (buzzerSequence && (play_mode_setting == PLAY_AUTOMATIC)) 00080 nextNote(); 00081 else 00082 isPlaying2(0); 00083 } 00084 00085 /** Beep with given frequency and duration. 00086 * 00087 * @param frequency - the frequency of the tone in Hz 00088 * @param time - the duration of the tone in seconds 00089 */ 00090 00091 bool PololuBuzzer::isPlaying2(int request){ 00092 if (request == 0) { 00093 playing = false; 00094 } 00095 else if (request == 1){ 00096 playing = true; 00097 } 00098 return playing; 00099 } 00100 00101 void PololuBuzzer::beep(float freq, float time, float volume) { 00102 _pwm.period(1.0/freq); 00103 _pwm.write(0.5); // 50% duty cycle - beep on 00104 float newTime = (time/500); 00105 toff.attach(callback(this, &PololuBuzzer::nobeep), newTime); 00106 } 00107 00108 // Timer2 overflow interrupt 00109 // ISR (TIMER2_OVF_vect) 00110 // { 00111 // if (buzzerTimeout-- == 0) 00112 // { 00113 // DISABLE_TIMER_INTERRUPT(); 00114 // sei(); // re-enable global interrupts (nextNote() is very slow) 00115 // TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32; // select IO clock 00116 // OCR2A = (F_CPU/64) / 1000; // set TOP for freq = 1 kHz 00117 // OCR2B = 0; // 0% duty cycle 00118 // buzzerFinished = 1; 00119 // if (buzzerSequence && (play_mode_setting == PLAY_AUTOMATIC)) 00120 // nextNote(); 00121 // } 00122 // } 00123 00124 00125 // this is called by playFrequency() 00126 inline void PololuBuzzer::init() 00127 { 00128 if (!buzzerInitialized) 00129 { 00130 buzzerInitialized = 1; 00131 //init2(); 00132 } 00133 } 00134 00135 // initializes timer4 (32U4) or timer2 (328P) for buzzer control 00136 // void PololuBuzzer::init2() 00137 // { 00138 // DISABLE_TIMER_INTERRUPT(); 00139 00140 // TCCR2A = 0x21; // bits 7 and 6 clear: normal port op., OC4A disconnected 00141 // // bit 5 set, 4 clear: clear OC2B on comp match when upcounting, 00142 // // set OC2B on comp match when downcounting 00143 // // bits 3 and 2: not used 00144 // // bit 1 clear, 0 set: combine with bit 3 of TCCR2B... 00145 00146 // TCCR2B = 0x0B; // bit 7 clear: no force output compare for channel A 00147 // // bit 6 clear: no force output compare for channel B 00148 // // bits 5 and 4: not used 00149 // // bit 3 set: combine with bits 1 and 0 of TCCR2A to 00150 // // select waveform generation mode 5, phase-correct PWM, 00151 // // TOP = OCR2A, OCR2B set at TOP, TOV2 flag set at BOTTOM 00152 // // bit 2 clear, 1-0 set: timer clock = clkT2S/32 00153 00154 // This sets timer 2 to run in phase-correct PWM mode, where TOP = OCR2A, 00155 // OCR2B is updated at TOP, TOV2 Flag is set on BOTTOM. OC2B is cleared 00156 // on compare match when upcounting, set on compare match when downcounting; 00157 // OC2A is disconnected. 00158 // Note: if the PWM frequency and duty cycle are changed, the first 00159 // cycle of the new frequency will be at the old duty cycle, since 00160 // the duty cycle (OCR2B) is not updated until TOP. 00161 00162 00163 // OCR2A = (F_CPU/64) / 1000; // set TOP for freq = 1 kHz 00164 // OCR2B = 0; // 0% duty cycle 00165 00166 // BUZZER_DDR |= BUZZER; // buzzer pin set as an output 00167 // sei(); 00168 // } 00169 00170 00171 // Set up the timer to play the desired frequency (in Hz or .1 Hz) for the 00172 // the desired duration (in ms). Allowed frequencies are 40 Hz to 10 kHz. 00173 // volume controls buzzer volume, with 15 being loudest and 0 being quietest. 00174 // Note: frequency*duration/1000 must be less than 0xFFFF (65535). This 00175 // means that you can't use a max duration of 65535 ms for frequencies 00176 // greater than 1 kHz. For example, the max duration you can use for a 00177 // frequency of 10 kHz is 6553 ms. If you use a duration longer than this, 00178 // you will cause an integer overflow that produces unexpected behavior. 00179 BuzzerValues PololuBuzzer::playFrequency(unsigned int freq, unsigned int dur, 00180 unsigned char volume) 00181 { 00182 init(); // initializes the buzzer if necessary 00183 buzzerFinished = 0; 00184 00185 unsigned int timeout; 00186 unsigned char multiplier = 1; 00187 00188 if (freq & DIV_BY_10) // if frequency's DIV_BY_10 bit is set 00189 { // then the true frequency is freq/10 00190 multiplier = 10; // (gives higher resolution for small freqs) 00191 freq &= ~DIV_BY_10; // clear DIV_BY_10 bit 00192 } 00193 00194 unsigned char min = 40 * multiplier; 00195 if (freq < min) // min frequency allowed is 40 Hz 00196 freq = min; 00197 if (multiplier == 1 && freq > 10000) 00198 freq = 10000; // max frequency allowed is 10kHz 00199 00200 // unsigned int top; 00201 // unsigned char newCS2 = 2; // try prescaler divider of 8 first (minimum necessary for 10 kHz) 00202 // unsigned int divider = cs2_divider[newCS2]; 00203 00204 // // calculate necessary clock source and counter top value to get freq 00205 // top = (unsigned int)(((F_CPU/16 * multiplier) + (freq >> 1))/ freq); 00206 00207 // while (top > 255) 00208 // { 00209 // divider = cs2_divider[++newCS2]; 00210 // top = (unsigned int)(((F_CPU/2/divider * multiplier) + (freq >> 1))/ freq); 00211 // } 00212 00213 // set timeout (duration): 00214 if (multiplier == 10) 00215 freq = (freq + 5) / 10; 00216 00217 if (freq == 1000) 00218 timeout = dur; // duration for silent notes is exact 00219 else 00220 timeout = (unsigned int)((long)dur * freq / 1000); 00221 00222 if (volume > 15) 00223 volume = 15; 00224 00225 BuzzerValues buzz(freq,timeout,volume); 00226 return buzz; 00227 00228 // DISABLE_TIMER_INTERRUPT(); // disable interrupts while writing to registers 00229 00230 // TCCR2B = (TCCR2B & 0xF8) | newCS2; // select timer 2 clock prescaler 00231 // OCR2A = top; // set timer 2 pwm frequency 00232 // OCR2B = top >> (16 - volume); // set duty cycle (volume) 00233 // buzzerTimeout = timeout; // set buzzer duration 00234 00235 // TIFR2 |= 0xFF; // clear any pending t2 overflow int. 00236 00237 // ENABLE_TIMER_INTERRUPT(); 00238 } 00239 00240 00241 00242 // Determine the frequency for the specified note, then play that note 00243 // for the desired duration (in ms). This is done without using floats 00244 // and without having to loop. volume controls buzzer volume, with 15 being 00245 // loudest and 0 being quietest. 00246 // Note: frequency*duration/1000 must be less than 0xFFFF (65535). This 00247 // means that you can't use a max duration of 65535 ms for frequencies 00248 // greater than 1 kHz. For example, the max duration you can use for a 00249 // frequency of 10 kHz is 6553 ms. If you use a duration longer than this, 00250 // you will cause an integer overflow that produces unexpected behavior. 00251 BuzzerValues PololuBuzzer::playNote(unsigned char note, unsigned int dur, 00252 unsigned char volume) 00253 { 00254 // note = key + octave * 12, where 0 <= key < 12 00255 // example: A4 = A + 4 * 12, where A = 9 (so A4 = 57) 00256 // A note is converted to a frequency by the formula: 00257 // Freq(n) = Freq(0) * a^n 00258 // where 00259 // Freq(0) is chosen as A4, which is 440 Hz 00260 // and 00261 // a = 2 ^ (1/12) 00262 // n is the number of notes you are away from A4. 00263 // One can see that the frequency will double every 12 notes. 00264 // This function exploits this property by defining the frequencies of the 00265 // 12 lowest notes allowed and then doubling the appropriate frequency 00266 // the appropriate number of times to get the frequency for the specified 00267 // note. 00268 00269 // if note = 16, freq = 41.2 Hz (E1 - lower limit as freq must be >40 Hz) 00270 // if note = 57, freq = 440 Hz (A4 - central value of ET Scale) 00271 // if note = 111, freq = 9.96 kHz (D#9 - upper limit, freq must be <10 kHz) 00272 // if note = 255, freq = 1 kHz and buzzer is silent (silent note) 00273 00274 // The most significant bit of freq is the "divide by 10" bit. If set, 00275 // the units for frequency are .1 Hz, not Hz, and freq must be divided 00276 // by 10 to get the true frequency in Hz. This allows for an extra digit 00277 // of resolution for low frequencies without the need for using floats. 00278 00279 unsigned int freq = 0; 00280 unsigned char offset_note = note - 16; 00281 BuzzerValues buzz; 00282 00283 if (note == SILENT_NOTE || volume == 0) 00284 { 00285 freq = 1000; // silent notes => use 1kHz freq (for cycle counter) 00286 buzz.changeValue(freq,dur,volume); 00287 // buzz = playFrequency(freq, dur, 0); 00288 // return buzz; 00289 } 00290 else { 00291 if (note <= 16) 00292 offset_note = 0; 00293 else if (offset_note > 95) 00294 offset_note = 95; 00295 00296 unsigned char exponent = offset_note / 12; 00297 00298 // frequency table for the lowest 12 allowed notes 00299 // frequencies are specified in tenths of a Hertz for added resolution 00300 switch (offset_note - exponent * 12) // equivalent to (offset_note % 12) 00301 { 00302 case 0: // note E1 = 41.2 Hz 00303 freq = 412; 00304 break; 00305 case 1: // note F1 = 43.7 Hz 00306 freq = 437; 00307 break; 00308 case 2: // note F#1 = 46.3 Hz 00309 freq = 463; 00310 break; 00311 case 3: // note G1 = 49.0 Hz 00312 freq = 490; 00313 break; 00314 case 4: // note G#1 = 51.9 Hz 00315 freq = 519; 00316 break; 00317 case 5: // note A1 = 55.0 Hz 00318 freq = 550; 00319 break; 00320 case 6: // note A#1 = 58.3 Hz 00321 freq = 583; 00322 break; 00323 case 7: // note B1 = 61.7 Hz 00324 freq = 617; 00325 break; 00326 case 8: // note C2 = 65.4 Hz 00327 freq = 654; 00328 break; 00329 case 9: // note C#2 = 69.3 Hz 00330 freq = 693; 00331 break; 00332 case 10: // note D2 = 73.4 Hz 00333 freq = 734; 00334 break; 00335 case 11: // note D#2 = 77.8 Hz 00336 freq = 778; 00337 break; 00338 } 00339 if (exponent < 7) 00340 { 00341 freq = freq << exponent; // frequency *= 2 ^ exponent 00342 if (exponent > 1) // if the frequency is greater than 160 Hz 00343 freq = (freq + 5) / 10; // we don't need the extra resolution 00344 else 00345 freq += DIV_BY_10; // else keep the added digit of resolution 00346 } 00347 else 00348 freq = (freq * 64 + 2) / 5; // == freq * 2^7 / 10 without int overflow 00349 00350 if (volume > 15) 00351 volume = 15; 00352 buzz = playFrequency(freq, dur, volume); // set buzzer this freq/duration 00353 } 00354 return buzz; 00355 } 00356 00357 00358 00359 // Returns 1 if the buzzer is currently playing, otherwise it returns 0 00360 unsigned char PololuBuzzer::isPlaying() 00361 { 00362 return !buzzerFinished || buzzerSequence != 0; 00363 } 00364 00365 00366 // Plays the specified sequence of notes. If the play mode is 00367 // PLAY_AUTOMATIC, the sequence of notes will play with no further 00368 // action required by the user. If the play mode is PLAY_CHECK, 00369 // the user will need to call playCheck() in the main loop to initiate 00370 // the playing of each new note in the sequence. The play mode can 00371 // be changed while the sequence is playing. 00372 // This is modeled after the PLAY commands in GW-BASIC, with just a 00373 // few differences. 00374 // 00375 // The notes are specified by the characters C, D, E, F, G, A, and 00376 // B, and they are played by default as "quarter notes" with a 00377 // length of 500 ms. This corresponds to a tempo of 120 00378 // beats/min. Other durations can be specified by putting a number 00379 // immediately after the note. For example, C8 specifies C played as an 00380 // eighth note, with half the duration of a quarter note. The special 00381 // note R plays a rest (no sound). 00382 // 00383 // Various control characters alter the sound: 00384 // '>' plays the next note one octave higher 00385 // 00386 // '<' plays the next note one octave lower 00387 // 00388 // '+' or '#' after a note raises any note one half-step 00389 // 00390 // '-' after a note lowers any note one half-step 00391 // 00392 // '.' after a note "dots" it, increasing the length by 00393 // 50%. Each additional dot adds half as much as the 00394 // previous dot, so that "A.." is 1.75 times the length of 00395 // "A". 00396 // 00397 // 'O' followed by a number sets the octave (default: O4). 00398 // 00399 // 'T' followed by a number sets the tempo (default: T120). 00400 // 00401 // 'L' followed by a number sets the default note duration to 00402 // the type specified by the number: 4 for quarter notes, 8 00403 // for eighth notes, 16 for sixteenth notes, etc. 00404 // (default: L4) 00405 // 00406 // 'V' followed by a number from 0-15 sets the music volume. 00407 // (default: V15) 00408 // 00409 // 'MS' sets all subsequent notes to play staccato - each note is played 00410 // for 1/2 of its allotted time, followed by an equal period 00411 // of silence. 00412 // 00413 // 'ML' sets all subsequent notes to play legato - each note is played 00414 // for its full length. This is the default setting. 00415 // 00416 // '!' resets all persistent settings to their defaults. 00417 // 00418 // The following plays a c major scale up and back down: 00419 // play("L16 V8 cdefgab>cbagfedc"); 00420 // 00421 // Here is an example from Bach: 00422 // play("T240 L8 a gafaeada c+adaeafa <aa<bac#ada c#adaeaf4"); 00423 void PololuBuzzer::play(const char *notes) 00424 { 00425 // DISABLE_TIMER_INTERRUPT(); // prevent this from being interrupted 00426 buzzerSequence = notes; 00427 use_program_space = 0; 00428 staccato_rest_duration = 0; 00429 nextNote(); // this re-enables the timer interrupt 00430 } 00431 00432 void PololuBuzzer::playFromProgramSpace(const char *notes_p) 00433 { 00434 // DISABLE_TIMER_INTERRUPT(); // prevent this from being interrupted 00435 buzzerSequence = notes_p; 00436 use_program_space = 1; 00437 staccato_rest_duration = 0; 00438 nextNote(); // this re-enables the timer interrupt 00439 } 00440 00441 00442 // // stop all sound playback immediately 00443 // void PololuBuzzer::stopPlaying() 00444 // { 00445 // DISABLE_TIMER_INTERRUPT(); // disable interrupts 00446 00447 00448 // TCCR2B = (TCCR2B & 0xF8) | TIMER2_CLK_32; // select IO clock 00449 // OCR2A = (F_CPU/64) / 1000; // set TOP for freq = 1 kHz 00450 // OCR2B = 0; // 0% duty cycle 00451 00452 // buzzerFinished = 1; 00453 // buzzerSequence = 0; 00454 // } 00455 00456 // Gets the current character, converting to lower-case and skipping 00457 // spaces. For any spaces, this automatically increments sequence! 00458 static char currentCharacter() 00459 { 00460 char c = 0; 00461 do 00462 { 00463 // if(use_program_space) 00464 // c = pgm_read_byte(buzzerSequence); 00465 // else 00466 c = *buzzerSequence; 00467 00468 if(c >= 'A' && c <= 'Z') 00469 c += 'a'-'A'; 00470 } while(c == ' ' && (buzzerSequence ++)); 00471 00472 return c; 00473 } 00474 00475 // Returns the numerical argument specified at buzzerSequence[0] and 00476 // increments sequence to point to the character immediately after the 00477 // argument. 00478 static unsigned int getNumber() 00479 { 00480 unsigned int arg = 0; 00481 00482 // read all digits, one at a time 00483 char c = currentCharacter(); 00484 while(c >= '0' && c <= '9') 00485 { 00486 arg *= 10; 00487 arg += c-'0'; 00488 buzzerSequence ++; 00489 c = currentCharacter(); 00490 } 00491 00492 return arg; 00493 } 00494 00495 static void nextNote() 00496 { 00497 unsigned char note = 0; 00498 unsigned char rest = 0; 00499 unsigned char tmp_octave = octave; // the octave for this note 00500 unsigned int tmp_duration; // the duration of this note 00501 unsigned int dot_add; 00502 00503 char c; // temporary variable 00504 00505 // if we are playing staccato, after every note we play a rest 00506 if(staccato && staccato_rest_duration) 00507 { 00508 PololuBuzzer::playNote(SILENT_NOTE, staccato_rest_duration, 0); 00509 staccato_rest_duration = 0; 00510 return; 00511 } 00512 00513 parse_character: 00514 00515 // Get current character 00516 c = currentCharacter(); 00517 buzzerSequence ++; 00518 00519 // Interpret the character. 00520 switch(c) 00521 { 00522 case '>': 00523 // shift the octave temporarily up 00524 tmp_octave ++; 00525 goto parse_character; 00526 case '<': 00527 // shift the octave temporarily down 00528 tmp_octave --; 00529 goto parse_character; 00530 case 'a': 00531 note = NOTE_A(0); 00532 break; 00533 case 'b': 00534 note = NOTE_B(0); 00535 break; 00536 case 'c': 00537 note = NOTE_C(0); 00538 break; 00539 case 'd': 00540 note = NOTE_D(0); 00541 break; 00542 case 'e': 00543 note = NOTE_E(0); 00544 break; 00545 case 'f': 00546 note = NOTE_F(0); 00547 break; 00548 case 'g': 00549 note = NOTE_G(0); 00550 break; 00551 case 'l': 00552 // set the default note duration 00553 note_type = getNumber(); 00554 duration = whole_note_duration/note_type; 00555 goto parse_character; 00556 case 'm': 00557 // set music staccato or legato 00558 if(currentCharacter() == 'l') 00559 staccato = false; 00560 else 00561 { 00562 staccato = true; 00563 staccato_rest_duration = 0; 00564 } 00565 buzzerSequence ++; 00566 goto parse_character; 00567 case 'o': 00568 // set the octave permanently 00569 octave = tmp_octave = getNumber(); 00570 goto parse_character; 00571 case 'r': 00572 // Rest - the note value doesn't matter. 00573 rest = 1; 00574 break; 00575 case 't': 00576 // set the tempo 00577 whole_note_duration = 60*400/getNumber()*10; 00578 duration = whole_note_duration/note_type; 00579 goto parse_character; 00580 case 'v': 00581 // set the volume 00582 volume = getNumber(); 00583 goto parse_character; 00584 case '!': 00585 // reset to defaults 00586 octave = 4; 00587 whole_note_duration = 2000; 00588 note_type = 4; 00589 duration = 500; 00590 volume = 15; 00591 staccato = 0; 00592 // reset temp variables that depend on the defaults 00593 tmp_octave = octave; 00594 tmp_duration = duration; 00595 goto parse_character; 00596 default: 00597 buzzerSequence = 0; 00598 return; 00599 } 00600 00601 note += tmp_octave*12; 00602 00603 // handle sharps and flats 00604 c = currentCharacter(); 00605 while(c == '+' || c == '#') 00606 { 00607 buzzerSequence ++; 00608 note ++; 00609 c = currentCharacter(); 00610 } 00611 while(c == '-') 00612 { 00613 buzzerSequence ++; 00614 note --; 00615 c = currentCharacter(); 00616 } 00617 00618 // set the duration of just this note 00619 tmp_duration = duration; 00620 00621 // If the input is 'c16', make it a 16th note, etc. 00622 if(c > '0' && c < '9') 00623 tmp_duration = whole_note_duration/getNumber(); 00624 00625 // Handle dotted notes - the first dot adds 50%, and each 00626 // additional dot adds 50% of the previous dot. 00627 dot_add = tmp_duration/2; 00628 while(currentCharacter() == '.') 00629 { 00630 buzzerSequence ++; 00631 tmp_duration += dot_add; 00632 dot_add /= 2; 00633 } 00634 00635 if(staccato) 00636 { 00637 staccato_rest_duration = tmp_duration / 2; 00638 tmp_duration -= staccato_rest_duration; 00639 } 00640 00641 // this will re-enable the timer overflow interrupt 00642 PololuBuzzer::playNote(rest ? SILENT_NOTE : note, tmp_duration, volume); 00643 // wait_ms(tmp_duration); 00644 } 00645 00646 00647 // This puts play() into a mode where instead of advancing to the 00648 // next note in the sequence automatically, it waits until the 00649 // function playCheck() is called. The idea is that you can 00650 // put playCheck() in your main loop and avoid potential 00651 // delays due to the note sequence being checked in the middle of 00652 // a time sensitive calculation. It is recommended that you use 00653 // this function if you are doing anything that can't tolerate 00654 // being interrupted for more than a few microseconds. 00655 // Note that the play mode can be changed while a sequence is being 00656 // played. 00657 // 00658 // Usage: playMode(PLAY_AUTOMATIC) makes it automatic (the 00659 // default), playMode(PLAY_CHECK) sets it to a mode where you have 00660 // to call playCheck(). 00661 void PololuBuzzer::playMode(unsigned char mode) 00662 { 00663 play_mode_setting = mode; 00664 00665 // We want to check to make sure that we didn't miss a note if we 00666 // are going out of play-check mode. 00667 if(mode == PLAY_AUTOMATIC) 00668 playCheck(); 00669 } 00670 00671 00672 // Checks whether it is time to start another note, and starts 00673 // it if so. If it is not yet time to start the next note, this method 00674 // returns without doing anything. Call this as often as possible 00675 // in your main loop to avoid delays between notes in the sequence. 00676 // 00677 // Returns true if it is still playing. 00678 unsigned char PololuBuzzer::playCheck() 00679 { 00680 if(buzzerFinished && buzzerSequence != 0) 00681 nextNote(); 00682 return buzzerSequence != 0; 00683 }
Generated on Tue Jul 12 2022 20:24:48 by
1.7.2