What is the HP 1630a learn string checksum algorithm? - Page 1
Forum section: electronics / testgear

author: cmax100000
author_rank: Newbie
timestamp: January 01, 2023, 04:28:43 pm
content: I can't find any documentation about the learn string checksum algorithm. My goal is to be able to set all the parameters for the analyzer in my computer, generate the string, calculate the checksum, and send the receive command with the new string back to the machine.My simple test will be to set the date and send it back to the machine as the machine does not remember settings when turned off.Here are two very sparse learn strings from my machine that I have been using to try to get at the algorithm.In hex525400110000000000000300000000000000008110and5253000f00000000000000001b000000008295Bytes 3 and 4 are the bytes that follow beginning with byte5 and including 2 bytes at the end for the checksum result.Thanks in advance.

author: tv84
author_rank: Super Contributor
timestamp: January 01, 2023, 04:37:04 pm
content: Looking atthisshouldn't be much hard.It's not a checksum. It's a CRC.Can you show more examples?

author: Andy Watson
author_rank: Super Contributor
timestamp: January 01, 2023, 04:41:26 pm
content: It's a CRC 0x8005. The catch is that it operates on the lower byte of a 16 bit register rather than the more usual upper byte.https://www.eevblog.com/forum/testgear/searching-for-a-hp-1630-hp-1631-inverse-assembler-files/msg2146852/#msg2146852

author: tv84
author_rank: Super Contributor
timestamp: January 01, 2023, 05:43:28 pm
content: Quote from: Andy Watson on January 01, 2023, 04:41:26 pmIf I did not make any error, your code gives this:unsigned char buffer[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };CRC16 =810Aunsigned char buffer[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00 };CRC16 =8295So, it seems it'snotcorrect.Edit: Corrected, after OP acked the CRC 810A error.

author: Andy Watson
author_rank: Super Contributor
timestamp: January 01, 2023, 07:49:26 pm
content: Works for me on strings returned from my HP1630G This is the response to TT (transmit timing data request).41 54 00 1900 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 0A

author: cmax100000
author_rank: Newbie
timestamp: January 01, 2023, 07:58:30 pm
content: Sorry, on the first one I put in hex 10 instead of hexA.I'm going to have to check my notes on this as I was all over the IA posts and I tried the low byte only along with reversing bits, reversing bytes, poly 1021, and others and still couldn't come up with a matching crc.Thanks for doing the legwork on this. I will try again but I am still unclear on how to force the operation on just the lower byte when using some of the online tools for CRC generation. Is the result from C code that is modified to only use the lower byte of the poly so it's just 0x0005?I'll post a few more when I get back to the machine this afternoon.Thanks.

author: Andy Watson
author_rank: Super Contributor
timestamp: January 01, 2023, 08:08:02 pm
content: Quote from: cmax100000 on January 01, 2023, 07:58:30 pmI don't think you will find an online CRC generator that will produce the same output. I think the use of the lower part of the register was a mistake on HP's part. Usually, if you add the CRC bytes into calculation you should have zero as the result - but this doesn't work for the HP1630 due to the unusual method of calculating the CRC - which is why I think it's a bug.

author: Andy Watson
author_rank: Super Contributor
timestamp: January 01, 2023, 08:16:34 pm
content: This is the code that I am using - sorry it's a bit untidy but i've just hacked it together from different sources:Code:/* CRC calculation using HP1630 algorythm */#include <stdio.h>#include <stdlib.h>unsigned int CRC_table;unsigned int HP_CRC(unsigned char *,int , int );void HP_CRC_Initialise(unsigned int);int main(int argc, char *argp[]){unsigned int n,x,z;unsigned int crc;HP_CRC_Initialise(0x8005);crc = 0;printf("\n");for (z=1;z < argc;z++){n = sscanf(argp,"%x",&x);if (n!=1) {printf("\nUnable to interpret %s as a hex constant.\n",argp);exit(1);}crc = (crc & 0xff00) ^ CRC_table[(crc ^ x) & 0xff];}printf("\nCRC = %04X",crc);printf("\n");exit(0);}/* Generate table and perform CRC according to HP1630 requirements */unsigned int HP_CRC(unsigned char *buffer,int length, int seed){int x=0;while (length > 0) {seed = (seed & 0xff00) ^ CRC_table[(seed ^ buffer[x++]) & 0xff];length--;}return(seed);}void HP_CRC_Initialise(unsigned int poly){unsigned int crc,x,y;for (x=0;x<256;x++) {crc = x;for (y=0;y<16;y++) {crc <<= 1;if (crc & 0x10000) crc ^= poly;crc &= 0xffff;}CRC_table = crc;}}Enter the hex-bytes on the command line separate the bytes with a space.

author: tv84
author_rank: Super Contributor
timestamp: January 01, 2023, 08:27:03 pm
content: CRC residue may be different from 0. There are plenty of examples in use.At the moment there is a poly that answers all your 3 samples but I would like to test with more samples.Another idea: have you tried reversing the buffer and doing a "normal" CRC?

author: Andy Watson
author_rank: Super Contributor
timestamp: January 01, 2023, 08:31:58 pm
content: Yes, tried that. I tried most of the CRCs given on the wiki page, both reversed and inverted, none of them worked.

author: tv84
author_rank: Super Contributor
timestamp: January 01, 2023, 09:44:20 pm
content: Quote from: Andy Watson on January 01, 2023, 08:31:58 pmAgree. I've checked all combinations (ReflIn, ReflOut, XorIn, XorOut plus all polys) and it's impossible to calculate the CRC with the "normal" CRC algorithm.The reason, as Andy say, it's here (in this instruction):crc = (crc & 0xff00) ^ CRC_table[(crc ^ x) & 0xff];The normal ReflIn CRC code uses:crc = (crc >> 8) ^ CRC_table[(crc ^ x) & 0xff];So, the higher byte is XORed in the "wrong" place.2 possible reasons: programmer mistake or deliberate obfuscation by HP.So, Andy's code is the correct solution.

author: cmax100000
author_rank: Newbie
timestamp: January 08, 2023, 01:39:54 pm
content: Thank you for all the work so far on this problem. I am still struggling with this but my initial problem of knowing the poly value that was used to generate the CRC checksum is now something I can work with.I haven't looked at much C code in the last 20 years so I need to make sure I am reading this string of C correctly:In words, this line"crc=(crc&oxff00)^hpcrc_table[(crc ^*buffer++)&0xff];"is saying the new crc is equal to the old crc high byte xor'd with the crc low byte of the current buffer character,move the buffer pointer to the next character, and store the result in the high byte of the crc register.If the words are correct, is it the software equivalent of a hardware crc by loading of the first two bytes of data, appending a 16 bit crc 0, shifting in the remaining data string in to the crc register from the right and running until the data is fully shifted in and then 16 more shifts and then taking the value of the crc register?I am going to proceed with the answer provided by Andy as it solves my immediate problem but I remain foggy on this.