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 = 0to 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 = 0to topbit*2 + 1
for x = topbit to1step -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 = 0to 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 = 0to topbit*2 + 1
for x = topbit to1step -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.
Saucy, can you please describe the three terms in your cmafilter(x,y,z)?
The numbers are the lengths of the moving averages. I prefer describing the filters that way because it describes how to construct the filters.
octave:121> ones(8,1)'
ans =
11111111
octave:122> conv(ones(8,1),ones(10,1))'
ans =
12345678887654321
octave:123> conv(conv(ones(8,1),ones(10,1)),ones(12,1))'
ans =
13610152128364452596569717169655952443628211510631
octave:125> cmafilter(8,10,12)'
ans =
13610152128364452596569717169655952443628211510631
octave:128> ones(8,1)'
ans =
11111111
octave:129> conv(ones(8,1),ones(8,1))'
ans =
123456787654321
octave:130> conv(conv(ones(8,1),ones(10,1)),ones(8,1))'
ans =
136101521283643495355555349433628211510631
octave:131> cmafilter(8,8,8)'
ans =
13610152128364246484846423628211510631
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.
'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?
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:
Max values CMA67 = 4096 Tukey68 = 2040 CMA46 = 2048 Tukey45 = 1020 CMA30 = 1024 Hann30 = 510 CMA22 = 256 Blackman22 = 256
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.
CMA8*10*51 1 3 6 10 15 21 28 36 44 52 59 65 70 74 77 79 80 % sum=720 80[33] % 80*33 = 2640 + 1440 = 4080 = 255*16 80 79 77 74 70 65 59 52 44 36 28 21 15 10 6 3 1 % sum=720 CMA5*19*43 1 3 6 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 89 92 94 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 94 92 89 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 6 3 1 WindowFn Vpp98% StdDev HFNoisePower Length Sum freq -3dB freq -6dB cma67 0.9453125 0.25685335 0.093979185 67 4096 2.2583008 3.0517578 cmafilter(9,9,51) 0.93359375 0.25360235 0.087876466 67 4131 2.2583008 3.0517578 cmafilter(8,10,51) 0.91015625 0.2462003 0.083966496 67 4080 2.2583008 3.0517578 cmafilter(7,11,53) 0.84765625 0.22993315 0.055827542 69 4081 2.1972656 2.9296875 cmafilter(5,19,43) 0.90234375 0.21898064 0.017175846 65 4085 2.5024414 3.4179688 Winner? cmafilter(61,67) 0.44140625 0.1005641 0.0016081395 127 4087 1.4038086 1.8920898 cmafilter(7,8,73) 0.73828125 0.19108135 0.075131056 86 4088 1.6479492 2.1972656 cmafilter(3,29,47) 0.7734375 0.1800755 0.025439503 77 4089 2.1972656 2.9296875 cmafilter(12,11,31) 1.3359375 0.31267021 0.07171992 52 4092 3.3569336 4.5776367 cmafilter(2,23,89) 0.4609375 0.10954824 0.0084992018 112 4094 1.3427734 1.8310547 cmafilter(46,89) 0.37109375 0.084137484 0.0025121658 134 4094 1.2817383 1.7089844 cmafilter(7,13,45) 1.0039062 0.25080491 0.0549252 63 4095 2.5024414 3.3569336 cmafilter(9,13,35) 1.2304688 0.29084022 0.025621256 55 4095 3.0517578 4.1503906 cmafilter(7,15,39) 1.0625 0.25995787 0.0099692776 59 4095 2.8076172 3.7841797 cmafilter(13,15,21) 1.7851562 0.41339359 0.004897367 47 4095 4.0893555 5.6152344 cmafilter(23,23,23) 1.10677083 0.248253292 0.00663381155 67 12167 2.99072266 4.15039062 cmafilter(15,20,34) 0.9984375 0.224311137 0.000551419443 67 10200 2.80761719 3.84521484 cmafilter(18,18,18,16) 1.33077186 0.307690837 0.000285470381 67 93312 3.41796875 4.69970703
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.
WindowFn Vpp98% StdDev HFNoisePower Length Sum freq -3dB freq -6dB
cmafilter(15,16,17) 1.8710938 0.45310051 0.0097453259 46 4080 4.2114258 5.859375 cmafilter(12,17,20) 1.7851562 0.41339359 0.004897367 47 4095 4.0893555 5.6152344 cmafilter(13,15,21) 1.703125 0.41271856 0.0025632085 47 4080 4.0893555 5.6152344 cmafilter(10,17,24) 1.5546875 0.35814208 0.010309434 49 4080 3.7841797 5.1879883 cmafilter(11,12,31) 1.3359375 0.31267021 0.07171992 52 4092 3.3569336 4.5776367 cmafilter(8,17,30) 1.2695312 0.29777372 0.041569492 54 4080 3.112793 4.2724609 cmafilter(10,12,34) 1.265625 0.29298274 0.020882484 53 4080 3.3569336 4.5166016 cmafilter(8,15,34) 1.2304688 0.28550684 0.02088933 55 4080 3.112793 4.2114258 cmafilter(9,13,35) 1.2304688 0.29084022 0.025621256 55 4095 3.0517578 4.1503906 cmafilter(6,22,31) 1.0742188 0.25714119 0.027913922 57 4092 3.0517578 4.2114258 cmafilter(6,20,34) 1.0625 0.25995787 0.0099692776 59 4095 2.8076172 3.7841797 cmafilter(7,15,39) 1.046875 0.24883996 0.02482856 58 4080 2.9907227 4.0283203 cmafilter(5,24,34) 1.015625 0.23101449 0.026582745 61 4080 2.8076172 3.8452148 cmafilter(6,17,40) 1.0039062 0.25080491 0.0549252 63 4095 2.5024414 3.3569336 cmafilter(5,21,39) 0.9765625 0.23986534 0.011775686 61 4080 2.6855469 3.6621094 cmafilter(7,13,45) 0.97265625 0.22169555 0.028773534 66 4092 2.6245117 3.6010742 cmafilter(5,19,43) 0.96875 0.21869261 0.021288347 66 4080 2.6245117 3.6010742 cmafilter(4,30,34) 0.9453125 0.2219785 0.028801953 63 4095 2.6855469 3.6010742 cmafilter(4,31,33) 0.91015625 0.2462003 0.083966496 67 4080 2.2583008 3.0517578 cmafilter(8,10,51) 0.90234375 0.21898064 0.017175846 65 4085 2.5024414 3.4179688 cmafilter(5,17,48) 0.8828125 0.21550047 0.01768795 68 4080 2.3193359 3.112793 cmafilter(7,11,53) 0.84765625 0.22993315 0.055827542 69 4081 2.1972656 2.9296875 cmafilter(5,16,51) 0.84765625 0.18900605 0.0066547651 75 4080 2.3193359 3.112793 cmafilter(4,20,51) 0.8359375 0.2084993 0.018665709 70 4080 2.1972656 2.9907227 cmafilter(3,34,40) 0.82421875 0.18569615 0.0087039939 75 4095 2.3193359 3.112793 cmafilter(3,35,39) 0.79296875 0.19055261 0.016675073 73 4080 2.1972656 2.9296875 cmafilter(3,31,44) 0.78515625 0.20553193 0.091465996 79 4095 1.8310547 2.4414062 cmafilter(3,29,47) 0.7734375 0.1800755 0.025439503 77 4089 2.1972656 2.9296875 cmafilter(6,11,62) 0.765625 0.1784487 0.019493601 76 4092 2.2583008 3.0517578 cmafilter(4,17,60) 0.765625 0.20001477 0.054525232 77 4092 1.8920898 2.5634766 cmafilter(5,13,63) 0.73828125 0.19108135 0.075131056 86 4088 1.6479492 2.1972656 cmafilter(7,9,65) 0.734375 0.18651715 0.031620175 79 4095 1.8920898 2.5024414 cmafilter(6,10,68) 0.71875 0.18849886 0.074905481 82 4080 1.7700195 2.3193359 cmafilter(5,12,68) 0.71875 0.17393719 0.017857078 85 4080 1.7700195 2.3193359 cmafilter(4,15,68) 0.6953125 0.18060463 0.010035878 79 4080 1.953125 2.5634766 cmafilter(3,22,62) 0.6875 0.17827049 0.045283334 83 4080 1.7700195 2.3193359 cmafilter(7,8,73) 0.6796875 0.16979392 0.016435066 89 4088 1.6479492 2.1972656 cmafilter(3,21,65) 0.6640625 0.15440044 0.011133729 89 4080 1.7089844 2.3193359 cmafilter(3,20,68) 0.65625 0.16064566 0.015640098 85 4092 1.8310547 2.5024414 cmafilter(4,14,73) 0.65625 0.15789988 0.013131688 87 4095 1.7700195 2.3803711 cmafilter(2,40,51) 0.62890625 0.14304809 0.0056887585 91 4080 1.8920898 2.5634766 cmafilter(2,34,60) 0.62109375 0.15055978 0.057731851 103 4095 1.3427734 1.7700195 cmafilter(2,33,62) 0.61328125 0.14501547 0.0091484696 102 4080 1.4038086 1.8920898 cmafilter(6,8,85) 0.60546875 0.16565363 0.079584047 97 4080 1.4648438 1.8920898 cmafilter(2,31,66) 0.60546875 0.14378253 0.010198583 107 4095 1.3427734 1.7700195 cmafilter(2,30,68) 0.6015625 0.14457893 0.0072643578 98 4080 1.5258789 2.0141602 cmafilter(3,17,80) 0.6015625 0.14099539 0.03073128 106 4092 1.3427734 1.7700195 cmafilter(4,12,85) 0.59765625 0.14323234 0.004563578 94 4080 1.7700195 2.3803711 cmafilter(2,28,73) 0.58203125 0.13631145 0.0061415368 95 4092 1.7700195 2.3803711 cmafilter(3,16,85) 0.5625 0.1469321 0.031065718 99 4080 1.4648438 1.8920898 cmafilter(5,9,91) 0.5625 0.14958977 0.037040458 114 4080 1.2207031 1.6479492 cmafilter(4,11,93) 0.55859375 0.1313934 0.0099449442 97 4092 1.7089844 2.2583008 cmafilter(3,15,91) 0.55859375 0.12933839 0.01051853 98 4080 1.6479492 2.1972656 cmafilter(2,24,85) 0.55078125 0.12698544 0.053141074 127 4095 1.0986328 1.4648438 cmafilter(2,23,89) 0.546875 0.12927947 0.0087096441 101 4088 1.5869141 2.1362305 cmafilter(5,8,102) 0.5390625 0.15383191 0.058560707 113 4080 1.2207031 1.6479492 cmafilter(4,10,102) 0.51953125 0.12846422 0.015637843 119 4095 1.2207031 1.5869141 cmafilter(2,22,93) 0.5 0.11117836 0.0058186917 122 4080 1.2207031 1.5869141 cmafilter(3,13,105) 0.4921875 0.12480833 0.021968404 147 4080 0.9765625 1.2817383 cmafilter(2,20,102) 0.48828125 0.11417822 0.0074740046 115 4092 1.3427734 1.7089844 cmafilter(1,60,68) 0.484375 0.11695425 0.0096959977 109 4080 1.4038086 1.8920898 cmafilter(1,61,67) 0.47265625 0.12116007 0.021602631 136 4092 1.0375977 1.3427734 cmafilter(1,62,66) 0.46875 0.11493629 0.029272387 179 4080 0.79345703 1.0375977 cmafilter(1,63,65) 0.4609375 0.10954824 0.0084992018 112 4094 1.3427734 1.8310547 cmafilter(5,7,117) 0.44140625 0.096554634 0.0014085564 127 4080 1.4038086 1.8920898 cmafilter(1,56,73) 0.44140625 0.1005641 0.0016081395 127 4087 1.4038086 1.8920898 cmafilter(1,53,77) 0.44140625 0.097355869 0.0021470632 127 4092 1.4038086 1.8920898 cmafilter(1,51,80) 0.4375 0.12216849 0.051376129 145 4080 0.9765625 1.2817383 cmafilter(1,48,85) 0.4375 0.10967076 0.0044945432 151 4080 0.9765625 1.2817383 cmafilter(1,47,87) 0.43359375 0.093805836 0.036547378 211 4080 0.67138672 0.91552734 cmafilter(1,46,89) 0.42578125 0.095734222 0.0028626318 127 4095 1.4038086 1.8920898 cmafilter(1,45,91) 0.421875 0.1165705 0.045902376 155 4088 0.91552734 1.159668 cmafilter(1,44,93) 0.41796875 0.094900488 0.001994358 128 4088 1.4038086 1.8310547 cmafilter(3,11,124) 0.41015625 0.092538658 0.0014063601 129 4081 1.3427734 1.8310547 cmafilter(2,17,120) 0.41015625 0.097042155 0.0040005586 137 4080 1.0375977 1.4038086 cmafilter(1,43,95) 0.40234375 0.091554082 0.0027861622 132 4080 1.2817383 1.7089844 cmafilter(1,40,102) 0.3984375 0.091083422 0.0017300966 130 4080 1.3427734 1.7700195 cmafilter(1,39,105) 0.390625 0.098972526 0.0063637559 160 4088 0.91552734 1.159668 cmafilter(5,6,136) 0.390625 0.10342484 0.042696333 178 4080 0.79345703 1.0375977 cmafilter(3,10,136) 0.390625 0.08975344 0.012173962 214 4080 0.67138672 0.91552734 cmafilter(2,15,136) 0.38671875 0.087852367 0.0027309409 133 4089 1.2817383 1.7089844 cmafilter(1,35,117) 0.38671875 0.091018672 0.0065057791 170 4082 0.85449219 1.0986328 cmafilter(1,34,120) 0.3828125 0.08619121 0.0022953354 135 4095 1.2817383 1.6479492 cmafilter(4,7,146) 0.3828125 0.097783378 0.027860707 203 4095 0.73242188 0.91552734 cmafilter(1,33,124) 0.3828125 0.098549037 0.028855762 261 4080 0.61035156 0.73242188 cmafilter(2,14,146) 0.375 0.08361578 0.013937691 236 4086 0.61035156 0.79345703 cmafilter(1,31,132) 0.37109375 0.084137484 0.0025121658 134 4094 1.2817383 1.7089844 cmafilter(1,30,136) 0.37109375 0.083127214 0.0021773357 136 4092 1.2207031 1.6479492 cmafilter(1,29,141) 0.3671875 0.083783222 0.0021492163 137 4085 1.2207031 1.6479492 cmafilter(2,13,157) 0.35546875 0.081168118 0.0018333482 141 4080 1.159668 1.5258789 cmafilter(1,28,146) 0.35546875 0.079744889 0.0016885936 143 4095 1.159668 1.5258789 cmafilter(4,6,170) 0.35546875 0.089073563 0.01439288 263 4080 0.61035156 0.73242188 cmafilter(3,8,170) 0.3515625 0.078977605 0.0014575215 151 4095 1.0375977 1.4038086 cmafilter(2,12,170) 0.3515625 0.092569415 0.019813774 345 4080 0.48828125 0.61035156 cmafilter(1,26,157) 0.34765625 0.095855087 0.014478488 458 4086 0.36621094 0.48828125 cmafilter(1,24,170) 0.34375 0.090143548 0.019714252 346 4092 0.48828125 0.61035156 cmafilter(2,11,186) 0.33984375 0.089411431 0.010912252 197 4092 0.73242188 0.9765625 cmafilter(1,23,178) 0.33984375 0.079240485 0.027985958 234 4086 0.61035156 0.79345703 cmafilter(3,7,195) 0.3359375 0.086808399 0.0092910354 182 4080 0.79345703 1.0375977 cmafilter(1,22,186) 0.328125 0.07704787 0.0019535137 156 4092 1.0375977 1.3427734 cmafilter(4,5,204) 0.328125 0.075551914 0.0022640931 162 4092 0.9765625 1.2817383 cmafilter(2,10,204) 0.31640625 0.074725289 0.001546331 153 4080 1.0375977 1.3427734 cmafilter(1,21,195) 0.3125 0.074472429 0.0021856468 165 4080 0.9765625 1.2207031 cmafilter(1,20,204) 0.3125 0.074447446 0.0024512287 169 4089 0.91552734 1.2207031 cmafilter(1,19,215) 0.3125 0.081568518 0.024795057 278 4080 0.54931641 0.73242188 cmafilter(3,6,227) 0.3125 0.090265673 0.014256314 459 4095 0.36621094 0.48828125 cmafilter(2,9,227) 0.3046875 0.072080149 0.0028858426 173 4088 0.91552734 1.159668 cmafilter(1,18,227) 0.30078125 0.080948295 0.024483061 279 4095 0.54931641 0.73242188 cmafilter(1,17,240) 0.296875 0.077590502 0.011119039 514 4080 0.36621094 0.42724609 cmafilter(4,4,255) 0.2890625 0.071737802 0.015006185 299 4088 0.54931641 0.67138672 cmafilter(2,8,255) 0.28515625 0.067967424 0.0026656105 182 4082 0.85449219 1.0986328 cmafilter(1,16,255) 0.28515625 0.068167586 0.0022197291 207 4092 0.73242188 0.9765625 cmafilter(3,5,272) 0.28515625 0.077683673 0.011085855 515 4088 0.36621094 0.42724609 cmafilter(3,5,273) 0.28515625 0.085005963 0.0081914691 684 4086 0.30517578 0.36621094 cmafilter(1,15,272) 0.28125 0.06846468 0.0026564947 193 4080 0.79345703 1.0375977 cmafilter(1,15,273) 0.28125 0.064601198 0.0019532652 215 4095 0.73242188 0.91552734
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.
octave:121> ones(8,1)' ans = 1 1 1 1 1 1 1 1 octave:122> conv(ones(8,1),ones(10,1))' ans = 1 2 3 4 5 6 7 8 8 8 7 6 5 4 3 2 1 octave:123> conv(conv(ones(8,1),ones(10,1)),ones(12,1))' ans = 1 3 6 10 15 21 28 36 44 52 59 65 69 71 71 69 65 59 52 44 36 28 21 15 10 6 3 1 octave:125> cmafilter(8,10,12)' ans = 1 3 6 10 15 21 28 36 44 52 59 65 69 71 71 69 65 59 52 44 36 28 21 15 10 6 3 1 octave:128> ones(8,1)' ans = 1 1 1 1 1 1 1 1 octave:129> conv(ones(8,1),ones(8,1))' ans = 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1 octave:130> conv(conv(ones(8,1),ones(10,1)),ones(8,1))' ans = 1 3 6 10 15 21 28 36 43 49 53 55 55 53 49 43 36 28 21 15 10 6 3 1 octave:131> cmafilter(8,8,8)' ans = 1 3 6 10 15 21 28 36 42 46 48 48 46 42 36 28 21 15 10 6 3 1
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.