silabs-abakurs / Mbed 2 deprecated PwmSpeaker

Dependencies:   mbed

Dependents:   PwmSpeaker-Example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Speaker.cpp Source File

Speaker.cpp

00001 #include "Speaker.h"
00002 
00003 static int notes[] = {0,
00004         NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
00005         NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
00006         NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
00007         NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
00008 };
00009 
00010 /**
00011  * Set output frequency of the speaker.
00012  *
00013  * \param frequency The frequency to set
00014  */
00015 void Speaker::set_frequency(uint32_t frequency) {
00016     _pwm.period(1.0/frequency);
00017 }
00018 
00019 /**
00020  * Enable or disable speaker output.
00021  *
00022  * \param enable Whether to enable or disable the speaker
00023  */
00024 void Speaker::enable(bool enable) {
00025     *this = enable;
00026 }
00027 
00028 /**
00029  * Enable or disable the speaker output.
00030  *
00031  * \param setting 0 to disable speaker, other values to enable speaker.
00032  */
00033 Speaker& Speaker::operator=(int setting) {
00034     if (setting) {
00035         _pwm = 0.5;
00036     } else {
00037         _pwm = 1;
00038     }
00039     return *this;    
00040 }
00041 
00042 /**
00043  * Play an old-school ringtone in RTTTL language.
00044  *
00045  * \param p Char array in RTTTL format
00046  */
00047 void Speaker::play_rtttl(char * p) {
00048   // Absolutely no error checking in here
00049 
00050   uint8_t default_dur = 4;
00051   uint8_t default_oct = 6;
00052   int bpm = 63;
00053   int num;
00054   long wholenote;
00055   long duration;
00056   uint8_t note;
00057   uint8_t scale;
00058 
00059   // format: d=N,o=N,b=NNN:
00060   // find the start (skip name, etc)
00061 
00062   while(*p != ':') p++;    // ignore name
00063   p++;                     // skip ':'
00064 
00065   // get default duration
00066   if(*p == 'd')
00067   {
00068     p++; p++;              // skip "d="
00069     num = 0;
00070     while(isdigit(*p))
00071     {
00072       num = (num * 10) + (*p++ - '0');
00073     }
00074     if(num > 0) default_dur = num;
00075     p++;                   // skip comma
00076   }
00077 
00078   printf("ddur: %d\n", default_dur);
00079 
00080   // get default octave
00081   if(*p == 'o')
00082   {
00083     p++; p++;              // skip "o="
00084     num = *p++ - '0';
00085     if(num >= 3 && num <=7) default_oct = num;
00086     p++;                   // skip comma
00087   }
00088 
00089   printf("doct: %d\n", default_oct);
00090 
00091   // get BPM
00092   if(*p == 'b')
00093   {
00094     p++; p++;              // skip "b="
00095     num = 0;
00096     while(isdigit(*p))
00097     {
00098       num = (num * 10) + (*p++ - '0');
00099     }
00100     bpm = num;
00101     p++;                   // skip colon
00102   }
00103 
00104   printf("bpm: %d\n",bpm);
00105 
00106   // BPM usually expresses the number of quarter notes per minute
00107   wholenote = (60 * 1000L / bpm) * 4;  // this is the time for whole note (in milliseconds)
00108 
00109   printf("wn: %d\n", wholenote);
00110 
00111 
00112   // now begin note loop
00113   while(*p)
00114   {
00115     // first, get note duration, if available
00116     num = 0;
00117     while(isdigit(*p))
00118     {
00119       num = (num * 10) + (*p++ - '0');
00120     }
00121 
00122     if(num) duration = wholenote / num;
00123     else duration = wholenote / default_dur;  // we will need to check if we are a dotted note after
00124 
00125     // now get the note
00126     note = 0;
00127 
00128     switch(*p)
00129     {
00130       case 'c':
00131         note = 1;
00132         break;
00133       case 'd':
00134         note = 3;
00135         break;
00136       case 'e':
00137         note = 5;
00138         break;
00139       case 'f':
00140         note = 6;
00141         break;
00142       case 'g':
00143         note = 8;
00144         break;
00145       case 'a':
00146         note = 10;
00147         break;
00148       case 'b':
00149         note = 12;
00150         break;
00151       case 'p':
00152       default:
00153         note = 0;
00154     }
00155     p++;
00156 
00157     // now, get optional '#' sharp
00158     if(*p == '#')
00159     {
00160       note++;
00161       p++;
00162     }
00163 
00164     // now, get optional '.' dotted note
00165     if(*p == '.')
00166     {
00167       duration += duration/2;
00168       p++;
00169     }
00170 
00171     // now, get scale
00172     if(isdigit(*p))
00173     {
00174       scale = *p - '0';
00175       p++;
00176     }
00177     else
00178     {
00179       scale = default_oct;
00180     }
00181 
00182     scale += _offset;
00183 
00184     if(*p == ',')
00185       p++;       // skip comma for next note (or we may be at the end)
00186 
00187     // now play the note
00188 
00189     if(note)
00190     {
00191       //printf("\027\033H");
00192       //printf("Playing: %d %d (%d) %d\n", scale, note, notes[(scale - 4) * 12 + note], duration);
00193       set_frequency(notes[(scale - 4) * 12 + note]);
00194       enable(true);
00195       wait_ms(duration);
00196       enable(false);
00197     }
00198     else
00199     {
00200       //printf("Pausing: %d\n", duration);
00201       wait_ms(duration);
00202     }
00203   }
00204 }