Added PAH8001 driver and WIP BMM150 driver.
continuous-integration/drone/push Build is passing Details

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-12-07 20:48:49 +08:00
parent 8280fe22c9
commit 954c38ac5a
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
6 changed files with 379 additions and 7 deletions

View File

@ -10,6 +10,8 @@ set(IMSENSORS_SRCS
"src/dht/dht_bme280.c"
"src/franklin/franklin_as3935.c"
"src/imu/imu_lsm6dsl.c"
"src/magnetic/magnetic_bmm150.c"
"src/ppg/ppg_pah8001.c"
)
set(IMSENSORS_INCS
@ -18,6 +20,8 @@ set(IMSENSORS_INCS
"include/imsensors/dht"
"include/imsensors/franklin"
"include/imsensors/imu"
"include/imsensors/magnetic"
"include/imsensors/ppg"
)
set(IMSENSORS_INTF_INCS

View File

@ -0,0 +1,52 @@
#ifndef IMS_BMM150_H
#define IMS_BMM150_H
#include "imsensors/common/sensors_common.h"
typedef enum {
IMS_BMM150_ODR_10HZ = 0U,
IMS_BMM150_ODR_2HZ = 1U,
IMS_BMM150_ODR_6HZ = 2U,
IMS_BMM150_ODR_8HZ = 3U,
IMS_BMM150_ODR_15HZ = 4U,
IMS_BMM150_ODR_20HZ = 5U,
IMS_BMM150_ODR_25HZ = 6U,
IMS_BMM150_ODR_30HZ = 7U,
} ims_bmm150_odr_t;
typedef enum {
IMS_BMM150_PRESET_LOWPOWER,
IMS_BMM150_PRESET_REGULAR,
IMS_BMM150_PRESET_ENHANCED_REGULAR,
IMS_BMM150_PRESET_HIGH_ACCURACY,
} ims_bmm150_preset_t;
typedef enum {
IMS_BMM150_MODE_SLEEP,
IMS_BMM150_MODE_FORCED,
IMS_BMM150_MODE_NORMAL,
} ims_bmm150_mode_t;
typedef struct {
} ims_bmm150_result_t;
typedef struct {
ims_i2c_xfer_t i2c_xfer;
ims_delay_t delay;
} ims_bmm150_cb_t;
typedef struct {
uint8_t rep_xy;
uint8_t rep_z;
ims_bmm150_odr_t odr;
} ims_bmm150_config_t;
typedef struct {
ims_bmm150_cb_t cb;
void *pdev;
uint8_t i2c_addr;
} ims_bmm150_t;
#endif

View File

@ -0,0 +1,26 @@
#ifndef PPG_PAH8001_H
#define PPG_PAH8001_H
#include "imsensors/common/sensors_common.h"
typedef enum {
IMS_PPG_ALG_A,
IMS_PPG_ALG_C,
} ims_pah8001_alg_t;
typedef struct {
ims_i2c_xfer_t i2c_xfer;
ims_delay_t delay;
} ims_pah8001_cb_t;
typedef struct {
ims_pah8001_cb_t cb;
void *pdev;
} ims_pah8001_t;
ims_ret_t ims_pah8001_init(ims_pah8001_t *pah);
ims_ret_t ims_pah8001_power(ims_pah8001_t *pah, const bool on);
ims_ret_t ims_pah8001_touched(ims_pah8001_t *pah, bool *touched);
ims_ret_t ims_pah8001_read_alg_hr(ims_pah8001_t *pah, ims_pah8001_alg_t alg, uint8_t *hr);
#endif // PPG_PAH8001_H

View File

@ -99,8 +99,8 @@ static const ims_bme280_config_t ims_bme280_presets[] = {
static ims_ret_t ims_bme280_reset(ims_bme280_t *bme);
static ims_ret_t ims_bme280_read_trim_data(ims_bme280_t *bme);
static ims_ret_t ims_bme280_set_mode(ims_bme280_t *bme, ims_bme280_mode_t mode);
static ims_ret_t ims_bme_get_mode(ims_bme280_t *bme, ims_bme280_mode_t *mode);
static ims_ret_t ims_bme_wait_measure_complete(ims_bme280_t *bme, uint32_t timeout_ms);
static ims_ret_t ims_bme280_get_mode(ims_bme280_t *bme, ims_bme280_mode_t *mode);
static ims_ret_t ims_bme280_wait_measure_complete(ims_bme280_t *bme, uint32_t timeout_ms);
static ims_ret_t ims_bme280_read_raw_data(ims_bme280_t *bme, uint32_t *raw_t, uint32_t *raw_p, uint32_t *raw_h);
static ims_ret_t ims_bme280_read_register(ims_bme280_t *bme, uint8_t reg, uint8_t *data, uint16_t len);
@ -147,7 +147,7 @@ ims_ret_t ims_bme280_config(ims_bme280_t *bme, ims_bme280_config_t *config) {
ims_bme280_mode_t mode;
ret = ims_bme_get_mode(bme, &mode);
ret = ims_bme280_get_mode(bme, &mode);
if (ret != IMS_SUCCESS) return ret;
if (mode != IMS_BME280_MODE_SLEEP) {
@ -205,7 +205,7 @@ ims_ret_t ims_bme280_read_forced(ims_bme280_t *bme, ims_bme280_result_t *result)
ims_bme280_mode_t mode;
ret = ims_bme_get_mode(bme, &mode);
ret = ims_bme280_get_mode(bme, &mode);
if (ret != IMS_SUCCESS) return ret;
/*
@ -218,7 +218,7 @@ ims_ret_t ims_bme280_read_forced(ims_bme280_t *bme, ims_bme280_result_t *result)
if (ret != IMS_SUCCESS) return ret;
}
ret = ims_bme_wait_measure_complete(bme, IMS_BME280_FORCED_TIMEOUT_MS);
ret = ims_bme280_wait_measure_complete(bme, IMS_BME280_FORCED_TIMEOUT_MS);
if (ret != IMS_SUCCESS) {
return ret;
}
@ -341,7 +341,7 @@ static ims_ret_t ims_bme280_set_mode(ims_bme280_t *bme, ims_bme280_mode_t mode)
return ret;
}
static ims_ret_t ims_bme_get_mode(ims_bme280_t *bme, ims_bme280_mode_t *mode) {
static ims_ret_t ims_bme280_get_mode(ims_bme280_t *bme, ims_bme280_mode_t *mode) {
ims_ret_t ret;
uint8_t ctrl_meas;
@ -354,7 +354,7 @@ static ims_ret_t ims_bme_get_mode(ims_bme280_t *bme, ims_bme280_mode_t *mode) {
return IMS_SUCCESS;
}
static ims_ret_t ims_bme_wait_measure_complete(ims_bme280_t *bme, uint32_t timeout_ms) {
static ims_ret_t ims_bme280_wait_measure_complete(ims_bme280_t *bme, uint32_t timeout_ms) {
ims_ret_t ret;
uint8_t loop_count = 0U;

View File

@ -0,0 +1,144 @@
#include <stddef.h>
/* Private */
#include "magnetic_bmm150.h"
static ims_ret_t ims_bmm150_read_register(ims_bmm150_t *bmm, uint8_t addr, uint8_t *val, uint8_t len) {
ims_i2c_xfer_desc_t desc = {
.tx_data = &addr,
.tx_size = 1U,
.rx_data = val,
.rx_size = len,
};
return bmm->cb.i2c_xfer(bmm->pdev, &desc);
}
static ims_ret_t ims_bmm150_write_register(ims_bmm150_t *bmm, uint8_t addr, uint8_t val) {
uint8_t tx_buf[2] = {addr, val};
ims_i2c_xfer_desc_t desc = {
.tx_data = tx_buf,
.tx_size = 2U,
.rx_data = NULL,
.rx_size = 0U,
};
return bmm->cb.i2c_xfer(bmm->pdev, &desc);
}
static ims_ret_t ims_bmm150_set_mode(ims_bmm150_t *bmm, ims_bmm150_mode_t mode) {
uint8_t b_mode;
if (ims_bmm150_read_register(bmm, 0x4C, &b_mode, 0x01) != IMS_SUCCESS) {
return IMS_FAIL;
}
switch (mode) {
case IMS_BMM150_MODE_SLEEP:
b_mode |= (0x03U << 1U);
break;
case IMS_BMM150_MODE_NORMAL:
b_mode &= (0x03U << 1U);
break;
case IMS_BMM150_MODE_FORCED:
b_mode &= (0x03U << 1U);
b_mode |= (0x01U << 1U);
break;
default:
break;
}
if (ims_bmm150_write_register(bmm, 0x4C, b_mode) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
static ims_ret_t ims_bmm150_enable_drdy(ims_bmm150_t *bmm) {
uint8_t reg;
if (ims_bmm150_read_register(bmm, 0x4E, &reg, 0x01) != IMS_SUCCESS) {
return IMS_FAIL;
}
reg |= (1U << 7);
if (ims_bmm150_write_register(bmm, 0x4E, reg) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
static ims_ret_t ims_bmm150_set_thresholds(ims_bmm150_t *bmm, uint8_t high, uint8_t low) {
if (ims_bmm150_write_register(bmm, 0x4F, low) != IMS_SUCCESS) {
return IMS_FAIL;
}
if (ims_bmm150_write_register(bmm, 0x50, high) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
static ims_ret_t ims_bmm150_set_repetitions(ims_bmm150_t *bmm, uint8_t xy, uint8_t z) {
if (ims_bmm150_write_register(bmm, 0x51, xy) != IMS_SUCCESS) {
return IMS_FAIL;
}
if (ims_bmm150_write_register(bmm, 0x52, z) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
static ims_ret_t ims_bmm150_reset(ims_bmm150_t *bmm) {
if (ims_bmm150_write_register(bmm, 0x4B, 0x00) != IMS_SUCCESS) {
return IMS_FAIL;
}
if (ims_bmm150_write_register(bmm, 0x4B, 0x01) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
ims_ret_t ims_bmm150_init(ims_bmm150_t *bmm) {
if (!bmm) return IMS_FAIL;
if (ims_bmm150_reset(bmm) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
ims_ret_t ims_bmm150_config(ims_bmm150_t *bmm, ims_bmm150_config_t *cfg) {
if (ims_bmm150_set_repetitions(bmm, cfg->rep_xy, cfg->rep_z) != IMS_SUCCESS) {
return IMS_FAIL;
}
uint8_t b_mode;
if (ims_bmm150_read_register(bmm, 0x4C, &b_mode, 0x01) != IMS_SUCCESS) {
return IMS_FAIL;
}
b_mode &= (7U << 3);
b_mode |= (cfg->odr << 3);
if (ims_bmm150_write_register(bmm, 0x4C, b_mode) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}
ims_ret_t ims_bmm150_watch(ims_bmm150_t *bmm) {
/* Enable interrupts and ... */
if (ims_bmm150_set_thresholds(bmm, 0, 0) != IMS_SUCCESS) {
return IMS_FAIL;
}
return IMS_SUCCESS;
}

146
src/ppg/ppg_pah8001.c Normal file
View File

@ -0,0 +1,146 @@
#include "ppg_pah8001.h"
#define PAH8001_R_CONFIG ((0U << 8U) | 0x06)
#define PAH8001_R_CONFIG_RESET_Pos 7
#define PAH8001_R_CONFIG_RESET_Msk (1U << PAH8001_R_CONFIG_RESET_Pos)
#define PAH8001_R_CONFIG_POWERDOWN_Pos 3
#define PAH8001_R_CONFIG_POWERDOWN_Msk (1U << PAH8001_R_CONFIG_POWERDOWN_Pos)
#define PAH8001_R_TOUCH_DET ((0U << 8U) | 0x59)
#define PAH8001_R_TOUCH_DET_DETECTED_Pos 7
#define PAH8001_R_TOUCH_DET_DETECTED_Msk (1U << PAH8001_R_TOUCH_DET_DETECTED_Pos)
#define PAH8001_R_HR_ALG_A ((1U << 8U) | 0x1A)
#define PAH8001_R_HR_ALG_C ((1U << 8U) | 0x1C)
#define PAH8001_ERROR_CHECK(x) \
if (x != IMS_SUCCESS) return IMS_FAIL
static ims_ret_t ims_pah8001_register_write(ims_pah8001_t *pah, const uint16_t addr, uint8_t data) {
ims_ret_t ret;
uint8_t tx_buf[] = {0x7F, (addr >> 8U)};
ims_i2c_xfer_desc_t xfer_desc = {
.tx_data = tx_buf,
.tx_size = 2U,
.rx_data = NULL,
.rx_size = 0U,
};
/* Switch register bank */
ret = pah->cb.i2c_xfer(pah->pdev, &xfer_desc);
if (ret != IMS_SUCCESS) {
return ret;
}
tx_buf[0] = (addr & 0xFFU);
tx_buf[1] = data;
ret = pah->cb.i2c_xfer(pah->pdev, &xfer_desc);
return ret;
}
static ims_ret_t ims_pah8001_register_read(ims_pah8001_t *pah, const uint16_t addr, uint8_t *data) {
ims_ret_t ret;
uint8_t tx_buf[] = {0x7F, (addr >> 8U)};
ims_i2c_xfer_desc_t xfer_desc = {
.tx_data = tx_buf,
.tx_size = 2U,
.rx_data = NULL,
.rx_size = 0U,
};
/* Switch register bank */
ret = pah->cb.i2c_xfer(pah->pdev, &xfer_desc);
if (ret != IMS_SUCCESS) {
return ret;
}
tx_buf[0] = (addr & 0xFFU);
xfer_desc.tx_size = 1U;
xfer_desc.rx_data = data;
xfer_desc.rx_size = 1U;
ret = pah->cb.i2c_xfer(pah->pdev, &xfer_desc);
return ret;
}
static ims_ret_t ims_pah8001_reset(ims_pah8001_t *pah) {
uint8_t wdata = PAH8001_R_CONFIG_RESET_Msk | 2U;
PAH8001_ERROR_CHECK(ims_pah8001_register_write(pah, PAH8001_R_CONFIG, wdata));
pah->cb.delay(pah->pdev, 5);
wdata = PAH8001_R_CONFIG_POWERDOWN_Msk | 2U;
PAH8001_ERROR_CHECK(ims_pah8001_register_write(pah, PAH8001_R_CONFIG, wdata));
pah->cb.delay(pah->pdev, 5);
return IMS_SUCCESS;
}
ims_ret_t ims_pah8001_init(ims_pah8001_t *pah) {
PAH8001_ERROR_CHECK(ims_pah8001_reset(pah));
return IMS_SUCCESS;
}
ims_ret_t ims_pah8001_power(ims_pah8001_t *pah, const bool on) {
ims_ret_t ret;
uint8_t wdata;
ret = ims_pah8001_register_read(pah, PAH8001_R_CONFIG, &wdata);
if (ret != IMS_SUCCESS) {
return ret;
}
if (!on) {
wdata |= PAH8001_R_CONFIG_POWERDOWN_Msk;
} else {
wdata &= ~PAH8001_R_CONFIG_POWERDOWN_Msk;
}
return ims_pah8001_register_write(pah, PAH8001_R_CONFIG, wdata);
}
ims_ret_t ims_pah8001_touched(ims_pah8001_t *pah, bool *touched) {
ims_ret_t ret;
uint8_t rdata;
ret = ims_pah8001_register_read(pah, PAH8001_R_TOUCH_DET, &rdata);
if (ret != IMS_SUCCESS) {
return ret;
}
if (rdata & PAH8001_R_TOUCH_DET_DETECTED_Msk) {
*touched = true;
} else {
*touched = false;
}
return IMS_SUCCESS;
}
ims_ret_t ims_pah8001_read_alg_hr(ims_pah8001_t *pah, ims_pah8001_alg_t alg, uint8_t *hr) {
uint16_t rreg;
switch (alg) {
case IMS_PPG_ALG_A:
rreg = PAH8001_R_HR_ALG_A;
break;
case IMS_PPG_ALG_C:
rreg = PAH8001_R_HR_ALG_C;
break;
default:
return IMS_FAIL;
}
return ims_pah8001_register_read(pah, rreg, hr);
}