EspoTek / Labrador

EspoTek Labrador is a USB device that transforms your PC or smartphone into a fully-featured electronics lab. This repo holds all of the source code!
http://espotek.com
1.1k stars 116 forks source link

Waveform generation clock settings #255

Closed dbsamithey closed 10 months ago

dbsamithey commented 10 months ago

I think that line 219 of genericUsbDriver.cpp should be changed from return CLOCK_FREQ / (division * channelData.samples.size() * channelData.freq); to return CLOCK_FREQ / (division * channelData.samples.size() * channelData.freq) - 0.5;

As I understand it, CPS = CLOCK_FREQ / (division * channelData.samples.size() * channelData.freq) is the appropriate number of clock cycles per waveform sample. Also, it looks like the PER setting of the waveform generating timer is set to the value returned on line 219, which is (int) CPS in the current code. But, the formula at the top of page 173 of the xmega-au manual indicates that the timer triggers every (PER + 1) clock cycles. This means that PER should be set to CPS-1 if CPS is an integer. If CPS is not an integer, adding 0.5 to the result before returning it produces a PER = (int) (CPS - 0.5) that is rounded instead of truncated to the nearest integer.

The attached plots show the power spectra of nominally 5 khz sin waveforms generated by the Labrador both before (PER = 75) and after (PER = 74) the change to line 219 is made. Before the change, the power spectrum peaks at 4,935 Hz, which corresponds to 76 clock cycles per waveform sample. After the change, it properly peaks at 5,000 Hz, which corresponds to 75 clock cycles per waveform sample. Before change: before_fix After change: after_fix

EspoTek commented 10 months ago

Thanks so much for the write up. I've had a few messages about slightly off frequencies, but have always come to the conclusion that it was just quantisation error (which, I suppose some of it is, but still).

I've committed the fix and it should upstream soon.

dbsamithey commented 10 months ago

No problem at all. I'm glad I could make some small contribution to the device. I think this also explains why the spectrum mode waveform breaks (#241) showed up for a nominally 1 khz signal. Because the signal was actually 48e6 / (128 376) = 997.34 Hz, a phase difference ( [ 3 33 (0.001 s) (997.34 Hz)] mod 1 = 0.74 periods ) built up over the 3 missing frames.