RobTillaart / CRC

CRC library for Arduino
MIT License
81 stars 17 forks source link

input content (uint8_t *array) as HEX #24

Closed robsonoduarte closed 2 years ago

robsonoduarte commented 2 years ago

Hi,

Have a possible to use the function crc16 when the value to calculate is in HEX ?

I am using this CRC calculation online to check the calc, when the content type is a String, the result is ok:

using the crc function: image

result by func => 5E5A

online: image

but we need the result in HEX: image

result => D550

So, we not found in documentation if is possible to do that :eyes:

Thanks !

RobTillaart commented 2 years ago

What you want to do is to calculate the CRC of a number representation in memory.

There are several problems to tackle

  1. the string must be converted to a number
  2. it must be clear in what base the number is , binary, octal, decimal, hexadecimal or ....
  3. it must be clear how many bits the number is 8,16,32,64, ...
  4. the number will be in a processor specific representation (order of bytes)
    • MSB (1,2,3,4), LSB (4,3,2,1), or even some obscure 16 bit (3,4,1,2) (2,1,4,3)

I'll post a minimal sketch asap


update: removed incorrect info from post.

RobTillaart commented 2 years ago

a minimal function to get the right output.

void test()
{
  char str[24] = "0x0105AA";   //   AA0501            //  NOTE add 0x for proper conversion
  uint32_t number = strtoul(str, (char**)0, 0);

  Serial.println(str);
  Serial.println(number, HEX);
  Serial.println(crc16((uint8_t *) &number, 3, 0x1021, 0xFFFF, 0xFFFF, true, true), HEX);   //  NOTE LENGTH 3
}

0x0105AA 105AA D550

Note this is not a solution, but I do not know how your input can change so I cannot write the function.

RobTillaart commented 2 years ago

Gave it a try and came up with this function. Another point of attention popped up when reversing the string, you must swap 2 chars (= 1 byte) per iteration.

uint32_t crc_HEX(char *str)
{
  // add 0x
  char ws[10] = "0x";

  // "reverse" string 2 digits per iteration
  uint8_t len = strlen(str);
  int j = 2;
  for (int i = len - 1; i > 0;)
  {
    ws[j + 1] = str[i--];
    ws[j] = str[i--];
    j += 2;
  }
  ws[j] = 0;
  Serial.println(ws);

  // convert to number
  uint32_t number = strtoul(ws, (char**)0, 0);

  // CRC
  uint32_t n = crc16((uint8_t *) &number, len / 2, 0x1021, 0xFFFF, 0xFFFF, true, true);
  return n;
}

As this is rather specific code I won't make it part of the library yet. I did add the link of the online CRC calculator to the readme, so in the future it will be part of the release.

robsonoduarte commented 2 years ago

Hi @RobTillaart !

Thanks for the all answers ! and codes :rocket:

About your questions:

You can help us, to change your minimal function to use the 11Bytes ?

RobTillaart commented 2 years ago

@robsonoduarte If you use 11 bytes for the code implies an integer of 88 bits ... The single call crc16() cannot handle that.

So you should create a CRC16 object, and "feed it byte by byte"

uint16_t crc_str(char * str)
{
  CRC16 crc;
  crc.setPolynome(0x1021);
  crc.setStartXOR(0xFFFF);
  crc.setEndXOR(0xFFFF);
  crc.setReverseIn(true);
  crc.setReverseOut(true);

  int len = strlen(str);
  int i = 0;
  while (i < len)
  {
    char s[5] = "0x";
    s[2] = str[i++];
    s[3] = str[i++];
    s[4] = 0;
    uint32_t value = strtoul(s, (char**)0, 0);
    crc.add(value);

    Serial.print(s);
    Serial.print("\t");
    Serial.print(value, HEX);
    Serial.print("\t");
    Serial.println(crc.getCRC(), HEX);
  }
}
RobTillaart commented 2 years ago

you can probably speed up the creation of value from the initial string in the loop

Think the CRC16 object might need an extra constructor to set all parameters at once. (other issue)

robsonoduarte commented 2 years ago

Thanks for your help @RobTillaart !

The last code worked perfectly for our problem !

:rocket: :muscle: :heart:

RobTillaart commented 2 years ago

if you have an optimized version for the function I'm interested for reference purposes.