TI (Texas Instruments) is awesome - I've always known it. What I like the most is their extremely low-cost ($4.30, who beats that?) Launchpad development kit that includes 2 "value line" (pronounced "super-cheap") micro-controllers, USB programmer and development software. That is everything you need to dive into the wonderful world of the super-lower-power microcontrollers.
Picking the test project
There are so many options for a first project: flashing LED, doomsday device, iSomething…
Hm, iSomething sounds like a cool idea. How about making a poor-guy MP3 player? Maybe downgraded to the extreme: one song, poor audio quality, no control buttons?
To make a digital audio player we need two major components: storage memory for digital audio and Digital-to-Analog Converter (DAC). Expectedly, such a simple microcontroller does not have a built-in DAC, so it sounds like I would need a separate chip. But wait...
Who needs a DAC for lousy quality audio?
There is an easy alternative to DAC – Pulse Width Modulation (PWM). The idea is to generate an audio signal with variable-width digital pulses, which should produce acceptable quality audio with high enough pulse frequency. Sure enough, TI has an application note to demonstrate exactly that (PWM for audio application). Since I decided not to worry about audio quality, I picked 8-bit for audio resolution (as a side note - it is supposed to be roughly equal to AM radio quality). The 8-bit resolution gave me 256 possible PWM widths (for example, value 10 means that output stays on for 10 cycles and after that turns off for 255-10=245 cycles).
Assuming that my TI chip runs at the max speed (16 MHz) my complete PWM cycle would be: 16,000,000Hz/256=62,500 Hz. Wow, at such high PWM frequency I should be able to generate sound with frequencies up to 62,500Hz/2=31,250 Hz (this calculation is based on Whittaker–Nyquist–Kotelnikov–Shannon sampling theorem). This also means that I have to store 31,250 bytes of data for 1 second of music. Where am I going to store my music?
External storage
MSP430G2231 only has 2KB of memory. Since I need 31,250 bytes to store 1 second of music, I could store the whole 0.06 seconds using internal storage. This is definitely not enough.
This just means that I need external storage. How about a SD/MMC Card? It is the perfect external storage for microcontrollers because it is inexpensive and supports microcontroller friendly SPI protocol. The Launchpad came with 2 chips: MSP430G2211 and MSP430G2231 the latest has built-in universal serial interface that supports SPI protocol, perfect! After checking the TI website, I found this application note to interface between MSP430 and SD Card. Now I need to decide how to store the music.
Audio format battle: mp3 vs. au
It would be really cool to play mp3 files on the Launchpad, but it's not going to work. For example, the smallest Helix mp3 decoder needs ~20K of program memory, and my microcontroller has only 2K. Of course I could add an external mp3 decoder - but that's not fun.
Since mp3 is out, I could just write audio as a stream of samples (bytes) and add simple header to tell how many samples are in my file, sample rate, etc. It would be nice to use a standard audio file format, however, so I chose arguably the simplest audio file format ever created: au format. Even though it is quite old, the format is still supported by many applications including my favorite (open source) audio editor – audacity.
Getting audio file to the SD card
Storing files to an SD card is also tricky. For multiple reasons I decided not to use a file system on the SD card, so I have to write an .au file to the card as a raw data. This can be done by using HDD imaging tools. I've had good experience with DiskImage, although other disk imaging software (such as dd) should work as well.
Hardware
There are only two external components to the Launchpad used: the SD card and the earbud headphones. I connected the SD card power to one of the Launchpad pins, so I could reset the card by toggling its power. The earbud headphones connected to the Launchpad PWM output pin through a current limiting resistor. "But where is your low-pass filter?" curious readers will ask. Well, yes, I should be using a low-pass filter to smooth-out PWM pulses. However, headphones work well enough as a low-pass filter due to their mechanical nature. So, cancel the filter and connect everything together!
SD card access time issue
After fixing a few software bugs I finally heard something in the headphones. It was sort-of music but with some strange clicking noise. Such a disappointment; I thought I was done!
It turns out that as the data, which was stored on the SD card in 512 byte blocks, sometimes took time to switch between these blocks, and every so often I was missing a few samples and it caused these clicks. I added a small (16 samples) FIFO buffer between the SD card and PWM. The buffer made its magic and I was enjoying AM quality music for a whole 15 minutes.
Conclusion
It's totally possible to play acceptable quality audio using a very basic microcontroller. The sample rate can be pretty high (~31kHz in my case), allowing you to achieve much better audio quality, although PWM resolution (8 bit) is a limiting factor.
One of the options to drastically improve audio quality would be to use two independent 8 bit PWMs and sum up their signals. This would increase the audio resolution to 16-bits which should sound (almost) like a CD quality. However, MSP430G2231 has only one PWM channel so it is not an option here.
Video
Here is a video of the Launchpad playing (kind of) music, enjoy.