cleanup + rename of some classes
This commit is contained in:
parent
75ac69f41f
commit
bd5f60512a
@ -1,15 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "log.hpp"
|
||||
#include "syscalls/kernel.h"
|
||||
#include "zephyr/sys/time_units.h"
|
||||
#include "zephyr/sys_clock.h"
|
||||
#include "function.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <ratio>
|
||||
#include <string_view>
|
||||
@ -17,6 +12,8 @@
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/sys/time_units.h>
|
||||
#include <zephyr/sys_clock.h>
|
||||
|
||||
#include <zephyr/drivers/adc.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
@ -127,7 +124,7 @@ class Timer {
|
||||
/* This is the time until the first expiration of the timer after you call k_timer_start().
|
||||
It's a one-time initial delay before the timer "fires" the first time. */
|
||||
k_timeout_t _duration;
|
||||
|
||||
|
||||
/* After the first expiration, the timer will automatically restart and continue to expire repeatedly with this interval (period time)
|
||||
between each expiration. If you set period to K_NO_WAIT, the timer only fires once (it becomes a one-shot timer).*/
|
||||
k_timeout_t _period;
|
||||
@ -164,7 +161,7 @@ class RecurringSemaphoreTimer : public Timer {
|
||||
|
||||
class SingleShootTimer : public Timer {
|
||||
public:
|
||||
SingleShootTimer(std::function<void()> cb, std::chrono::microseconds duration) : Timer(duration), _cb{std::move(cb)} {
|
||||
SingleShootTimer(rims::function<void()> cb, std::chrono::microseconds duration) : Timer(duration), _cb{std::move(cb)} {
|
||||
}
|
||||
|
||||
SingleShootTimer(const SingleShootTimer &) = delete;
|
||||
@ -176,7 +173,7 @@ class SingleShootTimer : public Timer {
|
||||
void expiry_cb() override {
|
||||
_cb();
|
||||
}
|
||||
|
||||
|
||||
void fire_at(clock::time_point target) {
|
||||
auto now = clock::now();
|
||||
if (target <= now) {
|
||||
@ -184,27 +181,16 @@ class SingleShootTimer : public Timer {
|
||||
_duration = chronoToKTimeout(std::chrono::microseconds{1});
|
||||
} else {
|
||||
auto delay = std::chrono::duration_cast<std::chrono::microseconds>(target - now);
|
||||
_duration = chronoToKTimeout(delay);
|
||||
_duration = chronoToKTimeout(delay);
|
||||
}
|
||||
|
||||
|
||||
_period = K_NO_WAIT; // Ensure it's a one-shot
|
||||
start();
|
||||
}
|
||||
|
||||
std::function<void()> _cb;
|
||||
rims::function<void()> _cb;
|
||||
};
|
||||
|
||||
// class RecurringTimer : public Timer {
|
||||
// public:
|
||||
// RecurringTimer(std::function<void()> cb, std::chrono::milliseconds interval) : Timer(interval, interval), _cb{std::move(cb)} {
|
||||
// }
|
||||
// void expiry_cb() override {
|
||||
// _cb();
|
||||
// }
|
||||
|
||||
// std::function<void()> _cb;
|
||||
// };
|
||||
|
||||
struct TStackBase {
|
||||
z_thread_stack_element *_sp;
|
||||
std::size_t _size;
|
||||
@ -297,6 +283,4 @@ constexpr auto ChannelNumber = 2;
|
||||
constexpr int GPIO_PIN_PB5 = 5;
|
||||
constexpr int GPIO_PIN_PB6 = 6;
|
||||
|
||||
|
||||
|
||||
} // namespace rims
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
|
||||
#include "ring_buffer.hpp"
|
||||
|
||||
namespace rims{
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
namespace rims {
|
||||
|
||||
template <typename T> struct ZephyrFifoElement {
|
||||
void *_reserved;
|
||||
@ -14,19 +16,19 @@ template <typename T, size_t N> class fifo_queue {
|
||||
// static_assert(std::is_trivial_v<T>);
|
||||
fifo_queue(k_fifo &fifo) : _fifo{fifo} {
|
||||
}
|
||||
|
||||
|
||||
void k_event_init(k_poll_event &event) {
|
||||
zephyr::event_pool::k_init(event, _fifo);
|
||||
}
|
||||
|
||||
|
||||
template <typename Fn> //
|
||||
bool try_consume(Fn fn) {
|
||||
// std::lock_guard<ZephyrMutex> _lock{_mutex};
|
||||
if (_elements.empty()) return false;
|
||||
|
||||
/// read from queue
|
||||
|
||||
/// read from queue
|
||||
ZephyrFifoElement<T> *el = reinterpret_cast<ZephyrFifoElement<T> *>(k_fifo_get(&_fifo, K_NO_WAIT));
|
||||
|
||||
|
||||
try {
|
||||
if (not el) return false; // should be a assert
|
||||
fn(el->item); // consume item, fn can throw
|
||||
@ -35,15 +37,15 @@ template <typename T, size_t N> class fifo_queue {
|
||||
_elements.pop_front();
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
template <typename Fn> //
|
||||
bool try_produce(Fn fn) {
|
||||
// std::lock_guard<ZephyrMutex> _lock{_mutex};
|
||||
if (_elements.full()) return false;
|
||||
|
||||
|
||||
auto tmp = ZephyrFifoElement<T>{};
|
||||
if (fn(tmp.item)) // fill new data
|
||||
{
|
||||
@ -51,13 +53,13 @@ template <typename T, size_t N> class fifo_queue {
|
||||
k_fifo_put(&_fifo, &el); // put data into a queue
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// ZephyrMutex _mutex{};
|
||||
ring_buffer<ZephyrFifoElement<T>, N> _elements{};
|
||||
RingBuffer<ZephyrFifoElement<T>, N> _elements{};
|
||||
k_fifo &_fifo;
|
||||
};
|
||||
}
|
||||
} // namespace rims
|
||||
|
||||
@ -1,81 +1,198 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include "details/function.hpp"
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <cstring> // For std::memset
|
||||
|
||||
namespace rims{
|
||||
template <typename>
|
||||
class Function;
|
||||
namespace rims {
|
||||
template <typename, unsigned = 1> struct trivial_function;
|
||||
template <typename, unsigned = 1> struct function;
|
||||
|
||||
// A simple std::function alternative that never allocates. It contains
|
||||
// enough space to store a lambda that captures N pointer-sized objects.
|
||||
// The lambda's destructor and copy/move constructors are never used,
|
||||
// which makes it very cheap to pass around. This also implies that only
|
||||
// trivial types, such as pointers and references, can safely be captured.
|
||||
template <typename R, typename... A, unsigned N> struct trivial_function<R(A...), N> {
|
||||
constexpr trivial_function() noexcept = default;
|
||||
constexpr ~trivial_function() = default;
|
||||
constexpr trivial_function(trivial_function &&) noexcept = default;
|
||||
constexpr trivial_function(const trivial_function &) noexcept = default;
|
||||
constexpr trivial_function &operator=(trivial_function &&) noexcept = default;
|
||||
constexpr trivial_function &operator=(const trivial_function &) noexcept = default;
|
||||
|
||||
template <typename T, unsigned M> trivial_function(function<T, M> &&) = delete;
|
||||
template <typename T, unsigned M> trivial_function(const function<T, M> &) = delete;
|
||||
|
||||
constexpr trivial_function(std::nullptr_t) noexcept : trivial_function{} {
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
requires(not detail::is_function_instance<std::remove_cvref_t<F>>)
|
||||
explicit trivial_function(F &&func) : trivial_function{create(std::forward<F>(func))} {
|
||||
}
|
||||
|
||||
template <typename F> trivial_function &operator=(F &&func) noexcept {
|
||||
return *this = trivial_function{std::forward<F>(func)};
|
||||
}
|
||||
|
||||
template <unsigned M>
|
||||
requires(M < N)
|
||||
trivial_function(const trivial_function<R(A...), M> &other) noexcept : call{other.call} {
|
||||
std::memcpy(storage, &other.storage, sizeof(other.storage));
|
||||
}
|
||||
|
||||
R operator()(A... args) const {
|
||||
return call(&storage, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
constexpr bool valid() const noexcept {
|
||||
return call != nullptr;
|
||||
}
|
||||
explicit constexpr operator bool() const noexcept {
|
||||
return valid();
|
||||
}
|
||||
|
||||
template <typename Ret, typename... Args>
|
||||
class Function<Ret(Args...)> {
|
||||
private:
|
||||
static constexpr size_t BufferSize = 16; // Adjust this size as needed for your use case.
|
||||
using InvokeFn = Ret (*)(void*, Args&&...);
|
||||
|
||||
alignas(std::max_align_t) char buffer[BufferSize];
|
||||
InvokeFn invokeFn = nullptr;
|
||||
|
||||
template <typename Callable>
|
||||
static Ret invokeImpl(void* callable, Args&&... args) {
|
||||
return (*reinterpret_cast<Callable*>(callable))(std::forward<Args>(args)...);
|
||||
template <typename F> static trivial_function create(F &&func) {
|
||||
using functor = detail::functor<std::remove_cvref_t<F>>;
|
||||
static_assert(std::is_trivially_destructible_v<functor>);
|
||||
static_assert(sizeof(functor) <= sizeof(dummy));
|
||||
static_assert(alignof(functor) <= alignof(dummy));
|
||||
trivial_function f;
|
||||
new (&f.storage) functor{std::forward<F>(func)};
|
||||
f.call = functor::template call<R, A...>;
|
||||
return f;
|
||||
}
|
||||
|
||||
template <typename Callable>
|
||||
void storeCallable(Callable&& callable) {
|
||||
using CallableType = std::decay_t<Callable>;
|
||||
static_assert(sizeof(CallableType) <= BufferSize, "Callable too large for Function buffer");
|
||||
static_assert(alignof(CallableType) <= alignof(std::max_align_t), "Callable alignment exceeds max_align_t");
|
||||
|
||||
new (buffer) CallableType(std::forward<Callable>(callable));
|
||||
invokeFn = &invokeImpl<CallableType>;
|
||||
|
||||
template <typename, unsigned> friend struct trivial_function;
|
||||
template <typename, unsigned> friend struct function;
|
||||
using dummy = detail::functor<decltype([x = std::declval<std::array<void *, N>>()](A...) {})>;
|
||||
|
||||
union {
|
||||
struct {
|
||||
} nothing{};
|
||||
alignas(dummy) std::byte storage[sizeof(dummy)];
|
||||
};
|
||||
R (*call)(const void *, A &&...){nullptr};
|
||||
};
|
||||
|
||||
template <typename F, typename Signature = typename detail::member_function_signature<decltype(&F::operator())>::type>
|
||||
trivial_function(F) -> trivial_function<Signature, (sizeof(F) - 1) / sizeof(void *) + 1>;
|
||||
|
||||
// A fixed-size function object that can store non-trivial lambdas. It is
|
||||
// larger than trivial_function and requires the use of virtual function
|
||||
// calls on copy/move/destroy.
|
||||
template <typename R, typename... A, unsigned N> struct function<R(A...), N> {
|
||||
constexpr function() noexcept = default;
|
||||
constexpr ~function() {
|
||||
if (call != nullptr) vtable->destroy(&storage);
|
||||
}
|
||||
|
||||
public:
|
||||
Function() = default;
|
||||
|
||||
template <typename Callable>
|
||||
Function(Callable&& callable) {
|
||||
storeCallable(std::forward<Callable>(callable));
|
||||
|
||||
template <typename F> function &operator=(F &&func) {
|
||||
return assign(std::forward<F>(func));
|
||||
}
|
||||
|
||||
Function(const Function&) = delete; // Disable copying for simplicity
|
||||
Function& operator=(const Function&) = delete;
|
||||
|
||||
Function(Function&& other) noexcept {
|
||||
std::memcpy(buffer, other.buffer, BufferSize);
|
||||
invokeFn = other.invokeFn;
|
||||
other.invokeFn = nullptr;
|
||||
|
||||
constexpr function(std::nullptr_t) noexcept : function{} {
|
||||
}
|
||||
|
||||
Function& operator=(Function&& other) noexcept {
|
||||
if (this != &other) {
|
||||
this->~Function();
|
||||
std::memcpy(buffer, other.buffer, BufferSize);
|
||||
invokeFn = other.invokeFn;
|
||||
other.invokeFn = nullptr;
|
||||
}
|
||||
return *this;
|
||||
|
||||
template <typename F>
|
||||
requires(not detail::is_function_instance<std::remove_cvref_t<F>>)
|
||||
explicit function(F &&func) : function{create(std::forward<F>(func))} {
|
||||
}
|
||||
|
||||
~Function() {
|
||||
if (invokeFn) {
|
||||
reinterpret_cast<void(*)(void*)>(buffer)(buffer);
|
||||
}
|
||||
|
||||
template <unsigned M>
|
||||
requires(M <= N)
|
||||
function(function<R(A...), M> &&other) : vtable{other.vtable}, call{other.call} {
|
||||
if (call == nullptr) return;
|
||||
vtable->move(&storage, &other.storage);
|
||||
other.call = nullptr;
|
||||
}
|
||||
|
||||
Ret operator()(Args... args) const {
|
||||
if (!invokeFn) {
|
||||
// throw std::bad_function_call();
|
||||
assert(false); ///TODO handle asserts
|
||||
}
|
||||
return invokeFn(const_cast<void*>(reinterpret_cast<const void*>(buffer)), std::forward<Args>(args)...);
|
||||
|
||||
template <unsigned M>
|
||||
requires(M <= N)
|
||||
function(const function<R(A...), M> &other) noexcept : vtable{other.vtable}, call{other.call} {
|
||||
if (call == nullptr) return;
|
||||
vtable->copy(&storage, &other.storage);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return invokeFn != nullptr;
|
||||
|
||||
template <unsigned M>
|
||||
requires(M <= N)
|
||||
function(const trivial_function<R(A...), M> &other) noexcept
|
||||
: vtable{detail::functor_vtable::trivial<sizeof(other.storage)>()}, call{other.call} {
|
||||
std::memcpy(&storage, &other.storage, sizeof(storage));
|
||||
}
|
||||
};}
|
||||
|
||||
R operator()(A... args) const {
|
||||
return call(&storage, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
constexpr bool valid() const noexcept {
|
||||
return call != nullptr;
|
||||
}
|
||||
explicit constexpr operator bool() const noexcept {
|
||||
return valid();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F> static function create(F &&func) {
|
||||
using functor = detail::functor<std::remove_cvref_t<F>>;
|
||||
static_assert(sizeof(functor) <= sizeof(dummy));
|
||||
static_assert(alignof(functor) <= alignof(dummy));
|
||||
function f;
|
||||
new (&f.storage) functor{std::forward<F>(func)};
|
||||
f.call = functor::template call<R, A...>;
|
||||
f.vtable = detail::functor_vtable::create<std::remove_cvref_t<F>>();
|
||||
return f;
|
||||
}
|
||||
|
||||
template <typename F> function &assign(F &&other) {
|
||||
this->~function();
|
||||
return *new (this) function{std::forward<F>(other)};
|
||||
}
|
||||
|
||||
template <typename, unsigned> friend struct function;
|
||||
using dummy = trivial_function<R(A...), N>::dummy;
|
||||
|
||||
union {
|
||||
struct {
|
||||
} nothing{};
|
||||
struct {
|
||||
alignas(dummy) std::byte storage[sizeof(dummy)];
|
||||
const detail::functor_vtable *vtable;
|
||||
};
|
||||
};
|
||||
R (*call)(const void *, A &&...){nullptr};
|
||||
};
|
||||
|
||||
template <typename F, typename Signature = typename detail::member_function_signature<decltype(&F::operator())>::type>
|
||||
function(F) -> function<Signature, (sizeof(F) - 1) / sizeof(void *) + 1>;
|
||||
|
||||
// A single-use function object with stored arguments.
|
||||
template <typename T> struct callable_tuple {
|
||||
template <typename... E> constexpr callable_tuple(E &&...elements) : tuple{std::forward<E>(elements)...} {
|
||||
}
|
||||
|
||||
template <typename... A> decltype(auto) operator()(A &&...args) {
|
||||
return call(std::make_index_sequence<std::tuple_size_v<T>>{}, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
template <std::size_t... I, typename... A> decltype(auto) call(std::index_sequence<I...>, A &&...args) {
|
||||
return std::invoke(std::get<I>(std::move(tuple))..., std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
T tuple;
|
||||
};
|
||||
|
||||
template <typename... E> callable_tuple(E...) -> callable_tuple<std::tuple<std::decay_t<E>...>>;
|
||||
} // namespace rims
|
||||
|
||||
namespace rims::detail {
|
||||
template <typename Sig, unsigned N> inline constexpr bool is_function_instance<trivial_function<Sig, N>> = true;
|
||||
|
||||
template <typename Sig, unsigned N> inline constexpr bool is_function_instance<function<Sig, N>> = true;
|
||||
} // namespace rims::detail
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "gpio.hpp"
|
||||
#include "proto/gpio.pb.h"
|
||||
#include "zephyr.hpp"
|
||||
#include "log.hpp"
|
||||
#include <exception>
|
||||
|
||||
namespace rims {
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
#include "common.hpp"
|
||||
|
||||
#include "ring_buffer.hpp"
|
||||
#include "fifo_queue.hpp"
|
||||
|
||||
#include "proto/gpio.pb.h"
|
||||
#include "zephyr.hpp"
|
||||
#include "zephyr/kernel.h"
|
||||
#include <array>
|
||||
|
||||
namespace rims {
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <source_location>
|
||||
#include <string_view>
|
||||
|
||||
#include "fifo_queue.hpp"
|
||||
#include "function.hpp"
|
||||
#include "proto/log.pb.h"
|
||||
|
||||
namespace rims {
|
||||
@ -28,7 +28,7 @@ static LogLevel g_logLevel = LogLevel::Debug;
|
||||
class Log {
|
||||
public:
|
||||
using Level = LogLevel;
|
||||
using Sink = std::function<void(Level level, std::string_view usermsg, const std::source_location &sl)>;
|
||||
using Sink = rims::function<void(Level level, std::string_view usermsg, const std::source_location &sl)>;
|
||||
|
||||
// static void registerSink(std::string_view name, Sink sink);
|
||||
// static void unregisterSink(std::string_view name);
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
#include "zephyr.hpp"
|
||||
|
||||
namespace rims {
|
||||
K_MSGQ_DEFINE(messenger_buffer_arrived_queue, sizeof(rims::buffer), 2, 1);
|
||||
K_MSGQ_DEFINE(messenger_buffer_arrived_queue, sizeof(rims::BufferView), 2, 1);
|
||||
namespace {
|
||||
|
||||
bool crcIsInvalid(std::span<uint8_t> data, std::uint32_t crc) {
|
||||
@ -222,7 +222,7 @@ void MessengerThread::event_dataArrived() {
|
||||
std::span<uint8_t> submessage{};
|
||||
WireFormatID id{};
|
||||
uint32_t crc{};
|
||||
buffer buf;
|
||||
BufferView buf;
|
||||
|
||||
try {
|
||||
k_msgq_get(&messenger_buffer_arrived_queue, &buf, K_NO_WAIT);
|
||||
@ -493,8 +493,8 @@ void MessengerThread::putActiveRequest(WireFormatID wireId, uint32_t id, AsyncUA
|
||||
throw messenger::request_queue_full{};
|
||||
}
|
||||
|
||||
std::optional<MessengerThread::requestData> MessengerThread::takeActiveRequest(int wireId_receiver, uint32_t id) {
|
||||
std::optional<MessengerThread::requestData> ret{};
|
||||
std::optional<MessengerThread::RequestData> MessengerThread::takeActiveRequest(int wireId_receiver, uint32_t id) {
|
||||
std::optional<MessengerThread::RequestData> ret{};
|
||||
// find first of active type/requestId pair
|
||||
for (auto &req : _activeRequests) {
|
||||
if (req.wireId.receiver == wireId_receiver && req.requestId == id) {
|
||||
|
||||
@ -5,12 +5,13 @@
|
||||
#include "id.hpp"
|
||||
#include "proto/message.pb.h"
|
||||
|
||||
#include <span>
|
||||
#include <cstdint>
|
||||
|
||||
namespace rims {
|
||||
class AsyncUART;
|
||||
|
||||
struct buffer {
|
||||
struct BufferView {
|
||||
std::span<uint8_t> data;
|
||||
AsyncUART *device;
|
||||
};
|
||||
@ -28,7 +29,7 @@ class MessengerThread : public ZephyrThread {
|
||||
void threadMain() override;
|
||||
|
||||
private:
|
||||
struct requestData {
|
||||
struct RequestData {
|
||||
WireFormatID wireId; // original ID of IngressMessage
|
||||
uint32_t requestId; // requestID from message
|
||||
AsyncUART *cb;
|
||||
@ -53,10 +54,10 @@ class MessengerThread : public ZephyrThread {
|
||||
void egressPush(void *submessage, const pb_msgdesc_t &fields, int id, std::optional<uint32_t> requestId);
|
||||
|
||||
void putActiveRequest(WireFormatID wireId, uint32_t id, AsyncUART *cb);
|
||||
std::optional<requestData> takeActiveRequest(int type, uint32_t id);
|
||||
std::optional<RequestData> takeActiveRequest(int type, uint32_t id);
|
||||
|
||||
std::array<k_poll_event, 6> _events;
|
||||
std::array<requestData, 8> _activeRequests;
|
||||
std::array<RequestData, 8> _activeRequests;
|
||||
uint8_t _activeRequestsNr;
|
||||
};
|
||||
} // namespace rims
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "power_control.hpp"
|
||||
|
||||
#include "ring_buffer.hpp"
|
||||
#include "common.hpp"
|
||||
#include "log.hpp"
|
||||
#include "proto/ctrl.pb.h"
|
||||
@ -15,7 +14,6 @@
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
|
||||
|
||||
namespace rims {
|
||||
|
||||
namespace ctrl {
|
||||
@ -58,8 +56,8 @@ constexpr std::array<gpio_dt_spec, MaxChannels> pins = {
|
||||
|
||||
PhaseModulation::PhaseModulation(const gpio_dt_spec &gpio)
|
||||
: PinControlStrategyBase(gpio), //
|
||||
_triacTimerStart{[this]() { this->on(); }, std::chrono::milliseconds{0}},
|
||||
_triacTimerStop{[this]() { this->off(); }, std::chrono::milliseconds{0}} {
|
||||
_triacTimerStart{rims::function<void()>{[this]() { this->on(); }}, std::chrono::milliseconds{0}},
|
||||
_triacTimerStop{rims::function<void()>{[this]() { this->off(); }}, std::chrono::milliseconds{0}} {
|
||||
ULOG_INFO("PhaseModulation started for gpio %d", gpio.pin);
|
||||
}
|
||||
|
||||
@ -83,25 +81,24 @@ void PhaseModulation::zeroCrossDetectionTick(ZeroCrossDetectionEvent::Data data)
|
||||
// Calculate offset: higher power -> shorter delay, lower power -> longer delay
|
||||
// _power in percent
|
||||
const float clampedPower = std::clamp(_power, 0.0f, 100.0f);
|
||||
|
||||
|
||||
const auto usToNext = data.cycle_duration;
|
||||
|
||||
|
||||
const auto maxDelay = usToNext - minimalGatePulse - minimalLatchTime - minimalSafeMargin;
|
||||
const auto onDelay = std::min(delay(clampedPower, usToNext), maxDelay);
|
||||
|
||||
if (onDelay > maxDelay) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Start timer to turn triac ON at calculated phase delay
|
||||
// _triacTimerStart.fire_at(data.restored() + data.to_zcd + onDelay - minimalLatchTime);
|
||||
// Schedule triac to turn OFF shortly after firing (e.g., 100 us pulse)
|
||||
// _triacTimerStop.fire_at(data.restored() + data.to_zcd + onDelay + minimalGatePulse);
|
||||
// _triacTimerStop.setDuration(onDelay + minimalGatePulse);
|
||||
|
||||
|
||||
// // Start timer to turn triac ON at calculated phase delay
|
||||
_triacTimerStart.setDuration(onDelay+data.to_zcd);
|
||||
_triacTimerStart.setDuration(onDelay + data.to_zcd);
|
||||
_triacTimerStart.start();
|
||||
|
||||
// // Schedule triac to turn OFF shortly after firing (e.g., 100 us pulse)
|
||||
@ -362,7 +359,7 @@ void PhaseModulationOrchestrator::checkCurrentMode(const uint8_t channel, ModeOf
|
||||
|
||||
void PhaseModulationOrchestrator::setMode(uint8_t ch, ModeOfOperation mode) {
|
||||
checkChannel(ch);
|
||||
|
||||
|
||||
switch (mode) {
|
||||
case ctrl_ModeOfOperation_Disabled:
|
||||
_chModeOfOperationStorage[ch].emplace<DisabledMode>();
|
||||
@ -399,7 +396,7 @@ ModeOfOperation PhaseModulationOrchestrator::mode(uint8_t ch) {
|
||||
|
||||
void PhaseModulationOrchestrator::setPowerControlAlgorithm(uint8_t ch, PowerControlAlgorithm alg) {
|
||||
checkChannel(ch);
|
||||
|
||||
|
||||
switch (alg) {
|
||||
case ctrl_PowerControlAlgorithm_NoModulation:
|
||||
_chPowerControlStrategy[ch].emplace<NoModulation>();
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
/* Kernel event for notifying other threads */
|
||||
#include "ring_buffer.hpp"
|
||||
#include "common.hpp"
|
||||
#include "inplace_vector.hpp"
|
||||
#include "proto/ctrl.pb.h"
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@ -151,14 +150,14 @@ struct RingIndex {
|
||||
bool _full{false};
|
||||
};
|
||||
|
||||
template <class T, std::size_t N> class ring_buffer {
|
||||
template <class T, std::size_t N> class RingBuffer {
|
||||
public:
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
static_assert(std::is_trivially_destructible_v<T>);
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
|
||||
using value_type = T;
|
||||
explicit ring_buffer() : _index{N} {
|
||||
explicit RingBuffer() : _index{N} {
|
||||
}
|
||||
|
||||
T &push_back(const T &item) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "ring_buffer.hpp"
|
||||
#include "fifo_queue.hpp"
|
||||
#include "common.hpp"
|
||||
|
||||
#include "proto/temperature.pb.h"
|
||||
@ -82,7 +82,7 @@ class TemperatureSampler {
|
||||
zephyr::semaphore::sem _broadcastSem{0, 1};
|
||||
RecurringSemaphoreTimer _broadcastTimer{_broadcastSem, std::chrono::seconds{60}};
|
||||
|
||||
ring_buffer<adc_sample, MaxSampleSize> _samples;
|
||||
RingBuffer<adc_sample, MaxSampleSize> _samples;
|
||||
// number of samples taken to filter
|
||||
std::uint8_t _samplesNumber{MaxSampleSize};
|
||||
|
||||
|
||||
@ -196,7 +196,7 @@ uint8_t AsyncUART::rxByte() {
|
||||
}
|
||||
|
||||
void AsyncUART::processMessage() {
|
||||
buffer buf{.data = {rxBuffer().data(), rxBuffer().size()}, .device = this};
|
||||
BufferView buf{.data = {rxBuffer().data(), rxBuffer().size()}, .device = this};
|
||||
switchRxBuffer();
|
||||
k_msgq_put(&messenger_buffer_arrived_queue, &buf, K_NO_WAIT);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ class uart_rx_not_ready_error;
|
||||
|
||||
class AsyncUART {
|
||||
using rx_buffer_t = beman::inplace_vector<uint8_t, 256>;
|
||||
using tx_buffer_t = ring_buffer<uint8_t, 256>;
|
||||
using tx_buffer_t = RingBuffer<uint8_t, 256>;
|
||||
|
||||
public:
|
||||
AsyncUART();
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "zephyr/drivers/adc.h"
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <source_location>
|
||||
#include <span>
|
||||
|
||||
#include <zephyr/drivers/adc.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/crc.h>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
/* Kernel event for notifying other threads */
|
||||
#include "ring_buffer.hpp"
|
||||
#include "common.hpp"
|
||||
#include "fifo_queue.hpp"
|
||||
#include "zephyr.hpp"
|
||||
|
||||
#include <chrono>
|
||||
@ -16,8 +16,8 @@ struct ZeroCrossDetectionEvent {
|
||||
return clock::time_point{std::chrono::nanoseconds{time_point}};
|
||||
}
|
||||
void store_now() {
|
||||
auto now = clock::now();
|
||||
time_point = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
|
||||
auto now = clock::now();
|
||||
time_point = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
|
||||
}
|
||||
uint64_t time_point; // timepoint
|
||||
microseconds_u16_t cycle_duration;
|
||||
@ -52,14 +52,21 @@ class ZeroCrossDetection {
|
||||
zephyr::semaphore::sem _intCheckSem;
|
||||
RecurringSemaphoreTimer _intCheckTimer;
|
||||
|
||||
clock::time_point _pulseDown{};
|
||||
rims::ring_buffer<microseconds_u16_t, 20> _pulsWidths;
|
||||
rims::ring_buffer<microseconds_u16_t, 20> _cyclesWidths;
|
||||
clock::time_point _pulseDown{};
|
||||
rims::RingBuffer<microseconds_u16_t, 20> _pulsWidths;
|
||||
rims::RingBuffer<microseconds_u16_t, 20> _cyclesWidths;
|
||||
};
|
||||
|
||||
class ZeroCrossDetectionOrchestrator {
|
||||
public:
|
||||
ZeroCrossDetectionOrchestrator();
|
||||
|
||||
ZeroCrossDetectionOrchestrator(const ZeroCrossDetectionOrchestrator &) = delete;
|
||||
ZeroCrossDetectionOrchestrator &operator=(const ZeroCrossDetectionOrchestrator &) = delete;
|
||||
|
||||
ZeroCrossDetectionOrchestrator(ZeroCrossDetectionOrchestrator &&) = delete;
|
||||
ZeroCrossDetectionOrchestrator &operator=(ZeroCrossDetectionOrchestrator &&) = delete;
|
||||
|
||||
void loop();
|
||||
|
||||
void event_zcdCheck(ZeroCrossDetection &channel);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user