Post Go back to editing

AD4134 / AD7134 : How to calculate ODR Register (Mistake in Datasheet?)

Category: Datasheet/Specs

Hi,

the datasheet of AD4134 (and AD7134) report the following examples to calculate the ODR (AD4134, Datasheet Rev.0 page 49):

The datasheet states that the target ODR is 187.23 kS/s. Hence the decimation rate is approximately 128.1846. 128 in hex is 0x80. So far so good. But how is the float part (ODR_VAL_FLT) calculated?

When I try to convert the float part 1846 (the part after the comma) into hex, I get 0x736 and not the given 0x2F4103E5 as per datasheet (which would be as a decimal: 792789989).  Am I missing something? The second example does not help (no float part) and in both ADC Datasheets the examples are the same.

I want to have an ODR of 81.92 kHz. What are the right register bits / how to calculate them?

I would have assumed ODR_VAL_INT = 0x000051 (decimal 81) and ODR_VAL_FLT = 0x00005C (decimal 92). 

Thank you very much already,

Patrick



- fixed minor wording issues
[edited by: pre at 6:38 PM (GMT -5) on 4 Feb 2023]
  • Hi  ,

     

    The float part (ODR_VAL_FLT) is calculated by converting the fractional part of the decimation rate to hexadecimal.

    In the datasheet example, the decimation rate computed to get the ODR of 187.23kS/s is 128.1845858.

     

    To get the hexadecimal equivalent, we must analyze and convert the integer and fractional part separately. I see that you were able to get the same hex value for the integer part, 128, but not for the fractional part.

     

    The conversion of the fractional part 0.1845858 does not follow the same rules as integers for decimal to hexadecimal conversion.

     

    In converting fractional part, we must first multiply 0.1845858 by 16, which gives 2.953372857, note the integer then multiply the fractional part by 16 and repeat the process as below:

     

    0.1845858 * 16 = 2.953372857 -> 2

    0.953372857 * 16 = 15.253965712  -> 15 (F in hex)

    0.253965712 * 16 = 4.063451392   -> 4

    0.063451392 * 16 = 1.015222272  -> 1

    0.015222272 * 16 = 0.243556352  --> 0

    0.24355632 * 16 = 3.89690112  --> 3

    0.89690112 * 16 = 14.35041792  --> 14 (E in hex)

    0.35041792 * 16 = 5.60668672  --> 5

     

    ODR_VAL_INT[23:0] = 0x80

    ODR_VAL_FLT[31:0] = 0X254103E5

     

    0x16 ODR_VAL_INT_LSB = 0x80

    0x17 ODR_VAL_INT_MID = 0x00

    0x18 ODR_VAL_INT_MSB = 0x00

    0x19 ODR_VAL_FLT_LSB = 0xE5

    0x1A ODR_VAL_FLT_MID0 = 0x03

    0x1B ODR_VAL_FLT_MID1 = 0x41

    0x1C ODR_VAL_FLT_MSB = 0x25

     

    To get an ODR of 81.92kHz, please note that the value of the decimation rate is stored in the registers and not the target ODR.

     

    To get the decimation rate, we divide 24MHz by the target ODR of 81.92kHz, and we will get the decimation rate of 292.96875

     

    We convert first the integer part 292 to hexadecimal = 124

    Then, we convert the fractional part:

     

    0.96875 * 16 = 15.5 --> 15 (F in Hex)

    0.5 * 16 = 8 --> 8

     

    ODR_VAL_INT[23:0] = 0X124

    ODR_VAL_FLT[31:0] = 0xF8000000

     

    0x16 ODR_VAL_INT_LSB = 0x24

    0x17 ODR_VAL_INT_MID = 0x01

    0x18 ODR_VAL_INT_MSB = 0x00

    0x19 ODR_VAL_FLT_LSB = 0x00

    0x1A ODR_VAL_FLT_MID0 = 0x00

    0x1B ODR_VAL_FLT_MID1 = 0x00

    0x1C ODR_VAL_FLT_MSB = 0xF8

     

     

    Another method to convert a decimal number with fractional part is to multiply the number by 16 until there is no fractional part remaining

     

    292.96875 * 16 = 4,687.5

    4687.5 * 16 = 75000

    Convert 75000 to hexadecimal = 124F8 and move the decimal place by the how many times it was multiplied by 16 (2 times)

     

    292.96875 = 0x124.F8

     

    I hope this helps. Please let us know if you have other questions.

     

    Thanks,

    Janine

  • Hello Janine,

    thank you very much for your detailed answer. This made it really easy to implement a solution in C. I just stumbled upon two points:

    • When I tested the algorithm in Python I calculated a slightly deviating MSB & LSB 0X2F4103D6 (see attached Screenshot). I think the MSB is just a typo. The difference in the LSB is probably due to different rounding. Which one will lead to a better match regarding the ODR?
    • While the described algorithm really helped understanding, i think there is a simpler solution in C:
       tmp_data = (uint32_t)(fmodf(MCLK_FREQ_HZ/odr_frequency_hz, 1.0)*pow(16,8));

    Kind regards,

    Patrick

  • Hi Patrick,

    Apologies for getting back just now. You are right. I made a typo in the MSB. Thanks for pointing that out. It should be 0X2F4103E5.

    The difference in the LSB is due to the different rounding. I used the entire number up to the 13th decimal place but only wrote up to 6 decimal places in my comment.

    Upon checking both, 0X2F4103E5 and 0X2F4103D6, both will result to 187230sps accurate up to 5th decimal place, with 0X2F4103E5 more accurate up to 6th decimal place.

    Thanks,
    Janine