Anti-feature (bug?) in CGEN frequency calculation

I’m working on an application that requires the LimeSDR to be synchronized with some other bits of hardware. Both the rf frequencies as well as the timestamps need to behave predictably.

I’ve got the LimeSDR board running from an external 10 MHz reference clock, and was very surprised to find that when I requested a 10 MHz sample rate, it didn’t seem to be able to give it (exactly), rather it was off by 3.8ppb. That’s a small shift, but it matters.

I went digging through the code to see how the frequencies are calculated. First: the 10 MHz reference gets multiplied by 384/125 by the ADF4002 to give Fref = 30.72 MHz. Then the CGEN frequencies are generated from that 30.72 MHz reference clock. The CGEN vco frequency: Fvco = 2 * (H+1) Fsamp where H is an integer, and Fvco must be between 1950 and 2900 MHz. Then , Fsamp = (I+F/2^20) Fref, where I and F and integers. So ultimately, Fsamp = (I+F/2^20) * Fref / (2(H+1)) (with a constraint on H that Fvco lies in range).

Now to get an exactly 10 MHz sample clock, we need for (I+F/2^20)/(2(H+1)) = 125/384. The problem here is that 384 = 3 x 2^7, and if 2(H+1) isn’t divisible by 3, there’s no way to get exactly 10 MHz. In SetFrequencyCGEN, it just picks an H that puts Fvco near to the center of its range. For a 10 MHz sample rate, it picks an (H+1) that is not divisible by 3.

Its an easy fix, but very important for my application. Just after choosing H (iHdiv in the code) I added:

if (  ((iHdiv+1)/3)*3 != (iHdiv+1) ){
  // try one less:
  float_type dFvco2 = 2*(iHdiv) * freq_Hz;
  if (dFvco2 > gCGEN_VCO_frequencies[0] && dFvco < gCGEN_VCO_frequencies[1] && ( ((iHdiv)/3)*3 == iHdiv) ){
dFvco = dFvco2;
iHdiv -= 1;
  }
  else{
dFvco2 = 2*(iHdiv+2) * freq_Hz;
if (dFvco2 > gCGEN_VCO_frequencies[0] && dFvco < gCGEN_VCO_frequencies[1] && ( ((iHdiv)/3)*3 == iHdiv) ){
  dFvco = dFvco2;
  iHdiv += 1;
}
}
}

and now if possible it chooses an H that wipes out the 3. This may not be the best solution, maybe under some circumstances somebody might want the 1/3 in there, but I would think that under most circumstances its better to get rid of it.

It seems that there may be similar issues lurking in the TX and RX synthesizer frequency settings, but I haven’t gone looking yet.

I’d also love to be able to actually set an oversampling factor of 1. When setting it to one in the call to LMS_SetSampleRate, it seems to want to make it 2 anyway.

Suspect this is one for @IgnasJ.