Simon board plays “Mary Had a Little Lamb” at start up, then transitions to tones when buttons are pressed
Points related to music:
Points related to buttons:
In the template project for Lab 5, Timer Module TIMA1 is configured to drive the buzzer on the Simon PCB. In this lab, you will integrate this buzzer into the Lab 5 concept.
When the duty cycle is set to 50%, PWM creates a square wave signal at the frequency
selected by the period register. Thus, In order to change the sound that is created,
you need to change the value both of the period register (to change the frequency)
and the duty cycle. On the Simon PCB, the buzzer is connected to TIMA1 channel C0.
In hw_interface.c, the TIMA1 module is configured to count based on the main
SYSOSC BUSCLK (32 MHz) with a divider of 4, so at 8 MHz.
When the Lab 5 template code is run, the buzzer beeps briefly at startup. The code
which configures the frequency of this beep is at the end of the TIMA1 initialization
in hw_interface.c. Note that both the period and the duty cycle need to be configured!
TIMA1->COUNTERREGS.LOAD = 3999; // Period is LOAD+1 - this is 8000000/4000 = 2kHz
// HEADS UP: This sets the frequency of the buzzer!
TIMA1->COUNTERREGS.CC_01[0] = (TIMA1->COUNTERREGS.LOAD + 1) / 2; // half of load to make this a square wave
There are two other lines of code which are relevant. First, the following line in hw_interface.c
enables the Timer Module’s counting function (enables the counter to tick). This is the
standard way of effectively enabling the Timer Module’s functioning, and in this case, it
turns the PWM, and thus sound, on.
TIMA1->COUNTERREGS.CTRCTL |= (GPTIMER_CTRCTL_EN_ENABLED);
Second, at the top of the lab5.c function, we have the following lines of code which
disables the Timer Module counting, which turns off the PWM / sound.
// let the buzzer run for 0.1 s just so we know it's there!
delay_cycles(1600000);
TIMA1->COUNTERREGS.CTRCTL &= ~(GPTIMER_CTRCTL_EN_ENABLED); // Disable the buzzer
Your task in Lab 5 is twofold. First, conceptually, you can start with your button state machine code from Lab 3. For this lab, we do not care about long-presses or short-presses. Instead, the goal is that whenever a button is pressed (not bouncing), you should play a tone that corresponds to the button being depressed.
Second, similarly to how there were two highest-level states for the clock (ticking or setting), there should be two highest-level states. In the first, which is active upon reboot, your PCB should play the song “Mary Had a Little Lamb” repeatedly. When any button is depressed, you should transition out of the the initialization state into the button-tone state described above.
When a button is depressed, set the frequency and duty cycle and enable the PWM counter to play the appropriate sound. (Hint: Begin by adding your state machine code to the lab template. Remove the long-press states, and modify the short-pressed state to enable PWM.)
From this website, we have the suggestion that the notes for Simon should be:
Our buzzer has a fundamental frequency in the 4-8 kHz range. Frequencies outside this range will induce more nonlinearities in the piezo mebrane. So using notes that are two octaves higher (i.e., G6, E6, C6, and G5) will sound a bit less mechanical.
In order to play music, you need the ability to specify both the frequency and duration of the notes that you are playing. (Music comprises both tonal sound and silence!) If we notated music as tuples of note and duration, if “q” is a quarter note, “h” is a half note, and “w” is a whole note, Mary Had a Little Lamb could be represented as:
(E,q) (D,q) (C,q) (D,q) (E,q) (E,q) (E,h) (D,q) (D,q) (D,h) (E,q) (E,q) (E,h)
(E,q) (D,q) (C,q) (D,q) (E,q) (E,q) (E,q) (C,q) (D,q) (D,q) (E,q) (D,q) (C,w)
Here is the suggested approach.
Presumably quarter notes will correspond to something like 600-800 ms, while your interrupt ticks will occur every 10 ms. Thus, the “music playing” state will need to implement a counter that resets for each note and then counts down while the note should be being played. In order to play a note, you will need to set the approriate values for the frequncy and duty cycle of the PWM. Importantly, when no tone should be being played (e.g., during the brief periods between notes or during a musical rest), you can disable the counter using the CTRCTL register’s enable/disable bit.
Full rubric credit for the song requires that the song be easily changed to a different musical score.
One more requirement for the notes for this lab is that sounds should not slur from one note to another. This means that there needs to be a gap of silence between notes. Full credit for this requirement requires that the whole note including the internote gap is four times as long as the quarter note including the internote gap. (This makes it harder to just paste on to existing code.)
The buzzer is also connected to a pin that can be controlled by the DAC output of the MSMPM0+. Rather than driving the sounds with PWM square-waves, implement more complex waveforms like sinusoids.
Optimize your code for lower power. Configure the SYSOSC to use a 4 MHz frequency for both your code and timer. Implement at GPIO interrupt to additionally trigger wakeups with button state changes and timer G0 wakeups. Optimize the timer interrupt for debouncing. Ensure that you go into SLEEP while waiting for input. Measure power consumption before and after these changes and demonstrate the improvement.
The schematic for the Simon PCB can be found on the github - https://github.com/ckemere/ELEC327/tree/master/PCBs/Simon-2026-JLC. Of critical importance, the GPIOs conneted to the buttons are PA23, PA24, PA25, and PA26. The Workspace template Code Composer Studio project https://github.com/ckemere/ELEC327/tree/master/Workspace/Lab5 helps you out by configuring the GPIO for those 4 buttons, as well as 2 modules:
In order to program the Simon PCB, remove the 10 jumpers that connect across the top of the Launchpad.
These connect an XDS110 debugging interface at the top of the PCB to the microcontroller at the bottom.
Instead, you need to connect these pins to the Simon PCB. The programming pins are labelled - you will
need to connect GND, VCC=3V3, NRST, SWDIO, and SWCLK. (The other ones we won’t connect allow
the debug interface to pass through UART communications to the PC and enable some sort of boot-strap loader.)
The video below shows a jumper cable connecting the Launcpad and a Simon PCB.
Video of Launchpad Connected to Simon PCB