#pragma once #include #include #include #include namespace interrupt { template concept nexus_for_cfg = Config::template has_flows_for; template ... Nexi> struct irq_impl : Config { constexpr static bool active = Config::template active; static auto init_mcu_interrupts() -> void { Config::template enable(); } [[nodiscard]] static auto get_interrupt_enables() -> stdx::tuple<> { return {}; } static auto run() -> void { if constexpr (active) { using status_policy_t = typename Config::status_policy_t; hal::run(Config::irq_number, [] { Config::template isr(); }); } } }; template ... Nexi> struct sub_irq_impl : Config { constexpr static bool active = Config::template active; using Config::enable_field; using Config::status_field; [[nodiscard]] static auto get_interrupt_enables() { if constexpr (active) { return stdx::make_tuple(enable_field); } else { return stdx::tuple{}; } } static auto run() -> void { if constexpr (active) { using status_policy_t = typename Config::status_policy_t; if (apply(read(enable_field)) && apply(read(status_field))) { status_policy_t::run([&] { apply(clear(status_field)); }, [&] { Config::template isr(); }); } } } }; template struct shared_irq_impl : Config { constexpr static bool active = (Subs::active or ...); static auto init_mcu_interrupts() -> void { Config::template enable(); } [[nodiscard]] static auto get_interrupt_enables() { return stdx::tuple_cat(Subs::get_interrupt_enables()...); } static auto run() -> void { if constexpr (active) { using status_policy_t = typename Config::status_policy_t; hal::run(Config::irq_number, [] { (Subs::run(), ...); }); } } }; template struct shared_sub_irq_impl : Config { constexpr static bool active = (Subs::active or ...); using Config::enable_field; using Config::status_field; [[nodiscard]] static auto get_interrupt_enables() { if constexpr (active) { return stdx::tuple_cat(stdx::make_tuple(enable_field), Subs::get_interrupt_enables()...); } else { return stdx::tuple{}; } } static auto run() -> void { if constexpr (active) { using status_policy_t = typename Config::status_policy_t; if (apply(read(enable_field)) && apply(read(status_field))) { status_policy_t::run([&] { apply(clear(status_field)); }, [&] { (Subs::run(), ...); }); } } } }; } // namespace interrupt