A Low Cost Frequency Generator

frequency generator


In one of my labs, a GTA was proudly showing us a tuning experiment he set up with two frequency generators, an oscilliscope, and speakers. I thought it was neat and wanted to recreate it, but most of us don't have money to burn on expensive equipment. And why should we, when a computer could do almost all of that at a fraction of the price?

Well, as it turns out, it probably was a good thing that UTA has money to burn on this sort of stuff. While I would certainly not call this hack a failure, it left a lot to be desired.


Today's personal computers are capable of sending and recieving data from the parallel port. I had my first introduction to parallel port hacking my senior year of high school when I designed and wrote software for Blinkin' Adrenaline. Here the concept would be similar, except instead of lighting LEDs, I would send data to the speakers.

I eventually gave up trying to find a description of how speakers actually work, and went with my gut. I was right, and here is how they work:

For a single speaker, there exists a data line and a ground line. If there is only one speaker then it doesn't matter which you choose to be which. When power is applied, the speaker flexes outward driven by an electromagnet. When the power is cut the speaker is yanked back to its initial position. Now if you were to flip the power on and off rapidly, the speaker would produce noise. Therefore, it stands to reason that we could turn a pin of the parallel port on and off rapidly and, if that pin is connected to the speaker, produce a pitch.

If it is a stereo connection, then each speaker will have its own line and they will share a common ground. So there will be a total of three pins used: two data and one ground.

Finally, the microphone input on the soundcard could be used as an oscilliscope to visualize the frequency. I have to credit my lab GTA for this idea. Sadly, my sound card's microphone jack has been broken for a long time now and I was unable to test this out.


Materials wont put you out much. I spent $11 at Radio Shack. You'll need a D-Sub connector and a hood if you want to splurge (I skipped the hood). Also, you'll need appropriate audio jacks. I accidentally bought male jacks instead of female and have to use a double female connector with my speakers. Finally, don't forget some wire. Shielding wont be necessary because the signal will already be pretty noisy.

I am going to assume that you already have things like a soldering iron and a pin inserter (if not, they cost about $3).

You might notice that I did not use any resistors. This is sloppy, and in theory could fry your parallel port. If you wish, you might consider measuring how much current your stereo pulls and use resistors to drop that into something appropriate for the parallel port.

Constrution and Software

Put all the parts together as makes sense. This should be fairly intuitive. I used pins 2 and 3 for the speaker lines and pin 25 as ground. Make sure you understand what you are doing if you choose other pins instead.

I wrote my software for my freeBSD computer. The inital challange was to find a library that supports parallel port access with freeBSD. It turns out that freeBSD comes with PPI which does the job just fine. If you are not familiar with PPI and are running freeBSD, man ppi.


If you have not yet noticed, this is not a very good frequency generator. For one, a "real" frequency generator would produce an analog signal and we are sending a digital signal. Therefore, instead of having pretty sinusoidal sound waves, we get square (1,0,1,0,1, ...) waves. At higher frequencies the difference is nominal, but this means that the lower frequencies wont sound very good.

There is a solution to this. If one were so inclined, that person could build a cheap digital to analog converter and improve the quality of the wave. I didn't bother.

Another problem is changing the period. There is a delay associated with sending data to the parallel port, and that will cause the period to be longer than we expected, causing a lower frequency than asked for. On top of that, the sleep functions appear to have a 1 milisecond delay (determined experimentally) and have poor resolution (~2 miliseconds). This causes the frequency to jump to predetermined frequencies instead of transitioning between them.

I got around the some of the above problems by not using a sleep function, but instead using an empty counting loop. This allowed for much better resolution, but at the cost of having to guess what the frequency is. Also, the frequency will drop if the processor's load were to increase significantly. It is possible that nanosleep could fix this, but nanosleep requires predetermined values be compiled into the program.

Valid HTML 4.01 Transition

Valid CSS!

© 2006 Nic Reveles