Playing Sheet Music with the Piezospeaker
Playing Sheet Music with the Piezospeaker
·
We all have our favorite songs, and sometimes playing them would add that extra “something” to our BASIC Stamp applications.· This project will demonstrate how to take the sheet music from your favorite songs and play them with the piezospeaker.
Getting Started
If you are new to the BASIC Stamp microcontroller or to programming, it would be a good idea to review Chapter 8 in What’s a Microcontroller before continuing.
Parts Required
(1)· HomeWork Board with BASIC Stamp 2
····· The BASIC Stamp 2 Board of Education is also suitable for·this activity
(1) Piezospeaker
Schematics and Building the Circuits
All that is needed for this project is a piezoelectric speaker.· Build the circuit shown in Figure 1 below.
·
Figure 1 – Piezoelectric Speaker Circuit Schematic and Wiring Diagram
![attachment.php?attachmentid=63094](http://forums.parallax.com/attachment.php?attachmentid=63094)
Reading Sheet Music – The Basics
Before any PBASIC coding can happen, it would be best to cover the basics of reading sheet music.· After all, without knowing how to do that, translating it into code would be tricky business!· These next sections will introduce the basics of reading sheet music, so the next time you want to feature a favorite song in a BASIC Stamp Application, you’ll be ready to go.
The Staff and Clefs
The staff is perhaps the most important building block of reading sheet music.· It is a set of 5 lines with 4 spaces that holds the information needed for the musician to play the correct notes, in the correct tempo, at the right pitch.· Each note on a staff increases by one letter from a line to a space, and by two letters from line to line.
·
The symbol that appears at the beginning of every staff is known as a clef.· This symbol lets the musician know which notes to play as well as the octave to play them in.· When reading sheet music, one of two clefs will be used – treble or bass.· The treble clef is used for higher notes, such as those for a soprano singer, flute, violin, or for the pianist any note above “Middle C”.· The bass clef is used for lower notes, such as a bass or baritone singer, tuba, trombone, or any note below “Middle C” on a piano.·
·
Figure 2 displays how to read notes for the treble clef, and these notes can be easily remembered through the use of mnemonic devices.· For example, the staff lines for the treble clef read: E, G, B, D, F – which can be remembered through the phrase “Every Good Boy Does Fine”.· You can also memorize the spaces between the lines as they spell the word “FACE”.
·
Figure 2 – Treble Clef Order of Notes
![attachment.php?attachmentid=63095](http://forums.parallax.com/attachment.php?attachmentid=63095)
Figure 3 displays how to read notes for the bass clef.· Here, the order of notes changes to: G, B, D, F, A which can be remembered the mnemonic device “Good Burritos Don’t Fall Apart”.· Sadly, the spaces between the lines don’t spell anything for the bass clef (A, C, E, G) but you can use the phrase “All Cows Eat Grass” to help you remember.
·
Figure 3 – Bass Clef Order of Notes
![attachment.php?attachmentid=63096](http://forums.parallax.com/attachment.php?attachmentid=63096)
The Octave
Take a look at Figure 4 below and see if you can see the pattern that is beginning to emerge:
·
Figure 4 – Octave Example
![attachment.php?attachmentid=63097](http://forums.parallax.com/attachment.php?attachmentid=63097)
The highlighted “E’s” are what’s known as an octave, or a sequence of 8 musical notes.· Octaves are measured note to note, for example: C-to-C or A-to-A.· As the octaves increase up the staff, the pitch of each note increases.· Conversely, as octaves decrease down the staff, the pitches of the notes decrease.
·
Since the pitch of a note gets higher or lower depending on the octave, a number system exists to help keep track of each octave.· Take another look at Figure 4 above.· The first highlighted “E” note is considered to be in the 4th octave, while the second highlighted “E” note is in the 5th octave.· Octaves increase or decrease in value from note C to note C.· So the first half of the staff (E-F-G-A-B) is in the 4th octave, while the second half (C-D-E-F) is in the 5th octave.
The Key Signature
The key signature is a series of sharp or flat symbols located directly to the left of the clef.· These symbols tell the musician which notes get played a half-step higher (sharp) or a half-step lower (flat).· These notes are then played as sharps or flats throughout the entire piece of music, regardless of the octave.· For example, Figure 5 below demonstrates examples of both sharp and flat key signatures.· See if you can determine which notes will get changed based on the mnemonic devices introduced in the “Staff and Clefs” section above.
·
Figure 5 – Sharp and Flat Key signatures
![attachment.php?attachmentid=63098](http://forums.parallax.com/attachment.php?attachmentid=63098)
![attachment.php?attachmentid=73650](http://forums.parallax.com/attachment.php?attachmentid=73650)
Note Durations and Rests
One key component to keeping rhythm when playing a piece of music is to know how long a note should last.· Note durations are represented by symbols and the best way to remember their “values” is simply through rote memorization.· Below is a table of commonly used notes and their durations:
![attachment.php?attachmentid=63101](http://forums.parallax.com/attachment.php?attachmentid=63101)
![attachment.php?attachmentid=73651](http://forums.parallax.com/attachment.php?attachmentid=73651)
When playing sheet music, it is just as important to know how long to stop playing (or rest) as it is to know how long to hold a note.· Just like there are note durations, there are also rest durations, or the time a musician should stop playing.· The durations of rests are the same as those for notes: a quarter rest would last the same amount of time as a quarter note.· Below is a table of commonly used rests:
![attachment.php?attachmentid=63103](http://forums.parallax.com/attachment.php?attachmentid=63103)
The Time Signature
On most pieces of music, there is a number that looks like a fraction directly to the right of the key signature.· This number is known as the time signature and is crucial to keeping the correct tempo when playing a song.· Figure 6 below demonstrates 4/4 time, which is also known as “common time” and is sometimes denoted with a “c”.· Common time means that there are 4 beats in every measure, and the quarter note gets a whole beat.· In sheet music, measures are separated by vertical lines.
·
Figure 6 – “Common Time” Time Signature
·![attachment.php?attachmentid=63100](http://forums.parallax.com/attachment.php?attachmentid=63100)
Sheet Music and the Piezospeaker
Let’s apply the techniques just learned about reading sheet music to an actual song.· Since the start of school is just around the corner, the song “School Days” by Will Cobb and Gus Edwards seems most appropriate for this activity.· The sheet music for the song is shown in Figure 7 below:
·
Figure 7 – School Days Sheet Music
![attachment.php?attachmentid=63104](http://forums.parallax.com/attachment.php?attachmentid=63104)
So now we have the sheet music it’s time to map out the notes and octaves so we can easily translate it into PBASIC to play with the piezospeaker.· Below are some simple steps that you can take to successfully play sheet music with the piezospeaker and BASIC Stamp 2.
Step 1 – Identify the Notes
The first thing to do when planning to play sheet music with the piezospeaker is to identify the notes to be played.· Use Figure 2 above and mark the value of each note, and don’t forget to make a note octave changes and sharps or flats!· You can check your work with Figure 8 below.
·
Figure 8 – School Days Sheet Music with Notes
![attachment.php?attachmentid=63105](http://forums.parallax.com/attachment.php?attachmentid=63105)
Step 2 – Count out the Beats
Using the time signature, the next step will be to count out the beats for each measure.· This will help determine the duration of each note when playing it on the piezospeaker.· The time signature for this song is 3/4, which means that there are three beats in each measure and the quarter note gets one beat.· Use the “Note Duration and Rests” section above to count the beats for each measure.· You can check your work with Figure 9 below.
·
![attachment.php?attachmentid=73652](http://forums.parallax.com/attachment.php?attachmentid=73652)
·
Figure 9 – School Days Sheet Music with Beats
![attachment.php?attachmentid=63106](http://forums.parallax.com/attachment.php?attachmentid=63106)
Step 3 – Put it into Code
Congratulations, you have now successfully read a piece of sheet music!· Now we’re ready to take what we’ve read and put it into code for the BASIC Stamp.· As a quick recap, we need three pieces of information before we can begin our BASIC Stamp code:
√······· The notes to be played
√······· The octaves to play them in
√······· How long each note should last
·
This information is going to be stored to EEPROM on the BASIC Stamp.· That way, we can use the code as a template for any piece of music that we might want to play. If you recall from Chapter 8 of What’s a Microcontroller, every note corresponds to a specific frequency that can be played by the BASIC Stamp, as seen in Figure 10.
·
Figure 10 – Rightmost Piano Keys and Their Frequencies
![attachment.php?attachmentid=65239](http://forums.parallax.com/attachment.php?attachmentid=65239)
You may notice that the frequencies in the table are two higher than the ones we made note of on the sheet music.· This is because the 6th and 7th octaves sound the best through the piezospeaker.· So just remember that anytime you are playing sheet music with the piezospeaker, bump the octave up by two in order to get the best sound.
·
Armed with this knowledge, let’s take a look at the PBASIC code for playing “School Days” with the piezospeaker:
How it Works
The first part of the code defines what song will be played by saving the following to EEPROM:
·
√········ Notes
o······· This DATA directive defines which notes will be played.· Lower case letters denote flats while upper case letters denote notes that are played normally, and R denotes a rest.
√········ Octaves
o······· This DATA directive defines what octave the previously defined notes will be played in.· Remember that we’ve increased the octave by two from the sheet music; so any note played in the 4th octave is now played in the 6th and any note played in the 5th octave is now played in the 7th.
√········ Durations
o······· This DATA directive defines how long each note will be played.· The value of the duration corresponds to the denominator of the note’s value. ·So a half note (1/2) would have a duration value of 2 and a quarter note (1/4) will have a duration value of 4.
√········ Dots
o······· This DATA directive defines whether the note is dotted or not. A value of 1 denotes a dot and a value of 0 means the note is not dotted.
·
The code that follows the DATA directives can be used as a template for any song that you may want to play.· Basically, each note is read from EEPROM and played at the proper frequency for the correct amount of time. ·Let’s take a more in depth look at how the program accomplishes this.
·
The first part of the code reads the note stored in the Notes DATA directive and places it into a variable named noteLetter.
·
READ Notes + index, noteLetter
·
A lookup table is then used to store the corresponding frequency for each note relative to the eighth octave. ·The eighth octave in musical turns is technically simply the note “C”. ·However, for mathematical reasons and since the lower octaves don’t play clearly through the piezospeaker, we will define each note of the eighth octave with a frequency and use this octave as a baseline for calculating the frequencies of notes in other octaves.
·
LOOKDOWN noteLetter, [noparse][[/noparse]· "C",· "d",· "D",· "e",· "E",
······················· "F",· "g",· "G",· "a",· "A",
······················· "b",· "B",· "R",· "Q"···· ], offset
·
LOOKUP offset,······· [noparse][[/noparse] 4186, 4435, 4699, 4978, 5274,
······················· 5588, 5920, 6272, 6645, 7040,
······················· 7459, 7902,··· 0,··· 0···· ], noteFreq
·
Seeing as we don’t want every note to be played in the 8th octave, we need to calculate the frequency of each note in the octave we do want to play.· Take another look at Figure 10 above and see if you can detect a pattern when dropping from the note C8 to C7 to C6.· Do you notice how their values cut in half each time you drop an octave? ·For example, the frequency of C8 is 4186 Hz.· 4186 divided by 2 is 2093 or the frequency of the note C7. ·2093 divided by 2 is 1046.5 or the frequency of the note C6.· This pattern continues all the way down the octave, and is how we were able to assign frequency values for notes in our 8th octave.
·
However, we would have some pretty tedious PBASIC code if we had to keep dividing by 2 in order to get the desired frequency value. ·There must be an easier way to drop multiple octaves, right?· Right!· Let’s take the C-note example again: say we wanted to drop from C8 to C6, isn’t that the same as dividing the frequency of C8 by 4?· Or, if we wanted to drop from C8 to C5 (523.25 Hz), isn’t that the same as diving the frequency of C8 by 8? ·By George, I think there’s a pattern emerging here!
·
By using the 8th octave as a reference, we can divide a note’s frequency by 1, 2, 4, or 8 in order to calculate the frequency values for the 5th, 6th, 7th, and 8th octaves. ·To put it in even simpler terms: we could also divide by 20, 21, 22, or 23.· To translate this code into PBASIC, we first read the octave from EEPROM and save it to a variable named noteOctave.
·
READ Octaves + index, noteOctave
·
Then, in order to calculate the correct power to raise 2 to, we subtract the value in noteOctave from 8. ·So if noteOctave was 7 now it’s one.· If noteOctave 6 now it’s 2, etc.
·
noteOctave = 8 - noteOctave
·
Lastly, we need to divide the current frequency by 2 raised to the power of noteOctave.· In PBASIC we can use the DCD operator, which is a 2n-power decoder of a 4-bit value.· So if we divide noteFreq by DCD noteOctave, we are in turn diving by 1, 2, 4, or 8 which will, in turn, give us the correct noteFreq value.
·
noteFreq = noteFreq / (DCD noteOctave)
·
Now we need to calculate how long to play each note.· First, we read the value stored in the Durations DATA directive and store it in a variable named noteDuration.
·
READ Durations + index, noteDuration
·
In order to calculate the millisecond duration for each note, we’ll use the theoretical duration of a whole note as a base.· In this case, we’ll say a whole note would last one second. ·Therefore, a half note would last 500 ms, a quarter note would last 250 ms, and an eighth note would last 125 ms. ·Since we set the values in the Durations DATA directive to the number in the denominator of the notes value, we just need to divide 1000 by the value in noteDuration.
·
noteDuration = 1000 / noteDuration
·
To finish, we need to re-calculate the note’s duration if it is a dotted note.· Remember, we set dotted notes equal to 1 in the Dots DATA directive, so if we read a 1 from the Dots DATA directive, we need to increase that note’s duration by one-half its value. ·Or, to simplify matters, multiply the note’s duration by 1.5.
·
READ Dots + index, noteDot
IF noteDot = 1 THEN noteDuration = noteDuration * 3 / 2
·
Then, we play the note for the specified duration through the piezospeaker, add one to the EEPROM index and repeat the process until the value in the Notes DATA directive is “Q”.
__________________________________________________ ___________________________
··
(c) 2009·by Parallax Inc - all rights reserved.··
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax Inc.
Post Edited (Jessica Uelmen (Parallax)) : 8/25/2010 4:26:18 PM GMT
·
We all have our favorite songs, and sometimes playing them would add that extra “something” to our BASIC Stamp applications.· This project will demonstrate how to take the sheet music from your favorite songs and play them with the piezospeaker.
Getting Started
If you are new to the BASIC Stamp microcontroller or to programming, it would be a good idea to review Chapter 8 in What’s a Microcontroller before continuing.
Parts Required
(1)· HomeWork Board with BASIC Stamp 2
····· The BASIC Stamp 2 Board of Education is also suitable for·this activity
(1) Piezospeaker
Schematics and Building the Circuits
All that is needed for this project is a piezoelectric speaker.· Build the circuit shown in Figure 1 below.
·
Figure 1 – Piezoelectric Speaker Circuit Schematic and Wiring Diagram
Reading Sheet Music – The Basics
Before any PBASIC coding can happen, it would be best to cover the basics of reading sheet music.· After all, without knowing how to do that, translating it into code would be tricky business!· These next sections will introduce the basics of reading sheet music, so the next time you want to feature a favorite song in a BASIC Stamp Application, you’ll be ready to go.
The Staff and Clefs
The staff is perhaps the most important building block of reading sheet music.· It is a set of 5 lines with 4 spaces that holds the information needed for the musician to play the correct notes, in the correct tempo, at the right pitch.· Each note on a staff increases by one letter from a line to a space, and by two letters from line to line.
·
The symbol that appears at the beginning of every staff is known as a clef.· This symbol lets the musician know which notes to play as well as the octave to play them in.· When reading sheet music, one of two clefs will be used – treble or bass.· The treble clef is used for higher notes, such as those for a soprano singer, flute, violin, or for the pianist any note above “Middle C”.· The bass clef is used for lower notes, such as a bass or baritone singer, tuba, trombone, or any note below “Middle C” on a piano.·
·
Figure 2 displays how to read notes for the treble clef, and these notes can be easily remembered through the use of mnemonic devices.· For example, the staff lines for the treble clef read: E, G, B, D, F – which can be remembered through the phrase “Every Good Boy Does Fine”.· You can also memorize the spaces between the lines as they spell the word “FACE”.
·
Figure 2 – Treble Clef Order of Notes
Figure 3 displays how to read notes for the bass clef.· Here, the order of notes changes to: G, B, D, F, A which can be remembered the mnemonic device “Good Burritos Don’t Fall Apart”.· Sadly, the spaces between the lines don’t spell anything for the bass clef (A, C, E, G) but you can use the phrase “All Cows Eat Grass” to help you remember.
·
Figure 3 – Bass Clef Order of Notes
The Octave
Take a look at Figure 4 below and see if you can see the pattern that is beginning to emerge:
·
Figure 4 – Octave Example
The highlighted “E’s” are what’s known as an octave, or a sequence of 8 musical notes.· Octaves are measured note to note, for example: C-to-C or A-to-A.· As the octaves increase up the staff, the pitch of each note increases.· Conversely, as octaves decrease down the staff, the pitches of the notes decrease.
·
Since the pitch of a note gets higher or lower depending on the octave, a number system exists to help keep track of each octave.· Take another look at Figure 4 above.· The first highlighted “E” note is considered to be in the 4th octave, while the second highlighted “E” note is in the 5th octave.· Octaves increase or decrease in value from note C to note C.· So the first half of the staff (E-F-G-A-B) is in the 4th octave, while the second half (C-D-E-F) is in the 5th octave.
The Key Signature
The key signature is a series of sharp or flat symbols located directly to the left of the clef.· These symbols tell the musician which notes get played a half-step higher (sharp) or a half-step lower (flat).· These notes are then played as sharps or flats throughout the entire piece of music, regardless of the octave.· For example, Figure 5 below demonstrates examples of both sharp and flat key signatures.· See if you can determine which notes will get changed based on the mnemonic devices introduced in the “Staff and Clefs” section above.
·
Figure 5 – Sharp and Flat Key signatures
Note Durations and Rests
One key component to keeping rhythm when playing a piece of music is to know how long a note should last.· Note durations are represented by symbols and the best way to remember their “values” is simply through rote memorization.· Below is a table of commonly used notes and their durations:
When playing sheet music, it is just as important to know how long to stop playing (or rest) as it is to know how long to hold a note.· Just like there are note durations, there are also rest durations, or the time a musician should stop playing.· The durations of rests are the same as those for notes: a quarter rest would last the same amount of time as a quarter note.· Below is a table of commonly used rests:
The Time Signature
On most pieces of music, there is a number that looks like a fraction directly to the right of the key signature.· This number is known as the time signature and is crucial to keeping the correct tempo when playing a song.· Figure 6 below demonstrates 4/4 time, which is also known as “common time” and is sometimes denoted with a “c”.· Common time means that there are 4 beats in every measure, and the quarter note gets a whole beat.· In sheet music, measures are separated by vertical lines.
·
Figure 6 – “Common Time” Time Signature
·
Sheet Music and the Piezospeaker
Let’s apply the techniques just learned about reading sheet music to an actual song.· Since the start of school is just around the corner, the song “School Days” by Will Cobb and Gus Edwards seems most appropriate for this activity.· The sheet music for the song is shown in Figure 7 below:
·
Figure 7 – School Days Sheet Music
So now we have the sheet music it’s time to map out the notes and octaves so we can easily translate it into PBASIC to play with the piezospeaker.· Below are some simple steps that you can take to successfully play sheet music with the piezospeaker and BASIC Stamp 2.
Step 1 – Identify the Notes
The first thing to do when planning to play sheet music with the piezospeaker is to identify the notes to be played.· Use Figure 2 above and mark the value of each note, and don’t forget to make a note octave changes and sharps or flats!· You can check your work with Figure 8 below.
·
Figure 8 – School Days Sheet Music with Notes
Step 2 – Count out the Beats
Using the time signature, the next step will be to count out the beats for each measure.· This will help determine the duration of each note when playing it on the piezospeaker.· The time signature for this song is 3/4, which means that there are three beats in each measure and the quarter note gets one beat.· Use the “Note Duration and Rests” section above to count the beats for each measure.· You can check your work with Figure 9 below.
·
·
Figure 9 – School Days Sheet Music with Beats
Step 3 – Put it into Code
Congratulations, you have now successfully read a piece of sheet music!· Now we’re ready to take what we’ve read and put it into code for the BASIC Stamp.· As a quick recap, we need three pieces of information before we can begin our BASIC Stamp code:
√······· The notes to be played
√······· The octaves to play them in
√······· How long each note should last
·
This information is going to be stored to EEPROM on the BASIC Stamp.· That way, we can use the code as a template for any piece of music that we might want to play. If you recall from Chapter 8 of What’s a Microcontroller, every note corresponds to a specific frequency that can be played by the BASIC Stamp, as seen in Figure 10.
·
Figure 10 – Rightmost Piano Keys and Their Frequencies
You may notice that the frequencies in the table are two higher than the ones we made note of on the sheet music.· This is because the 6th and 7th octaves sound the best through the piezospeaker.· So just remember that anytime you are playing sheet music with the piezospeaker, bump the octave up by two in order to get the best sound.
·
Armed with this knowledge, let’s take a look at the PBASIC code for playing “School Days” with the piezospeaker:
[color=#020FC0][color=#008000]' SchoolDays.bs2[/color] [color=#008000]' Play the 1907 hit "School Days" by Will Cobb and Gus Edwards with the[/color] [color=#008000]' piezospeaker.[/color] [color=#008000]' {$STAMP BS2}[/color] [color=#008000]' {$PBASIC 2.5}[/color] [color=#000000]Notes [/color]DATA [color=#ff0000]"D"[/color][color=#000000], [/color][color=#ff0000]"F"[/color][color=#000000], [/color][color=#ff0000]"C"[/color][color=#000000], [/color][color=#ff0000]"F"[/color][color=#000000], [/color][color=#ff0000]"b"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000], [/color][color=#ff0000]"b"[/color][color=#000000], [/color][color=#ff0000]"C"[/color][color=#000000], [/color][color=#ff0000]"b"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000], [/color][color=#ff0000]"R"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000],[/color] [color=#ff0000]"e"[/color][color=#000000], [/color][color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000], [/color][color=#ff0000]"e"[/color][color=#000000], [/color][color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000], [/color][color=#ff0000]"R"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000], [/color][color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"D"[/color][color=#000000], [/color][color=#ff0000]"F"[/color][color=#000000],[/color] [color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"D"[/color][color=#000000], [/color][color=#ff0000]"F"[/color][color=#000000], [/color][color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"R"[/color][color=#000000], [/color][color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"G[/color][color=#000000]", [/color][color=#ff0000]"Q"[/color] [color=#000000]Octaves [/color]DATA[color=#000000] 7, 6, 7, 6, 6, 6, 6, 7, 6, 6, 6, 6,[/color] [color=#000000] 7, 6, 6, 7, 6, 6, 6, 6, 6, 6, 7, 6,[/color] [color=#000000] 6, 7, 6, 6, 6, 6, 6[/color] [color=#000000]Durations [/color]DATA[color=#000000] 2, 2, 2, 2, 2, 4, 2, 4, 2, 2, 4, 4,[/color] [color=#000000] 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4,[/color] [color=#000000] 4, 4, 4, 4, 4, 4, 2[/color] [color=#000000]Dots [/color]DATA[color=#000000] 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0,[/color] [color=#000000] 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,[/color] [color=#000000] 0, 0, 0, 0, 0, 0, 1[/color] [color=#000000]index VAR Byte[/color] [color=#000000]offset VAR Nib[/color] [color=#000000]noteLetter VAR Byte[/color] [color=#000000]noteFreq VAR Word[/color] [color=#000000]noteDuration VAR Word[/color] [color=#000000]noteOctave VAR Nib[/color] [color=#000000]noteDot VAR Bit[/color] DO UNTIL[color=#000000] noteLetter = [/color][color=#ff0000]"Q"[/color] READ[color=#000000] Notes + index, noteLetter[/color] LOOKDOWN[color=#000000] noteLetter, [noparse][[/noparse] [/color][color=#ff0000]"C"[/color][color=#000000], [/color][color=#ff0000]"d"[/color][color=#000000], [/color][color=#ff0000]"D"[/color][color=#000000], [/color][color=#ff0000]"e"[/color][color=#000000], [/color][color=#ff0000]"E"[/color][color=#000000],[/color] [color=#ff0000]"F"[/color][color=#000000], [/color][color=#ff0000]"g"[/color][color=#000000], [/color][color=#ff0000]"G"[/color][color=#000000], [/color][color=#ff0000]"a"[/color][color=#000000], [/color][color=#ff0000]"A"[/color][color=#000000],[/color] [color=#ff0000]"b"[/color][color=#000000], [/color][color=#ff0000]"B"[/color][color=#000000], [/color][color=#ff0000]"R"[/color][color=#000000], [/color][color=#ff0000]"Q"[/color][color=#000000] ], offset[/color] LOOKUP[color=#000000] offset, [noparse][[/noparse] 4186, 4435, 4699, 4978, 5274,[/color] [color=#000000] 5588, 5920, 6272, 6645, 7040,[/color] [color=#000000] 7459, 7902, 0, 0 ], noteFreq[/color] READ[color=#000000] Octaves + index, noteOctave[/color] [color=#000000] noteOctave = 8 - noteOctave[/color] [color=#000000] noteFreq = noteFreq / (DCD noteOctave)[/color] READ[color=#000000] Durations + index, noteDuration[/color] [color=#000000] noteDuration = 1000 / noteDuration[/color] READ[color=#000000] Dots + index, noteDot[/color] IF[color=#000000] noteDot = 1 [/color]THEN[color=#000000] noteDuration = noteDuration * 3 / 2[/color] FREQOUT[color=#000000] 9, noteDuration, noteFreq[/color] [color=#000000] index = index + 1[/color] LOOP END [/color]
How it Works
The first part of the code defines what song will be played by saving the following to EEPROM:
·
√········ Notes
o······· This DATA directive defines which notes will be played.· Lower case letters denote flats while upper case letters denote notes that are played normally, and R denotes a rest.
√········ Octaves
o······· This DATA directive defines what octave the previously defined notes will be played in.· Remember that we’ve increased the octave by two from the sheet music; so any note played in the 4th octave is now played in the 6th and any note played in the 5th octave is now played in the 7th.
√········ Durations
o······· This DATA directive defines how long each note will be played.· The value of the duration corresponds to the denominator of the note’s value. ·So a half note (1/2) would have a duration value of 2 and a quarter note (1/4) will have a duration value of 4.
√········ Dots
o······· This DATA directive defines whether the note is dotted or not. A value of 1 denotes a dot and a value of 0 means the note is not dotted.
·
The code that follows the DATA directives can be used as a template for any song that you may want to play.· Basically, each note is read from EEPROM and played at the proper frequency for the correct amount of time. ·Let’s take a more in depth look at how the program accomplishes this.
·
The first part of the code reads the note stored in the Notes DATA directive and places it into a variable named noteLetter.
·
READ Notes + index, noteLetter
·
A lookup table is then used to store the corresponding frequency for each note relative to the eighth octave. ·The eighth octave in musical turns is technically simply the note “C”. ·However, for mathematical reasons and since the lower octaves don’t play clearly through the piezospeaker, we will define each note of the eighth octave with a frequency and use this octave as a baseline for calculating the frequencies of notes in other octaves.
·
LOOKDOWN noteLetter, [noparse][[/noparse]· "C",· "d",· "D",· "e",· "E",
······················· "F",· "g",· "G",· "a",· "A",
······················· "b",· "B",· "R",· "Q"···· ], offset
·
LOOKUP offset,······· [noparse][[/noparse] 4186, 4435, 4699, 4978, 5274,
······················· 5588, 5920, 6272, 6645, 7040,
······················· 7459, 7902,··· 0,··· 0···· ], noteFreq
·
Seeing as we don’t want every note to be played in the 8th octave, we need to calculate the frequency of each note in the octave we do want to play.· Take another look at Figure 10 above and see if you can detect a pattern when dropping from the note C8 to C7 to C6.· Do you notice how their values cut in half each time you drop an octave? ·For example, the frequency of C8 is 4186 Hz.· 4186 divided by 2 is 2093 or the frequency of the note C7. ·2093 divided by 2 is 1046.5 or the frequency of the note C6.· This pattern continues all the way down the octave, and is how we were able to assign frequency values for notes in our 8th octave.
·
However, we would have some pretty tedious PBASIC code if we had to keep dividing by 2 in order to get the desired frequency value. ·There must be an easier way to drop multiple octaves, right?· Right!· Let’s take the C-note example again: say we wanted to drop from C8 to C6, isn’t that the same as dividing the frequency of C8 by 4?· Or, if we wanted to drop from C8 to C5 (523.25 Hz), isn’t that the same as diving the frequency of C8 by 8? ·By George, I think there’s a pattern emerging here!
·
By using the 8th octave as a reference, we can divide a note’s frequency by 1, 2, 4, or 8 in order to calculate the frequency values for the 5th, 6th, 7th, and 8th octaves. ·To put it in even simpler terms: we could also divide by 20, 21, 22, or 23.· To translate this code into PBASIC, we first read the octave from EEPROM and save it to a variable named noteOctave.
·
READ Octaves + index, noteOctave
·
Then, in order to calculate the correct power to raise 2 to, we subtract the value in noteOctave from 8. ·So if noteOctave was 7 now it’s one.· If noteOctave 6 now it’s 2, etc.
·
noteOctave = 8 - noteOctave
·
Lastly, we need to divide the current frequency by 2 raised to the power of noteOctave.· In PBASIC we can use the DCD operator, which is a 2n-power decoder of a 4-bit value.· So if we divide noteFreq by DCD noteOctave, we are in turn diving by 1, 2, 4, or 8 which will, in turn, give us the correct noteFreq value.
·
noteFreq = noteFreq / (DCD noteOctave)
·
Now we need to calculate how long to play each note.· First, we read the value stored in the Durations DATA directive and store it in a variable named noteDuration.
·
READ Durations + index, noteDuration
·
In order to calculate the millisecond duration for each note, we’ll use the theoretical duration of a whole note as a base.· In this case, we’ll say a whole note would last one second. ·Therefore, a half note would last 500 ms, a quarter note would last 250 ms, and an eighth note would last 125 ms. ·Since we set the values in the Durations DATA directive to the number in the denominator of the notes value, we just need to divide 1000 by the value in noteDuration.
·
noteDuration = 1000 / noteDuration
·
To finish, we need to re-calculate the note’s duration if it is a dotted note.· Remember, we set dotted notes equal to 1 in the Dots DATA directive, so if we read a 1 from the Dots DATA directive, we need to increase that note’s duration by one-half its value. ·Or, to simplify matters, multiply the note’s duration by 1.5.
·
READ Dots + index, noteDot
IF noteDot = 1 THEN noteDuration = noteDuration * 3 / 2
·
Then, we play the note for the specified duration through the piezospeaker, add one to the EEPROM index and repeat the process until the value in the Notes DATA directive is “Q”.
__________________________________________________ ___________________________
··
(c) 2009·by Parallax Inc - all rights reserved.··
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax Inc.
Post Edited (Jessica Uelmen (Parallax)) : 8/25/2010 4:26:18 PM GMT
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax, Inc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax Inc.
Post Edited (Jessica Uelmen (Parallax)) : 11/20/2009 6:07:35 PM GMT
1. You talk about rests but don't implement them in the code. The way that I immediately thought of doing it would be to create a "note" in your data table with, perhaps, "R" as the value, and 0 as the octave. Once the calculations interpret it, it forces the piezo speaker to play a note so low it's inaudible.
2. Tempo seems to be embedded in the code (your 1000). Why not make a simple constant that interprets BPM into a duration. In the code, you say a whole note is 1000 (ms). So, that's 240 BPM. Working backwards, the equation would be delay = (BPM*1000)/(4*60). Of course, this is for x/4 time signature.
Anyway, another good post. You should add a recording of the song being played. [noparse]:)[/noparse]
It is a music lesson as well! Very handy.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Whit+
"We keep moving forward, opening new doors, and doing new things, because we're curious and curiosity keeps leading us down new paths." - Walt Disney
Thanks as always for the feedback! If you take a look at the Notes DATA directive, you will find there are a few "R's" in there for rests. I didn't set the octave to 0, since the frequency is set to zero in the LOOKUP table - but maybe that would help them be more noticeable in the DATA directive.
As for BPM, I wrestled with that for awhile. Ideally, I wanted a universal equation for any time signature that didn't require another in-depth lecture about more music theory and metronomes, and so I landed on the 1000 / noteDuration. Really all BPM gets down to in music is how the song "sounds", and with this equation, all the user has to do is play with the value of the whole note until the song sounds "right".
But I do like your code idea - it would make a nice "Your Turn" section for the musically inclined to make their code more musically "accurate". I'll have to work on that, and the video. Unfortunately I didn't have time for this project with the current work load I've got - but hopefully I'll be able to get to it soon! [noparse]:)[/noparse]
@Whit
Thanks very much! Handy was just what I was going for! Hopefully people will now be able to add their favorite songs to their projects, instead of using the non-copyrighted ones that we provide. [noparse];)[/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax, Inc.
You could definitely simulate human error in these types of applications using the RANDOM command, but you would have to be very careful with the math to ensure that your delays won't cause the song to become unrecognizable.
For example, if you use the RANDOM command to generate psuedo-random numbers, maybe you'll only want to take a look at the first four bits of the number generated. This would give you an additional decimal delay of 0-15 ms (binary %0000-%1111). You could then add or subtract this value from the total noteDuration to introduce your error. You could even monitor another bit of the random number generated and add or subtract depending on if it's value is 0 or 1.
You might find that 0-15 ms isn't enough delay to make any noticeable difference in the sound. Maybe you'll then want to multiply the delay by 4 to get up to a 60 ms delay. It's completely up to you - try playing around with the code and see if you can find a reasonable range of values that will get you that great imperfect sound!
Of course, the RANDOM command only deals with psuedo-random numbers. This means, that even though the song sounds imperfect, it will be the same degree of imperfect every time the song plays. (Meaning your note durations will be the same each time through the song - even though these durations are "imperfect".) To get a truly random error each time, you would need to devise a way to randomize the seed value as well - check out the RANDOM command in the BASIC Stamp Syntax and Reference Manual for more information.
- Jessica
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax, Inc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax, Inc.
Thanks!
Yes, unfortunately these 'Mini Projects' took quite a beating during the forums transition. We're working to clean these up.
In the meantime, you can pop back to the frozen old forum and look at the post there:
http://forums.parallaxinc.com/forums/?f=6&m=378167
The other Stamps in Class 'Mini Projects' posts still do have broken images, I'll work on cleaning those up this week. I just did this one quickly first since you asked. :]
-- Jessica
http://www.youtube.com/watch?v=bHd01Q2xIis
Flight of the Bumblebee
' {$STAMP BS2}
' {$PBASIC 2.5}
duration VAR Word
frequency VAR Word
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 1975
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2039
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 1975
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 1975
FREQOUT 9, 100, 2093
FREQOUT 9, 100, 2217
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2489
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3160
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 3729
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3160
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3160
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 3729
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3160
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3729
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2637
FREQOUT 9, 100, 2793
FREQOUT 9, 100, 2960
FREQOUT 9, 100, 3136
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3729
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 3322
FREQOUT 9, 100, 3520
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3729
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 1661
FREQOUT 9, 100, 3729
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
FREQOUT 9, 100, 3720
FREQOUT 9, 100, 1760
Sweet Home Alabama
' {$STAMP BS2}
' {$PBASIC 2.5}
FREQOUT 9, 40, 1760
FREQOUT 9, 250, 2349
PAUSE 100
FREQOUT 9, 300, 2349
FREQOUT 9, 200, 3520
FREQOUT 9, 250, 2349
PAUSE 100
FREQOUT 9, 50, 1568
FREQOUT 9, 200, 2093
PAUSE 100
FREQOUT 9, 300, 2093
FREQOUT 9, 200, 3136
FREQOUT 9, 250, 2093
PAUSE 100
FREQOUT 9, 70, 1174
FREQOUT 9, 200, 1568
PAUSE 100
FREQOUT 9, 300, 1568
FREQOUT 9, 200, 2349
FREQOUT 9, 250, 1568
PAUSE 65
FREQOUT 9, 50, 1568
FREQOUT 9, 150, 1864
FREQOUT 9, 175, 1975
FREQOUT 9, 160, 2349
FREQOUT 9, 150, 2637
FREQOUT 9, 40, 2217
FREQOUT 9, 150, 2349
FREQOUT 9, 175, 1975
FREQOUT 9, 150, 1864
FREQOUT 9, 150, 1975
PAUSE 25
FREQOUT 9, 40, 1760
FREQOUT 9, 250, 2349
PAUSE 100
FREQOUT 9, 300, 2349
FREQOUT 9, 200, 3520
FREQOUT 9, 250, 2349
PAUSE 80
FREQOUT 9, 50, 1568
FREQOUT 9, 250, 2093
PAUSE 100
FREQOUT 9, 300, 2093
FREQOUT 9, 200, 3136
FREQOUT 9, 250, 2093
PAUSE 80
FREQOUT 9, 60, 1174
FREQOUT 9, 250, 1568
PAUSE 100
FREQOUT 9, 300, 1568
FREQOUT 9, 200, 2349
FREQOUT 9, 250, 1568
PAUSE 65
FREQOUT 9, 200, 1568
FREQOUT 9, 175, 3951
FREQOUT 9, 175, 3729
FREQOUT 9, 175, 3520
FREQOUT 9, 400, 3136
PAUSE 200
FREQOUT 9, 40, 1760
FREQOUT 9, 250, 2349
PAUSE 100
FREQOUT 9, 300, 2349
FREQOUT 9, 200, 3520
FREQOUT 9, 250, 2349
PAUSE 100
FREQOUT 9, 50, 1568
FREQOUT 9, 200, 2093
PAUSE 100
FREQOUT 9, 300, 2093
FREQOUT 9, 200, 3136
FREQOUT 9, 250, 2093
PAUSE 100
FREQOUT 9, 70, 1174
FREQOUT 9, 200, 1568
PAUSE 100
FREQOUT 9, 300, 1568
FREQOUT 9, 200, 2349
FREQOUT 9, 250, 1568
PAUSE 65
Zelda Theme
' {$STAMP BS2}
' {$PBASIC 2.5}
do
FREQOUT 9, 300, 1864
PAUSE 150
FREQOUT 9, 100, 1396
FREQOUT 9, 600, 1396
PAUSE 400
FREQOUT 9, 200, 1864
FREQOUT 9, 150, 1864
FREQOUT 9, 150, 2093
FREQOUT 9, 100, 2349
FREQOUT 9, 100, 2489
FREQOUT 9, 600, 2793
PAUSE 400
FREQOUT 9, 100, 2793
PAUSE 25
FREQOUT 9, 100, 2793
PAUSE 25
FREQOUT 9, 200, 2960
FREQOUT 9, 200, 3322
FREQOUT 9, 600, 3729
PAUSE 400
FREQOUT 9, 150, 3729
FREQOUT 9, 300, 3729
FREQOUT 9, 125, 3322
FREQOUT 9, 150, 2960
FREQOUT 9, 400, 3322
FREQOUT 9, 150, 2960
FREQOUT 9, 400, 2793
PAUSE 400
FREQOUT 9, 200, 2793
PAUSE 25
FREQOUT 9, 400, 2489
PAUSE 25
FREQOUT 9, 200, 2793
FREQOUT 9, 350, 2960
PAUSE 400
FREQOUT 9, 200, 2793
PAUSE 25
FREQOUT 9, 200, 2489
FREQOUT 9, 400, 2217
FREQOUT 9, 150, 2489
FREQOUT 9, 350, 2793
PAUSE 400
FREQOUT 9, 200, 2489
PAUSE 25
FREQOUT 9, 150, 2217
FREQOUT 9, 400, 2093
PAUSE 50
FREQOUT 9, 150, 2093
PAUSE 25
FREQOUT 9, 150, 2349
FREQOUT 9, 400, 2637
PAUSE 25
FREQOUT 9, 400, 3136
PAUSE 25
FREQOUT 9, 400, 2793
PAUSE 50
FREQOUT 9, 400, 1396
FREQOUT 9, 200, 1396
FREQOUT 9, 600, 1396
PAUSE 300
Loop
To do that in software could nearly easily double the size of the program if done by adding a high command before, and a low command after each freqout. A slightly quicker way would be to add a single toggle command after each freqout or pause, which would come on every other note. Or, connect two different LEDs to that output pin, one to +5V and one to ground, so they alternate as the pin is toggling (one is active high, the other active low). Still requires a lot of memory and tedious typing. Might be better to add a hardware circuit, an LED switched on by a transistor or mosfet driven by the audio output. But without pauses between notes, it would be on all the time.
If you do add lots of high & low commands, use all available output pins to drive as many different color LEDs as you can. That way you're programming a multicolor light show as well. Be sure to post a video!
She has already done it here with a look up look down table.
[thread]Christmas Caroling Device with Light Display[/thread]
Well that did not work out. Someplace I saw a message about highlighting a thread but I cannot find it now. Just put it in the search box above right and see what happens.
If I do find these helps, whom do I contact to have it made a sticky for us old folks who cannot remember what we had for dinner?
' {$STAMP BS2}
' {$PBASIC 2.5}
FREQOUT 4,200, 2793
FREQOUT 4,200, 3520
FREQOUT 4,200, 2794
FREQOUT 4,800, 2637
FREQOUT 4,200, 2793
FREQOUT 4,200, 3520
FREQOUT 4,200, 2637
FREQOUT 4,600, 2349
FREQOUT 4,200, 2349
FREQOUT 4,200, 2793
FREQOUT 4,200, 2349
FREQOUT 4,400, 2093
FREQOUT 4,200, 2349
FREQOUT 4,300, 3520
FREQOUT 4,400, 3136
FREQOUT 4,200, 2349
FREQOUT 4,300, 3520
FREQOUT 4,400, 3136
FREQOUT 4,200, 2637
FREQOUT 4,400, 2794
FREQOUT 4,800, 2349