EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

CRC Kermit problem

Started by Ed April 4, 2009
I found a C routine that calculates the CRC correctly
OnCrctst() is a button to run it.
I need a 8051 ASM routine to do the same thing or similar
I can only find a few PIC routines which I cannot seen to follow.
Please, someone help me.....
Ed
============================================================================

#define                 P_KERMIT    0x8408
unsigned short          update_crc_kermit(unsigned short crc, char c);
static int              crc_tabkermit_init = FALSE;
static unsigned short   crc_tabkermit[256];
static void             init_crckermit_tab( void );

void CEfloppyDlg::OnCrctst()
{
  int i, j;
  char ed[10];
  unsigned char dstr[20];

  dstr[0]=0x30;    //known data string 02 30 30 30 33 46 4F 21 20 20 03 68 
D5
  dstr[1]=0x30;    //02 is not processed for CRC
  dstr[2]=0x30;    //03 is string end and is included
  dstr[3]=0x33;    //68 D5 is CRC Kermit and does calculate correctly
  dstr[4]=0x46;    //with this routine
  dstr[5]=0x4f;
  dstr[6]=0x21;
  dstr[7]=0x20;
  dstr[8]=0x20;
  dstr[9]=0x03;
  crc = 0x0000;
  for (i=0; i<10; i++){
    j=update_crc_kermit(crc, dstr[i]);
    crc=j;
  }
  _itoa(crc, ed, 16);  //convert answer to ascii string
  AfxMessageBox(ed);   //display results with correct CRC value
}

unsigned short update_crc_kermit( unsigned short crc, char c )
{
  unsigned short tmp, short_c;

  short_c = 0x00ff & (unsigned short) c;
  if ( ! crc_tabkermit_init )
    init_crckermit_tab();
  tmp =  crc ^ short_c;
  crc = (crc >> 8) ^ crc_tabkermit[ tmp & 0xff ];

  return crc;
}

static void init_crckermit_tab( void )
{
  int i, j;
  unsigned short crc, c;

  for (i=0; i<256; i++) {
    crc = 0;
    c   = (unsigned short) i;
    for (j=0; j<8; j++) {
      if ( (crc ^ c) & 0x0001 )
        crc = ( crc >> 1 ) ^ P_KERMIT;
      else
        crc =   crc >> 1;
      c = c >> 1;
    }
    crc_tabkermit[i] = crc;
  }
  crc_tabkermit_init = TRUE;
}


On Sat, 4 Apr 2009 11:08:31 -0500, "Ed" <ed@ed.com> wrote:

>I found a C routine that calculates the CRC correctly >OnCrctst() is a button to run it. >I need a 8051 ASM routine to do the same thing or similar
You can probably adapt one of several routines here: http://www.8052.com/codelib -- Dan Henry
"Ed" <ed@ed.com> wrote in message 
news:N8adnSEFHtxjGErUnZ2dnUVZ_jyWnZ2d@giganews.com...
>I found a C routine that calculates the CRC correctly > OnCrctst() is a button to run it. > I need a 8051 ASM routine to do the same thing or similar > I can only find a few PIC routines which I cannot seen to follow. > Please, someone help me..... > Ed > ============================================================================ > > #define P_KERMIT 0x8408 > unsigned short update_crc_kermit(unsigned short crc, char c); > static int crc_tabkermit_init = FALSE; > static unsigned short crc_tabkermit[256]; > static void init_crckermit_tab( void ); > > void CEfloppyDlg::OnCrctst() > { > int i, j; > char ed[10]; > unsigned char dstr[20]; > > dstr[0]=0x30; //known data string 02 30 30 30 33 46 4F 21 20 20 03 68 > D5 > dstr[1]=0x30; //02 is not processed for CRC > dstr[2]=0x30; //03 is string end and is included > dstr[3]=0x33; //68 D5 is CRC Kermit and does calculate correctly > dstr[4]=0x46; //with this routine > dstr[5]=0x4f; > dstr[6]=0x21; > dstr[7]=0x20; > dstr[8]=0x20; > dstr[9]=0x03; > crc = 0x0000; > for (i=0; i<10; i++){ > j=update_crc_kermit(crc, dstr[i]); > crc=j; > } > _itoa(crc, ed, 16); //convert answer to ascii string > AfxMessageBox(ed); //display results with correct CRC value > } > > unsigned short update_crc_kermit( unsigned short crc, char c ) > { > unsigned short tmp, short_c; > > short_c = 0x00ff & (unsigned short) c; > if ( ! crc_tabkermit_init ) > init_crckermit_tab(); > tmp = crc ^ short_c; > crc = (crc >> 8) ^ crc_tabkermit[ tmp & 0xff ]; > > return crc; > } > > static void init_crckermit_tab( void ) > { > int i, j; > unsigned short crc, c; > > for (i=0; i<256; i++) { > crc = 0; > c = (unsigned short) i; > for (j=0; j<8; j++) { > if ( (crc ^ c) & 0x0001 ) > crc = ( crc >> 1 ) ^ P_KERMIT; > else > crc = crc >> 1; > c = c >> 1; > } > crc_tabkermit[i] = crc; > } > crc_tabkermit_init = TRUE; > } > >
Assuming you are using (or at least have access to) a C compiler, look at the assembly code produced. Tweak things. For example, crc_tabkermit_init should be a bit, but better to build the table first. And then split the table into hi-byte and low-byte and place it in the code segment so you can use the strange 8051 indexing mode. But if you do those things, you really won't need to use assembly code. Eventually, the C looks like: CrcT CRC_AddByte(CrcT Crc, u8 Byte) { Byte ^= Crc.Field.Hi; Crc.Field.Hi = CrcTable_hi[Byte] ^ Crc.Field.Lo; Crc.Field.Lo = CrcTable_lo[Byte]; return Crc; } You can use pycrc (http://www.tty1.net/pycrc/) to generate code and get: /** * \file Kermit.c * Functions and types for CRC checks. * * Generated on Mon Apr 06 10:49:37 2009, * by pycrc v0.7.1, http://www.tty1.net/pycrc/ * using the configuration: * Width = 16 * Poly = 0x1021 * XorIn = 0x0000 * ReflectIn = True * XorOut = 0x0000 * ReflectOut = True * Algorithm = table-driven * Direct = True *****************************************************************************/ #include "Kermit.h" #include <stdint.h> #include <stdlib.h> /** * Static table used for the table_driven implementation. *****************************************************************************/ static const crc_t crc_table[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; /** * Reflect all bits of a \a data word of \a data_len bytes. * * \param data The data word to be reflected. * \param data_len The width of \a data expressed in number of bits. * \return The reflected data. *****************************************************************************/ long crc_reflect(long data, size_t data_len) { unsigned int i; long ret; ret = data & 0x01; for (i = 1; i < data_len; i++) { data >>= 1; ret = (ret << 1) | (data & 0x01); } return ret; } /** * Update the crc value with new data. * * \param crc The current crc value. * \param data Pointer to a buffer of \a data_len bytes. * \param data_len Number of bytes in the \a data buffer. * \return The updated crc value. *****************************************************************************/ crc_t crc_update(crc_t crc, const unsigned char *data, size_t data_len) { unsigned int tbl_idx; while (data_len--) { tbl_idx = (crc ^ *data) & 0xff; crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffff; data++; } return crc & 0xffff; }

The 2024 Embedded Online Conference