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.
Hardware
There are only two external components to the Launchpad used: SD card and earbuds headphone. I connected SD card power to one of the Launchpad pins, so I can reset the card by toggling its power. Earbuds headphone connected to the Launchpad PWM output pin through a current limiting resistor. "But where is your low-pass filter?" curious reader will ask. Well, yes, I should be using a low-pass filter to smooth-out PWM pulses. But 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 a music, but with some strange clicking noise. Such a disappointment! I though I was done with it.
It turned out that data on the SD card stored in 512 byte blocks and sometimes switching these blocks takes some time, so every so often I was missing a few samples and it caused those clicks. I added a small (16 samples) FIFO buffer between SD card and PWM. Buffer made its magic and I was enjoying AM quality music for a whole 15 minutes or so.
Conclusion
It's totally possible to play an acceptable quality audio using the most basic microcontroller. Sample rate could be pretty high (~31kHz in my case) and allows to achieve a 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 summing up their signals. This would increase audio resolution to 16 bits which should sound (almost) like a CD quality. Although, MSP430G2231 has only one PWM channel, so it's not an option here.
Video
Here is a video of the Launchpad playing (kind of) music, enjoy.
Source Code
Grab it here.
Picking the test project
There are so many options for the 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 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 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 audio signal with variable-width digital pulses, with high enough pulse frequency it should produce acceptable quality audio. 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). 8 bit resolution gives 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). But it 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. Because 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. Well, it just means that I need an external storage. How about SD/MMC Card? It is a perfect external storage for microcontrollers because it is inexpensive and supports very 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! And of course after checking 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 not going to work, I could just write audio as a stream of samples (bytes) and add simple header to tell how many samples in my file, sample rate, etc. But it would be nice to use a standard audio file format, so I choose arguably the simplest audio file format ever created: au format. Even it is a quite old format, but still is supported by many applications including my favorite (open source) audio editor – audacity.
Getting audio file to the SD card
To store file to a 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 .au file to the card as a raw data. This could be done by HDD imaging tools, I had good experience with DiskImage, although other disk imaging software (such as dd) should work.
There are so many options for the 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 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 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 audio signal with variable-width digital pulses, with high enough pulse frequency it should produce acceptable quality audio. 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). 8 bit resolution gives 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). But it 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. Because 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. Well, it just means that I need an external storage. How about SD/MMC Card? It is a perfect external storage for microcontrollers because it is inexpensive and supports very 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! And of course after checking 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 not going to work, I could just write audio as a stream of samples (bytes) and add simple header to tell how many samples in my file, sample rate, etc. But it would be nice to use a standard audio file format, so I choose arguably the simplest audio file format ever created: au format. Even it is a quite old format, but still is supported by many applications including my favorite (open source) audio editor – audacity.
Getting audio file to the SD card
To store file to a 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 .au file to the card as a raw data. This could be done by HDD imaging tools, I had good experience with DiskImage, although other disk imaging software (such as dd) should work.
Hardware
There are only two external components to the Launchpad used: SD card and earbuds headphone. I connected SD card power to one of the Launchpad pins, so I can reset the card by toggling its power. Earbuds headphone connected to the Launchpad PWM output pin through a current limiting resistor. "But where is your low-pass filter?" curious reader will ask. Well, yes, I should be using a low-pass filter to smooth-out PWM pulses. But 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 a music, but with some strange clicking noise. Such a disappointment! I though I was done with it.
It turned out that data on the SD card stored in 512 byte blocks and sometimes switching these blocks takes some time, so every so often I was missing a few samples and it caused those clicks. I added a small (16 samples) FIFO buffer between SD card and PWM. Buffer made its magic and I was enjoying AM quality music for a whole 15 minutes or so.
Conclusion
It's totally possible to play an acceptable quality audio using the most basic microcontroller. Sample rate could be pretty high (~31kHz in my case) and allows to achieve a 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 summing up their signals. This would increase audio resolution to 16 bits which should sound (almost) like a CD quality. Although, MSP430G2231 has only one PWM channel, so it's not an option here.
Video
Here is a video of the Launchpad playing (kind of) music, enjoy.
Source Code
Grab it here.
Hello, I downloaded the source code few days ago and I am currently having hard time understanding "Disk Imaging".
ReplyDeleteI made an .AU file for the music and I made a raw file of SD card after puting AU file on it. What would be the next step? Should I copy the raw file into the SD card by just copying and pasting or should I copy the file using the Disk Imaging as well?
My question seems vague, but I am really stuck on this problem and it is really hard to move forward without understanding this. Thanks,
_Yi
wldnjs61114@hotmail.com
You have to use your .au file instead of the raw file to write it to the SD card. For example, in the Dubaron DiskImage select your SD card in the "physical drives" and click "import from file" button.
DeletePlease post the wiring connection diagram!
ReplyDeleteThere any electronic component in your scheme, beyond TI MSP430 LaunchPad and SD Card?
Regards,
Igor Isaias Banlian
Unfortunately I don't have a schematic, sorry.
DeleteThis is how TI chip connected to the SD Card:
TI P1.7(9)-SD MISO(7);
TI DVSS(14)-SD GND(6);
TI P1.5(7)-SD CLK(5);
TI P1.3(5)-SD 3.3V(4);
TI DVSS(14)-SD GND(3);
TI P1.6(8)-SD MOSI(2);
TI P1.4(6)-SD CS(1);
SD card pinout: http://www.interfacebus.com/Secure_Digital_Card_Pinout.html
One side of the headphone is connected to the TI pin P1.2 through the resistor (330 ohm should work), the other side is connected to the DVSS (GND).
Great project! What is the maximum capacity of SD that is supported?
ReplyDeleteThank you.
DeleteIt should support all standard SD cards (up to 2GB).
Hey Boris, have you tried the MSP430G2553? It has 2 timers so 2 PWM channels. It's shipped with newer Launchpads.
ReplyDeleteAlso, what should I change from your original code to loop the sound on the SD card forever?
No, I haven't tried MSP430G2553. I got the original launchpad that came with MSP430G2211 and MSP430G2231.
DeleteActually it should already be doing that, playing .au file in a loop.
This comment has been removed by the author.
ReplyDeleteI have one of the 2553's and after reading about this project, I was wondering if you might have any thoughts on how one might go about making an audio recording and play back device in this fashion.
ReplyDeleteI think it should be relatively easy to implement.
DeleteMy example doesn't have any routines to write to SD card, but I guess you could get a full SD card library (mmc.h and mmc.c) from TI website and its probably supports write functionality.
Rest of it should be simple. We don't need to worry about any particular file format, just sample ADC and save each sample to the SD card.
Actually, 2553 has a whole lot more FLASH memory (16Kb) than 2231, so you could get fancy and add a file system support, so you could read/write files on the SD card on the PC.
Hi you. I have some problems with your project.
ReplyDeleteI was wrote au file into SD Card but when I run this app, I don't hear anything from headphone although on-board red led still on.
Then I debug to find the faul, I found that it loop forever at mmc_GoIdle() function (in initMMC() fuction, in initMMC() funtion, in au_Init() function , in main() function). when run step by step at mmc_GoIdle() function i cant what happen with code, compiler pass some line code and goto wherever in this function.
I think the reason is that the compiler is not compatible.
Do you give me a version of your compiler?
if not the reasons you can help me put out a solution rather
sorry for the ability to write my english is not good and thanks you !!!
I was using Code Composer Studio (CCS) v4.
Deletehttp://processors.wiki.ti.com/index.php/Category:Code_Composer_Studio_v4
This comment has been removed by the author.
DeleteThis comment has been removed by the author.
DeleteI still do not get a response CMD0? Can you tell me the reason of this error? (I tried to read the card with my PC and everything ok)
DeleteI am using a SD card with 4GB capacity, Is this a problem?
Can you help me slove this problem? Please!
4GB would definitely be a problem. Technically your card is SDHC (SD High Capacity) and it's not supported by the MMC library used in this project, sorry.
DeleteThansk you very much, i was solved my problem !
DeleteBut now I can read header of au file, au_ReadHeader()function always return false, I think it dont read a magic number because it return at the first if statement.
May be I streamed an au file in a wrong way.
I was "Write to file" an au file (17,9KB) and then the au file have a same size with sd card. Finally, I "Import to file" it into sd card.
The above way have some wrong?
You can help me one more time :)
Just be sure that your .au file is in a right format:
DeleteEncoding: 8-bit linear PCM
Sample rate: 32000
Channels: 1 (mono)
How to create a au file have right format?
DeleteI have tried creat it as follow:
+ Convert file .mp3 to file .au by this app (http://www.convertfiles.com/convert/audio/AU-to-MP3.html)
+ Write file .au into SD Card by Diskimage
According above way, I dont know about informations of file?
I am not sure about this online tool, but any standard audio editor should work. Personally, I am using free, open source audio editor "Audacity" (http://audacity.sourceforge.net).
DeleteThis comment has been removed by the author.
DeleteIn this tool, I can edit sample rate, encoding format, number of channels but my input is a au file which was converted from a mp3 file.
DeleteWhen converting finshed, I read au file by VS C++ and didn't find a header. I wonder that Is this approach will not create the file header au?
Can you give me a au file sample which you write into sd card? Thank you
my email: ddt.khtn@gmail.com
This is how I create .au file:
Delete1. Start Audiacity (I am using v2.0.0)
2. File/Open your mp3 file.
3. Tracks/Stereo Track to Mono.
4. Left Bottom corner "Project Rate" - select 32000
5. File/Export, select "Other uncompressed files" format.
6. Click "Options": select "AU (Sun/NeXT)" header, "Signed 8-bit PCM" encoding, click "OK".
7. Enter file name, click "Save"
8. On the edit metadata popup click "OK"
.au file I used for testing: https://sites.google.com/site/boris0attachments/PF.au
DeleteNow all was OK.
DeleteBut when read header of au file. I always get 0 from lTemp variable.
I sure that I was write data successfully (I View Hex)
What's wrong? You can help me ?
Maybe you somehow wrote file to the wrong location?
DeleteThe file should starts at the first (physical) block.
This comment has been removed by the author.
Deletei'm sure that i wrote (by tool) and read (by MCU) at first block
DeleteBut when i write file, my SD Card is in "Logical volumes" not in "Phisical drivers".
What's wrong here?
This comment has been removed by the author.
DeleteYou have to write to Physical drive.
DeleteYour SD card should be listed in the physical drives section as "removable" media.
Try different tool (dd or similar), maybe it'll work better.
How to my SD Card be listed in "Physical drivers"?
DeleteI don't know why it's not listed as physical drive.
DeleteI am using Diskimage on Windows XP, maybe it's not compatible with your windows version?
Maybe you'll have better luck with other disk imaging tools.
Ok, I'll try it with another tool.
DeleteThank you very much :)
This comment has been removed by the author.
ReplyDeleteI was ok with writing file au into sd card.
DeleteNow I just listen about 1 second music and then nothing to listen.
Whats wrong here?
Don't know. Maybe verify that it reads an .au file size properly?
Deleteone doubt
ReplyDeleteis it possible to play different files based on some condition
for instance if a parameter a is passed to the function it plays different files based on the value of a??.
It is possible and would be easy to implement. Although, I am not sure that there is enough program (FLASH) memory left on this microprocessor. So maybe you have to upgrade to the bigger chip (e.g. MSP430G2452)
Deletei am using 2553
Deletewhat changes should be done in the code to incorporate this
I am using USI (Universal Serial Interface) to communicate to SD card. 2553 does not have USI, but have 2 USCIs instead. So the first thing you have to do is to modify the code to use USCI instead of USI.
Deletei am using g2553 ,, what changes should be done in the code
DeleteAs I mentioned earlier, you have to rewrite SD communication functions (mmc.c: spiSendByte, MMC_initSPI).
DeleteDear Sir,
ReplyDeleteI use diskimage tool to import file Audio, but it show error.
File size does not match target device size.
Filesize: 26773 Target size: 1985740800
Just ignore this error. It complains that your .au file is smaller than the SD card size.
DeleteHello Boris, i need ur help. I use msp430g2231 coding on Iar Embedded Workbench. I read all of ur writing, ur gived links, but i cant play audio with g2231. When i compile codes, it is error occured like:
ReplyDeleteError[e104]: Failed to fit all segments into specified ranges. Problem discovered in segment CODE. Unable to place 37 block(s) (0x87e byte(s) total) in 0x7c8 byte(s)
of memory. The problem occurred while processing the segment placement command "-P(CODE)CODE=F800-FFDF", where at the moment of placement the
available memory ranges were "CODE:f818-ffdf"
Error while running Linker
what must i do :( need help
It sounds like the compiled code does not fit the FLASH. Verify your optimization settings (it should be set to maximum optimization).
DeleteHi Boris, Can I use a .wav file instead of an .au file? could you please give me some hints?
ReplyDeleteI am using 43oh SD Card Reader Booster pack v1.2 and G2553
Deletewav file format is pretty simple. Just parse a few values from the header (number of channels, sample rate, etc).
DeleteGreat project!! I've learned so much about audio and msp430 here!
ReplyDeleteI just have a question - any hint on how I can have forward/back buttons so that I can go up or down the list of audio files on the disk?
Thanks in advanced!!!
Currently, there is no logic to handle multiple tracks. It sounds like you need something more advanced than this example, probably file system support, searching for audio files, etc. But it won't be possible to do so on this tiny microcontroller.
DeleteIntresting project, but I can only hear the clicking noise.
ReplyDeleteI wrote the .au.raw with DiskImage on the card and used CSS to get the source code onto the mikrocontroller.
Has anyone an idea, what the problen may be?
Don't know what is going on, verify that you getting a valid samples from the SD card.
DeleteIs there an AC coupling capacitor between the pwm pin and the headphones?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteCould we play music in list?
ReplyDeleteAnd.. How to write list of music to SD Card and play one by one
Thanks for sharing your project :D
Awesome project, thanks a lot for sharing!
ReplyDeleteI've seen lots of misinformation earlier about smallish MSP430 chips not being able to handle an SD card due to the 512 byte sector size -- now we can finally see for sure how that is totally irrelevant in cases like this. Thanks again!
This is great, I'm going to try to get it up and running.
ReplyDeleteOne question: why do you say PWM resolution is 8 bit? Timers are 16 bit so PWM is also 16 bit.
Can you send the code for this mail id (manimuruganvbc@gmail.com) pls
ReplyDelete