CRC32 Checksum NOVATEL implementing

Hello All

Please i need help getting the code to run to calculate a crc32 checksum for a novatel gps.
i tried a lot of libraries, they all calculatet a different crc then should.

this are two correct lines with the crc32 after the asterix:

%RAWIMUSA,2146,383076.381;2146,383076.381287958,80000000,-54590915,2687555,791980,-261806,-544952,-10583063d0e6cd
%RAWIMUSA,2146,383076.391;2146,383076.391287982,80000000,-48172060,1241744,-4615897,438118,-697743,-1758177
bd9fc612

for the checksum the % and the asterix are to be ignored

i found a code which should do this calculation from novatel but its in c and in my opinion part of a library
it seems i am not experienced enough to understand that

if someone can give me a hint thanks a lot
it runs on teensy4

the link to the original code: checksum/checksumDemo.c at master · novatel/checksum · GitHub

/*
The MIT License (MIT)
Copyright (c) 2019 NovAtel Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#define CRC32_POLYNOMIAL 0xEDB88320L
/* --------------------------------------------------------------------------
Calculate a CRC value to be used by CRC calculation functions.
-------------------------------------------------------------------------- */
unsigned long CRC32Value(int i) {
	int j;
	unsigned long ulCRC;
	ulCRC = i;
	for ( j = 8 ; j > 0; j-- ) {
		if ( ulCRC & 1 )
			ulCRC = ( ulCRC >> 1 ) ^ CRC32_POLYNOMIAL;
		else
			ulCRC >>= 1;
	}
	return ulCRC;
}

/* --------------------------------------------------------------------------
Calculates the CRC-32 of a block of data all at once
ulCount - Number of bytes in the data block
ucBuffer - Data block
-------------------------------------------------------------------------- */
unsigned long CalculateBlockCRC32( unsigned long ulCount, unsigned char *ucBuffer ) {
	unsigned long ulTemp1;
	unsigned long ulTemp2;
	unsigned long ulCRC = 0;
	while ( ulCount-- != 0 ) {
		ulTemp1 = ( ulCRC >> 8 ) & 0x00FFFFFFL;
		ulTemp2 = CRC32Value( ((int) ulCRC ^ *ucBuffer++ ) & 0xff );
		ulCRC = ulTemp1 ^ ulTemp2;
	}
	return( ulCRC );
}

void demoCalculateAsciiChecksum() {
	//Note that the checksum is computed between the leading '#' and the trailing '*' characters, exclusively.

	//Checksum for this block was: 9c9a92bb	
	//char *sampleMessageBlock = "BESTPOSA,COM1,0,78.0,FINESTEERING,1427,325298.000,00000000,\
6145,2748;SOL_COMPUTED,SINGLE,51.11678928753,-114.03886216575,\
1064.3470,-16.2708,WGS84,2.3434,1.3043,4.7300,\"\",0.000,0.000,7,7,0,0,0,06,0,03";

	//Checksum for this block was: 73cf9be2
	char *sampleMessageBlock = "BESTPOSA,ICOM2,0,85.0,FINESTEERING,2007,169577.000,02000020,b1f6,14693;SOL_COMPUTED,PPP,51.11679200638,-114.03886802392,1064.4326,-16.9000,WGS84,0.0498,0.0410,0.0756,\"TSTR\",17.000,0.000,18,18,18,16,00,00,00,33";
 
	unsigned long CRC = CalculateBlockCRC32(strlen(sampleMessageBlock), (unsigned char*)sampleMessageBlock);

	printf("\n%s %s\n", "Demonstrating CRC computed for the block:", sampleMessageBlock);
	
	//printf("\n\n%s %lu\n", "Computed ASCII checksum (in Decimal) is: ", CRC);
	printf("%s %lx\n", "Computed ASCII checksum is: ", CRC);
}
 

void main() {
	demoCalculateAsciiChecksum();
	 
}

Those two functions can be inserted into your Arduino code with no problems.

Correctly functioning example follows.

/*
The MIT License (MIT)
Copyright (c) 2019 NovAtel Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <string.h>
#include <inttypes.h>

#define CRC32_POLYNOMIAL 0xEDB88320L
/* --------------------------------------------------------------------------
Calculate a CRC value to be used by CRC calculation functions.
-------------------------------------------------------------------------- */
unsigned long CRC32Value(int i) {
  int j;
  unsigned long ulCRC;
  ulCRC = i;
  for ( j = 8 ; j > 0; j-- ) {
    if ( ulCRC & 1 )
      ulCRC = ( ulCRC >> 1 ) ^ CRC32_POLYNOMIAL;
    else
      ulCRC >>= 1;
  }
  return ulCRC;
}

/* --------------------------------------------------------------------------
Calculates the CRC-32 of a block of data all at once
ulCount - Number of bytes in the data block
ucBuffer - Data block
-------------------------------------------------------------------------- */
unsigned long CalculateBlockCRC32( unsigned long ulCount, unsigned char *ucBuffer ) {
  unsigned long ulTemp1;
  unsigned long ulTemp2;
  unsigned long ulCRC = 0;
  while ( ulCount-- != 0 ) {
    ulTemp1 = ( ulCRC >> 8 ) & 0x00FFFFFFL;
    ulTemp2 = CRC32Value( ((int) ulCRC ^ *ucBuffer++ ) & 0xff );
    ulCRC = ulTemp1 ^ ulTemp2;
  }
  return( ulCRC );
}

void demoCalculateAsciiChecksum() {
  //Note that the checksum is computed between the leading '#' and the trailing '*' characters, exclusively.
/*
  //Checksum for this block was: 9c9a92bb 
  //char *sampleMessageBlock = "BESTPOSA,COM1,0,78.0,FINESTEERING,1427,325298.000,00000000,\
6145,2748;SOL_COMPUTED,SINGLE,51.11678928753,-114.03886216575,\
1064.3470,-16.2708,WGS84,2.3434,1.3043,4.7300,\"\",0.000,0.000,7,7,0,0,0,06,0,03";
*/
 
// expected CRC 63D0E6CD

  char sampleMessageBlock[] = "RAWIMUSA,2146,383076.381;2146,383076.381287958,80000000,-54590915,2687555,791980,-261806,-544952,-105830"; 

  unsigned long CRC = CalculateBlockCRC32(strlen(sampleMessageBlock), (unsigned char*)sampleMessageBlock);

  Serial.println("Demonstrating CRC computed for the block:");
  Serial.println(sampleMessageBlock);
  
  //printf("\n\n%s %lu\n", "Computed ASCII checksum (in Decimal) is: ", CRC);
  Serial.print ("Computed ASCII checksum is: ");
  Serial.println(CRC,HEX);
}
 
void setup() {
  Serial.begin(9600);
  demoCalculateAsciiChecksum();
}
void loop() {}

hi jremington

thanks a lot, that was quick help. took me some lost hours.

my failure was i tried to put the code in the loop which didnt work couse its a function.

i completed and simplified it, reads from string (need this) and runs in the loop
also i addet leading zeros for the checksum

#include <string.h>
#include <inttypes.h>

#define CRC32_POLYNOMIAL 0xEDB88320L
 String msg;

unsigned long CRC32Value(int i) {
  int j;
  unsigned long ulCRC;
  ulCRC = i;
  for ( j = 8 ; j > 0; j-- ) {
    if ( ulCRC & 1 )
      ulCRC = ( ulCRC >> 1 ) ^ CRC32_POLYNOMIAL;
    else
      ulCRC >>= 1;
  }
  return ulCRC;
}
  unsigned long CalculateBlockCRC32( unsigned long ulCount, unsigned char *ucBuffer ) {
  unsigned long ulTemp1;
  unsigned long ulTemp2;
  unsigned long ulCRC = 0;
  while ( ulCount-- != 0 ) {
    ulTemp1 = ( ulCRC >> 8 ) & 0x00FFFFFFL;
    ulTemp2 = CRC32Value( ((int) ulCRC ^ *ucBuffer++ ) & 0xff );
    ulCRC = ulTemp1 ^ ulTemp2;
  }
  return( ulCRC );
}
 
void setup() 
{
  Serial.begin(460800);
}

void loop() 
{
     // should be 09b78f66
     String msg =("RAWIMUSA,2146,383074.881;2146,383074.881284274,80000000,-51490543,2377669,-324587,1124485,-599552,632832");
     const char * Message = (msg.c_str());
     unsigned long CRC = CalculateBlockCRC32(strlen(Message), (unsigned char*)Message);
    // leading zeros
    if (CRC <0x10) Serial.print ("0");
    if (CRC <0x100) Serial.print ("0");
    if (CRC <0x1000) Serial.print ("0");
    if (CRC <0x10000) Serial.print ("0");
    if (CRC <0x100000) Serial.print ("0");
    if (CRC <0x1000000) Serial.print ("0");
    if (CRC <0x10000000) Serial.print ("0");

    Serial.println(CRC,HEX);
    delay (1000);

  
  }

Don't use Strings if you are using an AVR based Arduino (like the Uno). They cause program crashes.