[COLOR=blue][B]// Function returns a 16-bit unsigned integer,
[/B][/COLOR]unsigned short
[COLOR=blue][B]// which is the same as two bytes, which bytes will have to be[/B][/COLOR]
[COLOR=blue][B]// converted to their four hexadecimal ASCII chars elsewhere.[/B][/COLOR]
[COLOR=blue][B]// N.B. beware byte order![/B][/COLOR]
[COLOR=blue][B]// - The first argument is pData[/B][/COLOR]
[COLOR=blue][B]// - a pointer to the first of the series of characters[/B][/COLOR]
[COLOR=blue][B]// that compose the command action[/B][/COLOR]
[COLOR=blue][B]// - The second argument is DataLen[/B][/COLOR]
[COLOR=blue][B]// - the number of characters in the command action[/B][/COLOR]
CalculateChecksum (const unsigned char* pData, int DataLen).
{
[COLOR=Blue][B]// CS is a 32-bit unsigned integer that well keep track of[/B][/COLOR]
[COLOR=Blue][B]// the running sum, then be converted to the checksum[/B][/COLOR]
unsigned long CS = 0;
[B][COLOR=blue]// psData is a pointer to the start of the series of characters[/COLOR][/B]
[B][COLOR=blue]// in the command action,[/COLOR][/B]
[B][COLOR=blue]// but it is treated by the C++ compiler as a pointer to a[/COLOR][/B]
[B][COLOR=blue]// series of unsigned 16-bit integers. I.e.[/COLOR][/B]
[B][COLOR=blue]// - psData points to pData series character 0[/COLOR][/B]
[B][COLOR=blue]// - psData+1 points to pData series character 2[/COLOR][/B]
[B][COLOR=blue]// - psData+n points to pData series character 2n[/COLOR][/B]
unsigned short* psData = (unsigned short*)pData;
[COLOR=Blue][B]
// Loop over pairs of characters (bytes) in command action
// [/B][/COLOR][COLOR=Blue][B][COLOR=Blue][B](i.e. [/B][/COLOR][0,1], [2,3], [4,5], etc,), treat them as unsigned
//[/B][/COLOR][COLOR=Blue][B][COLOR=Blue][B] 16-bit[/B][/COLOR] integers via psData[/B][/COLOR]
for (int Index = 0 [B][COLOR=blue]// Start at 16-bit Index 0[/COLOR][/B]
[B] [COLOR=blue]// At start of each loop pass[/COLOR][/B]
; Index < (DataLen / 2) [COLOR=Blue][B]// - Stop after last full pair[/B][/COLOR]
[COLOR=blue][B]// of chars[/B][/COLOR]
[B][COLOR=blue]// At end of each loop pass[/COLOR][/B]
; Index++, [B][COLOR=blue]// - Increment Index by 1[/COLOR][/B]
, psData++) [COLOR=blue][B]// - Increment 16-bit pointer[/B][/COLOR]
[COLOR=blue][B] // by 1, [I][COLOR=Red]which increments by[/COLOR][/I][/B][/COLOR]
[COLOR=blue][B][I][COLOR=Red] // 2 in command action chars[/COLOR][/I]
[/B][/COLOR]
{
[COLOR=Blue][B] // In each loop pass, add next two chars to CS (checksum).[/B][/COLOR]
[COLOR=Blue][B] // treating those two chars as a single unsigned 16-bit[/B][/COLOR]
[COLOR=Blue][B] // integer. N.B. there may be overflow, but CS is 32-bit[/B][/COLOR]
[COLOR=Blue][B] // so that overflow will be in bits 16 and up[/B][/COLOR]
CS += *psData;
}
[COLOR=Blue][B] // If the command action length is odd, then the last command[/B][/COLOR]
[COLOR=Blue][B] // action character (byte) was not added to the checksum by[/B][/COLOR]
[COLOR=Blue][B] // the loop above; add it here[/B][/COLOR]
[COLOR=Blue][B] // - % is the modulo [/B][/COLOR][COLOR=Blue][B][COLOR=Blue][B]binary[/B][/COLOR] operator e.g. (34 % 10) => 4[/B][/COLOR]
[COLOR=Blue][B] // - (blah % 2) will yield 0 if blah is even, or 1 if odd[/B][/COLOR]
[COLOR=Blue][B] //[/B][/COLOR]
[COLOR=Blue][B] // N.B. This effectively pads any odd-length command action[/B][/COLOR]
[COLOR=Blue][B] // method with a single char (byte) with value 0, for[/B][/COLOR]
[COLOR=Blue][B] // the purpose of calculating the checksum[/B][/COLOR]
If (DataLen % 2 != 0)
{
CS += pData[DataLen - 1];
}
[B][COLOR=blue] // Add low and high 16-bit words of 32-bit checksum,[/COLOR][/B]
[B][COLOR=blue] // place resulting sum in checksum.[/COLOR][/B]
[B][COLOR=blue] // - >> is right-shift binary operator; in this case it[/COLOR][/B]
[B][COLOR=blue] // is equivalent either to dividing by 65536 (10000f)[/COLOR][/B][B][COLOR=blue],[/COLOR][/B]
[B][COLOR=blue] // or to sixteen BSRs,[/COLOR][/B]
[B][COLOR=blue] // - & is bit-wise AND binary operator; 0xFFFF is FFFFh[/COLOR][/B]
[B][COLOR=blue] // N.B. I have never seen a checksum that used the carry[/COLOR][/B]
[B][COLOR=blue] // i.e. the high 16-bits of the 32-bit sum of 16-bit,[/COLOR][/B]
[B][COLOR=blue] // but here it is[/COLOR][/B]
CS = (CS >> 16) + (CS & 0xFFFF);
[B][COLOR=blue] // Add the high bits again, in case the previous sum resulted[/COLOR][/B]
[B][COLOR=blue] // in a carry beyond the low 16-bits[/COLOR][/B]
CS += (CS >> 16);
[COLOR=blue][B] // Invert the bits of the checksum,[/B][/COLOR]
[COLOR=blue][B] // cast (convert) to an unsigned 16-bit integer (drop hi 16),[/B][/COLOR]
[COLOR=blue][B] // and return the unsigned 16-bit checksum [/B][/COLOR]
return (unsigned short) ~CS;
}