Steal tunerstudio files from RusEFI (#71)

* Steal tunerstudio files from RusEFI

(cherry picked from commit dcba04fbd3)

* Steal crc32 files from RusEFI

(cherry picked from commit bfe88b5297)

* fix TS steal

(cherry picked from commit a77b9761da)

* fix crc32

(cherry picked from commit cdb4df09f6)

* TS stealed from RE

(cherry picked from commit ff470e1340)

* Steal TS

(cherry picked from commit d11406edc2)

* Steal Thread Controller

(cherry picked from commit 2aa5bbd571)

* Update TunerStudio protocol files

(cherry picked from commit 58f14216ec)

* byteswap.h

(cherry picked from commit 581d647fd4)

* bugfix

* one more file to compile, another file not ready - removing from this PR

* removing more from this PR

Co-authored-by: Andrey Gusakov <dron0gus@gmail.com>
Co-authored-by: rusefillc <sdfsdfqsf2334234234>
This commit is contained in:
rusefillc 2022-06-29 04:29:40 -04:00 committed by GitHub
parent 8269687295
commit ccb790f532
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 573 additions and 2 deletions

View File

@ -125,7 +125,8 @@ LDSCRIPT=app.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(ALLCSRC) $(BOARDDIR)/board.c
CSRC = $(ALLCSRC) $(BOARDDIR)/board.c \
util/math/crc.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
@ -145,6 +146,8 @@ CPPSRC = $(ALLCPPSRC) \
pump_control.cpp \
uart.cpp \
interpolation.cpp \
console/binary/tunerstudio_io_serial.cpp \
console/binary/tunerstudio_io.cpp \
main.cpp
# List ASM source files here.
@ -154,7 +157,13 @@ ASMSRC = $(ALLASMSRC)
ASMXSRC = $(ALLXASMSRC)
# Inclusion directories.
INCDIR = $(CONFDIR) $(ALLINC) boards/ $(BOARDDIR)/io/
INCDIR = $(CONFDIR) \
$(ALLINC) \
util/ \
util/math/ \
console/binary/ \
boards/ \
$(BOARDDIR)/io/
# Define C warning options here.
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes

View File

@ -0,0 +1,41 @@
/**
* @file tunerstudio_impl.h
*/
#pragma once
#include <cstdint>
#include <cstddef>
struct TsChannelBase;
typedef enum {
TS_PLAIN = 0,
TS_CRC = 1
} ts_response_format_e;
class TunerStudioBase {
public:
protected:
virtual void cmdOutputChannels(TsChannelBase* tsChannel, uint16_t offset, uint16_t count) = 0;
};
class TunerStudio : public TunerStudioBase {
public:
int handleCrcCommand(TsChannelBase* tsChannel, char *data, int incomingPacketSize);
bool handlePlainCommand(TsChannelBase* tsChannel, uint8_t command);
void cmdOutputChannels(TsChannelBase* tsChannel, uint16_t offset, uint16_t count) override;
void handleQueryCommand(TsChannelBase* tsChannel, ts_response_format_e mode);
void handleExecuteCommand(TsChannelBase* tsChannel, char *data, int incomingPacketSize);
void handlePageSelectCommand(TsChannelBase *tsChannel, ts_response_format_e mode);
void handleWriteChunkCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count,
void *content);
void handleCrc32Check(TsChannelBase *tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count);
void handleWriteValueCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint8_t value);
void handlePageReadCommand(TsChannelBase* tsChannel, ts_response_format_e mode, uint16_t offset, uint16_t count);
private:
void sendErrorCode(TsChannelBase* tsChannel, uint8_t code);
};

View File

@ -0,0 +1,121 @@
/**
* @file tunerstudio_io.cpp
*
* @date Mar 8, 2015
* @author Andrey Belomutskiy, (c) 2012-2020
*/
/* memcpy */
#include <cstring>
#include "tunerstudio_io.h"
#include "crc.h"
#include "byteswap.h"
size_t TsChannelBase::read(uint8_t* buffer, size_t size) {
return readTimeout(buffer, size, SR5_READ_TIMEOUT);
}
#define isBigPacket(size) ((size) > BLOCKING_FACTOR + 7)
void TsChannelBase::copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size) {
auto scratchBuffer = this->scratchBuffer;
// don't transmit too large a buffer
chDbgAssert(!isBigPacket(size), "copyAndWriteSmallCrcPacket tried to transmit too large a packet");
// If transmitting data, copy it in to place in the scratch buffer
// We want to prevent the data changing itself (higher priority threads could write
// tsOutputChannels) during the CRC computation. Instead compute the CRC on our
// local buffer that nobody else will write.
if (size) {
memcpy(scratchBuffer + 3, buf, size);
}
crcAndWriteBuffer(responseCode, size);
}
void TsChannelBase::crcAndWriteBuffer(uint8_t responseCode, size_t size) {
chDbgAssert(!isBigPacket(size), "crcAndWriteBuffer tried to transmit too large a packet");
auto scratchBuffer = this->scratchBuffer;
// Index 0/1 = packet size (big endian)
*(uint16_t*)scratchBuffer = SWAP_UINT16(size + 1);
// Index 2 = response code
scratchBuffer[2] = responseCode;
// CRC is computed on the responseCode and payload but not length
uint32_t crc = crc32(&scratchBuffer[2], size + 1); // command part of CRC
// Place the CRC at the end
*reinterpret_cast<uint32_t*>(&scratchBuffer[size + 3]) = SWAP_UINT32(crc);
// Write to the underlying stream
write(reinterpret_cast<uint8_t*>(scratchBuffer), size + 7, true);
flush();
}
void TsChannelBase::writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size) {
uint8_t headerBuffer[3];
uint8_t crcBuffer[4];
*(uint16_t*)headerBuffer = SWAP_UINT16(size + 1);
*(uint8_t*)(headerBuffer + 2) = responseCode;
// Command part of CRC
uint32_t crc = crc32((void*)(headerBuffer + 2), 1);
// Data part of CRC
crc = crc32inc((void*)buf, crc, size);
*(uint32_t*)crcBuffer = SWAP_UINT32(crc);
// Write header
write(headerBuffer, sizeof(headerBuffer), false);
// If data, write that
if (size) {
write(buf, size, false);
}
// Lastly the CRC footer
write(crcBuffer, sizeof(crcBuffer), true);
flush();
}
TsChannelBase::TsChannelBase(const char *name) {
this->name = name;
}
void TsChannelBase::assertPacketSize(size_t size, bool allowLongPackets) {
chDbgAssert(!(isBigPacket(size) && !allowLongPackets), "tried to send disallowed long packet");
}
/**
* Adds size to the beginning of a packet and a crc32 at the end. Then send the packet.
*/
void TsChannelBase::writeCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size, bool allowLongPackets) {
// don't transmit a null buffer...
if (!buf) {
size = 0;
}
assertPacketSize(size, allowLongPackets);
if (isBigPacket(size)) {
// for larger packets we do not use a buffer for CRC calculation meaning data is now allowed to modify while pending
writeCrcPacketLarge(responseCode, buf, size);
} else {
// for small packets we use a buffer for CRC calculation
copyAndWriteSmallCrcPacket(responseCode, buf, size);
}
}
void TsChannelBase::sendResponse(ts_response_format_e mode, const uint8_t * buffer, int size, bool allowLongPackets /* = false */) {
if (mode == TS_CRC) {
writeCrcPacket(TS_RESPONSE_OK, buffer, size, allowLongPackets);
} else {
if (size > 0) {
write(buffer, size, true);
flush();
}
}
}

View File

@ -0,0 +1,209 @@
/**
* @file tunerstudio_io.h
* @file TS protocol commands and methods are here
*
* @date Mar 8, 2015
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
/* to get ChibiOS hal config options */
#include "hal.h"
#include "tunerstudio_impl.h"
/* TODO: find better place */
#define BLOCKING_FACTOR 256
/* TODO: From autogenerated, rework! */
#define TS_BURN_COMMAND 'B'
#define TS_BURN_COMMAND_char B
#define TS_CHUNK_WRITE_COMMAND 'C'
#define TS_CHUNK_WRITE_COMMAND_char C
#define ts_command_e_TS_BENCH_CATEGORY 22
#define ts_command_e_TS_CLEAR_WARNINGS 17
#define ts_command_e_TS_COMMAND_1 1
#define ts_command_e_TS_COMMAND_11 11
#define ts_command_e_TS_COMMAND_12 12
#define ts_command_e_TS_COMMAND_13 13
#define ts_command_e_TS_COMMAND_14 14
#define ts_command_e_TS_COMMAND_15 15
#define ts_command_e_TS_COMMAND_16 16
#define ts_command_e_TS_COMMAND_4 4
#define ts_command_e_TS_COMMAND_5 5
#define ts_command_e_TS_COMMAND_9 9
#define ts_command_e_TS_CRAZY 32
#define ts_command_e_TS_DEBUG_MODE 0
#define ts_command_e_TS_GRAB_PEDAL_UP 6
#define ts_command_e_TS_GRAB_PEDAL_WOT 7
#define ts_command_e_TS_GRAB_TPS_CLOSED 2
#define ts_command_e_TS_GRAB_TPS_WOT 3
#define ts_command_e_TS_IGNITION_CATEGORY 18
#define ts_command_e_TS_INJECTOR_CATEGORY 19
#define ts_command_e_TS_RESET_TLE8888 8
#define ts_command_e_TS_UNUSED_23 23
#define ts_command_e_TS_UNUSED_25 25
#define ts_command_e_TS_UNUSED_26 26
#define ts_command_e_TS_UNUSED_27 27
#define ts_command_e_TS_UNUSED_28 28
#define ts_command_e_TS_UNUSED_29 29
#define ts_command_e_TS_UNUSED_30 30
#define ts_command_e_TS_UNUSED_31 31
#define ts_command_e_TS_UNUSED_CJ125_CALIB 24
#define ts_command_e_TS_WIDEBAND 21
#define ts_command_e_TS_WRITE_FLASH 10
#define ts_command_e_TS_X14 20
#define TS_COMMAND_F 'F'
#define TS_COMMAND_F_char F
#define TS_COMPOSITE_DISABLE 2
#define TS_COMPOSITE_ENABLE 1
#define TS_CRC_CHECK_COMMAND 'k'
#define TS_CRC_CHECK_COMMAND_char k
#define TS_EXECUTE 'E'
#define TS_EXECUTE_char E
#define TS_FILE_VERSION 20210312
#define TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY '8'
#define TS_GET_COMPOSITE_BUFFER_DONE_DIFFERENTLY_char 8
#define TS_GET_CONFIG_ERROR 'e'
#define TS_GET_CONFIG_ERROR_char e
#define TS_GET_FIRMWARE_VERSION 'V'
#define TS_GET_FIRMWARE_VERSION_char V
#define TS_GET_LOGGER_GET_BUFFER 'L'
#define TS_GET_LOGGER_GET_BUFFER_char L
#define TS_GET_OUTPUTS_SIZE '4'
#define TS_GET_OUTPUTS_SIZE_char 4
#define TS_GET_STRUCT '9'
#define TS_GET_STRUCT_char 9
#define TS_GET_TEXT 'G'
#define TS_GET_TEXT_char G
#define TS_HELLO_COMMAND 'S'
#define TS_HELLO_COMMAND_char S
#define TS_IO_TEST_COMMAND 'Z'
#define TS_IO_TEST_COMMAND_char Z
#define TS_ONLINE_PROTOCOL 'z'
#define TS_ONLINE_PROTOCOL_char z
#define TS_OUTPUT_COMMAND 'O'
#define TS_OUTPUT_COMMAND_char O
#define TS_PAGE_COMMAND 'P'
#define TS_PAGE_COMMAND_char P
#define TS_PERF_TRACE_BEGIN '_'
#define TS_PERF_TRACE_BEGIN_char _
#define TS_PERF_TRACE_GET_BUFFER 'b'
#define TS_PERF_TRACE_GET_BUFFER_char b
#define TS_PROTOCOL "001"
#define TS_QUERY_COMMAND 'Q'
#define TS_QUERY_COMMAND_char Q
#define TS_READ_COMMAND 'R'
#define TS_READ_COMMAND_char R
#define TS_RESPONSE_BURN_OK 4
#define TS_RESPONSE_COMMAND_OK 7
#define TS_RESPONSE_CRC_FAILURE 0x82
#define TS_RESPONSE_FRAMING_ERROR 0x8D
#define TS_RESPONSE_OK 0
#define TS_RESPONSE_OUT_OF_RANGE 0x84
#define TS_RESPONSE_UNDERRUN 0x80
#define TS_RESPONSE_UNRECOGNIZED_COMMAND 0x83
#define TS_SET_LOGGER_SWITCH 'l'
#define TS_SET_LOGGER_SWITCH_char l
#define TS_SINGLE_WRITE_COMMAND 'W'
#define TS_SINGLE_WRITE_COMMAND_char W
#define TS_TEST_COMMAND 't'
#define TS_TEST_COMMAND_char t
#define TS_TOTAL_OUTPUT_SIZE 1016
class TsChannelBase {
public:
TsChannelBase(const char *name);
// Virtual functions - implement these for your underlying transport
virtual void write(const uint8_t* buffer, size_t size, bool isEndOfPacket = false) = 0;
virtual size_t readTimeout(uint8_t* buffer, size_t size, int timeout) = 0;
// These functions are optional to implement, not all channels need them
virtual void flush() { }
virtual bool isConfigured() const { return true; }
virtual bool isReady() const { return true; }
virtual void stop() { }
// Base functions that use the above virtual implementation
size_t read(uint8_t* buffer, size_t size);
#ifdef EFI_CAN_SERIAL
virtual // CAN device needs this function to be virtual for small-packet optimization
#endif
void writeCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size, bool allowLongPackets = false);
void sendResponse(ts_response_format_e mode, const uint8_t * buffer, int size, bool allowLongPackets = false);
/**
* See 'blockingFactor' in rusefi.ini
*/
char scratchBuffer[BLOCKING_FACTOR + 30];
const char *name;
void assertPacketSize(size_t size, bool allowLongPackets);
void crcAndWriteBuffer(uint8_t responseCode, size_t size);
void copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size);
private:
void writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size);
};
// This class represents a channel for a physical async serial poart
class SerialTsChannelBase : public TsChannelBase {
public:
SerialTsChannelBase(const char *name) : TsChannelBase(name) {};
// Open the serial port with the specified baud rate
virtual void start(uint32_t baud) = 0;
};
#if HAL_USE_SERIAL
// This class implements a ChibiOS Serial Driver
class SerialTsChannel : public SerialTsChannelBase {
public:
SerialTsChannel(SerialDriver& driver) : SerialTsChannelBase("Serial"), m_driver(&driver) { }
void start(uint32_t baud) override;
void stop() override;
void write(const uint8_t* buffer, size_t size, bool isEndOfPacket) override;
size_t readTimeout(uint8_t* buffer, size_t size, int timeout) override;
private:
SerialDriver* const m_driver;
};
#endif // HAL_USE_SERIAL
#if HAL_USE_UART
// This class implements a ChibiOS UART Driver
class UartTsChannel : public SerialTsChannelBase {
public:
UartTsChannel(UARTDriver& driver) : SerialTsChannelBase("UART"), m_driver(&driver) { }
void start(uint32_t baud) override;
void stop() override;
void write(const uint8_t* buffer, size_t size, bool isEndOfPacket) override;
size_t readTimeout(uint8_t* buffer, size_t size, int timeout) override;
protected:
UARTDriver* const m_driver;
UARTConfig m_config;
};
#endif // HAL_USE_UART
#define CRC_VALUE_SIZE 4
// todo: double-check this
#define CRC_WRAPPING_SIZE (CRC_VALUE_SIZE + 3)
// that's 1 second
#define BINARY_IO_TIMEOUT TIME_MS2I(1000)
// that's 1 second
#define SR5_READ_TIMEOUT TIME_MS2I(1000)
void startSerialChannels();
SerialTsChannelBase* getBluetoothChannel();
void startCanConsole();
void sendOkResponse(TsChannelBase *tsChannel, ts_response_format_e mode);

View File

@ -0,0 +1,61 @@
/**
* Implementation for hardware-serial TunerStudio ports
*/
#include "tunerstudio_io.h"
#include "hal.h"
#if HAL_USE_SERIAL
void SerialTsChannel::start(uint32_t baud) {
SerialConfig cfg = {
.speed = baud,
.cr1 = 0,
.cr2 = USART_CR2_STOP1_BITS | USART_CR2_LINEN,
.cr3 = 0
};
sdStart(m_driver, &cfg);
}
void SerialTsChannel::stop() {
sdStop(m_driver);
}
void SerialTsChannel::write(const uint8_t* buffer, size_t size, bool) {
chnWriteTimeout(m_driver, buffer, size, BINARY_IO_TIMEOUT);
}
size_t SerialTsChannel::readTimeout(uint8_t* buffer, size_t size, int timeout) {
return chnReadTimeout(m_driver, buffer, size, timeout);
}
#endif // HAL_USE_SERIAL
#if (HAL_USE_UART == TRUE) && (UART_USE_WAIT == TRUE)
void UartTsChannel::start(uint32_t baud) {
m_config.txend1_cb = NULL;
m_config.txend2_cb = NULL;
m_config.rxend_cb = NULL;
m_config.rxchar_cb = NULL;
m_config.rxerr_cb = NULL;
m_config.timeout_cb = NULL;
m_config.speed = baud;
m_config.cr1 = 0;
m_config.cr2 = 0/*USART_CR2_STOP1_BITS*/ | USART_CR2_LINEN;
m_config.cr3 = 0;
uartStart(m_driver, &m_config);
}
void UartTsChannel::stop() {
uartStop(m_driver);
}
void UartTsChannel::write(const uint8_t* buffer, size_t size, bool) {
uartSendTimeout(m_driver, &size, buffer, BINARY_IO_TIMEOUT);
}
size_t UartTsChannel::readTimeout(uint8_t* buffer, size_t size, int timeout) {
uartReceiveTimeout(m_driver, &size, buffer, timeout);
return size;
}
#endif // HAL_USE_UART

14
firmware/util/byteswap.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
// http://en.wikipedia.org/wiki/Endianness
static inline uint16_t SWAP_UINT16(uint16_t x)
{
return ((x << 8) | (x >> 8));
}
static inline uint32_t SWAP_UINT32(uint32_t x)
{
return (((x >> 24) & 0x000000ff) | ((x << 8) & 0x00ff0000) |
((x >> 8) & 0x0000ff00) | ((x << 24) & 0xff000000));
}

94
firmware/util/math/crc.c Normal file
View File

@ -0,0 +1,94 @@
/**
* @file crc.c
* @date Sep 20, 2013
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "crc.h"
static const uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb,
0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e,
0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808,
0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162,
0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49,
0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc,
0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3,
0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d,
0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a,
0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14,
0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b,
0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee,
0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
/**
* Online CRC calculator:
* http://www.zorc.breitbandkatze.de/crc.html
*/
uint32_t crc32(const void *buf, uint32_t size) {
return crc32inc(buf, 0, size);
}
uint32_t crc32inc(const void *buf, uint32_t crc, uint32_t size) {
const uint8_t *p;
p = buf;
crc = crc ^ 0xFFFFFFFF;
while (size--) {
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFF;
}
/**
* http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
* https://stackoverflow.com/questions/38639423/understanding-results-of-crc8-sae-j1850-normal-vs-zero
* j1850 SAE crc8
*/
uint8_t crc8(const uint8_t *data, uint8_t len) {
uint8_t crc = 0;
if (data == 0)
return 0;
crc ^= 0xff;
while (len--) {
crc ^= *data++;
for (unsigned k = 0; k < 8; k++)
crc = crc & 0x80 ? (crc << 1) ^ 0x1d : crc << 1;
}
crc &= 0xff;
crc ^= 0xff;
return crc;
}

22
firmware/util/math/crc.h Normal file
View File

@ -0,0 +1,22 @@
/**
* @file crc.h
*
* @date Sep 20, 2013
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
uint8_t crc8(const uint8_t * buf, uint8_t len);
uint32_t crc32(const void *buf, uint32_t size);
uint32_t crc32inc(const void *buf, uint32_t crc, uint32_t size);
#ifdef __cplusplus
}
#endif /* __cplusplus */