From 1a582815ba218d2a9047abae92b9f33a3301ffd5 Mon Sep 17 00:00:00 2001 From: Jean-François Milants Date: Sun, 10 Jan 2021 17:57:26 +0100 Subject: First implementation of the HR sensor using 100% foss code (ported from waspos) --- src/drivers/Hrs3300.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/Hrs3300.h | 47 +++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 src/drivers/Hrs3300.cpp create mode 100644 src/drivers/Hrs3300.h (limited to 'src/drivers') diff --git a/src/drivers/Hrs3300.cpp b/src/drivers/Hrs3300.cpp new file mode 100644 index 00000000..31956575 --- /dev/null +++ b/src/drivers/Hrs3300.cpp @@ -0,0 +1,108 @@ +#include +#include +#include "Hrs3300.h" + +#include +#include +#include + +using namespace Pinetime::Drivers; + +Hrs3300::Hrs3300(TwiMaster &twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, twiAddress{twiAddress} { + +} + +void Hrs3300::Init() { + nrf_gpio_cfg_input(30, NRF_GPIO_PIN_NOPULL); + + Disable(); + vTaskDelay(100); + + // HRS disabled, 12.5 ms wait time between cycles, (partly) 20mA drive + WriteRegister(static_cast(Registers::Enable), 0x60); + + // (partly) 20mA drive, power on, "magic" (datasheet says both + // "reserved" and "set low nibble to 8" but 0xe gives better results + // and is used by at least two other HRS3300 drivers + WriteRegister(static_cast(Registers::PDriver), 0x6E); + + // HRS and ALS both in 16-bit mode + WriteRegister(static_cast(Registers::Res), 0x88); + + // 64x gain + WriteRegister(static_cast(Registers::Hgain), 0x10); +} + +void Hrs3300::Enable() { + NRF_LOG_INFO("ENABLE"); + auto value = ReadRegister(static_cast(Registers::Enable)); + value |= 0x80; + WriteRegister(static_cast(Registers::Enable), value); +} + +void Hrs3300::Disable() { + NRF_LOG_INFO("DISABLE"); + auto value = ReadRegister(static_cast(Registers::Enable)); + value &= ~0x80; + WriteRegister(static_cast(Registers::Enable), value); +} + +uint16_t Hrs3300::ReadHrs() { + auto m = ReadRegister(static_cast(Registers::C0DataM)); + auto h = ReadRegister(static_cast(Registers::C0DataH)); + auto l = ReadRegister(static_cast(Registers::C0dataL)); + return (m << 8) | ((h & 0x0f) << 4) | (l & 0x0f) | ((l & 0x30) << 12); +} + +uint16_t Hrs3300::ReadAls() { + auto m = ReadRegister(static_cast(Registers::C1dataM)); + auto h = ReadRegister(static_cast(Registers::C1dataH)); + auto l = ReadRegister(static_cast(Registers::C1dataL)); + return (m << 3) | ((h & 0x3f) << 11) | (l & 0x07); +} + +void Hrs3300::SetGain(uint8_t gain) { + static constexpr uint8_t maxGain = 64; + gain = std::min(gain, maxGain); + uint8_t hgain = 0; + while((1 << hgain) < gain) + hgain++; + + WriteRegister(static_cast(Registers::Hgain), hgain << 2); +} + +void Hrs3300::SetDrive(uint8_t drive) { + auto en = ReadRegister(static_cast(Registers::Enable)); + auto pd = ReadRegister(static_cast(Registers::PDriver)); + + en = (en & 0xf7) | ((drive & 2) << 2); + pd = (pd & 0xbf) | ((drive & 1) << 6); + + WriteRegister(static_cast(Registers::Enable), en); + WriteRegister(static_cast(Registers::PDriver), pd); +} + +void Hrs3300::WriteRegister(uint8_t reg, uint8_t data) { + auto ret = twiMaster.Write(twiAddress, reg, &data, 1); + if(ret != TwiMaster::ErrorCodes::NoError) + NRF_LOG_INFO("WRITE ERROR"); +} + +uint8_t Hrs3300::ReadRegister(uint8_t reg) { + uint8_t value; + auto ret = twiMaster.Read(twiAddress, reg, &value, 1); + if(ret != TwiMaster::ErrorCodes::NoError) + NRF_LOG_INFO("READ ERROR"); + return value; +} + + + + + + + + + + + diff --git a/src/drivers/Hrs3300.h b/src/drivers/Hrs3300.h new file mode 100644 index 00000000..c34d55c6 --- /dev/null +++ b/src/drivers/Hrs3300.h @@ -0,0 +1,47 @@ +#pragma once + +#include "TwiMaster.h" + +namespace Pinetime { + namespace Drivers { + class Hrs3300 { + public: + enum class Registers : uint8_t { + Id = 0x00, + Enable = 0x01, + EnableHen = 0x80, + C1dataM = 0x08, + C0DataM = 0x09, + C0DataH = 0x0a, + PDriver = 0x0c, + C1dataH = 0x0d, + C1dataL = 0x0e, + C0dataL = 0x0f, + Res = 0x16, + Hgain = 0x17 + }; + + Hrs3300(TwiMaster& twiMaster, uint8_t twiAddress); + Hrs3300(const Hrs3300&) = delete; + Hrs3300& operator=(const Hrs3300&) = delete; + Hrs3300(Hrs3300&&) = delete; + Hrs3300& operator=(Hrs3300&&) = delete; + + void Init(); + void Enable(); + void Disable(); + uint16_t ReadHrs(); + uint16_t ReadAls(); + void SetGain(uint8_t gain); + void SetDrive(uint8_t drive); + + private: + TwiMaster& twiMaster; + uint8_t twiAddress; + + void WriteRegister(uint8_t reg, uint8_t data); + uint8_t ReadRegister(uint8_t reg); + + }; + } +} -- cgit v1.2.3 From 3a3a14115a81b9dd2c6f839c0ad1b14d04367642 Mon Sep 17 00:00:00 2001 From: Jean-François Milants Date: Sun, 17 Jan 2021 16:33:45 +0100 Subject: Add License/copyright info in HR related files. --- src/components/heartrate/Biquad.cpp | 7 +++++++ src/components/heartrate/Ppg.cpp | 8 +++++++- src/components/heartrate/Ptagc.cpp | 7 +++++++ src/drivers/Hrs3300.cpp | 10 +++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) (limited to 'src/drivers') diff --git a/src/components/heartrate/Biquad.cpp b/src/components/heartrate/Biquad.cpp index 37b3ba67..6a4b8181 100644 --- a/src/components/heartrate/Biquad.cpp +++ b/src/components/heartrate/Biquad.cpp @@ -1,7 +1,14 @@ +/* + SPDX-License-Identifier: LGPL-3.0-or-later + Original work Copyright (C) 2020 Daniel Thompson + C++ port Copyright (C) 2021 Jean-François Milants +*/ + #include "Biquad.h" using namespace Pinetime::Controllers; +/** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */ Biquad::Biquad(float b0, float b1, float b2, float a1, float a2) : b0{b0}, b1{b1}, b2{b2}, a1{a1}, a2{a2} { } diff --git a/src/components/heartrate/Ppg.cpp b/src/components/heartrate/Ppg.cpp index 27617c15..233c3003 100644 --- a/src/components/heartrate/Ppg.cpp +++ b/src/components/heartrate/Ppg.cpp @@ -1,10 +1,16 @@ +/* + SPDX-License-Identifier: LGPL-3.0-or-later + Original work Copyright (C) 2020 Daniel Thompson + C++ port Copyright (C) 2021 Jean-François Milants +*/ + #include #include #include "Ppg.h" using namespace Pinetime::Controllers; +/** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */ namespace { - // TODO no vector! int Compare(int* d1, int* d2, size_t count) { int e = 0; for(int i = 0; i < count; i++) { diff --git a/src/components/heartrate/Ptagc.cpp b/src/components/heartrate/Ptagc.cpp index 9302af97..dd7c4411 100644 --- a/src/components/heartrate/Ptagc.cpp +++ b/src/components/heartrate/Ptagc.cpp @@ -1,8 +1,15 @@ +/* + SPDX-License-Identifier: LGPL-3.0-or-later + Original work Copyright (C) 2020 Daniel Thompson + C++ port Copyright (C) 2021 Jean-François Milants +*/ + #include #include "Ptagc.h" using namespace Pinetime::Controllers; +/** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */ Ptagc::Ptagc(float start, float decay, float threshold) : peak{start}, decay{decay}, boost{1.0f/decay}, threshold{threshold} { } diff --git a/src/drivers/Hrs3300.cpp b/src/drivers/Hrs3300.cpp index 31956575..2aded7d3 100644 --- a/src/drivers/Hrs3300.cpp +++ b/src/drivers/Hrs3300.cpp @@ -1,3 +1,9 @@ +/* + SPDX-License-Identifier: LGPL-3.0-or-later + Original work Copyright (C) 2020 Daniel Thompson + C++ port Copyright (C) 2021 Jean-François Milants +*/ + #include #include #include "Hrs3300.h" @@ -7,7 +13,9 @@ #include using namespace Pinetime::Drivers; - +/** Driver for the HRS3300 heart rate sensor. + * Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/drivers/hrs3300.py + */ Hrs3300::Hrs3300(TwiMaster &twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, twiAddress{twiAddress} { } -- cgit v1.2.3