This whole topic of filtering I can not overview, so this is what I see:
A clean signal is just a single value at any time. Something like a constant voltage. A fourier transform of such a signal only has one component not zero: the frequency zero, or DC-level.
The moment a single value is different, the spectrum will show an infinite number of non zero values, frequency 1 (one) is showing the largest amplitude, amplitudes decreasing with increasing frequency.
Any filter that limits high frequencies leaves over lower frequencies, so a spike, originally seen as a single value, now is cutted in amplitude, but spread in time, nearly undetectable. But when we integrate the signal over time, the bump will integrate to nearly the same value as the former spike did. So we gain nothing.
Now, how does a optimal filter work? Such a filter knows about the signals characteristic ( for example: spikes are not allowed) and just REMOVES any component that is not allowed. For example: if there is a spike, that is, amplitude changes faster than allowed, the slope is just limited.
Let the signal be constant, the change allowed is +-1. If now a change of 10 occures, this change is limited to 1. When the spike ends, the change is -10, limited: -1. So the error introduced is 1 times duration of the spike instead of 10 times duration of the spike. No signal is spreaded.
What we do so far is: we apply proven knowledge to an application, that is different to the original problem, leading to that knowledge. It's like draining a swamp in the dessert by watering, growing a swamp and then draining it.
Software defined radio, that is: sending bits at highest density using an electromagnetic wave can rely on the fact, that electromagnetic waves are law-abiding, means: the laws of physics apply. Then you can go to the limits, e.g. rely on Shannons Theorem. If not, and this is the case in the Propellers ADC,we should not try to squeeze out the last bit by doing experiments on a wavering platform.
Theory is one side of the medal, not the medal itself.
Chip, I'll look into it now. A long Tukey-type window is definitely the best way to get more than an eight-bit output every clock as I don't think we have the logic for an extra filter.
The main issue with the Tukey/Hann/Blackman windows is their max values are only about half of the cascaded moving averages (CMA for short).
As an alternative, with fairly minor tap changes and a little bit of skipping, the long CMA can fit into 69 of the 70 available taps including zeroes, as follows:
Chip, I'll look into it now. A long Tukey-type window is definitely the best way to get more than an eight-bit output every clock as I don't think we have the logic for an extra filter.
The main issue with the Tukey/Hann/Blackman windows is their max values are only about half of the cascaded moving averages (CMA for short).
As an alternative, with fairly minor tap changes and a little bit of skipping, the long CMA can fit into 69 of the 70 available taps including zeroes, as follows:
Here is the modified code with new window parameter c:
'window parameters
'a = 4: b = 0: c = 0: m = 32 'cma14 t2 and t3 cancel out
'a = 4: b = 8: c = 0: m = 16 'cma22
'a = 8: b = 0: c = 0: m = 4 'cma30 t2 and t3 cancel out
'a = 8: b = 16: c = 0: m = 2 'cma46
'a = 8: b = 48: c = 0: m = 1 'cma78
a = 8: b = 35: c = 1: m = 1 'cma67 *NEW*
gx = 10 : cy = 270 : by = cy + 100 : ay = by + 100 : dy = ay + 50
t0 = 0
t1 = t0 + a + c
t2 = t1 + a
t21 = t1 + a - c ' same as t2 when c = 0
t3 = t2 + b
t31 = t2 + b + c ' same as t3 when c = 0
t4 = t3 + a
t5 = t4 + a + c
topbit = t5
'for x = 1 to 35: print : next x
print "taps"
print t0,t1,t21,t2,t3,t31,t4,t5
print
dim t(topbit)
for x = 0 to topbit: t(x) = 0: next x 'clear bits
inta = 0
intb = 0
intc = 0
print "iter","ADC","delt","inta","intb","intc","samp","clam"
for iter = 0 to topbit*2 + 1
for x = topbit to 1 step -1: t(x) = t(x-1): next x 'shift bits
t(0) = (iter <= topbit) 'new ADC bit
't(0) = 1 - t(1)
't(0) = int(rnd + 0.5)
delt = t(t0) - t(t1)*2 + t(t2)*2 - t(t21) - t(t3)*2 + t(t31) + t(t4)*2 - t(t5)
inta = inta + delt
intb = intb + inta
intc = intc + intb * m
clam = int(intc/4096)
samp = int(intc/16) - clam
print iter,t(0),delt,inta,intb,intc,samp,clam
x = gx + iter*4
line x, cy, x, cy - intc/16 'plot intc
line x, by, x, by - intb 'plot intb
line x, ay, x, ay - inta*2 'plot inta
line x, dy, x, dy - delt*8 'plot delta
next iter
Here is the modified code with new window parameter c:
'window parameters
'a = 4: b = 0: c = 0: m = 32 'cma14 t2 and t3 cancel out
'a = 4: b = 8: c = 0: m = 16 'cma22
'a = 8: b = 0: c = 0: m = 4 'cma30 t2 and t3 cancel out
'a = 8: b = 16: c = 0: m = 2 'cma46
'a = 8: b = 48: c = 0: m = 1 'cma78
a = 8: b = 35: c = 1: m = 1 'cma67 *NEW*
gx = 10 : cy = 270 : by = cy + 100 : ay = by + 100 : dy = ay + 50
t0 = 0
t1 = t0 + a + c
t2 = t1 + a
t21 = t1 + a - c ' same as t2 when c = 0
t3 = t2 + b
t31 = t2 + b + c ' same as t3 when c = 0
t4 = t3 + a
t5 = t4 + a + c
topbit = t5
'for x = 1 to 35: print : next x
print "taps"
print t0,t1,t21,t2,t3,t31,t4,t5
print
dim t(topbit)
for x = 0 to topbit: t(x) = 0: next x 'clear bits
inta = 0
intb = 0
intc = 0
print "iter","ADC","delt","inta","intb","intc","samp","clam"
for iter = 0 to topbit*2 + 1
for x = topbit to 1 step -1: t(x) = t(x-1): next x 'shift bits
t(0) = (iter <= topbit) 'new ADC bit
't(0) = 1 - t(1)
't(0) = int(rnd + 0.5)
delt = t(t0) - t(t1)*2 + t(t2)*2 - t(t21) - t(t3)*2 + t(t31) + t(t4)*2 - t(t5)
inta = inta + delt
intb = intb + inta
intc = intc + intb * m
clam = int(intc/4096)
samp = int(intc/16) - clam
print iter,t(0),delt,inta,intb,intc,samp,clam
x = gx + iter*4
line x, cy, x, cy - intc/16 'plot intc
line x, by, x, by - intb 'plot intb
line x, ay, x, ay - inta*2 'plot inta
line x, dy, x, dy - delt*8 'plot delta
next iter
Fantastic, TonyB_!
Nice how you've got the filters sized at 14, +8, +8, +16, +32. Is the 67-tap's purpose to feed a filter for 12-bit samples?
Thinking more, we just need a sum that has 12 contiguous 1's in its top bits.
Is that essential, given that’s well outside the rails on the ADC ?
I guess $FFF is useful for easy clipping sense on the higher gain ranges, but 2040 could also be tested for ?
It's not essential, you're right. It just wouldn't need much explaining when someone used it.
Nice how you've got the filters sized at 14, +8, +8, +16, +32. Is the 67-tap's purpose to feed a filter for 12-bit samples?
CMA67's intended purpose is to give us full 12-bit or 8-bit samples and replace CMA78 that is too big to fit, then the four CMAx could be implemented instead of the Tukey/Hann/Blackman windows, depending on the logic size.
The BASIC program was written to generate all the different windows with common code and there is no need for eight taps apart from CMA67. As this is the largest window it makes some sort of sense that there is no skipping, which I think can only work when what is being skipped has the same delta as before and after. This means that skipping might have a part to play with the smaller windows so that more taps are common to all windows, however I haven't tried this yet.
We would have a spare config bit with CMAx. CMA46 has 11-bit output, CMA30 10-bit and maybe these could be extended to 12 bits to match CMA67? The numbers don't add up so well for the smallest window CMA22, which sums to 256 (and is Tukey-like).
TonyB_, okay, I see that CMA67 sums to 4096, which could be clamped to $FFF to feed a filter for 12-bit samples. Super!
Do you have any thoughts on how we ought to filter that 12-bit output to get steady 12-bit samples?
Will the output still be quite noisy after passing through 67 taps? I've thought about partially overlapping the windows in software so that every bit has exactly equal weight, with a sample taken every 60 50 or so clocks.
Is there any scope (pardon the pun) for anything else in hardware because the registers are fully used and the logic will be configured differently for different modes? I don't see how we could feed the output into some other existing filter in the same smart pin.
TonyB_, okay, I see that CMA67 sums to 4096, which could be clamped to $FFF to feed a filter for 12-bit samples. Super!
Do you have any thoughts on how we ought to filter that 12-bit output to get steady 12-bit samples?
I'm a bit concerned out all of this business of clipping 256 to 255 or 4096 to 4095 just to save a small amount of logic; rather than propagate the carry, or overflow bit to the next stage - since I strongly suspect that that could be a major source of 1/f noise; which should be plainly clear if I give an example. Suppose that you are in effect summing bits using whatever chosen methods are available; whether it is TukeyXYZ or cmaXYZ or whatever. So you get a maximum slew rate audio input for a few 10's of microseconds; and then input is actually at 655xx something, i.e., close to the rail; but not necessarily at the rail … still you get a bunch of consecutive 256's which get clipped to 255; maybe even 100 of them, so now you are 100 bits short on your long count; when you add all of the ones up; then the input swings the other way; and the long count slowly drops; but not just zero; but past zero farther than it should; because the long count is short that 100 or so bits; and it gets clipped again a few more times at the 4095 vs. 4096 boundary in another cascaded stage and whoops! .. there we go again, with another asymmetric source of accumulated non linear distortion; which would manifest over time as a 1/f in the audio.
Then again; if the theory holds that the equilibrium state of the modulator is when it cycles between 0,1,0,1,0,1 .. when there is "no input" or rather when the input is (1/2)(Vcc+GND), it would appear that eventually the apparent drift introduced would eventually be "forgotten" by the filters, as they get past the longest window. Still the noise added will be "an occasional" disparity resulting in ENOB never really making it reliably past 8 or 9 biits.
I think the Sinc3 filter is still in there ?
ie these other modes, are are additional scope-mode filters ?
The Sinc3 gives a predictable filter for external ADCs, which can deliver better than 16 bit performances.
My overall concern here is the time that is being spent on trying to solve what might be a endless chase. I did a fair amount of study at NSC with high speed and high resolution ADC's for Foveon cameras and it seems that everything eventually distills into sacrificing one thing for the other and you can't get something from nothing. You either have good resolution at low speed or diminished resolution at higher speed. The balancing act of the two is the endless chase I am referring to. I'm not saying to give up this effort. I just think everyone should be mindful of the circumstance and realize when you are chasing your own tail.
I think the Sinc3 filter is still in there ?
ie these other modes, are are additional scope-mode filters ?
The Sinc3 gives a predictable filter for external ADCs, which can deliver better than 16 bit performances.
Here is how I see things. Both Sinc3 and scope modes are intended. The latter could provide an output every clock (which Sinc3 cannot do), either 8-bit triggered or 12-bit non-triggered. The former would be combined with byte outputs from three other pins to give four-channel, 32-bit values. The latter would be a higher-res output and as close to 16-bit as we could get every clock, probably.
TonyB_, okay, I see that CMA67 sums to 4096, which could be clamped to $FFF to feed a filter for 12-bit samples. Super!
Do you have any thoughts on how we ought to filter that 12-bit output to get steady 12-bit samples?
I'm a bit concerned out all of this business of clipping 256 to 255 or 4096 to 4095 just to save a small amount of logic; rather than propagate the carry, or overflow bit to the next stage - since I strongly suspect that that could be a major source of 1/f noise; which should be plainly clear if I give an example. Suppose that you are in effect summing bits using whatever chosen methods are available; whether it is TukeyXYZ or cmaXYZ or whatever. So you get a maximum slew rate audio input for a few 10's of microseconds; and then input is actually at 655xx something, i.e., close to the rail; but not necessarily at the rail … still you get a bunch of consecutive 256's which get clipped to 255; maybe even 100 of them, so now you are 100 bits short on your long count; when you add all of the ones up; then the input swings the other way; and the long count slowly drops; but not just zero; but past zero farther than it should; because the long count is short that 100 or so bits; and it gets clipped again a few more times at the 4095 vs. 4096 boundary in another cascaded stage and whoops! .. there we go again, with another asymmetric source of accumulated non linear distortion; which would manifest over time as a 1/f in the audio.
Then again; if the theory holds that the equilibrium state of the modulator is when it cycles between 0,1,0,1,0,1 .. when there is "no input" or rather when the input is (1/2)(Vcc+GND), it would appear that eventually the apparent drift introduced would eventually be "forgotten" by the filters, as they get past the longest window. Still the noise added will be "an occasional" disparity resulting in ENOB never really making it reliably past 8 or 9 biits.
This is an interesting point, thanks for mentioning it. Clipping actually adds a little bit to the logic and here is comparison of the window filters again:
Chip, I'll look into it now. A long Tukey-type window is definitely the best way to get more than an eight-bit output every clock as I don't think we have the logic for an extra filter.
I've just looked at this properly for the first time. What were the 17 trigger bits become filter[16:0] and the subtract and add are cascaded?
I'm wondering what this would do. I examined a short binomial/triangular filter [1,2,1] in software using three successive windowed outputs but the bits entering or leaving have very little weight and overall the three outputs varied so little it appeared to be useless, for the longer windows anyway.
Chip, I'll look into it now. A long Tukey-type window is definitely the best way to get more than an eight-bit output every clock as I don't think we have the logic for an extra filter.
I've just looked at this properly for the first time. What were the 17 trigger bits become filter[16:0] and the subtract and add are cascaded?
I'm thinking that maybe this belongs in the Sinc3, where there are already big adders. The trouble is, I cannot get 16-bit stable readings until I go to a 4th order filter. 3rd-order doesn't seem to do it.
My overall concern here is the time that is being spent on trying to solve what might be a endless chase. I did a fair amount of study at NSC with high speed and high resolution ADC's for Foveon cameras and it seems that everything eventually distills into sacrificing one thing for the other and you can't get something from nothing. You either have good resolution at low speed or diminished resolution at higher speed. The balancing act of the two is the endless chase I am referring to. I'm not saying to give up this effort. I just think everyone should be mindful of the circumstance and realize when you are chasing your own tail.
Chip was super happy with the tapered filter in post 1 of this thread. I'm honestly not convinced that what gets implemented in the end will be a ton better than that, which was already a huge improvement over the unfiltered ADC.
Is there a spreadsheet somewhere with all of these filters in it, the effective # of ADC bits, the approximate amount of logic added, and the update rate of the filtered output? So a decision could just be made that no further progress is happening? A simple 3D plot could show where new suggestions fall with respect to prior suggestions.
Chip, I'll look into it now. A long Tukey-type window is definitely the best way to get more than an eight-bit output every clock as I don't think we have the logic for an extra filter.
The main issue with the Tukey/Hann/Blackman windows is their max values are only about half of the cascaded moving averages (CMA for short).
As an alternative, with fairly minor tap changes and a little bit of skipping, the long CMA can fit into 69 of the 70 available taps including zeroes, as follows:
What would have been 81 is skipped twice. I've shown 80 as part of the ramps for clarity (I hope). Some skipping is needed for the other windows, too.
It's great that you figured out how to modify the plateau. I was wondering about the construction of this, I guess you lowered the plateau from 81 to 80. Not necessarily a bad thing, but that was likely the cause of difficulty on the basic program. The ramp up matches a CMA9*9*51. The plateau value matches a CMA8*10*51. In the third derivative, sometimes the impulses combine together to increase the weight of a certain tap. This usually happens when using 2 filters of the length.
It's great that the triple integration method gives more flexibility than just CMA filters. We could design any filter we want as long as the 2nd, 3rd, or 4th derivative is sparse. You choose the number of integrations that minimizes the number of taps needed. The earlier Tukey windows were more efficeient at 2 integrations. The CMA filters are convenient as they guarantee smooth up and down curves and a very sparse derivative.
After a lot of experimenting and testing, I'm giving up on the live 16-bit and 12-bit sampling. If >8 bit sampling is wanted, the Sinc3 filter does a vastly superior job of filtering, with the caveat that you only get a sample every Nth clock, instead of on every clock.
I've found that to get the best A/D conversion, the pins involving the same Vxxxx supply pin should all be A/D inputs, in order to minimize noise. In a lot of experiments, I was using one pin for ADC and its neighbor pin for DAC. The DAC can variably draw several mA, which causes an IR drop on the bond wires and chip routing metal, which causes distortion in an ADC sharing those power signals. The interplay between ADC and DAC activity on same-power-supply pins had me thinking a few times that we had some strange problems, when we didn't.
In order to get around this shared-supply problem during development on the FPGA, with the two-I/O-pin test ASIC, I've resorted to recording ADC readings and then playing them back on a DAC, to avoid cross-talk. On the silicon, you need only use another 4-pin group with separate Vxxxx and GIO (GND) bond wires.
Here is what we can expect on the silicon. These are the bottom 8 bits of a 14-bit conversion of the apex of a sine wave. These samples were acquired in 256 clocks using the Sinc3 filter, and then decimated. Imagine that there are 64 more scope screens stacked vertically, in order to show the full scale. I think this is pretty good resolution:
So, TonyB_, we don't need any special-summing combos, anymore. Four nicely-spaced filters will do. I'll implement those with the trigger mechanism and call it done. Not sure if we should use the CMA or Tukey types.
The interplay between ADC and DAC activity on same-power-supply pins had me thinking a few times that we had some strange problems, when we didn't.
(So as a casual observer) is this what resolved the low frequency noise problem? I wasn't exactly sure what happened with that.
1/f noise is still an issue. The longer your measurement, the more of it you get. The Sinc3 filter is nice because it shortens measurements by getting more resolution in fewer counts. That not only increases efficiency, but reduces 1/f noise.
Thanks for chasing these ADC improvements. Even with things as-are the ADC is mighty useful
What are your thoughts as to integrating capacitor reduction, still thinking 7/8 reduction? Or is that not required, now
Reducing the integrator cap will help the ADC not muddle up high-frequency inputs. There should be no detrimental effect, other than you'll need to run the ADC at 8MHz+, instead of 1MHz+.
After a lot of experimenting and testing, I'm giving up on the live 16-bit and 12-bit sampling. If >8 bit sampling is wanted, the Sinc3 filter does a vastly superior job of filtering, with the caveat that you only get a sample every Nth clock, instead of on every clock.
I've found that to get the best A/D conversion, the pins involving the same Vxxxx supply pin should all be A/D inputs, in order to minimize noise. In a lot of experiments, I was using one pin for ADC and its neighbor pin for DAC. The DAC can variably draw several mA, which causes an IR drop on the bond wires and chip routing metal, which causes distortion in an ADC sharing those power signals. The interplay between ADC and DAC activity on same-power-supply pins had me thinking a few times that we had some strange problems, when we didn't.
In order to get around this shared-supply problem during development on the FPGA, with the two-I/O-pin test ASIC, I've resorted to recording ADC readings and then playing them back on a DAC, to avoid cross-talk. On the silicon, you need only use another 4-pin group with separate Vxxxx and GIO (GND) bond wires.
Here is what we can expect on the silicon. These are the bottom 8 bits of a 14-bit conversion of the apex of a sine wave. These samples were acquired in 256 clocks using the Sinc3 filter, and then decimated. Imagine that there are 64 more scope screens stacked vertically, in order to show the full scale. I think this is pretty good resolution:
Wow, that looks good!
For the high resolution, what about an integrate and dump scheme? There could be 2 integrators so that one can be read while the other is accumulating. Or just a buffer that captures the value before dumping. Of course you won't have a value every clock. But you could fake it by adding the incoming scope filter value to the integrator value.
But really, Sinc3 is the right way to do it. It's just expensive to get a sample every clock. If we could tolerate having a FIFO hundreds of bits long, the integrating filter should be able to do it.
After a lot of experimenting and testing, I'm giving up on the live 16-bit and 12-bit sampling. If >8 bit sampling is wanted, the Sinc3 filter does a vastly superior job of filtering, with the caveat that you only get a sample every Nth clock, instead of on every clock.
I've found that to get the best A/D conversion, the pins involving the same Vxxxx supply pin should all be A/D inputs, in order to minimize noise. In a lot of experiments, I was using one pin for ADC and its neighbor pin for DAC. The DAC can variably draw several mA, which causes an IR drop on the bond wires and chip routing metal, which causes distortion in an ADC sharing those power signals. The interplay between ADC and DAC activity on same-power-supply pins had me thinking a few times that we had some strange problems, when we didn't.
In order to get around this shared-supply problem during development on the FPGA, with the two-I/O-pin test ASIC, I've resorted to recording ADC readings and then playing them back on a DAC, to avoid cross-talk. On the silicon, you need only use another 4-pin group with separate Vxxxx and GIO (GND) bond wires.
Here is what we can expect on the silicon. These are the bottom 8 bits of a 14-bit conversion of the apex of a sine wave. These samples were acquired in 256 clocks using the Sinc3 filter, and then decimated. Imagine that there are 64 more scope screens stacked vertically, in order to show the full scale. I think this is pretty good resolution:
Wow, that looks good!
For the high resolution, what about an integrate and dump scheme? There could be 2 integrators so that one can be read while the other is accumulating. Or just a buffer that captures the value before dumping. Of course you won't have a value every clock. But you could fake it by adding the incoming scope filter value to the integrator value.
But really, Sinc3 is the right way to do it. It's just expensive to get a sample every clock. If we could tolerate having a FIFO hundreds of bits long, the integrating filter should be able to do it.
I think if you wanted 4x overlapped 256-clock samples, you could set the Sinc3 counter reload to 64 and get acc3 readings every 64 clocks. You would maintain a FIFO buffer of the last four readings and sum them up to get a 256-count delta from which you'd compute your sample.
Comments
A clean signal is just a single value at any time. Something like a constant voltage. A fourier transform of such a signal only has one component not zero: the frequency zero, or DC-level.
The moment a single value is different, the spectrum will show an infinite number of non zero values, frequency 1 (one) is showing the largest amplitude, amplitudes decreasing with increasing frequency.
Any filter that limits high frequencies leaves over lower frequencies, so a spike, originally seen as a single value, now is cutted in amplitude, but spread in time, nearly undetectable. But when we integrate the signal over time, the bump will integrate to nearly the same value as the former spike did. So we gain nothing.
Now, how does a optimal filter work? Such a filter knows about the signals characteristic ( for example: spikes are not allowed) and just REMOVES any component that is not allowed. For example: if there is a spike, that is, amplitude changes faster than allowed, the slope is just limited.
Let the signal be constant, the change allowed is +-1. If now a change of 10 occures, this change is limited to 1. When the spike ends, the change is -10, limited: -1. So the error introduced is 1 times duration of the spike instead of 10 times duration of the spike. No signal is spreaded.
What we do so far is: we apply proven knowledge to an application, that is different to the original problem, leading to that knowledge. It's like draining a swamp in the dessert by watering, growing a swamp and then draining it.
Software defined radio, that is: sending bits at highest density using an electromagnetic wave can rely on the fact, that electromagnetic waves are law-abiding, means: the laws of physics apply. Then you can go to the limits, e.g. rely on Shannons Theorem. If not, and this is the case in the Propellers ADC,we should not try to squeeze out the last bit by doing experiments on a wavering platform.
Theory is one side of the medal, not the medal itself.
TonyB_, I don't understand how we are going to skip 81 twice and wind up with a plateau of 80. How can we do this this?
Chip, it's tricky and I haven't got it working yet.
Fantastic, TonyB_!
Nice how you've got the filters sized at 14, +8, +8, +16, +32. Is the 67-tap's purpose to feed a filter for 12-bit samples?
It's not essential, you're right. It just wouldn't need much explaining when someone used it.
Do you have any thoughts on how we ought to filter that 12-bit output to get steady 12-bit samples?
CMA67's intended purpose is to give us full 12-bit or 8-bit samples and replace CMA78 that is too big to fit, then the four CMAx could be implemented instead of the Tukey/Hann/Blackman windows, depending on the logic size.
The BASIC program was written to generate all the different windows with common code and there is no need for eight taps apart from CMA67. As this is the largest window it makes some sort of sense that there is no skipping, which I think can only work when what is being skipped has the same delta as before and after. This means that skipping might have a part to play with the smaller windows so that more taps are common to all windows, however I haven't tried this yet.
We would have a spare config bit with CMAx. CMA46 has 11-bit output, CMA30 10-bit and maybe these could be extended to 12 bits to match CMA67? The numbers don't add up so well for the smallest window CMA22, which sums to 256 (and is Tukey-like).
Written before previous post was read.
Will the output still be quite noisy after passing through 67 taps? I've thought about partially overlapping the windows in software so that every bit has exactly equal weight, with a sample taken every 60 50 or so clocks.
Is there any scope (pardon the pun) for anything else in hardware because the registers are fully used and the logic will be configured differently for different modes? I don't see how we could feed the output into some other existing filter in the same smart pin.
I'm a bit concerned out all of this business of clipping 256 to 255 or 4096 to 4095 just to save a small amount of logic; rather than propagate the carry, or overflow bit to the next stage - since I strongly suspect that that could be a major source of 1/f noise; which should be plainly clear if I give an example. Suppose that you are in effect summing bits using whatever chosen methods are available; whether it is TukeyXYZ or cmaXYZ or whatever. So you get a maximum slew rate audio input for a few 10's of microseconds; and then input is actually at 655xx something, i.e., close to the rail; but not necessarily at the rail … still you get a bunch of consecutive 256's which get clipped to 255; maybe even 100 of them, so now you are 100 bits short on your long count; when you add all of the ones up; then the input swings the other way; and the long count slowly drops; but not just zero; but past zero farther than it should; because the long count is short that 100 or so bits; and it gets clipped again a few more times at the 4095 vs. 4096 boundary in another cascaded stage and whoops! .. there we go again, with another asymmetric source of accumulated non linear distortion; which would manifest over time as a 1/f in the audio.
Then again; if the theory holds that the equilibrium state of the modulator is when it cycles between 0,1,0,1,0,1 .. when there is "no input" or rather when the input is (1/2)(Vcc+GND), it would appear that eventually the apparent drift introduced would eventually be "forgotten" by the filters, as they get past the longest window. Still the noise added will be "an occasional" disparity resulting in ENOB never really making it reliably past 8 or 9 biits.
ie these other modes, are are additional scope-mode filters ?
The Sinc3 gives a predictable filter for external ADCs, which can deliver better than 16 bit performances.
Here is how I see things. Both Sinc3 and scope modes are intended. The latter could provide an output every clock (which Sinc3 cannot do), either 8-bit triggered or 12-bit non-triggered. The former would be combined with byte outputs from three other pins to give four-channel, 32-bit values. The latter would be a higher-res output and as close to 16-bit as we could get every clock, probably.
This is an interesting point, thanks for mentioning it. Clipping actually adds a little bit to the logic and here is comparison of the window filters again:
The two Tukeys and the Hann would not need clipping.
I've just looked at this properly for the first time. What were the 17 trigger bits become filter[16:0] and the subtract and add are cascaded?
I'm wondering what this would do. I examined a short binomial/triangular filter [1,2,1] in software using three successive windowed outputs but the bits entering or leaving have very little weight and overall the three outputs varied so little it appeared to be useless, for the longer windows anyway.
I'm thinking that maybe this belongs in the Sinc3, where there are already big adders. The trouble is, I cannot get 16-bit stable readings until I go to a 4th order filter. 3rd-order doesn't seem to do it.
Chip was super happy with the tapered filter in post 1 of this thread. I'm honestly not convinced that what gets implemented in the end will be a ton better than that, which was already a huge improvement over the unfiltered ADC.
Is there a spreadsheet somewhere with all of these filters in it, the effective # of ADC bits, the approximate amount of logic added, and the update rate of the filtered output? So a decision could just be made that no further progress is happening? A simple 3D plot could show where new suggestions fall with respect to prior suggestions.
It's great that the triple integration method gives more flexibility than just CMA filters. We could design any filter we want as long as the 2nd, 3rd, or 4th derivative is sparse. You choose the number of integrations that minimizes the number of taps needed. The earlier Tukey windows were more efficeient at 2 integrations. The CMA filters are convenient as they guarantee smooth up and down curves and a very sparse derivative.
The closer all 3 numbers are, the closer we approximate sinc3.
After a lot of experimenting and testing, I'm giving up on the live 16-bit and 12-bit sampling. If >8 bit sampling is wanted, the Sinc3 filter does a vastly superior job of filtering, with the caveat that you only get a sample every Nth clock, instead of on every clock.
I've found that to get the best A/D conversion, the pins involving the same Vxxxx supply pin should all be A/D inputs, in order to minimize noise. In a lot of experiments, I was using one pin for ADC and its neighbor pin for DAC. The DAC can variably draw several mA, which causes an IR drop on the bond wires and chip routing metal, which causes distortion in an ADC sharing those power signals. The interplay between ADC and DAC activity on same-power-supply pins had me thinking a few times that we had some strange problems, when we didn't.
In order to get around this shared-supply problem during development on the FPGA, with the two-I/O-pin test ASIC, I've resorted to recording ADC readings and then playing them back on a DAC, to avoid cross-talk. On the silicon, you need only use another 4-pin group with separate Vxxxx and GIO (GND) bond wires.
Here is what we can expect on the silicon. These are the bottom 8 bits of a 14-bit conversion of the apex of a sine wave. These samples were acquired in 256 clocks using the Sinc3 filter, and then decimated. Imagine that there are 64 more scope screens stacked vertically, in order to show the full scale. I think this is pretty good resolution:
Thanks for chasing these ADC improvements. Even with things as-are the ADC is mighty useful
What are your thoughts as to integrating capacitor reduction, still thinking 7/8 reduction? Or is that not required, now
(So as a casual observer) is this what resolved the low frequency noise problem? I wasn't exactly sure what happened with that.
1/f noise is still an issue. The longer your measurement, the more of it you get. The Sinc3 filter is nice because it shortens measurements by getting more resolution in fewer counts. That not only increases efficiency, but reduces 1/f noise.
Reducing the integrator cap will help the ADC not muddle up high-frequency inputs. There should be no detrimental effect, other than you'll need to run the ADC at 8MHz+, instead of 1MHz+.
For the high resolution, what about an integrate and dump scheme? There could be 2 integrators so that one can be read while the other is accumulating. Or just a buffer that captures the value before dumping. Of course you won't have a value every clock. But you could fake it by adding the incoming scope filter value to the integrator value.
But really, Sinc3 is the right way to do it. It's just expensive to get a sample every clock. If we could tolerate having a FIFO hundreds of bits long, the integrating filter should be able to do it.
The numbers are the lengths of the moving averages. I prefer describing the filters that way because it describes how to construct the filters.
I think if you wanted 4x overlapped 256-clock samples, you could set the Sinc3 counter reload to 64 and get acc3 readings every 64 clocks. You would maintain a FIFO buffer of the last four readings and sum them up to get a 256-count delta from which you'd compute your sample.