From 2e1227fab2971286bf2b2bf59b36ebde253f4bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 23 Oct 2022 19:01:32 +0200 Subject: [PATCH 01/10] This commit improves the hardware abstraction by integrating the Concepts features of C++20 for Spi, SpiMaster and SpiNorFlash. The 'interface' of the drivers are defined in `Pinetime::Drivers::Interface::Spi`, `Pinetime::Drivers::Interface::SpiMaster` and `Pinetime::Drivers::Interface::SpiNorFlash`. The actual implementation will be injected via the template parameter `T`. T is required to conform to the corresponding concepts `IsSpi`, `IsSpiMaster` and `IsFlashMemory`. This implementation should be practically free in terms of memory and cpu resource usage, but it provides way to implement multiple variations of the same driver. It also describes very clearly the interface of the drivers thanks to the concepts. This will allow us to support more easily other hardwares : different SoC, different sensors and memory chips. It'll also make the implemenation of InfiniSim much easier. --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 23 +-- src/components/ble/DfuService.h | 6 +- src/components/ble/NimbleController.h | 4 - src/components/fs/FS.h | 1 + src/drivers/Spi.h | 70 ++++++--- src/drivers/SpiMaster.h | 101 ++++++------- src/drivers/SpiNorFlash.h | 158 ++++++++++++++------- src/drivers/St7789.h | 4 +- src/drivers/{ => nrf52}/Spi.cpp | 4 +- src/drivers/nrf52/Spi.h | 30 ++++ src/drivers/{ => nrf52}/SpiMaster.cpp | 4 +- src/drivers/nrf52/SpiMaster.h | 67 +++++++++ src/drivers/{ => spiFlash}/SpiNorFlash.cpp | 12 +- src/drivers/spiFlash/SpiNorFlash.h | 62 ++++++++ src/main.cpp | 27 ++-- src/port/infinitime.h | 24 ++++ src/systemtask/SystemTask.h | 4 +- 18 files changed, 442 insertions(+), 161 deletions(-) rename src/drivers/{ => nrf52}/Spi.cpp (94%) create mode 100644 src/drivers/nrf52/Spi.h rename src/drivers/{ => nrf52}/SpiMaster.cpp (99%) create mode 100644 src/drivers/nrf52/SpiMaster.h rename src/drivers/{ => spiFlash}/SpiNorFlash.cpp (93%) create mode 100644 src/drivers/spiFlash/SpiNorFlash.h create mode 100644 src/port/infinitime.h diff --git a/CMakeLists.txt b/CMakeLists.txt index adb1754b28..a215180da2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") project(pinetime VERSION 1.11.0 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 20) # set(CMAKE_GENERATOR "Unix Makefiles") set(CMAKE_C_EXTENSIONS OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e59c0d814b..c3848a6271 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -436,9 +436,9 @@ list(APPEND SOURCE_FILES main.cpp drivers/St7789.cpp - drivers/SpiNorFlash.cpp - drivers/SpiMaster.cpp - drivers/Spi.cpp + drivers/nrf52/SpiMaster.cpp + drivers/nrf52/Spi.cpp + drivers/spiFlash/SpiNorFlash.cpp drivers/Watchdog.cpp drivers/DebugPins.cpp drivers/InternalFlash.cpp @@ -503,9 +503,8 @@ list(APPEND RECOVERY_SOURCE_FILES main.cpp drivers/St7789.cpp - drivers/SpiNorFlash.cpp - drivers/SpiMaster.cpp - drivers/Spi.cpp + drivers/nrf52/SpiMaster.cpp + drivers/nrf52/Spi.cpp drivers/Watchdog.cpp drivers/DebugPins.cpp drivers/InternalFlash.cpp @@ -566,9 +565,8 @@ list(APPEND RECOVERYLOADER_SOURCE_FILES FreeRTOS/port_cmsis_systick.c FreeRTOS/port_cmsis.c - drivers/SpiNorFlash.cpp - drivers/SpiMaster.cpp - drivers/Spi.cpp + drivers/nrf52/SpiMaster.cpp + drivers/nrf52/Spi.cpp logging/NrfLogger.cpp components/rle/RleDecoder.cpp @@ -587,6 +585,7 @@ set(INCLUDE_FILES BootloaderVersion.h logging/Logger.h logging/NrfLogger.h + port/infinitime.h displayapp/DisplayApp.h displayapp/Messages.h displayapp/TouchEvents.h @@ -619,8 +618,9 @@ set(INCLUDE_FILES displayapp/widgets/StatusIcons.h drivers/St7789.h drivers/SpiNorFlash.h - drivers/SpiMaster.h - drivers/Spi.h + drivers/nrf52/SpiMaster.h + drivers/nrf52/Spi.h + drivers/spiFlash/SpiNorFlash.h drivers/Watchdog.h drivers/DebugPins.h drivers/InternalFlash.h @@ -687,6 +687,7 @@ include_directories( . ../ libs/ + port/ FreeRTOS/ libs/date/include libs/mynewt-nimble/porting/npl/freertos/include diff --git a/src/components/ble/DfuService.h b/src/components/ble/DfuService.h index 4708a4a607..93d5ccf77e 100644 --- a/src/components/ble/DfuService.h +++ b/src/components/ble/DfuService.h @@ -9,13 +9,13 @@ #undef max #undef min +#include +#include "infinitime.h" + namespace Pinetime { namespace System { class SystemTask; } - namespace Drivers { - class SpiNorFlash; - } namespace Controllers { class Ble; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 000231fe71..e323461a82 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -25,10 +25,6 @@ #include "components/fs/FS.h" namespace Pinetime { - namespace Drivers { - class SpiNorFlash; - } - namespace System { class SystemTask; } diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 87fcdc23f4..31e59986d1 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -2,6 +2,7 @@ #include #include "drivers/SpiNorFlash.h" +#include "port/infinitime.h" #include namespace Pinetime { diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 9b6a30f43b..77b37a7a29 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -1,28 +1,56 @@ #pragma once #include #include -#include "drivers/SpiMaster.h" +#include +#include namespace Pinetime { namespace Drivers { - class Spi { - public: - Spi(SpiMaster& spiMaster, uint8_t pinCsn); - Spi(const Spi&) = delete; - Spi& operator=(const Spi&) = delete; - Spi(Spi&&) = delete; - Spi& operator=(Spi&&) = delete; - - bool Init(); - bool Write(const uint8_t* data, size_t size); - bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize); - bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); - void Sleep(); - void Wakeup(); - - private: - SpiMaster& spiMaster; - uint8_t pinCsn; - }; + template + concept IsSpi = requires(T s, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) { + { s.Write(constData, size) } -> std::same_as; + { s.Read(command, size, data, size) } -> std::same_as; + }; + + namespace Interface { + template + requires IsSpi + class Spi { + public: + Spi(T& spi) : impl {spi} { + } + Spi(const Spi&) = delete; + Spi& operator=(const Spi&) = delete; + Spi(Spi&&) = delete; + Spi& operator=(Spi&&) = delete; + + bool Init() { + return impl.Init(); + } + + bool Write(const uint8_t* data, size_t size) { + return impl.Write(data, size); + } + + bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { + return impl.Read(cmd, cmdSize, data, dataSize); + } + + bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) { + return impl.WriteCmdAndBuffer(cmd, cmdSize, data, dataSize); + } + + void Sleep() { + impl.Sleep(); + } + + void Wakeup() { + impl.Wakeup(); + } + + private: + T& impl; + }; + } } -} +} \ No newline at end of file diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 5ea624f255..45b57d1f63 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -1,65 +1,70 @@ #pragma once #include #include - -#include -#include -#include +#include namespace Pinetime { namespace Drivers { - class SpiMaster { - public: - enum class SpiModule : uint8_t { SPI0, SPI1 }; - enum class BitOrder : uint8_t { Msb_Lsb, Lsb_Msb }; - enum class Modes : uint8_t { Mode0, Mode1, Mode2, Mode3 }; - enum class Frequencies : uint8_t { Freq8Mhz }; - struct Parameters { - BitOrder bitOrder; - Modes mode; - Frequencies Frequency; - uint8_t pinSCK; - uint8_t pinMOSI; - uint8_t pinMISO; + template + concept IsSpiMaster = + requires(T spi, uint8_t pin, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) { + { spi.Init() } -> std::same_as; + { spi.Write(pin, constData, size) } -> std::same_as; + { spi.Read(pin, command, size, data, size) } -> std::same_as; + { spi.WriteCmdAndBuffer(pin, constCommand, size, constData, size) } -> std::same_as; + { spi.OnStartedEvent() }; + { spi.OnEndEvent() }; + { spi.Sleep() }; + { spi.Wakeup() }; }; - SpiMaster(const SpiModule spi, const Parameters& params); - SpiMaster(const SpiMaster&) = delete; - SpiMaster& operator=(const SpiMaster&) = delete; - SpiMaster(SpiMaster&&) = delete; - SpiMaster& operator=(SpiMaster&&) = delete; + namespace Interface { + template + requires IsSpiMaster + class SpiMaster { + public: + SpiMaster(T& spiMaster) : impl {spiMaster} { + } + SpiMaster(const SpiMaster&) = delete; + SpiMaster& operator=(const SpiMaster&) = delete; + SpiMaster(SpiMaster&&) = delete; + SpiMaster& operator=(SpiMaster&&) = delete; + + bool Init() { + return impl.Init(); + } - bool Init(); - bool Write(uint8_t pinCsn, const uint8_t* data, size_t size); - bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize); + bool Write(uint8_t pinCsn, const uint8_t* data, size_t size) { + return impl.Write(pinCsn, data, size); + } - bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); + bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { + return impl.Read(pinCsn, cmd, cmdSize, data, dataSize); + } - void OnStartedEvent(); - void OnEndEvent(); + bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize) { + return impl.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize); + } - void Sleep(); - void Wakeup(); + void OnStartedEvent() { + impl.OnStartedEvent(); + } - private: - void SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); - void DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); - void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size); - void PrepareRx(const volatile uint32_t cmdAddress, - const volatile size_t cmdSize, - const volatile uint32_t bufferAddress, - const volatile size_t size); + void OnEndEvent() { + impl.OnEndEvent(); + } - NRF_SPIM_Type* spiBaseAddress; - uint8_t pinCsn; + void Sleep() { + impl.Sleep(); + } - SpiMaster::SpiModule spi; - SpiMaster::Parameters params; + void Wakeup() { + impl.Wakeup(); + } - volatile uint32_t currentBufferAddr = 0; - volatile size_t currentBufferSize = 0; - volatile TaskHandle_t taskToNotify; - SemaphoreHandle_t mutex = nullptr; - }; + private: + T& impl; + }; + } } -} +} \ No newline at end of file diff --git a/src/drivers/SpiNorFlash.h b/src/drivers/SpiNorFlash.h index ad4d090756..ecea0a3513 100644 --- a/src/drivers/SpiNorFlash.h +++ b/src/drivers/SpiNorFlash.h @@ -1,60 +1,116 @@ #pragma once + #include #include +#include namespace Pinetime { namespace Drivers { - class Spi; - class SpiNorFlash { - public: - explicit SpiNorFlash(Spi& spi); - SpiNorFlash(const SpiNorFlash&) = delete; - SpiNorFlash& operator=(const SpiNorFlash&) = delete; - SpiNorFlash(SpiNorFlash&&) = delete; - SpiNorFlash& operator=(SpiNorFlash&&) = delete; - - struct __attribute__((packed)) Identification { - uint8_t manufacturer = 0; - uint8_t type = 0; - uint8_t density = 0; - }; + template + concept IsFlashMemory = requires(T memory, uint32_t address, uint8_t* buffer, const uint8_t* constBuffer, size_t size) { + { memory.ReadIdentification() }; + { memory.ReadStatusRegister() } -> std::same_as; + { memory.ReadConfigurationRegister() } -> std::same_as; + { memory.WriteInProgress() } -> std::same_as; + { memory.WriteEnabled() } -> std::same_as; + { memory.Read(address, buffer, size) }; + { memory.Write(address, constBuffer, size) }; + { memory.WriteEnable() }; + { memory.SectorErase(address) }; + { memory.ReadSecurityRegister() } -> std::same_as; + { memory.ProgramFailed() } -> std::same_as; + { memory.EraseFailed() } -> std::same_as; + { memory.Init() }; + { memory.Uninit() }; + { memory.Sleep() }; + { memory.Wakeup() }; + }; - Identification ReadIdentificaion(); - uint8_t ReadStatusRegister(); - bool WriteInProgress(); - bool WriteEnabled(); - uint8_t ReadConfigurationRegister(); - void Read(uint32_t address, uint8_t* buffer, size_t size); - void Write(uint32_t address, const uint8_t* buffer, size_t size); - void WriteEnable(); - void SectorErase(uint32_t sectorAddress); - uint8_t ReadSecurityRegister(); - bool ProgramFailed(); - bool EraseFailed(); - - void Init(); - void Uninit(); - - void Sleep(); - void Wakeup(); - - private: - enum class Commands : uint8_t { - PageProgram = 0x02, - Read = 0x03, - ReadStatusRegister = 0x05, - WriteEnable = 0x06, - ReadConfigurationRegister = 0x15, - SectorErase = 0x20, - ReadSecurityRegister = 0x2B, - ReadIdentification = 0x9F, - ReleaseFromDeepPowerDown = 0xAB, - DeepPowerDown = 0xB9 - }; - static constexpr uint16_t pageSize = 256; + namespace Interface { + template + requires IsFlashMemory + class SpiNorFlash { + public: + explicit SpiNorFlash(T& spi) : impl {spi} { + } + SpiNorFlash(const SpiNorFlash&) = delete; + SpiNorFlash& operator=(const SpiNorFlash&) = delete; + SpiNorFlash(SpiNorFlash&&) = delete; + SpiNorFlash& operator=(SpiNorFlash&&) = delete; + + struct __attribute__((packed)) Identification { + uint8_t manufacturer = 0; + uint8_t type = 0; + uint8_t density = 0; + }; + + Identification ReadIdentificaion() { + return impl.ReadIdentificaion(); + } + + uint8_t ReadStatusRegister() { + return impl.ReadStatusRegister(); + } + + bool WriteInProgress() { + return impl.WriteInProgress(); + } + + bool WriteEnabled() { + return impl.WriteEnabled(); + } + + uint8_t ReadConfigurationRegister() { + return impl.ReadConfigurationRegister(); + } + + void Read(uint32_t address, uint8_t* buffer, size_t size) { + impl.Read(address, buffer, size); + } + + void Write(uint32_t address, const uint8_t* buffer, size_t size) { + impl.Write(address, buffer, size); + } - Spi& spi; - Identification device_id; - }; + void WriteEnable() { + return impl.WriteEnable(); + } + + void SectorErase(uint32_t sectorAddress) { + impl.SectorErase(sectorAddress); + } + + uint8_t ReadSecurityRegister() { + return impl.ReadSecurityRegister(); + } + + bool ProgramFailed() { + return impl.ProgramFailed(); + } + + bool EraseFailed() { + return impl.EraseFailed(); + } + + void Init() { + impl.Init(); + } + + void Uninit() { + impl.Uninit(); + } + + void Sleep() { + impl.Sleep(); + } + + void Wakeup() { + impl.Wakeup(); + } + + private: + T& impl; + }; + } } -} +} \ No newline at end of file diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 8c2ac0936d..026f4fab34 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -1,10 +1,12 @@ #pragma once +#include "Spi.h" #include #include +#include "port/infinitime.h" namespace Pinetime { namespace Drivers { - class Spi; + class St7789 { public: explicit St7789(Spi& spi, uint8_t pinDataCommand); diff --git a/src/drivers/Spi.cpp b/src/drivers/nrf52/Spi.cpp similarity index 94% rename from src/drivers/Spi.cpp rename to src/drivers/nrf52/Spi.cpp index e477622b6f..437fce9f53 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/nrf52/Spi.cpp @@ -1,8 +1,8 @@ -#include "drivers/Spi.h" +#include "Spi.h" #include #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::Nrf52; Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn {pinCsn} { nrf_gpio_cfg_output(pinCsn); diff --git a/src/drivers/nrf52/Spi.h b/src/drivers/nrf52/Spi.h new file mode 100644 index 0000000000..8072c77ad9 --- /dev/null +++ b/src/drivers/nrf52/Spi.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include "drivers/nrf52/SpiMaster.h" + +namespace Pinetime { + namespace Drivers { + namespace Nrf52 { + class Spi { + public: + Spi(Pinetime::Drivers::Nrf52::SpiMaster& spiMaster, uint8_t pinCsn); + Spi(const Spi&) = delete; + Spi& operator=(const Spi&) = delete; + Spi(Spi&&) = delete; + Spi& operator=(Spi&&) = delete; + + bool Init(); + bool Write(const uint8_t* data, size_t size); + bool Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize); + bool WriteCmdAndBuffer(const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); + void Sleep(); + void Wakeup(); + + private: + Pinetime::Drivers::Nrf52::SpiMaster& spiMaster; + uint8_t pinCsn; + }; + } + } +} \ No newline at end of file diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/nrf52/SpiMaster.cpp similarity index 99% rename from src/drivers/SpiMaster.cpp rename to src/drivers/nrf52/SpiMaster.cpp index 38f72fee62..2f4da4b90d 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/nrf52/SpiMaster.cpp @@ -1,10 +1,10 @@ -#include "drivers/SpiMaster.h" +#include "SpiMaster.h" #include #include #include #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::Nrf52; SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters& params) : spi {spi}, params {params} { } diff --git a/src/drivers/nrf52/SpiMaster.h b/src/drivers/nrf52/SpiMaster.h new file mode 100644 index 0000000000..9d88b2bba2 --- /dev/null +++ b/src/drivers/nrf52/SpiMaster.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + namespace Nrf52 { + class SpiMaster { + public: + enum class SpiModule : uint8_t { SPI0, SPI1 }; + enum class BitOrder : uint8_t { Msb_Lsb, Lsb_Msb }; + enum class Modes : uint8_t { Mode0, Mode1, Mode2, Mode3 }; + enum class Frequencies : uint8_t { Freq8Mhz }; + struct Parameters { + BitOrder bitOrder; + Modes mode; + Frequencies Frequency; + uint8_t pinSCK; + uint8_t pinMOSI; + uint8_t pinMISO; + }; + + SpiMaster(const SpiModule spi, const Parameters& params); + SpiMaster(const SpiMaster&) = delete; + SpiMaster& operator=(const SpiMaster&) = delete; + SpiMaster(SpiMaster&&) = delete; + SpiMaster& operator=(SpiMaster&&) = delete; + + bool Init(); + bool Write(uint8_t pinCsn, const uint8_t* data, size_t size); + bool Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize); + + bool WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t* cmd, size_t cmdSize, const uint8_t* data, size_t dataSize); + + void OnStartedEvent(); + void OnEndEvent(); + + void Sleep(); + void Wakeup(); + + private: + void SetupWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void DisableWorkaroundForFtpan58(NRF_SPIM_Type* spim, uint32_t ppi_channel, uint32_t gpiote_channel); + void PrepareTx(const volatile uint32_t bufferAddress, const volatile size_t size); + void PrepareRx(const volatile uint32_t cmdAddress, + const volatile size_t cmdSize, + const volatile uint32_t bufferAddress, + const volatile size_t size); + + NRF_SPIM_Type* spiBaseAddress; + uint8_t pinCsn; + + SpiMaster::SpiModule spi; + SpiMaster::Parameters params; + + volatile uint32_t currentBufferAddr = 0; + volatile size_t currentBufferSize = 0; + volatile TaskHandle_t taskToNotify; + SemaphoreHandle_t mutex = nullptr; + }; + } + } +} \ No newline at end of file diff --git a/src/drivers/SpiNorFlash.cpp b/src/drivers/spiFlash/SpiNorFlash.cpp similarity index 93% rename from src/drivers/SpiNorFlash.cpp rename to src/drivers/spiFlash/SpiNorFlash.cpp index 28f82fe6c4..51944dbcbf 100644 --- a/src/drivers/SpiNorFlash.cpp +++ b/src/drivers/spiFlash/SpiNorFlash.cpp @@ -1,16 +1,16 @@ -#include "drivers/SpiNorFlash.h" +#include "drivers/spiFlash/SpiNorFlash.h" #include #include #include #include "drivers/Spi.h" -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::SpiFlash; -SpiNorFlash::SpiNorFlash(Spi& spi) : spi {spi} { +SpiNorFlash::SpiNorFlash(Pinetime::Drivers::Nrf52::Spi& spi) : spi {spi} { } void SpiNorFlash::Init() { - device_id = ReadIdentificaion(); + device_id = ReadIdentification(); NRF_LOG_INFO("[SpiNorFlash] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, @@ -32,7 +32,7 @@ void SpiNorFlash::Wakeup() { uint8_t cmd[cmdSize] = {static_cast(Commands::ReleaseFromDeepPowerDown), 0x01, 0x02, 0x03}; uint8_t id = 0; spi.Read(reinterpret_cast(&cmd), cmdSize, &id, 1); - auto devId = device_id = ReadIdentificaion(); + auto devId = device_id = ReadIdentification(); if (devId.type != device_id.type) { NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: Failed"); } else { @@ -41,7 +41,7 @@ void SpiNorFlash::Wakeup() { NRF_LOG_INFO("[SpiNorFlash] Wakeup") } -SpiNorFlash::Identification SpiNorFlash::ReadIdentificaion() { +SpiNorFlash::Identification SpiNorFlash::ReadIdentification() { auto cmd = static_cast(Commands::ReadIdentification); Identification identification; spi.Read(&cmd, 1, reinterpret_cast(&identification), sizeof(Identification)); diff --git a/src/drivers/spiFlash/SpiNorFlash.h b/src/drivers/spiFlash/SpiNorFlash.h new file mode 100644 index 0000000000..7beadd71d6 --- /dev/null +++ b/src/drivers/spiFlash/SpiNorFlash.h @@ -0,0 +1,62 @@ +#pragma once +#include "drivers/nrf52/Spi.h" +#include +#include + +namespace Pinetime { + namespace Drivers { + namespace SpiFlash { + class SpiNorFlash { + public: + explicit SpiNorFlash(Pinetime::Drivers::Nrf52::Spi& spi); + SpiNorFlash(const SpiNorFlash&) = delete; + SpiNorFlash& operator=(const SpiNorFlash&) = delete; + SpiNorFlash(SpiNorFlash&&) = delete; + SpiNorFlash& operator=(SpiNorFlash&&) = delete; + + struct __attribute__((packed)) Identification { + uint8_t manufacturer = 0; + uint8_t type = 0; + uint8_t density = 0; + }; + + Identification ReadIdentification(); + uint8_t ReadStatusRegister(); + bool WriteInProgress(); + bool WriteEnabled(); + uint8_t ReadConfigurationRegister(); + void Read(uint32_t address, uint8_t* buffer, size_t size); + void Write(uint32_t address, const uint8_t* buffer, size_t size); + void WriteEnable(); + void SectorErase(uint32_t sectorAddress); + uint8_t ReadSecurityRegister(); + bool ProgramFailed(); + bool EraseFailed(); + + void Init(); + void Uninit(); + + void Sleep(); + void Wakeup(); + + private: + enum class Commands : uint8_t { + PageProgram = 0x02, + Read = 0x03, + ReadStatusRegister = 0x05, + WriteEnable = 0x06, + ReadConfigurationRegister = 0x15, + SectorErase = 0x20, + ReadSecurityRegister = 0x2B, + ReadIdentification = 0x9F, + ReleaseFromDeepPowerDown = 0xAB, + DeepPowerDown = 0xB9 + }; + static constexpr uint16_t pageSize = 256; + + Pinetime::Drivers::Nrf52::Spi& spi; + Identification device_id; + }; + } + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ad7a07dc98..12a3f5931e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "BootloaderVersion.h" #include "components/battery/BatteryController.h" @@ -37,8 +38,8 @@ #include "components/datetime/DateTimeController.h" #include "components/heartrate/HeartRateController.h" #include "components/fs/FS.h" -#include "drivers/Spi.h" -#include "drivers/SpiMaster.h" +#include "drivers/nrf52/Spi.h" +#include "drivers/nrf52/SpiMaster.h" #include "drivers/SpiNorFlash.h" #include "drivers/St7789.h" #include "drivers/TwiMaster.h" @@ -57,23 +58,31 @@ Pinetime::Logging::NrfLogger logger; Pinetime::Logging::DummyLogger logger; #endif +#include "port/infinitime.h" + static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; static constexpr uint8_t heartRateSensorTwiAddress = 0x44; -Pinetime::Drivers::SpiMaster spi {Pinetime::Drivers::SpiMaster::SpiModule::SPI0, - {Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb, - Pinetime::Drivers::SpiMaster::Modes::Mode3, - Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, +Pinetime::Drivers::Nrf52::SpiMaster spiImpl {Pinetime::Drivers::Nrf52::SpiMaster::SpiModule::SPI0, + {Pinetime::Drivers::Nrf52::SpiMaster::BitOrder::Msb_Lsb, + Pinetime::Drivers::Nrf52::SpiMaster::Modes::Mode3, + Pinetime::Drivers::Nrf52::SpiMaster::Frequencies::Freq8Mhz, Pinetime::PinMap::SpiSck, Pinetime::PinMap::SpiMosi, Pinetime::PinMap::SpiMiso}}; -Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn}; +Pinetime::Drivers::SpiMaster spi {spiImpl}; + +Pinetime::Drivers::Nrf52::Spi lcdSpiIpmpl {spiImpl, Pinetime::PinMap::SpiLcdCsn}; +Pinetime::Drivers::Spi lcdSpi {lcdSpiIpmpl}; Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; -Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn}; -Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi}; +Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; +Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; + +Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpiImpl}; +Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; // The TWI device should work @ up to 400Khz but there is a HW bug which prevent it from // respecting correct timings. According to erratas heet, this magic value makes it run diff --git a/src/port/infinitime.h b/src/port/infinitime.h new file mode 100644 index 0000000000..a0297e9684 --- /dev/null +++ b/src/port/infinitime.h @@ -0,0 +1,24 @@ +#pragma once +#include "drivers/Spi.h" +#include "drivers/SpiMaster.h" +#include +#include + +#ifdef TARGET_DEVICE_PINETIME +#include +#include +#include +#endif + +// #error "Do not include this" +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using SpiMaster = Interface::SpiMaster; + using Spi = Interface::Spi; + using SpiNorFlash = Interface::SpiNorFlash; +#else + #error "No target device specified!" +#endif + } +} \ No newline at end of file diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index d1e4a004f9..9eb7f78a79 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "systemtask/SystemMonitor.h" #include "components/ble/NimbleController.h" @@ -34,13 +35,12 @@ #include "drivers/Watchdog.h" #include "systemtask/Messages.h" +#include "port/infinitime.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { namespace Drivers { class Cst816S; - class SpiMaster; - class SpiNorFlash; class St7789; class TwiMaster; class Hrs3300; From d8757c50aed984d06a0112ab4c652d875856f758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Tue, 27 Dec 2022 15:17:39 +0100 Subject: [PATCH 02/10] Fix include paths, add missing new line at end of files, rename template types name with more explicit names --- src/components/ble/DfuService.h | 4 ++-- src/drivers/Spi.h | 6 +++--- src/drivers/SpiMaster.h | 6 +++--- src/drivers/SpiNorFlash.h | 6 +++--- src/drivers/St7789.h | 2 +- src/drivers/nrf52/Spi.cpp | 2 +- src/drivers/nrf52/Spi.h | 2 +- src/drivers/nrf52/SpiMaster.h | 2 +- src/drivers/spiFlash/SpiNorFlash.h | 2 +- src/port/infinitime.h | 3 +-- 10 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/ble/DfuService.h b/src/components/ble/DfuService.h index 93d5ccf77e..f30e213d26 100644 --- a/src/components/ble/DfuService.h +++ b/src/components/ble/DfuService.h @@ -9,8 +9,8 @@ #undef max #undef min -#include -#include "infinitime.h" +#include "drivers/SpiNorFlash.h" +#include "port/infinitime.h" namespace Pinetime { namespace System { diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 77b37a7a29..0df3e2c09c 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -6,8 +6,8 @@ namespace Pinetime { namespace Drivers { - template - concept IsSpi = requires(T s, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) { + template + concept IsSpi = requires(SpiImpl s, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) { { s.Write(constData, size) } -> std::same_as; { s.Read(command, size, data, size) } -> std::same_as; }; @@ -53,4 +53,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 45b57d1f63..c916f3bf48 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -5,9 +5,9 @@ namespace Pinetime { namespace Drivers { - template + template concept IsSpiMaster = - requires(T spi, uint8_t pin, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) { + requires(SpiImpl spi, uint8_t pin, const uint8_t* constData, uint8_t* data, const uint8_t* constCommand, uint8_t* command, size_t size) { { spi.Init() } -> std::same_as; { spi.Write(pin, constData, size) } -> std::same_as; { spi.Read(pin, command, size, data, size) } -> std::same_as; @@ -67,4 +67,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/drivers/SpiNorFlash.h b/src/drivers/SpiNorFlash.h index ecea0a3513..e9d41c996b 100644 --- a/src/drivers/SpiNorFlash.h +++ b/src/drivers/SpiNorFlash.h @@ -6,8 +6,8 @@ namespace Pinetime { namespace Drivers { - template - concept IsFlashMemory = requires(T memory, uint32_t address, uint8_t* buffer, const uint8_t* constBuffer, size_t size) { + template + concept IsFlashMemory = requires(MemoryImpl memory, uint32_t address, uint8_t* buffer, const uint8_t* constBuffer, size_t size) { { memory.ReadIdentification() }; { memory.ReadStatusRegister() } -> std::same_as; { memory.ReadConfigurationRegister() } -> std::same_as; @@ -113,4 +113,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 026f4fab34..8e972d838d 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -1,5 +1,5 @@ #pragma once -#include "Spi.h" +#include "drivers/Spi.h" #include #include #include "port/infinitime.h" diff --git a/src/drivers/nrf52/Spi.cpp b/src/drivers/nrf52/Spi.cpp index 437fce9f53..4197ecfa06 100644 --- a/src/drivers/nrf52/Spi.cpp +++ b/src/drivers/nrf52/Spi.cpp @@ -1,4 +1,4 @@ -#include "Spi.h" +#include "drivers/nrf52/Spi.h" #include #include diff --git a/src/drivers/nrf52/Spi.h b/src/drivers/nrf52/Spi.h index 8072c77ad9..1891fe0a97 100644 --- a/src/drivers/nrf52/Spi.h +++ b/src/drivers/nrf52/Spi.h @@ -27,4 +27,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/drivers/nrf52/SpiMaster.h b/src/drivers/nrf52/SpiMaster.h index 9d88b2bba2..affaddfd17 100644 --- a/src/drivers/nrf52/SpiMaster.h +++ b/src/drivers/nrf52/SpiMaster.h @@ -64,4 +64,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/drivers/spiFlash/SpiNorFlash.h b/src/drivers/spiFlash/SpiNorFlash.h index 7beadd71d6..d7ff9e25a4 100644 --- a/src/drivers/spiFlash/SpiNorFlash.h +++ b/src/drivers/spiFlash/SpiNorFlash.h @@ -59,4 +59,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/port/infinitime.h b/src/port/infinitime.h index a0297e9684..8cdef6bff6 100644 --- a/src/port/infinitime.h +++ b/src/port/infinitime.h @@ -10,7 +10,6 @@ #include #endif -// #error "Do not include this" namespace Pinetime { namespace Drivers { #ifdef TARGET_DEVICE_PINETIME @@ -21,4 +20,4 @@ namespace Pinetime { #error "No target device specified!" #endif } -} \ No newline at end of file +} From 0fa32f3de04af228b28a82b67558c3ef3078c7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Tue, 27 Dec 2022 21:22:57 +0100 Subject: [PATCH 03/10] Refactor TwiMaster as a generic class that implements the concept IsTwi. --- src/CMakeLists.txt | 6 +- src/drivers/Bma421.h | 3 +- src/drivers/Cst816s.h | 2 +- src/drivers/Hrs3300.h | 1 + src/drivers/Spi.h | 3 +- src/drivers/SpiMaster.h | 3 +- src/drivers/TwiMaster.h | 82 ++++++++++++++++----------- src/drivers/{ => nrf52}/TwiMaster.cpp | 4 +- src/drivers/nrf52/TwiMaster.h | 44 ++++++++++++++ src/main.cpp | 3 +- src/port/infinitime.h | 3 + src/systemtask/SystemTask.cpp | 6 -- src/systemtask/SystemTask.h | 1 - 13 files changed, 109 insertions(+), 52 deletions(-) rename src/drivers/{ => nrf52}/TwiMaster.cpp (98%) create mode 100644 src/drivers/nrf52/TwiMaster.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c3848a6271..5ddfc17545 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -438,6 +438,7 @@ list(APPEND SOURCE_FILES drivers/St7789.cpp drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp + drivers/nrf52/TwiMaster.cpp drivers/spiFlash/SpiNorFlash.cpp drivers/Watchdog.cpp drivers/DebugPins.cpp @@ -484,7 +485,6 @@ list(APPEND SOURCE_FILES systemtask/SystemTask.cpp systemtask/SystemMonitor.cpp - drivers/TwiMaster.cpp heartratetask/HeartRateTask.cpp components/heartrate/Ppg.cpp @@ -505,6 +505,7 @@ list(APPEND RECOVERY_SOURCE_FILES drivers/St7789.cpp drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp + drivers/nrf52/TwiMaster.cpp drivers/Watchdog.cpp drivers/DebugPins.cpp drivers/InternalFlash.cpp @@ -545,7 +546,6 @@ list(APPEND RECOVERY_SOURCE_FILES systemtask/SystemTask.cpp systemtask/SystemMonitor.cpp - drivers/TwiMaster.cpp components/gfx/Gfx.cpp components/rle/RleDecoder.cpp components/heartrate/HeartRateController.cpp @@ -567,6 +567,7 @@ list(APPEND RECOVERYLOADER_SOURCE_FILES drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp + drivers/nrf52/TwiMaster.cpp logging/NrfLogger.cpp components/rle/RleDecoder.cpp @@ -620,6 +621,7 @@ set(INCLUDE_FILES drivers/SpiNorFlash.h drivers/nrf52/SpiMaster.h drivers/nrf52/Spi.h + drivers/nrf52/TwiMaster.h drivers/spiFlash/SpiNorFlash.h drivers/Watchdog.h drivers/DebugPins.h diff --git a/src/drivers/Bma421.h b/src/drivers/Bma421.h index ac5c707ffc..0e5fd85dba 100644 --- a/src/drivers/Bma421.h +++ b/src/drivers/Bma421.h @@ -1,9 +1,10 @@ #pragma once +#include "drivers/TwiMaster.h" +#include "port/infinitime.h" #include namespace Pinetime { namespace Drivers { - class TwiMaster; class Bma421 { public: enum class DeviceTypes : uint8_t { Unknown, BMA421, BMA425 }; diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index 9d426c9db9..3061869139 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -1,6 +1,6 @@ #pragma once -#include "drivers/TwiMaster.h" +#include "port/infinitime.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/Hrs3300.h b/src/drivers/Hrs3300.h index 8bbdc69a40..d3dfec44ee 100644 --- a/src/drivers/Hrs3300.h +++ b/src/drivers/Hrs3300.h @@ -1,6 +1,7 @@ #pragma once #include "drivers/TwiMaster.h" +#include "port/infinitime.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 0df3e2c09c..bfd9e8a5b2 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -17,8 +17,7 @@ namespace Pinetime { requires IsSpi class Spi { public: - Spi(T& spi) : impl {spi} { - } + explicit Spi(T& spi) : impl {spi} { } Spi(const Spi&) = delete; Spi& operator=(const Spi&) = delete; Spi(Spi&&) = delete; diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index c916f3bf48..b28c456ebf 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -23,8 +23,7 @@ namespace Pinetime { requires IsSpiMaster class SpiMaster { public: - SpiMaster(T& spiMaster) : impl {spiMaster} { - } + explicit SpiMaster(T& spiMaster) : impl {spiMaster} { } SpiMaster(const SpiMaster&) = delete; SpiMaster& operator=(const SpiMaster&) = delete; SpiMaster(SpiMaster&&) = delete; diff --git a/src/drivers/TwiMaster.h b/src/drivers/TwiMaster.h index 30ac6c5f92..0035c9db93 100644 --- a/src/drivers/TwiMaster.h +++ b/src/drivers/TwiMaster.h @@ -1,41 +1,55 @@ #pragma once -#include -#include -#include // NRF_TWIM_Type +#include +#include #include namespace Pinetime { namespace Drivers { - class TwiMaster { - public: - enum class ErrorCodes { NoError, TransactionFailed }; - - TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, uint8_t pinScl); - - void Init(); - ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); - ErrorCodes Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); - - void Sleep(); - void Wakeup(); - - private: - ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); - ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); - void FixHwFreezed(); - void ConfigurePins() const; - - NRF_TWIM_Type* twiBaseAddress; - SemaphoreHandle_t mutex = nullptr; - NRF_TWIM_Type* module; - uint32_t frequency; - uint8_t pinSda; - uint8_t pinScl; - static constexpr uint8_t maxDataSize {16}; - static constexpr uint8_t registerSize {1}; - uint8_t internalBuffer[maxDataSize + registerSize]; - uint32_t txStartedCycleCount = 0; - static constexpr uint32_t HwFreezedDelay {161000}; - }; + template + concept IsTwi = requires(TwiImpl twi, uint8_t deviceAddress, uint8_t registerAddress, uint8_t* data, const uint8_t* constData, size_t size) { + { twi.Init() }; + { twi.Write(deviceAddress, registerAddress, constData, size) }; + { twi.Read(deviceAddress, registerAddress, data, size) }; + { twi.Sleep() }; + { twi.Wakeup() }; + }; + + namespace Interface { + template + requires IsTwi + class TwiMaster { + public: + explicit TwiMaster(T& impl) : impl {impl} {} + TwiMaster(const TwiMaster&) = delete; + TwiMaster& operator=(const TwiMaster&) = delete; + TwiMaster(TwiMaster&&) = delete; + TwiMaster& operator=(TwiMaster&&) = delete; + + enum class ErrorCodes { NoError, TransactionFailed }; + + void Init() { + impl.Init(); + } + + ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size) { + return static_cast(impl.Read(deviceAddress, registerAddress, buffer, size)); + } + + ErrorCodes Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size) { + return static_cast(impl.Write(deviceAddress, registerAddress, data, size)); + } + + void Sleep() { + impl.Sleep(); + } + + void Wakeup() { + impl.WakeUp(); + } + + private: + T& impl; + }; + } } } diff --git a/src/drivers/TwiMaster.cpp b/src/drivers/nrf52/TwiMaster.cpp similarity index 98% rename from src/drivers/TwiMaster.cpp rename to src/drivers/nrf52/TwiMaster.cpp index 25d23c28ce..179a01d321 100644 --- a/src/drivers/TwiMaster.cpp +++ b/src/drivers/nrf52/TwiMaster.cpp @@ -1,9 +1,9 @@ -#include "drivers/TwiMaster.h" +#include "drivers/nrf52/TwiMaster.h" #include #include #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::Nrf52; // TODO use shortcut to automatically send STOP when receive LastTX, for example // TODO use DMA/IRQ diff --git a/src/drivers/nrf52/TwiMaster.h b/src/drivers/nrf52/TwiMaster.h new file mode 100644 index 0000000000..64b4e63a19 --- /dev/null +++ b/src/drivers/nrf52/TwiMaster.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include +#include // NRF_TWIM_Type +#include +#include "drivers/TwiMaster.h" + +namespace Pinetime { + namespace Drivers { + namespace Nrf52 { + class TwiMaster { + public: + enum class ErrorCodes { NoError, TransactionFailed }; + + TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, uint8_t pinScl); + + void Init(); + ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); + ErrorCodes Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); + + void Sleep(); + void Wakeup(); + + private: + ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); + ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); + void FixHwFreezed(); + void ConfigurePins() const; + + NRF_TWIM_Type* twiBaseAddress; + SemaphoreHandle_t mutex = nullptr; + NRF_TWIM_Type* module; + uint32_t frequency; + uint8_t pinSda; + uint8_t pinScl; + static constexpr uint8_t maxDataSize {16}; + static constexpr uint8_t registerSize {1}; + uint8_t internalBuffer[maxDataSize + registerSize]; + uint32_t txStartedCycleCount = 0; + static constexpr uint32_t HwFreezedDelay {161000}; + }; + } + } +} diff --git a/src/main.cpp b/src/main.cpp index 12a3f5931e..17fd1bd76d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,7 +88,8 @@ Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; // respecting correct timings. According to erratas heet, this magic value makes it run // at ~390Khz with correct timings. static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000}; -Pinetime::Drivers::TwiMaster twiMaster {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, Pinetime::PinMap::TwiSda, Pinetime::PinMap::TwiScl}; +Pinetime::Drivers::Nrf52::TwiMaster twiMasterImpl {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, Pinetime::PinMap::TwiSda, Pinetime::PinMap::TwiScl}; +Pinetime::Drivers::TwiMaster twiMaster{twiMasterImpl}; Pinetime::Drivers::Cst816S touchPanel {twiMaster, touchPanelTwiAddress}; #ifdef PINETIME_IS_RECOVERY #include "displayapp/DummyLittleVgl.h" diff --git a/src/port/infinitime.h b/src/port/infinitime.h index 8cdef6bff6..7957039ba3 100644 --- a/src/port/infinitime.h +++ b/src/port/infinitime.h @@ -1,12 +1,14 @@ #pragma once #include "drivers/Spi.h" #include "drivers/SpiMaster.h" +#include "drivers/TwiMaster.h" #include #include #ifdef TARGET_DEVICE_PINETIME #include #include +#include #include #endif @@ -15,6 +17,7 @@ namespace Pinetime { #ifdef TARGET_DEVICE_PINETIME using SpiMaster = Interface::SpiMaster; using Spi = Interface::Spi; + using TwiMaster = Interface::TwiMaster; using SpiNorFlash = Interface::SpiNorFlash; #else #error "No target device specified!" diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index ef631af74e..b93d3da265 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -8,17 +8,11 @@ #include "displayapp/TouchEvents.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" -#include "drivers/InternalFlash.h" -#include "drivers/SpiMaster.h" -#include "drivers/SpiNorFlash.h" -#include "drivers/TwiMaster.h" #include "drivers/Hrs3300.h" #include "drivers/PinMap.h" #include "main.h" #include "BootErrors.h" -#include - using namespace Pinetime::System; namespace { diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 9eb7f78a79..6be19bc137 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -42,7 +42,6 @@ namespace Pinetime { namespace Drivers { class Cst816S; class St7789; - class TwiMaster; class Hrs3300; } namespace Controllers { From ddcf491e2e4ef85438bdbfd04ae36f9692215e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 28 Dec 2022 12:03:30 +0100 Subject: [PATCH 04/10] Fix recovery firmware/loader. --- src/CMakeLists.txt | 2 ++ src/recoveryLoader.cpp | 29 ++++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ddfc17545..77fce63de9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -506,6 +506,7 @@ list(APPEND RECOVERY_SOURCE_FILES drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp drivers/nrf52/TwiMaster.cpp + drivers/spiFlash/SpiNorFlash.cpp drivers/Watchdog.cpp drivers/DebugPins.cpp drivers/InternalFlash.cpp @@ -568,6 +569,7 @@ list(APPEND RECOVERYLOADER_SOURCE_FILES drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp drivers/nrf52/TwiMaster.cpp + drivers/spiFlash/SpiNorFlash.cpp logging/NrfLogger.cpp components/rle/RleDecoder.cpp diff --git a/src/recoveryLoader.cpp b/src/recoveryLoader.cpp index 27a79d9c73..04d4699d55 100644 --- a/src/recoveryLoader.cpp +++ b/src/recoveryLoader.cpp @@ -35,19 +35,26 @@ static constexpr uint8_t bytesPerPixel = 2; static constexpr uint16_t colorWhite = 0xFFFF; static constexpr uint16_t colorGreen = 0xE007; -Pinetime::Drivers::SpiMaster spi {Pinetime::Drivers::SpiMaster::SpiModule::SPI0, - {Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb, - Pinetime::Drivers::SpiMaster::Modes::Mode3, - Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz, - Pinetime::PinMap::SpiSck, - Pinetime::PinMap::SpiMosi, - Pinetime::PinMap::SpiMiso}}; -Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn}; -Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi}; - -Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn}; +Pinetime::Drivers::Nrf52::SpiMaster spiImpl {Pinetime::Drivers::Nrf52::SpiMaster::SpiModule::SPI0, + {Pinetime::Drivers::Nrf52::SpiMaster::BitOrder::Msb_Lsb, + Pinetime::Drivers::Nrf52::SpiMaster::Modes::Mode3, + Pinetime::Drivers::Nrf52::SpiMaster::Frequencies::Freq8Mhz, + Pinetime::PinMap::SpiSck, + Pinetime::PinMap::SpiMosi, + Pinetime::PinMap::SpiMiso}}; + +Pinetime::Drivers::SpiMaster spi {spiImpl}; + +Pinetime::Drivers::Nrf52::Spi lcdSpiIpmpl {spiImpl, Pinetime::PinMap::SpiLcdCsn}; +Pinetime::Drivers::Spi lcdSpi {lcdSpiIpmpl}; Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; +Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; +Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; + +Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpiImpl}; +Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; + Pinetime::Components::Gfx gfx {lcd}; Pinetime::Controllers::BrightnessController brightnessController; From 2094dbdab30ea08587e21a2bdc2c85f559bea017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 28 Dec 2022 12:22:39 +0100 Subject: [PATCH 05/10] Refactor Cst816S as a generic class that implements the concept IsTouchPanel. --- src/CMakeLists.txt | 6 +- src/displayapp/DisplayApp.cpp | 3 +- src/displayapp/DisplayApp.h | 5 +- src/displayapp/DisplayAppRecovery.cpp | 2 +- src/displayapp/DisplayAppRecovery.h | 5 +- src/displayapp/DummyLittleVgl.h | 4 +- src/displayapp/LittleVgl.cpp | 3 +- src/displayapp/LittleVgl.h | 6 +- src/displayapp/screens/SystemInfo.cpp | 2 +- src/displayapp/screens/SystemInfo.h | 4 +- src/drivers/Cst816s.h | 76 --------------------- src/drivers/TouchPanel.h | 83 +++++++++++++++++++++++ src/drivers/{ => touchpanels}/Cst816s.cpp | 10 +-- src/drivers/touchpanels/Cst816s.h | 60 ++++++++++++++++ src/main.cpp | 6 +- src/port/TouchPanel.h | 16 +++++ src/port/TwiMaster.h | 16 +++++ src/systemtask/SystemTask.cpp | 3 +- src/systemtask/SystemTask.h | 5 +- src/touchhandler/TouchHandler.cpp | 32 ++++----- src/touchhandler/TouchHandler.h | 12 ++-- 21 files changed, 226 insertions(+), 133 deletions(-) delete mode 100644 src/drivers/Cst816s.h create mode 100644 src/drivers/TouchPanel.h rename src/drivers/{ => touchpanels}/Cst816s.cpp (95%) create mode 100644 src/drivers/touchpanels/Cst816s.h create mode 100644 src/port/TouchPanel.h create mode 100644 src/port/TwiMaster.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 77fce63de9..f752070873 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -475,7 +475,7 @@ list(APPEND SOURCE_FILES components/timer/TimerController.cpp components/alarm/AlarmController.cpp components/fs/FS.cpp - drivers/Cst816s.cpp + drivers/touchpanels/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c FreeRTOS/port_cmsis.c @@ -540,7 +540,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/settings/Settings.cpp components/timer/TimerController.cpp components/alarm/AlarmController.cpp - drivers/Cst816s.cpp + drivers/touchpanels/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c FreeRTOS/port_cmsis.c @@ -659,7 +659,7 @@ set(INCLUDE_FILES components/settings/Settings.h components/timer/TimerController.h components/alarm/AlarmController.h - drivers/Cst816s.h + drivers/touchpanels/Cst816s.h FreeRTOS/portmacro.h FreeRTOS/portmacro_cmsis.h libs/date/include/date/tz.h diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 108e380d69..68ea3923ab 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,7 +30,6 @@ #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" -#include "drivers/Cst816s.h" #include "drivers/St7789.h" #include "drivers/Watchdog.h" #include "systemtask/SystemTask.h" @@ -62,7 +61,7 @@ namespace { DisplayApp::DisplayApp(Drivers::St7789& lcd, Components::LittleVgl& lvgl, - Drivers::Cst816S& touchPanel, + Pinetime::Drivers::TouchPanel& touchPanel, Controllers::Battery& batteryController, Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 4c54e22739..972b490c2d 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -24,7 +24,6 @@ namespace Pinetime { namespace Drivers { class St7789; - class Cst816S; class WatchdogView; } namespace Controllers { @@ -49,7 +48,7 @@ namespace Pinetime { DisplayApp(Drivers::St7789& lcd, Components::LittleVgl& lvgl, - Drivers::Cst816S&, + Pinetime::Drivers::TouchPanel&, Controllers::Battery& batteryController, Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, @@ -76,7 +75,7 @@ namespace Pinetime { private: Pinetime::Drivers::St7789& lcd; Pinetime::Components::LittleVgl& lvgl; - Pinetime::Drivers::Cst816S& touchPanel; + Pinetime::Drivers::TouchPanel& touchPanel; Pinetime::Controllers::Battery& batteryController; Pinetime::Controllers::Ble& bleController; Pinetime::Controllers::DateTime& dateTimeController; diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index e553aa8794..cf1f416f3d 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -12,7 +12,7 @@ using namespace Pinetime::Applications; DisplayApp::DisplayApp(Drivers::St7789& lcd, Components::LittleVgl& lvgl, - Drivers::Cst816S& touchPanel, + Drivers::TouchPanel& touchPanel, Controllers::Battery& batteryController, Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 7d4f0fd0c0..00f6d19a03 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -6,7 +6,6 @@ #include #include #include "components/gfx/Gfx.h" -#include "drivers/Cst816s.h" #include #include #include @@ -15,11 +14,11 @@ #include "displayapp/Apps.h" #include "displayapp/Messages.h" #include "displayapp/DummyLittleVgl.h" +#include "port/TouchPanel.h" namespace Pinetime { namespace Drivers { class St7789; - class Cst816S; class WatchdogView; } namespace Controllers { @@ -47,7 +46,7 @@ namespace Pinetime { public: DisplayApp(Drivers::St7789& lcd, Components::LittleVgl& lvgl, - Drivers::Cst816S&, + Drivers::TouchPanel&, Controllers::Battery& batteryController, Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, diff --git a/src/displayapp/DummyLittleVgl.h b/src/displayapp/DummyLittleVgl.h index 05355a9730..7ca2de83a1 100644 --- a/src/displayapp/DummyLittleVgl.h +++ b/src/displayapp/DummyLittleVgl.h @@ -4,14 +4,14 @@ #include #include #include -#include +#include "port/TouchPanel.h" namespace Pinetime { namespace Components { class LittleVgl { public: enum class FullRefreshDirections { None, Up, Down }; - LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel) { + LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::TouchPanel & touchPanel) { } LittleVgl(const LittleVgl&) = delete; diff --git a/src/displayapp/LittleVgl.cpp b/src/displayapp/LittleVgl.cpp index d5f31848c4..143defcf5e 100644 --- a/src/displayapp/LittleVgl.cpp +++ b/src/displayapp/LittleVgl.cpp @@ -4,7 +4,6 @@ #include #include //#include -#include "drivers/Cst816s.h" #include "drivers/St7789.h" using namespace Pinetime::Components; @@ -31,7 +30,7 @@ bool touchpad_read(lv_indev_drv_t* indev_drv, lv_indev_data_t* data) { return lvgl->GetTouchPadInfo(data); } -LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel) : lcd {lcd}, touchPanel {touchPanel} { +LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::TouchPanel& touchPanel) : lcd {lcd}, touchPanel {touchPanel} { } void LittleVgl::Init() { diff --git a/src/displayapp/LittleVgl.h b/src/displayapp/LittleVgl.h index 4582616533..09c709d3ff 100644 --- a/src/displayapp/LittleVgl.h +++ b/src/displayapp/LittleVgl.h @@ -1,10 +1,10 @@ #pragma once #include +#include "port/TouchPanel.h" namespace Pinetime { namespace Drivers { - class Cst816S; class St7789; } @@ -12,7 +12,7 @@ namespace Pinetime { class LittleVgl { public: enum class FullRefreshDirections { None, Up, Down, Left, Right, LeftAnim, RightAnim }; - LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel); + LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::TouchPanel& touchPanel); LittleVgl(const LittleVgl&) = delete; LittleVgl& operator=(const LittleVgl&) = delete; @@ -40,7 +40,7 @@ namespace Pinetime { void InitTheme(); Pinetime::Drivers::St7789& lcd; - Pinetime::Drivers::Cst816S& touchPanel; + Pinetime::Drivers::TouchPanel& touchPanel; lv_disp_buf_t disp_buf_2; lv_color_t buf2_1[LV_HOR_RES_MAX * 4]; diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 01c351955e..56d1de3e2e 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -37,7 +37,7 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Ble& bleController, Pinetime::Drivers::WatchdogView& watchdog, Pinetime::Controllers::MotionController& motionController, - Pinetime::Drivers::Cst816S& touchPanel) + Pinetime::Drivers::TouchPanel& touchPanel) : Screen(app), dateTimeController {dateTimeController}, batteryController {batteryController}, diff --git a/src/displayapp/screens/SystemInfo.h b/src/displayapp/screens/SystemInfo.h index a382ed8f50..9efaea3f29 100644 --- a/src/displayapp/screens/SystemInfo.h +++ b/src/displayapp/screens/SystemInfo.h @@ -29,7 +29,7 @@ namespace Pinetime { Pinetime::Controllers::Ble& bleController, Pinetime::Drivers::WatchdogView& watchdog, Pinetime::Controllers::MotionController& motionController, - Pinetime::Drivers::Cst816S& touchPanel); + Pinetime::Drivers::TouchPanel& touchPanel); ~SystemInfo() override; bool OnTouchEvent(TouchEvents event) override; @@ -40,7 +40,7 @@ namespace Pinetime { Pinetime::Controllers::Ble& bleController; Pinetime::Drivers::WatchdogView& watchdog; Pinetime::Controllers::MotionController& motionController; - Pinetime::Drivers::Cst816S& touchPanel; + Pinetime::Drivers::TouchPanel& touchPanel; ScreenList<5> screens; diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h deleted file mode 100644 index 3061869139..0000000000 --- a/src/drivers/Cst816s.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include "port/infinitime.h" - -namespace Pinetime { - namespace Drivers { - class Cst816S { - public: - enum class Gestures : uint8_t { - None = 0x00, - SlideDown = 0x01, - SlideUp = 0x02, - SlideLeft = 0x03, - SlideRight = 0x04, - SingleTap = 0x05, - DoubleTap = 0x0B, - LongPress = 0x0C - }; - struct TouchInfos { - uint16_t x = 0; - uint16_t y = 0; - Gestures gesture = Gestures::None; - bool touching = false; - bool isValid = false; - }; - - Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); - Cst816S(const Cst816S&) = delete; - Cst816S& operator=(const Cst816S&) = delete; - Cst816S(Cst816S&&) = delete; - Cst816S& operator=(Cst816S&&) = delete; - - bool Init(); - TouchInfos GetTouchInfo(); - void Sleep(); - void Wakeup(); - - uint8_t GetChipId() const { - return chipId; - } - uint8_t GetVendorId() const { - return vendorId; - } - uint8_t GetFwVersion() const { - return fwVersion; - } - - private: - bool CheckDeviceIds(); - - // Unused/Unavailable commented out - static constexpr uint8_t gestureIndex = 1; - static constexpr uint8_t touchPointNumIndex = 2; - // static constexpr uint8_t touchEventIndex = 3; - static constexpr uint8_t touchXHighIndex = 3; - static constexpr uint8_t touchXLowIndex = 4; - // static constexpr uint8_t touchIdIndex = 5; - static constexpr uint8_t touchYHighIndex = 5; - static constexpr uint8_t touchYLowIndex = 6; - // static constexpr uint8_t touchStep = 6; - // static constexpr uint8_t touchXYIndex = 7; - // static constexpr uint8_t touchMiscIndex = 8; - - static constexpr uint8_t maxX = 240; - static constexpr uint8_t maxY = 240; - - TwiMaster& twiMaster; - uint8_t twiAddress; - - uint8_t chipId; - uint8_t vendorId; - uint8_t fwVersion; - }; - - } -} diff --git a/src/drivers/TouchPanel.h b/src/drivers/TouchPanel.h new file mode 100644 index 0000000000..5a6b9ffcef --- /dev/null +++ b/src/drivers/TouchPanel.h @@ -0,0 +1,83 @@ +#pragma once +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + template + concept IsTouchPanel = requires(touchpanelImpl touchpanel) { + { touchpanel.Init() }; + { touchpanel.GetTouchInfo() }; + { touchpanel.Sleep() }; + { touchpanel.Wakeup() }; + { touchpanel.GetChipId() }; + { touchpanel.GetVendorId() }; + { touchpanel.GetFwVersion() }; + }; + + namespace TouchPanels { + enum class Gestures : uint8_t { + None = 0x00, + SlideDown = 0x01, + SlideUp = 0x02, + SlideLeft = 0x03, + SlideRight = 0x04, + SingleTap = 0x05, + DoubleTap = 0x0B, + LongPress = 0x0C + }; + struct TouchInfos { + uint16_t x = 0; + uint16_t y = 0; + Gestures gesture = Gestures::None; + bool touching = false; + bool isValid = false; + }; + } + + namespace Interface { + template + requires IsTouchPanel + class Touchpanel { + public: + explicit Touchpanel(T& impl) : impl {impl} {} + Touchpanel(const Touchpanel&) = delete; + Touchpanel& operator=(const Touchpanel&) = delete; + Touchpanel(Touchpanel&&) = delete; + Touchpanel& operator=(Touchpanel&&) = delete; + + bool Init() { + return impl.Init(); + } + + TouchPanels::TouchInfos GetTouchInfo() { + return impl.GetTouchInfo(); + } + + void Sleep() { + impl.Sleep(); + } + + void Wakeup() { + impl.Wakeup(); + } + + uint8_t GetChipId() const { + return impl.GetChipId(); + } + + uint8_t GetVendorId() const { + return impl.GetVendorId(); + } + + uint8_t GetFwVersion() const { + return impl.GetFwVersion(); + } + + private: + T& impl; + }; + } + } +} diff --git a/src/drivers/Cst816s.cpp b/src/drivers/touchpanels/Cst816s.cpp similarity index 95% rename from src/drivers/Cst816s.cpp rename to src/drivers/touchpanels/Cst816s.cpp index cf10c895f5..a55b5ae220 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/touchpanels/Cst816s.cpp @@ -1,11 +1,11 @@ -#include "drivers/Cst816s.h" +#include "Cst816s.h" #include #include #include #include #include "drivers/PinMap.h" -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::TouchPanels; /* References : * This implementation is based on this article : @@ -59,8 +59,8 @@ bool Cst816S::Init() { return true; } -Cst816S::TouchInfos Cst816S::GetTouchInfo() { - Cst816S::TouchInfos info; +TouchInfos Cst816S::GetTouchInfo() { + TouchInfos info; uint8_t touchData[7]; auto ret = twiMaster.Read(twiAddress, 0, touchData, sizeof(touchData)); @@ -77,7 +77,7 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { uint8_t yHigh = touchData[touchYHighIndex] & 0x0f; uint8_t yLow = touchData[touchYLowIndex]; uint16_t y = (yHigh << 8) | yLow; - Gestures gesture = static_cast(touchData[gestureIndex]); + auto gesture = static_cast(touchData[gestureIndex]); // Validity check if (x >= maxX || y >= maxY || diff --git a/src/drivers/touchpanels/Cst816s.h b/src/drivers/touchpanels/Cst816s.h new file mode 100644 index 0000000000..70d6ee16cf --- /dev/null +++ b/src/drivers/touchpanels/Cst816s.h @@ -0,0 +1,60 @@ +#pragma once +#include +#include "port/TwiMaster.h" +#include "drivers/TouchPanel.h" + +namespace Pinetime { + namespace Drivers { + namespace TouchPanels{ + class Cst816S { + public: + Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); + Cst816S(const Cst816S&) = delete; + Cst816S& operator=(const Cst816S&) = delete; + Cst816S(Cst816S&&) = delete; + Cst816S& operator=(Cst816S&&) = delete; + + bool Init(); + TouchPanels::TouchInfos GetTouchInfo(); + void Sleep(); + void Wakeup(); + + uint8_t GetChipId() const { + return chipId; + } + uint8_t GetVendorId() const { + return vendorId; + } + uint8_t GetFwVersion() const { + return fwVersion; + } + + private: + bool CheckDeviceIds(); + + // Unused/Unavailable commented out + static constexpr uint8_t gestureIndex = 1; + static constexpr uint8_t touchPointNumIndex = 2; + // static constexpr uint8_t touchEventIndex = 3; + static constexpr uint8_t touchXHighIndex = 3; + static constexpr uint8_t touchXLowIndex = 4; + // static constexpr uint8_t touchIdIndex = 5; + static constexpr uint8_t touchYHighIndex = 5; + static constexpr uint8_t touchYLowIndex = 6; + // static constexpr uint8_t touchStep = 6; + // static constexpr uint8_t touchXYIndex = 7; + // static constexpr uint8_t touchMiscIndex = 8; + + static constexpr uint8_t maxX = 240; + static constexpr uint8_t maxY = 240; + + TwiMaster& twiMaster; + uint8_t twiAddress; + + uint8_t chipId; + uint8_t vendorId; + uint8_t fwVersion; + }; + } + } +} diff --git a/src/main.cpp b/src/main.cpp index 17fd1bd76d..63baa71d99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,7 +43,7 @@ #include "drivers/SpiNorFlash.h" #include "drivers/St7789.h" #include "drivers/TwiMaster.h" -#include "drivers/Cst816s.h" +#include "drivers/touchpanels/Cst816s.h" #include "drivers/PinMap.h" #include "systemtask/SystemTask.h" #include "drivers/PinMap.h" @@ -59,6 +59,7 @@ Pinetime::Logging::DummyLogger logger; #endif #include "port/infinitime.h" +#include "port/TouchPanel.h" static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; @@ -90,7 +91,8 @@ Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000}; Pinetime::Drivers::Nrf52::TwiMaster twiMasterImpl {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, Pinetime::PinMap::TwiSda, Pinetime::PinMap::TwiScl}; Pinetime::Drivers::TwiMaster twiMaster{twiMasterImpl}; -Pinetime::Drivers::Cst816S touchPanel {twiMaster, touchPanelTwiAddress}; +Pinetime::Drivers::TouchPanels::Cst816S touchPanelImpl {twiMaster, touchPanelTwiAddress}; +Pinetime::Drivers::TouchPanel touchPanel {touchPanelImpl}; #ifdef PINETIME_IS_RECOVERY #include "displayapp/DummyLittleVgl.h" #include "displayapp/DisplayAppRecovery.h" diff --git a/src/port/TouchPanel.h b/src/port/TouchPanel.h new file mode 100644 index 0000000000..d1df252b98 --- /dev/null +++ b/src/port/TouchPanel.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/TouchPanel.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using TouchPanel = Interface::Touchpanel; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/port/TwiMaster.h b/src/port/TwiMaster.h new file mode 100644 index 0000000000..9134f03378 --- /dev/null +++ b/src/port/TwiMaster.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/TwiMaster.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using TwiMaster = Interface::TwiMaster; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index b93d3da265..7976510500 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -6,7 +6,6 @@ #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "displayapp/TouchEvents.h" -#include "drivers/Cst816s.h" #include "drivers/St7789.h" #include "drivers/Hrs3300.h" #include "drivers/PinMap.h" @@ -44,7 +43,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, Drivers::St7789& lcd, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::TwiMaster& twiMaster, - Drivers::Cst816S& touchPanel, + Pinetime::Drivers::TouchPanel& touchPanel, Components::LittleVgl& lvgl, Controllers::Battery& batteryController, Controllers::Ble& bleController, diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 6be19bc137..4b562786f0 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -40,7 +40,6 @@ extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { namespace Drivers { - class Cst816S; class St7789; class Hrs3300; } @@ -57,7 +56,7 @@ namespace Pinetime { Drivers::St7789& lcd, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::TwiMaster& twiMaster, - Drivers::Cst816S& touchPanel, + Pinetime::Drivers::TouchPanel& touchPanel, Components::LittleVgl& lvgl, Controllers::Battery& batteryController, Controllers::Ble& bleController, @@ -101,7 +100,7 @@ namespace Pinetime { Pinetime::Drivers::St7789& lcd; Pinetime::Drivers::SpiNorFlash& spiNorFlash; Pinetime::Drivers::TwiMaster& twiMaster; - Pinetime::Drivers::Cst816S& touchPanel; + Pinetime::Drivers::TouchPanel& touchPanel; Pinetime::Components::LittleVgl& lvgl; Pinetime::Controllers::Battery& batteryController; diff --git a/src/touchhandler/TouchHandler.cpp b/src/touchhandler/TouchHandler.cpp index 0e4fb5414a..1a49d6792f 100644 --- a/src/touchhandler/TouchHandler.cpp +++ b/src/touchhandler/TouchHandler.cpp @@ -9,30 +9,30 @@ using namespace Pinetime::Controllers; using namespace Pinetime::Applications; namespace { - TouchEvents ConvertGesture(Pinetime::Drivers::Cst816S::Gestures gesture) { + TouchEvents ConvertGesture(Pinetime::Drivers::TouchPanels::Gestures gesture) { switch (gesture) { - case Pinetime::Drivers::Cst816S::Gestures::SingleTap: + case Pinetime::Drivers::TouchPanels::Gestures::SingleTap: return TouchEvents::Tap; - case Pinetime::Drivers::Cst816S::Gestures::LongPress: + case Pinetime::Drivers::TouchPanels::Gestures::LongPress: return TouchEvents::LongTap; - case Pinetime::Drivers::Cst816S::Gestures::DoubleTap: + case Pinetime::Drivers::TouchPanels::Gestures::DoubleTap: return TouchEvents::DoubleTap; - case Pinetime::Drivers::Cst816S::Gestures::SlideRight: + case Pinetime::Drivers::TouchPanels::Gestures::SlideRight: return TouchEvents::SwipeRight; - case Pinetime::Drivers::Cst816S::Gestures::SlideLeft: + case Pinetime::Drivers::TouchPanels::Gestures::SlideLeft: return TouchEvents::SwipeLeft; - case Pinetime::Drivers::Cst816S::Gestures::SlideDown: + case Pinetime::Drivers::TouchPanels::Gestures::SlideDown: return TouchEvents::SwipeDown; - case Pinetime::Drivers::Cst816S::Gestures::SlideUp: + case Pinetime::Drivers::TouchPanels::Gestures::SlideUp: return TouchEvents::SwipeUp; - case Pinetime::Drivers::Cst816S::Gestures::None: + case Pinetime::Drivers::TouchPanels::Gestures::None: default: return TouchEvents::None; } } } -TouchHandler::TouchHandler(Drivers::Cst816S& touchPanel, Components::LittleVgl& lvgl) : touchPanel {touchPanel}, lvgl {lvgl} { +TouchHandler::TouchHandler(Pinetime::Drivers::TouchPanel& touchPanel, Components::LittleVgl& lvgl) : touchPanel {touchPanel}, lvgl {lvgl} { } void TouchHandler::CancelTap() { @@ -55,13 +55,13 @@ bool TouchHandler::GetNewTouchInfo() { return false; } - if (info.gesture != Pinetime::Drivers::Cst816S::Gestures::None) { + if (info.gesture != Pinetime::Drivers::TouchPanels::Gestures::None) { if (gestureReleased) { - if (info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideDown || - info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideLeft || - info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideUp || - info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideRight || - info.gesture == Pinetime::Drivers::Cst816S::Gestures::LongPress) { + if (info.gesture == Pinetime::Drivers::TouchPanels::Gestures::SlideDown || + info.gesture == Pinetime::Drivers::TouchPanels::Gestures::SlideLeft || + info.gesture == Pinetime::Drivers::TouchPanels::Gestures::SlideUp || + info.gesture == Pinetime::Drivers::TouchPanels::Gestures::SlideRight || + info.gesture == Pinetime::Drivers::TouchPanels::Gestures::LongPress) { if (info.touching) { gesture = ConvertGesture(info.gesture); gestureReleased = false; diff --git a/src/touchhandler/TouchHandler.h b/src/touchhandler/TouchHandler.h index 332041e5a4..aa47b190c5 100644 --- a/src/touchhandler/TouchHandler.h +++ b/src/touchhandler/TouchHandler.h @@ -1,18 +1,16 @@ #pragma once -#include "drivers/Cst816s.h" +#include "port/TouchPanel.h" #include "displayapp/TouchEvents.h" namespace Pinetime { namespace Components { class LittleVgl; } - namespace Drivers { - class Cst816S; - } + namespace Controllers { class TouchHandler { public: - explicit TouchHandler(Drivers::Cst816S&, Components::LittleVgl&); + explicit TouchHandler(Pinetime::Drivers::TouchPanel&, Components::LittleVgl&); void CancelTap(); bool GetNewTouchInfo(); void UpdateLvglTouchPoint(); @@ -29,8 +27,8 @@ namespace Pinetime { Pinetime::Applications::TouchEvents GestureGet(); private: - Pinetime::Drivers::Cst816S::TouchInfos info; - Pinetime::Drivers::Cst816S& touchPanel; + Pinetime::Drivers::TouchPanels::TouchInfos info; + Pinetime::Drivers::TouchPanel& touchPanel; Pinetime::Components::LittleVgl& lvgl; Pinetime::Applications::TouchEvents gesture; bool isCancelled = false; From 7d42c99e4df0dc3020d102801fdaee6f1f41d1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 28 Dec 2022 13:02:07 +0100 Subject: [PATCH 06/10] Split port/infinitime.h into multiple files. SpiNorFlash : use the generic SPI driver instead of the NRF52 one. --- src/CMakeLists.txt | 1 - src/components/ble/DfuService.h | 3 +-- src/components/fs/FS.h | 2 +- src/drivers/Bma421.h | 2 +- src/drivers/Hrs3300.h | 2 +- src/drivers/St7789.h | 2 +- src/drivers/spiFlash/SpiNorFlash.cpp | 2 +- src/drivers/spiFlash/SpiNorFlash.h | 7 ++++--- src/main.cpp | 3 +-- src/port/Spi.h | 16 ++++++++++++++++ src/port/SpiMaster.h | 16 ++++++++++++++++ src/port/SpiNorFlash.h | 16 ++++++++++++++++ src/port/infinitime.h | 26 -------------------------- src/recoveryLoader.cpp | 6 +++++- src/systemtask/SystemTask.h | 2 +- 15 files changed, 65 insertions(+), 41 deletions(-) create mode 100644 src/port/Spi.h create mode 100644 src/port/SpiMaster.h create mode 100644 src/port/SpiNorFlash.h delete mode 100644 src/port/infinitime.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f752070873..be0b7b0c9d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -588,7 +588,6 @@ set(INCLUDE_FILES BootloaderVersion.h logging/Logger.h logging/NrfLogger.h - port/infinitime.h displayapp/DisplayApp.h displayapp/Messages.h displayapp/TouchEvents.h diff --git a/src/components/ble/DfuService.h b/src/components/ble/DfuService.h index f30e213d26..d4aed37080 100644 --- a/src/components/ble/DfuService.h +++ b/src/components/ble/DfuService.h @@ -9,8 +9,7 @@ #undef max #undef min -#include "drivers/SpiNorFlash.h" -#include "port/infinitime.h" +#include "port/SpiNorFlash.h" namespace Pinetime { namespace System { diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 31e59986d1..9890f5050e 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -2,7 +2,7 @@ #include #include "drivers/SpiNorFlash.h" -#include "port/infinitime.h" +#include "port/SpiNorFlash.h" #include namespace Pinetime { diff --git a/src/drivers/Bma421.h b/src/drivers/Bma421.h index 0e5fd85dba..5f27da1563 100644 --- a/src/drivers/Bma421.h +++ b/src/drivers/Bma421.h @@ -1,6 +1,6 @@ #pragma once #include "drivers/TwiMaster.h" -#include "port/infinitime.h" +#include "port/TwiMaster.h" #include namespace Pinetime { diff --git a/src/drivers/Hrs3300.h b/src/drivers/Hrs3300.h index d3dfec44ee..7372a976ae 100644 --- a/src/drivers/Hrs3300.h +++ b/src/drivers/Hrs3300.h @@ -1,7 +1,7 @@ #pragma once #include "drivers/TwiMaster.h" -#include "port/infinitime.h" +#include "port/TwiMaster.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h index 8e972d838d..5cca48ae12 100644 --- a/src/drivers/St7789.h +++ b/src/drivers/St7789.h @@ -2,7 +2,7 @@ #include "drivers/Spi.h" #include #include -#include "port/infinitime.h" +#include "port/Spi.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/spiFlash/SpiNorFlash.cpp b/src/drivers/spiFlash/SpiNorFlash.cpp index 51944dbcbf..40015590ad 100644 --- a/src/drivers/spiFlash/SpiNorFlash.cpp +++ b/src/drivers/spiFlash/SpiNorFlash.cpp @@ -6,7 +6,7 @@ using namespace Pinetime::Drivers::SpiFlash; -SpiNorFlash::SpiNorFlash(Pinetime::Drivers::Nrf52::Spi& spi) : spi {spi} { +SpiNorFlash::SpiNorFlash(Pinetime::Drivers::Spi& spi) : spi {spi} { } void SpiNorFlash::Init() { diff --git a/src/drivers/spiFlash/SpiNorFlash.h b/src/drivers/spiFlash/SpiNorFlash.h index d7ff9e25a4..d730fb2e55 100644 --- a/src/drivers/spiFlash/SpiNorFlash.h +++ b/src/drivers/spiFlash/SpiNorFlash.h @@ -1,5 +1,6 @@ #pragma once -#include "drivers/nrf52/Spi.h" +#include "drivers/Spi.h" +#include "port/Spi.h" #include #include @@ -8,7 +9,7 @@ namespace Pinetime { namespace SpiFlash { class SpiNorFlash { public: - explicit SpiNorFlash(Pinetime::Drivers::Nrf52::Spi& spi); + explicit SpiNorFlash(Pinetime::Drivers::Spi& spi); SpiNorFlash(const SpiNorFlash&) = delete; SpiNorFlash& operator=(const SpiNorFlash&) = delete; SpiNorFlash(SpiNorFlash&&) = delete; @@ -54,7 +55,7 @@ namespace Pinetime { }; static constexpr uint16_t pageSize = 256; - Pinetime::Drivers::Nrf52::Spi& spi; + Pinetime::Drivers::Spi& spi; Identification device_id; }; } diff --git a/src/main.cpp b/src/main.cpp index 63baa71d99..d2b2866c71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,7 +58,6 @@ Pinetime::Logging::NrfLogger logger; Pinetime::Logging::DummyLogger logger; #endif -#include "port/infinitime.h" #include "port/TouchPanel.h" static constexpr uint8_t touchPanelTwiAddress = 0x15; @@ -82,7 +81,7 @@ Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; -Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpiImpl}; +Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpi}; Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; // The TWI device should work @ up to 400Khz but there is a HW bug which prevent it from diff --git a/src/port/Spi.h b/src/port/Spi.h new file mode 100644 index 0000000000..4e56849b0d --- /dev/null +++ b/src/port/Spi.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/Spi.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using Spi = Interface::Spi; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/port/SpiMaster.h b/src/port/SpiMaster.h new file mode 100644 index 0000000000..57e528b10a --- /dev/null +++ b/src/port/SpiMaster.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/SpiMaster.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using SpiMaster = Interface::SpiMaster; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/port/SpiNorFlash.h b/src/port/SpiNorFlash.h new file mode 100644 index 0000000000..6830ae6f52 --- /dev/null +++ b/src/port/SpiNorFlash.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/SpiNorFlash.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using SpiNorFlash = Interface::SpiNorFlash; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/port/infinitime.h b/src/port/infinitime.h deleted file mode 100644 index 7957039ba3..0000000000 --- a/src/port/infinitime.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "drivers/Spi.h" -#include "drivers/SpiMaster.h" -#include "drivers/TwiMaster.h" -#include -#include - -#ifdef TARGET_DEVICE_PINETIME -#include -#include -#include -#include -#endif - -namespace Pinetime { - namespace Drivers { -#ifdef TARGET_DEVICE_PINETIME - using SpiMaster = Interface::SpiMaster; - using Spi = Interface::Spi; - using TwiMaster = Interface::TwiMaster; - using SpiNorFlash = Interface::SpiNorFlash; -#else - #error "No target device specified!" -#endif - } -} diff --git a/src/recoveryLoader.cpp b/src/recoveryLoader.cpp index 04d4699d55..792442d0d8 100644 --- a/src/recoveryLoader.cpp +++ b/src/recoveryLoader.cpp @@ -28,6 +28,10 @@ Pinetime::Logging::NrfLogger logger; Pinetime::Logging::DummyLogger logger; #endif +#include "port/SpiMaster.h" +#include "port/SpiNorFlash.h" +#include "port/Spi.h" + static constexpr uint8_t displayWidth = 240; static constexpr uint8_t displayHeight = 240; static constexpr uint8_t bytesPerPixel = 2; @@ -52,7 +56,7 @@ Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; -Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpiImpl}; +Pinetime::Drivers::SpiFlash::SpiNorFlash spiNorFlashImpl{flashSpi}; Pinetime::Drivers::SpiNorFlash spiNorFlash {spiNorFlashImpl}; Pinetime::Components::Gfx gfx {lcd}; diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 4b562786f0..313435d131 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -35,7 +35,7 @@ #include "drivers/Watchdog.h" #include "systemtask/Messages.h" -#include "port/infinitime.h" +#include "port/SpiMaster.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { From 7d2ca5c63f01257fbd1b9d4e8fab79c54cea7112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 28 Dec 2022 15:29:32 +0100 Subject: [PATCH 07/10] Refactor BMA421 as a generic class that implements the concept IsMotionSensor. --- src/components/motion/MotionController.cpp | 6 +- src/components/motion/MotionController.h | 5 +- src/drivers/Bma421.cpp | 12 ++-- src/drivers/Bma421.h | 69 ++++++++++--------- src/drivers/MotionSensor.h | 78 ++++++++++++++++++++++ src/main.cpp | 4 +- src/port/MotionSensor.h | 16 +++++ src/systemtask/SystemTask.cpp | 2 +- src/systemtask/SystemTask.h | 5 +- 9 files changed, 149 insertions(+), 48 deletions(-) create mode 100644 src/drivers/MotionSensor.h create mode 100644 src/port/MotionSensor.h diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index 7dd321271c..19f14f108d 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -69,12 +69,12 @@ int32_t MotionController::currentShakeSpeed() { void MotionController::IsSensorOk(bool isOk) { isSensorOk = isOk; } -void MotionController::Init(Pinetime::Drivers::Bma421::DeviceTypes types) { +void MotionController::Init(Pinetime::Drivers::MotionSensors::DeviceTypes types) { switch (types) { - case Drivers::Bma421::DeviceTypes::BMA421: + case Drivers::MotionSensors::DeviceTypes::BMA421: this->deviceType = DeviceTypes::BMA421; break; - case Drivers::Bma421::DeviceTypes::BMA425: + case Drivers::MotionSensors::DeviceTypes::BMA425: this->deviceType = DeviceTypes::BMA425; break; default: diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index f80b11b994..717946c509 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -1,7 +1,8 @@ #pragma once #include -#include +#include +#include #include namespace Pinetime { @@ -48,7 +49,7 @@ namespace Pinetime { return deviceType; } - void Init(Pinetime::Drivers::Bma421::DeviceTypes types); + void Init(Pinetime::Drivers::MotionSensors::DeviceTypes types); void SetService(Pinetime::Controllers::MotionService* service); private: diff --git a/src/drivers/Bma421.cpp b/src/drivers/Bma421.cpp index 539cc8d1d3..ee3a88ca59 100644 --- a/src/drivers/Bma421.cpp +++ b/src/drivers/Bma421.cpp @@ -4,7 +4,7 @@ #include "drivers/TwiMaster.h" #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::MotionSensors; namespace { int8_t user_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t length, void* intf_ptr) { @@ -44,13 +44,13 @@ void Bma421::Init() { switch (bma.chip_id) { case BMA423_CHIP_ID: - deviceType = DeviceTypes::BMA421; + deviceType = MotionSensors::DeviceTypes::BMA421; break; case BMA425_CHIP_ID: - deviceType = DeviceTypes::BMA425; + deviceType = MotionSensors::DeviceTypes::BMA425; break; default: - deviceType = DeviceTypes::Unknown; + deviceType = MotionSensors::DeviceTypes::Unknown; break; } @@ -99,7 +99,7 @@ void Bma421::Write(uint8_t registerAddress, const uint8_t* data, size_t size) { twiMaster.Write(deviceAddress, registerAddress, data, size); } -Bma421::Values Bma421::Process() { +Pinetime::Drivers::MotionSensors::Values Bma421::Process() { if (not isOk) return {}; struct bma4_accel data; @@ -133,6 +133,6 @@ void Bma421::SoftReset() { nrf_delay_ms(1); } } -Bma421::DeviceTypes Bma421::DeviceType() const { +Pinetime::Drivers::MotionSensors::DeviceTypes Bma421::DeviceType() const { return deviceType; } diff --git a/src/drivers/Bma421.h b/src/drivers/Bma421.h index 5f27da1563..7660c3a2d3 100644 --- a/src/drivers/Bma421.h +++ b/src/drivers/Bma421.h @@ -1,47 +1,50 @@ #pragma once #include "drivers/TwiMaster.h" #include "port/TwiMaster.h" +#include "drivers/MotionSensor.h" #include namespace Pinetime { namespace Drivers { - class Bma421 { - public: - enum class DeviceTypes : uint8_t { Unknown, BMA421, BMA425 }; - struct Values { - uint32_t steps; - int16_t x; - int16_t y; - int16_t z; - }; - Bma421(TwiMaster& twiMaster, uint8_t twiAddress); - Bma421(const Bma421&) = delete; - Bma421& operator=(const Bma421&) = delete; - Bma421(Bma421&&) = delete; - Bma421& operator=(Bma421&&) = delete; + namespace MotionSensors { + class Bma421 { + public: + enum class DeviceTypes : uint8_t { Unknown, BMA421, BMA425 }; + struct Values { + uint32_t steps; + int16_t x; + int16_t y; + int16_t z; + }; + Bma421(TwiMaster& twiMaster, uint8_t twiAddress); + Bma421(const Bma421&) = delete; + Bma421& operator=(const Bma421&) = delete; + Bma421(Bma421&&) = delete; + Bma421& operator=(Bma421&&) = delete; - /// The chip freezes the TWI bus after the softreset operation. Softreset is separated from the - /// Init() method to allow the caller to uninit and then reinit the TWI device after the softreset. - void SoftReset(); - void Init(); - Values Process(); - void ResetStepCounter(); + /// The chip freezes the TWI bus after the softreset operation. Softreset is separated from the + /// Init() method to allow the caller to uninit and then reinit the TWI device after the softreset. + void SoftReset(); + void Init(); + MotionSensors::Values Process(); + void ResetStepCounter(); - void Read(uint8_t registerAddress, uint8_t* buffer, size_t size); - void Write(uint8_t registerAddress, const uint8_t* data, size_t size); + void Read(uint8_t registerAddress, uint8_t* buffer, size_t size); + void Write(uint8_t registerAddress, const uint8_t* data, size_t size); - bool IsOk() const; - DeviceTypes DeviceType() const; + bool IsOk() const; + MotionSensors::DeviceTypes DeviceType() const; - private: - void Reset(); + private: + void Reset(); - TwiMaster& twiMaster; - uint8_t deviceAddress = 0x18; - struct bma4_dev bma; - bool isOk = false; - bool isResetOk = false; - DeviceTypes deviceType = DeviceTypes::Unknown; - }; + TwiMaster& twiMaster; + uint8_t deviceAddress = 0x18; + struct bma4_dev bma; + bool isOk = false; + bool isResetOk = false; + MotionSensors::DeviceTypes deviceType = MotionSensors::DeviceTypes::Unknown; + }; + } } } \ No newline at end of file diff --git a/src/drivers/MotionSensor.h b/src/drivers/MotionSensor.h new file mode 100644 index 0000000000..30f77d9aac --- /dev/null +++ b/src/drivers/MotionSensor.h @@ -0,0 +1,78 @@ +#pragma once +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + namespace MotionSensors { + enum class DeviceTypes : uint8_t { Unknown, BMA421, BMA425 }; + struct Values { + uint32_t steps; + int16_t x; + int16_t y; + int16_t z; + }; + } + + template + concept IsMotionSensor = requires(motionSensorImpl sensor, uint8_t registerAddress, uint8_t* data, uint8_t* constData, size_t size) { + { sensor.SoftReset() }; + { sensor.Init() }; + { sensor.Process() }; + { sensor.ResetStepCounter() }; + { sensor.IsOk() }; + { sensor.DeviceType() }; + { sensor.Read(registerAddress, data, size) }; + { sensor.Write(registerAddress, constData, size) }; + }; + + namespace Interface { + template + requires IsMotionSensor + class MotionSensor { + public: + explicit MotionSensor(T& impl) : impl {impl} {} + MotionSensor(const MotionSensor&) = delete; + MotionSensor& operator=(const MotionSensor&) = delete; + MotionSensor(MotionSensor&&) = delete; + MotionSensor& operator=(MotionSensor&&) = delete; + + void SoftReset() { + return impl.SoftReset(); + } + + void Init() { + impl.Init(); + } + + MotionSensors::Values Process() { + return impl.Process(); + } + + void ResetStepCounter() { + return impl.ResetStepCounter(); + } + + void Read(uint8_t registerAddress, uint8_t* buffer, size_t size) { + impl.Read(registerAddress, buffer, size); + } + + void Write(uint8_t registerAddress, const uint8_t* data, size_t size) { + impl.Write(registerAddress, data, size); + } + + bool IsOk() const { + return impl.IsOk(); + } + + MotionSensors::DeviceTypes DeviceType() const { + return impl.DeviceType(); + } + + private: + T& impl; + }; + } + } +} diff --git a/src/main.cpp b/src/main.cpp index d2b2866c71..f02756fb2b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,7 @@ Pinetime::Logging::DummyLogger logger; #endif #include "port/TouchPanel.h" +#include "port/MotionSensor.h" static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; @@ -101,7 +102,8 @@ Pinetime::Drivers::TouchPanel touchPanel {touchPanelImpl}; #endif Pinetime::Components::LittleVgl lvgl {lcd, touchPanel}; -Pinetime::Drivers::Bma421 motionSensor {twiMaster, motionSensorTwiAddress}; +Pinetime::Drivers::MotionSensors::Bma421 motionSensorImpl {twiMaster, motionSensorTwiAddress}; +Pinetime::Drivers::MotionSensor motionSensor {motionSensorImpl}; Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress}; TimerHandle_t debounceTimer; diff --git a/src/port/MotionSensor.h b/src/port/MotionSensor.h new file mode 100644 index 0000000000..5a92727436 --- /dev/null +++ b/src/port/MotionSensor.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/MotionSensor.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using MotionSensor = Interface::MotionSensor; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 7976510500..966a86cc39 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -55,7 +55,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, Pinetime::Controllers::MotorController& motorController, Pinetime::Drivers::Hrs3300& heartRateSensor, Pinetime::Controllers::MotionController& motionController, - Pinetime::Drivers::Bma421& motionSensor, + Pinetime::Drivers::MotionSensor& motionSensor, Controllers::Settings& settingsController, Pinetime::Controllers::HeartRateController& heartRateController, Pinetime::Applications::DisplayApp& displayApp, diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 313435d131..543e125327 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -36,6 +36,7 @@ #include "drivers/Watchdog.h" #include "systemtask/Messages.h" #include "port/SpiMaster.h" +#include "port/MotionSensor.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { @@ -68,7 +69,7 @@ namespace Pinetime { Pinetime::Controllers::MotorController& motorController, Pinetime::Drivers::Hrs3300& heartRateSensor, Pinetime::Controllers::MotionController& motionController, - Pinetime::Drivers::Bma421& motionSensor, + Pinetime::Drivers::MotionSensor& motionSensor, Controllers::Settings& settingsController, Pinetime::Controllers::HeartRateController& heartRateController, Pinetime::Applications::DisplayApp& displayApp, @@ -113,7 +114,7 @@ namespace Pinetime { Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::MotorController& motorController; Pinetime::Drivers::Hrs3300& heartRateSensor; - Pinetime::Drivers::Bma421& motionSensor; + Pinetime::Drivers::MotionSensor& motionSensor; Pinetime::Controllers::Settings& settingsController; Pinetime::Controllers::HeartRateController& heartRateController; Pinetime::Controllers::MotionController& motionController; From 8b2c875f02dd50719d3be4eda68deb3d070a9c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 28 Dec 2022 17:31:01 +0100 Subject: [PATCH 08/10] Refactor HRS3300 and Watchdog as a generic class. --- src/CMakeLists.txt | 16 ++-- src/displayapp/screens/SystemInfo.cpp | 20 ++-- src/drivers/HeartRateSensor.h | 63 +++++++++++++ src/drivers/Hrs3300.h | 47 ---------- src/drivers/Watchdog.cpp | 77 --------------- src/drivers/Watchdog.h | 93 +++++++++++++------ src/drivers/WatchdogView.h | 20 ++++ .../{ => heartRateSensors}/Hrs3300.cpp | 4 +- src/drivers/heartRateSensors/Hrs3300.h | 49 ++++++++++ src/drivers/{ => motionSensors}/Bma421.cpp | 2 +- src/drivers/{ => motionSensors}/Bma421.h | 0 src/drivers/nrf52/Watchdog.cpp | 52 +++++++++++ src/drivers/nrf52/Watchdog.h | 24 +++++ src/heartratetask/HeartRateTask.cpp | 4 +- src/heartratetask/HeartRateTask.h | 8 +- src/main.cpp | 18 ++-- src/port/HeartRateSensor.h | 16 ++++ src/port/MotionSensor.h | 2 +- src/port/Watchdog.h | 16 ++++ src/systemtask/SystemTask.cpp | 4 +- src/systemtask/SystemTask.h | 9 +- 21 files changed, 353 insertions(+), 191 deletions(-) create mode 100644 src/drivers/HeartRateSensor.h delete mode 100644 src/drivers/Hrs3300.h delete mode 100644 src/drivers/Watchdog.cpp create mode 100644 src/drivers/WatchdogView.h rename src/drivers/{ => heartRateSensors}/Hrs3300.cpp (97%) create mode 100644 src/drivers/heartRateSensors/Hrs3300.h rename src/drivers/{ => motionSensors}/Bma421.cpp (99%) rename src/drivers/{ => motionSensors}/Bma421.h (100%) create mode 100644 src/drivers/nrf52/Watchdog.cpp create mode 100644 src/drivers/nrf52/Watchdog.h create mode 100644 src/port/HeartRateSensor.h create mode 100644 src/port/Watchdog.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be0b7b0c9d..3942e4631f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -440,11 +440,11 @@ list(APPEND SOURCE_FILES drivers/nrf52/Spi.cpp drivers/nrf52/TwiMaster.cpp drivers/spiFlash/SpiNorFlash.cpp - drivers/Watchdog.cpp + drivers/nrf52/Watchdog.cpp drivers/DebugPins.cpp drivers/InternalFlash.cpp - drivers/Hrs3300.cpp - drivers/Bma421.cpp + drivers/heartRateSensors/Hrs3300.cpp + drivers/motionSensors/Bma421.cpp drivers/Bma421_C/bma4.c drivers/Bma421_C/bma423.c components/battery/BatteryController.cpp @@ -507,11 +507,11 @@ list(APPEND RECOVERY_SOURCE_FILES drivers/nrf52/Spi.cpp drivers/nrf52/TwiMaster.cpp drivers/spiFlash/SpiNorFlash.cpp - drivers/Watchdog.cpp + drivers/nrf52/Watchdog.cpp drivers/DebugPins.cpp drivers/InternalFlash.cpp - drivers/Hrs3300.cpp - drivers/Bma421.cpp + drivers/heartRateSensors/Hrs3300.cpp + drivers/motionSensors/Bma421.cpp drivers/Bma421_C/bma4.c drivers/Bma421_C/bma423.c components/battery/BatteryController.cpp @@ -627,9 +627,9 @@ set(INCLUDE_FILES drivers/Watchdog.h drivers/DebugPins.h drivers/InternalFlash.h - drivers/Hrs3300.h + drivers/heartRateSensors/Hrs3300.h drivers/PinMap.h - drivers/Bma421.h + drivers/motionSensors/Bma421.h drivers/Bma421_C/bma4.c drivers/Bma421_C/bma423.c components/battery/BatteryController.h diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 56d1de3e2e..aa6643983d 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -11,7 +11,7 @@ #include "components/brightness/BrightnessController.h" #include "components/datetime/DateTimeController.h" #include "components/motion/MotionController.h" -#include "drivers/Watchdog.h" +#include "drivers/WatchdogView.h" #include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -101,23 +101,23 @@ std::unique_ptr SystemInfo::CreateScreen2() { auto batteryPercent = batteryController.PercentRemaining(); auto resetReason = [this]() { switch (watchdog.ResetReason()) { - case Drivers::Watchdog::ResetReasons::Watchdog: + case Drivers::Watchdogs::ResetReasons::Watchdog: return "wtdg"; - case Drivers::Watchdog::ResetReasons::HardReset: + case Drivers::Watchdogs::ResetReasons::HardReset: return "hardr"; - case Drivers::Watchdog::ResetReasons::NFC: + case Drivers::Watchdogs::ResetReasons::NFC: return "nfc"; - case Drivers::Watchdog::ResetReasons::SoftReset: + case Drivers::Watchdogs::ResetReasons::SoftReset: return "softr"; - case Drivers::Watchdog::ResetReasons::CpuLockup: + case Drivers::Watchdogs::ResetReasons::CpuLockup: return "cpulock"; - case Drivers::Watchdog::ResetReasons::SystemOff: + case Drivers::Watchdogs::ResetReasons::SystemOff: return "off"; - case Drivers::Watchdog::ResetReasons::LpComp: + case Drivers::Watchdogs::ResetReasons::LpComp: return "lpcomp"; - case Drivers::Watchdog::ResetReasons::DebugInterface: + case Drivers::Watchdogs::ResetReasons::DebugInterface: return "dbg"; - case Drivers::Watchdog::ResetReasons::ResetPin: + case Drivers::Watchdogs::ResetReasons::ResetPin: return "rst"; default: return "?"; diff --git a/src/drivers/HeartRateSensor.h b/src/drivers/HeartRateSensor.h new file mode 100644 index 0000000000..b49cf1336f --- /dev/null +++ b/src/drivers/HeartRateSensor.h @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + template + concept IsHeartRateSensor = requires(HeartRateSensorImpl sensor, uint8_t gain, uint8_t drive) { + { sensor.Init() }; + { sensor.Enable() }; + { sensor.Disable() }; + { sensor.ReadHrs() } -> std::same_as; + { sensor.ReadAls() } -> std::same_as; + { sensor.SetGain(gain) }; + { sensor.SetDrive(drive) }; + }; + + namespace Interface { + template + requires IsHeartRateSensor + class HeartRateSensor { + public: + explicit HeartRateSensor(T& impl) : impl {impl} {} + HeartRateSensor(const HeartRateSensor&) = delete; + HeartRateSensor& operator=(const HeartRateSensor&) = delete; + HeartRateSensor(HeartRateSensor&&) = delete; + HeartRateSensor& operator=(HeartRateSensor&&) = delete; + + void Init() { + impl.Init(); + } + + void Enable() { + impl.Enable(); + } + + void Disable() { + impl.Disable(); + } + + uint32_t ReadHrs() { + return impl.ReadHrs(); + } + + uint32_t ReadAls() { + return impl.ReadAls(); + } + + void SetGain(uint8_t gain) { + impl.SetGain(gain); + } + + void SetDrive(uint8_t drive) { + impl.SetDrive(drive); + } + + private: + T& impl; + }; + } + } +} diff --git a/src/drivers/Hrs3300.h b/src/drivers/Hrs3300.h deleted file mode 100644 index 7372a976ae..0000000000 --- a/src/drivers/Hrs3300.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "drivers/TwiMaster.h" -#include "port/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(); - uint32_t ReadHrs(); - uint32_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); - }; - } -} diff --git a/src/drivers/Watchdog.cpp b/src/drivers/Watchdog.cpp deleted file mode 100644 index d0907a6502..0000000000 --- a/src/drivers/Watchdog.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "drivers/Watchdog.h" -#include -using namespace Pinetime::Drivers; - -void Watchdog::Setup(uint8_t timeoutSeconds) { - NRF_WDT->CONFIG &= ~(WDT_CONFIG_SLEEP_Msk << WDT_CONFIG_SLEEP_Pos); - NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Run << WDT_CONFIG_SLEEP_Pos); - - NRF_WDT->CONFIG &= ~(WDT_CONFIG_HALT_Msk << WDT_CONFIG_HALT_Pos); - NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos); - - /* timeout (s) = (CRV + 1) / 32768 */ - // JF : 7500 = 7.5s - uint32_t crv = (((timeoutSeconds * 1000u) << 15u) / 1000) - 1; - NRF_WDT->CRV = crv; - - /* Enable reload requests */ - NRF_WDT->RREN = (WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos); - - resetReason = ActualResetReason(); -} - -void Watchdog::Start() { - NRF_WDT->TASKS_START = 1; -} - -void Watchdog::Kick() { - NRF_WDT->RR[0] = WDT_RR_RR_Reload; -} - -Watchdog::ResetReasons Watchdog::ActualResetReason() const { - uint32_t reason = NRF_POWER->RESETREAS; - NRF_POWER->RESETREAS = 0xffffffff; - - if (reason & 0x01u) - return ResetReasons::ResetPin; - if ((reason >> 1u) & 0x01u) - return ResetReasons::Watchdog; - if ((reason >> 2u) & 0x01u) - return ResetReasons::SoftReset; - if ((reason >> 3u) & 0x01u) - return ResetReasons::CpuLockup; - if ((reason >> 16u) & 0x01u) - return ResetReasons::SystemOff; - if ((reason >> 17u) & 0x01u) - return ResetReasons::LpComp; - if ((reason) &0x01u) - return ResetReasons::DebugInterface; - if ((reason >> 19u) & 0x01u) - return ResetReasons::NFC; - return ResetReasons::HardReset; -} - -const char* Watchdog::ResetReasonToString(Watchdog::ResetReasons reason) { - switch (reason) { - case ResetReasons::ResetPin: - return "Reset pin"; - case ResetReasons::Watchdog: - return "Watchdog"; - case ResetReasons::DebugInterface: - return "Debug interface"; - case ResetReasons::LpComp: - return "LPCOMP"; - case ResetReasons::SystemOff: - return "System OFF"; - case ResetReasons::CpuLockup: - return "CPU Lock-up"; - case ResetReasons::SoftReset: - return "Soft reset"; - case ResetReasons::NFC: - return "NFC"; - case ResetReasons::HardReset: - return "Hard reset"; - default: - return "Unknown"; - } -} diff --git a/src/drivers/Watchdog.h b/src/drivers/Watchdog.h index 03807d61b2..56a4f3d8b6 100644 --- a/src/drivers/Watchdog.h +++ b/src/drivers/Watchdog.h @@ -1,34 +1,75 @@ #pragma once +#include #include namespace Pinetime { namespace Drivers { - class Watchdog { - public: + namespace Watchdogs { enum class ResetReasons { ResetPin, Watchdog, SoftReset, CpuLockup, SystemOff, LpComp, DebugInterface, NFC, HardReset }; - void Setup(uint8_t timeoutSeconds); - void Start(); - void Kick(); - ResetReasons ResetReason() const { - return resetReason; - } - static const char* ResetReasonToString(ResetReasons reason); - - private: - ResetReasons resetReason; - ResetReasons ActualResetReason() const; - }; - - class WatchdogView { - public: - WatchdogView(const Watchdog& watchdog) : watchdog {watchdog} { - } - Watchdog::ResetReasons ResetReason() const { - return watchdog.ResetReason(); - } - - private: - const Watchdog& watchdog; - }; + } + + template + concept IsWatchdog = requires(WatchdogImpl watchdog) { + { watchdog.Start() }; + { watchdog.Kick() }; + { watchdog.ResetReason() } -> std::same_as; + }; + + namespace Interface { + template + requires IsWatchdog + class Watchdog { + public: + explicit Watchdog(T& impl) : impl {impl} {} + Watchdog(const Watchdog&) = delete; + Watchdog& operator=(const Watchdog&) = delete; + Watchdog(Watchdog&&) = delete; + Watchdog& operator=(Watchdog&&) = delete; + + void Setup(uint8_t timeoutSeconds) { + impl.Setup(timeoutSeconds); + } + + void Start() { + impl.Start(); + } + + void Kick() { + impl.Kick(); + } + + Watchdogs::ResetReasons ResetReason() const { + return impl.ResetReason(); + } + + static const char* ResetReasonToString(Watchdogs::ResetReasons reason) { + switch (reason) { + case Watchdogs::ResetReasons::ResetPin: + return "Reset pin"; + case Watchdogs::ResetReasons::Watchdog: + return "Watchdog"; + case Watchdogs::ResetReasons::DebugInterface: + return "Debug interface"; + case Watchdogs::ResetReasons::LpComp: + return "LPCOMP"; + case Watchdogs::ResetReasons::SystemOff: + return "System OFF"; + case Watchdogs::ResetReasons::CpuLockup: + return "CPU Lock-up"; + case Watchdogs::ResetReasons::SoftReset: + return "Soft reset"; + case Watchdogs::ResetReasons::NFC: + return "NFC"; + case Watchdogs::ResetReasons::HardReset: + return "Hard reset"; + default: + return "Unknown"; + } + } + + private: + T& impl; + }; + } } } diff --git a/src/drivers/WatchdogView.h b/src/drivers/WatchdogView.h new file mode 100644 index 0000000000..ed42aadb3f --- /dev/null +++ b/src/drivers/WatchdogView.h @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace Pinetime { + namespace Drivers { + class WatchdogView { + public: + explicit WatchdogView(const Watchdog& watchdog) : watchdog {watchdog} { + } + + Watchdogs::ResetReasons ResetReason() const { + return watchdog.ResetReason(); + } + + private: + const Watchdog& watchdog; + }; + } +} + diff --git a/src/drivers/Hrs3300.cpp b/src/drivers/heartRateSensors/Hrs3300.cpp similarity index 97% rename from src/drivers/Hrs3300.cpp rename to src/drivers/heartRateSensors/Hrs3300.cpp index ec620af2ce..e329bb4792 100644 --- a/src/drivers/Hrs3300.cpp +++ b/src/drivers/heartRateSensors/Hrs3300.cpp @@ -4,7 +4,7 @@ C++ port Copyright (C) 2021 Jean-François Milants */ -#include "drivers/Hrs3300.h" +#include "Hrs3300.h" #include #include @@ -12,7 +12,7 @@ #include #include -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::HeartRateSensors; /** 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 */ diff --git a/src/drivers/heartRateSensors/Hrs3300.h b/src/drivers/heartRateSensors/Hrs3300.h new file mode 100644 index 0000000000..43ec44f748 --- /dev/null +++ b/src/drivers/heartRateSensors/Hrs3300.h @@ -0,0 +1,49 @@ +#pragma once + +#include "drivers/TwiMaster.h" +#include "port/TwiMaster.h" + +namespace Pinetime { + namespace Drivers { + namespace HeartRateSensors { + 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(); + uint32_t ReadHrs(); + uint32_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); + }; + } + } +} diff --git a/src/drivers/Bma421.cpp b/src/drivers/motionSensors/Bma421.cpp similarity index 99% rename from src/drivers/Bma421.cpp rename to src/drivers/motionSensors/Bma421.cpp index ee3a88ca59..8335bca18d 100644 --- a/src/drivers/Bma421.cpp +++ b/src/drivers/motionSensors/Bma421.cpp @@ -1,4 +1,4 @@ -#include "drivers/Bma421.h" +#include "Bma421.h" #include #include #include "drivers/TwiMaster.h" diff --git a/src/drivers/Bma421.h b/src/drivers/motionSensors/Bma421.h similarity index 100% rename from src/drivers/Bma421.h rename to src/drivers/motionSensors/Bma421.h diff --git a/src/drivers/nrf52/Watchdog.cpp b/src/drivers/nrf52/Watchdog.cpp new file mode 100644 index 0000000000..50845158b4 --- /dev/null +++ b/src/drivers/nrf52/Watchdog.cpp @@ -0,0 +1,52 @@ +#include "Watchdog.h" +#include +using namespace Pinetime::Drivers::Nrf52; + +void Watchdog::Setup(uint8_t timeoutSeconds) { + NRF_WDT->CONFIG &= ~(WDT_CONFIG_SLEEP_Msk << WDT_CONFIG_SLEEP_Pos); + NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Run << WDT_CONFIG_SLEEP_Pos); + + NRF_WDT->CONFIG &= ~(WDT_CONFIG_HALT_Msk << WDT_CONFIG_HALT_Pos); + NRF_WDT->CONFIG |= (WDT_CONFIG_HALT_Pause << WDT_CONFIG_HALT_Pos); + + /* timeout (s) = (CRV + 1) / 32768 */ + // JF : 7500 = 7.5s + uint32_t crv = (((timeoutSeconds * 1000u) << 15u) / 1000) - 1; + NRF_WDT->CRV = crv; + + /* Enable reload requests */ + NRF_WDT->RREN = (WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos); + + resetReason = ActualResetReason(); +} + +void Watchdog::Start() { + NRF_WDT->TASKS_START = 1; +} + +void Watchdog::Kick() { + NRF_WDT->RR[0] = WDT_RR_RR_Reload; +} + +Pinetime::Drivers::Watchdogs::ResetReasons Watchdog::ActualResetReason() const { + uint32_t reason = NRF_POWER->RESETREAS; + NRF_POWER->RESETREAS = 0xffffffff; + + if (reason & 0x01u) + return Watchdogs::ResetReasons::ResetPin; + if ((reason >> 1u) & 0x01u) + return Watchdogs::ResetReasons::Watchdog; + if ((reason >> 2u) & 0x01u) + return Watchdogs::ResetReasons::SoftReset; + if ((reason >> 3u) & 0x01u) + return Watchdogs::ResetReasons::CpuLockup; + if ((reason >> 16u) & 0x01u) + return Watchdogs::ResetReasons::SystemOff; + if ((reason >> 17u) & 0x01u) + return Watchdogs::ResetReasons::LpComp; + if ((reason) &0x01u) + return Watchdogs::ResetReasons::DebugInterface; + if ((reason >> 19u) & 0x01u) + return Watchdogs::ResetReasons::NFC; + return Watchdogs::ResetReasons::HardReset; +} diff --git a/src/drivers/nrf52/Watchdog.h b/src/drivers/nrf52/Watchdog.h new file mode 100644 index 0000000000..92f19f5252 --- /dev/null +++ b/src/drivers/nrf52/Watchdog.h @@ -0,0 +1,24 @@ +#pragma once +#include "drivers/Watchdog.h" +#include + +namespace Pinetime { + namespace Drivers { + namespace Nrf52 { + class Watchdog { + public: + enum class ResetReasons { ResetPin, Watchdog, SoftReset, CpuLockup, SystemOff, LpComp, DebugInterface, NFC, HardReset }; + void Setup(uint8_t timeoutSeconds); + void Start(); + void Kick(); + Watchdogs::ResetReasons ResetReason() const { + return resetReason; + } + + private: + Watchdogs::ResetReasons resetReason; + Watchdogs::ResetReasons ActualResetReason() const; + }; + } + } +} diff --git a/src/heartratetask/HeartRateTask.cpp b/src/heartratetask/HeartRateTask.cpp index bc22762469..72bd11a76c 100644 --- a/src/heartratetask/HeartRateTask.cpp +++ b/src/heartratetask/HeartRateTask.cpp @@ -1,11 +1,11 @@ #include "heartratetask/HeartRateTask.h" -#include +#include #include #include using namespace Pinetime::Applications; -HeartRateTask::HeartRateTask(Drivers::Hrs3300& heartRateSensor, Controllers::HeartRateController& controller) +HeartRateTask::HeartRateTask(Drivers::HeartRateSensor & heartRateSensor, Controllers::HeartRateController& controller) : heartRateSensor {heartRateSensor}, controller {controller}, ppg {} { } diff --git a/src/heartratetask/HeartRateTask.h b/src/heartratetask/HeartRateTask.h index 0796dc74dd..8ed310f89d 100644 --- a/src/heartratetask/HeartRateTask.h +++ b/src/heartratetask/HeartRateTask.h @@ -3,11 +3,9 @@ #include #include #include +#include "port/HeartRateSensor.h" namespace Pinetime { - namespace Drivers { - class Hrs3300; - } namespace Controllers { class HeartRateController; } @@ -17,7 +15,7 @@ namespace Pinetime { enum class Messages : uint8_t { GoToSleep, WakeUp, StartMeasurement, StopMeasurement }; enum class States { Idle, Running }; - explicit HeartRateTask(Drivers::Hrs3300& heartRateSensor, Controllers::HeartRateController& controller); + explicit HeartRateTask(Drivers::HeartRateSensor& heartRateSensor, Controllers::HeartRateController& controller); void Start(); void Work(); void PushMessage(Messages msg); @@ -30,7 +28,7 @@ namespace Pinetime { TaskHandle_t taskHandle; QueueHandle_t messageQueue; States state = States::Running; - Drivers::Hrs3300& heartRateSensor; + Drivers::HeartRateSensor& heartRateSensor; Controllers::HeartRateController& controller; Controllers::Ppg ppg; bool measurementStarted = false; diff --git a/src/main.cpp b/src/main.cpp index f02756fb2b..c1287de8e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,9 +25,8 @@ #include #include #include -#include -#include -#include +#include +#include #include "BootloaderVersion.h" #include "components/battery/BatteryController.h" @@ -47,6 +46,8 @@ #include "drivers/PinMap.h" #include "systemtask/SystemTask.h" #include "drivers/PinMap.h" +#include "drivers/Watchdog.h" +#include "drivers/WatchdogView.h" #include "touchhandler/TouchHandler.h" #include "buttonhandler/ButtonHandler.h" @@ -60,6 +61,8 @@ Pinetime::Logging::DummyLogger logger; #include "port/TouchPanel.h" #include "port/MotionSensor.h" +#include "port/HeartRateSensor.h" +#include "port/Watchdog.h" static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; @@ -104,7 +107,9 @@ Pinetime::Components::LittleVgl lvgl {lcd, touchPanel}; Pinetime::Drivers::MotionSensors::Bma421 motionSensorImpl {twiMaster, motionSensorTwiAddress}; Pinetime::Drivers::MotionSensor motionSensor {motionSensorImpl}; -Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress}; + +Pinetime::Drivers::HeartRateSensors::Hrs3300 heartRateSensorImpl {twiMaster, heartRateSensorTwiAddress}; +Pinetime::Drivers::HeartRateSensor heartRateSensor{heartRateSensorImpl}; TimerHandle_t debounceTimer; TimerHandle_t debounceChargeTimer; @@ -119,8 +124,9 @@ Pinetime::Controllers::Settings settingsController {fs}; Pinetime::Controllers::MotorController motorController {}; Pinetime::Controllers::DateTime dateTimeController {settingsController}; -Pinetime::Drivers::Watchdog watchdog; -Pinetime::Drivers::WatchdogView watchdogView(watchdog); +Pinetime::Drivers::Nrf52::Watchdog watchdogImpl; +Pinetime::Drivers::Watchdog watchdog{watchdogImpl}; +Pinetime::Drivers::WatchdogView watchdogView{watchdog}; Pinetime::Controllers::NotificationManager notificationManager; Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::TimerController timerController; diff --git a/src/port/HeartRateSensor.h b/src/port/HeartRateSensor.h new file mode 100644 index 0000000000..b28e7d5631 --- /dev/null +++ b/src/port/HeartRateSensor.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/HeartRateSensor.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using HeartRateSensor = Interface::HeartRateSensor; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/port/MotionSensor.h b/src/port/MotionSensor.h index 5a92727436..f6d51f457e 100644 --- a/src/port/MotionSensor.h +++ b/src/port/MotionSensor.h @@ -2,7 +2,7 @@ #include "drivers/MotionSensor.h" #ifdef TARGET_DEVICE_PINETIME - #include + #include #endif namespace Pinetime { diff --git a/src/port/Watchdog.h b/src/port/Watchdog.h new file mode 100644 index 0000000000..ff66ac6602 --- /dev/null +++ b/src/port/Watchdog.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/Watchdog.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using Watchdog = Interface::Watchdog; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 966a86cc39..5d91b6f197 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -7,7 +7,7 @@ #include "components/ble/BleController.h" #include "displayapp/TouchEvents.h" #include "drivers/St7789.h" -#include "drivers/Hrs3300.h" +#include "drivers/heartRateSensors/Hrs3300.h" #include "drivers/PinMap.h" #include "main.h" #include "BootErrors.h" @@ -53,7 +53,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, Drivers::Watchdog& watchdog, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::MotorController& motorController, - Pinetime::Drivers::Hrs3300& heartRateSensor, + Pinetime::Drivers::HeartRateSensor& heartRateSensor, Pinetime::Controllers::MotionController& motionController, Pinetime::Drivers::MotionSensor& motionSensor, Controllers::Settings& settingsController, diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 543e125327..3358411647 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,12 +37,13 @@ #include "systemtask/Messages.h" #include "port/SpiMaster.h" #include "port/MotionSensor.h" +#include "port/HeartRateSensor.h" +#include "port/Watchdog.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { namespace Drivers { class St7789; - class Hrs3300; } namespace Controllers { class Battery; @@ -67,7 +68,7 @@ namespace Pinetime { Drivers::Watchdog& watchdog, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::MotorController& motorController, - Pinetime::Drivers::Hrs3300& heartRateSensor, + Pinetime::Drivers::HeartRateSensor& heartRateSensor, Pinetime::Controllers::MotionController& motionController, Pinetime::Drivers::MotionSensor& motionSensor, Controllers::Settings& settingsController, @@ -113,7 +114,7 @@ namespace Pinetime { Pinetime::Drivers::Watchdog& watchdog; Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::MotorController& motorController; - Pinetime::Drivers::Hrs3300& heartRateSensor; + Pinetime::Drivers::HeartRateSensor& heartRateSensor; Pinetime::Drivers::MotionSensor& motionSensor; Pinetime::Controllers::Settings& settingsController; Pinetime::Controllers::HeartRateController& heartRateController; From 89421de606aecabb0b66c4ec065b57d6693aee1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 28 Dec 2022 18:12:32 +0100 Subject: [PATCH 09/10] Refactor St7789 as a generic Display class. --- src/CMakeLists.txt | 8 +-- src/components/gfx/Gfx.cpp | 4 +- src/components/gfx/Gfx.h | 8 +-- src/displayapp/DisplayApp.cpp | 4 +- src/displayapp/DisplayApp.h | 5 +- src/displayapp/DisplayAppRecovery.cpp | 2 +- src/displayapp/DisplayAppRecovery.h | 7 ++- src/displayapp/DummyLittleVgl.h | 5 +- src/displayapp/LittleVgl.cpp | 3 +- src/displayapp/LittleVgl.h | 9 ++-- src/drivers/Display.h | 68 +++++++++++++++++++++++ src/drivers/St7789.h | 77 -------------------------- src/drivers/{ => displays}/St7789.cpp | 4 +- src/drivers/displays/St7789.h | 78 +++++++++++++++++++++++++++ src/main.cpp | 6 ++- src/port/Display.h | 16 ++++++ src/recoveryLoader.cpp | 4 +- src/systemtask/SystemTask.cpp | 4 +- src/systemtask/SystemTask.h | 8 ++- 19 files changed, 199 insertions(+), 121 deletions(-) create mode 100644 src/drivers/Display.h delete mode 100644 src/drivers/St7789.h rename src/drivers/{ => displays}/St7789.cpp (98%) create mode 100644 src/drivers/displays/St7789.h create mode 100644 src/port/Display.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3942e4631f..31b5cb2a08 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -435,7 +435,7 @@ list(APPEND SOURCE_FILES ## main.cpp - drivers/St7789.cpp + drivers/displays/St7789.cpp drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp drivers/nrf52/TwiMaster.cpp @@ -502,7 +502,7 @@ list(APPEND RECOVERY_SOURCE_FILES displayapp/DisplayAppRecovery.cpp main.cpp - drivers/St7789.cpp + drivers/displays/St7789.cpp drivers/nrf52/SpiMaster.cpp drivers/nrf52/Spi.cpp drivers/nrf52/TwiMaster.cpp @@ -575,7 +575,7 @@ list(APPEND RECOVERYLOADER_SOURCE_FILES components/rle/RleDecoder.cpp components/gfx/Gfx.cpp - drivers/St7789.cpp + drivers/displays/St7789.cpp components/brightness/BrightnessController.cpp recoveryLoader.cpp @@ -618,7 +618,7 @@ set(INCLUDE_FILES displayapp/widgets/Counter.h displayapp/widgets/PageIndicator.h displayapp/widgets/StatusIcons.h - drivers/St7789.h + drivers/displays/St7789.h drivers/SpiNorFlash.h drivers/nrf52/SpiMaster.h drivers/nrf52/Spi.h diff --git a/src/components/gfx/Gfx.cpp b/src/components/gfx/Gfx.cpp index 3eaaa3fecc..6c51a1cdd4 100644 --- a/src/components/gfx/Gfx.cpp +++ b/src/components/gfx/Gfx.cpp @@ -1,8 +1,8 @@ #include "components/gfx/Gfx.h" -#include "drivers/St7789.h" +#include "drivers/displays/St7789.h" using namespace Pinetime::Components; -Gfx::Gfx(Pinetime::Drivers::St7789& lcd) : lcd {lcd} { +Gfx::Gfx(Pinetime::Drivers::Displays::St7789& lcd) : lcd {lcd} { } void Gfx::Init() { diff --git a/src/components/gfx/Gfx.h b/src/components/gfx/Gfx.h index 54c4a8b778..51fcdfe99e 100644 --- a/src/components/gfx/Gfx.h +++ b/src/components/gfx/Gfx.h @@ -8,12 +8,14 @@ namespace Pinetime { namespace Drivers { - class St7789; + namespace Displays { + class St7789; + } } namespace Components { class Gfx : public Pinetime::Drivers::BufferProvider { public: - explicit Gfx(Drivers::St7789& lcd); + explicit Gfx(Drivers::Displays::St7789& lcd); void Init(); void ClearScreen(); void DrawString(uint8_t x, uint8_t y, uint16_t color, const char* text, const FONT_INFO* p_font, bool wrap); @@ -49,7 +51,7 @@ namespace Pinetime { volatile State state; uint16_t buffer[width]; // 1 line buffer - Drivers::St7789& lcd; + Drivers::Displays::St7789& lcd; void SetBackgroundColor(uint16_t color); void WaitTransferFinished() const; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 68ea3923ab..a6003d9e3d 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,8 +30,6 @@ #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" -#include "drivers/St7789.h" -#include "drivers/Watchdog.h" #include "systemtask/SystemTask.h" #include "systemtask/Messages.h" @@ -59,7 +57,7 @@ namespace { } } -DisplayApp::DisplayApp(Drivers::St7789& lcd, +DisplayApp::DisplayApp(Drivers::Display& lcd, Components::LittleVgl& lvgl, Pinetime::Drivers::TouchPanel& touchPanel, Controllers::Battery& batteryController, diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 972b490c2d..b6ac6db0f8 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -23,7 +23,6 @@ namespace Pinetime { namespace Drivers { - class St7789; class WatchdogView; } namespace Controllers { @@ -46,7 +45,7 @@ namespace Pinetime { enum class States { Idle, Running }; enum class FullRefreshDirections { None, Up, Down, Left, Right, LeftAnim, RightAnim }; - DisplayApp(Drivers::St7789& lcd, + DisplayApp(Drivers::Display& lcd, Components::LittleVgl& lvgl, Pinetime::Drivers::TouchPanel&, Controllers::Battery& batteryController, @@ -73,7 +72,7 @@ namespace Pinetime { void Register(Pinetime::System::SystemTask* systemTask); private: - Pinetime::Drivers::St7789& lcd; + Pinetime::Drivers::Display& lcd; Pinetime::Components::LittleVgl& lvgl; Pinetime::Drivers::TouchPanel& touchPanel; Pinetime::Controllers::Battery& batteryController; diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index cf1f416f3d..00b9fe0762 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -10,7 +10,7 @@ using namespace Pinetime::Applications; -DisplayApp::DisplayApp(Drivers::St7789& lcd, +DisplayApp::DisplayApp(Drivers::Display& lcd, Components::LittleVgl& lvgl, Drivers::TouchPanel& touchPanel, Controllers::Battery& batteryController, diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 00f6d19a03..55826ae3ed 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include #include #include #include @@ -15,10 +14,10 @@ #include "displayapp/Messages.h" #include "displayapp/DummyLittleVgl.h" #include "port/TouchPanel.h" +#include "port/Display.h" namespace Pinetime { namespace Drivers { - class St7789; class WatchdogView; } namespace Controllers { @@ -44,7 +43,7 @@ namespace Pinetime { namespace Applications { class DisplayApp { public: - DisplayApp(Drivers::St7789& lcd, + DisplayApp(Drivers::Display& lcd, Components::LittleVgl& lvgl, Drivers::TouchPanel&, Controllers::Battery& batteryController, @@ -75,7 +74,7 @@ namespace Pinetime { void DisplayOtaProgress(uint8_t percent, uint16_t color); void InitHw(); void Refresh(); - Pinetime::Drivers::St7789& lcd; + Pinetime::Drivers::Display& lcd; Controllers::Ble& bleController; static constexpr uint8_t queueSize = 10; diff --git a/src/displayapp/DummyLittleVgl.h b/src/displayapp/DummyLittleVgl.h index 7ca2de83a1..baab7e59c7 100644 --- a/src/displayapp/DummyLittleVgl.h +++ b/src/displayapp/DummyLittleVgl.h @@ -3,15 +3,16 @@ #include #include #include -#include + #include "port/TouchPanel.h" +#include "port/Display.h" namespace Pinetime { namespace Components { class LittleVgl { public: enum class FullRefreshDirections { None, Up, Down }; - LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::TouchPanel & touchPanel) { + LittleVgl(Pinetime::Drivers::Display& lcd, Pinetime::Drivers::TouchPanel & touchPanel) { } LittleVgl(const LittleVgl&) = delete; diff --git a/src/displayapp/LittleVgl.cpp b/src/displayapp/LittleVgl.cpp index 143defcf5e..7eef851006 100644 --- a/src/displayapp/LittleVgl.cpp +++ b/src/displayapp/LittleVgl.cpp @@ -4,7 +4,6 @@ #include #include //#include -#include "drivers/St7789.h" using namespace Pinetime::Components; @@ -30,7 +29,7 @@ bool touchpad_read(lv_indev_drv_t* indev_drv, lv_indev_data_t* data) { return lvgl->GetTouchPadInfo(data); } -LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::TouchPanel& touchPanel) : lcd {lcd}, touchPanel {touchPanel} { +LittleVgl::LittleVgl(Pinetime::Drivers::Display& lcd, Pinetime::Drivers::TouchPanel& touchPanel) : lcd {lcd}, touchPanel {touchPanel} { } void LittleVgl::Init() { diff --git a/src/displayapp/LittleVgl.h b/src/displayapp/LittleVgl.h index 09c709d3ff..d6db792e33 100644 --- a/src/displayapp/LittleVgl.h +++ b/src/displayapp/LittleVgl.h @@ -2,17 +2,14 @@ #include #include "port/TouchPanel.h" +#include "port/Display.h" namespace Pinetime { - namespace Drivers { - class St7789; - } - namespace Components { class LittleVgl { public: enum class FullRefreshDirections { None, Up, Down, Left, Right, LeftAnim, RightAnim }; - LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::TouchPanel& touchPanel); + LittleVgl(Pinetime::Drivers::Display& lcd, Pinetime::Drivers::TouchPanel& touchPanel); LittleVgl(const LittleVgl&) = delete; LittleVgl& operator=(const LittleVgl&) = delete; @@ -39,7 +36,7 @@ namespace Pinetime { void InitTouchpad(); void InitTheme(); - Pinetime::Drivers::St7789& lcd; + Pinetime::Drivers::Display& lcd; Pinetime::Drivers::TouchPanel& touchPanel; lv_disp_buf_t disp_buf_2; diff --git a/src/drivers/Display.h b/src/drivers/Display.h new file mode 100644 index 0000000000..06a7116c18 --- /dev/null +++ b/src/drivers/Display.h @@ -0,0 +1,68 @@ +#pragma once +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + template + concept IsDisplay = requires(DisplayImpl display, uint16_t line, uint16_t coord, uint32_t color, uint16_t dimension, const uint8_t* data, size_t size) { + { display.Init() }; + { display.Uninit() }; + { display.DrawPixel(coord, coord, color) }; + { display.VerticalScrollDefinition(line, line, line) }; + { display.VerticalScrollStartAddress(line) }; + { display.DrawBuffer(coord, coord, dimension, dimension, data, size) }; + { display.Sleep() }; + { display.Wakeup() }; + }; + + namespace Interface { + template + requires IsDisplay + class Display { + public: + explicit Display(T& impl) : impl {impl} {} + Display(const Display&) = delete; + Display& operator=(const Display&) = delete; + Display(Display&&) = delete; + Display& operator=(Display&&) = delete; + + void Init() { + impl.Init(); + } + + void Uninit() { + impl.Uninit(); + } + + void DrawPixel(uint16_t x, uint16_t y, uint32_t color) { + impl.DrawPixel(x, y, color); + } + + void VerticalScrollDefinition(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines) { + impl.VerticalScrollDefinition(topFixedLines, scrollLines, bottomFixedLines); + } + + void VerticalScrollStartAddress(uint16_t line) { + impl.VerticalScrollStartAddress(line); + } + + void DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size) { + impl.DrawBuffer(x, y, width, height, data, size); + } + + void Sleep() { + impl.Sleep(); + } + + void Wakeup() { + impl.Wakeup(); + } + + private: + T& impl; + }; + } + } +} diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h deleted file mode 100644 index 5cca48ae12..0000000000 --- a/src/drivers/St7789.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#include "drivers/Spi.h" -#include -#include -#include "port/Spi.h" - -namespace Pinetime { - namespace Drivers { - - class St7789 { - public: - explicit St7789(Spi& spi, uint8_t pinDataCommand); - St7789(const St7789&) = delete; - St7789& operator=(const St7789&) = delete; - St7789(St7789&&) = delete; - St7789& operator=(St7789&&) = delete; - - void Init(); - void Uninit(); - void DrawPixel(uint16_t x, uint16_t y, uint32_t color); - - void VerticalScrollDefinition(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines); - void VerticalScrollStartAddress(uint16_t line); - - void DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size); - - void Sleep(); - void Wakeup(); - - private: - Spi& spi; - uint8_t pinDataCommand; - uint8_t verticalScrollingStartAddress = 0; - - void HardwareReset(); - void SoftwareReset(); - void SleepOut(); - void SleepIn(); - void ColMod(); - void MemoryDataAccessControl(); - void DisplayInversionOn(); - void NormalModeOn(); - void WriteToRam(); - void DisplayOn(); - void DisplayOff(); - - void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); - void SetVdv(); - void WriteCommand(uint8_t cmd); - void WriteSpi(const uint8_t* data, size_t size); - - enum class Commands : uint8_t { - SoftwareReset = 0x01, - SleepIn = 0x10, - SleepOut = 0x11, - NormalModeOn = 0x13, - DisplayInversionOn = 0x21, - DisplayOff = 0x28, - DisplayOn = 0x29, - ColumnAddressSet = 0x2a, - RowAddressSet = 0x2b, - WriteToRam = 0x2c, - MemoryDataAccessControl = 0x36, - VerticalScrollDefinition = 0x33, - VerticalScrollStartAddress = 0x37, - ColMod = 0x3a, - VdvSet = 0xc4, - }; - void WriteData(uint8_t data); - void ColumnAddressSet(); - - static constexpr uint16_t Width = 240; - static constexpr uint16_t Height = 320; - void RowAddressSet(); - }; - } -} diff --git a/src/drivers/St7789.cpp b/src/drivers/displays/St7789.cpp similarity index 98% rename from src/drivers/St7789.cpp rename to src/drivers/displays/St7789.cpp index cfd5bd2ce4..32328125a7 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/displays/St7789.cpp @@ -1,10 +1,10 @@ -#include "drivers/St7789.h" +#include "St7789.h" #include #include #include #include "drivers/Spi.h" -using namespace Pinetime::Drivers; +using namespace Pinetime::Drivers::Displays; St7789::St7789(Spi& spi, uint8_t pinDataCommand) : spi {spi}, pinDataCommand {pinDataCommand} { } diff --git a/src/drivers/displays/St7789.h b/src/drivers/displays/St7789.h new file mode 100644 index 0000000000..09db5ee639 --- /dev/null +++ b/src/drivers/displays/St7789.h @@ -0,0 +1,78 @@ +#pragma once +#include "drivers/Spi.h" +#include +#include +#include "port/Spi.h" + +namespace Pinetime { + namespace Drivers { + namespace Displays { + class St7789 { + public: + explicit St7789(Spi& spi, uint8_t pinDataCommand); + St7789(const St7789&) = delete; + St7789& operator=(const St7789&) = delete; + St7789(St7789&&) = delete; + St7789& operator=(St7789&&) = delete; + + void Init(); + void Uninit(); + void DrawPixel(uint16_t x, uint16_t y, uint32_t color); + + void VerticalScrollDefinition(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines); + void VerticalScrollStartAddress(uint16_t line); + + void DrawBuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t* data, size_t size); + + void Sleep(); + void Wakeup(); + + private: + Spi& spi; + uint8_t pinDataCommand; + uint8_t verticalScrollingStartAddress = 0; + + void HardwareReset(); + void SoftwareReset(); + void SleepOut(); + void SleepIn(); + void ColMod(); + void MemoryDataAccessControl(); + void DisplayInversionOn(); + void NormalModeOn(); + void WriteToRam(); + void DisplayOn(); + void DisplayOff(); + + void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); + void SetVdv(); + void WriteCommand(uint8_t cmd); + void WriteSpi(const uint8_t* data, size_t size); + + enum class Commands : uint8_t { + SoftwareReset = 0x01, + SleepIn = 0x10, + SleepOut = 0x11, + NormalModeOn = 0x13, + DisplayInversionOn = 0x21, + DisplayOff = 0x28, + DisplayOn = 0x29, + ColumnAddressSet = 0x2a, + RowAddressSet = 0x2b, + WriteToRam = 0x2c, + MemoryDataAccessControl = 0x36, + VerticalScrollDefinition = 0x33, + VerticalScrollStartAddress = 0x37, + ColMod = 0x3a, + VdvSet = 0xc4, + }; + void WriteData(uint8_t data); + void ColumnAddressSet(); + + static constexpr uint16_t Width = 240; + static constexpr uint16_t Height = 320; + void RowAddressSet(); + }; + } + } +} diff --git a/src/main.cpp b/src/main.cpp index c1287de8e3..1e4da37b1a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,7 @@ #include "drivers/nrf52/Spi.h" #include "drivers/nrf52/SpiMaster.h" #include "drivers/SpiNorFlash.h" -#include "drivers/St7789.h" +#include "drivers/displays/St7789.h" #include "drivers/TwiMaster.h" #include "drivers/touchpanels/Cst816s.h" #include "drivers/PinMap.h" @@ -63,6 +63,7 @@ Pinetime::Logging::DummyLogger logger; #include "port/MotionSensor.h" #include "port/HeartRateSensor.h" #include "port/Watchdog.h" +#include "port/Display.h" static constexpr uint8_t touchPanelTwiAddress = 0x15; static constexpr uint8_t motionSensorTwiAddress = 0x18; @@ -80,7 +81,8 @@ Pinetime::Drivers::SpiMaster spi {spiImpl}; Pinetime::Drivers::Nrf52::Spi lcdSpiIpmpl {spiImpl, Pinetime::PinMap::SpiLcdCsn}; Pinetime::Drivers::Spi lcdSpi {lcdSpiIpmpl}; -Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; +Pinetime::Drivers::Displays::St7789 lcdImpl {lcdSpi, Pinetime::PinMap::LcdDataCommand}; +Pinetime::Drivers::Display lcd{lcdImpl}; Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; diff --git a/src/port/Display.h b/src/port/Display.h new file mode 100644 index 0000000000..f7151272dc --- /dev/null +++ b/src/port/Display.h @@ -0,0 +1,16 @@ +#pragma once +#include "drivers/Display.h" + +#ifdef TARGET_DEVICE_PINETIME + #include +#endif + +namespace Pinetime { + namespace Drivers { +#ifdef TARGET_DEVICE_PINETIME + using Display = Interface::Display; +#else + #error "No target device specified!" +#endif + } +} diff --git a/src/recoveryLoader.cpp b/src/recoveryLoader.cpp index 792442d0d8..9ad2c1d4d6 100644 --- a/src/recoveryLoader.cpp +++ b/src/recoveryLoader.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include "recoveryImage.h" @@ -51,7 +51,7 @@ Pinetime::Drivers::SpiMaster spi {spiImpl}; Pinetime::Drivers::Nrf52::Spi lcdSpiIpmpl {spiImpl, Pinetime::PinMap::SpiLcdCsn}; Pinetime::Drivers::Spi lcdSpi {lcdSpiIpmpl}; -Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; +Pinetime::Drivers::Displays::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand}; Pinetime::Drivers::Nrf52::Spi flashSpiImpl {spiImpl, Pinetime::PinMap::SpiFlashCsn}; Pinetime::Drivers::Spi flashSpi {flashSpiImpl}; diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 5d91b6f197..6265df1539 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -6,8 +6,6 @@ #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "displayapp/TouchEvents.h" -#include "drivers/St7789.h" -#include "drivers/heartRateSensors/Hrs3300.h" #include "drivers/PinMap.h" #include "main.h" #include "BootErrors.h" @@ -40,7 +38,7 @@ void MeasureBatteryTimerCallback(TimerHandle_t xTimer) { } SystemTask::SystemTask(Drivers::SpiMaster& spi, - Drivers::St7789& lcd, + Drivers::Display& lcd, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::TwiMaster& twiMaster, Pinetime::Drivers::TouchPanel& touchPanel, diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 3358411647..d42a1ed4af 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -39,12 +39,10 @@ #include "port/MotionSensor.h" #include "port/HeartRateSensor.h" #include "port/Watchdog.h" +#include "port/Display.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { - namespace Drivers { - class St7789; - } namespace Controllers { class Battery; class TouchHandler; @@ -55,7 +53,7 @@ namespace Pinetime { public: enum class SystemTaskState { Sleeping, Running, GoingToSleep, WakingUp }; SystemTask(Drivers::SpiMaster& spi, - Drivers::St7789& lcd, + Drivers::Display& lcd, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::TwiMaster& twiMaster, Pinetime::Drivers::TouchPanel& touchPanel, @@ -99,7 +97,7 @@ namespace Pinetime { TaskHandle_t taskHandle; Pinetime::Drivers::SpiMaster& spi; - Pinetime::Drivers::St7789& lcd; + Pinetime::Drivers::Display& lcd; Pinetime::Drivers::SpiNorFlash& spiNorFlash; Pinetime::Drivers::TwiMaster& twiMaster; Pinetime::Drivers::TouchPanel& touchPanel; From ac50b00fc07b3b6f3fdce6bde69780080a71e78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Wed, 4 Jan 2023 15:20:45 +0100 Subject: [PATCH 10/10] Add documentation about the new hardware abstraction design. --- README.md | 2 +- doc/code/Intro.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fd4158600..b8c31b2d96 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Fast open-source firmware for the [PineTime smartwatch](https://www.pine64.org/p ## Development - [InfiniTime Vision](doc/InfiniTimeVision.md) -- [Rough structure of the code](doc/code/Intro.md) +- [Introduction to the code](doc/code/Intro.md) - [How to implement an application](doc/code/Apps.md) - [Generate the fonts and symbols](src/displayapp/fonts/README.md) - [Tips on designing an app UI](doc/ui_guidelines.md) diff --git a/doc/code/Intro.md b/doc/code/Intro.md index 34adc5fa6c..0089e20d06 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -47,3 +47,88 @@ For more detail see the [Apps page](./Apps.md) ## Bluetooth Header files with short documentation for the functions are inside [libs/mynewt-nimble/nimble/host/include/host/](/src/libs/mynewt-nimble/nimble/host/include/host/). + +## Hardware abstraction and device drivers + +Until version 1.12, InfiniTime did not provide any kind of hardware abstraction : the drivers were written specifically for the PineTime, and there was no easy way to provide any alternative implementation to support variants of the PineTime or for the integration in [InfiniSim](https://github.com/InfiniTimeOrg/InfiniSim). + +In [InfiniTime 1.12](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/1.12.0), we implemented a new design that allows to easily choose **at build time** a specific implementation for multiple device drivers (Display, heart rate sensor, motion sensor, SPI, flash memory, touch panel, TWI and Watchdog). + +This new design makes the code much cleaner in InfiniSim and allows the port of InfiniTime on other hardware (ex : many PineTime variants like the Colmi P8) more easily. + +This hardware abstraction is based on C++ `concepts` and a proxy object that enables 'static polymorphism'. It means that the actual implementations of the drivers are known at **build time** and that there's no `virtual` calls at runtime. + +Here's an overview of the design : + +```c++ +namespace Pinetime { + namespace Drivers { + template + concept IsDevice = { /* ... */ }; + + namespace Interface { + template + requires IsDevice + class Device { + public: + explicit Device(T& impl) : impl {impl} {} + /* ... */ + private: + T& impl; + }; + } + + using Device = Interface::Device; + } +} + +int main() { + /* ... */ + + Pinetime::Drivers::Category::Device deviceImpl { /* ctor arguments specific to this implementation of Device */ }; + Pinetime::Drivers::Device device {deviceImpl}; + + /* ... */ +} + +``` + +The concept `Pinetime::Drivers::IsDevice` describes the interface a class that implements a `Device` must expose. + +The template class `Pinetime::Drivers::Interface::Device` is the "proxy" objects that allows the build time polymorphism. + +`Pinetime::Drivers::Device` is aliased to `Pinetime::Drivers::Interface::Device`. This allows to remove the template argument so that the rest of the application does not need to handle it. Those aliases are defined in header files located in `port/`. This is the only place where `#ifdef`s are needed. + +The actual drivers are implemented in specific namespaces (`Pinetime::Drivers::MCU::Device` or `Pinetime::Drivers::Category::Device`). + +To declare a new driver in the code, you'll first need to instantiate an actual implementation of the driver and then give the reference to this instance to the corresponding proxy object. Here is an example with the display driver: + +```c++ +// Actual implementation of the SPI bus for the NRF52 MCU +Pinetime::Drivers::Nrf52::SpiMaster spiImpl {Pinetime::Drivers::Nrf52::SpiMaster::SpiModule::SPI0, + {Pinetime::Drivers::Nrf52::SpiMaster::BitOrder::Msb_Lsb, + Pinetime::Drivers::Nrf52::SpiMaster::Modes::Mode3, + Pinetime::Drivers::Nrf52::SpiMaster::Frequencies::Freq8Mhz, + Pinetime::PinMap::SpiSck, + Pinetime::PinMap::SpiMosi, + Pinetime::PinMap::SpiMiso}}; + +// Proxy object +Pinetime::Drivers::SpiMaster spi {spiImpl}; + +// Actual implementation of the SpiMaster drivers (it handles the chip select pin) +Pinetime::Drivers::Nrf52::Spi lcdSpiIpmpl {spiImpl, Pinetime::PinMap::SpiLcdCsn}; + +// Proxy object +Pinetime::Drivers::Spi lcdSpi {lcdSpiIpmpl}; + +// Actual implementation of the display driver (ST7789 display controller) +Pinetime::Drivers::Displays::St7789 lcdImpl {lcdSpi, Pinetime::PinMap::LcdDataCommand}; + +// Proxy object +Pinetime::Drivers::Display lcd{lcdImpl}; + +Pinetime::System::SystemTask systemTask(spi, lcd /* ... */); +``` + +Once the initialization is done, the application does not need to know the actual implementation of the drivers, all calls to the drivers will go through the proxy objects.