sensor: max30101: Add heart rate sensor driver
Adds basic sensor driver support for the Maxim MAX30101 heart rate sensor. This driver does not yet support any sensor triggers such as the data ready trigger, or runtime changing of sensor attributes. Default configuration values were taken from the MikroE Hexiwear driver. https://github.com/MikroElektronika/HEXIWEAR Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX30101.pdf Jira: ZEP-720 Change-Id: Ie8981e124da36a56a214f133bf9a11b9f47d60fa Signed-off-by: Maureen Helm <maureen.helm@nxp.com>
This commit is contained in:
parent
0025c20cfb
commit
53678df5e2
6 changed files with 579 additions and 0 deletions
|
@ -82,6 +82,8 @@ source "drivers/sensor/lsm9ds0_gyro/Kconfig"
|
|||
|
||||
source "drivers/sensor/lsm9ds0_mfd/Kconfig"
|
||||
|
||||
source "drivers/sensor/max30101/Kconfig"
|
||||
|
||||
source "drivers/sensor/max44009/Kconfig"
|
||||
|
||||
source "drivers/sensor/mcp9808/Kconfig"
|
||||
|
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_LPS25HB) += lps25hb/
|
|||
obj-$(CONFIG_LSM6DS0) += lsm6ds0/
|
||||
obj-$(CONFIG_LSM9DS0_GYRO) += lsm9ds0_gyro/
|
||||
obj-$(CONFIG_LSM9DS0_MFD) += lsm9ds0_mfd/
|
||||
obj-$(CONFIG_MAX30101) += max30101/
|
||||
obj-$(CONFIG_MAX44009) += max44009/
|
||||
obj-$(CONFIG_MCP9808) += mcp9808/
|
||||
obj-$(CONFIG_MPU6050) += mpu6050/
|
||||
|
|
218
drivers/sensor/max30101/Kconfig
Normal file
218
drivers/sensor/max30101/Kconfig
Normal file
|
@ -0,0 +1,218 @@
|
|||
# Kconfig - MAX30101 heart rate sensor
|
||||
#
|
||||
# Copyright (c) 2017, NXP
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig MAX30101
|
||||
bool
|
||||
prompt "MAX30101 Pulse Oximeter and Heart Rate Sensor"
|
||||
depends on SENSOR && I2C
|
||||
default n
|
||||
|
||||
if MAX30101
|
||||
|
||||
config MAX30101_NAME
|
||||
string
|
||||
prompt "Driver name"
|
||||
default "MAX30101"
|
||||
|
||||
config MAX30101_I2C_NAME
|
||||
string
|
||||
prompt "I2C device name"
|
||||
default "I2C_0"
|
||||
|
||||
config MAX30101_SMP_AVE
|
||||
int "Sample averaging"
|
||||
range 0 7
|
||||
default 0
|
||||
help
|
||||
To reduce the amount of data throughput, adjacent samples (in each
|
||||
individual channel) can be averaged and decimated on the chip by
|
||||
setting this register. Set to 0 for no averaging.
|
||||
0 = 1 sample (no averaging)
|
||||
1 = 2 samples
|
||||
2 = 4 samples
|
||||
3 = 8 samples
|
||||
4 = 16 samples
|
||||
5 = 32 samples
|
||||
6 = 32 samples
|
||||
7 = 32 samples
|
||||
|
||||
config MAX30101_FIFO_ROLLOVER_EN
|
||||
bool "FIFO rolls on full"
|
||||
default n
|
||||
help
|
||||
Controls the behavior of the FIFO when the FIFO becomes completely
|
||||
filled with data. If set, the FIFO address rolls over to zero and the
|
||||
FIFO continues to fill with new data. If not set, then the FIFO is
|
||||
not updated until FIFO_DATA is read or the WRITE/READ pointer
|
||||
positions are changed.
|
||||
|
||||
config MAX30101_FIFO_A_FULL
|
||||
int "FIFO almost full value"
|
||||
range 0 15
|
||||
default 0
|
||||
help
|
||||
Set the trigger for the FIFO_A_FULL interrupt
|
||||
|
||||
choice MAX30101_MODE
|
||||
prompt "Mode control"
|
||||
default MAX30101_MULTI_LED_MODE
|
||||
|
||||
config MAX30101_HEART_RATE_MODE
|
||||
bool "Heart rate mode"
|
||||
help
|
||||
Set to operate in heart rate only mode. The red LED channel is
|
||||
active.
|
||||
|
||||
config MAX30101_SPO2_MODE
|
||||
bool "SpO2 mode"
|
||||
help
|
||||
Set to operate in SpO2 mode. The red and IR LED channels are active.
|
||||
|
||||
config MAX30101_MULTI_LED_MODE
|
||||
bool "Multi-LED mode"
|
||||
help
|
||||
Set to operate in multi-LED mode. The green, red, and/or IR LED
|
||||
channels are active.
|
||||
|
||||
endchoice
|
||||
|
||||
config MAX30101_ADC_RGE
|
||||
int "ADC range control"
|
||||
range 0 3
|
||||
default 2
|
||||
help
|
||||
Set the ADC's full-scale range.
|
||||
0 = 7.81 pA/LSB
|
||||
1 = 15.63 pA/LSB
|
||||
2 = 31.25 pA/LSB
|
||||
3 = 62.5 pA/LSB
|
||||
|
||||
config MAX30101_SR
|
||||
int "ADC sample rate control"
|
||||
range 0 7
|
||||
default 0
|
||||
help
|
||||
Set the effective sampling rate with one sample consisting of one
|
||||
pulse/conversion per active LED channel. In SpO2 mode, these means
|
||||
one IR pulse/conversion and one red pulse/conversion per sample
|
||||
period.
|
||||
0 = 50 Hz
|
||||
1 = 100 Hz
|
||||
2 = 200 Hz
|
||||
3 = 400 Hz
|
||||
4 = 800 Hz
|
||||
5 = 1000 Hz
|
||||
6 = 1600 Hz
|
||||
7 = 3200 Hz
|
||||
|
||||
config MAX30101_LED1_PA
|
||||
hex "LED1 (red) pulse amplitude"
|
||||
range 0 0xff
|
||||
default 0xff
|
||||
help
|
||||
Set the pulse amplitude to control the LED1 (red) current. The actual
|
||||
measured LED current for each part can vary significantly due to the
|
||||
trimming methodology.
|
||||
0x00 = 0.0 mA
|
||||
0x01 = 0.2 mA
|
||||
0x02 = 0.4 mA
|
||||
0x0f = 3.1 mA
|
||||
0xff = 50.0 mA
|
||||
|
||||
config MAX30101_LED2_PA
|
||||
hex "LED2 (IR) pulse amplitude"
|
||||
range 0 0xff
|
||||
default 0x33
|
||||
help
|
||||
Set the pulse amplitude to control the LED2 (IR) current. The actual
|
||||
measured LED current for each part can vary significantly due to the
|
||||
trimming methodology.
|
||||
0x00 = 0.0 mA
|
||||
0x01 = 0.2 mA
|
||||
0x02 = 0.4 mA
|
||||
0x0f = 3.1 mA
|
||||
0xff = 50.0 mA
|
||||
|
||||
config MAX30101_LED3_PA
|
||||
hex "LED2 (green) pulse amplitude"
|
||||
range 0 0xff
|
||||
default 0xff
|
||||
help
|
||||
Set the pulse amplitude to control the LED3 (green) current. The
|
||||
actual measured LED current for each part can vary significantly due
|
||||
to the trimming methodology.
|
||||
0x00 = 0.0 mA
|
||||
0x01 = 0.2 mA
|
||||
0x02 = 0.4 mA
|
||||
0x0f = 3.1 mA
|
||||
0xff = 50.0 mA
|
||||
|
||||
if MAX30101_MULTI_LED_MODE
|
||||
|
||||
config MAX30101_SLOT1
|
||||
int "Slot 1"
|
||||
range 0 7
|
||||
default 3
|
||||
help
|
||||
Set which LED and pulse amplitude are active in time slot 1.
|
||||
0: None (disabled)
|
||||
1: LED1 (red), LED1_PA
|
||||
2: LED2 (IR), LED2_PA
|
||||
3: LED3 (green), LED3_PA
|
||||
4: None (disabled)
|
||||
5: LED1 (red), PILOT_PA
|
||||
6: LED2 (IR), PILOT_PA
|
||||
7: LED3 (green), PILOT_PA
|
||||
|
||||
config MAX30101_SLOT2
|
||||
int "Slot 2"
|
||||
range 0 7
|
||||
default 0
|
||||
help
|
||||
Set which LED and pulse amplitude are active in time slot 2.
|
||||
0: None (disabled)
|
||||
1: LED1 (red), LED1_PA
|
||||
2: LED2 (IR), LED2_PA
|
||||
3: LED3 (green), LED3_PA
|
||||
4: None (disabled)
|
||||
5: LED1 (red), PILOT_PA
|
||||
6: LED2 (IR), PILOT_PA
|
||||
7: LED3 (green), PILOT_PA
|
||||
|
||||
config MAX30101_SLOT3
|
||||
int "Slot 3"
|
||||
range 0 7
|
||||
default 0
|
||||
help
|
||||
Set which LED and pulse amplitude are active in time slot 3.
|
||||
0: None (disabled)
|
||||
1: LED1 (red), LED1_PA
|
||||
2: LED2 (IR), LED2_PA
|
||||
3: LED3 (green), LED3_PA
|
||||
4: None (disabled)
|
||||
5: LED1 (red), PILOT_PA
|
||||
6: LED2 (IR), PILOT_PA
|
||||
7: LED3 (green), PILOT_PA
|
||||
|
||||
config MAX30101_SLOT4
|
||||
int "Slot 4"
|
||||
range 0 7
|
||||
default 0
|
||||
help
|
||||
Set which LED and pulse amplitude are active in time slot 4.
|
||||
0: None (disabled)
|
||||
1: LED1 (red), LED1_PA
|
||||
2: LED2 (IR), LED2_PA
|
||||
3: LED3 (green), LED3_PA
|
||||
4: None (disabled)
|
||||
5: LED1 (red), PILOT_PA
|
||||
6: LED2 (IR), PILOT_PA
|
||||
7: LED3 (green), PILOT_PA
|
||||
|
||||
endif # MAX30101_MULTI_LED_MODE
|
||||
|
||||
endif # MAX30101
|
8
drivers/sensor/max30101/Makefile
Normal file
8
drivers/sensor/max30101/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Makefile - MAX30101 heart rate sensor
|
||||
#
|
||||
# Copyright (c) 2017, NXP
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
obj-$(CONFIG_MAX30101) += max30101.o
|
243
drivers/sensor/max30101/max30101.c
Normal file
243
drivers/sensor/max30101/max30101.c
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (c) 2017, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <max30101.h>
|
||||
|
||||
static int max30101_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct max30101_data *data = dev->driver_data;
|
||||
uint8_t buffer[MAX30101_MAX_BYTES_PER_SAMPLE];
|
||||
uint32_t fifo_data;
|
||||
int fifo_chan;
|
||||
int num_bytes;
|
||||
int i;
|
||||
|
||||
/* Read all the active channels for one sample */
|
||||
num_bytes = data->num_channels * MAX30101_BYTES_PER_CHANNEL;
|
||||
if (i2c_burst_read(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_FIFO_DATA, buffer, num_bytes)) {
|
||||
SYS_LOG_ERR("Could not fetch sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fifo_chan = 0;
|
||||
for (i = 0; i < num_bytes; i += 3) {
|
||||
/* Each channel is 18-bits */
|
||||
fifo_data = (buffer[i] << 16) | (buffer[i + 1] << 8) |
|
||||
(buffer[i + 2]);
|
||||
fifo_data &= MAX30101_FIFO_DATA_MASK;
|
||||
|
||||
/* Save the raw data */
|
||||
data->raw[fifo_chan++] = fifo_data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max30101_channel_get(struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct max30101_data *data = dev->driver_data;
|
||||
enum max30101_led_channel led_chan;
|
||||
int fifo_chan;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_RED:
|
||||
led_chan = MAX30101_LED_CHANNEL_RED;
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_IR:
|
||||
led_chan = MAX30101_LED_CHANNEL_IR;
|
||||
break;
|
||||
|
||||
case SENSOR_CHAN_GREEN:
|
||||
led_chan = MAX30101_LED_CHANNEL_GREEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
SYS_LOG_ERR("Unsupported sensor channel");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Check if the led channel is active by looking up the associated fifo
|
||||
* channel. If the fifo channel isn't valid, then the led channel
|
||||
* isn't active.
|
||||
*/
|
||||
fifo_chan = data->map[led_chan];
|
||||
if (fifo_chan >= MAX30101_MAX_NUM_CHANNELS) {
|
||||
SYS_LOG_ERR("Inactive sensor channel");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* TODO: Scale the raw data to standard units */
|
||||
val->val1 = data->raw[fifo_chan];
|
||||
val->val2 = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api max30101_driver_api = {
|
||||
.sample_fetch = max30101_sample_fetch,
|
||||
.channel_get = max30101_channel_get,
|
||||
};
|
||||
|
||||
static int max30101_init(struct device *dev)
|
||||
{
|
||||
const struct max30101_config *config = dev->config->config_info;
|
||||
struct max30101_data *data = dev->driver_data;
|
||||
uint8_t part_id;
|
||||
uint8_t mode_cfg;
|
||||
uint32_t led_chan;
|
||||
int fifo_chan;
|
||||
|
||||
/* Get the I2C device */
|
||||
data->i2c = device_get_binding(CONFIG_MAX30101_I2C_NAME);
|
||||
if (!data->i2c) {
|
||||
SYS_LOG_ERR("Could not find I2C device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check the part id to make sure this is MAX30101 */
|
||||
if (i2c_reg_read_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_PART_ID, &part_id)) {
|
||||
SYS_LOG_ERR("Could not get Part ID");
|
||||
return -EIO;
|
||||
}
|
||||
if (part_id != MAX30101_PART_ID) {
|
||||
SYS_LOG_ERR("Got Part ID 0x%02x, expected 0x%02x",
|
||||
part_id, MAX30101_PART_ID);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Reset the sensor */
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_MODE_CFG,
|
||||
MAX30101_MODE_CFG_RESET_MASK)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Wait for reset to be cleared */
|
||||
do {
|
||||
if (i2c_reg_read_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_MODE_CFG, &mode_cfg)) {
|
||||
SYS_LOG_ERR("Could read mode cfg after reset");
|
||||
return -EIO;
|
||||
}
|
||||
} while (mode_cfg & MAX30101_MODE_CFG_RESET_MASK);
|
||||
|
||||
/* Write the FIFO configuration register */
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_FIFO_CFG, config->fifo)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Write the mode configuration register */
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_MODE_CFG, config->mode)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Write the SpO2 configuration register */
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_SPO2_CFG, config->spo2)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Write the LED pulse amplitude registers */
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_LED1_PA, config->led_pa[0])) {
|
||||
return -EIO;
|
||||
}
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_LED2_PA, config->led_pa[1])) {
|
||||
return -EIO;
|
||||
}
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_LED3_PA, config->led_pa[2])) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAX30101_MULTI_LED_MODE
|
||||
uint8_t multi_led[2];
|
||||
|
||||
/* Write the multi-LED mode control registers */
|
||||
multi_led[0] = (config->slot[1] << 4) | (config->slot[0]);
|
||||
multi_led[1] = (config->slot[3] << 4) | (config->slot[2]);
|
||||
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_MULTI_LED, multi_led[0])) {
|
||||
return -EIO;
|
||||
}
|
||||
if (i2c_reg_write_byte(data->i2c, MAX30101_I2C_ADDRESS,
|
||||
MAX30101_REG_MULTI_LED + 1, multi_led[1])) {
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the channel map and active channel count */
|
||||
data->num_channels = 0;
|
||||
for (led_chan = 0; led_chan < MAX30101_MAX_NUM_CHANNELS; led_chan++) {
|
||||
data->map[led_chan] = MAX30101_MAX_NUM_CHANNELS;
|
||||
}
|
||||
|
||||
/* Count the number of active channels and build a map that translates
|
||||
* the LED channel number (red/ir/green) to the fifo channel number.
|
||||
*/
|
||||
for (fifo_chan = 0; fifo_chan < MAX30101_MAX_NUM_CHANNELS;
|
||||
fifo_chan++) {
|
||||
led_chan = (config->slot[fifo_chan] & MAX30101_SLOT_LED_MASK)-1;
|
||||
if (led_chan < MAX30101_MAX_NUM_CHANNELS) {
|
||||
data->map[led_chan] = fifo_chan;
|
||||
data->num_channels++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct max30101_config max30101_config = {
|
||||
.fifo = (CONFIG_MAX30101_SMP_AVE << MAX30101_FIFO_CFG_SMP_AVE_SHIFT) |
|
||||
#ifdef CONFIG_MAX30101_FIFO_ROLLOVER_EN
|
||||
MAX30101_FIFO_CFG_ROLLOVER_EN_MASK |
|
||||
#endif
|
||||
(CONFIG_MAX30101_FIFO_A_FULL <<
|
||||
MAX30101_FIFO_CFG_FIFO_FULL_SHIFT),
|
||||
|
||||
#if defined(CONFIG_MAX30101_HEART_RATE_MODE)
|
||||
.mode = MAX30101_MODE_HEART_RATE,
|
||||
.slot[0] = MAX30101_SLOT_RED_LED1_PA,
|
||||
.slot[1] = MAX30101_SLOT_DISABLED,
|
||||
.slot[2] = MAX30101_SLOT_DISABLED,
|
||||
.slot[3] = MAX30101_SLOT_DISABLED,
|
||||
#elif defined(CONFIG_MAX30101_SPO2_MODE)
|
||||
.mode = MAX30101_MODE_SPO2,
|
||||
.slot[0] = MAX30101_SLOT_RED_LED1_PA,
|
||||
.slot[1] = MAX30101_SLOT_IR_LED2_PA,
|
||||
.slot[2] = MAX30101_SLOT_DISABLED,
|
||||
.slot[3] = MAX30101_SLOT_DISABLED,
|
||||
#else
|
||||
.mode = MAX30101_MODE_MULTI_LED,
|
||||
.slot[0] = CONFIG_MAX30101_SLOT1,
|
||||
.slot[1] = CONFIG_MAX30101_SLOT2,
|
||||
.slot[2] = CONFIG_MAX30101_SLOT3,
|
||||
.slot[3] = CONFIG_MAX30101_SLOT4,
|
||||
#endif
|
||||
|
||||
.spo2 = (CONFIG_MAX30101_ADC_RGE << MAX30101_SPO2_ADC_RGE_SHIFT) |
|
||||
(CONFIG_MAX30101_SR << MAX30101_SPO2_SR_SHIFT) |
|
||||
(MAX30101_PW_18BITS << MAX30101_SPO2_PW_SHIFT),
|
||||
|
||||
.led_pa[0] = CONFIG_MAX30101_LED1_PA,
|
||||
.led_pa[1] = CONFIG_MAX30101_LED2_PA,
|
||||
.led_pa[2] = CONFIG_MAX30101_LED3_PA,
|
||||
};
|
||||
|
||||
static struct max30101_data max30101_data;
|
||||
|
||||
DEVICE_AND_API_INIT(max30101, CONFIG_MAX30101_NAME, max30101_init,
|
||||
&max30101_data, &max30101_config,
|
||||
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
|
||||
&max30101_driver_api);
|
107
drivers/sensor/max30101/max30101.h
Normal file
107
drivers/sensor/max30101/max30101.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2017, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <sensor.h>
|
||||
#include <i2c.h>
|
||||
#include <gpio.h>
|
||||
|
||||
#define SYS_LOG_DOMAIN "MAX30101"
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
|
||||
#include <logging/sys_log.h>
|
||||
|
||||
#define MAX30101_I2C_ADDRESS 0x57
|
||||
|
||||
#define MAX30101_REG_INT_STS1 0x00
|
||||
#define MAX30101_REG_INT_STS2 0x01
|
||||
#define MAX30101_REG_INT_EN1 0x02
|
||||
#define MAX30101_REG_INT_EN2 0x03
|
||||
#define MAX30101_REG_FIFO_WR 0x04
|
||||
#define MAX30101_REG_FIFO_OVF 0x05
|
||||
#define MAX30101_REG_FIFO_RD 0x06
|
||||
#define MAX30101_REG_FIFO_DATA 0x07
|
||||
#define MAX30101_REG_FIFO_CFG 0x08
|
||||
#define MAX30101_REG_MODE_CFG 0x09
|
||||
#define MAX30101_REG_SPO2_CFG 0x0a
|
||||
#define MAX30101_REG_LED1_PA 0x0c
|
||||
#define MAX30101_REG_LED2_PA 0x0d
|
||||
#define MAX30101_REG_LED3_PA 0x0e
|
||||
#define MAX30101_REG_PILOT_PA 0x10
|
||||
#define MAX30101_REG_MULTI_LED 0x11
|
||||
#define MAX30101_REG_TINT 0x1f
|
||||
#define MAX30101_REG_TFRAC 0x20
|
||||
#define MAX30101_REG_TEMP_CFG 0x21
|
||||
#define MAX30101_REG_PROX_INT 0x30
|
||||
#define MAX30101_REG_REV_ID 0xfe
|
||||
#define MAX30101_REG_PART_ID 0xff
|
||||
|
||||
#define MAX30101_INT_PPG_MASK (1 << 6)
|
||||
|
||||
#define MAX30101_FIFO_CFG_SMP_AVE_SHIFT 5
|
||||
#define MAX30101_FIFO_CFG_FIFO_FULL_SHIFT 0
|
||||
#define MAX30101_FIFO_CFG_ROLLOVER_EN_MASK (1 << 4)
|
||||
|
||||
#define MAX30101_MODE_CFG_SHDN_MASK (1 << 7)
|
||||
#define MAX30101_MODE_CFG_RESET_MASK (1 << 6)
|
||||
|
||||
#define MAX30101_SPO2_ADC_RGE_SHIFT 5
|
||||
#define MAX30101_SPO2_SR_SHIFT 2
|
||||
#define MAX30101_SPO2_PW_SHIFT 0
|
||||
|
||||
#define MAX30101_PART_ID 0x15
|
||||
|
||||
#define MAX30101_BYTES_PER_CHANNEL 3
|
||||
#define MAX30101_MAX_NUM_CHANNELS 3
|
||||
#define MAX30101_MAX_BYTES_PER_SAMPLE (MAX30101_MAX_NUM_CHANNELS * \
|
||||
MAX30101_BYTES_PER_CHANNEL)
|
||||
|
||||
#define MAX30101_SLOT_LED_MASK 0x03
|
||||
|
||||
#define MAX30101_FIFO_DATA_BITS 18
|
||||
#define MAX30101_FIFO_DATA_MASK ((1 << MAX30101_FIFO_DATA_BITS) - 1)
|
||||
|
||||
enum max30101_mode {
|
||||
MAX30101_MODE_HEART_RATE = 2,
|
||||
MAX30101_MODE_SPO2 = 3,
|
||||
MAX30101_MODE_MULTI_LED = 7,
|
||||
};
|
||||
|
||||
enum max30101_slot {
|
||||
MAX30101_SLOT_DISABLED = 0,
|
||||
MAX30101_SLOT_RED_LED1_PA,
|
||||
MAX30101_SLOT_IR_LED2_PA,
|
||||
MAX30101_SLOT_GREEN_LED3_PA,
|
||||
MAX30101_SLOT_RED_PILOT_PA,
|
||||
MAX30101_SLOT_IR_PILOT_PA,
|
||||
MAX30101_SLOT_GREEN_PILOT_PA,
|
||||
};
|
||||
|
||||
enum max30101_led_channel {
|
||||
MAX30101_LED_CHANNEL_RED = 0,
|
||||
MAX30101_LED_CHANNEL_IR,
|
||||
MAX30101_LED_CHANNEL_GREEN,
|
||||
};
|
||||
|
||||
enum max30101_pw {
|
||||
MAX30101_PW_15BITS = 0,
|
||||
MAX30101_PW_16BITS,
|
||||
MAX30101_PW_17BITS,
|
||||
MAX30101_PW_18BITS,
|
||||
};
|
||||
|
||||
struct max30101_config {
|
||||
uint8_t fifo;
|
||||
uint8_t spo2;
|
||||
uint8_t led_pa[MAX30101_MAX_NUM_CHANNELS];
|
||||
enum max30101_mode mode;
|
||||
enum max30101_slot slot[4];
|
||||
};
|
||||
|
||||
struct max30101_data {
|
||||
struct device *i2c;
|
||||
uint32_t raw[MAX30101_MAX_NUM_CHANNELS];
|
||||
uint8_t map[MAX30101_MAX_NUM_CHANNELS];
|
||||
uint8_t num_channels;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue