Announcement

Collapse
No announcement yet.

Converting C to Pb

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Converting C to Pb

    I am trying to port this code to PB. The code is used to generate 16 bit CRC code. (CRC-16, CCITT)
    I am a bit puzzled by the part in the do...while loop. (Not really easy to read)
    This is the c code:
    Code:
    #define POLY 0x8408
     
    unsigned short crc16(data_p, length)
    char *data_p;
    unsigned short length;
    {
           unsigned char i;
           unsigned int data;
           unsigned int crc;
           
           crc = 0xffff;
           
           if (length == 0)
                  return (~crc);
           
           do {
                  for (i = 0 data = (unsigned int)0xff & *data_p++;
                      i < 8;
                      i++, data >>= 1) {
                        if ((crc & 0x0001) ^ (data & 0x0001))
                               crc = (crc >> 1) ^ POLY;
                        else
                               crc >>= 1;
                  }
           } while (--length);
           
           crc = ~crc;
            
           data = crc;
           crc = (crc << 8) | (data >> 8 & 0xFF);
            
           return (crc);
    }
    Any ideas are welcome...


    ------------------
    Regards,
    Peter
    Regards,
    Peter

  • #2
    Peter, maybe something like this...

    Code:
    %POLY = &H08408
    FUNCTION crc16(BYVAL data_p AS BYTE PTR, length AS WORD) AS WORD
       LOCAL i AS BYTE, dData, crc, n AS DWORD
       crc = &H0ffff
       IF length = 0 THEN
          FOR i = 0 TO 31 'crc = ~crc
             BIT TOGGLE crc, i
          NEXT i
       ELSE
          DO 
             dData = CDWD(&H0ff AND data_p): INCR data_p
             FOR i = 0 TO 7       
                IF (crc AND &H0001) XOR (dData AND &H0001) THEN
                   SHIFT RIGHT crc, 1
                   crc = crc XOR %POLY
                ELSE
                   SHIFT RIGHT crc, 1
                END IF
                SHIFT RIGHT dData, 1
             NEXT i
             DECR length 'added this very necessary stmt
          LOOP WHILE length 
          FOR i = 0 TO 31  'crc = ~crc
             BIT TOGGLE crc, i
          NEXT i
          dData = crc
          SHIFT LEFT crc, 8: SHIFT RIGHT dData, 8
          crc = crc OR (dData AND &H0FF)
       END IF
       FUNCTION = crc
    END FUNCTION
    Added
    Since short was explicitly used for the length variable, I assumed that integers were 4 bytes.
    which seems like this algorithm would be for crc32 rather than for crc16. I'm confused.
    ------------------




    [This message has been edited by Charles Dietz (edited August 16, 2007).]

    Comment


    • #3
      One more version
      Code:
      #COMPILE EXE
      #DIM ALL
      '
      #INCLUDE "win32api.inc"
      '
      %POLY = &H8408??
      '
      'unsigned short crc16(data_p, length)
      FUNCTION crc16 (BYVAL data_p AS BYTE PTR, BYVAL length AS WORD) AS WORD
             LOCAL i AS BYTE     'unsigned char i;
             LOCAL wData AS WORD 'unsigned int data;
             LOCAL crc AS WORD   'unsigned int crc;
             '
             crc = &hFFFF?? 'crc = 0xffff;
             '
             IF length = 0 THEN 'if (length == 0)
                   FUNCTION = NOT crc : EXIT FUNCTION ' return (~crc);
             END IF
             '
             DO
                    'for (i = 0 wData = (unsigned int)0xff & *data_p++; i < 8; i++, wData >>= 1)
                    i = 0 : wData = &h00FF?? AND @Data_p
                    WHILE i < 8
                             IF ((crc AND &h0001??) XOR (wData AND &h0001??)) THEN
                                  SHIFT RIGHT crc,1   '<- crc = (crc >> 1) ^ %POLY;
                                  crc = crc XOR %POLY '<-
                             ELSE
                                  SHIFT RIGHT crc,1  'crc >>= 1;
                             END IF
                       INCR i
                       SHIFT RIGHT wData, 1
                    WEND
                    '
                    INCR Data_p
                    DECR length
             LOOP WHILE length '(--length);
             '
             crc = NOT crc ' crc = ~crc;
             '
             wDATA = crc ';
             '
             SHIFT RIGHT wData, 8 : wData = wData AND &h00FF?? '<- crc = (crc << 8) | (wDATA >> 8 & 0xFF);
             SHIFT LEFT crc, 8                                 '<-
             crc = crc OR wData                                '<-
             '
             FUNCTION = crc ' RETURN (crc);
      END FUNCTION
      '
      '===============================
      '
      FUNCTION PBMAIN () AS LONG
         LOCAL cData AS ASCIIZ * 32
         DIM bData(10) AS BYTE
         '
         cData = "abcdefgdddddddD"
         ? "0x" + HEX$(crc16(BYVAL VARPTR(cData) , LEN(cData)), 4) ,, "CRC16 of string ="
         '
         ARRAY ASSIGN bData() = 10,20,30,40,50,60,70,80,90,100,200 ' fill byte array with some data
         ? "0x" + HEX$(crc16(BYVAL VARPTR(bData(0)), UBOUND(bData)-LBOUND(bData)), 4) ,, "CRC16 of byte array ="
         '
      END FUNCTION
      '
      ------------------
      -=Alex=-
      -=Alex=-

      Comment


      • #4
        Thanks,

        I'll try them both out. I've already ported/tried several other code samples, but all give different (and incorrect) answers...
        There is a predefined 'test' string for CCITT CRC-16 test:

        When the input string is "123456789", the calculated CRC should be: E5CC Hex



        ------------------
        Regards,
        Peter
        Regards,
        Peter

        Comment


        • #5
          Looks like I left off the DECR length statement which I just edited in my code above.
          Also, Alex's use of bitwise NOT is of course the way to go.

          ------------------

          Comment


          • #6
            One more crc16 algorithm which is concur with test string of CCITT

            Code:
            #COMPILE EXE
            #DIM ALL
            '
            #INCLUDE "win32api.inc"
            '
            %POLY  = &H8408??
            %Magic = &H16DB??
            '
            FUNCTION crc16f1(BYVAL wData AS BYTE PTR, BYVAL lenght AS LONG, BYVAL seed AS WORD) AS WORD
              LOCAL b1 , b2 AS BYTE
              LOCAL crc AS WORD
              '
              crc = seed
              '
              IF lenght THEN
                  WHILE lenght
                      b1 = @wData AND &hff? : INCR wData
                      b2 = (crc XOR b1) AND &h0f?
                      SHIFT RIGHT crc, 4
                      crc = crc XOR (b2 * %Magic )
                      SHIFT RIGHT b1, 4
                      b2 = (crc XOR b1) AND &h0f?
                      SHIFT RIGHT crc, 4
                      crc = crc XOR (b2 * %Magic)
                      '
                      DECR lenght
                  WEND
              ELSE
                  crc = 0
              END IF
             
              FUNCTION = crc
            END FUNCTION
            '===============================
            '
            FUNCTION PBMAIN () AS LONG
               LOCAL cData AS ASCIIZ * 32
               LOCAL sRes AS STRING
               '
            '   There is a predefined 'test' string for CCITT CRC-16 test:
            '   When the input string is "123456789", the calculated CRC should be: E5CC Hex
               cData = "123456789"
               '
               ? "CRC16 of string ["+cData+"] = 0x" + HEX$(crc16f1(BYVAL VARPTR(cData) , LEN(cData), %POLY), 4) ,, "Result"
               '
            END FUNCTION
            P.S.
            BTW,
            very helpful links: http://www.joegeluso.com/software/articles/ccitt.htm http://www.zorc.breitbandkatze.de/crc.html
            ------------------
            -=Alex=-

            [This message has been edited by Aleksandr Dobrev (edited August 16, 2007).]
            -=Alex=-

            Comment


            • #7
              I have made some code by reading the specs of CRC-16 a few time. It's not very quick, but the results are OK.
              (I've added 2 more reference values)
              This is the straigth approach. It converts the incoming datastring into a binary string ("A" becomes "01000001")
              and compares bit by bit through complete string.
              Code:
              #Compile Exe
              #Dim All
              '
              #Include "win32api.inc"
              '
              %POLY  = &H11021
               
              Function Crc_16(dStr As String) As Word
                Local CntByte As Long, CntBit As Long, NewData As Byte, OldData As Byte, Buff As String, Crc As Word
                Local dwTemp As Dword
                Buff = String$(16, "1")
                For CntByte = 1 To Len(dStr)
                  NewData = Asc(dStr,CntByte)
                  For CntBit = 7 To 0 Step -1
                    If Bit(NewData, CntBit) Then Buff = Buff & "1" Else Buff = Buff & "0"
                  Next
                Next
                Buff = Buff & String$(16, "0")
                dwTemp = Val ("&b" & Mid$(Buff, 1, 16))
                For CntBit = 17 To Len(Buff)
                  Shift Left dwTemp, 1
                  If Mid$(Buff, CntBit, 1) = "1" Then Bit Set dwTemp, 0 Else Bit Reset dwTemp, 0
                  If Bit (dwTemp, 16) Then dwTemp = dwTemp Xor %POLY
                Next
                Function = dwTemp
              End Function
               
              '===============================
              Function PBMain () As Long
                MsgBox "CRC-16 of string " & $Dq & "123456789" & $Dq & " is:   0x" & Hex$(Crc_16("123456789")),,"Result: (expected: 0xE5CC)"
                MsgBox "CRC-16 of empty string" & $Dq & "" & $Dq & " is: is:   0x" & Hex$(Crc_16("")),,"Result: (expected: 0x1D0F)"
                MsgBox "CRC-16 of string " & $Dq & "A" & $Dq & " is:   0x" & Hex$(Crc_16("A")),,"Result: (expected: 0x9479)"
              End Function

              ------------------
              Regards,
              Peter
              Regards,
              Peter

              Comment

              Working...
              X