From 407e063af22ba812028fb83bbcbd80b8456075bc Mon Sep 17 00:00:00 2001 From: Jakub Klemsa Date: Wed, 3 Nov 2021 17:26:40 +0100 Subject: [PATCH 1/6] When I use some symbol(s), I include appropriate header(s). So simple. --- Src/it_sdk/eeprom/sdk_state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Src/it_sdk/eeprom/sdk_state.c b/Src/it_sdk/eeprom/sdk_state.c index 3d4545d..024b00c 100644 --- a/Src/it_sdk/eeprom/sdk_state.c +++ b/Src/it_sdk/eeprom/sdk_state.c @@ -32,6 +32,7 @@ #include #endif #include +#include itsdk_state_t itsdk_state; From 66ec9e4c334cdde3008ba7e3e3c4f64eb3872508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Kocur?= Date: Wed, 22 Dec 2021 15:08:01 +0100 Subject: [PATCH 2/6] Si72xx: add support for magnetic field sensor Si72xx. --- Inc/drivers/hall/si72xx/si72xx.h | 139 +++++ Inc/it_sdk/configDrivers.h.template | 13 + Src/drivers/hall/si72xx/si72xx.c | 890 ++++++++++++++++++++++++++++ 3 files changed, 1042 insertions(+) create mode 100644 Inc/drivers/hall/si72xx/si72xx.h create mode 100644 Src/drivers/hall/si72xx/si72xx.c diff --git a/Inc/drivers/hall/si72xx/si72xx.h b/Inc/drivers/hall/si72xx/si72xx.h new file mode 100644 index 0000000..86ae2b2 --- /dev/null +++ b/Inc/drivers/hall/si72xx/si72xx.h @@ -0,0 +1,139 @@ +/* ========================================================== + * si72xx.h - Driver for the Si72xx Hall Effect Sensor + * ---------------------------------------------------------- + * + * Created on: 21 dec 2021 + * Author: Zbynek Kocur + * ---------------------------------------------------------- + * Copyright (C) 2021 CTU in Prague + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU LESSER General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * ========================================================== + * Datasheet - https://www.silabs.com/documents/public/data-sheets/si7210-datasheet.pdf + * App Note - AN1018: Using the Si72xx Hall-effect Magnetic Position Sensors - https://www.silabs.com/documents/public/application-notes/an1018-si72xx-sensors.pdf + * + * ========================================================== + * Some peaces of that code directly comes from Silicon Laboratories Inc. + * and identified with << Copyright 2018 Silicon Laboratories Inc. www.silabs.com >> + * + * ========================================================== + */ + +#ifndef DRIVERS_HALL_SI72XX_SI72XX_H +#define DRIVERS_HALL_SI72XX_SI72XX_H + +/******************************************************************************* + ******************************* DEFINES *********************************** + ******************************************************************************/ + +/** I2C device address for Si72xx */ +#define SI7200_ADDR_0 0x30 +#define SI7200_ADDR_1 0x31 +#define SI7200_ADDR_2 0x32 +#define SI7200_ADDR_3 0x33 + +/** I2C registers for Si72xx */ +#define SI72XX_HREVID 0xC0 +#define SI72XX_DSPSIGM 0xC1 +#define SI72XX_DSPSIGL 0xC2 +#define SI72XX_DSPSIGSEL 0xC3 +#define SI72XX_POWER_CTRL 0xC4 +#define SI72XX_ARAUTOINC 0xC5 +#define SI72XX_CTRL1 0xC6 +#define SI72XX_CTRL2 0xC7 +#define SI72XX_SLTIME 0xC8 +#define SI72XX_CTRL3 0xC9 +#define SI72XX_A0 0xCA +#define SI72XX_A1 0xCB +#define SI72XX_A2 0xCC +#define SI72XX_CTRL4 0xCD +#define SI72XX_A3 0xCE +#define SI72XX_A4 0xCF +#define SI72XX_A5 0xD0 +#define SI72XX_OTP_ADDR 0xE1 +#define SI72XX_OTP_DATA 0xE2 +#define SI72XX_OTP_CTRL 0xE3 +#define SI72XX_TM_FG 0xE4 + +#define SI72XX_OTP_20MT_ADDR 0x21 +#define SI72XX_OTP_200MT_ADDR 0x27 + +/******************************************************************************* + ******************************** ENUMS ************************************ + ******************************************************************************/ +/** Si72xx magnetic field full-scales */ +typedef enum { + SI7210_20MT, + SI7210_200MT +} Si72xxFieldScale_t; + +/** Si72xx sleep modes */ +typedef enum { + SI72XX_SLEEP_MODE, + SI72XX_SLTIMEENA_MODE, + SI72XX_IDLE_MODE +} Si72xxSleepMode_t; + + +/*! + * @brief Si72xx API status result code. + */ +typedef enum drivers_si72xx_ret_e +{ + __SI72XX_OK = 0, + __SI72XX_ERROR = 1, + __SI72XX_BUSY = 2, + __SI72XX_TIMEOUT = 3, /* until here, I2C errors (cf. _I2C_Status) */ + __SI72XX_NODATA = 4, + __SI72XX_MISCALIB = 5, + __SI72XX_UNKNOWN = 6, +} drivers_si72xx_ret_e; + +/******************************************************************************* + ***************************** PROTOTYPES ********************************** + ******************************************************************************/ + +drivers_si72xx_ret_e Si72xx_WakeUpAndIdle(uint8_t addr); +drivers_si72xx_ret_e Si72xx_Read_MagField_Data(uint8_t addr, + int16_t *magData); +drivers_si72xx_ret_e Si72xx_FromIdle_GoToSleep(uint8_t addr); +drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr); + +drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, + Si72xxFieldScale_t mTScale, + Si72xxSleepMode_t sleepMode, + int16_t *magFieldData); +drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, + Si72xxSleepMode_t sleepMode); +drivers_si72xx_ret_e Si72xx_EnterLatchMode (uint8_t addr); +drivers_si72xx_ret_e Si72xx_ReadTemperatureAndSleep(uint8_t addr, + int32_t *rawTemp); +drivers_si72xx_ret_e Si72xx_ReadCorrectedTempAndSleep(uint8_t addr, + int16_t offsetData, + int16_t gainData, + int32_t *correctedTemp); +drivers_si72xx_ret_e Si72xx_ReadTempCorrectionDataAndSleep(uint8_t addr, + int16_t *offsetValue, + int16_t *gainValue); + +drivers_si72xx_ret_e Si72xx_IdentifyAndSleep(uint8_t addr, + uint8_t *partId, + uint8_t *partRev); +drivers_si72xx_ret_e Si72xx_ReadVariantAndSleep(uint8_t addr, + uint8_t *basePn, + uint8_t *pnVariant); +drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr); + + +#endif /* DRIVERS_HALL_SI72XX_SI72XX_H */ diff --git a/Inc/it_sdk/configDrivers.h.template b/Inc/it_sdk/configDrivers.h.template index 830123b..f7c30c9 100644 --- a/Inc/it_sdk/configDrivers.h.template +++ b/Inc/it_sdk/configDrivers.h.template @@ -299,5 +299,18 @@ #define ITSDK_DRIVERS_SL353_INT_BANK __BANK_A // HALL pin configuration #define ITSDK_DRIVERS_SL353_INT_PIN __LP_GPIO_0 // __LP_GPIO_NONE if not used +// ------------------------------------------------------------------------ +// Hall : SI72XX + +#define ITSDK_DRIVERS_SI72XX __DISABLE // Si72xx Hall Effect Sensor +#if ITSDK_DRIVERS_SI72XX == __ENABLE + #ifndef __I2C_INCLUDED + #define __I2C_INCLUDED + #include "i2c.h" + #endif + #include +#endif +#define ITSDK_DRIVERS_SI72XX_I2C hi2c1 // I2C port to be used for communications + #endif /* INC_IT_SDK_CONFIGDRIVERS_H_ */ \ No newline at end of file diff --git a/Src/drivers/hall/si72xx/si72xx.c b/Src/drivers/hall/si72xx/si72xx.c new file mode 100644 index 0000000..2d01001 --- /dev/null +++ b/Src/drivers/hall/si72xx/si72xx.c @@ -0,0 +1,890 @@ +/* ========================================================== + * si72xx.c - Driver for the Si72xx Hall Effect Sensor + * ---------------------------------------------------------- + * + * Created on: 21 dec 2021 + * Author: Zbynek Kocur + * ---------------------------------------------------------- + * Copyright (C) 2021 CTU in Prague + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU LESSER General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * ========================================================== + * Datasheet - https://www.silabs.com/documents/public/data-sheets/si7210-datasheet.pdf + * App Note - AN1018: Using the Si72xx Hall-effect Magnetic Position Sensors - https://www.silabs.com/documents/public/application-notes/an1018-si72xx-sensors.pdf + * + * ========================================================== + * Some peaces of that code directly comes from Silicon Laboratories Inc. + * and identified with << Copyright 2018 Silicon Laboratories Inc. www.silabs.com >> + * + * ========================================================== + */ + + +#include +#include +#include +#include + +#include + +#if ITSDK_DRIVERS_SI72XX == __ENABLE + +/******************************************************************************* + ******************************* DEFINES *********************************** + ******************************************************************************/ + +/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ + +#define SI72XX_SWOP_LATCHMODE 0x7F +#define SI72XX_FIELDPOLSEL_LATCHMODE 2 +#define SI72XX_FIELDPOLSEL_SHIFT 6 +#define SI72XX_SWHYST_LATCHMODE 0x12 + +#define SI72XX_OTP_BUSY_MASK 1 +#define SI72XX_OTP_READ_EN_MASK 2 + +#define SI72XX_DSPSIGSEL_MASK 0x07 +#define SI72XX_DSPSIGSEL_TEMP 0x01 + +#define SI72XX_ZERO_FIELD 16384 +#define SI72XX_FRESH_BIT_MASK 0x80 +#define SI72XX_FRESH_BIT_SHIFT 7 +#define SI72XX_DSPSIGM_MASK 0x7F +#define SI72XX_DSPSIGM_SHIFT 8 + +#define SI72XX_SLEEP_MASK 1 +#define SI72XX_STOP_MASK 2 +#define SI72XX_ONEBURST_MASK 4 +#define SI72XX_USESTORE_MASK 8 +#define SI72XX_POWERCTRL_MASK 0x0F +#define SI72XX_MEASRO_MASK 0x80 +#define SI72XX_MEASRO_SHIFT 7 + +#define SI72XX_SW_LOW4FIELD_MASK 0x80 +#define SI72XX_SW_OP_MASK 0x7F + +#define SI72XX_SWFIELDPOLSEL_MASK 0xC0 +#define SI72XX_SWHYST_MASK 0x3F + +#define SI72XX_SLTIMEENA_MASK 1 +#define SI72XX_SL_FAST_MASK 2 +#define SI72XX_SW_TAMPER_MASK 0xFC + +/* Burst sizes for mag. measurement */ +#define SI72XX_DF_BW_1 0x0U << 1 +#define SI72XX_DF_BW_2 0x1U << 1 +#define SI72XX_DF_BW_4 0x2U << 1 +#define SI72XX_DF_BW_8 0x3U << 1 +#define SI72XX_DF_BW_16 0x4U << 1 +#define SI72XX_DF_BW_32 0x5U << 1 +#define SI72XX_DF_BW_64 0x6U << 1 +#define SI72XX_DF_BW_128 0x7U << 1 /* default */ +#define SI72XX_DF_BW_256 0x8U << 1 +#define SI72XX_DF_BW_512 0x9U << 1 +#define SI72XX_DF_BW_1024 0xAU << 1 +#define SI72XX_DF_BW_2048 0xBU << 1 +#define SI72XX_DF_BW_4096 0xCU << 1 +#define SI72XX_DF_BURSTSIZE_1 0x0U << 5 /* default */ +#define SI72XX_DF_BURSTSIZE_2 0x1U << 5 +#define SI72XX_DF_BURSTSIZE_4 0x2U << 5 +#define SI72XX_DF_BURSTSIZE_8 0x3U << 5 +#define SI72XX_DF_BURSTSIZE_16 0x4U << 5 +#define SI72XX_DF_BURSTSIZE_32 0x5U << 5 +#define SI72XX_DF_BURSTSIZE_64 0x6U << 5 +#define SI72XX_DF_BURSTSIZE_128 0x7U << 5 +#define SI72XX_DFBW_MASK 0x1E +#define SI72XX_DFIIR_MASK 1 + +#define SI72XX_REV_MASK 0x0F +#define SI72XX_ID_MASK 0xF0 +#define SI72XX_ID_SHIFT 4 + +#define SI72XX_BASE_PART_NUMBER 0x14 +#define SI72XX_PART_VARIANT 0x15 + +#define SI72XX_OFFSET_ADDR 0x1D +#define SI72XX_GAIN_ADDR 0x1E +/** @endcond */ + +// macros + +// convert type _I2C_Status -> drivers_si72xx_ret_e +// (which reflects original I2C errors, but it has some extra values) +#define SI72XX_FROM_I2C_STATUS(i2c_st) \ + i2c_st == __I2C_ERROR ? __SI72XX_ERROR : \ + i2c_st == __I2C_BUSY ? __SI72XX_BUSY : \ + i2c_st == __I2C_TIMEOUT ? __SI72XX_TIMEOUT : \ + __SI72XX_UNKNOWN + +/***********************************************************************//** + * @brief + * Reads register from the Si72xx sensor. + * Command can only be issued if Si72xx is idle mode. + * @param[in] i2c + * The I2C peripheral to use (not used). + * @param[in] addr + * The I2C address of the sensor. + * @param[in] reg_addr + * The register address to read from in the sensor. + * @param[out] read_ptr + * The data read from the sensor. + * @return + * the behavior can be changed easily so that it, e.g., does not check the status and only + * OR's the I2C status as follows: i2c_st |= i2c_read8BRegister(...); + **************************************************************************/ +#define SI72XX_READ_8B(reg_addr, read_ptr) \ + i2c_st = i2c_read8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, read_ptr, 1); \ + if (i2c_st != __I2C_OK) \ + { \ + res = SI72XX_FROM_I2C_STATUS(i2c_st); \ + goto RETURN; \ + } + +/***********************************************************************//** + * @brief + * Writes register in the Si72xx sensor. + * Command can only be issued if Si72xx is idle mode. + * @param[in] i2c + * The I2C peripheral to use (not used). + * @param[in] addr + * The I2C address of the sensor. + * @param[in] reg_addr + * The register address to write to in the sensor. + * @param[in] write_val + * The data to write to the sensor. + * @return + * the behavior can be changed easily so that it, e.g., does not check the status and only + * OR's the I2C status as follows: i2c_st |= i2c_write8BRegister(...); + **************************************************************************/ +#define SI72XX_WRITE_8B(reg_addr, write_val) \ + i2c_st = i2c_write8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, write_val, 1); \ + if (i2c_st != __I2C_OK) \ + { \ + res = SI72XX_FROM_I2C_STATUS(i2c_st); \ + goto RETURN; \ + } + +#define SI72XX_INT_CALL(func) \ + res = func; \ + if (res != __SI72XX_OK) goto RETURN; + +// "private" functions + +static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, + int16_t dataCode); + + +/***********************************************************************//** + * @brief + * Read out Si72xx Magnetic Field Conversion Data + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor + * @param[out] magData + * Mag-field conversion reading, signed 16-bit integer + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_Read_MagField_Data(uint8_t addr, + int16_t *magData) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + uint8_t freshBit = 0; + + SI72XX_READ_8B(SI72XX_DSPSIGM, &read); + + freshBit = ((read & SI72XX_FRESH_BIT_MASK) >> SI72XX_FRESH_BIT_SHIFT); + if (freshBit == 0) + { + res = __SI72XX_NODATA; + goto RETURN; + } + + *magData = ((((uint16_t)read) & SI72XX_DSPSIGM_MASK) << SI72XX_DSPSIGM_SHIFT); + + SI72XX_READ_8B(SI72XX_DSPSIGL, &read); + /* Data code output is 15-bit unsigned value where 0mT=16384 */ + *magData |= read; + /* Converts data code output to a signed integer */ + *magData = *magData - SI72XX_ZERO_FIELD; + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Puts Si72xx into Sleep mode (lowest power).. + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor. + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_FromIdle_GoToSleep(uint8_t addr) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_READ_8B(SI72XX_CTRL3, &read); + read = (read & (~SI72XX_SLTIMEENA_MASK)); + SI72XX_WRITE_8B(SI72XX_CTRL3, read); + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read | SI72XX_SLEEP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Puts Si72xx into Sleep-Timer-Enable mode. + * Si72xx periodically wakes-up, samples the magnetic field, updates the + * output, and goes back to sleep-timer-enabled mode. + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor. + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_READ_8B(SI72XX_CTRL3, &read); + read = ((read & ~SI72XX_SL_FAST_MASK) | SI72XX_SLTIMEENA_MASK); + SI72XX_WRITE_8B(SI72XX_CTRL3, read); + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read & ~( SI72XX_ONEBURST_MASK | + SI72XX_STOP_MASK | + SI72XX_SLEEP_MASK)); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Wake-up Si72xx and places sensor in idle-mode. + * @param[in] addr + * The I2C address of the sensor. + * @return + * Returns zero on success. Otherwise returns error codes + * based on the I2CCSPM + **************************************************************************/ + +drivers_si72xx_ret_e Si72xx_WakeUpAndIdle(uint8_t devAdr) +{ + uint8_t value; + + if (i2c_write(&ITSDK_DRIVERS_SI72XX_I2C, devAdr, NULL, 0) != __I2C_OK) + return __I2C_ERROR; + + return i2c_read(&ITSDK_DRIVERS_SI72XX_I2C, devAdr, &value, 1); + +} + + +/***********************************************************************//** + * @brief + * Read Si72xx OTP Data + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor + * @param[in] otpAddr + * The OTB Byte address of the coefficients + * @param[out] data + * OTP data read out + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_Read_OTP(uint8_t addr, + uint8_t otpAddr, + uint8_t *otpData) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_READ_8B(SI72XX_OTP_CTRL, &read); + if (read & SI72XX_OTP_BUSY_MASK) + return __SI72XX_BUSY; + + SI72XX_WRITE_8B(SI72XX_OTP_ADDR, otpAddr); + SI72XX_WRITE_8B(SI72XX_OTP_CTRL, SI72XX_OTP_READ_EN_MASK); + SI72XX_READ_8B(SI72XX_OTP_DATA, &read); + + *otpData = read; + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Set magnetic-field output range, 20mT or 200mT full-scale + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor + * @param[in] mTScale + * 20mT or 200mT + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_Set_mT_Range(uint8_t addr, + Si72xxFieldScale_t mTScale) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t srcAddr = 0; + uint8_t data = 0; + + if (mTScale == SI7210_20MT) + { + srcAddr = SI72XX_OTP_20MT_ADDR; + } + else if (mTScale == SI7210_200MT) + { + srcAddr = SI72XX_OTP_200MT_ADDR; + } + + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A0, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A1, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A2, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A3, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A4, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A5, data); + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Wake-up SI72xx, performs a magnetic-field conversion with FIR, + * and places Si72xx back to sleep-mode or idle. + * @param[in] addr + * The I2C address of the sensor + * @param[in] mTScale + * mTScale= Si7210_20MT: 20mT full-scale magnetic-field range + * mTScale= Si7210_200MT: 200mT full-scale magnetic-field range + * @param[in] sleepMode + * SI72XX_SLEEP: Sleep mode. Lowest power & doesn't update output + * SI72XX_SLTIMEENA: Sleep-Timer-Enabled mode. Updates output periodically + * SI72XX_IDLE: No sleep + * @param[out] magFieldData + * Magnetic-field conversion reading, signed 16-bit integer + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, + Si72xxFieldScale_t mTScale, + Si72xxSleepMode_t sleepMode, + int16_t *magFieldData) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + /* set the stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + SI72XX_INT_CALL(Si72xx_Set_mT_Range(addr, mTScale)) + + /* Set the burst-size for averaging */ + SI72XX_WRITE_8B(SI72XX_CTRL4, SI72XX_DF_BURSTSIZE_1 | SI72XX_DF_BW_128); + + /* Perform a magnetic field conversion */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_ONEBURST_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Wait for measurement to complete */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + while ((read & SI72XX_MEASRO_MASK) >> SI72XX_MEASRO_SHIFT) + { + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + } + + SI72XX_INT_CALL(Si72xx_Read_MagField_Data(addr, magFieldData)) + + switch (sleepMode) + { + case SI72XX_SLEEP_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + break; + case SI72XX_SLTIMEENA_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) + break; + case SI72XX_IDLE_MODE : + //TODO + break; + default : + ; + } + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Wake-up Si72xx, and set sleep-mode option. + * If Si72xx is in a sleep-mode, it requires a wake-up command first. + * Useful for placing Si72xx in SLTIMEENA mode from SLEEP mode, + * or vice-versa. + * @param[in] addr + * The I2C address of the sensor + * @param[in] sleepMode + * SI72XX_SLEEP: Puts Si72xx into sleep mode. Lowest power & doesn't update + * SI72XX_SLTIMEENA: Si72xx into sltimeena mode. Updates output periodically + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, + Si72xxSleepMode_t sleepMode) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + switch (sleepMode) + { + case SI72XX_SLEEP_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + break; + case SI72XX_SLTIMEENA_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) + break; + case SI72XX_IDLE_MODE : + //TODO + break; + default : + ; + } + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Wake-up Si72xx, and configures output for Latch mode. + * Switch point = 0mT w/ 0.2mT hysteresis + * @param[in] addr + * The I2C address of the sensor + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_EnterLatchMode(uint8_t addr) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + /* Set Stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read | SI72XX_USESTORE_MASK | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Set output high for low magnetic field */ + /* Set sw_op to zero for latch mode */ + read = (SI72XX_SWOP_LATCHMODE | SI72XX_SW_LOW4FIELD_MASK); + SI72XX_WRITE_8B(SI72XX_CTRL1, read); + + /* Set output to unipolar positive with hysteresis = 0.2mT */ + read = ((SI72XX_FIELDPOLSEL_LATCHMODE << SI72XX_FIELDPOLSEL_SHIFT) + | SI72XX_SWHYST_LATCHMODE); + SI72XX_WRITE_8B(SI72XX_CTRL2, read); + + /* Enable the sleep-timer for periodic measurements */ + SI72XX_READ_8B(SI72XX_CTRL3, &read); + read = (read | SI72XX_SLTIMEENA_MASK); + SI72XX_WRITE_8B(SI72XX_CTRL3, read); + + /* Clear stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read & ~SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Wakes up SI72xx, performs temperature conversion and places Si72xx + * into SI72XX_SLEEP sleep-mode. + * @param[in] addr + * The I2C address of the sensor + * @param[out] temp + * Temperature measurement in millidegree Celsius + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_ReadTemperatureAndSleep(uint8_t addr, + int32_t *rawTemp) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + uint8_t dspSigM, dspSigL; + uint8_t freshBit; + int16_t dataValue; + int32_t milliCelsius; + + uint16_t tempCtrl4Setting = 0x00; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + /* Set stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* clear IIR & FIR filtering */ + SI72XX_WRITE_8B(SI72XX_CTRL4, tempCtrl4Setting); + + /* Select temperature conversion */ + SI72XX_READ_8B(SI72XX_DSPSIGSEL, &read); + read = ((read & ~SI72XX_DSPSIGSEL_MASK) | SI72XX_DSPSIGSEL_TEMP); + SI72XX_WRITE_8B(SI72XX_DSPSIGSEL, read); + + /* Perform temperature conversion */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (((read & (~SI72XX_STOP_MASK)) & ~(SI72XX_SLEEP_MASK)) + | SI72XX_ONEBURST_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Read conversion res */ + SI72XX_READ_8B(SI72XX_DSPSIGM, &dspSigM); + SI72XX_READ_8B(SI72XX_DSPSIGL, &dspSigL); + + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + + freshBit = dspSigM >> SI72XX_FRESH_BIT_SHIFT; + if (freshBit == 0) + { + res = __SI72XX_NODATA; + goto RETURN; + } + + /* dataValue = (Dspigm[6:0]<<5) + (Dspigl[7:0]>>3) */ + dataValue = (((uint16_t)dspSigM) & SI72XX_DSPSIGM_MASK) << 8; + dataValue = (dataValue | dspSigL) >> 3; + + /* rawTemp(mC) = ((dataValue^2)*(-3.83*10^-6))+(0.16094*dataValue)-279.8 */ + milliCelsius = ((int32_t)dataValue * (int32_t)dataValue * -383 / 100000) + + ((16094 * dataValue) / 100) - 279800; + + *rawTemp = milliCelsius; + +RETURN: + return res; +} + +/***********************************************************************//** + * @brief + * Wakes up SI72xx, performs temperature conversion and places Si72xx + * into SI72XX_SLEEP sleep-mode. + * @param[in] addr + * The I2C address of the sensor + * @param[out] offsetValue + * Temperature offset correction + * @param[out] gainValue + * Temperature gain correction + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_ReadTempCorrectionDataAndSleep(uint8_t addr, + int16_t *offsetValue, + int16_t *gainValue) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + /* Set Stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Read offset register value */ + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_OFFSET_ADDR, &read)) + /* Calculate offset: Offset = value(0x1D)/16 */ + *offsetValue = (int8_t)read * 1000 / 16; + + /* Read gain register value */ + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_GAIN_ADDR, &read)) + /* calculate gain: Gain = (value(0x1E)/2048) + 1 */ + *gainValue = ((int8_t)read * 1000 / 2048) + 1000; + + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + +RETURN: + return res; +} + +/**************************************************************************//** + * @brief + * Wakes up SI72xx, performs a temperature conversion, and places sensor + * back to sleep. Temperature calculation is performed using compensation + * data. + * @param[out] temp + * Temperature measurement in millidegree Celsius + * @param[in] offsetData + * Offset correction data + * @param[in] gainData + * Gain correction data + *****************************************************************************/ +drivers_si72xx_ret_e Si72xx_ReadCorrectedTempAndSleep(uint8_t addr, + int16_t offsetData, + int16_t gainData, + int32_t *correctedTemp) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + uint8_t dspSigM, dspSigL; + uint8_t freshBit; + int16_t dataValue; + int32_t rawTemp; + int32_t milliCelsius; + + uint16_t tempCtrl4Setting = 0x00; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + /* Set stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Clear IIR and FIR filtering */ + SI72XX_WRITE_8B(SI72XX_CTRL4, tempCtrl4Setting); + + /* Select Temperature conversion */ + SI72XX_READ_8B(SI72XX_DSPSIGSEL, &read); + read = ((read & ~SI72XX_DSPSIGSEL_MASK) | SI72XX_DSPSIGSEL_TEMP); + SI72XX_WRITE_8B(SI72XX_DSPSIGSEL, read); + + /* Perform temperature conversion */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (((read & (~SI72XX_STOP_MASK)) & ~(SI72XX_SLEEP_MASK)) + | SI72XX_ONEBURST_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Read temperature conversion result */ + SI72XX_READ_8B(SI72XX_DSPSIGM, &dspSigM); + SI72XX_READ_8B(SI72XX_DSPSIGL, &dspSigL); + + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + + freshBit = dspSigM >> SI72XX_FRESH_BIT_SHIFT; + if (freshBit == 0) + { + res = __SI72XX_NODATA; + goto RETURN; + } + + /* dataValue = (Dspigm[6:0]<<5) + (Dspigl[7:0]>>3) */ + dataValue = (((uint16_t)dspSigM) & SI72XX_DSPSIGM_MASK) << 8; + dataValue = (dataValue | dspSigL) >> 3; + + /* rawTemp equation is from Si7210 datasheet */ + /* rawTemp(mC) = ((dataValue^2)*(-3.83*10^-6))+(0.16094*dataValue)-279.8 */ + rawTemp = ((int32_t)dataValue * (int32_t)dataValue * -383 / 100000) + + ((16094 * dataValue) / 100) - 279800; + + milliCelsius = ((rawTemp * (int32_t)gainData) + offsetData) / 1000; + + *correctedTemp = milliCelsius; + +RETURN: + return res; +} + +/************************************************************************** +* @brief +* Wake-up Si72xx, read out part Revision and ID, and place Si72xx +* back to SLEEP sleep-mode. +* @param[in] addr +* The I2C address of the sensor +* @param[out] partId +* Si7210 part ID +* @param[out] partRev +* Si72xx part Revision +**************************************************************************/ +drivers_si72xx_ret_e Si72xx_IdentifyAndSleep(uint8_t addr, + uint8_t *partId, + uint8_t *partRev) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t read = 0; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, (read | SI72XX_STOP_MASK)); + SI72XX_READ_8B(SI72XX_HREVID, &read); + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + + *partRev = read & SI72XX_REV_MASK; + *partId = read >> SI72XX_ID_SHIFT; + +RETURN: + return res; +} + +/************************************************************************** +* @brief +* Wake-up Si72xx, read out Si72xx base part-number and variant, and +* place sensor back to SLEEP sleep-mode. +* @param[in] addr +* The I2C address of the sensor +* @param[out] basePn +* Si7210 part ID +* @param[out] partRev +* Si72xx part Revision +**************************************************************************/ +drivers_si72xx_ret_e Si72xx_ReadVariantAndSleep(uint8_t addr, + uint8_t *basePn, + uint8_t *pnVariant) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + + uint8_t read = 0; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_BASE_PART_NUMBER, &read)) + *basePn = read; + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_PART_VARIANT, &read)) + *pnVariant = read; + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + +RETURN: + return res; +} + +/************************************************************************** +* @brief +* Self-test sequence offered by the device. It uses an internal +* coil to generate and test the + and - field. +* @param[in] addr +* The I2C address of the sensor +**************************************************************************/ +drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + int16_t field_pos = 0; + int16_t field_neg = 0; + + /* Enable test field generator coil in POSITIVE direction. */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_WRITE_8B(SI72XX_TM_FG, 1); + + /* Measure field strength */ + SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_pos)) // 200mT + field_pos = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_pos)/1000; + + /* Enable test field generator coil in POSITIVE direction. */ + SI72XX_WRITE_8B(SI72XX_TM_FG, 2); + + /* Measure field strength */ + SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_neg)) + field_neg = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_neg)/1000; + + /* Disable test field generator coil. */ + SI72XX_WRITE_8B(SI72XX_TM_FG, 0); + + /* Send to sleep mode */ + SI72XX_INT_CALL(Si72xx_EnterSleepMode(addr, SI72XX_SLEEP_MODE)) + + /* Vdd of SI7210. This is used in device's self-test calculations */ + #define SI72xx_VDD (3.3f) + + float b_out = 1.16 * SI72xx_VDD; + float b_upper = b_out + (b_out * 0.25); /* +25% */ + float b_lower = b_out - (b_out * 0.25); /* -25% */ + + if( (field_pos <= b_upper) && + (field_pos >= b_lower) && + (field_neg >= (b_upper * -1)) && + (field_neg <= (b_lower * -1))) + { + log_info("(i) Sensor 0x%X self test PASS\r\n", addr); + } + else + { + log_info("(i) Sensor 0x%X self test FAIL!\r\n", addr); + res = __SI72XX_MISCALIB; + goto RETURN; + } + +RETURN: + return res; +} + +/**************************************************************************//** + * @brief Convert Si7210 I2C Data Readings to Magnetic Field in microTeslas + * @param[in] fieldScale + * 20mT or 200mT full-scale magnetic field range + * @param[in] dataCodes + * signed 15bit value read from hall sensor after magnetic field conversion + * @return microTeslas + *****************************************************************************/ +static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, + int16_t dataCode) +{ + switch (fieldScale) + { + case SI7210_20MT : + /* 20mT: 1(LSB) = 1.25uT */ + return (dataCode * 125) / 100; + case SI7210_200MT : + /* 200mT: 1(LSB) = 12.5uT */ + return (dataCode * 125) / 10; + default : + return 0; + } +} +#endif From 317363781d0886ca773295b3beafdcc7bb70c8a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Kocur?= Date: Wed, 22 Dec 2021 15:48:02 +0100 Subject: [PATCH 3/6] Add doc for si72xx --- Doc/drivers/si72xx.md | 85 ++++++++++++++++++++++++++++++++ Inc/drivers/hall/si72xx/si72xx.h | 8 +-- 2 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 Doc/drivers/si72xx.md diff --git a/Doc/drivers/si72xx.md b/Doc/drivers/si72xx.md new file mode 100644 index 0000000..d5f4954 --- /dev/null +++ b/Doc/drivers/si72xx.md @@ -0,0 +1,85 @@ +# SI72XX - Hall Effect Magnetic Position and Temperature Sensor Driver + +The Si7210 family of Hall effect magnetic sensors from Silicon Labs combines a +chopper-stabilized Hall element with a low-noise analog amplifier, 13-bit +analog-to-digital converter, and an I2C interface. Leveraging Silicon Labs' proven +CMOS design techniques, the Si7210 family incorporates digital signal processing +to provide precise compensation for temperature and offset drift. + +## Sources + - Datasheet: https://www.silabs.com/documents/public/data-sheets/si7210-datasheet.pdf + - Application Note AN1018: https://www.silabs.com/documents/public/application-notes/an1018-si72xx-sensors.pdf + +## Setup the SI72XX +As all the drivers you need to enable it and setup it in the _configDrivers.h_ + +## Using the SI72XX + +### SI72XX HW versions + + +Constant declared in `drivers/hall/si72xx/si72xx.h` + +```C +#define SI72XX_ADDR_0 0x30 +#define SI72XX_ADDR_1 0x31 +#define SI72XX_ADDR_2 0x32 +#define SI72XX_ADDR_3 0x33 +``` + +Based on the sensor version must be used proper I2C address: + - SI72XX_ADDR_0 (0x30): + - Si7210-B-00-IV(R) + - Si7210-B-01-IV(R) + - Si7210-B-10-IM2(R) + - Si7210-B-11-IM2(R) + - SI72XX_ADDR_1 (0x31): + - Si7210-B-02-IV(R) + - Si7210-B-12-IM2(R) + - SI72XX_ADDR_2 (0x32): + - Si7210-B-03-IV(R) + - Si7210-B-13-IM2(R) + - SI72XX_ADDR_3 (0x33): + - Si7210-B-04-IV(R) + - Si7210-B-05-IV(R) + - Si7210-B-14-IM2(R) + - Si7210-B-15-IM2(R) + + +### Measurement of magnetic field + +Read magnetic field with sensor SI72XX_ADDR_0 and go to sleep. + +```C +... + +int16_t data = 0; + +if (Si72xx_ReadMagFieldDataAndSleep(SI72XX_ADDR_0, SI7210_20MT, SI72XX_SLEEP_MODE, &data) == __SI72XX_OK) +{ + return __SI72XX_ERROR; +} + +return data; + +... +``` + +### Measurement of temperature + +Read temperature with sensor SI72XX_ADDR_0 and go to sleep. + +```C +... + +int32_t temp_mC = 0; /* output in milli Celsius */ + +if (Si72xx_ReadTemperatureAndSleep(SI72XX_ADDR_0, &temp_mC) != __SI72XX_OK) +{ + return __SI72XX_ERROR; +} + +return temp_mC; + +... +``` \ No newline at end of file diff --git a/Inc/drivers/hall/si72xx/si72xx.h b/Inc/drivers/hall/si72xx/si72xx.h index 86ae2b2..06b5aa7 100644 --- a/Inc/drivers/hall/si72xx/si72xx.h +++ b/Inc/drivers/hall/si72xx/si72xx.h @@ -38,10 +38,10 @@ ******************************************************************************/ /** I2C device address for Si72xx */ -#define SI7200_ADDR_0 0x30 -#define SI7200_ADDR_1 0x31 -#define SI7200_ADDR_2 0x32 -#define SI7200_ADDR_3 0x33 +#define SI72XX_ADDR_0 0x30 +#define SI72XX_ADDR_1 0x31 +#define SI72XX_ADDR_2 0x32 +#define SI72XX_ADDR_3 0x33 /** I2C registers for Si72xx */ #define SI72XX_HREVID 0xC0 From 10b37a7740b039e4d68f355a54bebea2d4cc43ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Kocur?= Date: Fri, 27 May 2022 11:46:04 +0200 Subject: [PATCH 4/6] si72xx: add sensor threshold function --- Inc/drivers/hall/si72xx/si72xx.h | 31 +++- Src/drivers/hall/si72xx/si72xx.c | 251 +++++++++++++++++++++++++++++-- 2 files changed, 262 insertions(+), 20 deletions(-) mode change 100644 => 100755 Inc/drivers/hall/si72xx/si72xx.h mode change 100644 => 100755 Src/drivers/hall/si72xx/si72xx.c diff --git a/Inc/drivers/hall/si72xx/si72xx.h b/Inc/drivers/hall/si72xx/si72xx.h old mode 100644 new mode 100755 index 06b5aa7..c66df35 --- a/Inc/drivers/hall/si72xx/si72xx.h +++ b/Inc/drivers/hall/si72xx/si72xx.h @@ -91,13 +91,14 @@ typedef enum { */ typedef enum drivers_si72xx_ret_e { - __SI72XX_OK = 0, - __SI72XX_ERROR = 1, - __SI72XX_BUSY = 2, - __SI72XX_TIMEOUT = 3, /* until here, I2C errors (cf. _I2C_Status) */ - __SI72XX_NODATA = 4, - __SI72XX_MISCALIB = 5, - __SI72XX_UNKNOWN = 6, + __SI72XX_OK = 0, + __SI72XX_ERROR = 1, + __SI72XX_BUSY = 2, + __SI72XX_TIMEOUT = 3, /* until here, I2C errors (cf. _I2C_Status) */ + __SI72XX_NODATA = 4, + __SI72XX_MISCALIB = 5, + __SI72XX_UNKNOWN = 6, + __SI72XX_INVALID_ARG = 7 } drivers_si72xx_ret_e; /******************************************************************************* @@ -110,12 +111,14 @@ drivers_si72xx_ret_e Si72xx_Read_MagField_Data(uint8_t addr, drivers_si72xx_ret_e Si72xx_FromIdle_GoToSleep(uint8_t addr); drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr); +drivers_si72xx_ret_e Si72xx_Set_mT_Range(uint8_t addr, + Si72xxFieldScale_t mTScale); drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, Si72xxFieldScale_t mTScale, Si72xxSleepMode_t sleepMode, int16_t *magFieldData); drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, - Si72xxSleepMode_t sleepMode); + Si72xxSleepMode_t sleepMode); drivers_si72xx_ret_e Si72xx_EnterLatchMode (uint8_t addr); drivers_si72xx_ret_e Si72xx_ReadTemperatureAndSleep(uint8_t addr, int32_t *rawTemp); @@ -136,4 +139,16 @@ drivers_si72xx_ret_e Si72xx_ReadVariantAndSleep(uint8_t addr, drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr); +// ============================================================================================= + +int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode); + +drivers_si72xx_ret_e Si72xx_Set_Threshold (uint8_t addr, + Si72xxFieldScale_t mTScale, + float threshold); +drivers_si72xx_ret_e Si72xx_Set_Hysteresis (uint8_t addr, + Si72xxFieldScale_t mTScale, + float hysteresis); +drivers_si72xx_ret_e Debug_Si72xx_register (uint8_t addr); + #endif /* DRIVERS_HALL_SI72XX_SI72XX_H */ diff --git a/Src/drivers/hall/si72xx/si72xx.c b/Src/drivers/hall/si72xx/si72xx.c old mode 100644 new mode 100755 index 2d01001..e5b76f6 --- a/Src/drivers/hall/si72xx/si72xx.c +++ b/Src/drivers/hall/si72xx/si72xx.c @@ -30,6 +30,7 @@ * ========================================================== */ +#include #include #include @@ -38,6 +39,7 @@ #include + #if ITSDK_DRIVERS_SI72XX == __ENABLE /******************************************************************************* @@ -147,7 +149,8 @@ i2c_st = i2c_read8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, read_ptr, 1); \ if (i2c_st != __I2C_OK) \ { \ - res = SI72XX_FROM_I2C_STATUS(i2c_st); \ + log_info("\r\n(d) ERROR SI72XX_READ_8B\r\n"); \ + res = SI72XX_FROM_I2C_STATUS(i2c_st); \ goto RETURN; \ } @@ -171,7 +174,8 @@ i2c_st = i2c_write8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, write_val, 1); \ if (i2c_st != __I2C_OK) \ { \ - res = SI72XX_FROM_I2C_STATUS(i2c_st); \ + log_info("\r\n(d) ERROR SI72XX_WRITE_8B\r\n"); \ + res = SI72XX_FROM_I2C_STATUS(i2c_st); \ goto RETURN; \ } @@ -181,8 +185,7 @@ // "private" functions -static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, - int16_t dataCode); +//static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode); /***********************************************************************//** @@ -266,21 +269,32 @@ drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr) drivers_si72xx_ret_e res = __SI72XX_OK; _I2C_Status i2c_st = __I2C_OK; + /* To store read register value */ uint8_t read = 0; + /* Setting SLTIMEENA to enable the sleep timer in order to make periodic measurements and update output pin + * Resetting ONEBURST, SLEEP and STOP to don't go to classic sleep + * Setting USESTORE to not reloaded after each sleep cycle the SI72XX_CTRL1 and SI72XX_CTRL2 registers + * */ SI72XX_READ_8B(SI72XX_CTRL3, &read); read = ((read & ~SI72XX_SL_FAST_MASK) | SI72XX_SLTIMEENA_MASK); SI72XX_WRITE_8B(SI72XX_CTRL3, read); SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + /* Reset the ONEBURST, SLEEP and STOP bits + * Set the USESTORE bit + * */ read = (read & ~( SI72XX_ONEBURST_MASK | SI72XX_STOP_MASK | - SI72XX_SLEEP_MASK)); + SI72XX_SLEEP_MASK)) | + SI72XX_USESTORE_MASK; SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); RETURN: return res; } + + /***********************************************************************//** * @brief * Wake-up Si72xx and places sensor in idle-mode. @@ -408,6 +422,7 @@ drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, drivers_si72xx_ret_e res = __SI72XX_OK; _I2C_Status i2c_st = __I2C_OK; + /* to get register value */ uint8_t read = 0; SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) @@ -420,7 +435,7 @@ drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, SI72XX_INT_CALL(Si72xx_Set_mT_Range(addr, mTScale)) /* Set the burst-size for averaging */ - SI72XX_WRITE_8B(SI72XX_CTRL4, SI72XX_DF_BURSTSIZE_1 | SI72XX_DF_BW_128); + SI72XX_WRITE_8B(SI72XX_CTRL4, SI72XX_DF_BURSTSIZE_1 | SI72XX_DF_BW_128); // SI72XX_DF_BURSTSIZE_128 | SI72XX_DF_BW_4096 /* Perform a magnetic field conversion */ SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); @@ -445,7 +460,7 @@ drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) break; case SI72XX_IDLE_MODE : - //TODO + // TODO break; default : ; @@ -484,7 +499,7 @@ drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) break; case SI72XX_IDLE_MODE : - //TODO + // TODO break; default : ; @@ -823,7 +838,7 @@ drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr) SI72XX_WRITE_8B(SI72XX_TM_FG, 1); /* Measure field strength */ - SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_pos)) // 200mT + SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_pos)); // 200mT field_pos = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_pos)/1000; /* Enable test field generator coil in POSITIVE direction. */ @@ -864,7 +879,7 @@ drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr) return res; } -/**************************************************************************//** +/**************************************************************************** * @brief Convert Si7210 I2C Data Readings to Magnetic Field in microTeslas * @param[in] fieldScale * 20mT or 200mT full-scale magnetic field range @@ -872,8 +887,8 @@ drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr) * signed 15bit value read from hall sensor after magnetic field conversion * @return microTeslas *****************************************************************************/ -static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, - int16_t dataCode) +//static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode) +int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode) { switch (fieldScale) { @@ -887,4 +902,216 @@ static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t return 0; } } + + + + +// ============================================================================= + + +/************************************************************************** + * @brief + * Function to set threshold value in sw_op register of Si7210 sensor (based on application note AN1018 and https://github.com/FARLY7/si7210-driver) + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor + * @param[in] mTScale + * The magnetic scale sensor + * @param[in] threshold + * The threshold value in mT. Threshold value available from 0.08 mT to 19.2 mT (for 20 mT scale) or 0.8 mT to 192 mT (for 200 mT scale) + **************************************************************************/ +drivers_si72xx_ret_e Si72xx_Set_Threshold (uint8_t addr, Si72xxFieldScale_t mTScale, float threshold) +{ + /* required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call */ + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + /* hysteresis value set to 10% of the threshold */ + float hysteresis = threshold * 0.1; + + /* Idle mode */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); + + /* Verifying the threshold value according to the scale */ + if (mTScale != SI7210_200MT && mTScale != SI7210_20MT) + { + return __SI72XX_INVALID_ARG; + } + + /* To store read register value */ + uint8_t read = 0; + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, (read & ~SI72XX_USESTORE_MASK) | SI72XX_STOP_MASK); /* Set the STOP bit */ + + /* Calculation of the threshold value and adapt his scale according to datasheet */ + if (mTScale == SI7210_200MT) + { + /* x20 (LSB = 0.05 mT) to adapt the range from 200mT to 4000 */ + threshold *= 20.0; + } + else + { + /* x200 (LSB = 0.005 mT) : to adapt the range from 20mT to 4000 */ + threshold *= 200.0; + } + + /* Available range from 16 to 3840, + * from 0.08 mT to 19.2 mT (20 mT scale) or 0.8 mT to 192 mT (200 mT scale) */ + if(threshold < 16) + { + threshold = 16; + } + else if (threshold > 3840) + { + threshold = 3840; + } + + /* sw_op register to fill for threshold + * threshold = ( 16 + sw_op[3:0] ) × 2^sw_op[6:4] */ + uint8_t div2_thr = 0; + + /* 4 bits max value : 15 */ + while (threshold >= 32) + { + threshold /= 2; + div2_thr++; + } + threshold -= 16; + + + /* Build the register value */ + uint8_t ctrl1 = 0; /* reset sw_low4field to have 0V by default on alert pin */ + ctrl1 |= ((div2_thr & 0x07) << 4) | ((uint8_t)(roundf(threshold)) & 0x0F); + + /* Write ctrl1 into SI72XX_CTRL1 register */ + SI72XX_WRITE_8B(SI72XX_CTRL1, ctrl1); + +RETURN: + return res; +} + + + +/************************************************************************** + * @brief + * Function to set hysteresis value in sw_hyst register of Si7210 sensor (based on application note AN1018) + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor + * @param[in] mTScale + * The magnetic scale sensor + * @param[in] hysteresis + * The hysteresis value in mT. Hysteresis value available from 0.04 mT to 8.96 mT (for 20 mT scale) or 0.4 mT to 89.6 mT (for 200 mT scale) +**************************************************************************/ +drivers_si72xx_ret_e Si72xx_Set_Hysteresis (uint8_t addr, Si72xxFieldScale_t mTScale, float hysteresis) +{ + /* required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call */ + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + /* Idle mode */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); + + /****************************************************/ + /* SET HYSTERESIS */ + /****************************************************/ + + /* Calculation of the hysteresis value and adapt his scale according to datasheet + * LSB = 0.005 mT */ + if (mTScale == SI7210_200MT) + { + /* x20 to adapt the range from 90 mT to 2000 */ + hysteresis *= 20.0; + } + else if (mTScale == SI7210_20MT) + { + /* x200 : to adapt the range from 9 mT to 2000 */ + hysteresis *= 200.0; + } + else + { + return __SI72XX_INVALID_ARG; + } + + /* Available range from 8 to 1792, + * from 0.04 mT to 8.96 mT (20 mT scale) or 0.4 mT to 89.6 mT (200 mT scale) */ + if (hysteresis < 8) + { + hysteresis = 8; + } + else if (hysteresis > 1792) + { + hysteresis = 1792; + } + + /* sw_hyst register to fill for hysteresis + * hysteresis = (8 + sw_hyst[2:0]) × 2^sw_hyst[5:3] */ + uint8_t div2_hys = 0; + + /* 3 bits max value : 7 */ + while (hysteresis >= 16) + { + hysteresis /= 2; + div2_hys++; + } + hysteresis -= 8; + + /* Build the register value + * sw_fieldpolsel = 0b00 => absolute value field to compare with threshold + * sw_hyst = 0b00 0000 */ + uint8_t ctrl2 = 0; /* reset sw_fieldpolsel to compare with absolute value */ + ctrl2 |= ((div2_hys & 0x07) << 3) | ((uint8_t)(roundf(hysteresis)) & 0x07); + + /* Write ctrl2 into SI72XX_CTRL2 register */ + SI72XX_WRITE_8B(SI72XX_CTRL2, ctrl2); + +RETURN: + return res; +} + + + + + +/************************************************************************** + * @brief + * Print some of the hall sensor registers. + * Command can only be issued if Si72xx is idle mode. + * @param[in] addr + * The I2C address of the sensor + **************************************************************************/ +drivers_si72xx_ret_e Debug_Si72xx_register (uint8_t addr) +{ + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + /* To store read register value */ + uint8_t read = 0; + + /* Idle mode */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); + + log_info("\r(i) Debug SI72xx register :\r\n"); + /* Read every register and deplay their value on uart terminal */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + log_info("\r\t(i) SI72XX_POWER_CTRL (0x%02x) : %02x\r\n", SI72XX_POWER_CTRL, read); + + SI72XX_READ_8B(SI72XX_CTRL1, &read); + log_info("\t(i) SI72XX_CTRL1 (0x%02x) : %02x\r\n", SI72XX_CTRL1, read); + + SI72XX_READ_8B(SI72XX_CTRL2, &read); + log_info("\t(i) SI72XX_CTRL2 (0x%02x) : %02x\r\n", SI72XX_CTRL2, read); + +RETURN: + return res; +} + + + #endif + + + + + From 7ca4b3dcb76f09890982851558a1d5aa00461780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Kocur?= Date: Fri, 27 May 2022 11:48:32 +0200 Subject: [PATCH 5/6] lorawan: fix duplicity in define MIN, MAX. --- Inc/drivers/lorawan/utilities.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) mode change 100644 => 100755 Inc/drivers/lorawan/utilities.h diff --git a/Inc/drivers/lorawan/utilities.h b/Inc/drivers/lorawan/utilities.h old mode 100644 new mode 100755 index 84c49e6..47e3faa --- a/Inc/drivers/lorawan/utilities.h +++ b/Inc/drivers/lorawan/utilities.h @@ -70,7 +70,9 @@ typedef uint32_t TimerTime_t; * \param [IN] b 2nd value * \retval minValue Minimum value */ -#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) +#ifndef MIN + #define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) +#endif /*! * \brief Returns the maximum value between a and b @@ -79,8 +81,9 @@ typedef uint32_t TimerTime_t; * \param [IN] b 2nd value * \retval maxValue Maximum value */ -#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) - +#ifndef MAX + #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) +#endif /*! * \brief Returns 2 raised to the power of n * From 65a00fe2b052a96751a6033ee02dfd89aa2a85ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbyn=C4=9Bk=20Kocur?= Date: Fri, 27 May 2022 12:08:23 +0200 Subject: [PATCH 6/6] si72xx: clear formating. --- Inc/drivers/hall/si72xx/si72xx.h | 66 +- Src/drivers/hall/si72xx/si72xx.c | 1174 +++++++++++++++--------------- 2 files changed, 620 insertions(+), 620 deletions(-) diff --git a/Inc/drivers/hall/si72xx/si72xx.h b/Inc/drivers/hall/si72xx/si72xx.h index c66df35..9a63ba0 100755 --- a/Inc/drivers/hall/si72xx/si72xx.h +++ b/Inc/drivers/hall/si72xx/si72xx.h @@ -74,15 +74,15 @@ ******************************************************************************/ /** Si72xx magnetic field full-scales */ typedef enum { - SI7210_20MT, - SI7210_200MT + SI7210_20MT, + SI7210_200MT } Si72xxFieldScale_t; /** Si72xx sleep modes */ typedef enum { - SI72XX_SLEEP_MODE, - SI72XX_SLTIMEENA_MODE, - SI72XX_IDLE_MODE + SI72XX_SLEEP_MODE, + SI72XX_SLTIMEENA_MODE, + SI72XX_IDLE_MODE } Si72xxSleepMode_t; @@ -91,13 +91,13 @@ typedef enum { */ typedef enum drivers_si72xx_ret_e { - __SI72XX_OK = 0, - __SI72XX_ERROR = 1, - __SI72XX_BUSY = 2, - __SI72XX_TIMEOUT = 3, /* until here, I2C errors (cf. _I2C_Status) */ - __SI72XX_NODATA = 4, - __SI72XX_MISCALIB = 5, - __SI72XX_UNKNOWN = 6, + __SI72XX_OK = 0, + __SI72XX_ERROR = 1, + __SI72XX_BUSY = 2, + __SI72XX_TIMEOUT = 3, /* until here, I2C errors (cf. _I2C_Status) */ + __SI72XX_NODATA = 4, + __SI72XX_MISCALIB = 5, + __SI72XX_UNKNOWN = 6, __SI72XX_INVALID_ARG = 7 } drivers_si72xx_ret_e; @@ -107,48 +107,48 @@ typedef enum drivers_si72xx_ret_e drivers_si72xx_ret_e Si72xx_WakeUpAndIdle(uint8_t addr); drivers_si72xx_ret_e Si72xx_Read_MagField_Data(uint8_t addr, - int16_t *magData); + int16_t *magData); drivers_si72xx_ret_e Si72xx_FromIdle_GoToSleep(uint8_t addr); drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr); drivers_si72xx_ret_e Si72xx_Set_mT_Range(uint8_t addr, - Si72xxFieldScale_t mTScale); + Si72xxFieldScale_t mTScale); drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, - Si72xxFieldScale_t mTScale, - Si72xxSleepMode_t sleepMode, - int16_t *magFieldData); + Si72xxFieldScale_t mTScale, + Si72xxSleepMode_t sleepMode, + int16_t *magFieldData); drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, - Si72xxSleepMode_t sleepMode); + Si72xxSleepMode_t sleepMode); drivers_si72xx_ret_e Si72xx_EnterLatchMode (uint8_t addr); drivers_si72xx_ret_e Si72xx_ReadTemperatureAndSleep(uint8_t addr, - int32_t *rawTemp); + int32_t *rawTemp); drivers_si72xx_ret_e Si72xx_ReadCorrectedTempAndSleep(uint8_t addr, - int16_t offsetData, - int16_t gainData, - int32_t *correctedTemp); + int16_t offsetData, + int16_t gainData, + int32_t *correctedTemp); drivers_si72xx_ret_e Si72xx_ReadTempCorrectionDataAndSleep(uint8_t addr, - int16_t *offsetValue, - int16_t *gainValue); + int16_t *offsetValue, + int16_t *gainValue); drivers_si72xx_ret_e Si72xx_IdentifyAndSleep(uint8_t addr, - uint8_t *partId, - uint8_t *partRev); + uint8_t *partId, + uint8_t *partRev); drivers_si72xx_ret_e Si72xx_ReadVariantAndSleep(uint8_t addr, - uint8_t *basePn, - uint8_t *pnVariant); + uint8_t *basePn, + uint8_t *pnVariant); drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr); // ============================================================================================= -int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode); + int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode); drivers_si72xx_ret_e Si72xx_Set_Threshold (uint8_t addr, - Si72xxFieldScale_t mTScale, - float threshold); + Si72xxFieldScale_t mTScale, + float threshold); drivers_si72xx_ret_e Si72xx_Set_Hysteresis (uint8_t addr, - Si72xxFieldScale_t mTScale, - float hysteresis); + Si72xxFieldScale_t mTScale, + float hysteresis); drivers_si72xx_ret_e Debug_Si72xx_register (uint8_t addr); #endif /* DRIVERS_HALL_SI72XX_SI72XX_H */ diff --git a/Src/drivers/hall/si72xx/si72xx.c b/Src/drivers/hall/si72xx/si72xx.c index e5b76f6..42c08bc 100755 --- a/Src/drivers/hall/si72xx/si72xx.c +++ b/Src/drivers/hall/si72xx/si72xx.c @@ -124,10 +124,10 @@ // convert type _I2C_Status -> drivers_si72xx_ret_e // (which reflects original I2C errors, but it has some extra values) #define SI72XX_FROM_I2C_STATUS(i2c_st) \ - i2c_st == __I2C_ERROR ? __SI72XX_ERROR : \ - i2c_st == __I2C_BUSY ? __SI72XX_BUSY : \ - i2c_st == __I2C_TIMEOUT ? __SI72XX_TIMEOUT : \ - __SI72XX_UNKNOWN + i2c_st == __I2C_ERROR ? __SI72XX_ERROR : \ + i2c_st == __I2C_BUSY ? __SI72XX_BUSY : \ + i2c_st == __I2C_TIMEOUT ? __SI72XX_TIMEOUT : \ + __SI72XX_UNKNOWN /***********************************************************************//** * @brief @@ -146,13 +146,13 @@ * OR's the I2C status as follows: i2c_st |= i2c_read8BRegister(...); **************************************************************************/ #define SI72XX_READ_8B(reg_addr, read_ptr) \ - i2c_st = i2c_read8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, read_ptr, 1); \ - if (i2c_st != __I2C_OK) \ - { \ - log_info("\r\n(d) ERROR SI72XX_READ_8B\r\n"); \ - res = SI72XX_FROM_I2C_STATUS(i2c_st); \ - goto RETURN; \ - } + i2c_st = i2c_read8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, read_ptr, 1); \ + if (i2c_st != __I2C_OK) \ + { \ + log_info("\r\n(d) ERROR SI72XX_READ_8B\r\n"); \ + res = SI72XX_FROM_I2C_STATUS(i2c_st); \ + goto RETURN; \ + } /***********************************************************************//** * @brief @@ -171,17 +171,17 @@ * OR's the I2C status as follows: i2c_st |= i2c_write8BRegister(...); **************************************************************************/ #define SI72XX_WRITE_8B(reg_addr, write_val) \ - i2c_st = i2c_write8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, write_val, 1); \ - if (i2c_st != __I2C_OK) \ - { \ - log_info("\r\n(d) ERROR SI72XX_WRITE_8B\r\n"); \ - res = SI72XX_FROM_I2C_STATUS(i2c_st); \ - goto RETURN; \ - } + i2c_st = i2c_write8BRegister(&ITSDK_DRIVERS_SI72XX_I2C, addr, reg_addr, write_val, 1); \ + if (i2c_st != __I2C_OK) \ + { \ + log_info("\r\n(d) ERROR SI72XX_WRITE_8B\r\n"); \ + res = SI72XX_FROM_I2C_STATUS(i2c_st); \ + goto RETURN; \ + } #define SI72XX_INT_CALL(func) \ - res = func; \ - if (res != __SI72XX_OK) goto RETURN; + res = func; \ + if (res != __SI72XX_OK) goto RETURN; // "private" functions @@ -198,34 +198,34 @@ * Mag-field conversion reading, signed 16-bit integer **************************************************************************/ drivers_si72xx_ret_e Si72xx_Read_MagField_Data(uint8_t addr, - int16_t *magData) + int16_t *magData) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; - uint8_t freshBit = 0; + uint8_t read = 0; + uint8_t freshBit = 0; - SI72XX_READ_8B(SI72XX_DSPSIGM, &read); + SI72XX_READ_8B(SI72XX_DSPSIGM, &read); - freshBit = ((read & SI72XX_FRESH_BIT_MASK) >> SI72XX_FRESH_BIT_SHIFT); - if (freshBit == 0) - { - res = __SI72XX_NODATA; - goto RETURN; - } + freshBit = ((read & SI72XX_FRESH_BIT_MASK) >> SI72XX_FRESH_BIT_SHIFT); + if (freshBit == 0) + { + res = __SI72XX_NODATA; + goto RETURN; + } - *magData = ((((uint16_t)read) & SI72XX_DSPSIGM_MASK) << SI72XX_DSPSIGM_SHIFT); + *magData = ((((uint16_t)read) & SI72XX_DSPSIGM_MASK) << SI72XX_DSPSIGM_SHIFT); - SI72XX_READ_8B(SI72XX_DSPSIGL, &read); - /* Data code output is 15-bit unsigned value where 0mT=16384 */ - *magData |= read; - /* Converts data code output to a signed integer */ - *magData = *magData - SI72XX_ZERO_FIELD; + SI72XX_READ_8B(SI72XX_DSPSIGL, &read); + /* Data code output is 15-bit unsigned value where 0mT=16384 */ + *magData |= read; + /* Converts data code output to a signed integer */ + *magData = *magData - SI72XX_ZERO_FIELD; -RETURN: - return res; + RETURN: + return res; } /***********************************************************************//** @@ -237,21 +237,21 @@ drivers_si72xx_ret_e Si72xx_Read_MagField_Data(uint8_t addr, **************************************************************************/ drivers_si72xx_ret_e Si72xx_FromIdle_GoToSleep(uint8_t addr) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; + uint8_t read = 0; - SI72XX_READ_8B(SI72XX_CTRL3, &read); - read = (read & (~SI72XX_SLTIMEENA_MASK)); - SI72XX_WRITE_8B(SI72XX_CTRL3, read); - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = (read | SI72XX_SLEEP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + SI72XX_READ_8B(SI72XX_CTRL3, &read); + read = (read & (~SI72XX_SLTIMEENA_MASK)); + SI72XX_WRITE_8B(SI72XX_CTRL3, read); + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read | SI72XX_SLEEP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); -RETURN: - return res; + RETURN: + return res; } /***********************************************************************//** @@ -265,32 +265,32 @@ drivers_si72xx_ret_e Si72xx_FromIdle_GoToSleep(uint8_t addr) **************************************************************************/ drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - /* To store read register value */ - uint8_t read = 0; + /* To store read register value */ + uint8_t read = 0; /* Setting SLTIMEENA to enable the sleep timer in order to make periodic measurements and update output pin * Resetting ONEBURST, SLEEP and STOP to don't go to classic sleep - * Setting USESTORE to not reloaded after each sleep cycle the SI72XX_CTRL1 and SI72XX_CTRL2 registers - * */ - SI72XX_READ_8B(SI72XX_CTRL3, &read); - read = ((read & ~SI72XX_SL_FAST_MASK) | SI72XX_SLTIMEENA_MASK); - SI72XX_WRITE_8B(SI72XX_CTRL3, read); - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - /* Reset the ONEBURST, SLEEP and STOP bits - * Set the USESTORE bit - * */ - read = (read & ~( SI72XX_ONEBURST_MASK | - SI72XX_STOP_MASK | - SI72XX_SLEEP_MASK)) | - SI72XX_USESTORE_MASK; - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - -RETURN: - return res; + * Setting USESTORE to not reloaded after each sleep cycle the SI72XX_CTRL1 and SI72XX_CTRL2 registers + * */ + SI72XX_READ_8B(SI72XX_CTRL3, &read); + read = ((read & ~SI72XX_SL_FAST_MASK) | SI72XX_SLTIMEENA_MASK); + SI72XX_WRITE_8B(SI72XX_CTRL3, read); + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + /* Reset the ONEBURST, SLEEP and STOP bits + * Set the USESTORE bit + * */ + read = (read & ~( SI72XX_ONEBURST_MASK | + SI72XX_STOP_MASK | + SI72XX_SLEEP_MASK)) | + SI72XX_USESTORE_MASK; + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + RETURN: + return res; } @@ -307,12 +307,12 @@ drivers_si72xx_ret_e Si72xx_FromIdle_GoToSltimeena(uint8_t addr) drivers_si72xx_ret_e Si72xx_WakeUpAndIdle(uint8_t devAdr) { - uint8_t value; + uint8_t value; - if (i2c_write(&ITSDK_DRIVERS_SI72XX_I2C, devAdr, NULL, 0) != __I2C_OK) - return __I2C_ERROR; + if (i2c_write(&ITSDK_DRIVERS_SI72XX_I2C, devAdr, NULL, 0) != __I2C_OK) + return __I2C_ERROR; - return i2c_read(&ITSDK_DRIVERS_SI72XX_I2C, devAdr, &value, 1); + return i2c_read(&ITSDK_DRIVERS_SI72XX_I2C, devAdr, &value, 1); } @@ -329,27 +329,27 @@ drivers_si72xx_ret_e Si72xx_WakeUpAndIdle(uint8_t devAdr) * OTP data read out **************************************************************************/ drivers_si72xx_ret_e Si72xx_Read_OTP(uint8_t addr, - uint8_t otpAddr, - uint8_t *otpData) + uint8_t otpAddr, + uint8_t *otpData) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; + uint8_t read = 0; - SI72XX_READ_8B(SI72XX_OTP_CTRL, &read); - if (read & SI72XX_OTP_BUSY_MASK) - return __SI72XX_BUSY; + SI72XX_READ_8B(SI72XX_OTP_CTRL, &read); + if (read & SI72XX_OTP_BUSY_MASK) + return __SI72XX_BUSY; - SI72XX_WRITE_8B(SI72XX_OTP_ADDR, otpAddr); - SI72XX_WRITE_8B(SI72XX_OTP_CTRL, SI72XX_OTP_READ_EN_MASK); - SI72XX_READ_8B(SI72XX_OTP_DATA, &read); + SI72XX_WRITE_8B(SI72XX_OTP_ADDR, otpAddr); + SI72XX_WRITE_8B(SI72XX_OTP_CTRL, SI72XX_OTP_READ_EN_MASK); + SI72XX_READ_8B(SI72XX_OTP_DATA, &read); - *otpData = read; + *otpData = read; -RETURN: - return res; + RETURN: + return res; } /***********************************************************************//** @@ -362,39 +362,39 @@ drivers_si72xx_ret_e Si72xx_Read_OTP(uint8_t addr, * 20mT or 200mT **************************************************************************/ drivers_si72xx_ret_e Si72xx_Set_mT_Range(uint8_t addr, - Si72xxFieldScale_t mTScale) + Si72xxFieldScale_t mTScale) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; - - uint8_t srcAddr = 0; - uint8_t data = 0; - - if (mTScale == SI7210_20MT) - { - srcAddr = SI72XX_OTP_20MT_ADDR; - } - else if (mTScale == SI7210_200MT) - { - srcAddr = SI72XX_OTP_200MT_ADDR; - } - - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) - SI72XX_WRITE_8B(SI72XX_A0, data); - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) - SI72XX_WRITE_8B(SI72XX_A1, data); - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) - SI72XX_WRITE_8B(SI72XX_A2, data); - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) - SI72XX_WRITE_8B(SI72XX_A3, data); - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) - SI72XX_WRITE_8B(SI72XX_A4, data); - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) - SI72XX_WRITE_8B(SI72XX_A5, data); - -RETURN: - return res; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + uint8_t srcAddr = 0; + uint8_t data = 0; + + if (mTScale == SI7210_20MT) + { + srcAddr = SI72XX_OTP_20MT_ADDR; + } + else if (mTScale == SI7210_200MT) + { + srcAddr = SI72XX_OTP_200MT_ADDR; + } + + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A0, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A1, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A2, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A3, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A4, data); + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, srcAddr++, &data)) + SI72XX_WRITE_8B(SI72XX_A5, data); + + RETURN: + return res; } /***********************************************************************//** @@ -414,60 +414,60 @@ drivers_si72xx_ret_e Si72xx_Set_mT_Range(uint8_t addr, * Magnetic-field conversion reading, signed 16-bit integer **************************************************************************/ drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, - Si72xxFieldScale_t mTScale, - Si72xxSleepMode_t sleepMode, - int16_t *magFieldData) + Si72xxFieldScale_t mTScale, + Si72xxSleepMode_t sleepMode, + int16_t *magFieldData) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; - - /* to get register value */ - uint8_t read = 0; - - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - - /* set the stop-bit */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - - SI72XX_INT_CALL(Si72xx_Set_mT_Range(addr, mTScale)) - - /* Set the burst-size for averaging */ - SI72XX_WRITE_8B(SI72XX_CTRL4, SI72XX_DF_BURSTSIZE_1 | SI72XX_DF_BW_128); // SI72XX_DF_BURSTSIZE_128 | SI72XX_DF_BW_4096 - - /* Perform a magnetic field conversion */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_ONEBURST_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - - /* Wait for measurement to complete */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - while ((read & SI72XX_MEASRO_MASK) >> SI72XX_MEASRO_SHIFT) - { - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - } - - SI72XX_INT_CALL(Si72xx_Read_MagField_Data(addr, magFieldData)) - - switch (sleepMode) - { - case SI72XX_SLEEP_MODE : - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) - break; - case SI72XX_SLTIMEENA_MODE : - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) - break; - case SI72XX_IDLE_MODE : - // TODO - break; - default : - ; - } - -RETURN: - return res; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + /* to get register value */ + uint8_t read = 0; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + /* set the stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + SI72XX_INT_CALL(Si72xx_Set_mT_Range(addr, mTScale)) + + /* Set the burst-size for averaging */ + SI72XX_WRITE_8B(SI72XX_CTRL4, SI72XX_DF_BURSTSIZE_1 | SI72XX_DF_BW_128); // SI72XX_DF_BURSTSIZE_128 | SI72XX_DF_BW_4096 + + /* Perform a magnetic field conversion */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_ONEBURST_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + + /* Wait for measurement to complete */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + while ((read & SI72XX_MEASRO_MASK) >> SI72XX_MEASRO_SHIFT) + { + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + } + + SI72XX_INT_CALL(Si72xx_Read_MagField_Data(addr, magFieldData)) + + switch (sleepMode) + { + case SI72XX_SLEEP_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + break; + case SI72XX_SLTIMEENA_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) + break; + case SI72XX_IDLE_MODE : + // TODO + break; + default : + ; + } + + RETURN: + return res; } /***********************************************************************//** @@ -483,30 +483,30 @@ drivers_si72xx_ret_e Si72xx_ReadMagFieldDataAndSleep(uint8_t addr, * SI72XX_SLTIMEENA: Si72xx into sltimeena mode. Updates output periodically **************************************************************************/ drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, - Si72xxSleepMode_t sleepMode) + Si72xxSleepMode_t sleepMode) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - - switch (sleepMode) - { - case SI72XX_SLEEP_MODE : - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) - break; - case SI72XX_SLTIMEENA_MODE : - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) - break; - case SI72XX_IDLE_MODE : - // TODO - break; - default : - ; - } - -RETURN: - return res; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + + switch (sleepMode) + { + case SI72XX_SLEEP_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + break; + case SI72XX_SLTIMEENA_MODE : + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSltimeena(addr)) + break; + case SI72XX_IDLE_MODE : + // TODO + break; + default : + ; + } + + RETURN: + return res; } /***********************************************************************//** @@ -518,41 +518,41 @@ drivers_si72xx_ret_e Si72xx_EnterSleepMode(uint8_t addr, **************************************************************************/ drivers_si72xx_ret_e Si72xx_EnterLatchMode(uint8_t addr) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; + uint8_t read = 0; - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - /* Set Stop-bit */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = (read | SI72XX_USESTORE_MASK | SI72XX_STOP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Set Stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read | SI72XX_USESTORE_MASK | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - /* Set output high for low magnetic field */ - /* Set sw_op to zero for latch mode */ - read = (SI72XX_SWOP_LATCHMODE | SI72XX_SW_LOW4FIELD_MASK); - SI72XX_WRITE_8B(SI72XX_CTRL1, read); + /* Set output high for low magnetic field */ + /* Set sw_op to zero for latch mode */ + read = (SI72XX_SWOP_LATCHMODE | SI72XX_SW_LOW4FIELD_MASK); + SI72XX_WRITE_8B(SI72XX_CTRL1, read); - /* Set output to unipolar positive with hysteresis = 0.2mT */ - read = ((SI72XX_FIELDPOLSEL_LATCHMODE << SI72XX_FIELDPOLSEL_SHIFT) - | SI72XX_SWHYST_LATCHMODE); - SI72XX_WRITE_8B(SI72XX_CTRL2, read); + /* Set output to unipolar positive with hysteresis = 0.2mT */ + read = ((SI72XX_FIELDPOLSEL_LATCHMODE << SI72XX_FIELDPOLSEL_SHIFT) + | SI72XX_SWHYST_LATCHMODE); + SI72XX_WRITE_8B(SI72XX_CTRL2, read); - /* Enable the sleep-timer for periodic measurements */ - SI72XX_READ_8B(SI72XX_CTRL3, &read); - read = (read | SI72XX_SLTIMEENA_MASK); - SI72XX_WRITE_8B(SI72XX_CTRL3, read); + /* Enable the sleep-timer for periodic measurements */ + SI72XX_READ_8B(SI72XX_CTRL3, &read); + read = (read | SI72XX_SLTIMEENA_MASK); + SI72XX_WRITE_8B(SI72XX_CTRL3, read); - /* Clear stop-bit */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = (read & ~SI72XX_STOP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Clear stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (read & ~SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); -RETURN: - return res; + RETURN: + return res; } /***********************************************************************//** @@ -565,66 +565,66 @@ drivers_si72xx_ret_e Si72xx_EnterLatchMode(uint8_t addr) * Temperature measurement in millidegree Celsius **************************************************************************/ drivers_si72xx_ret_e Si72xx_ReadTemperatureAndSleep(uint8_t addr, - int32_t *rawTemp) + int32_t *rawTemp) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; - uint8_t dspSigM, dspSigL; - uint8_t freshBit; - int16_t dataValue; - int32_t milliCelsius; + uint8_t read = 0; + uint8_t dspSigM, dspSigL; + uint8_t freshBit; + int16_t dataValue; + int32_t milliCelsius; - uint16_t tempCtrl4Setting = 0x00; + uint16_t tempCtrl4Setting = 0x00; - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - /* Set stop-bit */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Set stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - /* clear IIR & FIR filtering */ - SI72XX_WRITE_8B(SI72XX_CTRL4, tempCtrl4Setting); + /* clear IIR & FIR filtering */ + SI72XX_WRITE_8B(SI72XX_CTRL4, tempCtrl4Setting); - /* Select temperature conversion */ - SI72XX_READ_8B(SI72XX_DSPSIGSEL, &read); - read = ((read & ~SI72XX_DSPSIGSEL_MASK) | SI72XX_DSPSIGSEL_TEMP); - SI72XX_WRITE_8B(SI72XX_DSPSIGSEL, read); + /* Select temperature conversion */ + SI72XX_READ_8B(SI72XX_DSPSIGSEL, &read); + read = ((read & ~SI72XX_DSPSIGSEL_MASK) | SI72XX_DSPSIGSEL_TEMP); + SI72XX_WRITE_8B(SI72XX_DSPSIGSEL, read); - /* Perform temperature conversion */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = (((read & (~SI72XX_STOP_MASK)) & ~(SI72XX_SLEEP_MASK)) - | SI72XX_ONEBURST_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Perform temperature conversion */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (((read & (~SI72XX_STOP_MASK)) & ~(SI72XX_SLEEP_MASK)) + | SI72XX_ONEBURST_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - /* Read conversion res */ - SI72XX_READ_8B(SI72XX_DSPSIGM, &dspSigM); - SI72XX_READ_8B(SI72XX_DSPSIGL, &dspSigL); + /* Read conversion res */ + SI72XX_READ_8B(SI72XX_DSPSIGM, &dspSigM); + SI72XX_READ_8B(SI72XX_DSPSIGL, &dspSigL); - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) - freshBit = dspSigM >> SI72XX_FRESH_BIT_SHIFT; - if (freshBit == 0) - { - res = __SI72XX_NODATA; - goto RETURN; - } + freshBit = dspSigM >> SI72XX_FRESH_BIT_SHIFT; + if (freshBit == 0) + { + res = __SI72XX_NODATA; + goto RETURN; + } - /* dataValue = (Dspigm[6:0]<<5) + (Dspigl[7:0]>>3) */ - dataValue = (((uint16_t)dspSigM) & SI72XX_DSPSIGM_MASK) << 8; - dataValue = (dataValue | dspSigL) >> 3; + /* dataValue = (Dspigm[6:0]<<5) + (Dspigl[7:0]>>3) */ + dataValue = (((uint16_t)dspSigM) & SI72XX_DSPSIGM_MASK) << 8; + dataValue = (dataValue | dspSigL) >> 3; - /* rawTemp(mC) = ((dataValue^2)*(-3.83*10^-6))+(0.16094*dataValue)-279.8 */ - milliCelsius = ((int32_t)dataValue * (int32_t)dataValue * -383 / 100000) - + ((16094 * dataValue) / 100) - 279800; + /* rawTemp(mC) = ((dataValue^2)*(-3.83*10^-6))+(0.16094*dataValue)-279.8 */ + milliCelsius = ((int32_t)dataValue * (int32_t)dataValue * -383 / 100000) + + ((16094 * dataValue) / 100) - 279800; - *rawTemp = milliCelsius; + *rawTemp = milliCelsius; -RETURN: - return res; + RETURN: + return res; } /***********************************************************************//** @@ -639,36 +639,36 @@ drivers_si72xx_ret_e Si72xx_ReadTemperatureAndSleep(uint8_t addr, * Temperature gain correction **************************************************************************/ drivers_si72xx_ret_e Si72xx_ReadTempCorrectionDataAndSleep(uint8_t addr, - int16_t *offsetValue, - int16_t *gainValue) + int16_t *offsetValue, + int16_t *gainValue) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; + uint8_t read = 0; - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - /* Set Stop-bit */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Set Stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - /* Read offset register value */ - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_OFFSET_ADDR, &read)) - /* Calculate offset: Offset = value(0x1D)/16 */ - *offsetValue = (int8_t)read * 1000 / 16; + /* Read offset register value */ + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_OFFSET_ADDR, &read)) + /* Calculate offset: Offset = value(0x1D)/16 */ + *offsetValue = (int8_t)read * 1000 / 16; - /* Read gain register value */ - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_GAIN_ADDR, &read)) - /* calculate gain: Gain = (value(0x1E)/2048) + 1 */ - *gainValue = ((int8_t)read * 1000 / 2048) + 1000; + /* Read gain register value */ + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_GAIN_ADDR, &read)) + /* calculate gain: Gain = (value(0x1E)/2048) + 1 */ + *gainValue = ((int8_t)read * 1000 / 2048) + 1000; - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) -RETURN: - return res; + RETURN: + return res; } /**************************************************************************//** @@ -684,199 +684,199 @@ drivers_si72xx_ret_e Si72xx_ReadTempCorrectionDataAndSleep(uint8_t addr, * Gain correction data *****************************************************************************/ drivers_si72xx_ret_e Si72xx_ReadCorrectedTempAndSleep(uint8_t addr, - int16_t offsetData, - int16_t gainData, - int32_t *correctedTemp) + int16_t offsetData, + int16_t gainData, + int32_t *correctedTemp) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; - uint8_t dspSigM, dspSigL; - uint8_t freshBit; - int16_t dataValue; - int32_t rawTemp; - int32_t milliCelsius; + uint8_t read = 0; + uint8_t dspSigM, dspSigL; + uint8_t freshBit; + int16_t dataValue; + int32_t rawTemp; + int32_t milliCelsius; - uint16_t tempCtrl4Setting = 0x00; + uint16_t tempCtrl4Setting = 0x00; - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - /* Set stop-bit */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Set stop-bit */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = ((read & ~SI72XX_POWERCTRL_MASK) | SI72XX_STOP_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - /* Clear IIR and FIR filtering */ - SI72XX_WRITE_8B(SI72XX_CTRL4, tempCtrl4Setting); + /* Clear IIR and FIR filtering */ + SI72XX_WRITE_8B(SI72XX_CTRL4, tempCtrl4Setting); - /* Select Temperature conversion */ - SI72XX_READ_8B(SI72XX_DSPSIGSEL, &read); - read = ((read & ~SI72XX_DSPSIGSEL_MASK) | SI72XX_DSPSIGSEL_TEMP); - SI72XX_WRITE_8B(SI72XX_DSPSIGSEL, read); + /* Select Temperature conversion */ + SI72XX_READ_8B(SI72XX_DSPSIGSEL, &read); + read = ((read & ~SI72XX_DSPSIGSEL_MASK) | SI72XX_DSPSIGSEL_TEMP); + SI72XX_WRITE_8B(SI72XX_DSPSIGSEL, read); - /* Perform temperature conversion */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - read = (((read & (~SI72XX_STOP_MASK)) & ~(SI72XX_SLEEP_MASK)) - | SI72XX_ONEBURST_MASK); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); + /* Perform temperature conversion */ + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + read = (((read & (~SI72XX_STOP_MASK)) & ~(SI72XX_SLEEP_MASK)) + | SI72XX_ONEBURST_MASK); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, read); - /* Read temperature conversion result */ - SI72XX_READ_8B(SI72XX_DSPSIGM, &dspSigM); - SI72XX_READ_8B(SI72XX_DSPSIGL, &dspSigL); + /* Read temperature conversion result */ + SI72XX_READ_8B(SI72XX_DSPSIGM, &dspSigM); + SI72XX_READ_8B(SI72XX_DSPSIGL, &dspSigL); - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) - freshBit = dspSigM >> SI72XX_FRESH_BIT_SHIFT; - if (freshBit == 0) - { - res = __SI72XX_NODATA; - goto RETURN; - } + freshBit = dspSigM >> SI72XX_FRESH_BIT_SHIFT; + if (freshBit == 0) + { + res = __SI72XX_NODATA; + goto RETURN; + } - /* dataValue = (Dspigm[6:0]<<5) + (Dspigl[7:0]>>3) */ - dataValue = (((uint16_t)dspSigM) & SI72XX_DSPSIGM_MASK) << 8; - dataValue = (dataValue | dspSigL) >> 3; + /* dataValue = (Dspigm[6:0]<<5) + (Dspigl[7:0]>>3) */ + dataValue = (((uint16_t)dspSigM) & SI72XX_DSPSIGM_MASK) << 8; + dataValue = (dataValue | dspSigL) >> 3; - /* rawTemp equation is from Si7210 datasheet */ - /* rawTemp(mC) = ((dataValue^2)*(-3.83*10^-6))+(0.16094*dataValue)-279.8 */ - rawTemp = ((int32_t)dataValue * (int32_t)dataValue * -383 / 100000) - + ((16094 * dataValue) / 100) - 279800; + /* rawTemp equation is from Si7210 datasheet */ + /* rawTemp(mC) = ((dataValue^2)*(-3.83*10^-6))+(0.16094*dataValue)-279.8 */ + rawTemp = ((int32_t)dataValue * (int32_t)dataValue * -383 / 100000) + + ((16094 * dataValue) / 100) - 279800; - milliCelsius = ((rawTemp * (int32_t)gainData) + offsetData) / 1000; + milliCelsius = ((rawTemp * (int32_t)gainData) + offsetData) / 1000; - *correctedTemp = milliCelsius; + *correctedTemp = milliCelsius; -RETURN: - return res; + RETURN: + return res; } /************************************************************************** -* @brief -* Wake-up Si72xx, read out part Revision and ID, and place Si72xx -* back to SLEEP sleep-mode. -* @param[in] addr -* The I2C address of the sensor -* @param[out] partId -* Si7210 part ID -* @param[out] partRev -* Si72xx part Revision -**************************************************************************/ + * @brief + * Wake-up Si72xx, read out part Revision and ID, and place Si72xx + * back to SLEEP sleep-mode. + * @param[in] addr + * The I2C address of the sensor + * @param[out] partId + * Si7210 part ID + * @param[out] partRev + * Si72xx part Revision + **************************************************************************/ drivers_si72xx_ret_e Si72xx_IdentifyAndSleep(uint8_t addr, - uint8_t *partId, - uint8_t *partRev) + uint8_t *partId, + uint8_t *partRev) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - uint8_t read = 0; + uint8_t read = 0; - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, (read | SI72XX_STOP_MASK)); - SI72XX_READ_8B(SI72XX_HREVID, &read); - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, (read | SI72XX_STOP_MASK)); + SI72XX_READ_8B(SI72XX_HREVID, &read); + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) - *partRev = read & SI72XX_REV_MASK; - *partId = read >> SI72XX_ID_SHIFT; + *partRev = read & SI72XX_REV_MASK; + *partId = read >> SI72XX_ID_SHIFT; -RETURN: - return res; + RETURN: + return res; } /************************************************************************** -* @brief -* Wake-up Si72xx, read out Si72xx base part-number and variant, and -* place sensor back to SLEEP sleep-mode. -* @param[in] addr -* The I2C address of the sensor -* @param[out] basePn -* Si7210 part ID -* @param[out] partRev -* Si72xx part Revision -**************************************************************************/ + * @brief + * Wake-up Si72xx, read out Si72xx base part-number and variant, and + * place sensor back to SLEEP sleep-mode. + * @param[in] addr + * The I2C address of the sensor + * @param[out] basePn + * Si7210 part ID + * @param[out] partRev + * Si72xx part Revision + **************************************************************************/ drivers_si72xx_ret_e Si72xx_ReadVariantAndSleep(uint8_t addr, - uint8_t *basePn, - uint8_t *pnVariant) + uint8_t *basePn, + uint8_t *pnVariant) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; - uint8_t read = 0; + uint8_t read = 0; - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_BASE_PART_NUMBER, &read)) - *basePn = read; - SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_PART_VARIANT, &read)) - *pnVariant = read; - SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_BASE_PART_NUMBER, &read)) + *basePn = read; + SI72XX_INT_CALL(Si72xx_Read_OTP(addr, SI72XX_PART_VARIANT, &read)) + *pnVariant = read; + SI72XX_INT_CALL(Si72xx_FromIdle_GoToSleep(addr)) -RETURN: - return res; + RETURN: + return res; } /************************************************************************** -* @brief -* Self-test sequence offered by the device. It uses an internal -* coil to generate and test the + and - field. -* @param[in] addr -* The I2C address of the sensor -**************************************************************************/ + * @brief + * Self-test sequence offered by the device. It uses an internal + * coil to generate and test the + and - field. + * @param[in] addr + * The I2C address of the sensor + **************************************************************************/ drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr) { - // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; - - int16_t field_pos = 0; - int16_t field_neg = 0; - - /* Enable test field generator coil in POSITIVE direction. */ - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) - SI72XX_WRITE_8B(SI72XX_TM_FG, 1); - - /* Measure field strength */ - SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_pos)); // 200mT - field_pos = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_pos)/1000; - - /* Enable test field generator coil in POSITIVE direction. */ - SI72XX_WRITE_8B(SI72XX_TM_FG, 2); - - /* Measure field strength */ - SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_neg)) - field_neg = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_neg)/1000; - - /* Disable test field generator coil. */ - SI72XX_WRITE_8B(SI72XX_TM_FG, 0); - - /* Send to sleep mode */ - SI72XX_INT_CALL(Si72xx_EnterSleepMode(addr, SI72XX_SLEEP_MODE)) - - /* Vdd of SI7210. This is used in device's self-test calculations */ - #define SI72xx_VDD (3.3f) - - float b_out = 1.16 * SI72xx_VDD; - float b_upper = b_out + (b_out * 0.25); /* +25% */ - float b_lower = b_out - (b_out * 0.25); /* -25% */ - - if( (field_pos <= b_upper) && - (field_pos >= b_lower) && - (field_neg >= (b_upper * -1)) && - (field_neg <= (b_lower * -1))) - { - log_info("(i) Sensor 0x%X self test PASS\r\n", addr); - } - else - { - log_info("(i) Sensor 0x%X self test FAIL!\r\n", addr); - res = __SI72XX_MISCALIB; - goto RETURN; - } - -RETURN: - return res; + // required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + int16_t field_pos = 0; + int16_t field_neg = 0; + + /* Enable test field generator coil in POSITIVE direction. */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)) + SI72XX_WRITE_8B(SI72XX_TM_FG, 1); + + /* Measure field strength */ + SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_pos)); // 200mT + field_pos = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_pos)/1000; + + /* Enable test field generator coil in POSITIVE direction. */ + SI72XX_WRITE_8B(SI72XX_TM_FG, 2); + + /* Measure field strength */ + SI72XX_INT_CALL(Si72xx_ReadMagFieldDataAndSleep(addr, SI7210_200MT, SI72XX_IDLE_MODE, &field_neg)) + field_neg = Si72xx_ConvertDataCodesToMagneticField(SI7210_200MT, field_neg)/1000; + + /* Disable test field generator coil. */ + SI72XX_WRITE_8B(SI72XX_TM_FG, 0); + + /* Send to sleep mode */ + SI72XX_INT_CALL(Si72xx_EnterSleepMode(addr, SI72XX_SLEEP_MODE)) + + /* Vdd of SI7210. This is used in device's self-test calculations */ +#define SI72xx_VDD (3.3f) + + float b_out = 1.16 * SI72xx_VDD; + float b_upper = b_out + (b_out * 0.25); /* +25% */ + float b_lower = b_out - (b_out * 0.25); /* -25% */ + + if( (field_pos <= b_upper) && + (field_pos >= b_lower) && + (field_neg >= (b_upper * -1)) && + (field_neg <= (b_lower * -1))) + { + log_info("(i) Sensor 0x%X self test PASS\r\n", addr); + } + else + { + log_info("(i) Sensor 0x%X self test FAIL!\r\n", addr); + res = __SI72XX_MISCALIB; + goto RETURN; + } + + RETURN: + return res; } /**************************************************************************** @@ -890,17 +890,17 @@ drivers_si72xx_ret_e Si72xx_SelfTest(uint8_t addr) //static inline int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode) int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, int16_t dataCode) { - switch (fieldScale) - { - case SI7210_20MT : - /* 20mT: 1(LSB) = 1.25uT */ - return (dataCode * 125) / 100; - case SI7210_200MT : - /* 200mT: 1(LSB) = 12.5uT */ - return (dataCode * 125) / 10; - default : - return 0; - } + switch (fieldScale) + { + case SI7210_20MT : + /* 20mT: 1(LSB) = 1.25uT */ + return (dataCode * 125) / 100; + case SI7210_200MT : + /* 200mT: 1(LSB) = 12.5uT */ + return (dataCode * 125) / 10; + default : + return 0; + } } @@ -922,71 +922,71 @@ int32_t Si72xx_ConvertDataCodesToMagneticField(Si72xxFieldScale_t fieldScale, in **************************************************************************/ drivers_si72xx_ret_e Si72xx_Set_Threshold (uint8_t addr, Si72xxFieldScale_t mTScale, float threshold) { - /* required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call */ - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; + /* required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call */ + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; - /* hysteresis value set to 10% of the threshold */ - float hysteresis = threshold * 0.1; + /* hysteresis value set to 10% of the threshold */ + float hysteresis = threshold * 0.1; - /* Idle mode */ - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); + /* Idle mode */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); - /* Verifying the threshold value according to the scale */ - if (mTScale != SI7210_200MT && mTScale != SI7210_20MT) - { + /* Verifying the threshold value according to the scale */ + if (mTScale != SI7210_200MT && mTScale != SI7210_20MT) + { return __SI72XX_INVALID_ARG; - } - - /* To store read register value */ - uint8_t read = 0; - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - SI72XX_WRITE_8B(SI72XX_POWER_CTRL, (read & ~SI72XX_USESTORE_MASK) | SI72XX_STOP_MASK); /* Set the STOP bit */ - - /* Calculation of the threshold value and adapt his scale according to datasheet */ - if (mTScale == SI7210_200MT) - { - /* x20 (LSB = 0.05 mT) to adapt the range from 200mT to 4000 */ - threshold *= 20.0; - } - else - { + } + + /* To store read register value */ + uint8_t read = 0; + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + SI72XX_WRITE_8B(SI72XX_POWER_CTRL, (read & ~SI72XX_USESTORE_MASK) | SI72XX_STOP_MASK); /* Set the STOP bit */ + + /* Calculation of the threshold value and adapt his scale according to datasheet */ + if (mTScale == SI7210_200MT) + { + /* x20 (LSB = 0.05 mT) to adapt the range from 200mT to 4000 */ + threshold *= 20.0; + } + else + { /* x200 (LSB = 0.005 mT) : to adapt the range from 20mT to 4000 */ - threshold *= 200.0; - } - - /* Available range from 16 to 3840, - * from 0.08 mT to 19.2 mT (20 mT scale) or 0.8 mT to 192 mT (200 mT scale) */ - if(threshold < 16) - { - threshold = 16; - } - else if (threshold > 3840) - { - threshold = 3840; - } - - /* sw_op register to fill for threshold - * threshold = ( 16 + sw_op[3:0] ) × 2^sw_op[6:4] */ - uint8_t div2_thr = 0; - - /* 4 bits max value : 15 */ - while (threshold >= 32) - { - threshold /= 2; - div2_thr++; - } - threshold -= 16; - - - /* Build the register value */ - uint8_t ctrl1 = 0; /* reset sw_low4field to have 0V by default on alert pin */ - ctrl1 |= ((div2_thr & 0x07) << 4) | ((uint8_t)(roundf(threshold)) & 0x0F); + threshold *= 200.0; + } + + /* Available range from 16 to 3840, + * from 0.08 mT to 19.2 mT (20 mT scale) or 0.8 mT to 192 mT (200 mT scale) */ + if(threshold < 16) + { + threshold = 16; + } + else if (threshold > 3840) + { + threshold = 3840; + } + + /* sw_op register to fill for threshold + * threshold = ( 16 + sw_op[3:0] ) × 2^sw_op[6:4] */ + uint8_t div2_thr = 0; + + /* 4 bits max value : 15 */ + while (threshold >= 32) + { + threshold /= 2; + div2_thr++; + } + threshold -= 16; + + + /* Build the register value */ + uint8_t ctrl1 = 0; /* reset sw_low4field to have 0V by default on alert pin */ + ctrl1 |= ((div2_thr & 0x07) << 4) | ((uint8_t)(roundf(threshold)) & 0x0F); /* Write ctrl1 into SI72XX_CTRL1 register */ - SI72XX_WRITE_8B(SI72XX_CTRL1, ctrl1); + SI72XX_WRITE_8B(SI72XX_CTRL1, ctrl1); -RETURN: + RETURN: return res; } @@ -1002,70 +1002,70 @@ drivers_si72xx_ret_e Si72xx_Set_Threshold (uint8_t addr, Si72xxFieldScale_t mTSc * The magnetic scale sensor * @param[in] hysteresis * The hysteresis value in mT. Hysteresis value available from 0.04 mT to 8.96 mT (for 20 mT scale) or 0.4 mT to 89.6 mT (for 200 mT scale) -**************************************************************************/ + **************************************************************************/ drivers_si72xx_ret_e Si72xx_Set_Hysteresis (uint8_t addr, Si72xxFieldScale_t mTScale, float hysteresis) { - /* required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call */ - drivers_si72xx_ret_e res = __SI72XX_OK; - _I2C_Status i2c_st = __I2C_OK; - - /* Idle mode */ - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); - - /****************************************************/ - /* SET HYSTERESIS */ - /****************************************************/ - - /* Calculation of the hysteresis value and adapt his scale according to datasheet - * LSB = 0.005 mT */ - if (mTScale == SI7210_200MT) - { - /* x20 to adapt the range from 90 mT to 2000 */ - hysteresis *= 20.0; - } - else if (mTScale == SI7210_20MT) - { + /* required for SI72XX_READ/WRITE_8B / SI72XX_INT_CALL macro call */ + drivers_si72xx_ret_e res = __SI72XX_OK; + _I2C_Status i2c_st = __I2C_OK; + + /* Idle mode */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); + + /****************************************************/ + /* SET HYSTERESIS */ + /****************************************************/ + + /* Calculation of the hysteresis value and adapt his scale according to datasheet + * LSB = 0.005 mT */ + if (mTScale == SI7210_200MT) + { + /* x20 to adapt the range from 90 mT to 2000 */ + hysteresis *= 20.0; + } + else if (mTScale == SI7210_20MT) + { /* x200 : to adapt the range from 9 mT to 2000 */ - hysteresis *= 200.0; - } - else - { - return __SI72XX_INVALID_ARG; - } - - /* Available range from 8 to 1792, - * from 0.04 mT to 8.96 mT (20 mT scale) or 0.4 mT to 89.6 mT (200 mT scale) */ - if (hysteresis < 8) - { - hysteresis = 8; - } - else if (hysteresis > 1792) - { - hysteresis = 1792; - } - - /* sw_hyst register to fill for hysteresis - * hysteresis = (8 + sw_hyst[2:0]) × 2^sw_hyst[5:3] */ - uint8_t div2_hys = 0; - - /* 3 bits max value : 7 */ - while (hysteresis >= 16) - { - hysteresis /= 2; - div2_hys++; - } - hysteresis -= 8; - - /* Build the register value - * sw_fieldpolsel = 0b00 => absolute value field to compare with threshold - * sw_hyst = 0b00 0000 */ + hysteresis *= 200.0; + } + else + { + return __SI72XX_INVALID_ARG; + } + + /* Available range from 8 to 1792, + * from 0.04 mT to 8.96 mT (20 mT scale) or 0.4 mT to 89.6 mT (200 mT scale) */ + if (hysteresis < 8) + { + hysteresis = 8; + } + else if (hysteresis > 1792) + { + hysteresis = 1792; + } + + /* sw_hyst register to fill for hysteresis + * hysteresis = (8 + sw_hyst[2:0]) × 2^sw_hyst[5:3] */ + uint8_t div2_hys = 0; + + /* 3 bits max value : 7 */ + while (hysteresis >= 16) + { + hysteresis /= 2; + div2_hys++; + } + hysteresis -= 8; + + /* Build the register value + * sw_fieldpolsel = 0b00 => absolute value field to compare with threshold + * sw_hyst = 0b00 0000 */ uint8_t ctrl2 = 0; /* reset sw_fieldpolsel to compare with absolute value */ ctrl2 |= ((div2_hys & 0x07) << 3) | ((uint8_t)(roundf(hysteresis)) & 0x07); /* Write ctrl2 into SI72XX_CTRL2 register */ SI72XX_WRITE_8B(SI72XX_CTRL2, ctrl2); -RETURN: + RETURN: return res; } @@ -1086,25 +1086,25 @@ drivers_si72xx_ret_e Debug_Si72xx_register (uint8_t addr) drivers_si72xx_ret_e res = __SI72XX_OK; _I2C_Status i2c_st = __I2C_OK; - /* To store read register value */ - uint8_t read = 0; + /* To store read register value */ + uint8_t read = 0; - /* Idle mode */ - SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); + /* Idle mode */ + SI72XX_INT_CALL(Si72xx_WakeUpAndIdle(addr)); - log_info("\r(i) Debug SI72xx register :\r\n"); + log_info("\r(i) Debug SI72xx register :\r\n"); /* Read every register and deplay their value on uart terminal */ - SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); - log_info("\r\t(i) SI72XX_POWER_CTRL (0x%02x) : %02x\r\n", SI72XX_POWER_CTRL, read); + SI72XX_READ_8B(SI72XX_POWER_CTRL, &read); + log_info("\r\t(i) SI72XX_POWER_CTRL (0x%02x) : %02x\r\n", SI72XX_POWER_CTRL, read); - SI72XX_READ_8B(SI72XX_CTRL1, &read); - log_info("\t(i) SI72XX_CTRL1 (0x%02x) : %02x\r\n", SI72XX_CTRL1, read); + SI72XX_READ_8B(SI72XX_CTRL1, &read); + log_info("\t(i) SI72XX_CTRL1 (0x%02x) : %02x\r\n", SI72XX_CTRL1, read); - SI72XX_READ_8B(SI72XX_CTRL2, &read); - log_info("\t(i) SI72XX_CTRL2 (0x%02x) : %02x\r\n", SI72XX_CTRL2, read); + SI72XX_READ_8B(SI72XX_CTRL2, &read); + log_info("\t(i) SI72XX_CTRL2 (0x%02x) : %02x\r\n", SI72XX_CTRL2, read); -RETURN: - return res; + RETURN: + return res; }