# Teensy 4.0 600MHz ARM Cortex M-7 MCU - ideal for digital MCU based theremin?

Posted: 2/22/2020 9:33:06 PM

From: Northern NJ, USA

Joined: 2/17/2012

"Did you try to play at 80cm on Etherwave?"  - Buggins

No, but one with the ESPE01 or YAEWSBM might be somewhat playable there, but even then the "playing" would most likely only be suited to effects and such.

"So, I completely disagree with part 1 of your calculations."

I see what you are saying, and I don't entirely disagree with you disagreeing with me!

What's at the heart of this is how the "noise" is characterized.  For theoretical calculations it is usually treated as zero mean white noise, but here the "noise" is clearly correlated between samples.  Whatever error a single period measurement has is made up for in the next, so after many consecutive period measurements the error or uncertainty or noise is still one sample clock period.

Let me use the previous analogy because it better reflects the final implementation (a Theremin axis) and I'm simplifying the numbers a bit:

- LC resonance is 1MHz, we sample this at 100MHz and then sub-sample that at 1kHz.

- Sampling error is correlated so the 1kHz sub-sample will only have one clock of 100MHz of "nose" or error.

- 100MHz / 1kHz = 100,000 = ~17 bits.

So I was wrong by a wide margin here because I was treating the noise as uncorrelated.

However, if there are only 4 bits of "changing" information out of a total of 8, then I believe we would have to reduce this to 17 - 4 = 11 13 bits of "real" postional information.  I mean, the 17 bits above have a limited dynamic range of 4 bits out of 8 bits.  Does that make sense?

Because the noise is correlated, I don't believe further inspection and comparisons of the data with different shifts will yield much in the way of further benefit (i.e. higher order CIC or similar).  Some perhaps, but not as much because there isn't as much uncorrelated noise to filter away.  I mean, if you shift the circular buffer by one, pulling in one new sample and throwing away one older sample, the average isn't going to change much if you average this with the previous average.  You'll get a smoother output, but I don't think it will net you as much in terms of resolution increase as the uncorrelated case can.

Actually, by shifting and overlapping the measurements by 1mm, as in your second example, I believe you are introducing uncorrelated noise for each, and I'm not sure if that might actually help or hurt the final average.  There are real scenarios where more measurement actually hurts the SNR.

Of course you can take the output and filter it again down to 100Hz and increase the resolution ~1.6 bits.  Or you could immediately go from 100MHz to 100Hz and gain ~3.3 bits due to the correlation.  But then you might hear zippering if you don't do further filtering.

[EDIT] Vadim, I hope you don't think I'm arguing with you, or disagreeing just to be disagreeable, you are really helping me to straighten out my own thoughts regarding sampling.  I appreciate it when you point out the flaws in my reasoning.  As Feynman said, the objective is to prove yourself wrong as fast as possible!  I'm also not playing "devils' advocate" here, I want to understand this as well as you do.  I don't get a lot of opportunity to bounce this stuff off of people who are also in the process of thinking it through.

[EDIT2] The real trick would be to somehow keep the noise correlated through the entire process, but I think uncorrelated noise is ultimately introduced whenever the value is actually measured to be used.  I mean, every time you discard samples from the average you are starting it at a new location, which introduces new uncertainty or noise.  But if the sample discard is total after a single use, then the new start point is the old end point, and that would seem to minimize uncertainty.  I suppose there is a reason integrate-and-dump is called a "matched filter".

Posted: 2/23/2020 5:15:04 AM

From: Theremin Motherland

Joined: 3/16/2017

So, now you agree that taking 2 measurements with step d give log2(d) additional bits.
But unsure how can averaging of several such pairs help.

Let's consider group of n sequentional edge position measurements. Each has 1 LSB correlated error.
We need to calculate average position for this group.
Result will be (s1+s2+..sn) / n  (we can skip division by n - and just keep in mind that this value is *n).
Due to correlated error nature, result skill should have 1 LSB error. And we gained log2(n) bits.

Then, let's take another group of n sequentional edge position measurements, shifted by d from first one.
Its averaged position will have 1 LSB error as well.

By calculating of difference of these 2 points which correspond to positions of 2 groups with d edges step, we have signal period value *d*n
Error is still 1 MSB (positions of both groups have error correlated in the same way). And we got another log2(d) bits of signal period data.

So I believe my initial estimation was ok. And we can get 10+10 additional bits for two 1024 item groups at 1024 steps distance.

Need additional proof? Let's try to make model, e.g. written in Java or C++. It should be visible how many bits we got from averaging.

Posted: 2/23/2020 5:30:13 AM

Joined: 2/23/2020

I'm search the web for help with wiring Teensy 4.0 to Open.Theremin v3.
So far, no luck.

I also find the following site to be interesting as well (google translator needed) :
http://audiohologram.sblo.jp/pages/user/search/?keyword=teensy&tid=seesaa_hotspot&hid=167&c=12&search=1&ic=shift-jis

Any help with my wiring search or direction would greatly appreciated.

Posted: 2/23/2020 2:58:50 PM

From: Northern NJ, USA

Joined: 2/17/2012

"So, now you agree that taking 2 measurements with step d give log2(d) additional bits."  - Buggins

Using your 1mm resolution tape measure example here: starting at one point on the tape measure and ending farther away, taking the difference

(end - start) = d

we get log2(d) bits of data.  [EDIT] That is, we need log2(d) bits to hold the value of d.  Is that what you mean?  If so, I agree.

"Let's consider group of n sequentional edge position measurements. Each has 1 LSB correlated error.
We need to calculate average position for this group.
Result will be (s1+s2+..sn) / n  (we can skip division by n - and just keep in mind that this value is *n).
Due to correlated error nature, result skill should have 1 LSB error. And we gained log2(n) bits."

I agree with this, but for "We need to calculate average position" I think you mean "we need to calculate average interval or period".  [EDIT] OK, I think I see now that you are probably talking about points on the tape measure?

"Then, let's take another group of n sequentional edge position measurements, shifted by d from first one.
Its averaged position will have 1 LSB error as well."

Here I'm starting to get confused over what d and n are.  I think you mean for d = n?  So you have two groups of n that are sequential to each other?  If not, does this condition (d = n) cause any trouble for your argument / reasoning?

One thing I think that is causing confusion is noise / measurement error.  If possible, perhaps we should be discussing this in terms of no measurement error, and then introduce it later.

Posted: 2/23/2020 6:56:18 PM

From: Northern NJ, USA

Joined: 2/17/2012

OK, I've thought about it more and I believe the overall process is equivalent to a second order CIC:

At the top the LC oscillator period triggers interrupt, which sticks the timer/counter value in a memory circular buffer via DMA.  A running average is taken of the difference of the ends of the circular buffer conents.  Is that essentially correct?

If so, then the LC oscillator and timer/counter form an accumulator, and when coupled to the circular buffer and difference this forms a running average.  The running average after this is just that, a second running average.

Two running averages in series are equivalent to a second order CIC filter.  In pure hardware one would rearrange the integrators to be together, with the double differentiation happening only when a sample is needed, thus reducing the delay slots needed to one or two each.

I'm only presenting this as a possible route to analysis.  The more one can get things to look like known constructs, the more one can pull from what we already know about these things.

Posted: 2/23/2020 7:36:28 PM

From: Theremin Motherland

Joined: 3/16/2017

Easiest way to explain algorithm is to show its code.

I've implemented simulation in java - available on GitHub.
Two oscillators - sensor and timer clock are being simulated.
At each edge of sensor oscillator signal, capture timer value (counts number of rainsing edges of timer clock) is being stored to buffer.

Code:
```/**
* Measure signal period using averaging.
* @param samples is array of timer counter values captured on each oscillator signal edge
* @param pos is index of origin point (averaging done to the past from this point)
* @param diff is difference in captured items to the past (step)
* @param width is number of pairs to average
* @return measured period value * diff * width
*/
public static long measureAt(long[] samples, int pos, int diff, int width) {
long sum1 = 0;
long sum2 = 0;
for (int i = 0; i < width; i++) {
// older part
sum1 += samples[pos - diff - i];
// recent part
sum2 += samples[pos - i];
}
long measuredValue = sum2 - sum1;
return measuredValue;
}

```

Sample captured data from simulation:

Code:
```Testing measure of signal freq=1234567.890123456 timerFreq=2.4E8 diff=2048 width=2048
Captured data:
[2] 292 diff 98
[3] 389 diff 97
[4] 486 diff 97
[5] 583 diff 97
[6] 680 diff 97
[7] 778 diff 98
[8] 875 diff 97
[9] 972 diff 97
[10] 1069 diff 97
[11] 1166 diff 97
[12] 1264 diff 98
[13] 1361 diff 97
[14] 1458 diff 97
```

Testing averaging at different points:

Code:
```pos 10000 value 407686349 bin 11000010011001100110011001101 freq= 1234567.900628922 freqDiff 0.01050546602346003
pos 10137 value 407686348 bin 11000010011001100110011001100 freq= 1234567.9036571516 freqDiff 0.013533695600926876
pos 10274 value 407686350 bin 11000010011001100110011001110 freq= 1234567.8976006922 freqDiff 0.007477236213162541
pos 10411 value 407686348 bin 11000010011001100110011001100 freq= 1234567.9036571516 freqDiff 0.013533695600926876
pos 10548 value 407686349 bin 11000010011001100110011001101 freq= 1234567.900628922 freqDiff 0.01050546602346003
pos 10685 value 407686349 bin 11000010011001100110011001101 freq= 1234567.900628922 freqDiff 0.01050546602346003
pos 10822 value 407686348 bin 11000010011001100110011001100 freq= 1234567.9036571516 freqDiff 0.013533695600926876
pos 10959 value 407686350 bin 11000010011001100110011001110 freq= 1234567.8976006922 freqDiff 0.007477236213162541

...
period min=407686348 max=407686350 diff=2
```

Played a bit with different sensor signal frequencies and averaging window parameters.

I'm checking min and max values of period measured at different points.
Sometimes difference between min and max is 0, sometimes 2, biggest value

Code:
```Testing measure of signal freq=1000567.890123456 timerFreq=2.4E8 diff=2048 width=2048
period min=503030810 max=503030819 diff=9

Testing measure of signal freq=1001234.9876554 timerFreq=2.4E8 diff=2048 width=1024
period min=251347825 max=251347832 diff=7

Testing measure of signal freq=987654.3214567754 timerFreq=2.4E8 diff=2048 width=3000
period min=746496000 max=746496000 diff=0

Testing measure of signal freq=1234567.890123456 timerFreq=2.4E8 diff=2048 width=2048
period min=407686348 max=407686350 diff=2
```

Probably, standard deviation should be calculated instead of max-min.

Anyway, these results closer to my expectations that to yours.

2-3 bits may contain noise. But not 5 bits.

You can play with this simulation. On github, there is Eclipse project.

Posted: 2/23/2020 8:10:37 PM

From: Northern NJ, USA

Joined: 2/17/2012

Simulation is a good way to go.  I never really trust my thinking unless I can get it back to known filter constructs, there really aren't that many out there that are useful / effective, and it's amazing how often a simple cascade of 1st order IIR LPF works fine.  You can easily graph the frequency response of any digital filter in Excel with the difference equation (obtained via inspection and some algebra) and the Z-transform - I always do this to get a better grasp of what is going on (for zeros, bandwidth, order, aliasing when used for downsampling, etc.).

I guess I've thought about your scenario enough that I can rule it out for the D-Lev, my pitch numbers have tons of bits right off the bat, and I think it would be hard to average period measurements back out to that kind of resolution.  The pitch field has sufficient resolution over the playable range, which is the main thing.

Posted: 2/24/2020 3:11:01 PM

From: Theremin Motherland

Joined: 3/16/2017

Continuing my detective investigation.

Sensor filter diagram, to make design description clearer.

(correction to diagram: CLK should be passed to LP filter clock input instead of edge detection signal)

LC oscillator output is latched by FF each bus clock raising edge.
Two sequentional FFs and XOR between their output detect signal edges.

Timer counter increments each bus clock cycle.

Filter stage 1:
There is delay queue. Output shows value of input delayed by K writes.
Each time edge is detected, value of timer counter is being stored to queue. Queue output is being switched to next value.
As well, on edge detected, diff between current timer counter value and one K edges ago (queue output) is being latched in register.
Actually, output of this stage is oscillator period * K / 2 counted in timer clock cycles.

Filter stage 2:
Stage 1 output is passed to lowpass filter.
For FPGA, it can be implemented as several stages IIR filter updated each clock cycle.

For MCU implementation, it's running average (rectangular window FIR filter).

Actually, in Teensy 4 MCU implementatoin, we are using is 20bit PWM counter (16bit + 4 bit cycle counter).
Counter value is being captured by FlexPWM hardware each detected edge, DMA request is generated.
DMA handles request by copying FlexPWM capture register values into circular buffer.
Captured data in buffer is being processed once per audio frame (~1ms).
We need to know last DMA write position in buffer, and do proper correction of array index when accessing data (mod size of buffer).
Timer has only 20bits and overflows (switches from 0xfffff to 0) each ~0.25 ms.
Therefore, when calculating difference between recent sample and delayed one, operation should be done module buffer size.
Averaging with moving average (rectangular window FIR) filter algorithm at stage 2:

Code:
``` /**
* Measure signal period using averaging.
* @param samples is array of timer counter values captured on each oscillator signal edge
* @param pos is index of origin point (averaging done to the past from this point)
* @param diff is difference in captured items to the past (step)
* @param width is number of pairs to average
* @return measured period value * diff * width
*/
public static long measureAt(int[] samples, int pos, int diff, int width) {
int acc = 0;
for (int i = 0; i  30.0
103 of 30000 (0.343%) cases with standard deviation > 100.0
40 of 30000 (0.133%) cases with standard deviation > 200.0
At 80-90% cases we have pretty good result, highly effective filtering.
But not all frequencies as good as most of them.

Filter output standard deviation from exact value by frequency:

Filter output max-min value from exact value by frequency:

As you can see there are some cursed places where our filter performance reduces (twice in worst case - up to half of bits we gained by filtering (10 of 20) is getting rotten here.
As we can guess, these places are close to F_timer / integer divider. Or even rational F_timer * a / b.

[code]freq diff width period min max-min avg exactS
999983.981453462 2048 2048 503324539 31 503324544.10 8.150
999984.4302524126 2048 2048 503324299 88 503324322.50 33.497
999984.8790513631 2048 2048 503324045 151 503324079.00 45.238
999985.3278503136 2048 2048 503323776 212 503323877.53 74.600
999985.7766492642 2048 2048 503323506 275 503323652.97 89.426
999986.2254482147 2048 2048 503323322 231 503323393.43 79.685
999986.6742471652 2048 2048 503323139 169 503323172.80 50.634
999987.1230461157 2048 2048 503322942 95 503322952.97 25.174
999987.5718450663 2048 2048 503322732 29 503322736.83 8.050
999988.0206440168 2048 2048 503322506 36 503322509.77 7.479
999988.4694429673 2048 2048 503322262 121 503322283.57 34.778
999988.9182419179 2048 2048 503321998 188 503322049.10 65.659
999989.3670408684 2048 2048 503321713 299 503321847.97 104.870
999989.8158398189 2048 2048 503321404 402 503321573.27 128.649
999990.2646387694 2048 2048 503321246 324 503321351.17 114.292
999990.71343772 2048 2048 503321082 253 503321162.43 83.732
999991.1622366705 2048 2048 503320899 153 503320943.73 56.638
999991.611035621 2048 2048 503320698 41 503320701.13 8.894
999992.0598345716 2048 2048 503320472 46 503320476.23 8.696
999992.5086335221 2048 2048 503320220 159 503320250.80 50.167
999992.9574324726 2048 2048 503319938 289 503320034.07 106.266
999993.4062314231 2048 2048 503319616 479 503319800.83 148.597
999993.8550303737 2048 2048 503319248 645 503319626.77 199.868
999994.3038293242 2048 2048 503319111 534 503319325.80 190.233
999994.7526282747 2048 2048 503318986 440 503319076.33 122.653
999995.2014272253 2048 2048 503318838 266 503318887.93 89.076
999995.6502261758 2048 2048 503318659 112 503318666.37 22.832
999996.0990251263 2048 2048 503318438 65 503318441.73 11.530
999996.5478240768 2048 2048 503318161 334 503318209.63 98.271
999996.9966230274 2048 2048 503317799 618 503317951.03 219.672
999997.4454219779 2048 2048 503317313 1036 503317790.10 383.846
999997.8942209284 2048 2048 503316617 1819 503317432.53 541.696
999998.343019879 2048 2048 503316480 1750 503317089.87 676.028
999998.7918188295 2048 2048 503316480 2026 503317347.77 840.596
999999.24061778 2048 2048 503316480 1872 503316809.43 566.992
999999.6894167305 2048 2048 503316480 1843 503316667.30 519.839
1000000.1382156811 2048 2048 503316480 0 503316480.00 69.566
1000000.5870146316 2048 2048 503314577 1903 503316018.33 685.760
1000001.0358135821 2048 2048 503314637 1843 503315956.07 653.456
1000001.4846125327 2048 2048 503314479 2001 503315897.33 662.450
1000001.9334114832 2048 2048 503314486 1994 503315660.87 566.431
1000002.3822104337 2048 2048 503314546 1337 503315404.70 433.153
1000002.8310093842 2048 2048 503314489 840 503315070.00 293.040
1000003.2798083348 2048 2048 503314469 457 503314844.70 149.344
1000003.7286072853 2048 2048 503314531 90 503314611.97 20.766
1000004.1774062358 2048 2048 503314377 3 503314378.80 1.585
1000004.6262051864 2048 2048 503313954 232 503314156.27 73.217
1000005.0750041369 2048 2048 503313620 407 503313886.77 141.448
1000005.5238030874 2048 2048 503313393 500 503313711.40 195.128
1000005.972602038 2048 2048 503313150 622 503313436.20 176.180
1000006.4214009885 2048 2048 503312997 483 503313275.73 165.963
1000006.870199939 2048 2048 503312789 351 503313014.50 118.524
1000007.3189988895 2048 2048 503312656 188 503312796.33 61.988
1000007.7677978401 2048 2048 503312483 98 503312570.47 23.391
1000008.2165967906 2048 2048 503312328 18 503312343.77 3.799
1000008.6653957411 2048 2048 503312012 124 503312120.53 34.179
1000009.1141946916 2048 2048 503311765 182 503311901.47 61.394
1000009.5629936422 2048 2048 503311472 301 503311635.90 102.436
1000010.0117925927 2048 2048 503311244 359 503311413.80 129.883
1000010.4605915432 2048 2048 503311046 316 503311203.97 96.245
1000010.9093904938 2048 2048 503310839 229 503310975.83 76.333
1000011.3581894443 2048 2048 503310657 140 503310772.47 40.703
1000011.8069883948 2048 2048 503310485 61 503310534.13 20.363
1000012.2557873453 2048 2048 503310311 2 503310311.67 0.711
1000012.7045862959 2048 2048 503310034 63 503310090.37 16.873
1000013.1533852464 2048 2048 503309765 131 503309860.67 44.940
1000013.6021841969 2048 2048 503309500 207 503309623.90 76.481
1000014.0509831475 2048 2048 503309261 270 503309397.53 82.326
1000014.499782098 2048 2048 503309049 243 503309196.23 85.265
1000014.9485810485 2048 2048 503308863 153 503308967.20 50.174
1000015.397379999 2048 2048 503308661 97 503308737.57 31.339
1000015.8461789496 2048 2048 503308455 57 503308499.47 17.702
1000016.2949779001 2048 2048 503308277 3 503308278.27 0.918
1000016.7437768506 2048 2048 503308015 45 503308054.00 12.276
1000017.1925758012 2048 2048 503307752 100 503307824.10 35.067
1000017.6413747517 2048 2048 503307503 152 503307590.60 54.935
1000018.0901737022 2048 2048 503307273 195 503307386.27 60.831
1000018.5389726528 2048 2048 503307047 192 503307138.57 68.618
1000018.9877716033 2048 2048 503306830 144 503306942.47 46.915
1000019.4365705538 2048 2048 503306624 96 503306699.20 29.672
1000019.8853695043 2048 2048 503306437 42 503306471.00 12.371
1000020.3341684549 2048 2048 503306243 5 503306245.63 1.198
1000020.7829674054 2048 2048 503305987 40 503306021.03 9.497
1000021.2317663559 2048 2048 503305732 82 503305804.67 22.830
1000021.6805653065 2048 2048 503305501 111 503305569.50 36.547
1000022.129364257 2048 2048 503305251 164 503305337.87 52.498
1000022.5781632075 2048 2048 503305027 165 503305109.83 53.537
1000023.026962158 2048 2048 503304810 125 503304897.83 41.569
1000023.4757611086 2048 2048 503304607 77 503304668.40 24.256
1000023.9245600591 2048 2048 503304401 44 503304439.87 9.214
```

peak 2:

Code:
```freq diff width period min max-min avg exactS
991722.9391710798 2048 2048 507517215 88 507517238.40 33.462
991723.3879700303 2048 2048 507516999 24 507517001.27 4.203
991723.8367689808 2048 2048 507516766 45 507516771.10 10.066
991724.2855679314 2048 2048 507516514 135 507516535.80 35.710
991724.7343668819 2048 2048 507516242 208 507516341.37 75.076
991725.1831658324 2048 2048 507515947 318 507516080.20 102.351
991725.631964783 2048 2048 507515665 388 507515876.80 123.746
991726.0807637335 2048 2048 507515507 303 507515618.03 89.791
991726.529562684 2048 2048 507515335 218 507515389.30 66.015
991726.9783616345 2048 2048 507515144 103 507515158.30 28.448
991727.4271605851 2048 2048 507514931 27 507514935.00 5.792
991727.8759595356 2048 2048 507514695 67 507514705.20 20.075
991728.3247584861 2048 2048 507514430 208 507514485.87 73.815
991728.7735574367 2048 2048 507514128 374 507514264.73 123.366
991729.2223563872 2048 2048 507513784 513 507514002.00 158.580
991729.6711553377 2048 2048 507513482 645 507513739.17 208.706
991730.1199542882 2048 2048 507513366 511 507513539.07 182.251
991730.5687532388 2048 2048 507513229 385 507513351.97 136.274
991731.0175521893 2048 2048 507513066 225 507513091.87 57.286
991731.4663511398 2048 2048 507512865 3 507512866.87 0.800
991731.9151500904 2048 2048 507512616 201 507512647.30 61.966
991732.3639490409 2048 2048 507512296 523 507512441.23 178.693
991732.8127479914 2048 2048 507511870 910 507512101.10 291.865
991733.2615469419 2048 2048 507511276 1545 507511985.23 484.037
991733.7103458925 2048 2048 507510784 1925 507511755.87 616.463
991734.159144843 2048 2048 507510784 1994 507511428.37 649.436
991734.6079437935 2048 2048 507510784 2005 507511405.50 713.461
991735.056742744 2048 2048 507510784 2038 507511193.93 735.827
991735.5055416946 2048 2048 507510784 0 507510784.00 16.196
991735.9543406451 2048 2048 507508769 2015 507510637.07 463.151
991736.4031395956 2048 2048 507508925 1859 507510234.87 673.388
991736.8519385462 2048 2048 507508738 2046 507510098.80 696.136
991737.3007374967 2048 2048 507508865 1919 507510006.20 619.093
991737.7495364472 2048 2048 507508783 1610 507509720.73 491.756
991738.1983353978 2048 2048 507508756 1013 507509473.57 348.029
991738.6471343483 2048 2048 507508751 575 507509207.53 210.279
991739.0959332988 2048 2048 507508815 177 507508973.20 46.757
991739.5447322493 2048 2048 507508731 4 507508732.97 1.132
991739.9935311999 2048 2048 507508416 113 507508507.83 38.813
991740.4423301504 2048 2048 507507990 370 507508257.60 124.469
991740.8911291009 2048 2048 507507714 506 507508078.33 159.541
991741.3399280515 2048 2048 507507493 609 507507908.63 214.702
991741.788727002 2048 2048 507507278 560 507507567.23 174.030
991742.2375259525 2048 2048 507507092 395 507507352.37 138.283
991742.686324903 2048 2048 507506942 238 507507096.53 91.123
991743.1351238536 2048 2048 507506798 111 507506884.27 37.661
991743.5839228041 2048 2048 507506664 4 507506666.07 1.006
991744.0327217546 2048 2048 507506353 99 507506438.57 28.053
991744.4815207052 2048 2048 507506070 189 507506219.03 66.386
991744.9303196557 2048 2048 507505797 286 507506015.87 95.256
991745.3791186062 2048 2048 507505574 350 507505737.37 113.508
991745.8279175567 2048 2048 507505330 336 507505484.73 116.778
991746.2767165073 2048 2048 507505126 241 507505281.83 74.838
991746.7255154578 2048 2048 507504946 145 507505068.80 43.860
991747.1743144083 2048 2048 507504804 33 507504833.57 7.303
991747.6231133589 2048 2048 507504598 3 507504599.10 0.952
991748.0719123094 2048 2048 507504303 80 507504368.10 23.112
```

Now the question is, how to live with it?
If distance close to antenna falls into such region, it's not a problem at all.
But if unlikely such point corresponds to hand distance far from antenna, it would become unplayable (playable distance will at least drop to 60-70 cm instead of 90-100).
Trying to find some solution to avoid this curse.

UPD:
It's second stage (FIR) filter who is responsible for bad performance near F_BUS / k.
First stage filter gives log2(dist) bits w/o any errors.
So, it looks like applying better second stage filter may resolve issue.

Code:
```freq diff width period min max-min avg exactS
999999.7127913184 2048 2048 503316480 1171 503316557.50 297.381
999999.7127913184 2048 1024 251658240 1024 251658341.73 303.315
999999.7127913184 2048 512 125829120 512 125829173.07 142.665
999999.7127913184 2048 256 62914560 256 62914595.80 88.624
999999.7127913184 2048 128 31457280 128 31457287.33 27.882
999999.7127913184 2048 64 15728640 64 15728644.27 15.966
```

Posted: 2/24/2020 4:18:10 PM

From: Colmar, France

Joined: 12/31/2007

I'm search the web for help with wiring Teensy 4.0 to Open.Theremin v3.  So far, no luck. But reading this thread to be a fascinating dialogues. I also find the following site to be interesting as well (google translator needed) :http://audiohologram.sblo.jp/pages/user/search/?keyword=teensy&tid=seesaa_hotspot&hid=167&c=12&search=1&ic=shift-jisAny help with my wiring search or direction would greatly appreciated.

Not sure if it's worth the effort... The Open.Theremin shield suffers from too low oscillator amplitude and thus antenna voltage which makes it very sensitive to external interference. The software is very specifically written and optimized for the 8bit AVR 328 platform and would need a rewrite from scratch to work on a 32bit ARM platform where the GPIO registers, the timers, the CPU, everything is very very different.

And in particular, the 2 DACs on the Open.Theremin shield are controlled via 12bit SPI emulated through bit banging on the Arduino UNO since it has no native 12bit SPI (somebody knows a platform which has?)

Posted: 2/24/2020 4:25:03 PM

From: Theremin Motherland

Joined: 3/16/2017

Not sure if it's worth the effort... The Open.Theremin shield suffers from too low oscillator amplitude and thus antenna voltage which makes it very sensitive to external interference. The software is very specifically written and optimized for the 8bit AVR 328 platform and would need a rewrite from scratch to work on a 32bit ARM platform where the GPIO registers, the timers, the CPU, everything is very very different.

Although using Arduino libraries porting may be possible, to doesn't make sense. Using faster could allow to implement x1000 times better synthesis, but due to overcomplicated and low sensitivity Open.Theremin sensor part, it's bad idea.