Forums

dac dithering

Started by John Larkin November 29, 2013
In article <dksi99952gppmat1oh2bgq78a78en258f1@4ax.com>,
 John Larkin <jjlarkin@highNOTlandTHIStechnologyPART.com> wrote:

> On Fri, 29 Nov 2013 20:17:23 -0800, Kevin McMurtrie > <mcmurtrie@pixelmemory.us> wrote: > > >In article <e7ii9952f71b1gh01rfrvv8l0o701qrmln@4ax.com>, > > John Larkin <jjlarkin@highNOTlandTHIStechnologyPART.com> wrote: > > > >> OK, I'm sort of thinking this through. > >> > >> Suppose I have a stream of parallel digital words that represent a > >> waveform. Assume it's audio or something similar. Further assume that > >> it has an arbitrary number of bits available at an arbitrarily high > >> rate; we can fake the rate by digital interpolation if the raw data > >> stream isn't fast enough. > >> > >> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a > >> few parts per million) dynamic range. The 16 bit DAC quantizes the > >> signal to 15 PPM, and even worse, the DAC that we have in stock is > >> only guaranteed monotonic to 14 bits. > >> > >> We can clock this DAC really fast and lowpass filter the output. > >> > >> If the data is, say, 24 bits wide, we can call the first 16 bits H and > >> the low 8 bits L. > >> > >> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM. > >> > >> We could take the L bits and turn them into a PWM waveform, and when > >> the PWM was high, add one LSB to the 16 bit DAC. The averaged value of > >> the DAC now has 24 bit resolution. But the PWM signal winds up as a > >> spurious signal in the DAC output, at 1/256 the clock rate, and we'd > >> have to filter that out. That could be inconvenient. > >> > >> A better way to do this is to add the LSB correction at the same duty > >> cycle but splatter the highs and lows in time. That is, basically, a > >> first-order delta-sigma algorithm. The wiggled LSB is no longer a low > >> frequency whine, but it becomes wideband noise. > >> > >> One problem is that we can't be sure that the LSB that we dither is > >> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic > >> to 14 bits, so bad luck would have the dithered bit be 4x as big as > >> expected. Or negative. > >> > >> Assuming the DAC has the biggest nasties at major transitions, like > >> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when > >> we're making small signals. Add 64 or 293 or something maybe, to get > >> in a zone where it's probably pretty linear. > >> > >> One could accomplish the PWM by adding a sawtooth or triangle waveform > >> to L before quantizing to 16 bits. Or splatter the triangle samples > >> randomly, to get the delta-sigma noise shaping. > >> > >> If you added a bigger triangle than 1 LSB of H, the DAC output would > >> splatter over more than one bit. That reduces the probability that we > >> are using a "bad bit" transition, an non-monotic step, for the dither > >> interpolation. > >> > >> So it looks like I could have a lookup table of 24-bit numbers in the > >> ballpark of 293*256 or whatever, randomized with a flat probability > >> distribution (scrambled triangle) some modest number of H LSBs in p-p > >> amplitude. Every DAC clock, add the next one to the 24-bit data before > >> truncating to 16 bits for the DAC. That's sort of like a higher-order > >> "noise shaped" delta-sigma, but there's no feedback loop. The bigger > >> the spread of the random numbers, the more noise we make but the > >> better we cope with DAC monoticity errors. > > > >If you have a CPU generating the bits, it could run a linear > >congruential generator with little cost. I recommend initializing with > >a constant seed so that you can guarantee the results. The result is > >hardly random but it looks and sounds random when used for dithering. > >I've used it in photo processing algorithms to prevent blue sky and > >greyscale banding when generating ARGB packed in 32 bits. > > > >LCGs can be done with feedback loops in shift registers too. > > It's all in an FPGA, so a pseudo-random shift register, plus the DC > offset, could all be done in hardware. The low N bits of the random > number could be added to the 24-bit stuff, where N is, say, 11 or > thereabouts, to dither the DAC maybe 3 bits. > > I guess I could simulate this to tune it.
I forgot to add one thing: When I was converting 32 bit float to 8 bit integers for graphics, only a tiny amount of dither was added. The mathematically correct number produced visible noise in certain solid colors where the eye is sensitive. A very small amount, however, softened transitions from one value to another in nearly solid colors to make banding invisible. The same might hold true if this is audio. Fixing sharp steps in low frequencies might sound good with less filtering effort.
On Fri, 29 Nov 2013 21:44:24 -0600, Vladimir Vassilevsky
<nospam@nowhere.com> wrote:

>On 11/29/2013 8:37 PM, John Larkin wrote: > >> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a >> few parts per million) dynamic range. The 16 bit DAC quantizes the >> signal to 15 PPM, and even worse, the DAC that we have in stock is >> only guaranteed monotonic to 14 bits. > >Making 20 bits out of 14 bits = oversampling of factor 4096 ballpark.
If I bias the DAC into a zone without major transitions, it will likely be monotonic to 16 bits, at least when I'm making smallish signals. And if the added noise spans several LSBs, it gets better. So I only have to make 20 out of 16. The LTC1668 has sub-LSB DNL in zones, with a spike at major code crossings... looks like about 32 big DNL spikes. That makes sense for a classic R-2R ladder architecture. I just need to center the system "zero" in one of those nice regions.
> >> We can clock this DAC really fast and lowpass filter the output. > >Really really fast.
50 MHz, for a signal bandwidth around 100 KHz. Might work.
On Sat, 30 Nov 2013 00:07:04 -0600, Tim Wescott
<tim@seemywebsite.really> wrote:

>On Fri, 29 Nov 2013 18:37:01 -0800, John Larkin wrote: > >> OK, I'm sort of thinking this through. >> >> Suppose I have a stream of parallel digital words that represent a >> waveform. Assume it's audio or something similar. Further assume that it >> has an arbitrary number of bits available at an arbitrarily high rate; >> we can fake the rate by digital interpolation if the raw data stream >> isn't fast enough. >> >> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a few >> parts per million) dynamic range. The 16 bit DAC quantizes the signal to >> 15 PPM, and even worse, the DAC that we have in stock is only guaranteed >> monotonic to 14 bits. >> >> We can clock this DAC really fast and lowpass filter the output. >> >> If the data is, say, 24 bits wide, we can call the first 16 bits H and >> the low 8 bits L. >> >> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM. >> >> We could take the L bits and turn them into a PWM waveform, and when the >> PWM was high, add one LSB to the 16 bit DAC. The averaged value of the >> DAC now has 24 bit resolution. But the PWM signal winds up as a spurious >> signal in the DAC output, at 1/256 the clock rate, and we'd have to >> filter that out. That could be inconvenient. >> >> A better way to do this is to add the LSB correction at the same duty >> cycle but splatter the highs and lows in time. That is, basically, a >> first-order delta-sigma algorithm. The wiggled LSB is no longer a low >> frequency whine, but it becomes wideband noise. >> >> One problem is that we can't be sure that the LSB that we dither is >> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic to >> 14 bits, so bad luck would have the dithered bit be 4x as big as >> expected. Or negative. >> >> Assuming the DAC has the biggest nasties at major transitions, like >> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when >> we're making small signals. Add 64 or 293 or something maybe, to get in >> a zone where it's probably pretty linear. >> >> One could accomplish the PWM by adding a sawtooth or triangle waveform >> to L before quantizing to 16 bits. Or splatter the triangle samples >> randomly, to get the delta-sigma noise shaping. >> >> If you added a bigger triangle than 1 LSB of H, the DAC output would >> splatter over more than one bit. That reduces the probability that we >> are using a "bad bit" transition, an non-monotic step, for the dither >> interpolation. >> >> So it looks like I could have a lookup table of 24-bit numbers in the >> ballpark of 293*256 or whatever, randomized with a flat probability >> distribution (scrambled triangle) some modest number of H LSBs in p-p >> amplitude. Every DAC clock, add the next one to the 24-bit data before >> truncating to 16 bits for the DAC. That's sort of like a higher-order >> "noise shaped" delta-sigma, but there's no feedback loop. The bigger the >> spread of the random numbers, the more noise we make but the better we >> cope with DAC monoticity errors. > >You probably want to noise-shape the dithering, which means sigma-delta, >which means some arithmetic. But it means a much lower oversampling >ratio. > >The non-monotonicity comes from the DAC's differential nonlinearity, >which will be with you no matter what. So you're hardly going to be able >to get an accuracy of 120dB down from full scale, and you probably won't >be able to achieve a 120dB dynamic range by any but a very forgiving >specification of dynamic range. > >If all you're looking for is single-tone reproduction, and you don't mind >some considerable gain errors when you're down in that -120dB range, >well, maybe you can achieve it.
That is sort of the situation. The system resolution will be tested when there is a small signal, probably a single sine, because that's the obvious way to measure things. If I dither several LSBs, the gain is likely to be more accurate than a classic delta-sigma that just dithers one bit.
On Fri, 29 Nov 2013 18:37:01 -0800, John Larkin
<jjlarkin@highNOTlandTHIStechnologyPART.com> wrote:

> > >OK, I'm sort of thinking this through. > >Suppose I have a stream of parallel digital words that represent a >waveform. Assume it's audio or something similar. Further assume that >it has an arbitrary number of bits available at an arbitrarily high >rate; we can fake the rate by digital interpolation if the raw data >stream isn't fast enough. > >Assume that I want to use a 16 bit DAC but I need close to 120 dB (a >few parts per million) dynamic range. The 16 bit DAC quantizes the >signal to 15 PPM, and even worse, the DAC that we have in stock is >only guaranteed monotonic to 14 bits. > >We can clock this DAC really fast and lowpass filter the output. > >If the data is, say, 24 bits wide, we can call the first 16 bits H and >the low 8 bits L. > >If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM. > >We could take the L bits and turn them into a PWM waveform, and when >the PWM was high, add one LSB to the 16 bit DAC. The averaged value of >the DAC now has 24 bit resolution. But the PWM signal winds up as a >spurious signal in the DAC output, at 1/256 the clock rate, and we'd >have to filter that out. That could be inconvenient. > >A better way to do this is to add the LSB correction at the same duty >cycle but splatter the highs and lows in time. That is, basically, a >first-order delta-sigma algorithm. The wiggled LSB is no longer a low >frequency whine, but it becomes wideband noise. > >One problem is that we can't be sure that the LSB that we dither is >exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic >to 14 bits, so bad luck would have the dithered bit be 4x as big as >expected. Or negative. > >Assuming the DAC has the biggest nasties at major transitions, like >0x7FFF to 0x8000, we could add some DC offset to avoid that step when >we're making small signals. Add 64 or 293 or something maybe, to get >in a zone where it's probably pretty linear. > >One could accomplish the PWM by adding a sawtooth or triangle waveform >to L before quantizing to 16 bits. Or splatter the triangle samples >randomly, to get the delta-sigma noise shaping. > >If you added a bigger triangle than 1 LSB of H, the DAC output would >splatter over more than one bit. That reduces the probability that we >are using a "bad bit" transition, an non-monotic step, for the dither >interpolation. > >So it looks like I could have a lookup table of 24-bit numbers in the >ballpark of 293*256 or whatever, randomized with a flat probability >distribution (scrambled triangle) some modest number of H LSBs in p-p >amplitude. Every DAC clock, add the next one to the 24-bit data before >truncating to 16 bits for the DAC. That's sort of like a higher-order >"noise shaped" delta-sigma, but there's no feedback loop. The bigger >the spread of the random numbers, the more noise we make but the >better we cope with DAC monoticity errors. >
OK, it sounds like I need a black box that generates a stream of 24-bit dither codes at 50 MHz, the DAC rate. The codes should have a DC offset to push the DAC into one of its low-DNL zones. A triangular (maybe Gaussian?) probability distribution would probably be good, several (4? 16?) DAC LSBs p-p. The dither stream should have low noise density in the passband of the post-DAC lowpass filter. Gotta consider aliasing down-conversion too. One way to do this is to compute it on a PC, in PowerBasic or Matlab or something, and program an FPGA lookup table from the computed points. One could work in floats and invoke the RND function to make a stream of random numbers, then warp them through some function to change the probability density from rectangular to triangular. Then highpass (or bandpass?) filter, scale, convert to 24 bit integers, and dump into the FPGA tools. A 4K point table in the FPGA, walked by a counter, should do. My 24-bit signal points would then be summed with this noise stream, truncated to 16 bits, and fed to the DAC. Might work.
On Fri, 29 Nov 2013 23:18:35 -0800, John Larkin wrote:

> On Sat, 30 Nov 2013 00:07:04 -0600, Tim Wescott > <tim@seemywebsite.really> wrote: > >>On Fri, 29 Nov 2013 18:37:01 -0800, John Larkin wrote: >> >>> OK, I'm sort of thinking this through. >>> >>> Suppose I have a stream of parallel digital words that represent a >>> waveform. Assume it's audio or something similar. Further assume that >>> it has an arbitrary number of bits available at an arbitrarily high >>> rate; we can fake the rate by digital interpolation if the raw data >>> stream isn't fast enough. >>> >>> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a >>> few parts per million) dynamic range. The 16 bit DAC quantizes the >>> signal to 15 PPM, and even worse, the DAC that we have in stock is >>> only guaranteed monotonic to 14 bits. >>> >>> We can clock this DAC really fast and lowpass filter the output. >>> >>> If the data is, say, 24 bits wide, we can call the first 16 bits H and >>> the low 8 bits L. >>> >>> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM. >>> >>> We could take the L bits and turn them into a PWM waveform, and when >>> the PWM was high, add one LSB to the 16 bit DAC. The averaged value of >>> the DAC now has 24 bit resolution. But the PWM signal winds up as a >>> spurious signal in the DAC output, at 1/256 the clock rate, and we'd >>> have to filter that out. That could be inconvenient. >>> >>> A better way to do this is to add the LSB correction at the same duty >>> cycle but splatter the highs and lows in time. That is, basically, a >>> first-order delta-sigma algorithm. The wiggled LSB is no longer a low >>> frequency whine, but it becomes wideband noise. >>> >>> One problem is that we can't be sure that the LSB that we dither is >>> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic >>> to 14 bits, so bad luck would have the dithered bit be 4x as big as >>> expected. Or negative. >>> >>> Assuming the DAC has the biggest nasties at major transitions, like >>> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when >>> we're making small signals. Add 64 or 293 or something maybe, to get >>> in a zone where it's probably pretty linear. >>> >>> One could accomplish the PWM by adding a sawtooth or triangle waveform >>> to L before quantizing to 16 bits. Or splatter the triangle samples >>> randomly, to get the delta-sigma noise shaping. >>> >>> If you added a bigger triangle than 1 LSB of H, the DAC output would >>> splatter over more than one bit. That reduces the probability that we >>> are using a "bad bit" transition, an non-monotic step, for the dither >>> interpolation. >>> >>> So it looks like I could have a lookup table of 24-bit numbers in the >>> ballpark of 293*256 or whatever, randomized with a flat probability >>> distribution (scrambled triangle) some modest number of H LSBs in p-p >>> amplitude. Every DAC clock, add the next one to the 24-bit data before >>> truncating to 16 bits for the DAC. That's sort of like a higher-order >>> "noise shaped" delta-sigma, but there's no feedback loop. The bigger >>> the spread of the random numbers, the more noise we make but the >>> better we cope with DAC monoticity errors. >> >>You probably want to noise-shape the dithering, which means sigma-delta, >>which means some arithmetic. But it means a much lower oversampling >>ratio. >> >>The non-monotonicity comes from the DAC's differential nonlinearity, >>which will be with you no matter what. So you're hardly going to be >>able to get an accuracy of 120dB down from full scale, and you probably >>won't be able to achieve a 120dB dynamic range by any but a very >>forgiving specification of dynamic range. >> >>If all you're looking for is single-tone reproduction, and you don't >>mind some considerable gain errors when you're down in that -120dB >>range, well, maybe you can achieve it. > > That is sort of the situation. The system resolution will be tested when > there is a small signal, probably a single sine, because that's the > obvious way to measure things. If I dither several LSBs, the gain is > likely to be more accurate than a classic delta-sigma that just dithers > one bit.
You'll have a distinct speed vs. quality trade-off, exactly because using more bits means you need more noise (and hence more filtering, and hence higher speed). Random white noise fed into a high-pass filter may be your friend, here. Are you interested in a system that passes tests, or one that succeeds in your customer's hands? In most of the contexts that I'm used to, dynamic range means, essentially, "picking out a little signal that's buried in a big signal", not "being able to make a little signal or a big one". For the former definition, nonlinearities cause harmonics or other products of the big signal to interfere with the little signal, so in that context "dynamic range" is a measure of linearity. -- Tim Wescott Control system and signal processing consulting www.wescottdesign.com
On Sat, 30 Nov 2013 14:15:14 -0600, Tim Wescott
<tim@seemywebsite.please> wrote:

>On Fri, 29 Nov 2013 23:18:35 -0800, John Larkin wrote: > >> On Sat, 30 Nov 2013 00:07:04 -0600, Tim Wescott >> <tim@seemywebsite.really> wrote: >> >>>On Fri, 29 Nov 2013 18:37:01 -0800, John Larkin wrote: >>> >>>> OK, I'm sort of thinking this through. >>>> >>>> Suppose I have a stream of parallel digital words that represent a >>>> waveform. Assume it's audio or something similar. Further assume that >>>> it has an arbitrary number of bits available at an arbitrarily high >>>> rate; we can fake the rate by digital interpolation if the raw data >>>> stream isn't fast enough. >>>> >>>> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a >>>> few parts per million) dynamic range. The 16 bit DAC quantizes the >>>> signal to 15 PPM, and even worse, the DAC that we have in stock is >>>> only guaranteed monotonic to 14 bits. >>>> >>>> We can clock this DAC really fast and lowpass filter the output. >>>> >>>> If the data is, say, 24 bits wide, we can call the first 16 bits H and >>>> the low 8 bits L. >>>> >>>> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM. >>>> >>>> We could take the L bits and turn them into a PWM waveform, and when >>>> the PWM was high, add one LSB to the 16 bit DAC. The averaged value of >>>> the DAC now has 24 bit resolution. But the PWM signal winds up as a >>>> spurious signal in the DAC output, at 1/256 the clock rate, and we'd >>>> have to filter that out. That could be inconvenient. >>>> >>>> A better way to do this is to add the LSB correction at the same duty >>>> cycle but splatter the highs and lows in time. That is, basically, a >>>> first-order delta-sigma algorithm. The wiggled LSB is no longer a low >>>> frequency whine, but it becomes wideband noise. >>>> >>>> One problem is that we can't be sure that the LSB that we dither is >>>> exactly 1/65536 of the DAC full-scale amplitude. The dac is monotonic >>>> to 14 bits, so bad luck would have the dithered bit be 4x as big as >>>> expected. Or negative. >>>> >>>> Assuming the DAC has the biggest nasties at major transitions, like >>>> 0x7FFF to 0x8000, we could add some DC offset to avoid that step when >>>> we're making small signals. Add 64 or 293 or something maybe, to get >>>> in a zone where it's probably pretty linear. >>>> >>>> One could accomplish the PWM by adding a sawtooth or triangle waveform >>>> to L before quantizing to 16 bits. Or splatter the triangle samples >>>> randomly, to get the delta-sigma noise shaping. >>>> >>>> If you added a bigger triangle than 1 LSB of H, the DAC output would >>>> splatter over more than one bit. That reduces the probability that we >>>> are using a "bad bit" transition, an non-monotic step, for the dither >>>> interpolation. >>>> >>>> So it looks like I could have a lookup table of 24-bit numbers in the >>>> ballpark of 293*256 or whatever, randomized with a flat probability >>>> distribution (scrambled triangle) some modest number of H LSBs in p-p >>>> amplitude. Every DAC clock, add the next one to the 24-bit data before >>>> truncating to 16 bits for the DAC. That's sort of like a higher-order >>>> "noise shaped" delta-sigma, but there's no feedback loop. The bigger >>>> the spread of the random numbers, the more noise we make but the >>>> better we cope with DAC monoticity errors. >>> >>>You probably want to noise-shape the dithering, which means sigma-delta, >>>which means some arithmetic. But it means a much lower oversampling >>>ratio. >>> >>>The non-monotonicity comes from the DAC's differential nonlinearity, >>>which will be with you no matter what. So you're hardly going to be >>>able to get an accuracy of 120dB down from full scale, and you probably >>>won't be able to achieve a 120dB dynamic range by any but a very >>>forgiving specification of dynamic range. >>> >>>If all you're looking for is single-tone reproduction, and you don't >>>mind some considerable gain errors when you're down in that -120dB >>>range, well, maybe you can achieve it. >> >> That is sort of the situation. The system resolution will be tested when >> there is a small signal, probably a single sine, because that's the >> obvious way to measure things. If I dither several LSBs, the gain is >> likely to be more accurate than a classic delta-sigma that just dithers >> one bit. > >You'll have a distinct speed vs. quality trade-off, exactly because using >more bits means you need more noise (and hence more filtering, and hence >higher speed). Random white noise fed into a high-pass filter may be >your friend, here.
Right, the dither waveform shouldn't have low-frequency components that would get through the post-DAC analog lowpass filter. It maybe shouldn't have any energy within a band around the sample rate, because that could be aliased down into the passband. So the noise points should be generated as if they were passed through a bandpass filter from, say, 5 to 45 MHz. There must be a way to do that. I have an intern who claims to be good with Matlab. Can Matlab do filtering of sample sets? Hmmm, what if the dither waveform were a single sine wave around, say, 7 MHz or something? Or a bunch of sine waves all well within the stopband of the post-DAC lowpass filter? That's easy to compute. With a bunch of them, the mess approaches strictly bandlimited Gaussian noise.
> >Are you interested in a system that passes tests, or one that succeeds in >your customer's hands?
Well, both. There will be big booms and small booms, but I don't need PPM precision on the details of a big boom. But I need to make small booms that look pretty good. The previous vendor tried for a couple of years to get this to work with a mostly-analog design. We're going ADC-FPGA-DAC. The customer will be overjoyed to get anything that works. It's sort of a rescue/charity job, so the customer won't be hard-headed about specs. In most of the contexts that I'm used to, dynamic
>range means, essentially, "picking out a little signal that's buried in a >big signal", not "being able to make a little signal or a big one".
I think the latter will do. For
>the former definition, nonlinearities cause harmonics or other products >of the big signal to interfere with the little signal, so in that context >"dynamic range" is a measure of linearity.
The biggest nonlinearity of that sort, keeping the small stuff accurate on top of big stuff, will mostly depend on the 14-bit DNL of the DAC. It's really very good, fractional LSB, on most code transitions, but has about 32 big spikes across the code range. So I need to avoid them as much as possible. The best DC offset is then 1/64 of full scale.
On Sat, 30 Nov 2013 13:48:59 -0800, John Larkin wrote:

> On Sat, 30 Nov 2013 14:15:14 -0600, Tim Wescott > <tim@seemywebsite.please> wrote: > >>On Fri, 29 Nov 2013 23:18:35 -0800, John Larkin wrote: >> >>> On Sat, 30 Nov 2013 00:07:04 -0600, Tim Wescott >>> <tim@seemywebsite.really> wrote: >>> >>>>On Fri, 29 Nov 2013 18:37:01 -0800, John Larkin wrote: >>>> >>>>> OK, I'm sort of thinking this through. >>>>> >>>>> Suppose I have a stream of parallel digital words that represent a >>>>> waveform. Assume it's audio or something similar. Further assume >>>>> that it has an arbitrary number of bits available at an arbitrarily >>>>> high rate; we can fake the rate by digital interpolation if the raw >>>>> data stream isn't fast enough. >>>>> >>>>> Assume that I want to use a 16 bit DAC but I need close to 120 dB (a >>>>> few parts per million) dynamic range. The 16 bit DAC quantizes the >>>>> signal to 15 PPM, and even worse, the DAC that we have in stock is >>>>> only guaranteed monotonic to 14 bits. >>>>> >>>>> We can clock this DAC really fast and lowpass filter the output. >>>>> >>>>> If the data is, say, 24 bits wide, we can call the first 16 bits H >>>>> and the low 8 bits L. >>>>> >>>>> If we just stuff H into the DAC, we're quantized to 16 bits, 15 PPM. >>>>> >>>>> We could take the L bits and turn them into a PWM waveform, and when >>>>> the PWM was high, add one LSB to the 16 bit DAC. The averaged value >>>>> of the DAC now has 24 bit resolution. But the PWM signal winds up as >>>>> a spurious signal in the DAC output, at 1/256 the clock rate, and >>>>> we'd have to filter that out. That could be inconvenient. >>>>> >>>>> A better way to do this is to add the LSB correction at the same >>>>> duty cycle but splatter the highs and lows in time. That is, >>>>> basically, a first-order delta-sigma algorithm. The wiggled LSB is >>>>> no longer a low frequency whine, but it becomes wideband noise. >>>>> >>>>> One problem is that we can't be sure that the LSB that we dither is >>>>> exactly 1/65536 of the DAC full-scale amplitude. The dac is >>>>> monotonic to 14 bits, so bad luck would have the dithered bit be 4x >>>>> as big as expected. Or negative. >>>>> >>>>> Assuming the DAC has the biggest nasties at major transitions, like >>>>> 0x7FFF to 0x8000, we could add some DC offset to avoid that step >>>>> when we're making small signals. Add 64 or 293 or something maybe, >>>>> to get in a zone where it's probably pretty linear. >>>>> >>>>> One could accomplish the PWM by adding a sawtooth or triangle >>>>> waveform to L before quantizing to 16 bits. Or splatter the triangle >>>>> samples randomly, to get the delta-sigma noise shaping. >>>>> >>>>> If you added a bigger triangle than 1 LSB of H, the DAC output would >>>>> splatter over more than one bit. That reduces the probability that >>>>> we are using a "bad bit" transition, an non-monotic step, for the >>>>> dither interpolation. >>>>> >>>>> So it looks like I could have a lookup table of 24-bit numbers in >>>>> the ballpark of 293*256 or whatever, randomized with a flat >>>>> probability distribution (scrambled triangle) some modest number of >>>>> H LSBs in p-p amplitude. Every DAC clock, add the next one to the >>>>> 24-bit data before truncating to 16 bits for the DAC. That's sort of >>>>> like a higher-order "noise shaped" delta-sigma, but there's no >>>>> feedback loop. The bigger the spread of the random numbers, the more >>>>> noise we make but the better we cope with DAC monoticity errors. >>>> >>>>You probably want to noise-shape the dithering, which means >>>>sigma-delta, >>>>which means some arithmetic. But it means a much lower oversampling >>>>ratio. >>>> >>>>The non-monotonicity comes from the DAC's differential nonlinearity, >>>>which will be with you no matter what. So you're hardly going to be >>>>able to get an accuracy of 120dB down from full scale, and you >>>>probably won't be able to achieve a 120dB dynamic range by any but a >>>>very forgiving specification of dynamic range. >>>> >>>>If all you're looking for is single-tone reproduction, and you don't >>>>mind some considerable gain errors when you're down in that -120dB >>>>range, well, maybe you can achieve it. >>> >>> That is sort of the situation. The system resolution will be tested >>> when there is a small signal, probably a single sine, because that's >>> the obvious way to measure things. If I dither several LSBs, the gain >>> is likely to be more accurate than a classic delta-sigma that just >>> dithers one bit. >> >>You'll have a distinct speed vs. quality trade-off, exactly because >>using more bits means you need more noise (and hence more filtering, and >>hence higher speed). Random white noise fed into a high-pass filter may >>be your friend, here. > > Right, the dither waveform shouldn't have low-frequency components that > would get through the post-DAC analog lowpass filter. > > It maybe shouldn't have any energy within a band around the sample rate, > because that could be aliased down into the passband. > > So the noise points should be generated as if they were passed through a > bandpass filter from, say, 5 to 45 MHz. There must be a way to do that. > I have an intern who claims to be good with Matlab. Can Matlab do > filtering of sample sets? > > Hmmm, what if the dither waveform were a single sine wave around, say, > 7 MHz or something? Or a bunch of sine waves all well within the > stopband of the post-DAC lowpass filter? That's easy to compute. With a > bunch of them, the mess approaches strictly bandlimited Gaussian noise.
<< specsmanship comments snipped >> Yes, Matlab will do the filtering. If you do the filtering in the sampled-time domain at your sampling rate you'll automatically get the bandpass effect that you want. Or you can generate your collection of sine waves -- but doing so is kind of like making your own pieces of wood out of cotton thread and resin because you don't like saws. A 1st-order highpass filter is Really Freaking Easy to write in C; given the "really long table" vs. "a few lines of code" tradeoff, I'd go for the few lines of code. But you could generate a table of values and run with that. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com
On 11/29/2013 9:45 PM, John Larkin wrote:
> On Fri, 29 Nov 2013 21:19:05 -0800, miso <miso@sushi.com> wrote: > >> >> I mean seriously, this was so much already invented that I gave up after >> the first paragraph. > > Then you didn't read the interesting stuff. > >
tl;dr
On Sat, 30 Nov 2013 15:16:38 -0800, miso <miso@sushi.com> wrote:

>On 11/29/2013 9:45 PM, John Larkin wrote: >> On Fri, 29 Nov 2013 21:19:05 -0800, miso <miso@sushi.com> wrote: >> >>> >>> I mean seriously, this was so much already invented that I gave up after >>> the first paragraph. >> >> Then you didn't read the interesting stuff. >> >> > >tl;dr
sas
If anyone's interested, there's an LT Spice thing below.

I'm trying to get microvolt waveforms out of a 16 bit DAC that has 1
volt p-p range, which is 15 microvolt steps.

This uses two summed sines as the dither. Two sines has a better
probability distribution than one, and more don't seem to help. I
tried writing an LT SPice thing to graph the probability distribution
of summed sines, but it was too slow to be useful. Maybe my intern can
Matlab it.

The dither sines get intermodulated by the quantizer, generates sums
and differences, and the IM products have to be kept away from the 1
MHz passband.

Finding the optimum sinewave dither amplitudes and frequencies would
take either a lot of theory or a lot of fiddling. The values I'm using
seem to work pretty well. I can make a decent 6 uV p-p sine wave. 

I'm thinking that, if the dither were bandlimited gaussian noise,
there would be an infinite number of IM products folding the noise
back into the 1 MHz passband. Maybe the discrete sines are better.

I didn't include the dac clock yet. I guess a s/h clocked at 50 MHz
would be a pretty good model.

Sorry if I'm boring you, miso.


Version 4
SHEET 1 1316 680
WIRE 224 -400 160 -400
WIRE 256 -400 224 -400
WIRE 464 -400 336 -400
WIRE 160 -368 160 -400
WIRE 160 -272 160 -288
WIRE 224 -160 160 -160
WIRE 256 -160 224 -160
WIRE 464 -160 464 -400
WIRE 464 -160 336 -160
WIRE 544 -160 464 -160
WIRE 160 -128 160 -160
WIRE 688 -96 656 -96
WIRE 768 -96 688 -96
WIRE 896 -96 848 -96
WIRE 944 -96 896 -96
WIRE 1088 -96 1024 -96
WIRE 1152 -96 1088 -96
WIRE 1200 -96 1152 -96
WIRE 160 -32 160 -48
WIRE 656 -32 656 -96
WIRE 896 -32 896 -96
WIRE 1088 -32 1088 -96
WIRE 224 48 160 48
WIRE 256 48 224 48
WIRE 464 48 464 -160
WIRE 464 48 336 48
WIRE 160 80 160 48
WIRE 656 96 656 48
WIRE 896 96 896 32
WIRE 1088 96 1088 32
WIRE 160 176 160 160
FLAG 544 -160 Z
FLAG 160 176 0
FLAG 160 -32 0
FLAG 160 -272 0
FLAG 224 48 D1
FLAG 224 -160 D2
FLAG 224 -400 SIG
FLAG 656 96 0
FLAG 896 96 0
FLAG 688 -96 DACOUT
FLAG 1088 96 0
FLAG 1152 -96 LPF
SYMBOL voltage 160 64 R0
WINDOW 0 -165 44 Left 2
WINDOW 3 -275 96 Left 2
WINDOW 123 0 0 Left 2
WINDOW 39 0 0 Left 2
SYMATTR InstName V1
SYMATTR Value SINE(0 40 13.3e6)
SYMBOL voltage 160 -144 R0
WINDOW 0 -165 51 Left 2
WINDOW 3 -275 96 Left 2
WINDOW 123 0 0 Left 2
WINDOW 39 0 0 Left 2
SYMATTR InstName V2
SYMATTR Value SINE(0 40 21.7e6)
SYMBOL voltage 160 -384 R0
WINDOW 0 -177 26 Left 2
WINDOW 3 -257 73 Left 2
WINDOW 123 0 0 Left 2
WINDOW 39 0 0 Left 2
SYMATTR InstName V3
SYMATTR Value SINE(0 3u 100K)
SYMBOL res 352 32 R90
WINDOW 0 76 77 VBottom 2
WINDOW 3 48 26 VTop 2
SYMATTR InstName R2
SYMATTR Value 1e6
SYMBOL res 352 -176 R90
WINDOW 0 70 78 VBottom 2
WINDOW 3 42 25 VTop 2
SYMATTR InstName R3
SYMATTR Value 1e6
SYMBOL res 352 -416 R90
WINDOW 0 71 71 VBottom 2
WINDOW 3 43 33 VTop 2
SYMATTR InstName R5
SYMATTR Value 1
SYMBOL bv 656 -48 R0
WINDOW 3 -98 192 Left 2
WINDOW 0 13 111 Left 2
SYMATTR Value V=int(65536*V(Z)) / 65536
SYMATTR InstName B1
SYMBOL res 864 -112 R90
WINDOW 0 68 55 VBottom 2
WINDOW 3 79 55 VTop 2
SYMATTR InstName R6
SYMATTR Value 1
SYMBOL ind 928 -80 R270
WINDOW 0 -31 55 VTop 2
WINDOW 3 -36 59 VBottom 2
SYMATTR InstName L1
SYMATTR Value 220n
SYMBOL cap 880 -32 R0
WINDOW 0 32 64 Left 2
WINDOW 3 29 97 Left 2
SYMATTR InstName C1
SYMATTR Value 83n
SYMBOL cap 1072 -32 R0
WINDOW 0 39 63 Left 2
WINDOW 3 31 96 Left 2
SYMATTR InstName C2
SYMATTR Value 250n
TEXT 256 208 Left 2 !.tran 0 20u 0 500p
TEXT 648 -224 Left 2 ;QUANTIZER
TEXT 856 -224 Left 2 ;1 MHZ BUTTERWORTH
TEXT 640 -184 Left 2 ;15 uV STEPS
TEXT 256 -296 Left 2 ;SIGNAL
TEXT 256 -48 Left 2 ;DITHER
TEXT 880 -184 Left 2 ;LOWPASS FILTER
TEXT 680 -408 Left 2 ;SINEWAVE DAC DITHERING
TEXT 712 -352 Left 2 ;J LARKIN   DEC 1, 2013