Compare commits
3 Commits
8d49d2d446
...
0107d3e6e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0107d3e6e7 | ||
|
|
105a387efc | ||
|
|
08c23d6244 |
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
Button() = delete;
|
Button() = delete;
|
||||||
explicit Button(const gpio& sw)
|
explicit Button(const gpio& sw)
|
||||||
: sw(sw)
|
: sw(sw), was_pressed_(sw.read())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
@ -59,7 +59,15 @@ public:
|
|||||||
else if (!is_pressed && was_pressed_)
|
else if (!is_pressed && was_pressed_)
|
||||||
{
|
{
|
||||||
if (time_held > TIMEOUT_SHORT_PRESS && time_held <= TIMEOUT_LONG_PRESS)
|
if (time_held > TIMEOUT_SHORT_PRESS && time_held <= TIMEOUT_LONG_PRESS)
|
||||||
|
{
|
||||||
new_state = ButtonPress::SHORT_PRESS;
|
new_state = ButtonPress::SHORT_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state_exhausted_)
|
||||||
|
{
|
||||||
|
current_state_ = ButtonPress::NOT_PRESSED;
|
||||||
|
state_exhausted_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
time_pressed_down_ = 0;
|
time_pressed_down_ = 0;
|
||||||
}
|
}
|
||||||
@ -70,12 +78,24 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
was_pressed_ = is_pressed;
|
was_pressed_ = is_pressed;
|
||||||
current_state_ = new_state;
|
|
||||||
|
if (!state_exhausted_)
|
||||||
|
current_state_ = new_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ButtonPress getState() const
|
[[nodiscard]] ButtonPress getState() const
|
||||||
{
|
{
|
||||||
return current_state_;
|
if (!state_exhausted_)
|
||||||
|
{
|
||||||
|
if (current_state_ != ButtonPress::NOT_PRESSED && current_state_ != ButtonPress::SHORT_PRESS)
|
||||||
|
state_exhausted_ = true;
|
||||||
|
|
||||||
|
return current_state_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ButtonPress::NOT_PRESSED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SKULLC_WITH_CORO
|
#ifdef SKULLC_WITH_CORO
|
||||||
@ -96,9 +116,10 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool was_pressed_ = false;
|
bool was_pressed_;
|
||||||
std::uint32_t time_pressed_down_ = 0;
|
std::uint32_t time_pressed_down_ = 0;
|
||||||
ButtonPress current_state_ = ButtonPress::NOT_PRESSED;
|
ButtonPress current_state_ = ButtonPress::NOT_PRESSED;
|
||||||
|
mutable bool state_exhausted_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace Peripherals
|
}// namespace Peripherals
|
||||||
|
|||||||
@ -31,7 +31,7 @@ template<typename Origin>
|
|||||||
using IsrCallbackFn = void (*)(Origin*);
|
using IsrCallbackFn = void (*)(Origin*);
|
||||||
|
|
||||||
template<typename Origin, typename Handler, void (Handler::*func)(),
|
template<typename Origin, typename Handler, void (Handler::*func)(),
|
||||||
typename Tag>
|
typename Tag = decltype([] {})>
|
||||||
IsrCallbackFn<Origin> createCallback(Handler& h_in)
|
IsrCallbackFn<Origin> createCallback(Handler& h_in)
|
||||||
{
|
{
|
||||||
static Handler* h = &h_in;
|
static Handler* h = &h_in;
|
||||||
@ -200,6 +200,104 @@ struct SerialInterfaceAsync
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef SKULLC_WITH_CORO
|
||||||
|
template<typename T,
|
||||||
|
HAL_StatusTypeDef (*transmit_)(T*, std::uint8_t* data,
|
||||||
|
std::uint16_t data_len),
|
||||||
|
HAL_StatusTypeDef (*receive_)(T*, std::uint8_t* data,
|
||||||
|
std::uint16_t data_len)>
|
||||||
|
struct SerialInterfaceCoro
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void on_rx_complete()
|
||||||
|
{
|
||||||
|
if (rx_awaiter_)
|
||||||
|
rx_awaiter_->set_completed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_tx_complete()
|
||||||
|
{
|
||||||
|
if (tx_awaiter_)
|
||||||
|
tx_awaiter_->set_completed();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<skullc::coro::ISRAwaiter> rx_awaiter_ = std::nullopt;
|
||||||
|
std::optional<skullc::coro::ISRAwaiter> tx_awaiter_ = std::nullopt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using underlying_handle_type = T;
|
||||||
|
underlying_handle_type* handle;
|
||||||
|
|
||||||
|
SerialInterfaceCoro() = delete;
|
||||||
|
|
||||||
|
template<typename = decltype([] {})>
|
||||||
|
explicit SerialInterfaceCoro(underlying_handle_type* handle)
|
||||||
|
: handle(handle)
|
||||||
|
{
|
||||||
|
handle->RxCpltCallback = createCallback<T,
|
||||||
|
std::decay_t<decltype(*this)>,
|
||||||
|
&std::decay_t<decltype(*this)>::on_rx_complete>(*this);
|
||||||
|
|
||||||
|
handle->TxCpltCallback = createCallback<T,
|
||||||
|
std::decay_t<decltype(*this)>,
|
||||||
|
&std::decay_t<decltype(*this)>::on_tx_complete>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
skullc::coro::Task<bool> transmit(std::uint8_t* data, const std::uint32_t data_len)
|
||||||
|
{
|
||||||
|
tx_awaiter_.emplace();
|
||||||
|
const auto status = transmit_(handle, data, data_len);
|
||||||
|
if (status != HAL_StatusTypeDef::HAL_OK)
|
||||||
|
co_return false;
|
||||||
|
|
||||||
|
co_await *tx_awaiter_;
|
||||||
|
tx_awaiter_ = std::nullopt;
|
||||||
|
|
||||||
|
co_return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Td, std::size_t N>
|
||||||
|
skullc::coro::Task<bool> transmit(std::array<Td, N>& array)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Td) == sizeof(std::uint8_t), "Data is not a byte large.");
|
||||||
|
|
||||||
|
return transmit(reinterpret_cast<std::uint8_t*>(array.data()), std::uint32_t(N));
|
||||||
|
}
|
||||||
|
|
||||||
|
skullc::coro::Task<bool> receive(std::uint8_t* data, const std::uint32_t data_len)
|
||||||
|
{
|
||||||
|
rx_awaiter_.emplace();
|
||||||
|
const auto status = receive_(handle, data, data_len);
|
||||||
|
if (status != HAL_StatusTypeDef::HAL_OK)
|
||||||
|
co_return false;
|
||||||
|
|
||||||
|
co_await *rx_awaiter_;
|
||||||
|
rx_awaiter_ = std::nullopt;
|
||||||
|
|
||||||
|
co_return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Td, std::size_t N>
|
||||||
|
skullc::coro::Task<bool> receive(std::array<Td, N>& array)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Td) == sizeof(std::uint8_t), "Data is not a byte large.");
|
||||||
|
|
||||||
|
return receive(reinterpret_cast<std::uint8_t*>(array.data()), std::uint32_t(N));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
skullc::coro::Task<std::array<std::uint8_t, N>> receive()
|
||||||
|
{
|
||||||
|
std::array<std::uint8_t, N> data;
|
||||||
|
data.fill(0);
|
||||||
|
|
||||||
|
co_await receive(data.data(), std::uint32_t(N));
|
||||||
|
|
||||||
|
co_return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif// SKULLC_WITH_CORO
|
||||||
|
|
||||||
#ifdef HAL_SPI_MODULE_ENABLED
|
#ifdef HAL_SPI_MODULE_ENABLED
|
||||||
|
|
||||||
using SpiInterface =
|
using SpiInterface =
|
||||||
@ -296,6 +394,11 @@ inline HAL_StatusTypeDef uartTransmitDma(UART_HandleTypeDef* huart, std::uint8_t
|
|||||||
return HAL_UART_Transmit_DMA(huart, data, size);
|
return HAL_UART_Transmit_DMA(huart, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline HAL_StatusTypeDef uartTransmitIt(UART_HandleTypeDef* huart, std::uint8_t* data, const std::uint16_t size)
|
||||||
|
{
|
||||||
|
return HAL_UART_Transmit_IT(huart, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
}// namespace _Details
|
}// namespace _Details
|
||||||
|
|
||||||
using UartInterface =
|
using UartInterface =
|
||||||
@ -303,6 +406,14 @@ using UartInterface =
|
|||||||
using UartInterfaceDMA =
|
using UartInterfaceDMA =
|
||||||
SerialInterfaceAsync<UART_HandleTypeDef, _Details::uartTransmitDma,
|
SerialInterfaceAsync<UART_HandleTypeDef, _Details::uartTransmitDma,
|
||||||
HAL_UART_Receive_DMA>;
|
HAL_UART_Receive_DMA>;
|
||||||
|
#ifdef SKULLC_WITH_CORO
|
||||||
|
using UartInterfaceCoro =
|
||||||
|
SerialInterfaceCoro<UART_HandleTypeDef, _Details::uartTransmitIt,
|
||||||
|
HAL_UART_Receive_IT>;
|
||||||
|
using UartInterfaceCoroDma =
|
||||||
|
SerialInterfaceCoro<UART_HandleTypeDef, _Details::uartTransmitDma,
|
||||||
|
HAL_UART_Receive_DMA>;
|
||||||
|
#endif// SKULLC_WITH_CORO
|
||||||
|
|
||||||
#endif// HAL_UART_MODULE_ENABLED
|
#endif// HAL_UART_MODULE_ENABLED
|
||||||
|
|
||||||
|
|||||||
@ -46,10 +46,10 @@ struct Gpio
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set(const bool value)
|
void set(const bool value)
|
||||||
{ }
|
{}
|
||||||
|
|
||||||
void toggle()
|
void toggle()
|
||||||
{ }
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Gpio::is_set = false;
|
bool Gpio::is_set = false;
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
#include "skullc/coro/scheduler.hpp"
|
#include "skullc/coro/scheduler.hpp"
|
||||||
#include "skullc/coro/semaphore.hpp"
|
#include "skullc/coro/semaphore.hpp"
|
||||||
|
#include "skullc/coro/signal.hpp"
|
||||||
#include "skullc/coro/sleep.hpp"
|
#include "skullc/coro/sleep.hpp"
|
||||||
#include "skullc/coro/task.hpp"
|
#include "skullc/coro/task.hpp"
|
||||||
#include "skullc/coro/this_coro.hpp"
|
#include "skullc/coro/this_coro.hpp"
|
||||||
#include "skullc/coro/signal.hpp"
|
|
||||||
|
|
||||||
#include <semaphore>
|
#include <semaphore>
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ skullc::coro::Task<> send_signal(const int value, skullc::coro::Signal<int>* sig
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}// namespace
|
||||||
|
|
||||||
TEST_CASE("Signal awaiters work.", "[coro],[signal]")
|
TEST_CASE("Signal awaiters work.", "[coro],[signal]")
|
||||||
{
|
{
|
||||||
@ -300,7 +300,7 @@ TEST_CASE("Signal awaiters work.", "[coro],[signal]")
|
|||||||
REQUIRE(test_coro_called == 1);
|
REQUIRE(test_coro_called == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<int> values = { 10, 11, 13 };
|
const std::vector<int> values = {10, 11, 13};
|
||||||
|
|
||||||
SECTION("Sending multiple values.")
|
SECTION("Sending multiple values.")
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
@ -78,4 +79,42 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ISRAwaiter
|
||||||
|
{
|
||||||
|
ISRAwaiter() = default;
|
||||||
|
|
||||||
|
~ISRAwaiter()
|
||||||
|
{
|
||||||
|
if (continuation)
|
||||||
|
this_coro::scheduler().remove(continuation);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool await_ready()
|
||||||
|
{
|
||||||
|
return isr_completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void await_suspend(std::coroutine_handle<> h)
|
||||||
|
{
|
||||||
|
continuation = h;
|
||||||
|
suspended = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto await_resume()
|
||||||
|
{
|
||||||
|
continuation = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_completed()
|
||||||
|
{
|
||||||
|
isr_completed = true;
|
||||||
|
if (suspended == true)
|
||||||
|
this_coro::scheduler().schedule(continuation, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::coroutine_handle<> continuation;
|
||||||
|
std::atomic<bool> isr_completed = false;
|
||||||
|
std::atomic<bool> suspended = false;
|
||||||
|
};
|
||||||
|
|
||||||
}// namespace skullc::coro
|
}// namespace skullc::coro
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class Signal
|
|||||||
Awaiter(const Awaiter&) = delete;
|
Awaiter(const Awaiter&) = delete;
|
||||||
Awaiter(Awaiter&&) = delete;
|
Awaiter(Awaiter&&) = delete;
|
||||||
explicit Awaiter(Signal* signal)
|
explicit Awaiter(Signal* signal)
|
||||||
: signal(signal)
|
: signal(signal)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Awaiter& operator=(const Awaiter&) = delete;
|
Awaiter& operator=(const Awaiter&) = delete;
|
||||||
@ -83,9 +83,10 @@ public:
|
|||||||
|
|
||||||
return *awaiter_;
|
return *awaiter_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<T> data_;
|
std::optional<T> data_;
|
||||||
std::optional<Awaiter> awaiter_;
|
std::optional<Awaiter> awaiter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}// namespace skullc::coro
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user