Post Go back to editing

CRC implementation for the LTC3300 IC

Category: Software
Product Number: LTC3300-1

Dear Experts,

I apologize for this simple question. We have been attempting, without luck, to implement a CRC function for the LTC3300-1, as discussed on page 40 of the data sheet. However, we have not been successful in duplicating the example on page 40. And rather than continuing, I was hoping that there might be an appropriate published CRC implementation that we could use to go forward. If anyone knows of one, or is willing to share, it would be greatly appreciated.

// Eraticus

  • Hi Eraticus,

    No worries, it is a good question, the CRC algorithm mentioned on page 40 of the LTC3300-1 datasheet is a standard CRC-4 algorithm, so we can use the code below to implement it.

    #include <stdio.h>

    #include <stdint.h>

    // CRC-4/

    uint8_t calculate_crc4(const uint8_t *data, size_t length) {
    uint8_t crc = 0; // Initialize CRC to zero
    const uint8_t generator=0x3;
    for (size_t i = 0; i < length; i++) {
    uint8_t current_byte = data[i];
    crc ^= current_byte; // XOR the current data byte with the CRC

    // Perform 4 shifts
    for (int j = 0; j < 4; j++) {
    if((crc & 0x8)!=0)
    {
    crc = (uint8_t)((crc << 1) ^ generator);
    }
    else
    {
    crc <<= 1;
    }
    }
    }
    crc &= 0xF;
    return crc;
    }

    int main() {
    uint8_t data[] = {0xc, 0x1, 0x0}; // Example data bytes
    size_t data_length = sizeof(data) / sizeof(data[0]);

    uint8_t crc_result = calculate_crc4(data, data_length);
    printf("CRC-4 checksum: 0x%X\n", crc_result);

    return 0;
    }

    Compare to the example shown in Figure 16, the code returns the correct CRC result.

    The algorithm above was quite inefficient as it works bit by bit. For larger input data, this could be quite slow, we can use the lookup table methods to accelerate.

    #include <stdio.h>
    #include <stdint.h>
    uint8_t crc4_table[16];

    // calculate_crc4 table/
    uint8_t calculatetable_crc4() {
    const uint8_t generator=0x3;

    for (size_t i = 0; i < 16; i++) {
    uint8_t current_byte = (uint8_t)i;
    // Perform 4 shifts
    for (int j = 0; j < 4; j++) {
    if((current_byte & 0x8)!=0)
    {
    current_byte<<=1;
    current_byte^=generator;
    }
    else
    {
    current_byte <<= 1;
    }
    }
    crc4_table[i]=current_byte&= 0xF;
    }

    }


    uint8_t compute_crc4(const uint8_t *data, size_t length) {
    uint8_t crc = 0; // Initialize CRC to zero
    for (size_t i = 0; i < length; i++) {
    uint8_t index = (uint8_t)(data[i]^crc);
    crc =(uint8_t)(crc4_table[index]) ;

    }
    crc &= 0xF;
    return crc;
    }

    int main() {
    calculatetable_crc4();
    uint8_t data[] = {0xc, 0x1, 0x0}; // Example data bytes
    size_t data_length = sizeof(data) / sizeof(data[0]);

    uint8_t crc_result = compute_crc4(data, data_length);
    printf("CRC-4 checksum: 0x%X\n", crc_result);

    return 0;
    }

    Thanks and Best Regards,

    Frank

  • I have one question about this implementation.

    For a CRC3 you need to change the line 15 on hte picture to:

    if((crc & 0x4)!=0)

    ???

    Or you can keep the (crc&0x8) ?

    Also of course you need to return (crc&0x7)  and need to update the generator variable with the correct value for CRC3

    I'm just asking this because I need to implement the CRC3 to MAX25608 and I'm not getting the correct way to get the ACK from the part.

    Thanks,

    Eduardo

  • Hi Eduardo,

    Sorry for the late response, I just happened to be on vacation recently.

    For CRC3, line 10 and line 28 is needed.

    Thanks and Best Regards,

    Frank

  • Hii,

    Thanks for the reply.

    For the MAX25608 the generator that is on datasheet is x3+x1+1 . I'm using 0x3 on generator variable on your algorithm.

    Using your algorithm on a READ command sending those bytes ->  0x79 0x03 0x00 [CRC]

    I get CRC= 0x3 (calculated only using bytes 0x03 0x00, as stated on datasheet).

    Then I need to shift it to the MFb and I get 0x60 (as I understand from datasheet).

    Finally, the frame ready to be sent is: 0x79 0x03 0x00 0x60.

    When I send this I do not get ACK from MAX.

    Some questions...

    Do I need to shift the crc bytes to MFb?

    Is something wrong with the algorithm you propose?

    Thanks,

    Eduardo

  • Hi Eduardo,

    I don't think there is something wrong with the algorithm I propose.

    what I should mention to you is that the CRC3 result should be 3-bit wide, so the correct result of the program below should be 0b101.
    You can verify that this program is correct by completing CRC manual calculations. Your current problem may mainly come from data processing that does not conform to the datasheet specification of max25608.

    Thanks and Best Regards,

    Frank

  • ok, I understand.

    Any way I was trying to send some random CRC bits to the part and with those bytes as input: 0x03 x00 + CRC byte 0xC0 , I got ACK from the part.

    0xC0 is shifted to MSbits. This means the result CRC from your algorithm should be 0x06.

    If I introduce the bytes 0x03 0x00 in your algorithm, I do not get the 0x06.

    Can you clarify what I need to change in your algorithm to get the correct CRC-3 value?

    Meanwhile, I found another match. With bytes as input 0x03 0x01 I get ACK from the part with CRC byte 0x04 (sent to the part shifted to MSbits as 0x80).

    I tried a lot other algorithms, and I'm not finding the correct one to generate the CRC-3 bits that make the part reply with ACK all time.

    Thanks,

    Eduardo.

  • OK I got the code working to generate the CRC3 value for MAX25608.

    We need to change a bit your code but it works.

    It validates the READ, WRITE and REPLY messages from the part.

    If you want I can provide the code.

    Thanks any way.

    Eduardo.

  • Hello Eduardo,

    can you please provide code for calculate CRC3 for MAX25608?

    Thanks in advance.

    Radek