Prerequisite Modules
- Development Software Suite
- Version Control
- Embedded C and IAR Primer
- Firmware System
- LED Basic
- Button Interface
- Debug Interface
A simple and common audio source in an embedded system is a piezoelectric buzzer since they can be easily driven with a square wave directly from the processor with very minimal current draw. They will reproduce tones in the full audible range of a human ear which is about 50Hz to 15kHz.
The challenge in creating audio with a microcontroller is the various calculations needed to get the actual frequency correct, and then generating a constant frequency square wave without impacting the rest of the program. Therefore an API that does these things for you is very useful.
API Description
If you are following along sequentially in the EiE modules, this is the first task that will make use of one of the SAM3U2’s functional peripherals. If you explore the firmware, you will not find any code that toggles the output lines to the buzzer directly. All output is handled by the peripheral that is simply set up with the frequency and duty cycle required to create the audio signal.
Type Definitions
Enumerated types are defined in each development board’s hardware definition files to identify the buzzers:
- ASCII (file eief1-pcb-01.h): BUZZER1 (right side), BUZZER2 (left side)
- Dot matrix (file mpgl2-ehdw-02.h): BUZZER1
Public Functions
The buzzer API functions are defined in the board-specific firmware files (eief1-pcb-01.c for ASCII and mpgl2-ehdw-02.c for dot matrix). They do not get their own driver files as they are very hardware-specific and quite simplistic. The functions may be used by any application in the system, so task awareness is necessary to avoid conflicts.
- void PWMAudioSetFrequency(u32 u32Channel_, u16 u16Frequency_) – Configures the buzzer with the desired frequency. Parameter u32Channel_ is either BUZZER1 or BUZZER2; u16Frequency_ is in Hertz and should be in the range 100 – 20,000 though higher and lower frequencies are allowed. The buzzer remains in its current on or off state.
- void PWMAudioOn(u32 u32Channel_) – Turns on the buzzer specified in u32Channel_. The buzzer will run at whatever frequency it was last configured to. If the buzzer is already on, it will stay on.
- void PWMAudioOff(u32 u32Channel_) – Turns off the buzzer specified in u32Channel_. If the buzzer is already off, it will stay off.
Examples
Start with the Master code branch from GitHub and create a new Buzzer branch. The first task is to toggle a 500Hz tone on when BUTTON0 is pressed.
In UserApp1Initialize() add this line:
In UserApp1SM_Idle(), add the following:
Music (sort of) – Dot Matrix Development Board
Since the dot matrix development board has only two buttons, we’ll write code so BUTTON1 changes the frequency played by BUTTON0. The frequency selected will be sequential notes using the definitions from music.h, namely C4, D4, E4, F4, G4, A4, B4, and C5 (FYI there’s a lot of information about musical notes in the Buzzer Advanced module).
A sequence of anything begs the use of an array, so that is the data structure that will be set up to make this happen.
Now use WasButtonPressed() to monitor BUTTON1 and update the currently set frequency whenever the button is pressed. Wrap around to the beginning after the last note in the array.
Build and test the code. Check to see that it works properly. Notice than you may change the frequency with BUTTON1 while BUTTON0 is being held, but you can also change it without any sound being played.
Before the main module exercise, experiment with your program to make it do more interesting things. At the very least, think about how you would do each of the following:
- Instead of looping back to 0, traverse back down the array once the end is reached (and then traverse back up)
- Code a simple song in the array so it plays as you cycle through BUTTON1
- Code the 4 notes required for “Mary had a Little Lamb” in the array (C4, D4, E4, G4) and show the current u8NoteIndex value (which will be 0, 1, 2, or 3) on the LEDs (e.g. if 0, turn on BLUE0). Figure out the sequence you need to play, then see if you can play it by using BUTTON1 to select the correct note and BUTTON0 to play it when the LEDs confirm it.
Module Exercise
This exercise requires the use of the Debug API.
Add a full octave (12 notes including sharps and flats starting with C4) of notes by using keyboard keys through the debug interface. Use keyboard keys Z, X, C, V, B, N, and M for the musical notes C, D, E, F, G, A, B. Use keyboard keys S, D, G, H, and J for the sharps/flats. With each letter input, play the corresponding note for 300ms. The frequencies of the notes can be found in music.h.
Part 2: Use BUTTON1 to increase the octave, and BUTTON0 to decrease the octave so you can play 4 octaves of notes. The buttons can be used to set a multiplier to a base set of frequencies for the full scale of notes. It’s probably a good idea to indicate the current octave with an LED.
Try to play a song, or at least try to play every note from C3 to B6 in order.
[LAST UPDATE: 2024-OCT-29]