From: Nils Faerber Date: Tue, 19 Jul 2011 10:31:32 +0000 (+0200) Subject: Add CRC16 with reverse bit order X-Git-Url: https://git.kernelconcepts.de/?p=metawatch.git;a=commitdiff_plain;h=0d6cba45309388fdbe71a25739445f85ac44622b Add CRC16 with reverse bit order --- diff --git a/Makefile b/Makefile index e605bc2..4024ec9 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFLAGS = $(CCFLAGS) PRGNAME = metawatch -MEMBERS = metawatch +MEMBERS = metawatch crc16ccitt # no need to change anything below this line # ------------------------------------------ diff --git a/crc16ccitt.c b/crc16ccitt.c new file mode 100644 index 0000000..d468c80 --- /dev/null +++ b/crc16ccitt.c @@ -0,0 +1,367 @@ +/* + * derived from crctester.c + * original header: + * ---------------------------------------------------------------------------- + * CRC tester v1.3 written on 4th of February 2003 by Sven Reifegerste (zorc/reflex) + * This is the complete compilable C program, consisting only of this .c file. + * No guarantee for any mistakes. + * + * changes to CRC tester v1.2: + * + * - remove unneccessary (!(polynom&1)) test for invalid polynoms + * (now also XMODEM parameters 0x8408 work in c-code as they should) + * + * changes to CRC tester v1.1: + * + * - include an crc&0crcmask after converting non-direct to direct initial + * value to avoid overflow + * + * changes to CRC tester v1.0: + * + * - most int's were replaced by unsigned long's to allow longer input strings + * and avoid overflows and unnecessary type-casting's + * ---------------------------------------------------------------------------- + */ + +static const int order = 16; +static const unsigned long polynom = 0x1021; +static const int direct = 1; +static const unsigned long crcinit = 0xffff; +static const unsigned long crcxor = 0x0000; +static const int refin = 1; +static const int refout = 0; + +// 'order' [1..32] is the CRC polynom order, counted without the leading '1' bit +// 'polynom' is the CRC polynom without leading '1' bit +// 'direct' [0,1] specifies the kind of algorithm: 1=direct, no augmented zero bits +// 'crcinit' is the initial CRC value belonging to that algorithm +// 'crcxor' is the final XOR value +// 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not +// 'refout' [0,1] specifies if the CRC will be reflected before XOR + + +// internal global values: + +static unsigned long crcmask; +static unsigned long crchighbit; +static unsigned long crcinit_direct; +static unsigned long crcinit_nondirect; +static unsigned long crctab[256]; + + +// subroutines + +static unsigned long reflect (unsigned long crc, int bitnum) { + + // reflects the lower 'bitnum' bits of 'crc' + + unsigned long i, j=1, crcout=0; + + for (i=(unsigned long)1<<(bitnum-1); i; i>>=1) { + if (crc & i) crcout|=j; + j<<= 1; + } + return (crcout); +} + + + +static void generate_crc_table(void) +{ + // make CRC lookup table used by table algorithms + + int i, j; + unsigned long bit, crc; + + for (i=0; i<256; i++) { + + crc=(unsigned long)i; + if (refin) crc=reflect(crc, 8); + crc<<= order-8; + + for (j=0; j<8; j++) { + + bit = crc & crchighbit; + crc<<= 1; + if (bit) crc^= polynom; + } + + if (refin) crc = reflect(crc, order); + crc&= crcmask; + crctab[i]= crc; + } +} + + +static unsigned long crctablefast (unsigned char* p, unsigned long len) +{ + // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. + // only usable with polynom orders of 8, 16, 24 or 32. + + unsigned long crc = crcinit_direct; + + if (refin) crc = reflect(crc, order); + + if (!refin) while (len--) crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ *p++]; + else while (len--) crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ *p++]; + + if (refout^refin) crc = reflect(crc, order); + crc^= crcxor; + crc&= crcmask; + + return(crc); +} + +static unsigned long crctable (unsigned char* p, unsigned long len) +{ + // normal lookup table algorithm with augmented zero bytes. + // only usable with polynom orders of 8, 16, 24 or 32. + + unsigned long crc = crcinit_nondirect; + + if (refin) + crc = reflect(crc, order); + + if (!refin) + while (len--) + crc = ((crc << 8) | *p++) ^ crctab[ (crc >> (order-8)) & 0xff]; + else + while (len--) + crc = ((crc >> 8) | (*p++ << (order-8))) ^ crctab[ crc & 0xff]; + + if (!refin) + while (++len < order/8) + crc = (crc << 8) ^ crctab[ (crc >> (order-8)) & 0xff]; + else + while (++len < order/8) + crc = (crc >> 8) ^ crctab[crc & 0xff]; + + if (refout^refin) + crc = reflect(crc, order); + crc^= crcxor; + crc&= crcmask; + + return(crc); +} + + + +unsigned long crcbitbybit(unsigned char* p, unsigned long len) { + + // bit by bit algorithm with augmented zero bytes. + // does not use lookup table, suited for polynom orders between 1...32. + + unsigned long i, j, c, bit; + unsigned long crc = crcinit_nondirect; + + for (i=0; i>=1) { + bit = crc & crchighbit; + crc<<= 1; + if (c & j) + crc|= 1; + if (bit) + crc^= polynom; + } + } + + for (i=0; i>=1) { + bit = crc & crchighbit; + crc <<= 1; + if (c & j) + bit^= crchighbit; + if (bit) + crc^= polynom; + } + } + + if (refout) + crc=reflect(crc, order); + crc^= crcxor; + crc&= crcmask; + + return(crc); +} + +void crc16ccitt_init(void) +{ + int i; + unsigned long bit, crc; + + crcmask = ((((unsigned long)1<<(order-1))-1)<<1)|1; + crchighbit = (unsigned long)1<<(order-1); + + generate_crc_table(); + + if (!direct) { + crcinit_nondirect = crcinit; + crc = crcinit; + for (i=0; i>= 1; + if (bit) + crc|= crchighbit; + } + crcinit_nondirect = crc; + } +} + +unsigned short crc16ccitt (unsigned char *data, int len) +{ + // call CRC algorithms using the CRC parameters above and print result to the console + return crcbitbybitfast((unsigned char *)data, len); +} + +#if 0 +int main() { + + // test program for checking four different CRC computing types that are: + // crcbit(), crcbitfast(), crctable() and crctablefast(), see above. + // parameters are at the top of this program. + // Result will be printed on the console. + + int i; + unsigned long bit, crc; + + + // at first, compute constant bit masks for whole CRC and CRC high bit + + crcmask = ((((unsigned long)1<<(order-1))-1)<<1)|1; + crchighbit = (unsigned long)1<<(order-1); + + + // check parameters + + if (order < 1 || order > 32) { + printf("ERROR, invalid order, it must be between 1..32.\n"); + return(0); + } + + if (polynom != (polynom & crcmask)) { + printf("ERROR, invalid polynom.\n"); + return(0); + } + + if (crcinit != (crcinit & crcmask)) { + printf("ERROR, invalid crcinit.\n"); + return(0); + } + + if (crcxor != (crcxor & crcmask)) { + printf("ERROR, invalid crcxor.\n"); + return(0); + } + + + // generate lookup table + + generate_crc_table(); + + + // compute missing initial CRC value + + if (!direct) { + + crcinit_nondirect = crcinit; + crc = crcinit; + for (i=0; i>= 1; + if (bit) crc|= crchighbit; + } + crcinit_nondirect = crc; + } + + + // call CRC algorithms using the CRC parameters above and print result to the console + + printf("\n"); + printf("CRC tester v1.1 written on 13/01/2003 by Sven Reifegerste (zorc/reflex)\n"); + printf("-----------------------------------------------------------------------\n"); + printf("\n"); + printf("Parameters:\n"); + printf("\n"); + printf(" polynom : 0x%x\n", polynom); + printf(" order : %d\n", order); + printf(" crcinit : 0x%x direct, 0x%x nondirect\n", crcinit_direct, crcinit_nondirect); + printf(" crcxor : 0x%x\n", crcxor); + printf(" refin : %d\n", refin); + printf(" refout : %d\n", refout); + printf("\n"); + printf(" data string : '%s' (%d bytes)\n", string, strlen(string)); + printf("\n"); + printf("Results:\n"); + printf("\n"); + + printf(" crc bit by bit : 0x%x\n", crcbitbybit((unsigned char *)string, strlen(string))); + printf(" crc bit by bit fast : 0x%x\n", crcbitbybitfast((unsigned char *)string, strlen(string))); + if (!(order&7)) printf(" crc table : 0x%x\n", crctable((unsigned char *)string, strlen(string))); + if (!(order&7)) printf(" crc table fast : 0x%x\n", crctablefast((unsigned char *)string, strlen(string))); + + return(0); +} +#endif diff --git a/crc16ccitt.h b/crc16ccitt.h new file mode 100644 index 0000000..d9ade56 --- /dev/null +++ b/crc16ccitt.h @@ -0,0 +1,7 @@ +#ifndef _CRC16_h +#define _CRC16_H + +void crc16ccitt_init(void); +unsigned short crc16ccitt (unsigned char *data, int len); + +#endif diff --git a/metawatch.c b/metawatch.c index 7305b03..c6914ce 100644 --- a/metawatch.c +++ b/metawatch.c @@ -7,23 +7,90 @@ #include #include #include +#include +#include #include "metawatch_protocol.h" +#include "crc16ccitt.h" + + +void dump_frame(unsigned char *frame, int len) +{ + int i; + for (i=0; i> 8; + data[1] = (year & 0x00ff); + data[2] = mtm.tm_mon + 1; + data[3] = mtm.tm_mday; + data[4] = mtm.tm_wday; + data[5] = mtm.tm_hour; + data[6] = mtm.tm_min; + data[7] = mtm.tm_sec; + data[8] = clk1224; + data[9] = date_fmt; + + mw_send_packet(mw_fd, MW_SET_REAL_TIME_CLOCK, 0, data, 10); +} + int main(int argc, char **argv) { - int mwfd; + int mw_fd; if (argc != 2) { fprintf(stderr, "Usage:\n\t%s \n", argv[0]); return 1; }; - mwfd = open(argv[1], O_RDWR); - if (mwfd < 0) { + crc16ccitt_init(); + + mw_fd = open(argv[1], O_RDWR); + if (mw_fd < 0) { perror("open"); return 1; }; + mw_set_rtc(mw_fd, MW_RTC_CLOCK_24HR, MW_RTC_DATE_DDMM); + + fsync(mw_fd); + + close(mw_fd); + return 0; }; diff --git a/metawatch_protocol.h b/metawatch_protocol.h index cae11c9..c08b601 100644 --- a/metawatch_protocol.h +++ b/metawatch_protocol.h @@ -15,6 +15,11 @@ #define MW_GET_REAL_TIME_CLOCK 0x27 #define MW_GET_REAL_TIME_CLOCK_RSP 0x28 +#define MW_RTC_CLOCK_12HR 0x00 +#define MW_RTC_CLOCK_24HR 0x01 +#define MW_RTC_DATE_MMDD 0x00 +#define MW_RTC_DATE_DDMM 0x01 + #define MW_RESERVED 0x32 #define MW_STATUS_CHANGE_EVENT 0x33 #define MW_BUTTON_EVENT_MESSAGE 0x34