diff --git a/Peripherals/CMakeLists.txt b/Peripherals/CMakeLists.txt index 4928c42..43b44fe 100644 --- a/Peripherals/CMakeLists.txt +++ b/Peripherals/CMakeLists.txt @@ -10,5 +10,20 @@ target_include_directories(peripherals $ ) +if (DEFINED SKULLC_USE_HAL_ST) + set(PERIPHERALS_DEFINITIONS SKULLC_USE_HAL_ST) +endif () +if (DEFINED SKULLC_USE_HAL_ESP) + set(PERIPHERALS_DEFINITIONS SKULLC_USE_HAL_ESP) +endif () +if (DEFINED SKULLC_WITH_CORO) + list(APPEND PERIPHERALS_DEFINITIONS SKULLC_WITH_CORO) +endif () + +target_compile_definitions(peripherals + INTERFACE + ${PERIPHERALS_DEFINITIONS} +) + ## INSTALL skullc_install_packages(skullc peripherals ${SKULLC_VERSION}) diff --git a/Peripherals/Inc/peripherals_button.hpp b/Peripherals/Inc/peripherals_button.hpp index 0116dda..47fc354 100644 --- a/Peripherals/Inc/peripherals_button.hpp +++ b/Peripherals/Inc/peripherals_button.hpp @@ -10,6 +10,14 @@ #include +#include "peripherals_hal_concepts.hpp" + +#ifdef SKULLC_WITH_CORO +#include "skullc/coro/sleep.hpp" +#include "skullc/coro/task.hpp" +#include "skullc/coro/this_coro.hpp" +#endif + namespace Peripherals { @@ -20,7 +28,7 @@ enum class ButtonPress : std::uint32_t LONG_PRESS }; -template +template class Button { public: @@ -70,6 +78,23 @@ public: return current_state_; } +#ifdef SKULLC_WITH_CORO + skullc::coro::Task await_press() + { + ButtonPress result = ButtonPress::NOT_PRESSED; + while (result == ButtonPress::NOT_PRESSED) + { + update(); + result = getState(); + + if (result == ButtonPress::NOT_PRESSED) + co_await skullc::coro::sleep(std::chrono::milliseconds(hal::getMillis()), std::chrono::milliseconds(1)); + } + + co_return result; + } +#endif + private: bool was_pressed_ = false; std::uint32_t time_pressed_down_ = 0; diff --git a/Peripherals/Inc/peripherals_hal_concepts.hpp b/Peripherals/Inc/peripherals_hal_concepts.hpp index 05c989d..0d326c4 100644 --- a/Peripherals/Inc/peripherals_hal_concepts.hpp +++ b/Peripherals/Inc/peripherals_hal_concepts.hpp @@ -40,4 +40,9 @@ concept RegisterInterface = requires(T t, RegName reg, std::uint8_t* data, const t.readRegisterMultibyte(reg, data, len, std::uint32_t{}); }; +template +concept StaticHal = requires() { + { T::getMillis() } -> std::same_as; +}; + }// namespace Peripherals::Hal diff --git a/Peripherals/Inc/peripherals_hal_st.hpp b/Peripherals/Inc/peripherals_hal_st.hpp index fa034b9..8d3a105 100644 --- a/Peripherals/Inc/peripherals_hal_st.hpp +++ b/Peripherals/Inc/peripherals_hal_st.hpp @@ -14,6 +14,10 @@ #include +#ifdef SKULLC_WITH_CORO +#include "skullc/coro/peripheral_awaiters.hpp" +#endif + #define USE_DELAY_US namespace Peripherals @@ -92,6 +96,13 @@ struct Gpio void toggle() { HAL_GPIO_TogglePin(port, pin); } bool read() const { return inverted ? !bool(HAL_GPIO_ReadPin(port, pin)) : bool(HAL_GPIO_ReadPin(port, pin)); } + +#ifdef SKULLC_WITH_CORO + auto await_edge(const Edge& edge) + { + return skullc::coro::PinEdgeAwaiter(this, edge); + } +#endif }; #define CREATE_GPIO(name) \ diff --git a/Tests/coro.cpp b/Tests/coro.cpp index e45d49a..f06b166 100644 --- a/Tests/coro.cpp +++ b/Tests/coro.cpp @@ -4,11 +4,11 @@ #include -#include "skullc/coro/task.hpp" #include "skullc/coro/scheduler.hpp" -#include "skullc/coro/this_coro.hpp" -#include "skullc/coro/sleep.hpp" #include "skullc/coro/semaphore.hpp" +#include "skullc/coro/sleep.hpp" +#include "skullc/coro/task.hpp" +#include "skullc/coro/this_coro.hpp" #include @@ -43,7 +43,7 @@ skullc::coro::Task<> test_semaphore_coro(T* semaphore, const int expected) co_return; } -} +}// namespace TEST_CASE("Scheduler runs coroutines.", "[coro]") { @@ -96,9 +96,8 @@ TEST_CASE("Scheduler runs coroutines.", "[coro]") std::counting_semaphore<10> counting_semaphore{0}; scheduler.start_tasks( - test_semaphore_coro(&semaphore, 0), - test_semaphore_coro(&counting_semaphore, 1) - ); + test_semaphore_coro(&semaphore, 0), + test_semaphore_coro(&counting_semaphore, 1)); scheduler.loop(0); REQUIRE(test_coro_called == 0); @@ -119,9 +118,8 @@ TEST_CASE("Scheduler runs coroutines.", "[coro]") SECTION("Coros scheduled for the same millisecond get executed with the same time.") { scheduler.start_tasks( - test_sleepy_coro(0, std::chrono::milliseconds{2}), - test_sleepy_coro(1, std::chrono::milliseconds{2}) - ); + test_sleepy_coro(0, std::chrono::milliseconds{2}), + test_sleepy_coro(1, std::chrono::milliseconds{2})); scheduler.loop(0); scheduler.loop(0); @@ -169,7 +167,7 @@ skullc::coro::Task<> await_pin_edge(TestGpio* pin, const Peripherals::Hal::Edge co_return; } -} +}// namespace TEST_CASE("Peripheral awaiters work.", "[coro],[awaiters]") { @@ -181,7 +179,7 @@ TEST_CASE("Peripheral awaiters work.", "[coro],[awaiters]") SECTION("Pin edge awaiter works with rising edge.") { - TestGpio gpio{ false }; + TestGpio gpio{false}; scheduler.start_tasks(await_pin_edge(&gpio, Peripherals::Hal::Edge::Rising)); scheduler.loop(0); @@ -208,7 +206,7 @@ TEST_CASE("Peripheral awaiters work.", "[coro],[awaiters]") SECTION("Pin edge awaiter works with falling edge.") { - TestGpio gpio{ true }; + TestGpio gpio{true}; scheduler.start_tasks(await_pin_edge(&gpio, Peripherals::Hal::Edge::Falling)); scheduler.loop(0); diff --git a/coro/CMakeLists.txt b/coro/CMakeLists.txt index 636a865..c2a7888 100644 --- a/coro/CMakeLists.txt +++ b/coro/CMakeLists.txt @@ -10,5 +10,10 @@ target_include_directories(coro $ ) +target_compile_definitions(coro + INTERFACE + SKULLC_WITH_CORO +) + ## INSTALL skullc_install_packages(skullc coro ${SKULLC_VERSION}) diff --git a/coro/inc/skullc/coro/peripheral_awaiters.hpp b/coro/inc/skullc/coro/peripheral_awaiters.hpp index 5a48c58..e71d1db 100644 --- a/coro/inc/skullc/coro/peripheral_awaiters.hpp +++ b/coro/inc/skullc/coro/peripheral_awaiters.hpp @@ -9,8 +9,8 @@ #include "peripherals_hal_concepts.hpp" -#include "skullc/coro/this_coro.hpp" #include "skullc/coro/scheduler.hpp" +#include "skullc/coro/this_coro.hpp" namespace skullc::coro { @@ -20,14 +20,8 @@ struct PinEdgeAwaiter : TaskPoller { PinEdgeAwaiter() = delete; explicit PinEdgeAwaiter(G* pin, const Peripherals::Hal::Edge& edge) - : pin(pin) - , awaited_edge(edge) - { - if (awaited_edge == Peripherals::Hal::Edge::Rising) - previous_is_set = false; - else - previous_is_set = true; - } + : pin(pin), awaited_edge(edge), previous_is_set(pin->read()) + {} ~PinEdgeAwaiter() override { @@ -83,4 +77,4 @@ private: } }; -} +}// namespace skullc::coro diff --git a/coro/inc/skullc/coro/scheduler.hpp b/coro/inc/skullc/coro/scheduler.hpp index 03416e8..430651f 100644 --- a/coro/inc/skullc/coro/scheduler.hpp +++ b/coro/inc/skullc/coro/scheduler.hpp @@ -9,8 +9,8 @@ #include #include -#include "skullc/coro/task.hpp" #include "skullc/coro/scheduler_base.hpp" +#include "skullc/coro/task.hpp" namespace skullc::coro { @@ -84,7 +84,7 @@ public: if (pollers_need_updating) pollers_.erase(std::remove_if(pollers_.begin(), pollers_.end(), - [](const auto* poller) { return poller->stored_coro == nullptr; })); + [](const auto* poller) { return poller->stored_coro == nullptr; })); } void add_poller(TaskPoller* poller) override diff --git a/coro/inc/skullc/coro/scheduler_base.hpp b/coro/inc/skullc/coro/scheduler_base.hpp index 0fab197..2f76470 100644 --- a/coro/inc/skullc/coro/scheduler_base.hpp +++ b/coro/inc/skullc/coro/scheduler_base.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -28,4 +29,4 @@ public: virtual void add_poller(TaskPoller* poller) = 0; }; -} \ No newline at end of file +}// namespace skullc::coro \ No newline at end of file diff --git a/coro/inc/skullc/coro/semaphore.hpp b/coro/inc/skullc/coro/semaphore.hpp index dc7e79e..c37d660 100644 --- a/coro/inc/skullc/coro/semaphore.hpp +++ b/coro/inc/skullc/coro/semaphore.hpp @@ -14,14 +14,14 @@ namespace skullc::coro { template - requires requires (T t) { { t.try_acquire() } -> std::same_as; } + requires requires(T t) { { t.try_acquire() } -> std::same_as; } auto await_semaphore(T& semaphore) { struct Awaitable : TaskPoller { Awaitable() = delete; explicit Awaitable(T* semaphore) - : semaphore{semaphore} + : semaphore{semaphore} {} ~Awaitable() override @@ -56,4 +56,4 @@ auto await_semaphore(T& semaphore) return Awaitable{&semaphore}; } -} +}// namespace skullc::coro diff --git a/coro/inc/skullc/coro/sleep.hpp b/coro/inc/skullc/coro/sleep.hpp index b863114..64d8ee8 100644 --- a/coro/inc/skullc/coro/sleep.hpp +++ b/coro/inc/skullc/coro/sleep.hpp @@ -7,6 +7,8 @@ #include "skullc/coro/scheduler.hpp" #include "skullc/coro/this_coro.hpp" +#include "peripherals_hal_concepts.hpp" + namespace skullc::coro { @@ -48,4 +50,10 @@ inline auto sleep(const std::chrono::duration& time_now, c return detail::TimeAwaitable{time_now.count() + duration.count()}; } +template +auto sleep(const std::chrono::duration& duration) +{ + return detail::TimeAwaitable{Hal::getMillis() + duration.count()}; +} + }// namespace skullc::coro