14#include "max30102_drv.h"
23 uint8_t INT_STAT_1 = 0x00;
24 uint8_t INT_STAT_2 = 0x01;
25 uint8_t INT_ENABLE_1 = 0x02;
26 uint8_t INT_ENABLE_2 = 0x03;
28 uint8_t FIFO_WRITE_PTR = 0x04;
29 uint8_t FIFO_OVF_COUNTER = 0x05;
30 uint8_t FIFO_READ_PTR = 0x06;
31 uint8_t FIFO_DATA = 0x07;
33 uint8_t FIFO_CONFIG = 0x08;
34 uint8_t MODE_CONFIG = 0x09;
35 uint8_t SPO2_CONFIG = 0x0A;
36 uint8_t LED1_PULSE_AMP = 0x0C;
37 uint8_t LED2_PULSE_AMP = 0x0D;
39 uint8_t MUL_LED_CTRL_1 = 0x11;
40 uint8_t MUL_LED_CTRL_2 = 0x12;
42 uint8_t DIE_TEMP_INT = 0x1F;
43 uint8_t DIE_TEMP_FRAC = 0x20;
44 uint8_t DIE_TEMP_CFG = 0x21;
46 uint8_t REVISION_ID = 0xFE;
47 uint8_t PART_ID = 0xFF;
50 uint8_t INT_A_FULL_MASK = 0x80;
51 uint8_t INT_DATA_RDY_MASK = 0x40;
52 uint8_t INT_ALC_OVF_MASK = 0x20;
53 uint8_t INT_DIE_TEMP_RDY_MASK = 0x02;
54 uint8_t ROLLOVER_MASK = 0x10;
55 uint8_t A_FULL_MASK = 0x0f;
56 uint8_t SHUTDOWN_MASK = 0x80;
57 uint8_t RESET_MASK = 0x40;
58 uint8_t SAMPLE_AVG_MASK = 0xe0;
59 uint8_t MODE_MASK = 0x07;
60 uint8_t ADC_RANGE_MASK = 0x60;
61 uint8_t SAMPLE_RATE_MASK = 0x1c;
62 uint8_t PULSE_WIDTH_MASK = 0x03;
63 uint8_t SLOT1_MASK = 0x07;
64 uint8_t SLOT2_MASK = 0x70;
65 uint8_t SLOT3_MASK = 0x07;
66 uint8_t SLOT4_MASK = 0x70;
67 uint8_t TEMP_EN = 0x01;
70 uint8_t EXPECTED_PART_ID = 0x15;
73max30102_drv::max30102_drv(
i2c_interface & i2c, uint8_t i2c_addr)
74: _i2c(i2c), _i2c_addr(i2c_addr), _data {10,10,10,10},
75 _active_slots(0), _pulse_width(0) {
78void max30102_drv::setup_sensor(MAX30102::SAMPLE_AVG sample_avg,
79 MAX30102::LED_MODE led_mode,
80 MAX30102::ADC_RANGE adc_range,
81 MAX30102::SAMPLE_RATE sample_rate,
82 MAX30102::PULSE_WIDTH pulse_width,
85 assert(check_part_id());
87 set_fifo_average(sample_avg);
88 enable_fifo_rollover(
true);
89 set_led_mode(led_mode);
90 set_adc_range(adc_range);
91 set_sample_rate(sample_rate);
92 set_pulse_width(pulse_width);
93 set_pulse_amplitude_led1(pulse_amp);
94 set_pulse_amplitude_led2(pulse_amp);
95 enable_int_die_temp_rdy(
true);
98void max30102_drv::set_fifo_average(MAX30102::SAMPLE_AVG samples) {
99 set_register_mask_value(MAX30102::FIFO_CONFIG,
100 MAX30102::SAMPLE_AVG_MASK,
104void max30102_drv::set_led_mode(MAX30102::LED_MODE mode) {
105 if (mode == MAX30102::LED1_ONLY) {
108 else if (mode == MAX30102::BOTH_LEDS) {
111 set_register_mask_value(MAX30102::MODE_CONFIG,
116void max30102_drv::set_adc_range(MAX30102::ADC_RANGE adc_range) {
117 set_register_mask_value(MAX30102::SPO2_CONFIG,
118 MAX30102::ADC_RANGE_MASK,
122void max30102_drv::set_sample_rate(MAX30102::SAMPLE_RATE rate) {
123 set_register_mask_value(MAX30102::SPO2_CONFIG,
124 MAX30102::SAMPLE_RATE_MASK,
128void max30102_drv::set_pulse_width(MAX30102::PULSE_WIDTH width) {
129 _pulse_width = width;
130 set_register_mask_value(MAX30102::SPO2_CONFIG,
131 MAX30102::PULSE_WIDTH_MASK,
135uint8_t max30102_drv::slot_data_available(uint8_t slot) {
136 return _data[slot].available_get();
139uint32_t max30102_drv::get_slot_data(uint8_t slot) {
141 _data[slot].get(val);
145bool max30102_drv::check() {
147 int8_t number_of_samples = get_write_pointer() - get_read_pointer();
149 if (number_of_samples < 0) number_of_samples += 32;
151 if (number_of_samples) {
154 for (uint8_t sample = 0; sample < number_of_samples; ++sample) {
156 buf[0] = MAX30102::FIFO_DATA;
157 _i2c.i2cWrite(_i2c_addr, buf, 1,
false);
158 _i2c.i2cRead (_i2c_addr, buf, _active_slots * 3);
160 for(uint8_t slot=0; slot < _active_slots; ++slot) {
161 uint8_t offset = slot * 3;
163 value |= buf[offset];
165 value |= buf[offset+1];
167 value |= buf[offset+2];
170 value = (value & 0x3ffff) >> (3 - _pulse_width);
171 _data[slot].put(value);
180uint8_t max30102_drv::get_int_status_1() {
181 return read_register(MAX30102::INT_STAT_1);
184uint8_t max30102_drv::get_int_status_2() {
185 return read_register(MAX30102::INT_STAT_2);
188void max30102_drv::enable_int_a_full(
bool on) {
190 set_register_mask(MAX30102::INT_ENABLE_1,
191 MAX30102::INT_A_FULL_MASK);
193 clear_register_mask(MAX30102::INT_ENABLE_1,
194 MAX30102::INT_A_FULL_MASK);
198void max30102_drv::enable_int_data_rdy(
bool on) {
200 set_register_mask(MAX30102::INT_ENABLE_1,
201 MAX30102::INT_DATA_RDY_MASK);
203 clear_register_mask(MAX30102::INT_ENABLE_1,
204 MAX30102::INT_DATA_RDY_MASK);
208void max30102_drv::enable_int_alc_ovf(
bool on) {
210 set_register_mask(MAX30102::INT_ENABLE_1,
211 MAX30102::INT_ALC_OVF_MASK);
213 clear_register_mask(MAX30102::INT_ENABLE_1,
214 MAX30102::INT_ALC_OVF_MASK);
218void max30102_drv::enable_int_die_temp_rdy(
bool on) {
220 set_register_mask(MAX30102::INT_ENABLE_2,
221 MAX30102::INT_DIE_TEMP_RDY_MASK);
223 clear_register_mask(MAX30102::INT_ENABLE_2,
224 MAX30102::INT_DIE_TEMP_RDY_MASK);
228void max30102_drv::enable_fifo_rollover(
bool on) {
230 set_register_mask(MAX30102::FIFO_CONFIG,
231 MAX30102::ROLLOVER_MASK);
233 clear_register_mask(MAX30102::FIFO_CONFIG,
234 MAX30102::ROLLOVER_MASK);
238void max30102_drv::set_fifo_almost_full(uint8_t samples) {
239 assert(samples >= 17 && samples <=32);
240 set_register_mask_value(MAX30102::FIFO_CONFIG,
241 MAX30102::A_FULL_MASK,
245void max30102_drv::shutdown(
bool on) {
247 set_register_mask(MAX30102::MODE_CONFIG,
248 MAX30102::SHUTDOWN_MASK);
251 clear_register_mask(MAX30102::MODE_CONFIG,
252 MAX30102::SHUTDOWN_MASK);
256void max30102_drv::reset() {
257 set_register_mask(MAX30102::MODE_CONFIG, MAX30102::RESET_MASK);
258 uint8_t reset_bit = get_register_mask(MAX30102::MODE_CONFIG,
259 MAX30102::RESET_MASK);
262 reset_bit = get_register_mask(MAX30102::MODE_CONFIG,
263 MAX30102::RESET_MASK);
267void max30102_drv::set_pulse_amplitude_led1(uint8_t amplitude) {
268 write_register(MAX30102::LED1_PULSE_AMP, amplitude);
271void max30102_drv::set_pulse_amplitude_led2(uint8_t amplitude) {
272 write_register(MAX30102::LED2_PULSE_AMP, amplitude);
275void max30102_drv::config_slots(uint8_t slot1, uint8_t slot2,
276 uint8_t slot3, uint8_t slot4) {
278 if (slot1 != MAX30102::SLOT_NONE) {
279 set_register_mask_value(MAX30102::MUL_LED_CTRL_1,
280 MAX30102::SLOT1_MASK, slot1);
283 if (slot2 != MAX30102::SLOT_NONE) {
284 set_register_mask_value(MAX30102::MUL_LED_CTRL_1,
285 MAX30102::SLOT2_MASK, slot2 << 4);
288 if (slot3 != MAX30102::SLOT_NONE) {
289 set_register_mask_value(MAX30102::MUL_LED_CTRL_2,
290 MAX30102::SLOT3_MASK, slot3);
293 if (slot4 != MAX30102::SLOT_NONE) {
294 set_register_mask_value(MAX30102::MUL_LED_CTRL_2,
295 MAX30102::SLOT4_MASK, slot4 << 4);
300float max30102_drv::read_temperature() {
302 write_register(MAX30102::DIE_TEMP_CFG, MAX30102::TEMP_EN);
304 uint8_t rdy_bit = read_register(MAX30102::INT_STAT_2);
307 rdy_bit = read_register(MAX30102::INT_STAT_2);
309 uint8_t tempInt = read_register(MAX30102::DIE_TEMP_INT);
311 uint8_t tempFrac = read_register(MAX30102::DIE_TEMP_FRAC);
312 return (
float)tempInt + (float)tempFrac * 0.0625;
315uint8_t max30102_drv::read_part_id() {
316 return read_register(MAX30102::PART_ID);
319bool max30102_drv::check_part_id() {
320 return read_part_id() == MAX30102::EXPECTED_PART_ID;
323uint8_t max30102_drv::get_revision_id() {
324 return read_register(MAX30102::REVISION_ID);
327uint8_t max30102_drv::get_write_pointer() {
328 return read_register(MAX30102::FIFO_WRITE_PTR);
331uint8_t max30102_drv::get_ovf_counter() {
332 return read_register(MAX30102::FIFO_OVF_COUNTER);
335uint8_t max30102_drv::get_read_pointer() {
336 return read_register(MAX30102::FIFO_READ_PTR);
339uint8_t max30102_drv::read_register(uint8_t reg) {
342 _i2c.i2cWrite(_i2c_addr, buf, 1,
false);
343 _i2c.i2cRead (_i2c_addr, buf, 1);
347void max30102_drv::write_register(uint8_t reg, uint8_t data) {
351 _i2c.i2cWrite(_i2c_addr, buf, 2);
354uint8_t max30102_drv::get_register_mask(uint8_t reg, uint8_t mask) {
355 return read_register(reg) & mask;
358void max30102_drv::set_register_mask(uint8_t reg, uint8_t mask) {
360 write_register(reg, read_register(reg) | mask);
363void max30102_drv::set_register_mask_value(uint8_t reg, uint8_t mask, uint8_t val) {
365 write_register(reg, (read_register(reg) & ~mask) | (val & mask));
368void max30102_drv::clear_register_mask(uint8_t reg, uint8_t mask) {
369 write_register(reg, read_register(reg) & ~mask);