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
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

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!


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:
File Description
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 chock@global.co.za 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:

©1999 Chris Hockaday - Last updated