Add CRC16 with reverse bit order
This commit is contained in:
parent
5c3d6461a1
commit
0d6cba4530
5 changed files with 450 additions and 4 deletions
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ CFLAGS = $(CCFLAGS)
|
|||
|
||||
PRGNAME = metawatch
|
||||
|
||||
MEMBERS = metawatch
|
||||
MEMBERS = metawatch crc16ccitt
|
||||
|
||||
# no need to change anything below this line
|
||||
# ------------------------------------------
|
||||
|
|
367
crc16ccitt.c
Normal file
367
crc16ccitt.c
Normal file
|
@ -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<len; i++) {
|
||||
|
||||
c = (unsigned long)*p++;
|
||||
if (refin)
|
||||
c = reflect(c, 8);
|
||||
|
||||
for (j=0x80; j; j>>=1) {
|
||||
bit = crc & crchighbit;
|
||||
crc<<= 1;
|
||||
if (c & j)
|
||||
crc|= 1;
|
||||
if (bit)
|
||||
crc^= polynom;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<order; i++) {
|
||||
bit = crc & crchighbit;
|
||||
crc <<= 1;
|
||||
if (bit)
|
||||
crc^= polynom;
|
||||
}
|
||||
|
||||
if (refout)
|
||||
crc=reflect(crc, order);
|
||||
crc ^= crcxor;
|
||||
crc &= crcmask;
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned long crcbitbybitfast(unsigned char* p, unsigned long len) {
|
||||
|
||||
// fast bit by bit algorithm without 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_direct;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
c = (unsigned long)*p++;
|
||||
if (refin)
|
||||
c = reflect(c, 8);
|
||||
|
||||
for (j=0x80; j; j>>=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<order; i++) {
|
||||
bit = crc & crchighbit;
|
||||
crc <<= 1;
|
||||
if (bit)
|
||||
crc^= polynom;
|
||||
}
|
||||
crc &= crcmask;
|
||||
crcinit_direct = crc;
|
||||
} else {
|
||||
crcinit_direct = crcinit;
|
||||
crc = crcinit;
|
||||
for (i=0; i<order; i++) {
|
||||
bit = crc & 1;
|
||||
if (bit)
|
||||
crc^= polynom;
|
||||
crc >>= 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<order; i++) {
|
||||
|
||||
bit = crc & crchighbit;
|
||||
crc<<= 1;
|
||||
if (bit) crc^= polynom;
|
||||
}
|
||||
crc&= crcmask;
|
||||
crcinit_direct = crc;
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
crcinit_direct = crcinit;
|
||||
crc = crcinit;
|
||||
for (i=0; i<order; i++) {
|
||||
|
||||
bit = crc & 1;
|
||||
if (bit) crc^= polynom;
|
||||
crc >>= 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
|
7
crc16ccitt.h
Normal file
7
crc16ccitt.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef _CRC16_h
|
||||
#define _CRC16_H
|
||||
|
||||
void crc16ccitt_init(void);
|
||||
unsigned short crc16ccitt (unsigned char *data, int len);
|
||||
|
||||
#endif
|
73
metawatch.c
73
metawatch.c
|
@ -7,23 +7,90 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "metawatch_protocol.h"
|
||||
#include "crc16ccitt.h"
|
||||
|
||||
|
||||
void dump_frame(unsigned char *frame, int len)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<len; i++)
|
||||
fprintf(stderr, "0x%02x ", frame[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
void mw_send_packet(int mw_fd, unsigned char msg_type, unsigned char options, unsigned char *data, unsigned char len)
|
||||
{
|
||||
unsigned short crc;
|
||||
unsigned char frame[64];
|
||||
|
||||
memset(frame, 0, 64);
|
||||
frame[0] = MW_SOF;
|
||||
frame[1] = len + 6;
|
||||
frame[2] = msg_type;
|
||||
frame[3] = options;
|
||||
memcpy(frame+4, data, len);
|
||||
|
||||
crc = crc16ccitt(frame, len+4);
|
||||
*(unsigned short *)(frame+len+4) = crc;
|
||||
|
||||
dump_frame(frame, len+6);
|
||||
|
||||
write(mw_fd, frame, len+6);
|
||||
}
|
||||
|
||||
void mw_set_rtc(int mw_fd, unsigned char clk1224, unsigned char date_fmt)
|
||||
{
|
||||
time_t mtime;
|
||||
struct tm mtm;
|
||||
unsigned short year;
|
||||
unsigned char data[32];
|
||||
|
||||
mtime = time(NULL);
|
||||
localtime_r(&mtime, &mtm);
|
||||
|
||||
year = mtm.tm_year + 1900;
|
||||
data[0] = (year & 0x0f00) >> 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 <devicename>\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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue