#ifndef _TT_CRC_H_
#define _TT_CRC_H_

#include <stdint.h>
#include <sys/types.h>

/****************************************************************************************************************/

#ifdef WIN32
#define _CRCINLINE /* nuffin */
#else
#define _CRCINLINE inline __attribute__((__always_inline__))
#endif

/****************************************************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif

extern const uint8_t  _libcipher_crc8_table[256];
extern const uint16_t _libcipher_crc16_table[256];
extern const uint32_t _libcipher_crc32_table[256];

unsigned int crc8_buf(const void *buf, size_t len, unsigned int start);
unsigned int crc16_buf(const void *buf, size_t len, unsigned int start);
unsigned int crc16_buf_ccitt(const void *buf, size_t len, unsigned int start);
unsigned int crc32_buf(const void *buf, size_t len, unsigned int start);

unsigned int crc16_byte_modbus(unsigned int ch, unsigned int prev);
unsigned int crc16_buf_modbus(const void *buf, size_t len);

#if defined(__cplusplus)
}
#endif

/****************************************************************************************************************/

static _CRCINLINE unsigned int crc8_byte(unsigned int ch, unsigned int prev) {
  return _libcipher_crc8_table[ch ^ (prev & 0xFF)];
}

// Broken, but still good. Kept for backwards compatibility. Use crc16_byte_ccitt instead.
static _CRCINLINE unsigned int crc16_byte(unsigned int ch, unsigned int prev) {
  unsigned int crc_xor = _libcipher_crc16_table[(prev >> 8) & 0xFF];
  return (((prev << 8) | ch) ^ crc_xor) & 0xFFFF;
}

// CCITT CRC16
static _CRCINLINE unsigned int crc16_byte_ccitt(unsigned int ch, unsigned int prev) {
  return _libcipher_crc16_table[((prev>>8) ^ ch) & 0xFF] ^ ((prev & 0xFF) << 8);
}

static _CRCINLINE unsigned int crc32_byte(unsigned int ch, unsigned int prev) {
  return _libcipher_crc32_table[(prev ^ ch) & 0xFF] ^ (prev >> 8);
}

/****************************************************************************************************************/
#endif
