Simon board plays “Mary Had a Little Lamb” at start up, then transitions to tones when buttons are pressed
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 init_timer.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 init_timer.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 init_timer.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.
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.