picture home | pixelblog | qt_tools

omino code blog

We need code. Lots of code.
David Van Brink // Sat 2007.05.26 22:49 // {applet code wbl weird blinking lights}

The 1-bit DAC

This applet says it all… but there’s an explanation below, and even a bit of code.

Why? To blink the LED, of course.
If you’re like me you’ve often needed to use a single digital output pin on some chip or another to express an analog value. That’s because, if you’re like me, you’re a) too cheap to buy a DAC, b) too cheap AND lazy to rig one up out of multiple pins and resistors, and/or c) too clever by half.

Perhaps you want to fade an LED in and out from an FPGA or a PIC chip. Or you want to create NTSC-compatible video out of a single FPGA pin.

In general, you can just flick a pin high and low very fast to “simulate” some value between zero and one. Or, to be vaguely more specific, you flick the pin high and low much faster than the sort of signal you’re producing, and some other part of the system — your eyes or ears, the frequency response of the audio amplifier, or the RC filter you dutifully implemented — filters out those high frequencies.

Pulse Width Modulation, a Perennial Favorite
A typical approach is to use a “pulse width modulation”, in which you choose some basic sample-width, and raise your pin for a portion of the sample corresponding to the desired value. Suppose our sample-width is 8 clocks. We can represent the values between off and on with 8 intermediate values, with the following bitstreams:

Pulse Width Modulation
0.000 : 00000000 00000000 00000000...
0.125 : 10000000 10000000 10000000...
0.250 : 11000000 11000000 11000000...
0.375 : 11100000 11100000 11100000...
0.500 : 11110000 11110000 11110000...
0.625 : 11111000 11111000 11111000...
0.750 : 11111100 11111100 11111100...
0.875 : 11111110 11111110 11111110...
1.000 : 11111111 11111111 11111111...

The 1-bit DAC, a L337 Sekrit
A less-well-known approach is the so-called 1-bit DAC. (Also known as “sigma-delta modulation” and “pulse density modulation”.) It works by flickering the output pin as fast as possible to get, overall, the density of 1’s corresponding to the dac value. Here’s the bit patterns produced by a 1-bit DAC.

1-bit DAC
0.000 : 00000000 00000000 00000000...
0.125 : 00000001 00000001 00000001...
0.250 : 00010001 00010001 00010001...
0.375 : 00100101 00100101 00100101...
0.500 : 01010101 01010101 01010101...
0.625 : 01011011 01011011 01011011...
0.750 : 01110111 01110111 01110111...
0.875 : 01111111 01111111 01111111...
1.000 : 11111111 11111111 11111111...

The big difference is that the pin flickers faster. Why is this good? Well, in the case of, say, modulating the brightness of an LED it means the LED appears to flicker less!

Let’s show how it’s implemented — oh it’s so trivial! — and then talk a little bit more about why this technique is in some practical ways “better” than PWM.

How To Implement A 1-bit DAC

int dacRunningSum = 0;
int dacValue; // values are from 0 = off, to 8 = full on.
int getNextPinOutput() {
   int pinOutput = 0;
   dacRunningSum += dacValue;
   if(dacRunningSum >= 8) {
      pinOutput = 1;
      dacRunningSum -= 8;
   }
   return pinOutput;
}

Do you see how this can work? If your dacValue is 4, then exactly every other time through the running sum will exceed 8. And if it’s 5, a little more often; 3, a little less.

You can also see how easily this translates to checking the carry-bit in assembly language, or summing to a wider register in Verilog. I’ve used 8 levels in the examples, but 256 or even higher is a more common range.

Why It’s Better
For LED’s, which have essentially instant-on and instant-off times, flickering faster is just plain better. But why? It’s all about the frequency artifacts. The higher the frequency artifacts are, the further they are from the frequencies you’re actually interested in (such as the pulsing of an LED or an audible sine wave).

The applet above shows the high-frequency distributions for different bit patterns. The total amount of noise is about the same for both methods, but the distribution of noise favors higher frequences for the 1-bit DAC.

Applet Source Code
And, as customary, the source code to the Applet. I found an FFT on the web and used it as the basis for the frequency amplitudes display. (See frequencyAmplitudes() in Fft.java below.)

1 comments
Douglas // Sun 2007.06.10 07:517:51 am

Back in the early 90s when DACs were still expensive and you were lucky to get a CD player with an 8-bit DAC, Techniqs came out with their 1-bit DAC. I knew the basics of how it worked but your explanation fills in a lot of gaps. Thanks! Oh yeah, the CD player sounded great.

oh, i dont know. what do you think?



(c) 2003-2011 omino.com / contact poly@omino.com