forked from EmbeddedTeam/app_photomagnetic
- Remove heating and NTC functionality from communication module - Convert Infrared from template to runtime array-based implementation - Refactor Led to support multiple LEDs with compile-time name validation - Simplify main to remove direct hardware initialization - Update west manifest for dr2501a board and add ch9438 module
97 lines
3.0 KiB
C++
97 lines
3.0 KiB
C++
#ifndef __THER_LED_HPP__
|
|
#define __THER_LED_HPP__
|
|
#include <etl/algorithm.h>
|
|
#include <etl/array.h>
|
|
#include <zephyr/drivers/led.h>
|
|
#include <zpp/ct_string.hpp>
|
|
#include <zpp/work_queue.hpp>
|
|
namespace ther {
|
|
|
|
/* Compile-time check: every LED name must be distinct so that
|
|
* Led::On/Off/Flash<kName> name lookup stays unambiguous. */
|
|
template <typename T, std::size_t N>
|
|
consteval auto AreUniqueNames(const etl::array<T, N> &names) -> bool {
|
|
for (std::size_t i = 0; i < N; ++i) {
|
|
for (std::size_t j = i + 1; j < N; ++j) {
|
|
if (names[i] == names[j]) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#define LED_SPEC(node) led_dt_spec LED_DT_SPEC_GET(node)
|
|
#define LED_DEV_CHILD_SPEC(node) DT_FOREACH_CHILD_SEP(node, LED_SPEC, (, )),
|
|
#define LED_NODE_NAME(node) DT_FOREACH_CHILD_SEP(node, DEVICE_DT_NAME, (, ))
|
|
class Led {
|
|
|
|
private:
|
|
template <led_dt_spec> struct Periodic {
|
|
static auto Flash(led_dt_spec *spec) -> void {
|
|
bool flag = false;
|
|
if (flag) {
|
|
led_on_dt(spec);
|
|
} else {
|
|
led_off_dt(spec);
|
|
}
|
|
flag = !flag;
|
|
}
|
|
static inline zpp::periodic_work<led_dt_spec *> work{Flash};
|
|
};
|
|
|
|
public:
|
|
template <zpp::ct_string kName> static auto On() -> zpp::error {
|
|
static_assert(IsDeviceName<kName>());
|
|
const auto id = etl::find(s_led_node_name.begin(), s_led_node_name.end(),
|
|
std::string_view(kName)) -
|
|
s_led_node_name.begin();
|
|
return led_on_dt(&s_led_dev[id]);
|
|
}
|
|
template <zpp::ct_string kName> static auto Off() -> zpp::error {
|
|
static_assert(IsDeviceName<kName>());
|
|
const auto id = etl::find(s_led_node_name.begin(), s_led_node_name.end(),
|
|
std::string_view(kName)) -
|
|
s_led_node_name.begin();
|
|
return led_off_dt(&s_led_dev[id]);
|
|
}
|
|
template <zpp::ct_string kName, typename TRep, typename TPeriod>
|
|
static auto Flash(std::chrono::duration<TRep, TPeriod> period) {
|
|
static_assert(IsDeviceName<kName>());
|
|
const auto id = etl::find(s_led_node_name.begin(), s_led_node_name.end(),
|
|
std::string_view(kName)) -
|
|
s_led_node_name.begin();
|
|
Periodic<s_led_dev[id]>::work.submit(period);
|
|
}
|
|
|
|
private:
|
|
template <zpp::ct_string kName> static consteval auto IsDeviceName() {
|
|
for (size_t i = 0; i < s_led_node_name.size(); ++i) {
|
|
if (s_led_node_name[i] == std::string_view(kName)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static auto Flash(led_dt_spec *spec) -> void {
|
|
static bool flag = false;
|
|
if (flag) {
|
|
led_off_dt(spec);
|
|
} else {
|
|
led_on_dt(spec);
|
|
}
|
|
flag = !flag;
|
|
}
|
|
inline static constexpr etl::array s_led_dev{
|
|
DT_FOREACH_STATUS_OKAY(gpio_leds, LED_DEV_CHILD_SPEC)};
|
|
inline static constexpr auto s_led_node_name =
|
|
etl::make_array<std::string_view>(
|
|
DT_FOREACH_STATUS_OKAY(gpio_leds, LED_NODE_NAME));
|
|
static_assert(AreUniqueNames(s_led_node_name),
|
|
"LED node names must be unique");
|
|
};
|
|
|
|
} // namespace ther
|
|
#endif
|