1
\$\begingroup\$

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

setRfFrequency

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.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.