M5Unit-HEART 0.0.2 git rev:70607f7
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
42 bool shdn() const
43 {
44 return value & (1U << 7);
45 }
46 bool reset() const
47 {
48 return value & (1U << 6);
49 }
50 bool temperature() const
51 {
52 return value & (1U << 3);
53 }
54 Mode mode() const
55 {
56 return static_cast<Mode>(value & 0x07);
57 }
59
62 void shdn(const bool b)
63 {
64 value = (value & ~(1U << 7)) | ((b ? 1 : 0) << 7);
65 }
66 void reset(const bool b)
67 {
68 value = (value & ~(1U << 6)) | ((b ? 1 : 0) << 6);
69 }
70 void temperature(const bool b)
71 {
72 value = (value & ~(1U << 3)) | ((b ? 1 : 0) << 3);
73 }
74 void mode(const Mode m)
75 {
76 value = (value & ~0x07) | (m5::stl::to_underlying(m) & 0x07);
77 }
79
80 uint8_t value{};
81};
82
88enum class Sampling : uint8_t {
89 Rate50,
90 Rate100,
91 Rate167,
92 Rate200,
93 Rate400,
94 Rate600,
95 Rate800,
96 Rate1000,
97};
98
104uint32_t getSamplingRate(const Sampling rate);
105
110enum class LedPulseWidth {
111 PW200,
112 PW400,
113 PW800,
114 PW1600,
115};
116
149 bool highResolution() const
150 { // for SpO2
151 return value & (1U << 6);
152 }
153 Sampling samplingRate() const
154 {
155 return static_cast<Sampling>((value >> 2) & 0x07);
156 }
157 LedPulseWidth ledPulseWidth() const
158 {
159 return static_cast<LedPulseWidth>(value & 0x03);
160 }
162
165 void highResolution(const bool b)
166 { // for SpO2
167 value = (value & ~(1U << 6)) | ((b ? 1 : 0) << 6);
168 }
169 void samplingRate(const Sampling rate)
170 {
171 value = (value & ~(0x07 << 2)) | ((m5::stl::to_underlying(rate) & 0x07) << 2);
172 }
173 void ledPulseWidth(const LedPulseWidth width)
174 {
175 value = (value & ~0x03) | (m5::stl::to_underlying(width) & 0x03);
176 }
178
179 uint8_t value{};
180};
181
186enum class CurrentControl {
187 mA0_0,
188 mA4_4,
189 mA7_6,
190 mA11_0,
191 mA14_2,
192 mA17_4,
193 mA20_8,
194 mA24_0,
195 mA27_1,
196 mA30_6,
197 mA33_8,
198 mA37_0,
199 mA40_2,
200 mA43_6,
201 mA46_8,
202 mA50_0,
203};
204
212 CurrentControl red() const
213 {
214 return static_cast<CurrentControl>((value >> 4) & 0x0F);
215 }
216 CurrentControl ir() const
217 {
218 return static_cast<CurrentControl>(value & 0x0F);
219 }
223 void red(const CurrentControl cc)
224 {
225 value = (value & ~(0x0F << 4)) | ((m5::stl::to_underlying(cc) & 0x0F) << 4);
226 }
227 void ir(const CurrentControl cc)
228 {
229 value = (value & ~0x0F) | (m5::stl::to_underlying(cc) & 0x0F);
230 }
232 uint8_t value{};
233};
234
236constexpr uint8_t MAX_FIFO_DEPTH{16};
237
242struct Data {
243 std::array<uint8_t, 4> raw{};
244 uint16_t ir() const;
245 uint16_t red() const;
246};
247
253 std::array<uint8_t, 2> raw{};
255 inline float temperature() const
256 {
257 return celsius();
258 }
259 float celsius() const;
260 float fahrenheit() const;
261};
262
263} // namespace max30100
264
271class UnitMAX30100 : public Component, public PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data> {
272 M5_UNIT_COMPONENT_HPP_BUILDER(UnitMAX30100, 0x57);
273
274public:
280 struct config_t {
282 bool start_periodic{true};
284 max30100::Mode mode{max30100::Mode::SPO2};
286 max30100::Sampling sampling_rate{m5::unit::max30100::Sampling::Rate100};
288 max30100::LedPulseWidth pulse_width{m5::unit::max30100::LedPulseWidth::PW1600};
290 m5::unit::max30100::CurrentControl ir_current{m5::unit::max30100::CurrentControl::mA27_1};
292 bool high_resolution{true};
294 m5::unit::max30100::CurrentControl red_current{m5::unit::max30100::CurrentControl::mA27_1};
295 };
296
297 explicit UnitMAX30100(const uint8_t addr = DEFAULT_ADDRESS)
298 : Component(addr), _data{new m5::container::CircularBuffer<max30100::Data>(max30100::MAX_FIFO_DEPTH)}
299 {
300 auto ccfg = component_config();
301 ccfg.clock = 400 * 1000U;
302 ccfg.stored_size = max30100::MAX_FIFO_DEPTH;
303 component_config(ccfg);
304 }
305 virtual ~UnitMAX30100()
306 {
307 }
308
309 virtual bool begin() override;
310 virtual void update(const bool force = false) override;
311
314
316 {
317 return _cfg;
318 }
320 inline void config(const config_t& cfg)
321 {
322 _cfg = cfg;
323 }
325
329 inline uint16_t ir() const
330 {
331 return !empty() ? oldest().ir() : 0;
332 }
334 inline uint16_t red() const
335 {
336 return !empty() ? oldest().red() : 0;
337 }
344 inline uint8_t retrived() const
345 {
346 return _retrived;
347 }
352 inline uint8_t overflow() const
353 {
354 return _overflow;
355 }
357
360
365 {
366 return PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data>::startPeriodicMeasurement();
367 }
379 inline bool startPeriodicMeasurement(const max30100::Mode mode, const max30100::Sampling sample_rate,
380 const max30100::LedPulseWidth pulse_width,
381 const max30100::CurrentControl ir_current, const bool high_resolution = false,
382 const max30100::CurrentControl red_current = max30100::CurrentControl::mA0_0)
383 {
384 return PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data>::startPeriodicMeasurement(
385 mode, sample_rate, pulse_width, ir_current, high_resolution, red_current);
386 }
392 {
393 return PeriodicMeasurementAdapter<UnitMAX30100, max30100::Data>::stopPeriodicMeasurement();
394 }
395
400
413 bool writeMode(const max30100::Mode mode);
416 {
417 return enable_power_save(true);
418 }
421 {
422 return enable_power_save(false);
423 }
425
430
443 bool writeSamplingRate(const max30100::Sampling rate);
448 {
449 return enable_high_resolution(true);
450 }
453 {
454 return enable_high_resolution(false);
455 }
457
463
478
483
491
496 bool resetFIFO();
502 bool reset();
503
504protected:
505 bool start_periodic_measurement();
506 bool start_periodic_measurement(const max30100::Mode mode, const max30100::Sampling sample_rate,
507 const max30100::LedPulseWidth pulse_width,
508 const max30100::CurrentControl ir_current, const bool high_resolution,
509 const max30100::CurrentControl red_current);
510 bool stop_periodic_measurement();
511
512 bool read_FIFO();
513 bool read_measurement_temperature(max30100::TemperatureData& td);
514
515 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitMAX30100, max30100::Data);
516
517 bool read_mode_configration(uint8_t& c);
518 bool write_mode_configration(const uint8_t c);
519 bool enable_power_save(const bool enabled);
520 bool read_spo2_configration(uint8_t& c);
521 bool write_spo2_configration(const uint8_t c);
522 bool enable_high_resolution(const bool enabled);
523 bool read_led_configration(uint8_t& c);
524 bool write_led_configration(const uint8_t c);
525
526 bool read_register(const uint8_t reg, uint8_t* buf, const size_t len);
527 bool read_register8(const uint8_t reg, uint8_t& v);
528
529protected:
530 max30100::Mode _mode{max30100::Mode::None};
531 uint8_t _retrived{}, _overflow{};
532 std::unique_ptr<m5::container::CircularBuffer<max30100::Data>> _data{};
533
534 config_t _cfg{};
535};
536
538namespace max30100 {
539namespace command {
540// STATUS
541constexpr uint8_t READ_INTERRUPT_STATUS{0x00};
542constexpr uint8_t INTERRUPT_ENABLE{0x01};
543// FIFO
544constexpr uint8_t FIFO_WRITE_POINTER{0x02};
545constexpr uint8_t FIFO_OVERFLOW_COUNTER{0x03};
546constexpr uint8_t FIFO_READ_POINTER{0x04};
547// Note that FIFO_DATA_REGISTER cannot be burst read.
548constexpr uint8_t FIFO_DATA_REGISTER{0x05};
549// CONFIGURATION
550constexpr uint8_t MODE_CONFIGURATION{0x06};
551constexpr uint8_t SPO2_CONFIGURATION{0x07};
552constexpr uint8_t LED_CONFIGURATION{0x09};
553// TEMPERATURE
554constexpr uint8_t TEMP_INTEGER{0x16};
555constexpr uint8_t TEMP_FRACTION{0x17};
556// PART ID
557constexpr uint8_t READ_REVISION_ID{0xFE};
558constexpr uint8_t PART_ID{0xFF};
559
560} // namespace command
561} // namespace max30100
563
564} // namespace unit
565} // namespace m5
566
567#endif
Pulse oximetry and heart-rate sensor.
Definition unit_MAX30100.hpp:271
void config(const config_t &cfg)
Set the configration.
Definition unit_MAX30100.hpp:320
uint8_t overflow() const
The number of samples lost.
Definition unit_MAX30100.hpp:352
bool readSpO2Configuration(max30100::SpO2Configuration &sc)
Read SpO2 configrartion.
Definition unit_MAX30100.cpp:224
bool writeSamplingRate(const max30100::Sampling rate)
Write sample rate.
Definition unit_MAX30100.cpp:234
bool writePowerSaveDisable()
Write power save mode to disable.
Definition unit_MAX30100.hpp:420
bool measureTemperatureSingleshot(max30100::TemperatureData &td)
Measure tempeature single shot.
Definition unit_MAX30100.cpp:278
bool writeHighResolutionDisable()
Write SpO2 high resolution mode to disable.
Definition unit_MAX30100.hpp:452
bool writeSpO2Configuration(const max30100::SpO2Configuration sc)
Write SpO2 configrartion.
Definition unit_MAX30100.cpp:229
bool startPeriodicMeasurement()
Start periodic measurement in the current settings.
Definition unit_MAX30100.hpp:364
bool writeMode(const max30100::Mode mode)
Write Mode.
Definition unit_MAX30100.cpp:196
uint8_t retrived() const
Number of data last retrieved.
Definition unit_MAX30100.hpp:344
bool startPeriodicMeasurement(const max30100::Mode mode, const max30100::Sampling sample_rate, const max30100::LedPulseWidth pulse_width, const max30100::CurrentControl ir_current, const bool high_resolution=false, const max30100::CurrentControl red_current=max30100::CurrentControl::mA0_0)
Start periodic measurement.
Definition unit_MAX30100.hpp:379
config_t config()
Gets the configration.
Definition unit_MAX30100.hpp:315
bool writeModeConfiguration(const max30100::ModeConfiguration mc)
Write Mode configuration.
Definition unit_MAX30100.cpp:191
bool readModeConfiguration(max30100::ModeConfiguration &mc)
Read Mode configuration.
Definition unit_MAX30100.cpp:186
bool writeHighResolutionEnable()
Writee SpO2 high resolution mode to enable.
Definition unit_MAX30100.hpp:447
bool stopPeriodicMeasurement()
Stop periodic measurement.
Definition unit_MAX30100.hpp:391
bool writeLedConfiguration(const max30100::LedConfiguration lc)
Write Led configrartion.
Definition unit_MAX30100.cpp:259
bool reset()
Reset.
Definition unit_MAX30100.cpp:206
bool writeLedCurrent(const max30100::CurrentControl ir, const max30100::CurrentControl red)
Write IR/RED current.
Definition unit_MAX30100.cpp:264
bool resetFIFO()
Reset FIFO buffer.
Definition unit_MAX30100.cpp:272
bool writeLedPulseWidth(const max30100::LedPulseWidth width)
Write LED pulse width.
Definition unit_MAX30100.cpp:244
uint16_t red() const
Oldest Red.
Definition unit_MAX30100.hpp:334
uint16_t ir() const
Oldest IR.
Definition unit_MAX30100.hpp:329
bool writePowerSaveEnable()
Write power save mode to enable.
Definition unit_MAX30100.hpp:415
bool readLedConfiguration(max30100::LedConfiguration &lc)
Read Led configrartion.
Definition unit_MAX30100.cpp:254
Top level namespace of M5stack.
For MAX30100.
Unit-related namespace.
Settings for begin.
Definition unit_MAX30100.hpp:280
max30100::LedPulseWidth pulse_width
Led pulse width if start on begin.
Definition unit_MAX30100.hpp:288
m5::unit::max30100::CurrentControl red_current
Led current for Red if start on begin (only SpO2)
Definition unit_MAX30100.hpp:294
m5::unit::max30100::CurrentControl ir_current
Led current for IR if start on begin.
Definition unit_MAX30100.hpp:290
bool start_periodic
Start periodic measurement on begin?
Definition unit_MAX30100.hpp:282
max30100::Mode mode
Operating mode if start on begin.
Definition unit_MAX30100.hpp:284
max30100::Sampling sampling_rate
Sampling rate if start on begin.
Definition unit_MAX30100.hpp:286
bool high_resolution
The SpO2 ADC resolution if start on begin (only SpO2)
Definition unit_MAX30100.hpp:292
Measurement data group.
Definition unit_MAX30100.hpp:242
uint16_t red() const
RED.
Definition unit_MAX30100.cpp:62
uint16_t ir() const
IR.
Definition unit_MAX30100.cpp:58
Accessor for LedConfiguration.
Definition unit_MAX30100.hpp:209
Accessor for ModeConfiguration.
Definition unit_MAX30100.hpp:39
void mode(const Mode m)
Mode control.
Definition unit_MAX30100.hpp:74
bool reset() const
Reset control.
Definition unit_MAX30100.hpp:46
void shdn(const bool b)
Shutdown Control (SHDN)
Definition unit_MAX30100.hpp:62
bool shdn() const
Shutdown Control (SHDN)
Definition unit_MAX30100.hpp:42
void temperature(const bool b)
Temperature enable.
Definition unit_MAX30100.hpp:70
bool temperature() const
Temperature enable.
Definition unit_MAX30100.hpp:50
Mode mode() const
Mode control.
Definition unit_MAX30100.hpp:54
void reset(const bool b)
Reset control.
Definition unit_MAX30100.hpp:66
Accessor for SpO2Configuration.
Definition unit_MAX30100.hpp:146
Measurement data group for temperature.
Definition unit_MAX30100.hpp:252
float fahrenheit() const
temperature (Fahrenheit)
Definition unit_MAX30100.cpp:72
float celsius() const
temperature (Celsius)
Definition unit_MAX30100.cpp:67
float temperature() const
temperature (Celsius)
Definition unit_MAX30100.hpp:255
Mode
Operation mode.
Definition unit_MAX30100.hpp:29
@ HROnly
HR only enabled.
@ SPO2
SPO2 and HR enabled.
constexpr uint8_t MAX_FIFO_DEPTH
FIFO depth.
Definition unit_MAX30100.hpp:236
CurrentControl
Current level for Led.
Definition unit_MAX30100.hpp:186
LedPulseWidth
LED pulse width (the IR and RED have the same pulse width)
Definition unit_MAX30100.hpp:110
@ PW200
200 us (ADC 13 bits)
@ PW1600
1600 us (ADC 16 bits)
@ PW800
800 us (ADC 15 bits)
@ PW400
400 us (ADC 14 bits)
Sampling
Sampling rate for pulse.
Definition unit_MAX30100.hpp:88