168 lines
5.0 KiB
C
168 lines
5.0 KiB
C
/*
|
|
IST8310 地磁传感器。
|
|
|
|
*/
|
|
|
|
/* Includes ----------------------------------------------------------------- */
|
|
#include "ist8310.h"
|
|
|
|
#include <gpio.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
#include "bsp\delay.h"
|
|
#include "bsp\gpio.h"
|
|
#include "bsp\i2c.h"
|
|
|
|
/* Private define ----------------------------------------------------------- */
|
|
#define IST8310_WAI (0x00)
|
|
#define IST8310_STAT1 (0x02)
|
|
#define IST8310_DATAXL (0x03)
|
|
#define IST8310_STAT2 (0x09)
|
|
#define IST8310_CNTL1 (0x0A)
|
|
#define IST8310_CNTL2 (0x0B)
|
|
#define IST8310_STR (0x0C)
|
|
#define IST8310_TEMPL (0x1C)
|
|
#define IST8310_TEMPH (0x1D)
|
|
#define IST8310_AVGCNTL (0x41)
|
|
#define IST8310_PDCNTL (0x42)
|
|
|
|
#define IST8310_CHIP_ID (0x10)
|
|
|
|
#define IST8310_IIC_ADDRESS (0x0E << 1)
|
|
|
|
#define IST8310_LEN_RX_BUFF (6)
|
|
/* Private macro ------------------------------------------------------------ */
|
|
#define IST8310_SET() \
|
|
HAL_GPIO_WritePin(CMPS_RST_GPIO_Port, CMPS_RST_Pin, GPIO_PIN_SET)
|
|
#define IST8310_RESET() \
|
|
HAL_GPIO_WritePin(CMPS_RST_GPIO_Port, CMPS_RST_Pin, GPIO_PIN_RESET)
|
|
|
|
/* Private typedef ---------------------------------------------------------- */
|
|
/* Private variables -------------------------------------------------------- */
|
|
uint8_t ist8310_rxbuf[IST8310_LEN_RX_BUFF];
|
|
|
|
static osThreadId_t thread_alert;
|
|
static bool inited = false;
|
|
|
|
/* Private function -------------------------------------------------------- */
|
|
static void IST8310_WriteSingle(uint8_t reg, uint8_t data) {
|
|
HAL_I2C_Mem_Write(BSP_I2C_GetHandle(BSP_I2C_COMP), IST8310_IIC_ADDRESS, reg,
|
|
I2C_MEMADD_SIZE_8BIT, &data, 1, 100);
|
|
}
|
|
|
|
static uint8_t IST8310_ReadSingle(uint8_t reg) {
|
|
uint8_t buf = 0;
|
|
HAL_I2C_Mem_Read(BSP_I2C_GetHandle(BSP_I2C_COMP), IST8310_IIC_ADDRESS, reg,
|
|
I2C_MEMADD_SIZE_8BIT, &buf, 1, 100);
|
|
return buf;
|
|
}
|
|
|
|
static void IST8310_Read(uint8_t reg, uint8_t *data, uint8_t len) {
|
|
if (data == NULL) return;
|
|
|
|
HAL_I2C_Mem_Read_DMA(BSP_I2C_GetHandle(BSP_I2C_COMP), IST8310_IIC_ADDRESS,
|
|
reg, I2C_MEMADD_SIZE_8BIT, data, len);
|
|
}
|
|
|
|
static void IST8310_MemRxCpltCallback(void) {
|
|
osThreadFlagsSet(thread_alert, SIGNAL_IST8310_MAGN_RAW_REDY);
|
|
}
|
|
|
|
static void IST8310_IntCallback(void) {
|
|
osThreadFlagsSet(thread_alert, SIGNAL_IST8310_MAGN_NEW_DATA);
|
|
}
|
|
|
|
/* Exported functions ------------------------------------------------------- */
|
|
int8_t IST8310_Init(IST8310_t *ist8310, const IST8310_Cali_t *cali) {
|
|
if (ist8310 == NULL) return DEVICE_ERR_NULL;
|
|
if (cali == NULL) return DEVICE_ERR_NULL;
|
|
if (inited) return DEVICE_ERR_INITED;
|
|
if ((thread_alert = osThreadGetId()) == NULL) return DEVICE_ERR_NULL;
|
|
|
|
ist8310->cali = cali;
|
|
|
|
IST8310_RESET();
|
|
BSP_Delay(50);
|
|
IST8310_SET();
|
|
BSP_Delay(50);
|
|
|
|
if (IST8310_ReadSingle(IST8310_WAI) != IST8310_CHIP_ID)
|
|
return DEVICE_ERR_NO_DEV;
|
|
|
|
BSP_GPIO_DisableIRQ(CMPS_INT_Pin);
|
|
|
|
BSP_I2C_RegisterCallback(BSP_I2C_COMP, HAL_I2C_MEM_RX_CPLT_CB,
|
|
IST8310_MemRxCpltCallback);
|
|
BSP_GPIO_RegisterCallback(CMPS_INT_Pin, IST8310_IntCallback);
|
|
|
|
/* Init. */
|
|
/* 0x00: Stand-By mode. 0x01: Single measurement mode. */
|
|
|
|
/* 0x08: Data ready function enable. DRDY signal active low*/
|
|
IST8310_WriteSingle(IST8310_CNTL2, 0x08);
|
|
|
|
IST8310_WriteSingle(IST8310_AVGCNTL, 0x09);
|
|
IST8310_WriteSingle(IST8310_PDCNTL, 0xC0);
|
|
IST8310_WriteSingle(IST8310_CNTL1, 0x0B);
|
|
BSP_Delay(10);
|
|
|
|
inited = true;
|
|
|
|
BSP_GPIO_EnableIRQ(CMPS_INT_Pin);
|
|
return DEVICE_OK;
|
|
}
|
|
|
|
bool IST8310_WaitNew(uint32_t timeout) {
|
|
return (osThreadFlagsWait(SIGNAL_IST8310_MAGN_NEW_DATA, osFlagsWaitAll,
|
|
timeout) == SIGNAL_IST8310_MAGN_NEW_DATA);
|
|
}
|
|
|
|
int8_t IST8310_StartDmaRecv() {
|
|
IST8310_Read(IST8310_DATAXL, ist8310_rxbuf, IST8310_LEN_RX_BUFF);
|
|
return DEVICE_OK;
|
|
}
|
|
|
|
uint32_t IST8310_WaitDmaCplt() {
|
|
return osThreadFlagsWait(SIGNAL_IST8310_MAGN_RAW_REDY, osFlagsWaitAll,
|
|
osWaitForever);
|
|
}
|
|
|
|
int8_t IST8310_Parse(IST8310_t *ist8310) {
|
|
if (ist8310 == NULL) return DEVICE_ERR_NULL;
|
|
|
|
#if 1
|
|
/* Magn -> T */
|
|
int16_t raw_x, raw_y, raw_z;
|
|
memcpy(&raw_x, ist8310_rxbuf + 0, sizeof(raw_x));
|
|
memcpy(&raw_y, ist8310_rxbuf + 2, sizeof(raw_y));
|
|
memcpy(&raw_z, ist8310_rxbuf + 4, sizeof(raw_z));
|
|
|
|
ist8310->magn.x = (float)raw_x;
|
|
ist8310->magn.y = (float)raw_y;
|
|
ist8310->magn.z = (float)-raw_z;
|
|
|
|
#else
|
|
const int16_t *raw_x = (int16_t *)(ist8310_rxbuf + 0);
|
|
const int16_t *raw_y = (int16_t *)(ist8310_rxbuf + 2);
|
|
const int16_t *raw_z = (int16_t *)(ist8310_rxbuf + 4);
|
|
|
|
ist8310->magn.x = (float)*raw_x;
|
|
ist8310->magn.y = (float)*raw_y;
|
|
ist8310->magn.z = -(float)*raw_z;
|
|
#endif
|
|
|
|
ist8310->magn.x *= 3.0f / 20.0f;
|
|
ist8310->magn.y *= 3.0f / 20.0f;
|
|
ist8310->magn.z *= 3.0f / 20.0f;
|
|
|
|
ist8310->magn.x = (ist8310->magn.x - ist8310->cali->magn_offset.x) *
|
|
ist8310->cali->magn_scale.x;
|
|
ist8310->magn.y = (ist8310->magn.y - ist8310->cali->magn_offset.y) *
|
|
ist8310->cali->magn_scale.y;
|
|
ist8310->magn.z = (ist8310->magn.z - ist8310->cali->magn_offset.y) *
|
|
ist8310->cali->magn_scale.z;
|
|
|
|
return DEVICE_OK;
|
|
}
|