-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Better hardware abstraction using C++20 concepts #1387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
2e1227f
d8757c5
0fa32f3
ddcf491
2094dbd
7d42c99
7d2ca5c
8b2c875
89421de
ac50b00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,56 @@ | ||
| #pragma once | ||
| #include <cstdint> | ||
| #include <cstddef> | ||
| #include "drivers/SpiMaster.h" | ||
| #include <utility> | ||
| #include <concepts> | ||
|
|
||
| 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 <typename T> | ||
JF002 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 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<bool>; | ||
| { s.Read(command, size, data, size) } -> std::same_as<bool>; | ||
| }; | ||
|
|
||
| namespace Interface { | ||
| template <class T> | ||
| requires IsSpi<T> | ||
| 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; | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| } | ||
JF002 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,65 +1,70 @@ | ||
| #pragma once | ||
| #include <cstddef> | ||
| #include <cstdint> | ||
|
|
||
| #include <FreeRTOS.h> | ||
| #include <semphr.h> | ||
| #include <task.h> | ||
| #include <algorithm> | ||
|
|
||
| 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 <typename T> | ||
JF002 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| concept IsSpiMaster = | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (outsider suggestion) (ditto for other places) Concepts should be named like adjectives rather than predicates, i.e.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with this. However... this rule is not easy to apply here :
Renaming the concept from |
||
| 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<bool>; | ||
| { spi.Write(pin, constData, size) } -> std::same_as<bool>; | ||
| { spi.Read(pin, command, size, data, size) } -> std::same_as<bool>; | ||
| { spi.WriteCmdAndBuffer(pin, constCommand, size, constData, size) } -> std::same_as<bool>; | ||
| { 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 <class T> | ||
| requires IsSpiMaster<T> | ||
| 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; | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| } | ||
JF002 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Uh oh!
There was an error while loading. Please reload this page.