M5Unit-HEART 0.1.0 git rev:05c3b01
Loading...
Searching...
No Matches
unit_MAX30100.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_HEART_UNIT_MAX30100_HPP
11#define M5_UNIT_HEART_UNIT_MAX30100_HPP
12
13#include <M5UnitComponent.hpp>
14#include <m5_utility/stl/extension.hpp>
15#include <m5_utility/container/circular_buffer.hpp>
16#include <limits> // NaN
17
18namespace m5 {
19namespace unit {
24namespace max30100 {
29enum class Mode : uint8_t {
30 None,
31 HROnly = 0x02,
32 SpO2,
33};
34
40enum class Sampling : uint8_t {
41 Rate50,
42 Rate100,
43 Rate167,
44 Rate200,
45 Rate400,
46 Rate600,
47 Rate800,
48 Rate1000,
49};
50
55enum class LEDPulse : uint8_t {
56 Width200,
57 Width400,
58 Width800,
59 Width1600,
60};
61
84
85constexpr uint8_t MAX_FIFO_DEPTH{16};
86
91struct Data {
92 std::array<uint8_t, 4> raw{}; // [0...1]:IR [2...3]:Red
93 inline uint16_t ir() const
94 {
95 return m5::types::big_uint16_t(raw[0], raw[1]).get();
96 }
97 inline uint16_t red() const
98 {
99 return m5::types::big_uint16_t(raw[2], raw[3]).get();
100 }
101};
102
108 std::array<uint8_t, 2> raw{0xFF, 0xFF}; // [0]:integer [1]:fraction
110 inline float temperature() const
111 {
112 return celsius();
113 }
115 inline float celsius() const
116 {
117 return (raw[0] != 0xFF) ? (int8_t)raw[0] + raw[1] * 0.0625f : std::numeric_limits<float>::quiet_NaN();
118 }
120 inline float fahrenheit() const
121 {
122 return celsius() * 9.0f / 5.0f + 32.f;
123 }
124};
125
127namespace command {
128// STATUS
129constexpr uint8_t READ_INTERRUPT_STATUS{0x00};
130constexpr uint8_t INTERRUPT_ENABLE{0x01};
131// FIFO
132constexpr uint8_t FIFO_WRITE_POINTER{0x02};
133constexpr uint8_t FIFO_OVERFLOW_COUNTER{0x03};
134constexpr uint8_t FIFO_READ_POINTER{0x04};
135constexpr uint8_t FIFO_DATA_REGISTER{0x05};
136// CONFIGURATION
137constexpr uint8_t MODE_CONFIGURATION{0x06};
138constexpr uint8_t SPO2_CONFIGURATION{0x07};
139constexpr uint8_t LED_CONFIGURATION{0x09};
140// TEMPERATURE
141constexpr uint8_t TEMP_INTEGER{0x16};
142constexpr uint8_t TEMP_FRACTION{0x17};
143// PART ID
144constexpr uint8_t READ_REVISION_ID{0xFE};
145constexpr uint8_t READ_PART_ID{0xFF};
146
147} // namespace command
148
149struct SpO2Configuration;
151
152} // namespace max30100
153
159class UnitMAX30100 : public Component, public PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data> {
160 M5_UNIT_COMPONENT_HPP_BUILDER(UnitMAX30100, 0x57);
161
162public:
168 struct config_t {
170 bool start_periodic{true};
172 max30100::Mode mode{max30100::Mode::SpO2};
174 max30100::Sampling rate{max30100::Sampling::Rate100};
176 max30100::LEDPulse width{max30100::LEDPulse::Width1600};
178 m5::unit::max30100::LED ir_current{max30100::LED::Current27_1};
180 bool high_resolution{true};
182 m5::unit::max30100::LED red_current{max30100::LED::Current27_1};
183 };
184
185 explicit UnitMAX30100(const uint8_t addr = DEFAULT_ADDRESS)
186 : Component(addr), _data{new m5::container::CircularBuffer<max30100::Data>(max30100::MAX_FIFO_DEPTH)}
187 {
188 auto ccfg = component_config();
189 ccfg.clock = 400 * 1000U;
190 ccfg.stored_size = max30100::MAX_FIFO_DEPTH;
191 component_config(ccfg);
192 }
193 virtual ~UnitMAX30100()
194 {
195 }
196
197 virtual bool begin() override;
198 virtual void update(const bool force = false) override;
199
202
204 {
205 return _cfg;
206 }
208 inline void config(const config_t& cfg)
209 {
210 _cfg = cfg;
211 }
213
217 inline uint16_t ir() const
218 {
219 return !empty() ? oldest().ir() : 0;
220 }
222 inline uint16_t red() const
223 {
224 return !empty() ? oldest().red() : 0;
225 }
232 inline uint8_t retrived() const
233 {
234 return _retrived;
235 }
240 inline uint8_t overflow() const
241 {
242 return _overflow;
243 }
245
251 uint32_t caluculateSamplingRate();
252
255
260 {
261 return PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data>::startPeriodicMeasurement();
262 }
275 const max30100::LEDPulse width, const max30100::LED ir_current,
276 const bool high_resolution = false,
277 const max30100::LED red_current = max30100::LED::Current0_0)
278 {
279 return PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data>::startPeriodicMeasurement(
280 mode, rate, width, ir_current, high_resolution, red_current);
281 }
287 {
288 return PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data>::stopPeriodicMeasurement();
289 }
291
294
299 bool readMode(max30100::Mode& mode);
306 bool writeMode(const max30100::Mode mode);
312 bool readShutdownControl(bool& shdn);
319 bool writeShutdownControl(const bool shdn);
321
349
356 bool readSpO2Configuration(bool& resolution, max30100::Sampling& rate, max30100::LEDPulse& width);
364 bool writeSpO2Configuration(const bool resolution, const max30100::Sampling rate, const max30100::LEDPulse width);
365
367 inline bool readSpO2HighResolution(bool& enabled)
368 {
369 max30100::Sampling rate{};
370 max30100::LEDPulse width{};
371 return readSpO2Configuration(enabled, rate, width);
372 }
374 bool writeSpO2HighResolution(const bool enabled);
377 {
378 return writeSpO2HighResolution(true);
379 }
382 {
383 return writeSpO2HighResolution(false);
384 }
387 {
388 bool enabled{};
389 max30100::LEDPulse width{};
390 return readSpO2Configuration(enabled, rate, width);
391 }
396 {
397 bool enabled{};
398 max30100::Sampling rate{};
399 return readSpO2Configuration(enabled, rate, width);
400 }
404
406 // @warning and only the IR LED is used to capture optical data and determine the heart rate
409
415 bool readLEDCurrent(max30100::LED& ir_current, max30100::LED& red_current);
422 bool writeLEDCurrent(const max30100::LED ir_current, const max30100::LED red_current);
424
427
437
441 inline bool readFIFOReadPointer(uint8_t& rptr)
442 {
443 rptr = 0xFF;
444 return read_register8(max30100::command::FIFO_READ_POINTER, rptr);
445 }
447 inline bool writeFIFOReadPointer(const uint8_t rptr)
448 {
449 return writeRegister8(max30100::command::FIFO_READ_POINTER, rptr);
450 }
452 inline bool readFIFOWritePointer(uint8_t& wptr)
453 {
454 wptr = 0xFF;
455 return read_register8(max30100::command::FIFO_WRITE_POINTER, wptr);
456 }
458 inline bool writeFIFOWritePointer(const uint8_t wptr)
459 {
460 return writeRegister8(max30100::command::FIFO_WRITE_POINTER, wptr);
461 }
463 inline bool readFIFOOverflowCounter(uint8_t& cnt)
464 {
465 cnt = 0xFF;
466 return read_register8(max30100::command::FIFO_OVERFLOW_COUNTER, cnt);
467 }
469 inline bool writeFIFOOverflowCounter(const uint8_t cnt)
470 {
471 return writeRegister8(max30100::command::FIFO_OVERFLOW_COUNTER, cnt);
472 }
474 bool resetFIFO();
476
482 bool reset();
483
491 bool readRevisionID(uint8_t& rev);
492
493protected:
494 bool read_register(const uint8_t reg, uint8_t* buf, const size_t len);
495 bool read_register8(const uint8_t reg, uint8_t& v);
496
497 bool start_periodic_measurement();
498 bool start_periodic_measurement(const max30100::Mode mode, const max30100::Sampling rate,
499 const max30100::LEDPulse width, const max30100::LED ir_current,
500 const bool resolution, const max30100::LED red_current);
501 bool stop_periodic_measurement();
502
503 bool read_FIFO();
504 bool read_measurement_temperature(max30100::TemperatureData& td);
505
506 bool write_spo2_configuration(const max30100::SpO2Configuration& sc);
507
508 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitMAX30100, max30100::Data);
509
510protected:
511 max30100::Mode _mode{max30100::Mode::None};
512 uint8_t _retrived{}, _overflow{};
513 std::unique_ptr<m5::container::CircularBuffer<max30100::Data>> _data{};
514
515 config_t _cfg{};
516};
517
518} // namespace unit
519} // namespace m5
520
521#endif
Pulse oximetry and heart-rate sensor.
void config(const config_t &cfg)
Set the configration.
Definition unit_MAX30100.hpp:208
bool readSpO2Configuration(bool &resolution, max30100::Sampling &rate, max30100::LEDPulse &width)
Read the SpO2 configuration.
Definition unit_MAX30100.cpp:310
uint8_t overflow() const
The number of samples lost.
Definition unit_MAX30100.hpp:240
bool readFIFOWritePointer(uint8_t &wptr)
Read the FIFO write pointer.
Definition unit_MAX30100.hpp:452
bool writeSpO2HighResolutionDisable()
Write the SpO2 high resolution mode to disable.
Definition unit_MAX30100.hpp:381
bool writeFIFOReadPointer(const uint8_t rptr)
Write the FIFO read pointer.
Definition unit_MAX30100.hpp:447
bool readRevisionID(uint8_t &rev)
Read the revision ID.
Definition unit_MAX30100.cpp:518
bool writeSpO2HighResolutionEnable()
Write the SpO2 high resolution mode to enable.
Definition unit_MAX30100.hpp:376
bool readShutdownControl(bool &shdn)
Read the shutdown control.
Definition unit_MAX30100.cpp:284
bool measureTemperatureSingleshot(max30100::TemperatureData &td)
Measure tempeature single shot.
Definition unit_MAX30100.cpp:407
bool writeFIFOWritePointer(const uint8_t wptr)
Write the FIFO write pointer.
Definition unit_MAX30100.hpp:458
uint32_t caluculateSamplingRate()
Calculate the sampling rate from the current settings.
Definition unit_MAX30100.cpp:524
bool startPeriodicMeasurement()
Start periodic measurement in the current settings.
Definition unit_MAX30100.hpp:259
bool writeSpO2HighResolution(const bool enabled)
Write the SpO2 resolution mode.
Definition unit_MAX30100.cpp:360
bool writeSpO2LEDPulseWidth(const max30100::LEDPulse width)
Write LED pulse width.
Definition unit_MAX30100.cpp:370
bool writeMode(const max30100::Mode mode)
Write the operation mode.
Definition unit_MAX30100.cpp:266
uint8_t retrived() const
Number of data last retrieved.
Definition unit_MAX30100.hpp:232
config_t config()
Gets the configration.
Definition unit_MAX30100.hpp:203
bool readFIFOOverflowCounter(uint8_t &cnt)
Read the FIFO overflow counter.
Definition unit_MAX30100.hpp:463
bool writeFIFOOverflowCounter(const uint8_t cnt)
Write the FIFO overflow counter.
Definition unit_MAX30100.hpp:469
bool writeSpO2Configuration(const bool resolution, const max30100::Sampling rate, const max30100::LEDPulse width)
Write the SpO2 configuration.
Definition unit_MAX30100.cpp:326
bool readMode(max30100::Mode &mode)
Read the operation mode.
Definition unit_MAX30100.cpp:255
bool writeSpO2SamplingRate(const max30100::Sampling rate)
Write the sampling rate.
Definition unit_MAX30100.cpp:350
bool writeShutdownControl(const bool shdn)
Write the shutdown control.
Definition unit_MAX30100.cpp:295
bool stopPeriodicMeasurement()
Stop periodic measurement.
Definition unit_MAX30100.hpp:286
bool writeLEDCurrent(const max30100::LED ir_current, const max30100::LED red_current)
Write the LED current.
Definition unit_MAX30100.cpp:393
bool startPeriodicMeasurement(const max30100::Mode mode, const max30100::Sampling rate, const max30100::LEDPulse width, const max30100::LED ir_current, const bool high_resolution=false, const max30100::LED red_current=max30100::LED::Current0_0)
Start periodic measurement.
Definition unit_MAX30100.hpp:274
bool readSpO2HighResolution(bool &enabled)
Read the SpO2 resolution mode.
Definition unit_MAX30100.hpp:367
bool readSpO2SamplingRate(max30100::Sampling &rate)
Read the sampling rate.
Definition unit_MAX30100.hpp:386
bool reset()
Reset.
Definition unit_MAX30100.cpp:428
bool resetFIFO()
Reset FIFO pointer and counter.
Definition unit_MAX30100.cpp:401
bool readSpO2LEDPulseWidth(max30100::LEDPulse &width)
Write LED pulse width.
Definition unit_MAX30100.hpp:395
uint16_t red() const
Oldest Red.
Definition unit_MAX30100.hpp:222
uint16_t ir() const
Oldest IR.
Definition unit_MAX30100.hpp:217
bool readFIFOReadPointer(uint8_t &rptr)
Read the FIFO read pointer.
Definition unit_MAX30100.hpp:441
bool readLEDCurrent(max30100::LED &ir_current, max30100::LED &red_current)
Read the LED curremt.
Definition unit_MAX30100.cpp:380
Top level namespace of M5stack.
For MAX30100.
Unit-related namespace.
Settings for begin.
Definition unit_MAX30100.hpp:168
m5::unit::max30100::LED red_current
Led current for Red if start on begin (only SpO2)
Definition unit_MAX30100.hpp:182
m5::unit::max30100::LED ir_current
Led current for IR if start on begin.
Definition unit_MAX30100.hpp:178
max30100::Sampling rate
Sampling rate if start on begin.
Definition unit_MAX30100.hpp:174
max30100::LEDPulse width
Led pulse width if start on begin.
Definition unit_MAX30100.hpp:176
bool start_periodic
Start periodic measurement on begin?
Definition unit_MAX30100.hpp:170
max30100::Mode mode
Operating mode if start on begin.
Definition unit_MAX30100.hpp:172
bool high_resolution
The SpO2 ADC resolution if start on begin.
Definition unit_MAX30100.hpp:180
Measurement data group.
Definition unit_MAX30100.hpp:91
Measurement data group for temperature.
Definition unit_MAX30100.hpp:107
float fahrenheit() const
temperature (Fahrenheit)
Definition unit_MAX30100.hpp:120
float celsius() const
Temperature (Celsius)
Definition unit_MAX30100.hpp:115
float temperature() const
Temperature (Celsius)
Definition unit_MAX30100.hpp:110
Mode
Operation mode.
Definition unit_MAX30100.hpp:29
@ HROnly
HR only enabled.
@ SpO2
SPO2 and HR enabled.
LEDPulse
LED pulse width (the IR and RED have the same pulse width)
Definition unit_MAX30100.hpp:55
@ Width200
200 us (ADC 13 bits)
@ Width1600
1600 us (ADC 16 bits)
@ Width400
400 us (ADC 14 bits)
@ Width800
800 us (ADC 15 bits)
constexpr uint8_t MAX_FIFO_DEPTH
FIFO depth.
Definition unit_MAX30100.hpp:85
Sampling
Sampling rate for pulse/conversion.
Definition unit_MAX30100.hpp:40
LED
LED current control.
Definition unit_MAX30100.hpp:66