MIDI-Stamp Primer??
"Steamboat Ed" Haas
Posts: 29
· --OK here's the deal: I've got no musical abilities at all, but I've gone ahead and built a 12-note solenoid-operated calliope. I'm commanding the solenoids on/off with a BS2 and pBasic, but it's really a cumbersome task to program it this way. What I'd like to do is find some *simple* tunes, somehow·make them·12-note compatible, then 'automatically' load·it as·something the Stamp can process. Anyone got suggestions about reading matter or canned routines to do something like this?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---
Comments
Your calliope sounds pretty neat! Can you post some photos?
-Phil
·Tell me more about this gadget; got a part number??
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---
-Phil
' What's a Microcontroller - MicroMusicWithRtttl.bs2
' Play Nokia RTTTL format ringtones using DATA.
'{$STAMP BS2}
'{$PBASIC 2.5}
'
[noparse][[/noparse] I/O Definitions ]
· SpeakerPin···· CON···· 15·················· ' Piezospeaker connected to P11.
'
[noparse][[/noparse] Variables ]
· counter······· VAR···· Word··············· ' General purpose counter.
· char·········· VAR···· Byte··············· ' Variable stores characters.
· index········· VAR···· Word··············· ' Index for pointing at data.
· noteLetter···· VAR···· Byte··············· ' Stores note character.
· noteFreq······ VAR···· Word··············· ' Stores note frequency.
· notePin······· VAR···· Byte··············· ' turns pin numbers into outputs
· noteOctave···· VAR···· Word··············· ' Stores note octave.
· duration······ VAR···· Word··············· ' Stores note duration.
· tempo········· VAR···· Word··············· ' Stores tempo.
· default_d····· VAR···· Byte··············· ' Stores default duration.
· default_o····· VAR···· Byte··············· ' Stores default octave.
· default_b····· VAR···· Word··············· ' Stores default beats/min.
· value········· VAR···· Byte
'
[noparse][[/noparse] EEPROM Data ]
'· RTTTL_File····· DATA··· "Flint:d=32,o=7,b=300:a#,p,a#,p,8b,p,a#,p,b,p,8c#6,p,b,p,c#6,p,8d#6,p,c#6,p,b,p,8a#,p,a#,p,a#,p,8b."
'·· RTTTL_File····· DATA···· "Looney:d=8,o=6,b=140:C,F,E,D,C,4A5,C,F,E,D,D#,4E,E,E,C,D,C,E,C,D,A5,C,G5,A#5,A5,F5"
·'· RTTTL_File····· DATA··· "PirateLife:d=4,o=5,b=100:8a.,8c.6,8d.6,8c6,16a#,8a,16a,8g,",
·'························· "16g,f,16p,16a,16a.,32p,16a,16a,16a,16a,16a,16a,16a,16a,16a,",
·'························· "16a,16d.6,32p,16a,16f,16f,16g,16a.,p,16a,16a#,16a#,16a#,16g,",
·'························· "16g,16g,16a,16a,16a,16f,16f,16f,16g,16g,16g,16g,16a,16b,8c6,16p,"'
·'························· "16p,8a.,8c.6,8d.6,8c6,16a#,8a,16a,8g,16g,f,16p"
· RTTTL_File······ DATA··· "Wallace And Gromit Theme:d=4,o=7,b=112:c6,16a#,16p,16a,",
··························· "16p,c6,16a#,16p,16a,16p,16c6,16p,2g,p,8d6,16c6,16p,16d6,",
··························· "16p,e6,16d6,16p,16c6,16p,16a#,16p,2a,p,c6,16a#,16p,16a,16p,",
··························· "c6,16a#,16p,16a,16p,16c6,16p,2g,p,8d6,16c6,16p,16d6,16p,8e6,",
··························· "16p,d6,16e6,16p,16f6"
'· RTTTL_File····· DATA···· "Scale:d=32,o=7,b=50:c,c#,d,d#,e,f,f#,g,g#,a,a#,b"
' RTTTL_File···· DATA··· "Reveille:d=4,o=7,b=140:8g6,8c,16e,16c,8g6,8e,",
'················· ············· "8c,16e,16c,8g6,8e,8c,16e,16c,8a6,8c,e,8c,8g6,",
'········ ················ ····· "8c,16e,16c,8g6,8e,8c,16e,16c,8g6,8e,8c,16e,",
'······ ···················· ··· "16c,8g6,8e,c,p,8e,8e,8e,8e,g,8e,8c,8e,8c,8e,8c,",
'··· ························ ·· "e,8c,8e,8e,8e,8e,8e,g,8e,8c,8e,8c,8g6,8g6,c."
· Done·········· DATA··· ",q,"
· Notes········· DATA···· "p",······ "a",······ "#",······ "b",
························· "c",······ "#",······ "d",······ "#",
························· "e",······ "f",······ "#",······ "g",
························· "#"
· pins·········· DATA···· 0,········ 1,········ %10,······ %100,
························· %1000,···· %10000,··· %100000,·· %1000000,
························· %10000000, %1,······· %10,······ %100,
························· %1000
· Octave8······· DATA··· Word 0,··· Word 3520, Word 3729, Word 3951,
························ Word 4186, Word 4435, Word 4699, Word 4978,
························ Word 5274, Word 5588, Word 5920, Word 6272,
························ Word 6645
'
[noparse][[/noparse] Initialization ]
· counter = 0······························· ' Initialize counter.
· GOSUB FindEquals·························· ' Find first '=' in file.
· GOSUB ProcessDuration····················· ' Get default duration.
· GOSUB FindEquals·························· ' Find next '='.
· GOSUB ProcessOctave······················· ' Get default octave.
· GOSUB FindEquals·························· ' Find last '='.
· GOSUB GetTempo···························· ' Get default tempo.
'
[noparse][[/noparse] Program Code ]
· DO UNTIL char = "q"······················· ' Loop until 'q' in DATA.
··· GOSUB ProcessDuration··················· ' Get note duration.
··· GOSUB ProcessNote······················· ' Get index value of note.
··· GOSUB CheckForDot······················· ' If dot, 3/2 duration.
··· GOSUB ProcessOctave····················· ' Get octave.
··· GOSUB PlayNote·························· ' Get freq, play note, next.
· LOOP······································ ' End of main loop.
· END······································· ' End of program.
'
[noparse][[/noparse] Subroutine - Find Equals Character ]
· FindEquals:······························· ' Go through characters in
············································ ' RTTTL file looking for
··· DO······································ ' '='.· Increment counter
····· READ RTTTL_File + counter, char······· ' until '=' is found, then
····· counter = counter + 1················· ' return.
··· LOOP UNTIL char = "="
··· RETURN
'
[noparse][[/noparse] Subroutine - Read Tempo from RTTTL Header ]
' Each keyboard character has a unique number called an ASCII value.
' The characters 0, 1, 2,...9 have ASCII values of 48, 49, 50,...57.
' You can always convert from the character representing a digit to
' to its value by subtracting 48 from the variable storing the digit.
' You can examine this by comparing DEBUG DEC 49 and DEBUG 49.
· GetTempo:································· ' Parse RTTTL file for Tempo.
············································ ' Convert characters to
··· default_b = 0··························· ' digits by subtracting 48
··· DO······································ ' from each character's ASCII
····· READ RTTTL_File + counter, char······· ' value.· Iteratively multiply
····· IF char = ":" THEN···················· ' each digit by 10 if there
······· default_b = default_b / 10·········· ' is another digit, then add
······· counter = counter + 1··············· ' the most recent digit to
······· EXIT································ ' one's column.
····· ENDIF································· ' For example, the string
······· default_b = default_b + char - 48··· ' "120" is (1 X 10 X 10)
······· counter = counter + 1··············· ' + (2 X 10) + 0.· The '1'
······· default_b = default_b * 10·········· ' is converted first, then
··· LOOP UNTIL char = ":"··················· ' multiplied by 10.· The '2'
············································ ' is then converted/added.
··· RETURN·································· ' 0 is converted/added, done.
'
[noparse][[/noparse] Subroutine - Look up Octave ]
· ProcessOctave:···························· ' Octave may or may not be
············································ ' included in a given note
··· READ RTTTL_File + counter, char········· ' because any note that is
··· SELECT char····························· ' played in the default
····· CASE "5" TO "8"······················· ' octave does not specify
······· noteOctave = char - "0"············· ' the octave.· If a char
······· counter = counter + 1··············· ' from '5' to '8' then use
····· CASE ELSE····························· ' it, else use default_o.
······· noteOctave = default_o·············· ' Characters are converted
··· ENDSELECT······························· ' to digits by subtracting
··· IF default_o = 0 THEN··················· ' '0', which is the same as
····· default_o = noteOctave················ ' subtracting 48. The first
··· ENDIF··································· ' time this subroutine is
············································ ' called, default_o is 0.
··· RETURN·································· ' If 0, then set default_o.
'
[noparse][[/noparse] Subroutine - Find Index of Note ]
· ProcessNote:······························ ' Set index value for lookup
············································ ' of note frequency based on
··· READ RTTTL_File + counter, char········· ' note character. If 'p',
··· SELECT char····························· ' index is 0.· If 'a' to 'g',
····· CASE "p"······························ ' read character values in
······· index = 0··························· ' DATA table and find match.
······· counter = counter + 1··············· ' Record index value when
····· CASE "a" TO "g"······················· ' match is found.· If next
······· FOR index = 1 TO 12················· ' char is a sharp (#), add
········· READ Notes + index, noteLetter···· ' 1 to the index value to
········· IF noteLetter = char THEN EXIT···· ' increase the index (and
······· NEXT································ ' frequency) by 1 notch.
······· counter = counter + 1··············· ' As with other subroutines,
······· READ RTTTL_File + counter, char····· ' increment counter for each
······· SELECT char························· ' character that is processed.
········· CASE "#"
··········· index = index + 1
··········· counter = counter + 1
······· ENDSELECT
··· ENDSELECT
··· RETURN
'
[noparse][[/noparse] Subroutine - Determine Note Duration ]
· ProcessDuration:·························· ' Check to see if characters
············································ ' form 1, 2, 4, 8, 16 or 32.
··· READ RTTTL_File + counter, char········· ' If yes, then convert from
············································ ' ASCII character to a value
··· SELECT char····························· ' by subtracting 48. In the
····· CASE "1", "2", "3", "4", "8"·········· ' case of 16 or 32, multiply
······· duration = char - 48················ ' by 10 and add the next
······· counter = counter + 1··············· ' digit to the ones column.
······· READ RTTTL_File + counter, char
······· SELECT char
········· CASE "6", "2"
··········· duration = duration * 10 + char - 48
··········· counter = counter + 1
······· ENDSELECT
······· CASE ELSE··························· ' If no duration, use
······· duration = default_d················ ' use default.
··· ENDSELECT
··· IF default_d <> 0 THEN·················· ' If default_d not defined
····· duration = 60000/default_b/duration*3· ' (if default_d = 0), then
··· ELSE···································· ' set default_d = to the
····· default_d = duration·················· ' duration from the d=#.
··· ENDIF
··· RETURN
'
[noparse][[/noparse] Subroutine - Check For '.' Indicating 1.5 Duration ]
· CheckForDot:······························ ' Check for dot indicating
············································ ' multiply duration by 3/2.
··· READ RTTTL_File + counter, char········· ' If dot found, multiply by
··· SELECT char····························· ' 3/2 and increment counter,
····· CASE "."······························ ' else, do nothing and
······· duration = duration * 3 / 2········· ' return.
······· counter = counter + 1
··· ENDSELECT
··· RETURN
'
[noparse][[/noparse] Subroutine - Find Comma and Play Note/Duration ]
· PlayNote:································· ' Find last comma in the
············································ ' current note entry.· Then,
··· READ RTTTL_File + counter, char········· ' fetch the note frequency
··· SELECT char····························· ' from data, and play it, or
····· CASE ","······························ ' pause if frequency = 0.
······· counter = counter + 1
······· READ Octave8 + (index * 2), Word noteFreq
·· '···· LOOKDOWN noteLetter, [noparse][[/noparse]"a", "a#", "b", "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#"], notePin
······· LOOKDOWN noteFreq, [noparse][[/noparse]4186, 4435, 4699, 4978,
·························· 5274, 5588, 5920, 6272, 6645, 3520, 3729, 3951], notePin
······· noteOctave = 8 - noteOctave
······· noteFreq = noteFreq / (DCD noteOctave)
······· DEBUG noteLetter, " = ", DEC notePin, " : ", "noteFreq = ", DEC noteFreq, CR
······· IF noteFreq = 0 THEN
········· PAUSE duration
······· ELSE
········· HIGH notePin······································ ' LED will remain on
········· FREQOUT SpeakerPin, duration, noteFreq············ ' all the time the speaker is
········· LOW notePin······································· ' playing so don't delete the FREQOUT
······· ENDIF
··· ENDSELECT
··· RETURN
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---
http://www.youtube.com/watch?v=vKG3MYgIeMc&feature=related
· ...and new software for use with proto driver board with 12: TIP-120s currently on another machine; will post that later today.
· Hope to have all and sundry at upcoming Makers Faire at San Mateo County Fairgrounds on May 30-31. I'll have a hand-out with all the URLs and some sordid details of construction.·Come on·by and say hi!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
························ Hacking the Trailing Edge!
················http://www.nmpproducts.com/intro.htm
················---Decks a-wash in a sea of words---