#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#define PACKET_LEN (7)
#define NUM_OF_CYCLES (100000)
static unsigned char reverse_table[16] =
{
0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF
};
uint8_t reverse_bits(uint8_t byte)
{
// Reverse the top and bottom nibble then swap them.
return (reverse_table[byte & 0b1111] << 4) | reverse_table[byte >> 4];
}
uint16_t reverse_word(uint16_t word)
{
return ((reverse_bits(word & 0xFF) << 8) | reverse_bits(word >> 8));
}
uint16_t crc16_common(uint8_t *data, uint8_t len, uint16_t poly, uint16_t init,
uint16_t doXor, bool refIn, bool refOut)
{
uint8_t y;
uint16_t crc;
crc = init;
while (len--)
{
if (refIn)
crc = ((uint16_t)reverse_bits(*data++) << 8) ^ crc;
else
crc = ((uint16_t)*data++ << 8) ^ crc;
for (y = 0; y < 8; y++)
{
if (crc & 0x8000)
crc = (crc << 1) ^ poly;
else
crc = crc << 1;
}
}
if (refOut)
crc = reverse_word(crc);
return (crc ^ doXor);
}
uint16_t crc16_ccitt(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x1021, 0xFFFF, 0x0000, false, false);
}
uint16_t crc16_bypass(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x8005, 0x0000, 0x0000, false, false);
}
uint16_t crc16_xmodem(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x1021, 0x0000, 0x0000, false, false);
}
uint16_t crc16_teledisk(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0xA097, 0x0000, 0x0000, false, false);
}
uint16_t crc16_augccitt(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x1021, 0x1d0f, 0x0000, false, false);
}
uint16_t crc16_cdma2000(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0xc867, 0xffff, 0x0000, false, false);
}
uint16_t crc16_dds110(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x8005, 0x800d, 0x0000, false, false);
}
uint16_t crc16_dect(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x0589, 0x0000, 0x0000, false, false);
}
uint16_t crc16_en13757(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x3d65, 0x0000, 0xffff, false, false);
}
uint16_t crc16_t10dif(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x8bb7, 0x0000, 0x0000, false, false);
}
uint16_t crc16_cms(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x8005, 0xFFFF, 0x0000, false, false);
}
uint16_t crc16_modbus(uint8_t *data, uint8_t len)
{
return crc16_common(data, len, 0x8005, 0xFFFF, 0x0000, true, true);
}
bool compare_buf(uint8_t *buf1, uint8_t *buf2)
{
uint8_t x;
for (x = 0; x < PACKET_LEN; x++)
{
if (buf1[x] != buf2[x])
return true;
}
return false;
}
bool method_shuffle(uint8_t *buf)
{
uint8_t i, j;
uint16_t rnd;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
for (i = 0; i < PACKET_LEN; i++)
{
for (j = 0; j < 10; j++)
{
rnd = (uint16_t)rand();
if (rnd % 7 == 0)
buf[i] ^= (1 << (rnd % 8));
}
}
return compare_buf(buf, copy);
}
bool method_bitshift(uint8_t *buf)
{
uint8_t x, i, j;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
x = (uint8_t)(rand() % PACKET_LEN) + 1;
for (j = 0; j < x; j++)
{
i = (uint8_t)(rand() % PACKET_LEN);
if (buf[i] == 0)
buf[i] = 0x01;
else
buf[i] <<= 1;
}
return compare_buf(buf, copy);
}
bool method_packetroll(uint8_t *buf)
{
uint8_t x, i, j;
uint8_t temp;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
x = (uint8_t)(rand() % (PACKET_LEN - 1)) + 1;
for (j = 0; j < x; j++)
{
temp = buf[0];
for (i = 0; i < PACKET_LEN - 1; i++)
buf[i] = buf[i + 1];
buf[PACKET_LEN - 1] = temp;
}
return compare_buf(buf, copy);
}
bool method_shiftright(uint8_t *buf)
{
uint8_t i;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
for (i = 0; i < PACKET_LEN - 1; i++)
buf[i + 1] = buf[i];
buf[0] = 0xff;
return compare_buf(buf, copy);
}
bool method_shiftleft(uint8_t *buf)
{
uint8_t i;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
for (i = 0; i < PACKET_LEN - 1; i++)
buf[i] = buf[i + 1];
buf[PACKET_LEN - 1] = 0xff;
return compare_buf(buf, copy);
}
bool method_zero(uint8_t *buf)
{
uint8_t x, i, j;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
x = (uint8_t)(rand() % PACKET_LEN) + 1;
for (j = 0; j < x; j++)
{
i = (uint8_t)(rand() % PACKET_LEN);
if (buf[i] != 0x00)
buf[i] = 0x00;
else
buf[i] = 0xFF;
}
return compare_buf(buf, copy);
}
bool method_one(uint8_t *buf)
{
uint8_t x, i, j;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
x = (uint8_t)(rand() % PACKET_LEN) + 1;
for (j = 0; j < x; j++)
{
i = (uint8_t)(rand() % PACKET_LEN);
if (buf[i] != 0xFF)
buf[i] = 0xFF;
else
buf[i] = 0x00;
}
return compare_buf(buf, copy);
}
bool method_injection(uint8_t *buf)
{
uint8_t x, i;
uint8_t copy[PACKET_LEN];
memcpy(copy, buf, PACKET_LEN);
x = (uint8_t)(rand() % PACKET_LEN);
for (i = PACKET_LEN - 1; i > x; i--)
{
buf[i] = buf[i - 1];
}
buf[x] = (uint8_t)rand();
return compare_buf(buf, copy);
}
bool method_single(uint8_t *buf)
{
uint8_t x;
x = (uint8_t)(rand() % (PACKET_LEN * 8));
buf[(uint8_t)(x / 8)] ^= (1 << (x % 8));
return true;
}
typedef struct
{
uint16_t crc1;
uint16_t crc2;
uint32_t errors;
uint16_t (*fn)(uint8_t *data, uint8_t len);
char name[32];
} tCRC;
typedef struct
{
bool (*fn)(uint8_t *buf);
char name[32];
} tMethod;
static tMethod methods[] =
{
{method_shuffle, "Shuffle"},
{method_bitshift, "Bit shift"},
{method_packetroll, "Roll packet"},
{method_shiftright, "Right shift"},
{method_shiftleft, "Left shift"},
{method_zero, "Fill zeros"},
{method_one, "Fill ones"},
{method_injection, "Byte injection"},
{method_single, "Single bit"}
};
static tCRC crcs[] =
{
{0, 0, 0, crc16_cms, "CMS"},
{0, 0, 0, crc16_ccitt, "CCITT"},
{0, 0, 0, crc16_augccitt, "AUG-CCITT"},
{0, 0, 0, crc16_bypass, "BYPASS"},
{0, 0, 0, crc16_cdma2000, "CDMA2000"},
{0, 0, 0, crc16_dds110, "DDS-110"},
{0, 0, 0, crc16_dect, "DECT-X"},
{0, 0, 0, crc16_en13757, "EN-13757"},
{0, 0, 0, crc16_modbus, "Modbus"},
{0, 0, 0, crc16_t10dif, "T10-DIF"},
{0, 0, 0, crc16_teledisk, "TELEDISK"},
{0, 0, 0, crc16_xmodem, "XMODEM"}
};
int main(int argc, char * argv[])
{
uint32_t num_of_cycle;
uint32_t num_of_sums;
uint8_t packet[PACKET_LEN];
uint8_t i;
uint8_t m;
//uint8_t buf[8] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
srand(time(NULL));
printf("------------------------- CRC16 comparison -------------------------\n");
num_of_sums = sizeof(crcs) / sizeof(tCRC);
for (m = 0; m < sizeof(methods) / sizeof(tMethod); m++)
{
printf("\r%s:\n", methods[m].name);
for (i = 0; i < num_of_sums; i++)
{
crcs[i].errors = 0;
}
for (num_of_cycle = 0; num_of_cycle < NUM_OF_CYCLES; num_of_cycle++)
{
for (i = 0; i < PACKET_LEN; i++)
packet[i] = (uint8_t)rand();
for (i = 0; i < num_of_sums; i++)
crcs[i].crc1 = crcs[i].fn(packet, PACKET_LEN);
if (!methods[m].fn(packet))
continue;
for (i = 0; i < num_of_sums; i++)
{
crcs[i].crc2 = crcs[i].fn(packet, PACKET_LEN);
if (crcs[i].crc1 == crcs[i].crc2)
crcs[i].errors++;
}
if (num_of_cycle % 1000 == 0)
printf("\r%.2f%%", (float)num_of_cycle / NUM_OF_CYCLES * 100);
}
for (i = 0; i < num_of_sums; i++)
printf("\r %20s: %10d\n", crcs[i].name, crcs[i].errors);
}
return 0;
}
...
воскресенье, 4 ноября 2018 г.
Надежность контрольной суммы CRC16
Подписаться на:
Комментарии к сообщению (Atom)
Комментариев нет:
Отправить комментарий