rtttl
rtttl/rtttl.h
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #if defined(ARDUINO) && ARDUINO >= 100
00004 # include "Arduino.h"
00005 #else
00006 # include "WProgram.h"
00007 # include "pins_arduino.h"
00008 #endif
00009 
00010 #include <avr/pgmspace.h>
00011 #include <notes.h>
00012 
00013 #define isdigit(n) (n >= '0' && n <= '9')
00014 
00015 inline char read_byte(const char *p, bool pgm)
00016 {
00017     if (pgm)
00018         return pgm_read_byte(p);
00019     else
00020         return *p;
00021 }
00022 
00023 inline uint16_t read_word(const uint16_t *p, bool pgm)
00024 {
00025     if (pgm)
00026         return pgm_read_word(p);
00027     else
00028         return *p;
00029 }
00030 
00031 const prog_uint16_t notes[] PROGMEM =
00032 {   0, //
00033     NOTE_C4, //
00034     NOTE_CS4, //
00035     NOTE_D4, //
00036     NOTE_DS4, //
00037     NOTE_E4, //
00038     NOTE_F4, //
00039     NOTE_FS4, //
00040     NOTE_G4, //
00041     NOTE_GS4, //
00042     NOTE_A4, //
00043     NOTE_AS4, //
00044     NOTE_B4, //
00045 
00046     NOTE_C5, //
00047     NOTE_CS5, //
00048     NOTE_D5, //
00049     NOTE_DS5, //
00050     NOTE_E5, //
00051     NOTE_F5, //
00052     NOTE_FS5, //
00053     NOTE_G5, //
00054     NOTE_GS5, //
00055     NOTE_A5, //
00056     NOTE_AS5, //
00057     NOTE_B5, //
00058 
00059     NOTE_C6, //
00060     NOTE_CS6, //
00061     NOTE_D6, //
00062     NOTE_DS6, //
00063     NOTE_E6, //
00064     NOTE_F6, //
00065     NOTE_FS6, //
00066     NOTE_G6, //
00067     NOTE_GS6, //
00068     NOTE_A6, //
00069     NOTE_AS6, //
00070     NOTE_B6, //
00071 
00072     NOTE_C7, //
00073     NOTE_CS7, //
00074     NOTE_D7, //
00075     NOTE_DS7, //
00076     NOTE_E7, //
00077     NOTE_F7, //
00078     NOTE_FS7, //
00079     NOTE_G7, //
00080     NOTE_GS7, //
00081     NOTE_A7, //
00082     NOTE_AS7, //
00083     NOTE_B7, //
00084 
00085     2*NOTE_C7, //
00086     2*NOTE_CS7, //
00087     2*NOTE_D7, //
00088     2*NOTE_DS7, //
00089     2*NOTE_E7, //
00090     2*NOTE_F7, //
00091     2*NOTE_FS7, //
00092     2*NOTE_G7, //
00093     2*NOTE_GS7, //
00094     2*NOTE_A7, //
00095     2*NOTE_AS7, //
00096     2*NOTE_B7, //
00097     0
00098 };
00099 
00100 /*
00101  *
00102  * playing RTTTL music files in blocking mode
00103  * http://en.wikipedia.org/wiki/Ring_Tone_Transfer_Language
00104  *
00105  * based on Tone library demo
00106  *
00107  */
00108 class Rtttl
00109 {
00110     uint8_t _pinSpk;
00111 #ifdef _Tone_h
00112     Tone m_tone;
00113 #endif
00114 
00115 public:
00116     Rtttl()
00117     {
00118         //      this->begin(tonePin);
00119     }
00120 
00121     void begin(uint8_t tonePin)
00122     {
00123         this->_pinSpk = tonePin;
00124 #ifdef _Tone_h
00125         //      Serial.println("begin");
00126         //      Serial.println(tonePin, DEC);
00127         this->m_tone.begin(tonePin);
00128         //      Serial.println("begin");
00129 #endif
00130 
00131     }
00132 
00133 #ifdef _Tone_h
00134     void _tone(uint16_t freq)
00135     {
00136         //      Serial.println(freq);
00137         this->m_tone.play(freq);
00138     }
00139 
00140     void _noTone()
00141     {
00142         //      Serial.println("1stop");
00143         this->m_tone.stop();
00144     }
00145 #else
00146     void _tone(uint16_t freq)
00147     {
00148         //      Serial.println(freq);
00149         tone(this->_pinSpk, freq);
00150     }
00151 
00152     void _noTone()
00153     {
00154         //      Serial.println("2stop");
00155         noTone(this->_pinSpk);
00156     }
00157 #endif
00158 
00159     void play_P(const prog_char *p, uint8_t octave_offset = 0)
00160     {
00161         _play(p, octave_offset, true);
00162     }
00163     void play(const char *p, uint8_t octave_offset = 0)
00164     {
00165         _play(p, octave_offset, false);
00166     }
00167 
00168     void _play(const prog_char *p, uint8_t octave_offset, bool pgm)
00169     {
00170         // Absolutely no error checking in here
00171 
00172         byte default_dur = 4;
00173         byte default_oct = 6;
00174         int bpm = 63;
00175         int num;
00176         long wholenote;
00177         long duration;
00178         byte note;
00179         byte scale;
00180 
00181         // format: d=N,o=N,b=NNN:
00182         // find the start (skip name, etc)
00183 
00184         while (read_byte(p, pgm) != ':')
00185             p++; // ignore name
00186         p++; // skip ':'
00187 
00188         // get default duration
00189         if (read_byte(p, pgm) == 'd')
00190         {
00191             p++;
00192             p++; // skip "d="
00193             num = 0;
00194             while (isdigit(read_byte(p, pgm)))
00195             {
00196                 num = (num * 10) + (read_byte(p, pgm) - '0');
00197                 p++;
00198             }
00199             if (num > 0)
00200                 default_dur = num;
00201             p++; // skip comma
00202         }
00203 
00204         // get default octave
00205         if (read_byte(p, pgm) == 'o')
00206         {
00207             p++;
00208             p++; // skip "o="
00209             num = read_byte(p, pgm) - '0';
00210             p++;
00211             if (num >= 3 && num <= 7)
00212                 default_oct = num;
00213             p++; // skip comma
00214         }
00215 
00216         // get BPM
00217         if (read_byte(p, pgm) == 'b')
00218         {
00219             p++;
00220             p++; // skip "b="
00221             num = 0;
00222             while (isdigit(read_byte(p, pgm)))
00223             {
00224                 num = (num * 10) + (read_byte(p, pgm) - '0');
00225                 p++;
00226             }
00227             bpm = num;
00228             p++; // skip colon
00229         }
00230 
00231         // BPM usually expresses the number of quarter notes per minute
00232         wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds)
00233 
00234         // now begin note loop
00235         while (read_byte(p, pgm))
00236         {
00237             // first, get note duration, if available
00238             num = 0;
00239             while (isdigit(read_byte(p, pgm)))
00240             {
00241                 num = (num * 10) + (read_byte(p, pgm) - '0');
00242                 p++;
00243             }
00244 
00245             if (num)
00246                 duration = wholenote / num;
00247             else
00248                 duration = wholenote / default_dur; // we will need to check if we are a dotted note after
00249 
00250             // now get the note
00251             note = 0;
00252 
00253             switch (read_byte(p, pgm))
00254             {
00255             case 'c':
00256                 note = 1;
00257                 break;
00258             case 'd':
00259                 note = 3;
00260                 break;
00261             case 'e':
00262                 note = 5;
00263                 break;
00264             case 'f':
00265                 note = 6;
00266                 break;
00267             case 'g':
00268                 note = 8;
00269                 break;
00270             case 'a':
00271                 note = 10;
00272                 break;
00273             case 'b':
00274                 note = 12;
00275                 break;
00276             case 'p':
00277             default:
00278                 note = 0;
00279             }
00280             p++;
00281 
00282             // now, get optional '#' sharp
00283             if (read_byte(p, pgm) == '#')
00284             {
00285                 note++;
00286                 p++;
00287             }
00288 
00289             // now, get optional '.' dotted note
00290             if (read_byte(p, pgm) == '.')
00291             {
00292                 duration += duration / 2;
00293                 p++;
00294             }
00295 
00296             // now, get scale
00297             if (isdigit(read_byte(p, pgm)))
00298             {
00299                 scale = read_byte(p, pgm) - '0';
00300                 p++;
00301             }
00302             else
00303             {
00304                 scale = default_oct;
00305             }
00306 
00307             scale += octave_offset;
00308 
00309             if (read_byte(p, pgm) == ',')
00310                 p++; // skip comma for next note (or we may be at the end)
00311 
00312             // now play the note
00313 
00314             if (note)
00315             {
00316                 _tone(read_word(&notes[(scale - 4) * 12 + note], pgm));
00317                 delay(duration);
00318                 _noTone();
00319             }
00320             else
00321             {
00322                 delay(duration);
00323             }
00324         }
00325     }
00326 };
00327 
 All Classes Files Functions Variables Defines