Created
November 5, 2016 14:49
-
-
Save wimvds/91e8c492d16e95c5578fc7060768106f to your computer and use it in GitHub Desktop.
play_RTTTL function to play ringtones on ESP8266 (Adafruit Feather Huzzah) with Arduino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO | |
#define OCTAVE_OFFSET 0 | |
#define isdigit(n) (n >= '0' && n <= '9') | |
int tone_pin = 4; // You can assing any digital output pin for speaker output! | |
void play_RTTTL(char* p){ | |
byte default_dur = 4; | |
byte default_oct = 6; | |
int bpm = 63; | |
int num; | |
long wholenote; | |
long duration; | |
byte note; | |
byte scale; | |
// Absolutely no error checking in here | |
// format: d=N,o=N,b=NNN: | |
// find the start (skip name, etc) | |
while(*p != ':') p++; // ignore name | |
p++; // skip ':' | |
// get default duration | |
if(*p == 'd') | |
{ | |
p++; p++; // skip "d=" | |
num = 0; | |
while(isdigit(*p)) | |
{ | |
num = (num * 10) + (*p++ - '0'); | |
} | |
if(num > 0) default_dur = num; | |
p++; // skip comma | |
} | |
// get default octave | |
if(*p == 'o') | |
{ | |
p++; p++; // skip "o=" | |
num = *p++ - '0'; | |
if(num >= 3 && num <=7) default_oct = num; | |
p++; // skip comma | |
} | |
// get BPM | |
if(*p == 'b') | |
{ | |
p++; p++; // skip "b=" | |
num = 0; | |
while(isdigit(*p)) | |
{ | |
num = (num * 10) + (*p++ - '0'); | |
} | |
bpm = num; | |
p++; // skip colon | |
} | |
// BPM usually expresses the number of quarter notes per minute | |
wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) | |
// now begin note loop | |
while(*p) | |
{ | |
// first, get note duration, if available | |
num = 0; | |
while(isdigit(*p)) | |
{ | |
num = (num * 10) + (*p++ - '0'); | |
} | |
if(num) duration = wholenote / num; | |
else duration = wholenote / default_dur; // we will need to check if we are a dotted note after | |
// now get the note | |
note = 0; | |
switch(*p) | |
{ | |
case 'c': | |
note = 1; | |
break; | |
case 'd': | |
note = 3; | |
break; | |
case 'e': | |
note = 5; | |
break; | |
case 'f': | |
note = 6; | |
break; | |
case 'g': | |
note = 8; | |
break; | |
case 'a': | |
note = 10; | |
break; | |
case 'b': | |
note = 12; | |
break; | |
case 'p': | |
default: | |
note = 0; | |
} | |
p++; | |
// now, get optional '#' sharp | |
if(*p == '#') | |
{ | |
note++; | |
p++; | |
} | |
// now, get optional '.' dotted note | |
if(*p == '.') | |
{ | |
duration += duration/2; | |
p++; | |
} | |
// now, get scale | |
if(isdigit(*p)) | |
{ | |
scale = *p - '0'; | |
p++; | |
} | |
else | |
{ | |
scale = default_oct; | |
} | |
scale += OCTAVE_OFFSET; | |
if(*p == ',') | |
p++; // skip comma for next note (or we may be at the end) | |
// now play the note | |
if(note) | |
{ | |
tone(tone_pin, notes[(scale - 4) * 12 + note]); // original - 4, not - 5 | |
delay(duration); | |
noTone(tone_pin); | |
} | |
else | |
{ | |
delay(duration); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment