Priyata Kaneria / Robot Control Interface: From Arduino to ARM Mbed
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PololuBuzzer.cpp Source File

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 }