Step 3How it works:
First, here are a bunch of includes. Of course there are the ones for the processor as well as some standard libraries. What is important here is the header files which correspond to the samples. This is a way to conveniently load data from your computer into the microcontroller at compile time. I wrote a MATLAB script which reads .wav files and declares a large array e.g.:
int mydata[] = {1, 2, 3, 4};
Then there's the section:
void __attribute__((__interrupt__)) _T2Interrupt( void )
{
This is the interrupt for Timer 2, which drives the PWM. A PWM (Pulse-Width Modulator) generates a sort-of-analog waveform by quickly changing the duty cycle of a pulse waveform. This is because the digital outputs of the microcontroller can only generate a logical 0 (which is at ground voltage) or a logical 1 (which is at the battery voltage). If we want to say, approximate a voltage halfway between that, we can use the PWM to turn on the pin half the time and turn it off half the time. As long as this is done very quickly, we can approximate the voltage well enough to sound like the original waveform.
The T2Interrupt function is an interrupt handler for Timer 2. It basically means that the PWM needs another sample, so we read another sample from program memory and stuff it into the OC1RS register. This is how PWM knows what voltage to approximate for the next sample time.
void __attribute__((__interrupt__)) _CNInterrupt( void )
{
This section is an interrupt handler for the change notification. The change notification throws an interrupt (that is, executes the above function) any time one of the pins you have enabled changes state (goes high->low or vice versa). This is how we detect the switch being pressed. Notice that we could poll here, but the change notification peripheral works even when the microcontroller is asleep, allowing us to save a lot of power. What we do here depends on whether a sound is already playing. If a sound is already playing and we are in the first 375ms of the sample, it will simply reset the sample index (thereby restarting playback at the beginning of the same sample). If there is no sound playing or we are past the first 375ms, we will randomly pick a new sound out of the 10 and play that. This allows the Lil Jon Button to repeat the same sample but still have enough random behavior to be interesting (e.g. Ya-Ya-Yeah! OKAY!).
void setupHS()
void setupCN()
void setupPWM()
Here are some setup functions. This is quite complicated and you are best to consult the datasheet for exactly what happens here. Suffice to say the first sets up the processor clock to 66.33 Mhz, the second sets up the change notification, and the third sets up the PWM. For your reference, the datasheet can be found here:
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en532296
Finally the:
int main ()
{
Which is the main loop. Code starts executing here, so the first thing it does is set up the peripherals. Then the main loop doesn't so a whole lot. It basically just waits around for a bit, and goes to sleep. All the work happens because the interrupts above have been registered, so when something needs attention (e.g. the PWM needs the next sample), the correct interrupt will automatically be called. Typically when the microcontroller goes to sleep, no code gets executed. However, because the change notification peripheral has been enabled, a push on the button will cause the microcontroller to wake up and immediately service that interrupt and start playing a sample.
Final note:
An observant engineer might ask, why did you not use the DAC feature of the microcontroller? In fact the dsPIC33FJ128GP802 has an audio DAC which is designed for this sort of thing. The reason is to simplify the design. Notice that in order to drive a speaker out of a PWM, the only thing that is needed is single digital switch (a BJT in this case with no resistors for biasing). If instead the output was a DAC, a linear amplifier made out of transistors (with additional resistors) or an op-amp would be required. This greatly increases the complexity of the design and the part count. Notice that the input waveforms are simply 8kHz 8bit audio files, so a full CD-quality DAC is overkill in terms of audio quality, but increases the overall expense.
Other final note:
The dsPIC33FJ128GP802's voltage range is only 3.0-3.6V. I have observed it to run at about 2.8V without problems with this code, but stability cannot be guaranteed for the long run. I recommend if you are to experiment with the code to use some lithium AAA batteries: http://www.amazon.com/Energizer-Ultimate-L92BP-4-Lithium-Battery/dp/B0002DUQDQ . They maintain 1.5V for a much longer time than alkaline AAAs.
| « Previous Step | Download PDFView All Steps | Next Step » |
![]() |
Add Comment
|







































