Shop OBEX P1 Docs P2 Docs Learn Events
Working CRC16 code in spin for the CrystalFontz display — Parallax Forums

Working CRC16 code in spin for the CrystalFontz display

CannibalRoboticsCannibalRobotics Posts: 535
edited 2010-05-01 18:47 in Propeller 1
OK, this is the CRC-CCITT code that works with the CrystalFontz display if you are interested.


    _crc := $FFFF                       ' initialize _crc
    Repeat i from 0 to PacketSize       ' Paload of bytes sent here
      _crc := UpdateCRC(Packet[noparse][[/noparse]i],_crc) ' Update _crc with each byte
      TSc.tx(Packet[noparse][[/noparse]i])                 ' Send the byte 
                                     ' Invert or adjust CRC as necessary
    crcl  :=  !(_crc & $00FF)        ' Bottom 8 bits into crc low & invert      
    crch  :=  !(_crc >> 8)           ' Top 8 bits into crc High & invert 
    
    TSc.tx(crcl)                     ' complete transmission with last two CRC bytes
    TSc.tx(crch)

Pri UpdateCRC(data,crc):newcrc|i,icrc

  Repeat i from 0 to 7                ' go around for each bit
    if ((crc ^ data) & $01)
      crc := crc >> 1
      crc := crc ^ $8408              ' $8408 is the 'polynomial'
    else
      crc := crc >> 1
    data := data >> 1
      
  return crc & $FFFF





▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Signature space for rent!
Send $1 to CannibalRobotics.com.

Comments

  • Dave HeinDave Hein Posts: 6,347
    edited 2010-04-29 21:58
    It looks like you found the solution.· Your data is bit-reversed relative to Rayman's YMODEM data, which is why your polynomial is $8408 instead of $1021.· You also have to initialize the CRC to $ffff instead of 0.· Eventhough you already found the answer I am attaching my code that shows the solution as well since I spent several minutes playing around with it.· The C code is tested an produces the correct result.· I haven't tested the converted Spin code, but it should work in theory.

    Dave
    c
    c
    844B
  • scanlimescanlime Posts: 106
    edited 2010-04-29 22:33
    If you want more speed in about the same amount of memory, you could use a small 16-entry lookup table, to process one nybble at a time rather than one bit.

    "pycrc" is a pretty handy tool that can calculate lookup tables (and generate sample C code) for just about any flavor of CRC:

    www.tty1.net/pycrc/

    --Micah
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2010-04-30 14:26
    You know, I worked with rayman's code for a long time trying all of the variants of the polynomial and inverted and XOR'd the outputs. I could never get it to work with the display I am using. I know his code does work in it's application. Since this was becoming a monumentally frustrating to me, I finally just adapted the C routine provided by CrystalFontz. I noticed the bit reversal and honestly, I was doubtful it would work but on the first run it worked.
    It's strange, mathematically they should both produce the same result but I never could make it happen.
    Go figure...
    As for speed, the application is not a big data monster - it's a control application that sends 20 byte packets for display data in response to human button events. CRC is calculated by one cog and the results passed to a modified FullDuplexSerialExtended running at 19200. I have not done the math but since I've got small packets I'm pretty sure the the serial transmission is taking up most of the time here and I'm big on the simplicity.
    Thanks for the input!
    Jim-

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Signature space for rent!
    Send $1 to CannibalRobotics.com.
  • Dave HeinDave Hein Posts: 6,347
    edited 2010-04-30 15:56
    I ran a timing test on Rayman's CRC code to understand why my receive buffer was overflowing at high baud rates.· I modified FDS by adding an rxfill method that fills the serial RX buffer with a constant value for testing.· I ran timing tests on the following two loops.

    · ser.rxfill("A", 10)
    · repeat j from 0 to 9
    ··· i := ser.rx
    ··· crc := UpdateCRC(i, crc)
    ··· pdata[noparse][[/noparse]j] := i

    · ser.rxfill("A", 10)
    · repeat j from 0 to 9
    ··· i := ser.rx
    ··· pdata[noparse][[/noparse]j] := i

    The first loop takes about 400 usec per byte.· The second loop is 5 times faster at about 80 usec per byte.· This corresponds to baud rates of 25,000 and 125,000.· This means you could compute the CRC "real-time" while receiving data at 19.2 and below.· At higher rates you would need to compute the CRC after receiving the data packet, and depend on ACKs to flow control the transmitter.· BTW, my tests were run with a system clock of 80 MHz.

    Dave
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2010-05-01 18:47
    Good to know where that boundary lives - the device has a higher baud setting but it's above those speeds.
    Thanks for the data!
    Jim-

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Signature space for rent!
    Send $1 to CannibalRobotics.com.
Sign In or Register to comment.