From 8280fe22c9558f39e535ba70481128b2d635418c Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Sun, 30 Jul 2023 16:21:46 +0800 Subject: [PATCH] Added AS3935 driver. Signed-off-by: Yilin Sun --- CMakeLists.txt | 2 + include/imsensors/franklin/franklin_as3935.h | 37 ++++ src/franklin/franklin_as3935.c | 169 +++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 include/imsensors/franklin/franklin_as3935.h create mode 100644 src/franklin/franklin_as3935.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f4648d..30b6021 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(IMSENSORS_SRCS "src/als/als_ltr_303als.c" "src/dht/dht_aht10.c" "src/dht/dht_bme280.c" + "src/franklin/franklin_as3935.c" "src/imu/imu_lsm6dsl.c" ) @@ -15,6 +16,7 @@ set(IMSENSORS_INCS "include/imsensors/common" "include/imsensors/als" "include/imsensors/dht" + "include/imsensors/franklin" "include/imsensors/imu" ) diff --git a/include/imsensors/franklin/franklin_as3935.h b/include/imsensors/franklin/franklin_as3935.h new file mode 100644 index 0000000..475722e --- /dev/null +++ b/include/imsensors/franklin/franklin_as3935.h @@ -0,0 +1,37 @@ +#ifndef IMS_AS3935_H +#define IMS_AS3935_H + +#include "imsensors/common/sensors_common.h" + +typedef enum { + IMS_AS3935_MODE_ACTIVE = 0U, + IMS_AS3935_MODE_POWER_DOWN = 1U, +} ims_as3935_mode_t; + +typedef enum { + IMS_AS3935_AFE_INDOOR = 0x12U, + IMS_AS3935_AFE_OUTDOOR = 0x0EU, +} ims_as3935_afe_mode_t; + +typedef enum { + IMS_AS3935_IRQ_TYPE_NH = 0x01U, /* Noise level too high */ + IMS_AS3935_IRQ_TYPE_D = 0x04U, /* Disturber detected */ + IMS_AS3935_IRQ_TYPE_L = 0x08U, /* Lightning detected */ +} ims_as3935_irq_type_t; + +typedef struct { + ims_i2c_xfer_t i2c_xfer; + ims_delay_t delay; +} ims_as3935_cb_t; + +typedef struct { + void *pdev; + ims_as3935_cb_t cb; +} ims_as3935_t; + +ims_ret_t ims_as3935_init(ims_as3935_t *ltn); +ims_ret_t ims_as3935_get_noise_floor(ims_as3935_t *ltn, uint8_t *nf); +ims_ret_t ims_as3935_set_noise_floor(ims_as3935_t *ltn, uint8_t nf); +ims_ret_t ims_as3935_get_irq_status(ims_as3935_t *ltn, uint8_t *irq_status); + +#endif // IMS_AS3935_H diff --git a/src/franklin/franklin_as3935.c b/src/franklin/franklin_as3935.c new file mode 100644 index 0000000..241ba97 --- /dev/null +++ b/src/franklin/franklin_as3935.c @@ -0,0 +1,169 @@ +#include "franklin_as3935.h" + +static ims_ret_t ims_as3935_mode_set(ims_as3935_t *ltn, ims_as3935_mode_t mode); +static ims_ret_t ims_as3935_reg_preset(ims_as3935_t *ltn); +static ims_ret_t ims_as3935_calibrate_rco(ims_as3935_t *ltn); + +static ims_ret_t ims_as3935_register_read(ims_as3935_t *ltn, uint8_t reg, uint8_t *data); +static ims_ret_t ims_as3935_register_write(ims_as3935_t *ltn, uint8_t reg, uint8_t data); + +ims_ret_t ims_as3935_init(ims_as3935_t *ltn) { + ims_ret_t ret; + + ret = ims_as3935_mode_set(ltn, IMS_AS3935_MODE_POWER_DOWN); + if (ret != IMS_SUCCESS) { + return ret; + } + + ret = ims_as3935_reg_preset(ltn); + if (ret != IMS_SUCCESS) { + return ret; + } + + ret = ims_as3935_mode_set(ltn, IMS_AS3935_MODE_ACTIVE); + if (ret != IMS_SUCCESS) { + return ret; + } + + ret = ims_as3935_calibrate_rco(ltn); + if (ret != IMS_SUCCESS) { + return ret; + } + + uint8_t irq_status; + ret = ims_as3935_get_irq_status(ltn, &irq_status); + + return ret; +} + +ims_ret_t ims_as3935_get_noise_floor(ims_as3935_t *ltn, uint8_t *nf) { + ims_ret_t ret; + + uint8_t reg; + + ret = ims_as3935_register_read(ltn, 0x01U, ®); + if (ret != IMS_SUCCESS) { + return ret; + } + + *nf = (reg >> 4U) & 0x07U; + + return IMS_SUCCESS; +} + +ims_ret_t ims_as3935_set_noise_floor(ims_as3935_t *ltn, uint8_t nf) { + ims_ret_t ret; + + uint8_t reg; + + ret = ims_as3935_register_read(ltn, 0x01U, ®); + if (ret != IMS_SUCCESS) { + return ret; + } + + reg &= ~(0x07U << 4U); + reg |= ((nf & 0x07U) << 4U); + + ret = ims_as3935_register_write(ltn, 0x01U, reg); + return ret; +} + +ims_ret_t ims_as3935_get_irq_status(ims_as3935_t *ltn, uint8_t *irq_status) { + ims_ret_t ret; + + uint8_t reg; + + ret = ims_as3935_register_read(ltn, 0x03U, ®); + if (ret != IMS_SUCCESS) { + return ret; + } + + *irq_status = reg & 0x0FU; + + return IMS_SUCCESS; +} + +static ims_ret_t ims_as3935_mode_set(ims_as3935_t *ltn, ims_as3935_mode_t mode) { + ims_ret_t ret; + + uint8_t reg; + + ret = ims_as3935_register_read(ltn, 0x00, ®); + if (ret != IMS_SUCCESS) { + return ret; + } + + reg &= ~(0x01U); + reg |= mode; + + ret = ims_as3935_register_write(ltn, 0x00, reg); + return ret; +} + +static ims_ret_t ims_as3935_reg_preset(ims_as3935_t *ltn) { + ims_ret_t ret; + + ret = ims_as3935_register_write(ltn, 0x3C, 0x96); + + return ret; +} + +static ims_ret_t ims_as3935_calibrate_rco(ims_as3935_t *ltn) { + ims_ret_t ret; + + ret = ims_as3935_register_write(ltn, 0x3D, 0x96); + if (ret != IMS_SUCCESS) { + return ret; + } + + uint8_t trco_calib; + uint8_t srco_calib; + for (uint8_t i = 0; i < 32; i++) { + ret = ims_as3935_register_read(ltn, 0x3A, &trco_calib); + if (ret != IMS_SUCCESS) { + return ret; + } + + ret = ims_as3935_register_read(ltn, 0x3B, &srco_calib); + if (ret != IMS_SUCCESS) { + return ret; + } + + /* Calibration failed */ + if ((trco_calib & (1U << 6U)) || (srco_calib & (1U << 6U))) { + return IMS_FAIL; + } + + if ((trco_calib & (1U << 7U)) && (srco_calib & (1U << 7U))) { + return IMS_SUCCESS; + } + + ltn->cb.delay(ltn->pdev, 5); + } + + /* Timed out */ + return IMS_FAIL; +} + +static ims_ret_t ims_as3935_register_read(ims_as3935_t *ltn, uint8_t reg, uint8_t *data) { + ims_i2c_xfer_desc_t xfer_desc = { + .tx_data = ®, + .tx_size = 1U, + .rx_data = data, + .rx_size = 1U, + }; + + return ltn->cb.i2c_xfer(ltn->pdev, &xfer_desc); +} + +static ims_ret_t ims_as3935_register_write(ims_as3935_t *ltn, uint8_t reg, uint8_t data) { + uint8_t tx_buf[2] = {reg, data}; + ims_i2c_xfer_desc_t xfer_desc = { + .tx_data = tx_buf, + .tx_size = 2U, + .rx_data = NULL, + .rx_size = 0U, + }; + + return ltn->cb.i2c_xfer(ltn->pdev, &xfer_desc); +} \ No newline at end of file