# Where is SX1268's frequency calculation formula shown in the datasheet?

The SX1261/2/8's datasheet describes the function to calculate the frequency to set the IC:

Re-arranging the formula to find out the 4 bytes to send gives: $$\ RF_{Freq}= \cfrac{RF_{frequency}*2^{25}}{F_{XTAL}} \$$
where $$\ F_{XTAL} = 32Mhz \$$
$$\ RF_{Freq}= \cfrac{RF_{frequency}*2^{25}}{32Mhz} =\$$
$$\ RF_{Freq}= \cfrac{RF_{frequency}*33 554 432}{32Mhz} =\$$
$$\ RF_{Freq}= RF_{frequency}*1.048576 \$$

In the official library on github that they published, the function uint32_t sx126x_convert_freq_in_hz_to_pll_step( uint32_t freq_in_hz ) calculates the 4 bytes of frequency in another way which yields a different result/output than the datasheet's (my) function. The formula they use in the official library is either not mentioned in the datasheet or I failed to spot where in the datasheet mentions that formula. The function in the official lib uses a couple of the #defined variables so let me replace these and make it a bit easier to read:

    uint32_t sx126x_convert_freq_in_hz_to_pll_step( uint32_t freq_in_hz )
{
uint32_t steps_int;
uint32_t steps_frac;

// Get integer and fractional parts of the frequency computed with a PLL step scaled value
steps_int  = freq_in_hz / 250000;
steps_frac = freq_in_hz - ( steps_int * 250000 );

// Apply the scaling factor to retrieve a frequency in Hz (+ ceiling)
return ( steps_int << 14 ) + ( ( ( steps_frac << 14 ) + ( 250000 >> 1 ) ) / 250000 );
}


At this point, I believe the datasheet is incomplete. I don't care so much as to why it is calculated as it is in the official library. I mostly care about how could I figure out that formula without looking at the official library by just by checking the datasheet.

I think it has something to do with that part in the datasheet that says:

The LSB of Freq is equal to the PLL step which is:...

It is visible in the screenshot above, but I can't understand that sentence.

I think you made some math errors while substituting for the #defines. SX126X_PLL_STEP_SCALED should be 32000000 >> 11 = 15625, not 250000. After fixing that, the results are the same to within rounding error.

For example, taking a target frequency of 123,456,789 Hz, using the formula in the datasheet gives a PLL value of 123456789 * 1.048576 ≅ 129,453,825.98 (rounded to 129,453,826).

And tracing through the function with the correct values of the constants we end up with

steps_int = 123456789 / 15625 = 7901
steps_frac = 123456789 - (7901 * 15625) = 3664
retval = (7901 << 14) + ((( 3664 << 14 ) + (15625 >> 1)) / 15625)
= 129449984 + (60030976 + 7182) / 15625
= 129449984 + 60038158 / 15625
= 129449984 + 3842
= 129453826


which is exactly the correct value.

On occasion the fixed-point arithmetic will come up with a value that differs by ±1 unit from the exact math, but that error is orders of magnitude smaller than the crystal accuracy, and doesn't amount to anything.