Use bits from BSides repo
This commit is contained in:
parent
278055f585
commit
8f1a99fbc1
|
@ -0,0 +1,231 @@
|
|||
//
|
||||
// BSides Badge Serial Bridge Message Format
|
||||
//
|
||||
#ifndef __SERIALBRIDGE_MESSAGES_H
|
||||
#define __SERIALBRIDGE_MESSAGES_H
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <CircularBuffer.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define SERIALBRIDGE_MESSAGE_MAGIC 0xdeadcafe
|
||||
|
||||
#define SERIALBRIDGE_MESSAGE_SIZE 64 // bytes
|
||||
#define SERIALBRIDGE_MESSAGE_V1 1
|
||||
#define SERIALBRIDGE_MESSAGE_CURRENT_VERSION SERIALBRIDGE_MESSAGE_V1
|
||||
|
||||
#define SERIALBRIDGE_MESSAGE_QUEUE_MAX_SIZE 10
|
||||
|
||||
/**
|
||||
* Serial bridge message types
|
||||
*/
|
||||
typedef enum {
|
||||
SERIALBRIDGE_MESSAGE_TYPE_MIN = 0,
|
||||
// VBat request/response
|
||||
VBATRequest = SERIALBRIDGE_MESSAGE_TYPE_MIN,
|
||||
VBATResponse,
|
||||
// IRdA send/receive
|
||||
IRdASend,
|
||||
IRdACheck,
|
||||
IRdARecv,
|
||||
// IMU event
|
||||
IMUEvent,
|
||||
// Audio event
|
||||
AudioEvent,
|
||||
// Wi-Fi event
|
||||
WiFiEvent,
|
||||
// Bluetooth Event
|
||||
BluetoothEvent,
|
||||
// SD card event
|
||||
SDEvent,
|
||||
// SAO I2C send/receive
|
||||
SAOWireSend,
|
||||
SAOWireRequest,
|
||||
// SAO GPIO read/set
|
||||
SAOGPIOGet,
|
||||
SAOGPIOSet,
|
||||
SAOGPIOVal,
|
||||
// Set RGB LED state
|
||||
LEDSet,
|
||||
// Capsense pad state
|
||||
Capsense,
|
||||
// Enable/disable direct capsense feedback to LEDs
|
||||
CapsenseFeedbackEnable,
|
||||
// D-pad button state
|
||||
DPad,
|
||||
// Call to suspend the SAMD for power saving
|
||||
SAMD_Suspend,
|
||||
// Diagnostics ping-pong
|
||||
Diagnostics_PING,
|
||||
Diagnostics_PONG,
|
||||
// ACK/NACK of serial send
|
||||
Message_ACK,
|
||||
Message_NACK,
|
||||
SERIALBRIDGE_MESSAGE_TYPE_MAX,
|
||||
} MessageType_Enum;
|
||||
|
||||
typedef uint8_t MessageType;
|
||||
|
||||
/**
|
||||
* Serial bridge message header
|
||||
*/
|
||||
typedef struct SerialMessageHeader {
|
||||
uint32_t magic;
|
||||
uint8_t seqNo;
|
||||
uint8_t version;
|
||||
MessageType type;
|
||||
uint32_t crc32;
|
||||
} __attribute((packed)) SerialMessageHeader;
|
||||
|
||||
#define SERIALBRIDGE_MESSAGE_DATA_SIZE_MAX (SERIALBRIDGE_MESSAGE_SIZE - sizeof(SerialMessageHeader))
|
||||
|
||||
// Padding type to make all messages the same size
|
||||
typedef struct padding {
|
||||
uint8_t padding[SERIALBRIDGE_MESSAGE_DATA_SIZE_MAX];
|
||||
} __attribute((packed)) padding;
|
||||
|
||||
/*
|
||||
* VBAT battery value
|
||||
*/
|
||||
typedef struct VBATValue {
|
||||
// The value of the battery voltage
|
||||
float value;
|
||||
} __attribute((packed)) VBATValue;
|
||||
|
||||
/**
|
||||
* IR Code
|
||||
*/
|
||||
typedef struct IRCode {
|
||||
uint8_t code[SERIALBRIDGE_MESSAGE_DATA_SIZE_MAX];
|
||||
} __attribute((packed)) IRCode;
|
||||
|
||||
|
||||
/**
|
||||
* IR Component Check
|
||||
*/
|
||||
typedef struct IRCheck {
|
||||
bool checkResult;
|
||||
} __attribute((packed)) IRCheck;
|
||||
|
||||
/**
|
||||
* SAO I2C command and data
|
||||
* - note: this is a preliminary message type, we will want to change this.
|
||||
*/
|
||||
typedef struct SAOWireData {
|
||||
uint8_t cmd;
|
||||
uint8_t data[128];
|
||||
} __attribute((packed)) SAOWireData;
|
||||
|
||||
/**
|
||||
* SAO GPIO Data state
|
||||
*/
|
||||
typedef struct SAOGPIOData {
|
||||
uint8_t pinmode[2];
|
||||
uint8_t pinstate[2];
|
||||
} __attribute((packed)) SAOGPIOData;
|
||||
|
||||
/**
|
||||
* RGB LED State to set
|
||||
*/
|
||||
typedef struct RGBLEDState {
|
||||
uint8_t brightness[8];
|
||||
uint8_t red[8];
|
||||
uint8_t green[8];
|
||||
uint8_t blue[8];
|
||||
} __attribute((packed)) RGBLEDState;
|
||||
|
||||
/**
|
||||
* Capsense pad state
|
||||
*/
|
||||
typedef struct CapsenseState {
|
||||
bool pads[8];
|
||||
} __attribute((packed)) CapsenseState;
|
||||
|
||||
typedef struct CapsenseFeedback {
|
||||
bool enable;
|
||||
} __attribute((packed)) CapsenseFeedback;
|
||||
|
||||
/**
|
||||
* DPad state
|
||||
*/
|
||||
typedef struct DPadState {
|
||||
bool up;
|
||||
bool down;
|
||||
bool left;
|
||||
bool right;
|
||||
bool enter;
|
||||
} __attribute((packed)) DPadState;
|
||||
|
||||
/**
|
||||
* Serial bridge message data
|
||||
*/
|
||||
typedef struct SerialMessageData {
|
||||
union {
|
||||
padding none;
|
||||
VBATValue vbat;
|
||||
IRCode code;
|
||||
SAOWireData i2cData;
|
||||
SAOGPIOData gpio;
|
||||
RGBLEDState leds;
|
||||
CapsenseState capsense;
|
||||
CapsenseFeedback feedback;
|
||||
DPadState dpad;
|
||||
IRCheck ircheck;
|
||||
} __attribute((packed)) payload;
|
||||
} __attribute((packed)) SerialMessageData;
|
||||
|
||||
/**
|
||||
* Serial bridge message structure
|
||||
*/
|
||||
typedef struct SerialMessage_v1 {
|
||||
SerialMessageHeader header;
|
||||
SerialMessageData data;
|
||||
} __attribute((packed)) SerialMessage;
|
||||
|
||||
/**
|
||||
* Serial message queue convenience type
|
||||
*/
|
||||
typedef CircularBuffer<SerialMessage,SERIALBRIDGE_MESSAGE_QUEUE_MAX_SIZE> SerialMessageQueue;
|
||||
|
||||
// MARK: Messaging functionality
|
||||
|
||||
/**
|
||||
* Populate a message type correctly, setting its version and type fields appropriately
|
||||
* @internal populates the data section with the (non-typed) data structure
|
||||
* @return false if datalen too large to fit
|
||||
*/
|
||||
bool prepareMessage(SerialMessage &msg, MessageType type, uint8_t seqNo, const void *data, size_t datalen);
|
||||
/**
|
||||
* Validate a message is a recognised version and message type
|
||||
* @return false if message version or type is unknown
|
||||
*/
|
||||
bool validateMessage(const SerialMessage &msg);
|
||||
|
||||
/**
|
||||
* Monotonically-increasing sequence number (not thread-safe)
|
||||
*/
|
||||
uint8_t nextSequenceNumber(void);
|
||||
|
||||
/**
|
||||
* Enqueue a message for processing
|
||||
* @return false if message not valid, or queue error
|
||||
*/
|
||||
bool enqueueMessage(const SerialMessage &msg, SerialMessageQueue &queue);
|
||||
|
||||
/**
|
||||
* Dequeue a message for proecssing
|
||||
* @internal populates msgOut section with the message
|
||||
* @note Will consume the first element of the queue regardless of whether it's a valid message or not
|
||||
* @note It's up to the caller to guarantee the msg pointee is large enough to hold a SerialMessage
|
||||
* @return false if message not valid, msgOut is NULL, or no messages available
|
||||
*/
|
||||
bool dequeueMessage(SerialMessage *msgOut, SerialMessageQueue &queue);
|
||||
|
||||
/**
|
||||
* Returns a string describing message type, or "unknown" if it's not a valid type enum
|
||||
*/
|
||||
const char* messageType(MessageType type);
|
||||
|
||||
#endif // __SERIALBRIDGE_MESSAGES_H
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef _BADGE_LOG_H_
|
||||
#define _BADGE_LOG_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Log level definition and config helpers */
|
||||
typedef enum {
|
||||
LOG_NOTSET,
|
||||
LOG_TRACE,
|
||||
LOG_DEBUG,
|
||||
LOG_INFO,
|
||||
LOG_WARN,
|
||||
LOG_ERROR,
|
||||
LOG_CRITICAL,
|
||||
LOG_PANIC,
|
||||
_LOG_MAX_LV,
|
||||
} log_level_e;
|
||||
|
||||
void set_log_level(const log_level_e);
|
||||
|
||||
typedef enum {
|
||||
LOG_DECORATED = true,
|
||||
LOG_UNDECORATED = false,
|
||||
_LOG_MAX_DEC,
|
||||
} log_decoration_e;
|
||||
|
||||
void set_log_decoration(const log_decoration_e);
|
||||
|
||||
/* All logging calls are simple, short voided functions in order to reduce the
|
||||
* overhead on the caller - both in coding and calling. The caller can assume
|
||||
* that a call to the logging subsystem will return quickly and that data
|
||||
* passed by reference is then safe to deallocate.
|
||||
*/
|
||||
void __attribute__ ((format (printf, 2, 3)))
|
||||
log(const log_level_e, const char * const, ...);
|
||||
void __attribute__ ((format (printf, 3, 4)))
|
||||
log(const log_level_e, const log_decoration_e, const char * const, ...);
|
||||
|
||||
void log_dump();
|
||||
|
||||
#endif//_BADGE_LOG_H_
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef _SERIAL_BRIDGE_2020_
|
||||
#define _SERIAL_BRIDGE_2020_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "badge_pins.h"
|
||||
#include "BSidesMessaging.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#ifndef ssize_t
|
||||
#define ssize_t int
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define WOULD_BLOCK ((ssize_t)-100)
|
||||
#ifdef SAMD21
|
||||
extern Uart DebugSerial;
|
||||
#endif
|
||||
|
||||
typedef enum BridgeState {
|
||||
disconnected,
|
||||
pending,
|
||||
live,
|
||||
} BridgeState;
|
||||
|
||||
class SerialBridgeLink {
|
||||
public:
|
||||
SerialBridgeLink();
|
||||
void begin(unsigned long baud=9600);
|
||||
void end(void);
|
||||
int available(void);
|
||||
int read(void);
|
||||
void flush(void);
|
||||
size_t write(uint8_t);
|
||||
};
|
||||
|
||||
class SerialBridge {
|
||||
public:
|
||||
SerialBridge();
|
||||
void connect(void);
|
||||
void disconnect(void);
|
||||
int available(void);
|
||||
bool sendMessage(const SerialMessage& msg);
|
||||
bool recvMessage(SerialMessage* msg);
|
||||
ssize_t send(const void *buf, size_t buf_size);
|
||||
ssize_t recv(void *buf, size_t buf_size);
|
||||
private:
|
||||
SerialBridgeLink link;
|
||||
void sendAckMessage(uint8_t seqNo);
|
||||
void sendNackMessage(uint8_t seqNo);
|
||||
};
|
||||
|
||||
#endif // _SERIAL_BRIDGE_2020_
|
|
@ -0,0 +1,25 @@
|
|||
// HSPI pins
|
||||
#define HSPI_MISO 12
|
||||
#define HSPI_MOSI 13
|
||||
#define HSPI_SCLK 14
|
||||
#define HSPI_SS 15
|
||||
|
||||
// ePaper display
|
||||
#define EPD_DC 25
|
||||
#define EPD_CS 27
|
||||
#define EPD_BUSY 35
|
||||
#define SRAM_CS -1
|
||||
#define EPD_RESET 26
|
||||
#define EPD_SPI &SPI3
|
||||
|
||||
// I2C
|
||||
#define ESP_SDA 22
|
||||
#define ESP_SCL 38
|
||||
|
||||
// ATMEL UART Bridge
|
||||
#define UART_RXD (33u)
|
||||
#define UART_TXD (32U)
|
||||
|
||||
// IMU
|
||||
#define ESP32_I2C_IMU_SDA ((int)22)
|
||||
#define ESP32_I2C_IMU_SCL ((int)19)
|
|
@ -0,0 +1,344 @@
|
|||
#ifndef _ICM20602_H
|
||||
#define _ICM20602_H
|
||||
|
||||
/***** Includes *****/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/***** Macros *****/
|
||||
|
||||
/** This initializer will zero out the ICM20602 struct for initialization
|
||||
* purposes. This is advised as to avoid having uninitialized garbage values
|
||||
* left within the struct */
|
||||
#define ICM20602_INIT() \
|
||||
{ \
|
||||
.id = 0, \
|
||||
.hal_wr = NULL, \
|
||||
.hal_rd = NULL, \
|
||||
.hal_sleep = NULL, \
|
||||
.mutex_lock = NULL, \
|
||||
.mutex_unlock = NULL, \
|
||||
.use_accel = false, \
|
||||
.accel_fifo = false, \
|
||||
.accel_dlpf = 0, \
|
||||
.accel_g = 0, \
|
||||
.use_gyro = false, \
|
||||
.gyro_fifo = false, \
|
||||
.gyro_dlpf = 0, \
|
||||
.gyro_dps = 0, \
|
||||
.sample_rate_div = 1, \
|
||||
.i2c_disable = false, \
|
||||
}
|
||||
|
||||
/** This initializer will configure the ICM20602 with settings that should
|
||||
* yield some actual output on both the gyroscope and the accelerometer. All
|
||||
* that the developer should need to set manually are the "hal_wr", "hal_rd",
|
||||
* and "hal_sleep" function pointers. It is recommended to use this for
|
||||
* testing purposes. */
|
||||
#define ICM20602_DEFAULT_INIT() \
|
||||
{ \
|
||||
.id = 0, \
|
||||
.hal_wr = NULL, \
|
||||
.hal_rd = NULL, \
|
||||
.hal_sleep = NULL, \
|
||||
.mutex_lock = NULL, \
|
||||
.mutex_unlock = NULL, \
|
||||
.use_accel = true, \
|
||||
.accel_fifo = false, \
|
||||
.accel_dlpf = ICM20602_ACCEL_DLPF_10_2_HZ, \
|
||||
.accel_g = ICM20602_ACCEL_RANGE_4G, \
|
||||
.use_gyro = true, \
|
||||
.gyro_fifo = false, \
|
||||
.gyro_dlpf = ICM20602_GYRO_DLPF_10_HZ, \
|
||||
.gyro_dps = ICM20602_GYRO_RANGE_2000_DPS, \
|
||||
.sample_rate_div = 100, \
|
||||
.i2c_disable = false, \
|
||||
}
|
||||
|
||||
/***** Typedefs *****/
|
||||
|
||||
/** \brief Function pointer for write function.
|
||||
* \param id the ID value of the icm20602 device struct
|
||||
* \param reg ICM20602 register address to target
|
||||
* \param data pointer to data to write
|
||||
* \param len number of bytes to write
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
typedef int8_t (*icm20602_hal_wr)(uint8_t id, uint8_t reg, uint8_t * data,
|
||||
uint16_t len);
|
||||
|
||||
/** \brief Function pointer for read function.
|
||||
* \param id the ID value of the icm20602 device struct
|
||||
* \param reg ICM20602 register address to target
|
||||
* \param data pointer to data to read
|
||||
* \param len number of bytes to read
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
typedef int8_t (*icm20602_hal_rd)(uint8_t id, uint8_t reg, uint8_t * data,
|
||||
uint16_t len);
|
||||
|
||||
/** \brief Function pointer for sleep function.
|
||||
* \param ms the total number of milliseconds to sleep for
|
||||
* \return void
|
||||
*/
|
||||
typedef void (*icm20602_hal_sleep)(uint32_t ms);
|
||||
|
||||
/** \brief Function pointer for mutex locking function.
|
||||
* \param id the ID value of the icm20602 device struct
|
||||
* \return void
|
||||
*/
|
||||
typedef void (*icm20602_mutex_lock)(uint8_t id);
|
||||
|
||||
/** \brief Function pointer for mutex unlocking function.
|
||||
* \param id the ID value of the icm20602 device struct
|
||||
* \return void
|
||||
*/
|
||||
typedef void (*icm20602_mutex_unlock)(uint8_t id);
|
||||
|
||||
/***** Enums *****/
|
||||
|
||||
/** Enumerated value corresponds with A_DLPF_CFG in the ACCEL_CONFIG2 register
|
||||
* unless BYPASS is specified in the name. If BYPASS is used, the DLPF is
|
||||
* removed from the signal path and ACCEL_FCHOICE_B is set in the
|
||||
* ACCEL_CONFIG2 register. */
|
||||
enum icm20602_accel_dlpf {
|
||||
ICM20602_ACCEL_DLPF_218_1_HZ = 0, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_99_HZ = 2, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_44_8_HZ = 3, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_21_2_HZ = 4, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_10_2_HZ = 5, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_5_1_HZ = 6, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_420_HZ = 7, // data clocked at 1kHz
|
||||
ICM20602_ACCEL_DLPF_BYPASS_1046_HZ, // no filter, data clocked at 4kHz
|
||||
};
|
||||
|
||||
/** Enumerated value corresponds with ACCEL_FS_SEL in the ACCEL_CONFIG
|
||||
* register. Values listed are the full +/- G range. */
|
||||
enum icm20602_accel_g {
|
||||
ICM20602_ACCEL_RANGE_2G = 0,
|
||||
ICM20602_ACCEL_RANGE_4G = 1,
|
||||
ICM20602_ACCEL_RANGE_8G = 2,
|
||||
ICM20602_ACCEL_RANGE_16G = 3,
|
||||
};
|
||||
|
||||
/** Enumerated value corresponds with DLPF_CFG in the CONFIG register unless
|
||||
* BYPASS is specified in the name. If BYPASS is used, the DLPF is removed
|
||||
* from the signal path and FCHOICE_B is set in GYRO_CONFIG register. */
|
||||
enum icm20602_gyro_dlpf {
|
||||
ICM20602_GYRO_DLPF_250_HZ = 0, // data clocked at 8kHz
|
||||
ICM20602_GYRO_DLPF_176_HZ = 1, // data clocked at 1kHz
|
||||
ICM20602_GYRO_DLPF_92_HZ = 2, // data clocked at 1kHz
|
||||
ICM20602_GYRO_DLPF_41_HZ = 3, // data clocked at 1kHz
|
||||
ICM20602_GYRO_DLPF_20_HZ = 4, // data clocked at 1kHz
|
||||
ICM20602_GYRO_DLPF_10_HZ = 5, // data clocked at 1kHz
|
||||
ICM20602_GYRO_DLPF_5_HZ = 6, // data clocked at 1kHz
|
||||
ICM20602_GYRO_DLPF_3281_HZ = 7, // data clocked at 8kHz
|
||||
ICM20602_GYRO_DLPF_BYPASS_3281_HZ, // no filter, data clocked at 32kHz
|
||||
ICM20602_GYRO_DLPF_BYPASS_8173_HZ, // no filter, data clocked at 32kHz
|
||||
};
|
||||
|
||||
/** Enumerated value corresponds with FS_SEL in the GYRO_CONFIG register.
|
||||
* Values listed are the full +/- DPS range. */
|
||||
enum icm20602_gyro_dps {
|
||||
ICM20602_GYRO_RANGE_250_DPS = 0,
|
||||
ICM20602_GYRO_RANGE_500_DPS = 1,
|
||||
ICM20602_GYRO_RANGE_1000_DPS = 2,
|
||||
ICM20602_GYRO_RANGE_2000_DPS = 3,
|
||||
};
|
||||
|
||||
/***** Structs *****/
|
||||
|
||||
struct icm20602_dev {
|
||||
/// Identifier, can be I2C address, SPI CS line, or some other unique value.
|
||||
uint8_t id;
|
||||
|
||||
/// Required function pointer for register write function.
|
||||
icm20602_hal_wr hal_wr;
|
||||
/// Required function pointer for register read function.
|
||||
icm20602_hal_rd hal_rd;
|
||||
/// Required function pointer for system sleep/delay.
|
||||
icm20602_hal_sleep hal_sleep;
|
||||
|
||||
/// Optional function pointer to mutex lock if needed, NULL otherwise.
|
||||
icm20602_mutex_lock mutex_lock;
|
||||
/// Optional function pointer to mutex unlocking if needed, NULL otherwise.
|
||||
icm20602_mutex_lock mutex_unlock;
|
||||
|
||||
/// Set to "true" to configure the accelerometer.
|
||||
bool use_accel;
|
||||
/// Enable or disable fifo for accelerometer.
|
||||
bool accel_fifo;
|
||||
/// Select the digital low pass filter to use with the accelerometer.
|
||||
enum icm20602_accel_dlpf accel_dlpf;
|
||||
/// Select the accelerometer's g-force range.
|
||||
enum icm20602_accel_g accel_g;
|
||||
|
||||
/// Set to "true" to configure the gyroscope.
|
||||
bool use_gyro;
|
||||
/// Enable or disable fifo for gyroscope.
|
||||
bool gyro_fifo;
|
||||
/// Select the digital low pass filter to use with the gyroscope.
|
||||
enum icm20602_gyro_dlpf gyro_dlpf;
|
||||
/// Select the gyroscope's degrees per second range.
|
||||
enum icm20602_gyro_dps gyro_dps;
|
||||
|
||||
/// Divides the data clock for both the accelerometer and gyroscope.
|
||||
uint8_t sample_rate_div;
|
||||
|
||||
/// Disable hardware I2C communications to chip, recommeded if using SPI.
|
||||
bool i2c_disable;
|
||||
};
|
||||
|
||||
/***** Global Functions *****/
|
||||
|
||||
/** \brief Initializes the ICM20602 sensor.
|
||||
* \param config pointer to configuration struct
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_init(struct icm20602_dev * dev);
|
||||
|
||||
/** \brief Reads current G-force values of accelerometer.
|
||||
* \param p_x destination for x G value
|
||||
* \param p_y destination for y G value
|
||||
* \param p_z destination for z G value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_accel(struct icm20602_dev * dev, float * p_x, float * p_y,
|
||||
float * p_z);
|
||||
|
||||
/** \brief Reads current degrees per second values of gyroscope.
|
||||
* \param p_x destination for x value
|
||||
* \param p_y destination for y value
|
||||
* \param p_z destination for z value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_gyro(struct icm20602_dev * dev, float * p_x, float * p_y,
|
||||
float * p_z);
|
||||
|
||||
/** \brief Reads current values of accelerometer and gyroscope.
|
||||
* \param p_ax destination for accelerometer x G value
|
||||
* \param p_ay destination for accelerometer y G value
|
||||
* \param p_az destination for accelerometer z G value
|
||||
* \param p_gx destination for gyroscope x DPS value
|
||||
* \param p_gy destination for gyroscope y DPS value
|
||||
* \param p_gz destination for gyroscope z DPS value
|
||||
* \param p_t destination for temperature degrees C value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_data(struct icm20602_dev * dev, float * p_ax, float * p_ay,
|
||||
float * p_az, float * p_gx, float * p_gy, float * p_gz, float * p_t);
|
||||
|
||||
/** \brief Reads current raw values of accelerometer.
|
||||
* \param p_x destination for x value
|
||||
* \param p_y destination for y value
|
||||
* \param p_z destination for z value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_accel_raw(struct icm20602_dev * dev, int16_t * p_x, int16_t * p_y,
|
||||
int16_t * p_z);
|
||||
|
||||
/** \brief Reads current raw values of gyroscope.
|
||||
* \param p_x destination for x value
|
||||
* \param p_y destination for y value
|
||||
* \param p_z destination for z value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_gyro_raw(struct icm20602_dev * dev, int16_t * p_x, int16_t * p_y,
|
||||
int16_t * p_z);
|
||||
|
||||
/** \brief Reads current raw values of accelerometer and gyroscope.
|
||||
* \param p_ax destination for accelerometer x value
|
||||
* \param p_ay destination for accelerometer y value
|
||||
* \param p_az destination for accelerometer z value
|
||||
* \param p_gx destination for gyroscope x value
|
||||
* \param p_gy destination for gyroscope y value
|
||||
* \param p_gz destination for gyroscope z value
|
||||
* \param p_t destination for temperature value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_data_raw(struct icm20602_dev * dev, int16_t * p_ax,
|
||||
int16_t * p_ay, int16_t * p_az, int16_t * p_gx, int16_t * p_gy,
|
||||
int16_t * p_gz, int16_t * p_t);
|
||||
|
||||
/** \brief Reads FIFO G-force values of accelerometer.
|
||||
* \param p_x destination for x G value
|
||||
* \param p_y destination for y G value
|
||||
* \param p_z destination for z G value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_accel_fifo(struct icm20602_dev * dev, float * x, float * y,
|
||||
float * z);
|
||||
|
||||
/** \brief Reads FIFO degrees per second values of gyroscope.
|
||||
* \param p_x destination for x value
|
||||
* \param p_y destination for y value
|
||||
* \param p_z destination for z value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_gyro_fifo(struct icm20602_dev * dev, float * x, float * y,
|
||||
float * z);
|
||||
|
||||
/** \brief Reads FIFO values of accelerometer and gyroscope. Note, both
|
||||
* accelerometer and gyroscope fifos should be enabled if this
|
||||
* function is to be used.
|
||||
* \param p_ax destination for accelerometer x G value
|
||||
* \param p_ay destination for accelerometer y G value
|
||||
* \param p_az destination for accelerometer z G value
|
||||
* \param p_gx destination for gyroscope x DPS value
|
||||
* \param p_gy destination for gyroscope y DPS value
|
||||
* \param p_gz destination for gyroscope z DPS value
|
||||
* \param p_t destination for temperature degrees C value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_fifo_data(struct icm20602_dev * dev, float * p_ax, float * p_ay,
|
||||
float * p_az, float * p_gx, float * p_gy, float * p_gz, float * p_t);
|
||||
|
||||
/** \brief Reads FIFO raw values of accelerometer.
|
||||
* \param p_x destination for x value
|
||||
* \param p_y destination for y value
|
||||
* \param p_z destination for z value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_fifo_accel_raw(struct icm20602_dev * dev, int16_t * p_x,
|
||||
int16_t * p_y, int16_t * p_z);
|
||||
|
||||
/** \brief Reads FIFO raw values of gyroscope.
|
||||
* \param p_x destination for x value
|
||||
* \param p_y destination for y value
|
||||
* \param p_z destination for z value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_fifo_gyro_raw(struct icm20602_dev * dev, int16_t * p_x,
|
||||
int16_t * p_y, int16_t * p_z);
|
||||
|
||||
/** \brief Reads FIFO raw values of accelerometer and gyroscope. Note, both
|
||||
* accelerometer and gyroscope fifos should be enabled if this
|
||||
* function is to be used.
|
||||
* \param p_ax destination for accelerometer x value
|
||||
* \param p_ay destination for accelerometer y value
|
||||
* \param p_az destination for accelerometer z value
|
||||
* \param p_gx destination for gyroscope x value
|
||||
* \param p_gy destination for gyroscope y value
|
||||
* \param p_gz destination for gyroscope z value
|
||||
* \param p_t destination for temperature value
|
||||
* \return zero on success, anything else is an error
|
||||
*/
|
||||
extern int8_t
|
||||
icm20602_read_fifo_data_raw(struct icm20602_dev * dev, int16_t * p_ax,
|
||||
int16_t * p_ay, int16_t * p_az, int16_t * p_gx, int16_t * p_gy,
|
||||
int16_t * p_gz, int16_t * p_t);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,69 @@
|
|||
// //////////////////////////////////////////////////////////
|
||||
// Crc32.h
|
||||
// Copyright (c) 2011-2019 Stephan Brumme. All rights reserved.
|
||||
// Slicing-by-16 contributed by Bulat Ziganshin
|
||||
// Tableless bytewise CRC contributed by Hagai Gold
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
// if running on an embedded system, you might consider shrinking the
|
||||
// big Crc32Lookup table by undefining these lines:
|
||||
#define CRC32_USE_LOOKUP_TABLE_BYTE
|
||||
#define CRC32_USE_LOOKUP_TABLE_SLICING_BY_4
|
||||
#define CRC32_USE_LOOKUP_TABLE_SLICING_BY_8
|
||||
#define CRC32_USE_LOOKUP_TABLE_SLICING_BY_16
|
||||
// - crc32_bitwise doesn't need it at all
|
||||
// - crc32_halfbyte has its own small lookup table
|
||||
// - crc32_1byte_tableless and crc32_1byte_tableless2 don't need it at all
|
||||
// - crc32_1byte needs only Crc32Lookup[0]
|
||||
// - crc32_4bytes needs only Crc32Lookup[0..3]
|
||||
// - crc32_8bytes needs only Crc32Lookup[0..7]
|
||||
// - crc32_4x8bytes needs only Crc32Lookup[0..7]
|
||||
// - crc32_16bytes needs all of Crc32Lookup
|
||||
// using the aforementioned #defines the table is automatically fitted to your needs
|
||||
|
||||
// uint8_t, uint32_t, int32_t
|
||||
#include <stdint.h>
|
||||
// size_t
|
||||
#include <cstddef>
|
||||
|
||||
// crc32_fast selects the fastest algorithm depending on flags (CRC32_USE_LOOKUP_...)
|
||||
/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs
|
||||
uint32_t crc32_fast (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
|
||||
/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA))
|
||||
uint32_t crc32_combine (uint32_t crcA, uint32_t crcB, size_t lengthB);
|
||||
|
||||
/// compute CRC32 (bitwise algorithm)
|
||||
uint32_t crc32_bitwise (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
/// compute CRC32 (half-byte algoritm)
|
||||
uint32_t crc32_halfbyte(const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_BYTE
|
||||
/// compute CRC32 (standard algorithm)
|
||||
uint32_t crc32_1byte (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
#endif
|
||||
|
||||
/// compute CRC32 (byte algorithm) without lookup tables
|
||||
uint32_t crc32_1byte_tableless (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
/// compute CRC32 (byte algorithm) without lookup tables
|
||||
uint32_t crc32_1byte_tableless2(const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4
|
||||
/// compute CRC32 (Slicing-by-4 algorithm)
|
||||
uint32_t crc32_4bytes (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
#endif
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8
|
||||
/// compute CRC32 (Slicing-by-8 algorithm)
|
||||
uint32_t crc32_8bytes (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times
|
||||
uint32_t crc32_4x8bytes(const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
#endif
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16
|
||||
/// compute CRC32 (Slicing-by-16 algorithm)
|
||||
uint32_t crc32_16bytes (const void* data, size_t length, uint32_t previousCrc32 = 0);
|
||||
/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks)
|
||||
uint32_t crc32_16bytes_prefetch(const void* data, size_t length, uint32_t previousCrc32 = 0, size_t prefetchAhead = 256);
|
||||
#endif
|
|
@ -0,0 +1,546 @@
|
|||
// //////////////////////////////////////////////////////////
|
||||
// Crc32.ino
|
||||
// Copyright (c) 2011 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
/// zlib's CRC32 polynomial
|
||||
const uint32_t Polynomial = 0xEDB88320;
|
||||
|
||||
const size_t NumBytes = 256;
|
||||
uint8_t data[NumBytes];
|
||||
const size_t Repetitions = 4*1024;
|
||||
|
||||
|
||||
PROGMEM uint32_t crc32Lookup[8*256] =
|
||||
{ 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,
|
||||
|
||||
0x00000000,0x191B3141,0x32366282,0x2B2D53C3,0x646CC504,0x7D77F445,0x565AA786,0x4F4196C7,
|
||||
0xC8D98A08,0xD1C2BB49,0xFAEFE88A,0xE3F4D9CB,0xACB54F0C,0xB5AE7E4D,0x9E832D8E,0x87981CCF,
|
||||
0x4AC21251,0x53D92310,0x78F470D3,0x61EF4192,0x2EAED755,0x37B5E614,0x1C98B5D7,0x05838496,
|
||||
0x821B9859,0x9B00A918,0xB02DFADB,0xA936CB9A,0xE6775D5D,0xFF6C6C1C,0xD4413FDF,0xCD5A0E9E,
|
||||
0x958424A2,0x8C9F15E3,0xA7B24620,0xBEA97761,0xF1E8E1A6,0xE8F3D0E7,0xC3DE8324,0xDAC5B265,
|
||||
0x5D5DAEAA,0x44469FEB,0x6F6BCC28,0x7670FD69,0x39316BAE,0x202A5AEF,0x0B07092C,0x121C386D,
|
||||
0xDF4636F3,0xC65D07B2,0xED705471,0xF46B6530,0xBB2AF3F7,0xA231C2B6,0x891C9175,0x9007A034,
|
||||
0x179FBCFB,0x0E848DBA,0x25A9DE79,0x3CB2EF38,0x73F379FF,0x6AE848BE,0x41C51B7D,0x58DE2A3C,
|
||||
0xF0794F05,0xE9627E44,0xC24F2D87,0xDB541CC6,0x94158A01,0x8D0EBB40,0xA623E883,0xBF38D9C2,
|
||||
0x38A0C50D,0x21BBF44C,0x0A96A78F,0x138D96CE,0x5CCC0009,0x45D73148,0x6EFA628B,0x77E153CA,
|
||||
0xBABB5D54,0xA3A06C15,0x888D3FD6,0x91960E97,0xDED79850,0xC7CCA911,0xECE1FAD2,0xF5FACB93,
|
||||
0x7262D75C,0x6B79E61D,0x4054B5DE,0x594F849F,0x160E1258,0x0F152319,0x243870DA,0x3D23419B,
|
||||
0x65FD6BA7,0x7CE65AE6,0x57CB0925,0x4ED03864,0x0191AEA3,0x188A9FE2,0x33A7CC21,0x2ABCFD60,
|
||||
0xAD24E1AF,0xB43FD0EE,0x9F12832D,0x8609B26C,0xC94824AB,0xD05315EA,0xFB7E4629,0xE2657768,
|
||||
0x2F3F79F6,0x362448B7,0x1D091B74,0x04122A35,0x4B53BCF2,0x52488DB3,0x7965DE70,0x607EEF31,
|
||||
0xE7E6F3FE,0xFEFDC2BF,0xD5D0917C,0xCCCBA03D,0x838A36FA,0x9A9107BB,0xB1BC5478,0xA8A76539,
|
||||
0x3B83984B,0x2298A90A,0x09B5FAC9,0x10AECB88,0x5FEF5D4F,0x46F46C0E,0x6DD93FCD,0x74C20E8C,
|
||||
0xF35A1243,0xEA412302,0xC16C70C1,0xD8774180,0x9736D747,0x8E2DE606,0xA500B5C5,0xBC1B8484,
|
||||
0x71418A1A,0x685ABB5B,0x4377E898,0x5A6CD9D9,0x152D4F1E,0x0C367E5F,0x271B2D9C,0x3E001CDD,
|
||||
0xB9980012,0xA0833153,0x8BAE6290,0x92B553D1,0xDDF4C516,0xC4EFF457,0xEFC2A794,0xF6D996D5,
|
||||
0xAE07BCE9,0xB71C8DA8,0x9C31DE6B,0x852AEF2A,0xCA6B79ED,0xD37048AC,0xF85D1B6F,0xE1462A2E,
|
||||
0x66DE36E1,0x7FC507A0,0x54E85463,0x4DF36522,0x02B2F3E5,0x1BA9C2A4,0x30849167,0x299FA026,
|
||||
0xE4C5AEB8,0xFDDE9FF9,0xD6F3CC3A,0xCFE8FD7B,0x80A96BBC,0x99B25AFD,0xB29F093E,0xAB84387F,
|
||||
0x2C1C24B0,0x350715F1,0x1E2A4632,0x07317773,0x4870E1B4,0x516BD0F5,0x7A468336,0x635DB277,
|
||||
0xCBFAD74E,0xD2E1E60F,0xF9CCB5CC,0xE0D7848D,0xAF96124A,0xB68D230B,0x9DA070C8,0x84BB4189,
|
||||
0x03235D46,0x1A386C07,0x31153FC4,0x280E0E85,0x674F9842,0x7E54A903,0x5579FAC0,0x4C62CB81,
|
||||
0x8138C51F,0x9823F45E,0xB30EA79D,0xAA1596DC,0xE554001B,0xFC4F315A,0xD7626299,0xCE7953D8,
|
||||
0x49E14F17,0x50FA7E56,0x7BD72D95,0x62CC1CD4,0x2D8D8A13,0x3496BB52,0x1FBBE891,0x06A0D9D0,
|
||||
0x5E7EF3EC,0x4765C2AD,0x6C48916E,0x7553A02F,0x3A1236E8,0x230907A9,0x0824546A,0x113F652B,
|
||||
0x96A779E4,0x8FBC48A5,0xA4911B66,0xBD8A2A27,0xF2CBBCE0,0xEBD08DA1,0xC0FDDE62,0xD9E6EF23,
|
||||
0x14BCE1BD,0x0DA7D0FC,0x268A833F,0x3F91B27E,0x70D024B9,0x69CB15F8,0x42E6463B,0x5BFD777A,
|
||||
0xDC656BB5,0xC57E5AF4,0xEE530937,0xF7483876,0xB809AEB1,0xA1129FF0,0x8A3FCC33,0x9324FD72,
|
||||
|
||||
0x00000000,0x01C26A37,0x0384D46E,0x0246BE59,0x0709A8DC,0x06CBC2EB,0x048D7CB2,0x054F1685,
|
||||
0x0E1351B8,0x0FD13B8F,0x0D9785D6,0x0C55EFE1,0x091AF964,0x08D89353,0x0A9E2D0A,0x0B5C473D,
|
||||
0x1C26A370,0x1DE4C947,0x1FA2771E,0x1E601D29,0x1B2F0BAC,0x1AED619B,0x18ABDFC2,0x1969B5F5,
|
||||
0x1235F2C8,0x13F798FF,0x11B126A6,0x10734C91,0x153C5A14,0x14FE3023,0x16B88E7A,0x177AE44D,
|
||||
0x384D46E0,0x398F2CD7,0x3BC9928E,0x3A0BF8B9,0x3F44EE3C,0x3E86840B,0x3CC03A52,0x3D025065,
|
||||
0x365E1758,0x379C7D6F,0x35DAC336,0x3418A901,0x3157BF84,0x3095D5B3,0x32D36BEA,0x331101DD,
|
||||
0x246BE590,0x25A98FA7,0x27EF31FE,0x262D5BC9,0x23624D4C,0x22A0277B,0x20E69922,0x2124F315,
|
||||
0x2A78B428,0x2BBADE1F,0x29FC6046,0x283E0A71,0x2D711CF4,0x2CB376C3,0x2EF5C89A,0x2F37A2AD,
|
||||
0x709A8DC0,0x7158E7F7,0x731E59AE,0x72DC3399,0x7793251C,0x76514F2B,0x7417F172,0x75D59B45,
|
||||
0x7E89DC78,0x7F4BB64F,0x7D0D0816,0x7CCF6221,0x798074A4,0x78421E93,0x7A04A0CA,0x7BC6CAFD,
|
||||
0x6CBC2EB0,0x6D7E4487,0x6F38FADE,0x6EFA90E9,0x6BB5866C,0x6A77EC5B,0x68315202,0x69F33835,
|
||||
0x62AF7F08,0x636D153F,0x612BAB66,0x60E9C151,0x65A6D7D4,0x6464BDE3,0x662203BA,0x67E0698D,
|
||||
0x48D7CB20,0x4915A117,0x4B531F4E,0x4A917579,0x4FDE63FC,0x4E1C09CB,0x4C5AB792,0x4D98DDA5,
|
||||
0x46C49A98,0x4706F0AF,0x45404EF6,0x448224C1,0x41CD3244,0x400F5873,0x4249E62A,0x438B8C1D,
|
||||
0x54F16850,0x55330267,0x5775BC3E,0x56B7D609,0x53F8C08C,0x523AAABB,0x507C14E2,0x51BE7ED5,
|
||||
0x5AE239E8,0x5B2053DF,0x5966ED86,0x58A487B1,0x5DEB9134,0x5C29FB03,0x5E6F455A,0x5FAD2F6D,
|
||||
0xE1351B80,0xE0F771B7,0xE2B1CFEE,0xE373A5D9,0xE63CB35C,0xE7FED96B,0xE5B86732,0xE47A0D05,
|
||||
0xEF264A38,0xEEE4200F,0xECA29E56,0xED60F461,0xE82FE2E4,0xE9ED88D3,0xEBAB368A,0xEA695CBD,
|
||||
0xFD13B8F0,0xFCD1D2C7,0xFE976C9E,0xFF5506A9,0xFA1A102C,0xFBD87A1B,0xF99EC442,0xF85CAE75,
|
||||
0xF300E948,0xF2C2837F,0xF0843D26,0xF1465711,0xF4094194,0xF5CB2BA3,0xF78D95FA,0xF64FFFCD,
|
||||
0xD9785D60,0xD8BA3757,0xDAFC890E,0xDB3EE339,0xDE71F5BC,0xDFB39F8B,0xDDF521D2,0xDC374BE5,
|
||||
0xD76B0CD8,0xD6A966EF,0xD4EFD8B6,0xD52DB281,0xD062A404,0xD1A0CE33,0xD3E6706A,0xD2241A5D,
|
||||
0xC55EFE10,0xC49C9427,0xC6DA2A7E,0xC7184049,0xC25756CC,0xC3953CFB,0xC1D382A2,0xC011E895,
|
||||
0xCB4DAFA8,0xCA8FC59F,0xC8C97BC6,0xC90B11F1,0xCC440774,0xCD866D43,0xCFC0D31A,0xCE02B92D,
|
||||
0x91AF9640,0x906DFC77,0x922B422E,0x93E92819,0x96A63E9C,0x976454AB,0x9522EAF2,0x94E080C5,
|
||||
0x9FBCC7F8,0x9E7EADCF,0x9C381396,0x9DFA79A1,0x98B56F24,0x99770513,0x9B31BB4A,0x9AF3D17D,
|
||||
0x8D893530,0x8C4B5F07,0x8E0DE15E,0x8FCF8B69,0x8A809DEC,0x8B42F7DB,0x89044982,0x88C623B5,
|
||||
0x839A6488,0x82580EBF,0x801EB0E6,0x81DCDAD1,0x8493CC54,0x8551A663,0x8717183A,0x86D5720D,
|
||||
0xA9E2D0A0,0xA820BA97,0xAA6604CE,0xABA46EF9,0xAEEB787C,0xAF29124B,0xAD6FAC12,0xACADC625,
|
||||
0xA7F18118,0xA633EB2F,0xA4755576,0xA5B73F41,0xA0F829C4,0xA13A43F3,0xA37CFDAA,0xA2BE979D,
|
||||
0xB5C473D0,0xB40619E7,0xB640A7BE,0xB782CD89,0xB2CDDB0C,0xB30FB13B,0xB1490F62,0xB08B6555,
|
||||
0xBBD72268,0xBA15485F,0xB853F606,0xB9919C31,0xBCDE8AB4,0xBD1CE083,0xBF5A5EDA,0xBE9834ED,
|
||||
|
||||
0x00000000,0xB8BC6765,0xAA09C88B,0x12B5AFEE,0x8F629757,0x37DEF032,0x256B5FDC,0x9DD738B9,
|
||||
0xC5B428EF,0x7D084F8A,0x6FBDE064,0xD7018701,0x4AD6BFB8,0xF26AD8DD,0xE0DF7733,0x58631056,
|
||||
0x5019579F,0xE8A530FA,0xFA109F14,0x42ACF871,0xDF7BC0C8,0x67C7A7AD,0x75720843,0xCDCE6F26,
|
||||
0x95AD7F70,0x2D111815,0x3FA4B7FB,0x8718D09E,0x1ACFE827,0xA2738F42,0xB0C620AC,0x087A47C9,
|
||||
0xA032AF3E,0x188EC85B,0x0A3B67B5,0xB28700D0,0x2F503869,0x97EC5F0C,0x8559F0E2,0x3DE59787,
|
||||
0x658687D1,0xDD3AE0B4,0xCF8F4F5A,0x7733283F,0xEAE41086,0x525877E3,0x40EDD80D,0xF851BF68,
|
||||
0xF02BF8A1,0x48979FC4,0x5A22302A,0xE29E574F,0x7F496FF6,0xC7F50893,0xD540A77D,0x6DFCC018,
|
||||
0x359FD04E,0x8D23B72B,0x9F9618C5,0x272A7FA0,0xBAFD4719,0x0241207C,0x10F48F92,0xA848E8F7,
|
||||
0x9B14583D,0x23A83F58,0x311D90B6,0x89A1F7D3,0x1476CF6A,0xACCAA80F,0xBE7F07E1,0x06C36084,
|
||||
0x5EA070D2,0xE61C17B7,0xF4A9B859,0x4C15DF3C,0xD1C2E785,0x697E80E0,0x7BCB2F0E,0xC377486B,
|
||||
0xCB0D0FA2,0x73B168C7,0x6104C729,0xD9B8A04C,0x446F98F5,0xFCD3FF90,0xEE66507E,0x56DA371B,
|
||||
0x0EB9274D,0xB6054028,0xA4B0EFC6,0x1C0C88A3,0x81DBB01A,0x3967D77F,0x2BD27891,0x936E1FF4,
|
||||
0x3B26F703,0x839A9066,0x912F3F88,0x299358ED,0xB4446054,0x0CF80731,0x1E4DA8DF,0xA6F1CFBA,
|
||||
0xFE92DFEC,0x462EB889,0x549B1767,0xEC277002,0x71F048BB,0xC94C2FDE,0xDBF98030,0x6345E755,
|
||||
0x6B3FA09C,0xD383C7F9,0xC1366817,0x798A0F72,0xE45D37CB,0x5CE150AE,0x4E54FF40,0xF6E89825,
|
||||
0xAE8B8873,0x1637EF16,0x048240F8,0xBC3E279D,0x21E91F24,0x99557841,0x8BE0D7AF,0x335CB0CA,
|
||||
0xED59B63B,0x55E5D15E,0x47507EB0,0xFFEC19D5,0x623B216C,0xDA874609,0xC832E9E7,0x708E8E82,
|
||||
0x28ED9ED4,0x9051F9B1,0x82E4565F,0x3A58313A,0xA78F0983,0x1F336EE6,0x0D86C108,0xB53AA66D,
|
||||
0xBD40E1A4,0x05FC86C1,0x1749292F,0xAFF54E4A,0x322276F3,0x8A9E1196,0x982BBE78,0x2097D91D,
|
||||
0x78F4C94B,0xC048AE2E,0xD2FD01C0,0x6A4166A5,0xF7965E1C,0x4F2A3979,0x5D9F9697,0xE523F1F2,
|
||||
0x4D6B1905,0xF5D77E60,0xE762D18E,0x5FDEB6EB,0xC2098E52,0x7AB5E937,0x680046D9,0xD0BC21BC,
|
||||
0x88DF31EA,0x3063568F,0x22D6F961,0x9A6A9E04,0x07BDA6BD,0xBF01C1D8,0xADB46E36,0x15080953,
|
||||
0x1D724E9A,0xA5CE29FF,0xB77B8611,0x0FC7E174,0x9210D9CD,0x2AACBEA8,0x38191146,0x80A57623,
|
||||
0xD8C66675,0x607A0110,0x72CFAEFE,0xCA73C99B,0x57A4F122,0xEF189647,0xFDAD39A9,0x45115ECC,
|
||||
0x764DEE06,0xCEF18963,0xDC44268D,0x64F841E8,0xF92F7951,0x41931E34,0x5326B1DA,0xEB9AD6BF,
|
||||
0xB3F9C6E9,0x0B45A18C,0x19F00E62,0xA14C6907,0x3C9B51BE,0x842736DB,0x96929935,0x2E2EFE50,
|
||||
0x2654B999,0x9EE8DEFC,0x8C5D7112,0x34E11677,0xA9362ECE,0x118A49AB,0x033FE645,0xBB838120,
|
||||
0xE3E09176,0x5B5CF613,0x49E959FD,0xF1553E98,0x6C820621,0xD43E6144,0xC68BCEAA,0x7E37A9CF,
|
||||
0xD67F4138,0x6EC3265D,0x7C7689B3,0xC4CAEED6,0x591DD66F,0xE1A1B10A,0xF3141EE4,0x4BA87981,
|
||||
0x13CB69D7,0xAB770EB2,0xB9C2A15C,0x017EC639,0x9CA9FE80,0x241599E5,0x36A0360B,0x8E1C516E,
|
||||
0x866616A7,0x3EDA71C2,0x2C6FDE2C,0x94D3B949,0x090481F0,0xB1B8E695,0xA30D497B,0x1BB12E1E,
|
||||
0x43D23E48,0xFB6E592D,0xE9DBF6C3,0x516791A6,0xCCB0A91F,0x740CCE7A,0x66B96194,0xDE0506F1,
|
||||
|
||||
0x00000000,0x3D6029B0,0x7AC05360,0x47A07AD0,0xF580A6C0,0xC8E08F70,0x8F40F5A0,0xB220DC10,
|
||||
0x30704BC1,0x0D106271,0x4AB018A1,0x77D03111,0xC5F0ED01,0xF890C4B1,0xBF30BE61,0x825097D1,
|
||||
0x60E09782,0x5D80BE32,0x1A20C4E2,0x2740ED52,0x95603142,0xA80018F2,0xEFA06222,0xD2C04B92,
|
||||
0x5090DC43,0x6DF0F5F3,0x2A508F23,0x1730A693,0xA5107A83,0x98705333,0xDFD029E3,0xE2B00053,
|
||||
0xC1C12F04,0xFCA106B4,0xBB017C64,0x866155D4,0x344189C4,0x0921A074,0x4E81DAA4,0x73E1F314,
|
||||
0xF1B164C5,0xCCD14D75,0x8B7137A5,0xB6111E15,0x0431C205,0x3951EBB5,0x7EF19165,0x4391B8D5,
|
||||
0xA121B886,0x9C419136,0xDBE1EBE6,0xE681C256,0x54A11E46,0x69C137F6,0x2E614D26,0x13016496,
|
||||
0x9151F347,0xAC31DAF7,0xEB91A027,0xD6F18997,0x64D15587,0x59B17C37,0x1E1106E7,0x23712F57,
|
||||
0x58F35849,0x659371F9,0x22330B29,0x1F532299,0xAD73FE89,0x9013D739,0xD7B3ADE9,0xEAD38459,
|
||||
0x68831388,0x55E33A38,0x124340E8,0x2F236958,0x9D03B548,0xA0639CF8,0xE7C3E628,0xDAA3CF98,
|
||||
0x3813CFCB,0x0573E67B,0x42D39CAB,0x7FB3B51B,0xCD93690B,0xF0F340BB,0xB7533A6B,0x8A3313DB,
|
||||
0x0863840A,0x3503ADBA,0x72A3D76A,0x4FC3FEDA,0xFDE322CA,0xC0830B7A,0x872371AA,0xBA43581A,
|
||||
0x9932774D,0xA4525EFD,0xE3F2242D,0xDE920D9D,0x6CB2D18D,0x51D2F83D,0x167282ED,0x2B12AB5D,
|
||||
0xA9423C8C,0x9422153C,0xD3826FEC,0xEEE2465C,0x5CC29A4C,0x61A2B3FC,0x2602C92C,0x1B62E09C,
|
||||
0xF9D2E0CF,0xC4B2C97F,0x8312B3AF,0xBE729A1F,0x0C52460F,0x31326FBF,0x7692156F,0x4BF23CDF,
|
||||
0xC9A2AB0E,0xF4C282BE,0xB362F86E,0x8E02D1DE,0x3C220DCE,0x0142247E,0x46E25EAE,0x7B82771E,
|
||||
0xB1E6B092,0x8C869922,0xCB26E3F2,0xF646CA42,0x44661652,0x79063FE2,0x3EA64532,0x03C66C82,
|
||||
0x8196FB53,0xBCF6D2E3,0xFB56A833,0xC6368183,0x74165D93,0x49767423,0x0ED60EF3,0x33B62743,
|
||||
0xD1062710,0xEC660EA0,0xABC67470,0x96A65DC0,0x248681D0,0x19E6A860,0x5E46D2B0,0x6326FB00,
|
||||
0xE1766CD1,0xDC164561,0x9BB63FB1,0xA6D61601,0x14F6CA11,0x2996E3A1,0x6E369971,0x5356B0C1,
|
||||
0x70279F96,0x4D47B626,0x0AE7CCF6,0x3787E546,0x85A73956,0xB8C710E6,0xFF676A36,0xC2074386,
|
||||
0x4057D457,0x7D37FDE7,0x3A978737,0x07F7AE87,0xB5D77297,0x88B75B27,0xCF1721F7,0xF2770847,
|
||||
0x10C70814,0x2DA721A4,0x6A075B74,0x576772C4,0xE547AED4,0xD8278764,0x9F87FDB4,0xA2E7D404,
|
||||
0x20B743D5,0x1DD76A65,0x5A7710B5,0x67173905,0xD537E515,0xE857CCA5,0xAFF7B675,0x92979FC5,
|
||||
0xE915E8DB,0xD475C16B,0x93D5BBBB,0xAEB5920B,0x1C954E1B,0x21F567AB,0x66551D7B,0x5B3534CB,
|
||||
0xD965A31A,0xE4058AAA,0xA3A5F07A,0x9EC5D9CA,0x2CE505DA,0x11852C6A,0x562556BA,0x6B457F0A,
|
||||
0x89F57F59,0xB49556E9,0xF3352C39,0xCE550589,0x7C75D999,0x4115F029,0x06B58AF9,0x3BD5A349,
|
||||
0xB9853498,0x84E51D28,0xC34567F8,0xFE254E48,0x4C059258,0x7165BBE8,0x36C5C138,0x0BA5E888,
|
||||
0x28D4C7DF,0x15B4EE6F,0x521494BF,0x6F74BD0F,0xDD54611F,0xE03448AF,0xA794327F,0x9AF41BCF,
|
||||
0x18A48C1E,0x25C4A5AE,0x6264DF7E,0x5F04F6CE,0xED242ADE,0xD044036E,0x97E479BE,0xAA84500E,
|
||||
0x4834505D,0x755479ED,0x32F4033D,0x0F942A8D,0xBDB4F69D,0x80D4DF2D,0xC774A5FD,0xFA148C4D,
|
||||
0x78441B9C,0x4524322C,0x028448FC,0x3FE4614C,0x8DC4BD5C,0xB0A494EC,0xF704EE3C,0xCA64C78C,
|
||||
|
||||
0x00000000,0xCB5CD3A5,0x4DC8A10B,0x869472AE,0x9B914216,0x50CD91B3,0xD659E31D,0x1D0530B8,
|
||||
0xEC53826D,0x270F51C8,0xA19B2366,0x6AC7F0C3,0x77C2C07B,0xBC9E13DE,0x3A0A6170,0xF156B2D5,
|
||||
0x03D6029B,0xC88AD13E,0x4E1EA390,0x85427035,0x9847408D,0x531B9328,0xD58FE186,0x1ED33223,
|
||||
0xEF8580F6,0x24D95353,0xA24D21FD,0x6911F258,0x7414C2E0,0xBF481145,0x39DC63EB,0xF280B04E,
|
||||
0x07AC0536,0xCCF0D693,0x4A64A43D,0x81387798,0x9C3D4720,0x57619485,0xD1F5E62B,0x1AA9358E,
|
||||
0xEBFF875B,0x20A354FE,0xA6372650,0x6D6BF5F5,0x706EC54D,0xBB3216E8,0x3DA66446,0xF6FAB7E3,
|
||||
0x047A07AD,0xCF26D408,0x49B2A6A6,0x82EE7503,0x9FEB45BB,0x54B7961E,0xD223E4B0,0x197F3715,
|
||||
0xE82985C0,0x23755665,0xA5E124CB,0x6EBDF76E,0x73B8C7D6,0xB8E41473,0x3E7066DD,0xF52CB578,
|
||||
0x0F580A6C,0xC404D9C9,0x4290AB67,0x89CC78C2,0x94C9487A,0x5F959BDF,0xD901E971,0x125D3AD4,
|
||||
0xE30B8801,0x28575BA4,0xAEC3290A,0x659FFAAF,0x789ACA17,0xB3C619B2,0x35526B1C,0xFE0EB8B9,
|
||||
0x0C8E08F7,0xC7D2DB52,0x4146A9FC,0x8A1A7A59,0x971F4AE1,0x5C439944,0xDAD7EBEA,0x118B384F,
|
||||
0xE0DD8A9A,0x2B81593F,0xAD152B91,0x6649F834,0x7B4CC88C,0xB0101B29,0x36846987,0xFDD8BA22,
|
||||
0x08F40F5A,0xC3A8DCFF,0x453CAE51,0x8E607DF4,0x93654D4C,0x58399EE9,0xDEADEC47,0x15F13FE2,
|
||||
0xE4A78D37,0x2FFB5E92,0xA96F2C3C,0x6233FF99,0x7F36CF21,0xB46A1C84,0x32FE6E2A,0xF9A2BD8F,
|
||||
0x0B220DC1,0xC07EDE64,0x46EAACCA,0x8DB67F6F,0x90B34FD7,0x5BEF9C72,0xDD7BEEDC,0x16273D79,
|
||||
0xE7718FAC,0x2C2D5C09,0xAAB92EA7,0x61E5FD02,0x7CE0CDBA,0xB7BC1E1F,0x31286CB1,0xFA74BF14,
|
||||
0x1EB014D8,0xD5ECC77D,0x5378B5D3,0x98246676,0x852156CE,0x4E7D856B,0xC8E9F7C5,0x03B52460,
|
||||
0xF2E396B5,0x39BF4510,0xBF2B37BE,0x7477E41B,0x6972D4A3,0xA22E0706,0x24BA75A8,0xEFE6A60D,
|
||||
0x1D661643,0xD63AC5E6,0x50AEB748,0x9BF264ED,0x86F75455,0x4DAB87F0,0xCB3FF55E,0x006326FB,
|
||||
0xF135942E,0x3A69478B,0xBCFD3525,0x77A1E680,0x6AA4D638,0xA1F8059D,0x276C7733,0xEC30A496,
|
||||
0x191C11EE,0xD240C24B,0x54D4B0E5,0x9F886340,0x828D53F8,0x49D1805D,0xCF45F2F3,0x04192156,
|
||||
0xF54F9383,0x3E134026,0xB8873288,0x73DBE12D,0x6EDED195,0xA5820230,0x2316709E,0xE84AA33B,
|
||||
0x1ACA1375,0xD196C0D0,0x5702B27E,0x9C5E61DB,0x815B5163,0x4A0782C6,0xCC93F068,0x07CF23CD,
|
||||
0xF6999118,0x3DC542BD,0xBB513013,0x700DE3B6,0x6D08D30E,0xA65400AB,0x20C07205,0xEB9CA1A0,
|
||||
0x11E81EB4,0xDAB4CD11,0x5C20BFBF,0x977C6C1A,0x8A795CA2,0x41258F07,0xC7B1FDA9,0x0CED2E0C,
|
||||
0xFDBB9CD9,0x36E74F7C,0xB0733DD2,0x7B2FEE77,0x662ADECF,0xAD760D6A,0x2BE27FC4,0xE0BEAC61,
|
||||
0x123E1C2F,0xD962CF8A,0x5FF6BD24,0x94AA6E81,0x89AF5E39,0x42F38D9C,0xC467FF32,0x0F3B2C97,
|
||||
0xFE6D9E42,0x35314DE7,0xB3A53F49,0x78F9ECEC,0x65FCDC54,0xAEA00FF1,0x28347D5F,0xE368AEFA,
|
||||
0x16441B82,0xDD18C827,0x5B8CBA89,0x90D0692C,0x8DD55994,0x46898A31,0xC01DF89F,0x0B412B3A,
|
||||
0xFA1799EF,0x314B4A4A,0xB7DF38E4,0x7C83EB41,0x6186DBF9,0xAADA085C,0x2C4E7AF2,0xE712A957,
|
||||
0x15921919,0xDECECABC,0x585AB812,0x93066BB7,0x8E035B0F,0x455F88AA,0xC3CBFA04,0x089729A1,
|
||||
0xF9C19B74,0x329D48D1,0xB4093A7F,0x7F55E9DA,0x6250D962,0xA90C0AC7,0x2F987869,0xE4C4ABCC,
|
||||
|
||||
0x00000000,0xA6770BB4,0x979F1129,0x31E81A9D,0xF44F2413,0x52382FA7,0x63D0353A,0xC5A73E8E,
|
||||
0x33EF4E67,0x959845D3,0xA4705F4E,0x020754FA,0xC7A06A74,0x61D761C0,0x503F7B5D,0xF64870E9,
|
||||
0x67DE9CCE,0xC1A9977A,0xF0418DE7,0x56368653,0x9391B8DD,0x35E6B369,0x040EA9F4,0xA279A240,
|
||||
0x5431D2A9,0xF246D91D,0xC3AEC380,0x65D9C834,0xA07EF6BA,0x0609FD0E,0x37E1E793,0x9196EC27,
|
||||
0xCFBD399C,0x69CA3228,0x582228B5,0xFE552301,0x3BF21D8F,0x9D85163B,0xAC6D0CA6,0x0A1A0712,
|
||||
0xFC5277FB,0x5A257C4F,0x6BCD66D2,0xCDBA6D66,0x081D53E8,0xAE6A585C,0x9F8242C1,0x39F54975,
|
||||
0xA863A552,0x0E14AEE6,0x3FFCB47B,0x998BBFCF,0x5C2C8141,0xFA5B8AF5,0xCBB39068,0x6DC49BDC,
|
||||
0x9B8CEB35,0x3DFBE081,0x0C13FA1C,0xAA64F1A8,0x6FC3CF26,0xC9B4C492,0xF85CDE0F,0x5E2BD5BB,
|
||||
0x440B7579,0xE27C7ECD,0xD3946450,0x75E36FE4,0xB044516A,0x16335ADE,0x27DB4043,0x81AC4BF7,
|
||||
0x77E43B1E,0xD19330AA,0xE07B2A37,0x460C2183,0x83AB1F0D,0x25DC14B9,0x14340E24,0xB2430590,
|
||||
0x23D5E9B7,0x85A2E203,0xB44AF89E,0x123DF32A,0xD79ACDA4,0x71EDC610,0x4005DC8D,0xE672D739,
|
||||
0x103AA7D0,0xB64DAC64,0x87A5B6F9,0x21D2BD4D,0xE47583C3,0x42028877,0x73EA92EA,0xD59D995E,
|
||||
0x8BB64CE5,0x2DC14751,0x1C295DCC,0xBA5E5678,0x7FF968F6,0xD98E6342,0xE86679DF,0x4E11726B,
|
||||
0xB8590282,0x1E2E0936,0x2FC613AB,0x89B1181F,0x4C162691,0xEA612D25,0xDB8937B8,0x7DFE3C0C,
|
||||
0xEC68D02B,0x4A1FDB9F,0x7BF7C102,0xDD80CAB6,0x1827F438,0xBE50FF8C,0x8FB8E511,0x29CFEEA5,
|
||||
0xDF879E4C,0x79F095F8,0x48188F65,0xEE6F84D1,0x2BC8BA5F,0x8DBFB1EB,0xBC57AB76,0x1A20A0C2,
|
||||
0x8816EAF2,0x2E61E146,0x1F89FBDB,0xB9FEF06F,0x7C59CEE1,0xDA2EC555,0xEBC6DFC8,0x4DB1D47C,
|
||||
0xBBF9A495,0x1D8EAF21,0x2C66B5BC,0x8A11BE08,0x4FB68086,0xE9C18B32,0xD82991AF,0x7E5E9A1B,
|
||||
0xEFC8763C,0x49BF7D88,0x78576715,0xDE206CA1,0x1B87522F,0xBDF0599B,0x8C184306,0x2A6F48B2,
|
||||
0xDC27385B,0x7A5033EF,0x4BB82972,0xEDCF22C6,0x28681C48,0x8E1F17FC,0xBFF70D61,0x198006D5,
|
||||
0x47ABD36E,0xE1DCD8DA,0xD034C247,0x7643C9F3,0xB3E4F77D,0x1593FCC9,0x247BE654,0x820CEDE0,
|
||||
0x74449D09,0xD23396BD,0xE3DB8C20,0x45AC8794,0x800BB91A,0x267CB2AE,0x1794A833,0xB1E3A387,
|
||||
0x20754FA0,0x86024414,0xB7EA5E89,0x119D553D,0xD43A6BB3,0x724D6007,0x43A57A9A,0xE5D2712E,
|
||||
0x139A01C7,0xB5ED0A73,0x840510EE,0x22721B5A,0xE7D525D4,0x41A22E60,0x704A34FD,0xD63D3F49,
|
||||
0xCC1D9F8B,0x6A6A943F,0x5B828EA2,0xFDF58516,0x3852BB98,0x9E25B02C,0xAFCDAAB1,0x09BAA105,
|
||||
0xFFF2D1EC,0x5985DA58,0x686DC0C5,0xCE1ACB71,0x0BBDF5FF,0xADCAFE4B,0x9C22E4D6,0x3A55EF62,
|
||||
0xABC30345,0x0DB408F1,0x3C5C126C,0x9A2B19D8,0x5F8C2756,0xF9FB2CE2,0xC813367F,0x6E643DCB,
|
||||
0x982C4D22,0x3E5B4696,0x0FB35C0B,0xA9C457BF,0x6C636931,0xCA146285,0xFBFC7818,0x5D8B73AC,
|
||||
0x03A0A617,0xA5D7ADA3,0x943FB73E,0x3248BC8A,0xF7EF8204,0x519889B0,0x6070932D,0xC6079899,
|
||||
0x304FE870,0x9638E3C4,0xA7D0F959,0x01A7F2ED,0xC400CC63,0x6277C7D7,0x539FDD4A,0xF5E8D6FE,
|
||||
0x647E3AD9,0xC209316D,0xF3E12BF0,0x55962044,0x90311ECA,0x3646157E,0x07AE0FE3,0xA1D90457,
|
||||
0x579174BE,0xF1E67F0A,0xC00E6597,0x66796E23,0xA3DE50AD,0x05A95B19,0x34414184,0x92364A30,
|
||||
|
||||
0x00000000,0xCCAA009E,0x4225077D,0x8E8F07E3,0x844A0EFA,0x48E00E64,0xC66F0987,0x0AC50919,
|
||||
0xD3E51BB5,0x1F4F1B2B,0x91C01CC8,0x5D6A1C56,0x57AF154F,0x9B0515D1,0x158A1232,0xD92012AC,
|
||||
0x7CBB312B,0xB01131B5,0x3E9E3656,0xF23436C8,0xF8F13FD1,0x345B3F4F,0xBAD438AC,0x767E3832,
|
||||
0xAF5E2A9E,0x63F42A00,0xED7B2DE3,0x21D12D7D,0x2B142464,0xE7BE24FA,0x69312319,0xA59B2387,
|
||||
0xF9766256,0x35DC62C8,0xBB53652B,0x77F965B5,0x7D3C6CAC,0xB1966C32,0x3F196BD1,0xF3B36B4F,
|
||||
0x2A9379E3,0xE639797D,0x68B67E9E,0xA41C7E00,0xAED97719,0x62737787,0xECFC7064,0x205670FA,
|
||||
0x85CD537D,0x496753E3,0xC7E85400,0x0B42549E,0x01875D87,0xCD2D5D19,0x43A25AFA,0x8F085A64,
|
||||
0x562848C8,0x9A824856,0x140D4FB5,0xD8A74F2B,0xD2624632,0x1EC846AC,0x9047414F,0x5CED41D1,
|
||||
0x299DC2ED,0xE537C273,0x6BB8C590,0xA712C50E,0xADD7CC17,0x617DCC89,0xEFF2CB6A,0x2358CBF4,
|
||||
0xFA78D958,0x36D2D9C6,0xB85DDE25,0x74F7DEBB,0x7E32D7A2,0xB298D73C,0x3C17D0DF,0xF0BDD041,
|
||||
0x5526F3C6,0x998CF358,0x1703F4BB,0xDBA9F425,0xD16CFD3C,0x1DC6FDA2,0x9349FA41,0x5FE3FADF,
|
||||
0x86C3E873,0x4A69E8ED,0xC4E6EF0E,0x084CEF90,0x0289E689,0xCE23E617,0x40ACE1F4,0x8C06E16A,
|
||||
0xD0EBA0BB,0x1C41A025,0x92CEA7C6,0x5E64A758,0x54A1AE41,0x980BAEDF,0x1684A93C,0xDA2EA9A2,
|
||||
0x030EBB0E,0xCFA4BB90,0x412BBC73,0x8D81BCED,0x8744B5F4,0x4BEEB56A,0xC561B289,0x09CBB217,
|
||||
0xAC509190,0x60FA910E,0xEE7596ED,0x22DF9673,0x281A9F6A,0xE4B09FF4,0x6A3F9817,0xA6959889,
|
||||
0x7FB58A25,0xB31F8ABB,0x3D908D58,0xF13A8DC6,0xFBFF84DF,0x37558441,0xB9DA83A2,0x7570833C,
|
||||
0x533B85DA,0x9F918544,0x111E82A7,0xDDB48239,0xD7718B20,0x1BDB8BBE,0x95548C5D,0x59FE8CC3,
|
||||
0x80DE9E6F,0x4C749EF1,0xC2FB9912,0x0E51998C,0x04949095,0xC83E900B,0x46B197E8,0x8A1B9776,
|
||||
0x2F80B4F1,0xE32AB46F,0x6DA5B38C,0xA10FB312,0xABCABA0B,0x6760BA95,0xE9EFBD76,0x2545BDE8,
|
||||
0xFC65AF44,0x30CFAFDA,0xBE40A839,0x72EAA8A7,0x782FA1BE,0xB485A120,0x3A0AA6C3,0xF6A0A65D,
|
||||
0xAA4DE78C,0x66E7E712,0xE868E0F1,0x24C2E06F,0x2E07E976,0xE2ADE9E8,0x6C22EE0B,0xA088EE95,
|
||||
0x79A8FC39,0xB502FCA7,0x3B8DFB44,0xF727FBDA,0xFDE2F2C3,0x3148F25D,0xBFC7F5BE,0x736DF520,
|
||||
0xD6F6D6A7,0x1A5CD639,0x94D3D1DA,0x5879D144,0x52BCD85D,0x9E16D8C3,0x1099DF20,0xDC33DFBE,
|
||||
0x0513CD12,0xC9B9CD8C,0x4736CA6F,0x8B9CCAF1,0x8159C3E8,0x4DF3C376,0xC37CC495,0x0FD6C40B,
|
||||
0x7AA64737,0xB60C47A9,0x3883404A,0xF42940D4,0xFEEC49CD,0x32464953,0xBCC94EB0,0x70634E2E,
|
||||
0xA9435C82,0x65E95C1C,0xEB665BFF,0x27CC5B61,0x2D095278,0xE1A352E6,0x6F2C5505,0xA386559B,
|
||||
0x061D761C,0xCAB77682,0x44387161,0x889271FF,0x825778E6,0x4EFD7878,0xC0727F9B,0x0CD87F05,
|
||||
0xD5F86DA9,0x19526D37,0x97DD6AD4,0x5B776A4A,0x51B26353,0x9D1863CD,0x1397642E,0xDF3D64B0,
|
||||
0x83D02561,0x4F7A25FF,0xC1F5221C,0x0D5F2282,0x079A2B9B,0xCB302B05,0x45BF2CE6,0x89152C78,
|
||||
0x50353ED4,0x9C9F3E4A,0x121039A9,0xDEBA3937,0xD47F302E,0x18D530B0,0x965A3753,0x5AF037CD,
|
||||
0xFF6B144A,0x33C114D4,0xBD4E1337,0x71E413A9,0x7B211AB0,0xB78B1A2E,0x39041DCD,0xF5AE1D53,
|
||||
0x2C8E0FFF,0xE0240F61,0x6EAB0882,0xA201081C,0xA8C40105,0x646E019B,0xEAE10678,0x264B06E6
|
||||
};
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_bitwise(const void* data, size_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
uint8_t* current = (uint8_t*) data;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
crc ^= *current++;
|
||||
|
||||
for (uint8_t j = 0; j < 8; j++)
|
||||
{
|
||||
//if (crc & 1)
|
||||
// crc = (crc >> 1) ^ Polynomial;
|
||||
//else
|
||||
// crc = crc >> 1;
|
||||
uint8_t lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
}
|
||||
|
||||
// fully unrolled
|
||||
/*uint8_t lowestBit;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;*/
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_halfbyte(const void* data, size_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
uint8_t* current = (uint8_t*) data;
|
||||
|
||||
/// look-up table for half-byte, same as crc32Lookup[0][16*i]
|
||||
static PROGMEM uint32_t crc32Lookup16[16] =
|
||||
{
|
||||
0x00000000,0x1DB71064,0x3B6E20C8,0x26D930AC,0x76DC4190,0x6B6B51F4,0x4DB26158,0x5005713C,
|
||||
0xEDB88320,0xF00F9344,0xD6D6A3E8,0xCB61B38C,0x9B64C2B0,0x86D3D2D4,0xA00AE278,0xBDBDF21C
|
||||
};
|
||||
|
||||
while (length--)
|
||||
{
|
||||
crc = pgm_read_dword_near(crc32Lookup16 + ((uint8_t(crc) ^ *current ) & 0x0F)) ^ (crc >> 4);
|
||||
crc = pgm_read_dword_near(crc32Lookup16 + ((uint8_t(crc) ^ (*current >> 4)) & 0x0F)) ^ (crc >> 4);
|
||||
current++;
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_1byte(const void* data, size_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
uint8_t* current = (uint8_t*) data;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
uint8_t offset = uint8_t(crc) ^ *current++;
|
||||
crc = (crc >> 8) ^ pgm_read_dword_near(crc32Lookup + offset);
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_4bytes(const void* data, size_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t* current = (uint32_t*) data;
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
|
||||
// process four bytes at once
|
||||
while (length >= 4)
|
||||
{
|
||||
crc ^= *current++;
|
||||
uint16_t offset3 = 3*256 + ( crc & 0xFF);
|
||||
uint16_t offset2 = 2*256 + ((crc>> 8) & 0xFF);
|
||||
uint16_t offset1 = 1*256 + ((crc>>16) & 0xFF);
|
||||
uint16_t offset0 = 0*256 + ((crc>>24) & 0xFF);
|
||||
crc = pgm_read_dword_near(crc32Lookup + offset3) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset2) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset1) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset0);
|
||||
length -= 4;
|
||||
}
|
||||
|
||||
const uint8_t* currentChar = (uint8_t*) current;
|
||||
// remaining 1 to 3 bytes (standard CRC table-based algorithm)
|
||||
while (length--)
|
||||
{
|
||||
uint8_t offset = uint8_t(crc) ^ *current++;
|
||||
crc = (crc >> 8) ^ pgm_read_dword_near(crc32Lookup + offset);
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t* current = (uint32_t*) data;
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
|
||||
// process eight bytes at once
|
||||
while (length >= 8)
|
||||
{
|
||||
uint32_t one = *current++ ^ crc;
|
||||
uint32_t two = *current++;
|
||||
uint16_t offset7 = 7*256 + ( one & 0xFF);
|
||||
uint16_t offset6 = 6*256 + ((one>> 8) & 0xFF);
|
||||
uint16_t offset5 = 5*256 + ((one>>16) & 0xFF);
|
||||
uint16_t offset4 = 4*256 + ((one>>24) & 0xFF);
|
||||
uint16_t offset3 = 3*256 + ( two & 0xFF);
|
||||
uint16_t offset2 = 2*256 + ((two>> 8) & 0xFF);
|
||||
uint16_t offset1 = 1*256 + ((two>>16) & 0xFF);
|
||||
uint16_t offset0 = 0*256 + ((two>>24) & 0xFF);
|
||||
crc = pgm_read_dword_near(crc32Lookup + offset7) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset6) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset5) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset4) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset3) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset2) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset1) ^
|
||||
pgm_read_dword_near(crc32Lookup + offset0);
|
||||
length -= 8;
|
||||
}
|
||||
|
||||
uint8_t* currentChar = (uint8_t*) current;
|
||||
// remaining 1 to 7 bytes (standard CRC table-based algorithm)
|
||||
while (length--)
|
||||
{
|
||||
uint8_t offset = uint8_t(crc) ^ *current++;
|
||||
crc = (crc >> 8) ^ pgm_read_dword_near(crc32Lookup + offset);
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
Serial.println("initialize ...");
|
||||
for (size_t i = 0; i < NumBytes; i++)
|
||||
data[i] = uint8_t(i & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
unsigned long now, millisecs, throughput;
|
||||
uint32_t crc;
|
||||
|
||||
// bitwise
|
||||
now = millis();
|
||||
for (int i = 1; i < Repetitions; i++)
|
||||
crc = crc32_bitwise(data, NumBytes);
|
||||
millisecs = millis() - now;
|
||||
throughput = (unsigned long)Repetitions * NumBytes / millisecs;
|
||||
Serial.print("crc32_bitwise = ");
|
||||
Serial.print(crc, HEX);
|
||||
Serial.print(" (");
|
||||
Serial.print(millisecs);
|
||||
Serial.print("ms, ");
|
||||
Serial.print(throughput);
|
||||
Serial.println(" kByte/s)");
|
||||
|
||||
// half-byte
|
||||
now = millis();
|
||||
for (int i = 1; i < Repetitions; i++)
|
||||
crc = crc32_halfbyte(data, NumBytes);
|
||||
millisecs = millis() - now;
|
||||
throughput = (unsigned long)Repetitions * NumBytes / millisecs;
|
||||
Serial.print("crc32_halfbyte = ");
|
||||
Serial.print(crc, HEX);
|
||||
Serial.print(" (");
|
||||
Serial.print(millisecs);
|
||||
Serial.print("ms, ");
|
||||
Serial.print(throughput);
|
||||
Serial.println(" kByte/s)");
|
||||
|
||||
// 1 byte
|
||||
now = millis();
|
||||
for (int i = 1; i < Repetitions; i++)
|
||||
crc = crc32_1byte(data, NumBytes);
|
||||
millisecs = millis() - now;
|
||||
throughput = (unsigned long)Repetitions * NumBytes / millisecs;
|
||||
Serial.print("crc32_1byte = ");
|
||||
Serial.print(crc, HEX);
|
||||
Serial.print(" (");
|
||||
Serial.print(millisecs);
|
||||
Serial.print("ms, ");
|
||||
Serial.print(throughput);
|
||||
Serial.println(" kByte/s)");
|
||||
|
||||
|
||||
// 4 bytes
|
||||
now = millis();
|
||||
for (int i = 1; i < Repetitions; i++)
|
||||
crc = crc32_4bytes(data, NumBytes);
|
||||
millisecs = millis() - now;
|
||||
throughput = (unsigned long)Repetitions * NumBytes / millisecs;
|
||||
Serial.print("crc32_4bytes = ");
|
||||
Serial.print(crc, HEX);
|
||||
Serial.print(" (");
|
||||
Serial.print(millisecs);
|
||||
Serial.print("ms, ");
|
||||
Serial.print(throughput);
|
||||
Serial.println(" kByte/s)");
|
||||
|
||||
|
||||
// 8 bytes
|
||||
now = millis();
|
||||
for (int i = 1; i < Repetitions; i++)
|
||||
crc = crc32_8bytes(data, NumBytes);
|
||||
millisecs = millis() - now;
|
||||
throughput = (unsigned long)Repetitions * NumBytes / millisecs;
|
||||
Serial.print("crc32_8bytes = ");
|
||||
Serial.print(crc, HEX);
|
||||
Serial.print(" (");
|
||||
Serial.print(millisecs);
|
||||
Serial.print("ms, ");
|
||||
Serial.print(throughput);
|
||||
Serial.println(" kByte/s)");
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
// //////////////////////////////////////////////////////////
|
||||
// Crc32Best.ino
|
||||
// Copyright (c) 2011 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
/// zlib's CRC32 polynomial
|
||||
const uint32_t Polynomial = 0xEDB88320;
|
||||
|
||||
const uint16_t NumBytes = 256;
|
||||
uint8_t data[NumBytes];
|
||||
|
||||
|
||||
PROGMEM uint32_t crc32Lookup[256] =
|
||||
{ 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
|
||||
};
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_bitwise(const void* data, uint16_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
uint8_t* current = (uint8_t*) data;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
crc ^= *current++;
|
||||
for (uint8_t j = 0; j < 8; j++)
|
||||
{
|
||||
//if (crc & 1)
|
||||
// crc = (crc >> 1) ^ Polynomial;
|
||||
//else
|
||||
// crc = crc >> 1;
|
||||
uint8_t lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
}
|
||||
|
||||
|
||||
// fully unrolled
|
||||
/*uint8_t lowestBit;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;
|
||||
lowestBit = crc & 1;
|
||||
crc >>= 1;
|
||||
if (lowestBit)
|
||||
crc ^= Polynomial;*/
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
/// compute CRC32
|
||||
uint32_t crc32_1byte(const void* data, uint16_t length, uint32_t previousCrc32 = 0)
|
||||
{
|
||||
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
|
||||
uint8_t* current = (uint8_t*) data;
|
||||
|
||||
while (length--)
|
||||
{
|
||||
uint8_t offset = uint8_t(crc) ^ *current++;
|
||||
crc = (crc >> 8) ^ pgm_read_dword_near(crc32Lookup + offset);
|
||||
}
|
||||
|
||||
return ~crc; // same as crc ^ 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
for (size_t i = 0; i < NumBytes; i++)
|
||||
data[i] = uint8_t(i & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint32_t crc = crc32_bitwise(data, NumBytes);
|
||||
Serial.println(crc, HEX);
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
// //////////////////////////////////////////////////////////
|
||||
// Crc32Test.cpp
|
||||
// Copyright (c) 2016-2019 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#include "Crc32.h"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
// the slicing-by-4/8/16 tests are only performed if the corresponding
|
||||
// preprocessor symbol is defined in Crc32.h
|
||||
// simpler algorithms can be enabled/disabled right here:
|
||||
#define CRC32_TEST_BITWISE
|
||||
#define CRC32_TEST_HALFBYTE
|
||||
#define CRC32_TEST_TABLELESS
|
||||
|
||||
// //////////////////////////////////////////////////////////
|
||||
// test code
|
||||
|
||||
/// one gigabyte
|
||||
const size_t NumBytes = 1024*1024*1024;
|
||||
/// 4k chunks during last test
|
||||
const size_t DefaultChunkSize = 4*1024;
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
// timing
|
||||
static double seconds()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER frequency, now;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
QueryPerformanceCounter (&now);
|
||||
return now.QuadPart / double(frequency.QuadPart);
|
||||
#else
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
return now.tv_sec + now.tv_nsec / 1000000000.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
printf("Please wait ...\n");
|
||||
|
||||
uint32_t randomNumber = 0x27121978;
|
||||
// initialize
|
||||
char* data = new char[NumBytes];
|
||||
for (size_t i = 0; i < NumBytes; i++)
|
||||
{
|
||||
data[i] = char(randomNumber & 0xFF);
|
||||
// simple LCG, see http://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
randomNumber = 1664525 * randomNumber + 1013904223;
|
||||
}
|
||||
|
||||
// re-use variables
|
||||
double startTime, duration;
|
||||
uint32_t crc;
|
||||
|
||||
#ifdef CRC32_TEST_BITWISE
|
||||
// bitwise
|
||||
startTime = seconds();
|
||||
crc = crc32_bitwise(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf("bitwise : CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_TEST_BITWISE
|
||||
|
||||
#ifdef CRC32_TEST_HALFBYTE
|
||||
// half-byte
|
||||
startTime = seconds();
|
||||
crc = crc32_halfbyte(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf("half-byte : CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_TEST_HALFBYTE
|
||||
|
||||
#ifdef CRC32_TEST_TABLELESS
|
||||
// one byte at once (without lookup tables)
|
||||
startTime = seconds();
|
||||
crc = crc32_1byte_tableless(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf("tableless (byte) : CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// one byte at once (without lookup tables)
|
||||
startTime = seconds();
|
||||
crc = crc32_1byte_tableless2(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf("tableless (byte2): CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_TEST_TABLELESS
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_BYTE
|
||||
// one byte at once
|
||||
startTime = seconds();
|
||||
crc = crc32_1byte(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 1 byte at once: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_USE_LOOKUP_TABLE_BYTE
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4
|
||||
// four bytes at once
|
||||
startTime = seconds();
|
||||
crc = crc32_4bytes(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 4 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_4
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8
|
||||
// eight bytes at once
|
||||
startTime = seconds();
|
||||
crc = crc32_8bytes(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 8 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// eight bytes at once, unrolled 4 times (=> 32 bytes per loop)
|
||||
startTime = seconds();
|
||||
crc = crc32_4x8bytes(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf("4x8 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8
|
||||
|
||||
#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16
|
||||
// sixteen bytes at once
|
||||
startTime = seconds();
|
||||
crc = crc32_16bytes(data, NumBytes);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 16 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// sixteen bytes at once
|
||||
startTime = seconds();
|
||||
crc = crc32_16bytes_prefetch(data, NumBytes, 0, 256);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 16 bytes at once: CRC=%08X, %.3fs, %.3f MB/s (including prefetching)\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_16
|
||||
|
||||
// process in 4k chunks
|
||||
startTime = seconds();
|
||||
crc = 0; // also default parameter of crc32_xx functions
|
||||
size_t bytesProcessed = 0;
|
||||
while (bytesProcessed < NumBytes)
|
||||
{
|
||||
size_t bytesLeft = NumBytes - bytesProcessed;
|
||||
size_t chunkSize = (DefaultChunkSize < bytesLeft) ? DefaultChunkSize : bytesLeft;
|
||||
|
||||
crc = crc32_fast(data + bytesProcessed, chunkSize, crc);
|
||||
|
||||
bytesProcessed += chunkSize;
|
||||
}
|
||||
duration = seconds() - startTime;
|
||||
printf(" chunked : CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
delete[] data;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
// //////////////////////////////////////////////////////////
|
||||
// Crc32TestMultithreaded.cpp
|
||||
// Copyright (c) 2019 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
#include "Crc32.h"
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// C++11 multithreading
|
||||
#include <thread>
|
||||
#include <future>
|
||||
|
||||
// //////////////////////////////////////////////////////////
|
||||
// test code
|
||||
|
||||
/// one gigabyte
|
||||
const size_t NumBytes = 1024*1024*1024;
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
// timing
|
||||
static double seconds()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER frequency, now;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
QueryPerformanceCounter (&now);
|
||||
return now.QuadPart / double(frequency.QuadPart);
|
||||
#else
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
return now.tv_sec + now.tv_nsec / 1000000000.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////
|
||||
// run a CRC32 algorithm on multiple threads
|
||||
typedef uint32_t (*Crc32Algorithm)(const void* data, size_t length, uint32_t previousCrc32);
|
||||
// compute CRC32 of up to maxBlockSize bytes and start recursively a new thread for excess data
|
||||
uint32_t asyncCrc32(Crc32Algorithm myCrc32, const void* data, size_t numBytes, size_t maxBlockSize)
|
||||
{
|
||||
// last block ?
|
||||
if (numBytes <= maxBlockSize)
|
||||
return myCrc32(data, numBytes, 0); // we're done
|
||||
|
||||
// compute CRC of the remaining bytes in a separate thread
|
||||
auto dataLeft = (const char*)data + maxBlockSize;
|
||||
auto bytesLeft = numBytes - maxBlockSize;
|
||||
auto remainder = std::async(std::launch::async, asyncCrc32, myCrc32, dataLeft, bytesLeft, maxBlockSize);
|
||||
|
||||
// compute CRC of the current block
|
||||
auto currentCrc = myCrc32(data, maxBlockSize, 0);
|
||||
// get CRC of the remainder
|
||||
auto remainderCrc = remainder.get();
|
||||
// and merge both
|
||||
return crc32_combine(currentCrc, remainderCrc, bytesLeft);
|
||||
}
|
||||
// call: run(crc32_8bytes, data, NumBytes, 8) if you have an octocore CPU
|
||||
uint32_t run(Crc32Algorithm myCrc32, const void* data, size_t numBytes, size_t numThreads = 0)
|
||||
{
|
||||
// run on all cores
|
||||
if (numThreads == 0)
|
||||
numThreads = std::thread::hardware_concurrency();
|
||||
|
||||
// split data evenly, rounding up
|
||||
auto defaultBlocksize = (numBytes + numThreads - 1) / numThreads;
|
||||
|
||||
return asyncCrc32(myCrc32, data, numBytes, defaultBlocksize);
|
||||
}
|
||||
|
||||
|
||||
// test original sequential CRC32 algorithm against crc32_combine
|
||||
bool testCombine(const char* data, size_t maxBytes = 1024)
|
||||
{
|
||||
bool ok = true;
|
||||
for (size_t lengthA = 1; lengthA < maxBytes; lengthA++)
|
||||
{
|
||||
// split bytes into two blocks of lengthA and lengthB
|
||||
auto lengthB = maxBytes - lengthA;
|
||||
|
||||
// compute CRC of both blocks
|
||||
auto crcA = crc32_1byte(data, lengthA);
|
||||
auto crcB = crc32_1byte(data + lengthA, lengthB);
|
||||
|
||||
// CRC of the whole block
|
||||
auto crcAtOnce = crc32_1byte(data, maxBytes);
|
||||
// CRC of both blocks in a sequential fashion
|
||||
auto crcSequential = crc32_1byte(data + lengthA, lengthB, crcA);
|
||||
|
||||
// CRC using the new crc32_combine function
|
||||
auto crcCombined = crc32_combine(crcA, crcB, lengthB);
|
||||
|
||||
// check results
|
||||
if (crcAtOnce != crcSequential || crcAtOnce != crcCombined)
|
||||
{
|
||||
printf("FAILED @ %d: %08X %08X %08X %08X %08X\n", lengthA, crcA, crcB, crcAtOnce, crcSequential, crcCombined);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// //////////////////////////////////////////////////////////
|
||||
printf("Please wait ...\n");
|
||||
|
||||
uint32_t randomNumber = 0x27121978;
|
||||
// initialize
|
||||
char* data = new char[NumBytes];
|
||||
for (size_t i = 0; i < NumBytes; i++)
|
||||
{
|
||||
data[i] = char(randomNumber & 0xFF);
|
||||
// simple LCG, see http://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
randomNumber = 1664525 * randomNumber + 1013904223;
|
||||
}
|
||||
|
||||
// re-use variables
|
||||
double startTime, duration;
|
||||
uint32_t crc;
|
||||
std::vector<std::future<uint32_t>> futures;
|
||||
|
||||
// number of threads: use all cores by default or set number as command-line parameter
|
||||
auto numThreads = 0;
|
||||
if (argc == 2)
|
||||
numThreads = std::stoi(argv[1]);
|
||||
if (numThreads <= 0)
|
||||
numThreads = std::thread::hardware_concurrency();
|
||||
printf("use %d threads:\n", numThreads);
|
||||
|
||||
// //////////////////////////////////////////////////////////
|
||||
// one byte at once
|
||||
startTime = seconds();
|
||||
crc = run(crc32_1byte, data, NumBytes, numThreads);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 1 byte at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
numThreads, crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// four bytes at once
|
||||
startTime = seconds();
|
||||
crc = run(crc32_4bytes, data, NumBytes, numThreads);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 4 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
numThreads, crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// eight bytes at once
|
||||
startTime = seconds();
|
||||
crc = run(crc32_8bytes, data, NumBytes, numThreads);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
numThreads, crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// eight bytes at once, unrolled 4 times (=> 32 bytes per loop)
|
||||
startTime = seconds();
|
||||
crc = run(crc32_4x8bytes, data, NumBytes, numThreads);
|
||||
duration = seconds() - startTime;
|
||||
printf("4x8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
numThreads, crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// sixteen bytes at once
|
||||
startTime = seconds();
|
||||
crc = run(crc32_16bytes, data, NumBytes, numThreads);
|
||||
duration = seconds() - startTime;
|
||||
printf(" 16 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
numThreads, crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
|
||||
// //////////////////////////////////////////////////////////
|
||||
// slowly increment number of threads to determine scalability
|
||||
printf("run slicing-by-8 algorithm with 1 to %d threads:\n", numThreads);
|
||||
for (auto scaleThreads = 1; scaleThreads <= numThreads; scaleThreads++)
|
||||
{
|
||||
// eight bytes at once
|
||||
startTime = seconds();
|
||||
|
||||
if (scaleThreads == 1)
|
||||
crc = crc32_8bytes (data, NumBytes); // single-threaded
|
||||
else
|
||||
crc = run(crc32_8bytes, data, NumBytes, scaleThreads); // multi-threaded
|
||||
|
||||
duration = seconds() - startTime;
|
||||
printf(" 8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n",
|
||||
scaleThreads, crc, duration, (NumBytes / (1024*1024)) / duration);
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////
|
||||
// verify crc32_combine
|
||||
if (!testCombine(data, 1024))
|
||||
printf("ERROR in crc32_combine !!!\n");
|
||||
|
||||
delete[] data;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
zlib License
|
||||
|
||||
Copyright (c) 2011-2016 Stephan Brumme
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
|
@ -0,0 +1,26 @@
|
|||
# simple Makefile
|
||||
#CXX = g++
|
||||
|
||||
# files
|
||||
PROGRAM = Crc32Test
|
||||
LIBS = -lrt
|
||||
HEADERS = Crc32.h
|
||||
OBJECTS = Crc32.o Crc32Test.o
|
||||
|
||||
# flags
|
||||
FLAGS = -O3 -Wall -Wextra -pedantic -s
|
||||
|
||||
default: $(PROGRAM)
|
||||
all: default
|
||||
|
||||
$(PROGRAM): $(OBJECTS) Makefile
|
||||
$(CXX) $(OBJECTS) $(FLAGS) $(LIBS) -o $(PROGRAM)
|
||||
|
||||
%.o: %.cpp $(HEADERS) Makefile
|
||||
$(CXX) $(FLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
-rm -f $(OBJECTS) $(PROGRAM)
|
||||
|
||||
run: $(PROGRAM)
|
||||
./$(PROGRAM)
|
|
@ -0,0 +1,38 @@
|
|||
# Changelog
|
||||
This file tracks the main changes to my CRC32 library.
|
||||
|
||||
project website: https://create.stephan-brumme.com/crc32/
|
||||
GitHub mirror: https://github.com/stbrumme/crc32/
|
||||
|
||||
## December 6, 2019 (version 9)
|
||||
- added support for multi-threaded computation
|
||||
|
||||
## November 27, 2019
|
||||
- use C++'s include names
|
||||
- removed warning on little-endian systems
|
||||
- fixed typo in comments
|
||||
|
||||
## May 27, 2019 (version 8)
|
||||
- fixed misspelt preprocessor symbol
|
||||
|
||||
## October 21, 2016 (version 7)
|
||||
- changed code structure into a library format
|
||||
- added tableless byte algorithms
|
||||
|
||||
## August 14, 2015 (version 6)
|
||||
- improved #ifdefs for Cygwin, MinGW and Clang
|
||||
|
||||
## February 4, 2015 (version 5)
|
||||
- added Slicing-by-16
|
||||
|
||||
## August 12, 2014 (version 4)
|
||||
- added Javascript port
|
||||
|
||||
## May 4, 2013 (version 3)
|
||||
- endian aware, slightly faster Slicing-by-8
|
||||
|
||||
## November 13, 2011 (version 2)
|
||||
- improved portability
|
||||
|
||||
## November 10, 2011 (version 1)
|
||||
- initial release
|
|
@ -0,0 +1,43 @@
|
|||
// //////////////////////////////////////////////////////////
|
||||
// crc32.js
|
||||
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
|
||||
// see http://create.stephan-brumme.com/disclaimer.html
|
||||
//
|
||||
|
||||
function hex(what)
|
||||
{
|
||||
// adjust negative numbers
|
||||
if (what < 0)
|
||||
what = 0xFFFFFFFF + what + 1;
|
||||
// convert to hexadecimal string
|
||||
var result = what.toString(16);
|
||||
// add leading zeros
|
||||
return ('0000000' + result).slice(-8);
|
||||
}
|
||||
|
||||
function crc32_bitwise(text)
|
||||
{
|
||||
// CRC32b polynomial
|
||||
var Polynomial = 0xEDB88320;
|
||||
// start value
|
||||
var crc = 0xFFFFFFFF;
|
||||
|
||||
for (var i = 0; i < text.length; i++)
|
||||
{
|
||||
// XOR next byte into state
|
||||
crc ^= text.charCodeAt(i);
|
||||
|
||||
// process 8 bits
|
||||
for (var bit = 0; bit < 8; bit++)
|
||||
{
|
||||
// look at lowest bit
|
||||
if ((crc & 1) != 0)
|
||||
crc = (crc >>> 1) ^ Polynomial;
|
||||
else
|
||||
crc = crc >>> 1;
|
||||
}
|
||||
}
|
||||
|
||||
// return hex string
|
||||
return hex(~crc);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# Fast CRC32
|
||||
|
||||
This is a mirror of my CRC32 library hosted at https://create.stephan-brumme.com/crc32/
|
||||
|
||||
Features in a nutshell:
|
||||
- C++ code, single file
|
||||
- the fastest algorithms need about 1 CPU cycle per byte
|
||||
- endian-aware
|
||||
- support for multi-threaded computation
|
||||
- runs even on Arduino, Raspberry Pi, etc.
|
||||
- quite long posting about it on https://create.stephan-brumme.com/crc32/, describing each implemented algorithm in detail
|
||||
|
||||
Algorithms:
|
||||
- bitwise
|
||||
- branch-free bitwise
|
||||
- half-byte
|
||||
- tableless full-byte
|
||||
- Sarwate's original algorithm
|
||||
- slicing-by-4
|
||||
- slicing-by-8
|
||||
- slicing-by-16
|
||||
|
||||
- crc32_combine() "merges" two indepedently computed CRC32 values which is the basis for even faster multi-threaded calculation
|
||||
|
||||
See my website https://create.stephan-brumme.com/crc32/ for documentation, code examples and a benchmark.
|
|
@ -0,0 +1,98 @@
|
|||
#include "BSidesMessaging.h"
|
||||
#include <string.h>
|
||||
#include <Crc32.h>
|
||||
|
||||
// Monotonically-increasing sequence number
|
||||
static uint8_t monotonicSequenceNumber;
|
||||
|
||||
bool prepareMessage(SerialMessage &msg, MessageType type, uint8_t seqNo, const void *data, size_t datalen) {
|
||||
if ((datalen > SERIALBRIDGE_MESSAGE_DATA_SIZE_MAX)
|
||||
|| (datalen > 0 && data == NULL)
|
||||
|| (datalen == 0 && data != NULL)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
memset((void*)&msg, 0, sizeof(msg));
|
||||
msg.header.magic = SERIALBRIDGE_MESSAGE_MAGIC;
|
||||
msg.header.seqNo = seqNo;
|
||||
msg.header.type = type;
|
||||
msg.header.version = SERIALBRIDGE_MESSAGE_CURRENT_VERSION;
|
||||
if (datalen > 0) {
|
||||
memcpy((void*)(&msg.data.payload), data, datalen);
|
||||
}
|
||||
uint32_t crc32 = crc32_bitwise((void*)&msg, SERIALBRIDGE_MESSAGE_SIZE, 0);
|
||||
msg.header.crc32 = crc32;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateMessage(const SerialMessage &msg) {
|
||||
if ((msg.header.magic != SERIALBRIDGE_MESSAGE_MAGIC)
|
||||
|| (msg.header.version > SERIALBRIDGE_MESSAGE_CURRENT_VERSION)
|
||||
|| (msg.header.type < SERIALBRIDGE_MESSAGE_TYPE_MIN)
|
||||
|| (msg.header.type >= SERIALBRIDGE_MESSAGE_TYPE_MAX)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
// validate CRC32
|
||||
SerialMessage crcCheck = msg;
|
||||
// Set crc to zero for calculation
|
||||
crcCheck.header.crc32 = 0;
|
||||
uint32_t crc32_to_compare = msg.header.crc32;
|
||||
uint32_t crc32_calculated = crc32_bitwise((void*)&crcCheck, SERIALBRIDGE_MESSAGE_SIZE, 0);
|
||||
return crc32_to_compare == crc32_calculated;
|
||||
}
|
||||
|
||||
uint8_t nextSequenceNumber(void) {
|
||||
return monotonicSequenceNumber++;
|
||||
}
|
||||
|
||||
bool enqueueMessage(const SerialMessage &msg, SerialMessageQueue &queue) {
|
||||
if (!validateMessage(msg)) {
|
||||
return false;
|
||||
}
|
||||
queue.push(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dequeueMessage(SerialMessage *msgOut, SerialMessageQueue &queue) {
|
||||
if (queue.isEmpty() || (msgOut == NULL)) {
|
||||
return false;
|
||||
}
|
||||
// Consume the first message
|
||||
SerialMessage msg = queue.pop();
|
||||
if (!validateMessage(msg)) {
|
||||
return false;
|
||||
}
|
||||
memcpy(msgOut, &msg, SERIALBRIDGE_MESSAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* messageType(MessageType type) {
|
||||
switch (type) {
|
||||
case VBATRequest: return "VBATRequest";
|
||||
case VBATResponse: return "VBATResponse";
|
||||
case IRdASend: return "IRdASend";
|
||||
case IRdARecv: return "IRdARecv";
|
||||
case IRdACheck: return "IRdACheck";
|
||||
case IMUEvent: return "IMUEvent";
|
||||
case AudioEvent: return "AudioEvent";
|
||||
case WiFiEvent: return "WiFiEvent";
|
||||
case BluetoothEvent: return "BluetoothEvent";
|
||||
case SDEvent: return "SDEvent";
|
||||
case SAOWireSend: return "SAOWireSend";
|
||||
case SAOWireRequest: return "SAOWireRequest";
|
||||
case SAOGPIOGet: return "SAOGPIOGet";
|
||||
case SAOGPIOSet: return "SAOGPIOSet";
|
||||
case SAOGPIOVal: return "SAOGPIOVal";
|
||||
case LEDSet: return "LEDSet";
|
||||
case Capsense: return "Capsense";
|
||||
case CapsenseFeedbackEnable: return "Capsense feedback enable";
|
||||
case DPad: return "DPad";
|
||||
case SAMD_Suspend: return "Suspend";
|
||||
case Diagnostics_PING: return "PING";
|
||||
case Diagnostics_PONG: return "PONG";
|
||||
case Message_ACK: return "ACK";
|
||||
case Message_NACK: return "NACK";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
#include <cstdarg>
|
||||
#include <cstdbool>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "BadgeLog.h"
|
||||
#ifdef SAMD21
|
||||
#include "SerialBridge.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Internal definitions
|
||||
*/
|
||||
#ifndef LOG_RINGBUF_SZ
|
||||
#define LOG_RINGBUF_SZ (4096U)
|
||||
#endif//LOG_RINGBUF_SZ
|
||||
|
||||
/* Log entries are truncated to a maximum of `LOG_MAX_SZ - 1` characters */
|
||||
#ifndef LOG_MAX_SZ
|
||||
#define LOG_MAX_SZ (256U)
|
||||
#endif//LOG_MAX_SZ$
|
||||
|
||||
#ifndef DEFAULT_BADGEOS_LOG_LEVEL
|
||||
#define DEFAULT_BADGEOS_LOG_LEVEL (LOG_INFO)
|
||||
#endif//DEFAULT_BADGEOS_LOG_LEVEL
|
||||
|
||||
#ifndef LOG_LEVEL
|
||||
# ifdef CONFIG_BADGEOS_LOG_LEVEL
|
||||
# define LOG_LEVEL (CONFIG_BADGEOS_LOG_LEVEL)
|
||||
# else
|
||||
# define LOG_LEVEL (DEFAULT_BADGEOS_LOG_LEVEL)
|
||||
# endif
|
||||
#endif//LOG_LEVEL
|
||||
|
||||
#ifndef LOG_DECORATE
|
||||
#define LOG_DECORATE (LOG_DECORATED)
|
||||
#endif//LOG_DECORATE
|
||||
|
||||
/**
|
||||
* Logging ringbuffer
|
||||
*/
|
||||
static char ringbuf[LOG_RINGBUF_SZ];
|
||||
static char *cur_r = ringbuf, *cur_w = ringbuf;
|
||||
#define _RINGBUF_END (&ringbuf[sizeof(ringbuf)])
|
||||
|
||||
/* Cursor management */
|
||||
static inline size_t _cur_w_sz(bool contig) {
|
||||
char *stop;
|
||||
ptrdiff_t sz;
|
||||
|
||||
if (contig) {
|
||||
stop = cur_r > cur_w ? cur_r : _RINGBUF_END;
|
||||
} else {
|
||||
stop = cur_r + sizeof(ringbuf);
|
||||
}
|
||||
sz = stop - cur_w;
|
||||
return (sz >= 0) ? (size_t) sz : 0;
|
||||
}
|
||||
static inline void _cur_adv(char **cur_p, const size_t sz) {
|
||||
*cur_p += sz;
|
||||
while (*cur_p >= _RINGBUF_END) *cur_p -= LOG_RINGBUF_SZ;
|
||||
}
|
||||
/* R/W */
|
||||
static inline size_t _ring_rd(char *buf, size_t buf_sz) {
|
||||
size_t i;
|
||||
for (i = 0; buf_sz-- >= 0; ++i, ++buf) {
|
||||
/* Immediately bail if we're about to copy from the write cursor */
|
||||
if (cur_r == cur_w) break;
|
||||
*buf = *cur_r;
|
||||
/* Check if we hit a NUL before advancing `cur_r` */
|
||||
if (*(cur_r++) == '\0') break;
|
||||
if (cur_r >= _RINGBUF_END) cur_r -= LOG_RINGBUF_SZ;
|
||||
}
|
||||
/* Ensure we always NUL terminate */
|
||||
*buf = '\0';
|
||||
return i;
|
||||
}
|
||||
static inline void _ring_wr(const char * buf, size_t buf_sz) {
|
||||
while (buf_sz-- >= 0 && *buf != '\0') {
|
||||
*(cur_w++) = *(buf++);
|
||||
if (cur_w >= _RINGBUF_END) cur_w -= LOG_RINGBUF_SZ;
|
||||
}
|
||||
*(cur_w++) = '\0';
|
||||
}
|
||||
|
||||
/* Entry truncation logic */
|
||||
static const char _trunc_s[] = "[trunc]";
|
||||
static inline void _mark_trunc(char * const buf, const size_t buf_sz) {
|
||||
/* If we don't have room for the marker, do nothing */
|
||||
if (sizeof(_trunc_s) < buf_sz) {
|
||||
strncpy(buf + buf_sz - sizeof(_trunc_s), _trunc_s, sizeof(_trunc_s));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual logging
|
||||
*/
|
||||
static log_level_e _g_level = LOG_LEVEL;
|
||||
void set_log_level(const log_level_e level) {
|
||||
_g_level = level;
|
||||
}
|
||||
|
||||
static log_decoration_e _g_decorate = LOG_DECORATE;
|
||||
void set_log_decoration(const log_decoration_e decorate) {
|
||||
_g_decorate = decorate;
|
||||
}
|
||||
|
||||
static const char *_level_as[] = {
|
||||
[LOG_NOTSET] = "NOT SET",
|
||||
[LOG_TRACE] = "TRACE",
|
||||
[LOG_DEBUG] = "DEBUG",
|
||||
[LOG_INFO] = "INFO",
|
||||
[LOG_WARN] = "WARN",
|
||||
[LOG_ERROR] = "ERROR",
|
||||
[LOG_CRITICAL] = "CRITICAL",
|
||||
[LOG_PANIC] = "PANIC",
|
||||
[_LOG_MAX_LV] = "UNKNOWN",
|
||||
};
|
||||
|
||||
void _do_log(
|
||||
const log_level_e level, const log_decoration_e decoration,
|
||||
const char * const fmt, va_list ap
|
||||
) {
|
||||
bool direct;
|
||||
char *ent, *p;
|
||||
int sprint_sz, ent_sz = 0;
|
||||
|
||||
/* Bail early if this is below the current level */
|
||||
if (level < _g_level) return;
|
||||
|
||||
/* Fastest path is to format directly into the ring buffer */
|
||||
if (_cur_w_sz(true) >= LOG_MAX_SZ) {
|
||||
direct = true;
|
||||
ent = cur_w;
|
||||
} else {
|
||||
direct = false;
|
||||
ent = (char *) alloca(LOG_MAX_SZ);
|
||||
}
|
||||
/* We have a pointer to our current cursor in the entry being formatted */
|
||||
p = ent;
|
||||
|
||||
/* If we need to decorate the log entry, attempt to do so but never consume
|
||||
* more than a quarter of the buffer size (arbitrarily selected).
|
||||
*/
|
||||
if (decoration == LOG_DECORATED) {
|
||||
const size_t dec_max = LOG_MAX_SZ >> 2;
|
||||
/* Find the appropriate log level string for decoration and fall back
|
||||
* to the maximum value for "UNKNOWN" if we are out of bounds or NULL.
|
||||
*/
|
||||
const char *lv_s = _level_as[level < _LOG_MAX_LV ? level : _LOG_MAX_LV];
|
||||
if (lv_s == NULL) lv_s = _level_as[_LOG_MAX_LV];
|
||||
/* If we fail here, we can't really recover. Bail immediately without
|
||||
* advancing the cursor (for direct writes) so that the next entry will
|
||||
* overwrite the decoration we just wrote, or allow it to fall out of
|
||||
* the stack once we return (for indirect).
|
||||
*/
|
||||
sprint_sz = snprintf(p, dec_max, "[%s:%lu] ", lv_s, millis());
|
||||
if (sprint_sz < 0) return;
|
||||
/* Ensure that if the decoration was truncated we have a close brace */
|
||||
if (sprint_sz >= dec_max) {
|
||||
ent[dec_max - 1] = ']';
|
||||
sprint_sz = dec_max; /* Advance to the trailing NUL */
|
||||
}
|
||||
/* Advance the entry cursor and size */
|
||||
p += sprint_sz;
|
||||
ent_sz += sprint_sz;
|
||||
}
|
||||
|
||||
/* Perform the log string formatting */
|
||||
sprint_sz = vsnprintf(p, LOG_MAX_SZ - ent_sz, fmt, ap);
|
||||
|
||||
/* If we didn't error out, we need to either advance the cursor for direct
|
||||
* writes or use the ringbuf helper to do a potentialy segmented write.
|
||||
* Otherwise we'll fall through without advancing the cursor/writing to the
|
||||
* ring buffer.
|
||||
*/
|
||||
if (sprint_sz >= 0) {
|
||||
ent_sz += sprint_sz;
|
||||
/* If the sum of the prior `ent_sz` and the size returned by
|
||||
* `vsnprintf()` is equal to or greater than the maximum buffer size,
|
||||
* that indicates the formatted string was truncated and we filled the
|
||||
* space in the buffer we allowed ourselves to use (including a NUL).
|
||||
*/
|
||||
if (ent_sz >= LOG_MAX_SZ) {
|
||||
_mark_trunc(ent, LOG_MAX_SZ);
|
||||
/* We only wrote this much, not including the trailing NUL which will
|
||||
* be accounted for below.
|
||||
*/
|
||||
ent_sz = LOG_MAX_SZ - 1;
|
||||
}
|
||||
ent_sz += 1; /* Account for the trailing NUL first */
|
||||
if (direct) _cur_adv(&cur_w, (size_t) ent_sz);
|
||||
else _ring_wr(ent, ent_sz);
|
||||
}
|
||||
}
|
||||
|
||||
void log(const log_level_e level,
|
||||
const char * const fmt, ...
|
||||
) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
_do_log(level, _g_decorate, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void log(const log_level_e level, const log_decoration_e decoration,
|
||||
const char * const fmt, ...
|
||||
) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
_do_log(level, decoration, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Dump all pending log entries manually */
|
||||
void log_dump(void) {
|
||||
char buf[LOG_MAX_SZ];
|
||||
while (_ring_rd(buf, sizeof(buf)) > 0) {
|
||||
#ifndef __unix__
|
||||
Serial.println(buf);
|
||||
#ifdef SAMD21
|
||||
DebugSerial.println(buf);
|
||||
#endif
|
||||
#else
|
||||
printf("%s\n", buf);
|
||||
fflush(NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
#include <cstdbool>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef ARDUINO_SAMD_MKRZERO
|
||||
#ifndef SAMD21
|
||||
#define SAMD21
|
||||
#endif
|
||||
#endif // ARDUINO_SAMD_MKRZERO
|
||||
|
||||
#ifdef ESP32
|
||||
#define HAS_BRIDGELINK
|
||||
#define BRIDGELINK_NEEDS_FLUSH true
|
||||
#include <HardwareSerial.h>
|
||||
#endif
|
||||
#ifdef SAMD21
|
||||
#define HAS_BRIDGELINK
|
||||
#define BRIDGELINK_NEEDS_FLUSH
|
||||
#include <Arduino.h>
|
||||
#include "wiring_private.h" // pinPeripheral() function
|
||||
#endif
|
||||
#ifdef __unix__
|
||||
#include <SoftwareSerial.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <BadgeLog.h>
|
||||
|
||||
#include "SerialBridge.h"
|
||||
// Include pin assignments
|
||||
#include "badge_pins.h"
|
||||
|
||||
#ifdef SAMD21
|
||||
// SAMD21 Arduino pinouts for UART bridge use -- we set up a Serial object here on the relevant pins
|
||||
// UART_RXD on SERCOM4, PAD[0]
|
||||
// UART_TXD on SERCOM4, PAD[2];
|
||||
Uart BridgeLink(&sercom4, UART_RXD, UART_TXD, SERCOM_RX_PAD_0, UART_TX_PAD_2);
|
||||
Uart DebugSerial(&sercom0, UART_SCI_RXD, UART_SCI_TXD, SERCOM_RX_PAD_3, UART_TX_PAD_2);
|
||||
void SERCOM4_Handler()
|
||||
{
|
||||
BridgeLink.IrqHandler();
|
||||
}
|
||||
void SERCOM0_Handler()
|
||||
{
|
||||
DebugSerial.IrqHandler();
|
||||
}
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
// ESP32 pinouts don't define a serial bridge on these pins, so we make our own
|
||||
// We take over UART #1
|
||||
HardwareSerial BridgeLink(1);
|
||||
#endif
|
||||
|
||||
SerialBridgeLink::SerialBridgeLink()
|
||||
{
|
||||
}
|
||||
|
||||
void SerialBridgeLink::begin(unsigned long baud)
|
||||
{
|
||||
log(LOG_INFO, "Connecting Serial Link");
|
||||
#ifdef SAMD21
|
||||
pinPeripheral(UART_RXD, PIO_SERCOM_ALT);
|
||||
pinPeripheral(UART_TXD, PIO_SERCOM_ALT);
|
||||
pinPeripheral(UART_SCI_RXD, PIO_SERCOM);
|
||||
pinPeripheral(UART_SCI_TXD, PIO_SERCOM);
|
||||
BridgeLink.begin(baud);
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
BridgeLink.begin(baud, SERIAL_8N1, UART_RXD, UART_TXD);
|
||||
#endif
|
||||
log(LOG_INFO, "Connected");
|
||||
}
|
||||
|
||||
void SerialBridgeLink::end(void)
|
||||
{
|
||||
#ifdef HAS_BRIDGELINK
|
||||
return BridgeLink.end();
|
||||
#endif
|
||||
}
|
||||
|
||||
int SerialBridgeLink::available(void)
|
||||
{
|
||||
#ifdef HAS_BRIDGELINK
|
||||
return BridgeLink.available();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int SerialBridgeLink::read(void)
|
||||
{
|
||||
#ifdef HAS_BRIDGELINK
|
||||
return BridgeLink.read();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SerialBridgeLink::flush(void)
|
||||
{
|
||||
#ifdef HAS_BRIDGELINK
|
||||
return BridgeLink.flush(BRIDGELINK_NEEDS_FLUSH);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t SerialBridgeLink::write(uint8_t value)
|
||||
{
|
||||
#ifdef HAS_BRIDGELINK
|
||||
return BridgeLink.write(value);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
SerialBridge::SerialBridge()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SerialBridge::connect(void)
|
||||
{
|
||||
this->link.begin();
|
||||
}
|
||||
|
||||
void SerialBridge::disconnect(void)
|
||||
{
|
||||
this->link.end();
|
||||
}
|
||||
|
||||
int SerialBridge::available(void)
|
||||
{
|
||||
return this->link.available();
|
||||
}
|
||||
|
||||
/* These are intended to ensure we get always get the start and end of a message, but
|
||||
* we don't currently do anything to mark framing past this. Any application layer
|
||||
* protocol on to of this wire protocol can handle SYNACKs if need be.
|
||||
*/
|
||||
#define SERIALBRIDGE_SYNC (0b11011001U)
|
||||
#define SERIALBRIDGE_EOF (0b00100110U)
|
||||
// 1 SYNC transmits appears to be enough for a mostly reliable line during busy messaging
|
||||
#define SERIALBRIDGE_SYNC_TX (1U)
|
||||
|
||||
bool SerialBridge::sendMessage(const SerialMessage& msg) {
|
||||
// Send sync bytes
|
||||
for (int i = 0; i < SERIALBRIDGE_SYNC_TX; ++i) {
|
||||
if (this->link.write(SERIALBRIDGE_SYNC) != 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ssize_t sent = this->send(&msg, SERIALBRIDGE_MESSAGE_SIZE);
|
||||
if (sent != SERIALBRIDGE_MESSAGE_SIZE) {
|
||||
return false;
|
||||
}
|
||||
// We send a single EOF
|
||||
if (this->link.write(SERIALBRIDGE_EOF) != 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SerialBridge::sendAckMessage(uint8_t seqNo) {
|
||||
SerialMessage msg;
|
||||
prepareMessage(msg, Message_ACK, seqNo, NULL, 0);
|
||||
log(LOG_DEBUG, "ACK message %d", seqNo);
|
||||
this->sendMessage(msg);
|
||||
}
|
||||
|
||||
void SerialBridge::sendNackMessage(uint8_t seqNo) {
|
||||
SerialMessage msg;
|
||||
prepareMessage(msg, Message_NACK, seqNo, NULL, 0);
|
||||
log(LOG_DEBUG, "NACK message %d", seqNo);
|
||||
this->sendMessage(msg);
|
||||
}
|
||||
|
||||
bool SerialBridge::recvMessage(SerialMessage* msg) {
|
||||
if (this->link.available() < (SERIALBRIDGE_MESSAGE_SIZE + (SERIALBRIDGE_SYNC_TX))) {
|
||||
log(LOG_DEBUG, "Not enough bytes to be a minimally valid message");
|
||||
return false;
|
||||
}
|
||||
// Find a SYNC byte
|
||||
uint8_t sync = 0;
|
||||
while ((sync != SERIALBRIDGE_SYNC) && (this->link.available() > 0)) {
|
||||
sync = this->link.read();
|
||||
}
|
||||
// Consume SYNC bytes
|
||||
while ((sync == SERIALBRIDGE_SYNC) && (this->link.available() > 0)) {
|
||||
sync = this->link.read();
|
||||
}
|
||||
// Ensure we haven't just consumed SYNCs
|
||||
if (sync == SERIALBRIDGE_SYNC) {
|
||||
log(LOG_ERROR, "Failed to find message");
|
||||
return false;
|
||||
}
|
||||
// Put the first byte in and consume the rest of the message
|
||||
uint8_t *buf = (uint8_t*)msg;
|
||||
buf[0] = sync;
|
||||
buf++;
|
||||
ssize_t recvd = this->recv((void*)buf, SERIALBRIDGE_MESSAGE_SIZE - 1) + 1;
|
||||
if (recvd < (SERIALBRIDGE_MESSAGE_SIZE - 1)) {
|
||||
log(LOG_DEBUG, "Not a full message: received %d expected %d", recvd, SERIALBRIDGE_MESSAGE_SIZE);
|
||||
}
|
||||
// Consume until EOF byte found
|
||||
sync = 0;
|
||||
while ((sync != SERIALBRIDGE_EOF) && (this->link.available() > 0)) {
|
||||
sync = this->link.read();
|
||||
}
|
||||
if (!validateMessage(*msg)) {
|
||||
log(LOG_ERROR, "Invalid %s message", messageType(msg->header.type));
|
||||
// Don't (n)ACK a (n)ACK
|
||||
if ((msg->header.type != Message_ACK)
|
||||
&& (msg->header.type != Message_NACK)) {
|
||||
this->sendNackMessage(msg->header.seqNo);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Don't (n)ACK a (n)ACK
|
||||
if ((msg->header.type != Message_ACK)
|
||||
&& (msg->header.type != Message_NACK)) {
|
||||
this->sendAckMessage(msg->header.seqNo);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ssize_t SerialBridge::send(const void *buf, size_t buf_size)
|
||||
{
|
||||
size_t i = -1;
|
||||
#ifdef HAS_BRIDGELINK
|
||||
uint8_t *p = (uint8_t*) buf;
|
||||
|
||||
for ( i = 0; i < buf_size; i++ ) {
|
||||
if (this->link.write(p[i]) != 1) goto flush;
|
||||
}
|
||||
|
||||
flush:
|
||||
this->link.flush();
|
||||
#endif
|
||||
return (ssize_t)i;
|
||||
}
|
||||
|
||||
ssize_t SerialBridge::recv(void *buf, size_t buf_size)
|
||||
{
|
||||
uint8_t *p = (uint8_t*)buf;
|
||||
int offset = -1;
|
||||
#ifdef HAS_BRIDGELINK
|
||||
while (this->link.available() && offset < (int)buf_size) {
|
||||
++offset;
|
||||
p[offset] = this->link.read();
|
||||
}
|
||||
#endif
|
||||
return offset;
|
||||
}
|
|
@ -0,0 +1,549 @@
|
|||
/***** Includes *****/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "icm20602.h"
|
||||
|
||||
/***** Defines *****/
|
||||
|
||||
#define REG_XG_OFFS_TC_H 0x04
|
||||
#define REG_XG_OFFS_TC_L 0x05
|
||||
#define REG_YG_OFFS_TC_H 0x07
|
||||
#define REG_YG_OFFS_TC_L 0x08
|
||||
#define REG_ZG_OFFS_TC_H 0x0A
|
||||
#define REG_ZG_OFFS_TC_L 0x0B
|
||||
#define REG_SELF_TEST_X_ACCEL 0x0D
|
||||
#define REG_SELF_TEST_Y_ACCEL 0x0E
|
||||
#define REG_SELF_TEST_Z_ACCEL 0x0F
|
||||
#define REG_XG_OFFS_USRH 0x13
|
||||
#define REG_XG_OFFS_USRL 0x14
|
||||
#define REG_YG_OFFS_USRH 0x15
|
||||
#define REG_YG_OFFS_USRL 0x16
|
||||
#define REG_ZG_OFFS_USRH 0x17
|
||||
#define REG_ZG_OFFS_USRL 0x18
|
||||
#define REG_SMPLRT_DIV 0x19
|
||||
#define REG_CONFIG 0x1A
|
||||
#define REG_GYRO_CONFIG 0x1B
|
||||
#define REG_ACCEL_CONFIG 0x1C
|
||||
#define REG_ACCEL_CONFIG_2 0x1D
|
||||
#define REG_LP_MODE_CFG 0x1E
|
||||
#define REG_ACCEL_WOM_X_THR 0x20
|
||||
#define REG_ACCEL_WOM_Y_THR 0x21
|
||||
#define REG_ACCEL_WOM_Z_THR 0x22
|
||||
#define REG_FIFO_EN 0x23
|
||||
#define REG_FSYNC_INT 0x36
|
||||
#define REG_INT_PIN_CFG 0x37
|
||||
#define REG_INT_ENABLE 0x38
|
||||
#define REG_FIFO_WM_INT_STATUS 0x39
|
||||
#define REG_INT_STATUS 0x3A
|
||||
#define REG_ACCEL_XOUT_H 0x3B
|
||||
#define REG_ACCEL_XOUT_L 0x3C
|
||||
#define REG_ACCEL_YOUT_H 0x3D
|
||||
#define REG_ACCEL_YOUT_L 0x3E
|
||||
#define REG_ACCEL_ZOUT_H 0x3F
|
||||
#define REG_ACCEL_ZOUT_L 0x40
|
||||
#define REG_TEMP_OUT_H 0x41
|
||||
#define REG_TEMP_OUT_L 0x42
|
||||
#define REG_GYRO_XOUT_H 0x43
|
||||
#define REG_GYRO_XOUT_L 0x44
|
||||
#define REG_GYRO_YOUT_H 0x45
|
||||
#define REG_GYRO_YOUT_L 0x46
|
||||
#define REG_GYRO_ZOUT_H 0x47
|
||||
#define REG_GYRO_ZOUT_L 0x48
|
||||
#define REG_SELF_TEST_X_GYRO 0x50
|
||||
#define REG_SELF_TEST_Y_GYRO 0x51
|
||||
#define REG_SELF_TEST_Z_GYRO 0x52
|
||||
#define REG_FIFO_WM_TH1 0x60
|
||||
#define REG_FIFO_WM_TH2 0x61
|
||||
#define REG_SIGNAL_PATH_RESET 0x68
|
||||
#define REG_ACCEL_INTEL_CTRL 0x69
|
||||
#define REG_USER_CTRL 0x6A
|
||||
#define REG_PWR_MGMT_1 0x6B
|
||||
#define REG_PWR_MGMT_2 0x6C
|
||||
#define REG_I2C_IF 0x70
|
||||
#define REG_FIFO_COUNTH 0x72
|
||||
#define REG_FIFO_COUNTL 0x73
|
||||
#define REG_FIFO_R_W 0x74
|
||||
#define REG_WHO_AM_I 0x75
|
||||
#define REG_XA_OFFSET_H 0x77
|
||||
#define REG_XA_OFFSET_L 0x78
|
||||
#define REG_YA_OFFSET_H 0x7A
|
||||
#define REG_YA_OFFSET_L 0x7B
|
||||
#define REG_ZA_OFFSET_H 0x7D
|
||||
#define REG_ZA_OFFSET_L 0x7E
|
||||
|
||||
#define REG_WHO_AM_I_CONST 0X12
|
||||
|
||||
/***** Macros *****/
|
||||
|
||||
#define ON_ERROR_GOTO(cond, symbol) \
|
||||
if (!(cond)) { goto symbol; }
|
||||
|
||||
// extra steps, but I'm paranoid about some compilers/systems not handling the
|
||||
// conversion from uint8_t to int16_t correctly
|
||||
#define UINT8_TO_INT16(dst, src_high, src_low) \
|
||||
do { \
|
||||
dst = (src_high); \
|
||||
dst <<= 8; \
|
||||
dst |= (src_low); \
|
||||
} while (0);
|
||||
|
||||
/***** Local Data *****/
|
||||
|
||||
// TODO: Look into getting real temp sensitivity.
|
||||
static float _temp_sensitivity = 326.8;
|
||||
|
||||
/***** Local Functions *****/
|
||||
|
||||
/// Used to convert raw accelerometer readings to G-force.
|
||||
float
|
||||
_get_accel_sensitivity(enum icm20602_accel_g accel_g)
|
||||
{
|
||||
float f = 0.0;
|
||||
|
||||
switch (accel_g) {
|
||||
case (ICM20602_ACCEL_RANGE_2G):
|
||||
f = 16384.0;
|
||||
break;
|
||||
case (ICM20602_ACCEL_RANGE_4G):
|
||||
f = 8192.0;
|
||||
break;
|
||||
case (ICM20602_ACCEL_RANGE_8G):
|
||||
f = 4096.0;
|
||||
break;
|
||||
case (ICM20602_ACCEL_RANGE_16G):
|
||||
f = 2048.0;
|
||||
break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/// Used to convert raw gyroscope readings to degrees per second.
|
||||
float
|
||||
_get_gyro_sensitivity(enum icm20602_gyro_dps gyro_dps)
|
||||
{
|
||||
float f = 0;
|
||||
|
||||
switch (gyro_dps) {
|
||||
case (ICM20602_GYRO_RANGE_250_DPS):
|
||||
f = 131.0;
|
||||
break;
|
||||
case (ICM20602_GYRO_RANGE_500_DPS):
|
||||
f = 65.5;
|
||||
break;
|
||||
case (ICM20602_GYRO_RANGE_1000_DPS):
|
||||
f = 32.8;
|
||||
break;
|
||||
case (ICM20602_GYRO_RANGE_2000_DPS):
|
||||
f = 16.4;
|
||||
break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
int8_t
|
||||
_read_data(struct icm20602_dev * dev, uint8_t reg, uint8_t * buf, uint32_t len)
|
||||
{
|
||||
int8_t r = 0;
|
||||
|
||||
if ((!dev->hal_wr) || (!dev->hal_rd) || (!dev->hal_sleep)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dev->mutex_lock) {
|
||||
dev->mutex_lock(dev->id);
|
||||
}
|
||||
|
||||
r = dev->hal_rd(dev->id, reg, buf, len);
|
||||
|
||||
if (dev->mutex_unlock) {
|
||||
dev->mutex_unlock(dev->id);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/***** Global Functions *****/
|
||||
|
||||
int8_t
|
||||
icm20602_init(struct icm20602_dev * dev)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
int8_t r = 0;
|
||||
|
||||
if ((!dev->hal_wr) || (!dev->hal_rd) || (!dev->hal_sleep)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// General Procedure:
|
||||
// 1. reset chip
|
||||
// 2. set clock for PLL for optimum performance as documented in datasheet
|
||||
// 3. place accelerometer and gyroscope into standby
|
||||
// 4. disable fifo
|
||||
// 5. configure chip
|
||||
// 6. enable accelerometer and gyroscope
|
||||
|
||||
if (dev->mutex_lock) {
|
||||
dev->mutex_lock(dev->id);
|
||||
}
|
||||
|
||||
// full reset of chip
|
||||
tmp = 0x80;
|
||||
r = dev->hal_wr(dev->id, REG_PWR_MGMT_1, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
// TODO: better reset delay value
|
||||
dev->hal_sleep(1000);
|
||||
|
||||
// verify we are able to read from the chip
|
||||
r = dev->hal_rd(dev->id, REG_WHO_AM_I, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
if (REG_WHO_AM_I_CONST != tmp) {
|
||||
r = -1;
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
|
||||
// set clock to internal PLL
|
||||
tmp = 0x01;
|
||||
r = dev->hal_wr(dev->id, REG_PWR_MGMT_1, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
// place accel and gyro on standby
|
||||
tmp = 0x3F;
|
||||
r = dev->hal_wr(dev->id, REG_PWR_MGMT_2, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
// disable fifo
|
||||
tmp = 0x00;
|
||||
r = dev->hal_wr(dev->id, REG_USER_CTRL, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
if (dev->i2c_disable) {
|
||||
// disable chip I2C communications
|
||||
tmp = 0x40;
|
||||
r = dev->hal_wr(dev->id, REG_I2C_IF, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
|
||||
if (dev->use_accel) {
|
||||
if (ICM20602_ACCEL_DLPF_BYPASS_1046_HZ == dev->accel_dlpf) {
|
||||
tmp = (1 << 3);
|
||||
r = dev->hal_wr(dev->id, REG_ACCEL_CONFIG_2, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
else {
|
||||
tmp = dev->accel_dlpf;
|
||||
r = dev->hal_wr(dev->id, REG_ACCEL_CONFIG_2, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
|
||||
tmp = (dev->accel_g) << 2;
|
||||
r = dev->hal_wr(dev->id, REG_ACCEL_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
|
||||
if (dev->use_gyro) {
|
||||
if (ICM20602_GYRO_DLPF_BYPASS_3281_HZ == dev->gyro_dlpf) {
|
||||
// bypass dpf and set dps
|
||||
tmp = 0x00;
|
||||
r = dev->hal_wr(dev->id, REG_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
tmp = (dev->gyro_dps << 3) | 0x02; // see table page 37 of datasheet
|
||||
r = dev->hal_wr(dev->id, REG_GYRO_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
else if (ICM20602_GYRO_DLPF_BYPASS_8173_HZ == dev->gyro_dlpf) {
|
||||
// bypass dpf and set dps
|
||||
tmp = 0x00;
|
||||
r = dev->hal_wr(dev->id, REG_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
tmp = (dev->gyro_dps << 3) | 0x01; // see table page 37 of datasheet
|
||||
r = dev->hal_wr(dev->id, REG_GYRO_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
else {
|
||||
// configure dpf and set dps
|
||||
tmp = dev->gyro_dlpf;
|
||||
r = dev->hal_wr(dev->id, REG_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
tmp = dev->gyro_dps << 3;
|
||||
r = dev->hal_wr(dev->id, REG_GYRO_CONFIG, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
}
|
||||
}
|
||||
|
||||
// enable FIFO if requested
|
||||
tmp = ((dev->use_accel) && (dev->accel_fifo)) ? 0x08 : 0x00;
|
||||
tmp |= ((dev->use_gyro) && (dev->gyro_fifo)) ? 0x10 : 0x00;
|
||||
r = dev->hal_wr(dev->id, REG_FIFO_EN, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
// configure sample rate divider (TODO: is this gyro only?)
|
||||
// note: SAMPLE_RATE = INTERNAL_SAMPLE_RATE / (1 + SMPLRT_DIV)
|
||||
tmp = (0 != dev->sample_rate_div) ? dev->sample_rate_div - 1 : 1;
|
||||
r = dev->hal_wr(dev->id, REG_SMPLRT_DIV, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
tmp = 0;
|
||||
tmp |= (dev->use_gyro) ? 0 : 0x07; // 0 - on, 1 - disabled
|
||||
tmp |= (dev->use_accel) ? 0 : 0x38; // 0 - on, 1 - disabled
|
||||
r = dev->hal_wr(dev->id, REG_PWR_MGMT_2, &tmp, 1);
|
||||
ON_ERROR_GOTO((0 == r), return_err);
|
||||
|
||||
return_err:
|
||||
|
||||
if (dev->mutex_unlock) {
|
||||
dev->mutex_unlock(dev->id);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_accel(struct icm20602_dev * dev, float * p_x, float * p_y,
|
||||
float * p_z)
|
||||
{
|
||||
float accel_sensitivity;
|
||||
int16_t x, y, z;
|
||||
int8_t r = 0;
|
||||
|
||||
accel_sensitivity = _get_accel_sensitivity(dev->accel_g);
|
||||
|
||||
r = icm20602_read_accel_raw(dev, &x, &y, &z);
|
||||
if (0 == r) {
|
||||
*p_x = ((float) x) / accel_sensitivity;
|
||||
*p_y = ((float) y) / accel_sensitivity;
|
||||
*p_z = ((float) z) / accel_sensitivity;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_gyro(struct icm20602_dev * dev, float * p_x, float * p_y,
|
||||
float * p_z)
|
||||
{
|
||||
float gyro_sensitivity;
|
||||
int16_t x, y, z;
|
||||
int8_t r = 0;
|
||||
|
||||
gyro_sensitivity = _get_gyro_sensitivity(dev->gyro_dps);
|
||||
|
||||
r = icm20602_read_gyro_raw(dev, &x, &y, &z);
|
||||
if (0 == r) {
|
||||
*p_x = ((float) x) / gyro_sensitivity;
|
||||
*p_y = ((float) y) / gyro_sensitivity;
|
||||
*p_z = ((float) z) / gyro_sensitivity;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_data(struct icm20602_dev * dev, float * p_ax, float * p_ay,
|
||||
float * p_az, float * p_gx, float * p_gy, float * p_gz, float * p_t)
|
||||
{
|
||||
float accel_sensitivity;
|
||||
float gyro_sensitivity;
|
||||
int16_t ax, ay, az, gx, gy, gz, t;
|
||||
int8_t r = 0;
|
||||
|
||||
accel_sensitivity = _get_accel_sensitivity(dev->accel_g);
|
||||
gyro_sensitivity = _get_gyro_sensitivity(dev->gyro_dps);
|
||||
|
||||
r = icm20602_read_data_raw(dev, &ax, &ay, &az, &gx, &gy, &gz, &t);
|
||||
if (0 == r) {
|
||||
*p_ax = ((float) ax) / accel_sensitivity;
|
||||
*p_ay = ((float) ay) / accel_sensitivity;
|
||||
*p_az = ((float) az) / accel_sensitivity;
|
||||
*p_gx = ((float) gx) / gyro_sensitivity;
|
||||
*p_gy = ((float) gy) / gyro_sensitivity;
|
||||
*p_gz = ((float) gz) / gyro_sensitivity;
|
||||
*p_t = ((float) t) / _temp_sensitivity;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_accel_raw(struct icm20602_dev * dev, int16_t * p_x, int16_t * p_y,
|
||||
int16_t * p_z)
|
||||
{
|
||||
uint8_t buf[8] = {0};
|
||||
int8_t r = 0;
|
||||
|
||||
r = _read_data(dev, REG_ACCEL_XOUT_H, buf, 8);
|
||||
if (0 == r) {
|
||||
UINT8_TO_INT16(*p_x, buf[0], buf[1]);
|
||||
UINT8_TO_INT16(*p_y, buf[2], buf[3]);
|
||||
UINT8_TO_INT16(*p_z, buf[4], buf[5]);
|
||||
// buf[6] and buf[7] hold temperature
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_gyro_raw(struct icm20602_dev * dev, int16_t * p_x, int16_t * p_y,
|
||||
int16_t * p_z)
|
||||
{
|
||||
uint8_t buf[6] = {0};
|
||||
int8_t r = 0;
|
||||
|
||||
r = _read_data(dev, REG_GYRO_XOUT_H, buf, 6);
|
||||
if (0 == r) {
|
||||
UINT8_TO_INT16(*p_x, buf[0], buf[1]);
|
||||
UINT8_TO_INT16(*p_y, buf[2], buf[3]);
|
||||
UINT8_TO_INT16(*p_z, buf[4], buf[5]);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_data_raw(struct icm20602_dev * dev, int16_t * p_ax,
|
||||
int16_t * p_ay, int16_t * p_az, int16_t * p_gx, int16_t * p_gy,
|
||||
int16_t * p_gz, int16_t * p_t)
|
||||
{
|
||||
uint8_t buf[14] = {0};
|
||||
int8_t r = 0;
|
||||
|
||||
r = _read_data(dev, REG_ACCEL_XOUT_H, buf, 14);
|
||||
if (0 == r) {
|
||||
UINT8_TO_INT16(*p_ax, buf[0], buf[1]);
|
||||
UINT8_TO_INT16(*p_ay, buf[2], buf[3]);
|
||||
UINT8_TO_INT16(*p_az, buf[4], buf[5]);
|
||||
UINT8_TO_INT16(*p_t, buf[6], buf[7]);
|
||||
UINT8_TO_INT16(*p_gx, buf[8], buf[9]);
|
||||
UINT8_TO_INT16(*p_gy, buf[10], buf[11]);
|
||||
UINT8_TO_INT16(*p_gz, buf[12], buf[13]);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_accel_fifo(struct icm20602_dev * dev, float * p_x, float * p_y,
|
||||
float * p_z)
|
||||
{
|
||||
float accel_sensitivity;
|
||||
int16_t x, y, z;
|
||||
int8_t r = 0;
|
||||
|
||||
accel_sensitivity = _get_accel_sensitivity(dev->accel_g);
|
||||
|
||||
r = icm20602_read_fifo_accel_raw(dev, &x, &y, &z);
|
||||
if (0 == r) {
|
||||
*p_x = ((float) x) / accel_sensitivity;
|
||||
*p_y = ((float) y) / accel_sensitivity;
|
||||
*p_z = ((float) z) / accel_sensitivity;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_gyro_fifo(struct icm20602_dev * dev, float * p_x, float * p_y,
|
||||
float * p_z)
|
||||
{
|
||||
float gyro_sensitivity;
|
||||
int16_t x, y, z;
|
||||
int8_t r = 0;
|
||||
|
||||
gyro_sensitivity = _get_gyro_sensitivity(dev->gyro_dps);
|
||||
|
||||
r = icm20602_read_fifo_gyro_raw(dev, &x, &y, &z);
|
||||
if (0 == r) {
|
||||
*p_x = ((float) x) / gyro_sensitivity;
|
||||
*p_y = ((float) y) / gyro_sensitivity;
|
||||
*p_z = ((float) z) / gyro_sensitivity;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_fifo_data(struct icm20602_dev * dev, float * p_ax, float * p_ay,
|
||||
float * p_az, float * p_gx, float * p_gy, float * p_gz, float * p_t)
|
||||
{
|
||||
float accel_sensitivity;
|
||||
float gyro_sensitivity;
|
||||
int16_t ax, ay, az, gx, gy, gz, t;
|
||||
int8_t r = 0;
|
||||
|
||||
accel_sensitivity = _get_accel_sensitivity(dev->accel_g);
|
||||
gyro_sensitivity = _get_gyro_sensitivity(dev->gyro_dps);
|
||||
|
||||
r = icm20602_read_fifo_data_raw(dev, &ax, &ay, &az, &gx, &gy, &gz, &t);
|
||||
if (0 == r) {
|
||||
*p_ax = ((float) ax) / accel_sensitivity;
|
||||
*p_ay = ((float) ay) / accel_sensitivity;
|
||||
*p_az = ((float) az) / accel_sensitivity;
|
||||
*p_gx = ((float) gx) / gyro_sensitivity;
|
||||
*p_gy = ((float) gy) / gyro_sensitivity;
|
||||
*p_gz = ((float) gz) / gyro_sensitivity;
|
||||
*p_t = ((float) t) / _temp_sensitivity;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_fifo_accel_raw(struct icm20602_dev * dev, int16_t * p_x,
|
||||
int16_t * p_y, int16_t * p_z)
|
||||
{
|
||||
uint8_t buf[6] = {0};
|
||||
int8_t r = 0;
|
||||
|
||||
r = _read_data(dev, REG_FIFO_R_W, buf, 6);
|
||||
if (0 == r) {
|
||||
UINT8_TO_INT16(*p_x, buf[0], buf[1]);
|
||||
UINT8_TO_INT16(*p_y, buf[2], buf[3]);
|
||||
UINT8_TO_INT16(*p_z, buf[4], buf[5]);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_fifo_gyro_raw(struct icm20602_dev * dev, int16_t * p_x,
|
||||
int16_t * p_y, int16_t * p_z)
|
||||
{
|
||||
uint8_t buf[6] = {0};
|
||||
int8_t r = 0;
|
||||
|
||||
r = _read_data(dev, REG_FIFO_R_W, buf, 6);
|
||||
if (0 == r) {
|
||||
UINT8_TO_INT16(*p_x, buf[0], buf[1]);
|
||||
UINT8_TO_INT16(*p_y, buf[2], buf[3]);
|
||||
UINT8_TO_INT16(*p_z, buf[4], buf[5]);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int8_t
|
||||
icm20602_read_fifo_data_raw(struct icm20602_dev * dev, int16_t * p_ax,
|
||||
int16_t * p_ay, int16_t * p_az, int16_t * p_gx, int16_t * p_gy,
|
||||
int16_t * p_gz, int16_t * p_t)
|
||||
{
|
||||
uint8_t buf[14] = {0};
|
||||
int8_t r = 0;
|
||||
|
||||
r = _read_data(dev, REG_FIFO_R_W, buf, 14);
|
||||
if (0 == r) {
|
||||
UINT8_TO_INT16(*p_ax, buf[0], buf[1]);
|
||||
UINT8_TO_INT16(*p_ay, buf[2], buf[3]);
|
||||
UINT8_TO_INT16(*p_az, buf[4], buf[5]);
|
||||
UINT8_TO_INT16(*p_t, buf[6], buf[7]);
|
||||
UINT8_TO_INT16(*p_gx, buf[8], buf[9]);
|
||||
UINT8_TO_INT16(*p_gy, buf[10], buf[11]);
|
||||
UINT8_TO_INT16(*p_gz, buf[12], buf[13]);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
Loading…
Reference in New Issue