Solved

Checksum for cash register packet

Posted on 2004-08-21
7
850 Views
Last Modified: 2013-11-18
I have problem finding the right checksum for this packet.
Checksum is CRC-like type except for the table.
This is "Datecs" cash registers and the packet that is sent trough RS-232 from PC. For now, i'm looking for easy solution (not decompiling executive of the program that does the communication or disassemble the firmware to find it out).

Here it is:
Example 1:
#$0A R2;1; #$0D #$18 #$78 - This command is a "read" with subcommand 2 and article no. 1.
#$0A I0;1; #$0D #$5A #$51 - Don't remember what this command does, but it's using the same scheme

Here's the format:
"All bytes in the block are ASCII characters except the two control bytes CRC.
A sucessful transmission of a block from the ECR includes transmitting of:
- control character for beginning of a block  BEG ( 0A HEX or ^J)
- data bytes
- control symbol for end of block END ( 0D HEX or  ^M)
- 2 control bytes CRC."

So, i need the way to calculate last 2 numbers from the packet - in first case $1878 and in the second $5A51.

Here's the explanation of the manufacturers (very unclear) - looks like some CRC16, but it's not alike anything i ever see:
      The two CRC bytes are calculated according to the formula x^15 + 1. In the calculation are included all data bytes plus the byte for block end. Every byte passes through the calculation register from teh MSB to LSB.
      Three working bytes are used - S1, S0 and TR
      S1 - Most significant byte from the CRC ( it is transmitted immediatelly after END)
      S0 - Least significant byte from the CRC ( It is transmitted after S1)
      TR - the current transmitted byte in the block.

      The CRC is calculated as follows:
      1. S1 and S0 are zeroed
      2. TR is loaded with the current transmitted byte. The byte is transmitted.
      3. Points 3.1 and 3.2 are executed 8 times:
      3.1. S1, S0 and TR are shifted one bit to the left.
      3.2. If the carry bit from S1 is 1, the MSB of S1 and LSB of S0 are inverted.
      Points 2 and 3 are executed for all bytes, included in the calculation of the CRC - from the first byte after BEG up to and including byte END.
      4. TR is loaded with 0 and point 3 is executed
      5. TR is loaded with 0 and point 3 is executed
      6. Byte S1 is transmitted
      7. Byte S0 is transmitted
0
Comment
Question by:Dragonmen
7 Comments
 
LVL 84

Expert Comment

by:ozo
ID: 11862173
What do you need?
A program in some particular language to calculate S1 and S0?
0
 
LVL 5

Author Comment

by:Dragonmen
ID: 11872875
A scheme for calculating will be good enough.
And, yes, it's S0 and S1 (checksum byte 1 and 2).
0
 
LVL 19

Accepted Solution

by:
drichards earned 500 total points
ID: 11878289
Can someone out there figure out what I did wrong here?  I think this should be the algorithm, but I get an extra bit in my answer:

0x9878 vs. 0x1878 in the first case and
0x5AD1 vs. 0x5A51 in the second.

Interestingly, off by 0x8000 and 0x0080.

Here's my code:
---------------------------------------------------
  // Put these lines in main or combine into main...
  unsigned char data1[] = { 0x0A, 'R', '2', ';', '1', ';', 0x0D, 0x18, 0x78 };
  unsigned char data2[] = { 0x0A, 'I', '0', ';', '1', ';', 0x0D, 0x5A, 0x51 };
  unsigned short c1 = Checksum(data1);
  unsigned short c2 = Checksum(data2);

// Checksum computation
unsigned short Checksum(unsigned char*)
{
    unsigned char TR = 0;
    unsigned short checksum = 0;
    unsigned char &S0 = *((unsigned char*)&checksum);
    unsigned char &S1 = *(&S0+1);

    for ( int ii = 1; TR != 0x0d; ii++ )
    {
        TR = data[ii];
        checksum = checksum ^ ((unsigned short)TR << 8);
        for ( int jj = 0; jj < 8; jj++ )
        {
            if ( (checksum & 0x8000) != 0 )
            {
                checksum = (checksum << 1) ^ 0x8001;
            }
            else
            {
                checksum <<= 1;
            }
        }
    }
    return checksum;
}
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 5

Author Comment

by:Dragonmen
ID: 11886349
Really don't know, but here's one more examples:
0X0A,'0','0','5','6','9','0',';',0X0D,0XF8,0X4C
And it returns F8CC instead of F84C. Interestly, 0x80 again ?
0
 
LVL 19

Expert Comment

by:drichards
ID: 11887706
Seems very strange that after that many shifts and XOR's it would be off by only 1 bit.  I must be missing something.
0
 
LVL 5

Author Comment

by:Dragonmen
ID: 11889995
Maybe it's just an extra processing which isn't explained ?
I did this and it worked for these test samples:

if (Checksum AND $80)<>0 then
Checksum:=Checksum XOR $80 else
Checksum:=Checksum XOR $8000;

Thank you anyway
0
 

Expert Comment

by:_dem
ID: 12044860
As for me, _this_ works fine.

function TForm1.CheckSum(s: string): word;
var tr,z,x : byte;
_checksum : word;
_s0,_s1 : ^byte;
begin
tr:=0;
_checksum:=0;
_s0:=pointer(@_checksum);
_s1:=pointer(integer(@_checksum) + 1);
for z:=1 to length(s) do begin
        tr:=ord(s[z]);
        _checksum:=_checksum xor ( tr shl 8 );
        for x:= 0 to 7 do begin
                if _checksum and $8000 <> 0 then
                _checksum:=(_checksum shl 1) xor $8001
                else
                _checksum := _checksum shl 1;
{ /// DON'T need ??

                if (_Checksum AND $80)<>0 then
                _Checksum:=_Checksum XOR $80 else
                _Checksum:=_Checksum XOR $8000;    }
        end;
        end;
result:=_checksum;
end;

seems works ok !
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
countAbc challenge 9 59
word0 challenge 4 65
Basic Java Case or If-Else statement... 3 43
How to insert gas or chemical names in SQL server. For e.g. CO2 to CO₂. 5 67
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
How important is it to take extra precautions to protect your online business? These are some steps you can take to make sure you're free of any cyber crime.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now