mirror of https://github.com/rusefi/wideband.git
Steal tunerstudio files from RusEFI (#71)
* Steal tunerstudio files from RusEFI (cherry picked from commitdcba04fbd3
) * Steal crc32 files from RusEFI (cherry picked from commitbfe88b5297
) * fix TS steal (cherry picked from commita77b9761da
) * fix crc32 (cherry picked from commitcdb4df09f6
) * TS stealed from RE (cherry picked from commitff470e1340
) * Steal TS (cherry picked from commitd11406edc2
) * Steal Thread Controller (cherry picked from commit2aa5bbd571
) * Update TunerStudio protocol files (cherry picked from commit58f14216ec
) * byteswap.h (cherry picked from commit581d647fd4
) * 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:
parent
8269687295
commit
ccb790f532
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
Loading…
Reference in New Issue