Skip to content

Exact frequency calculations #39

Description

@cmichal2

Further to issue #36, I've spent quite a bit of time tracking down the exact frequencies that are produced. It's a bit more complicated a story than I expected, sorry for the long read! I also realize that the frequency differences I am interested in here may be smaller than most people care about. For my application knowing them exactly is essential.

My set up is this: I have an old-school (analog) PTS synthesizer that provides a 10 MHz reference output and a main output whose frequency is known exactly (relative to the 10 MHz reference). I use the 10 MHz reference output to drive the external clock on the fobos, then attenuate the main output and provide it as a signal input to the Fobos. I am communicating with the fobos with a C program via soapy. I removed the on-the-fly DC offset correction and on-the-fly channel balance corrections from the driver as they will cause problems for my application.

To start, I set the PTS frequency in the HF range: eg: 1.25 MHz, and connect to the HF1 connector. I collected ~15 seconds worth of samples at 8 or 20 MSPS and dump to disk. An FFT shows the signal at exactly the frequency expected. Since the 1.25 MHz is related to the 8 and 20MSPS sample rates used, you can see right in the data that the frequency is exactly correct. Just decimating the 8 MSPS samples by a factor of 32 shows a clean horizontal line that indicates there is no small frequency offset. So I am satisfied that the Fobos is using the external clock (the indicator light does light), and that the clocking of the ADC is correct (this is non-trivial. I've done some work with the LimeSDR and there the driver library would mess up the programming of the PLL that clocks the ADC so when you ask for 10MSPS it is not quite the same frequency as the 10 MHz reference!)

Next I bumped the PTS frequency up to 150 MHz and fed in to the RF input on the Fobos. In software, I requested a tuning frequency of 151.1 MHz. The driver claims to tune to 151099996.46 Hz, so you would expect to find the signal at an offset of 1099996.46. But that's not where it is. Instead it is at ~1100008.5 Hz, about 12 Hz off of where the driver told me it should be.

As mentioned in issue #36, I believe there is a minor error in the libfobos calculation of the MAX2830 frequency.
In particular, in the calculation of the PLL divisor:
div = (double)(div_int) + (double)(div_frac) / 1048575.0;
I believe the denominator should be 2^20 rather than 2^20-1. This is supported by an application note produced by Analog Devices
https://www.analog.com/en/resources/app-notes/understanding-the-operation-of--the-frequency-synthesizer-in-maxims-rf-transceivers.html
where, if you scroll down to the MAX2830 section, does show the frequency for the MAX2380 as: (F_ref/R )*(N + F/2^20).
In fobos_max2830_set_frequency, *actual = div * fcomp calculates the max2830 frequency as 2350000009.536752. But using 2^20 in the denominator instead of 2^20-1, it is 2350000000.

That's a difference of about 9.5 Hz, which accounts for all but about 2.5 Hz of the offset - the tuned frequency is still a little less than 2.5 Hz off of what I expect.

Next, I went looking at the RFFC5071, and it turns out that the missing ~2.5 Hz turns out to be exactly 1/2 of a least significant bit in the fractional divisor. So the RFFC5071 frequency is actually: fbkdiv * fref * (n + (numerator+0.5)/2^24)/lodiv. The 0.5 in there shifts the frequency by about 2.384 Hz, right to where I find the signal. The calculation of this frequency in the driver truncates to an integer, so it won't be exact either way, but is also missing the 0.5. I haven't been able to find documents for the RFFC5071 that mention this 0.5, but apparently this sort of offset is often a feature of the dithering of the fractional PLL.

The best way I've found to verify that that frequency calculation is correct is to frequency shift the raw I+Q samples by the calculated frequency offset (by multiplying by exp(2 pi j f t). The resulting data when plotted gives nice horizontal lines (with substantial phase noise, that I believe is expected from the PLL dithering) with no rising/falling/sinusoidal trend, over 15s of data. A frequency offset of as little as 0.002 Hz would be very easy to see that way.

I have checked some other frequencies to verify that adding in that 0.5 Hz works at different frequencies, and it looks good.

Thanks so much. The Fobos seems like a terrific device and it looks as though it will work well in my application.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions