This enables you to play a .WAV off an 8k PIC microcontroller.
Please note! This project was never completed, and unfortunately I have lost my source code. However, I've had loads of people asking me about it in the last few weeks, so I've included what has now become my standard reply letter. Don't get me wrong, I really love to hear from all of you, and if you still can't get anywhere with what you find here, I'm more than happy to answer any further queries
Hi again OK, this is what I could scrounge together. I lost my actual PIC code, but it's no major loss really. It was really tacky, because I started this as a quick project just to see if it was possible, and lost interest after I got it working. You didn't say which micro you're using, but I'm assuming a PIC. This is a great choice, because the instruction words are 14 bits long. I used a PIC16F877, which has 8k of FLASH ROM, which can be read using a code sequence in the data sheet (if you haven't got this, just shout and I'll send it too) So what I did was write a quick script in BASIC to read the ASCII file generated by cooledit, convert the samples to binary and discard the LSB (effectively making the samples 7 bits). I then concatenate two consecutive samples and write them as one 'instruction' in an #include file, which I then simply #include in the code. I've attached this code. It should be fairly simple to figure out. If you don't want to figure it out, just run it with QBASIC. In Cooledit, I resampled the file to 6kHz before converting to ASCII. This way, with 8k * 2 samples in the ROM, at 6000 samples per second, you can cram about 2.5 seconds of sound into it. Of course you can always use external ROM if you need more, but you'll probably have to go back to 8bits. Now for the PIC code. It's very simple, really. I didn't use hard core timing loops or anything, I just NOPtimised my code to get the delays in the right ballpark. At 6000 samples a second, that's about 166 instruction cycles between outputs. There were two sections of code. The first reads the 14bits and gets the upper (or lower...check out my script and work it out, I can't remember) 7 bits, and then puts it on a port. In the second half, it simply takes the other 7 bits and puts them to the port. This involves a bit of shifting, and was where I ran into problems, but it can be sorted out with a bit of thought. Now for the D/A section, I just used an R2R ladder that I found in the PIC embedded control handbook. I've scanned the page and attached it. I never really built a successful output stage (amp etc.)...I just pumped it into my soundcard's line in through a 50k resistor. OK, that's about everything I can remember about this project. As I said, I never really finished it, and my links on my page are broken, because I uploaded that page by mistake before I completed it. Well, I hope I've been of some help. Feel free to write back if you need anything else Good luck! Chris
The code has been developed for the PIC16F877 8k Flash microcontroller, but can easily be ported to other PIC micros.
It is capable of playing up to 2.7 seconds of a 6kHz .WAV file by storing two 7 bit samples per 14 bit word of program memory.
Here's some stuff to ge you started:
|PIC-WAV.BAS||QBASIC file to convert Cooledit .ASC to .INC file|
|R2R.JPG||Scanned out of the Microchip Embedded Control Handbook - A very simple D/A converter|
|WAVEDATA.INC||[Zipped] This is the include file for the sound you heard when you loaded the page. [command codes verified]|
You will also need COOLEDIT from http://www.syntrillium.com to convert your wave files to 6kHz, 8-bit, MONO format ASCII TEXT DATA format
This application is a hell of a waste of an 8k micro, but it's a lot of fun once you have it working. In its present state, it continuously loops through the wave file, but can easily be modified to operate on interrupt
If you do anything amazing with this code, I would love to hear from you. Please email me at email@example.com and let me know what you've come up with. If you have any trouble getting started, mail me and I will be happy to answer your questions
Here are some example applications of this code: