imsensors/src/ppg/ppg_pah8001.c

146 lines
3.6 KiB
C

#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);
}