| 301 | /// @tparam Chipset One of `fl::ClocklessChipset` or `fl::SpiChipsetConfig`. |
| 302 | template<typename Chipset> |
| 303 | struct ChannelConfigOf { |
| 304 | /// @brief Construct from a typed chipset, LEDs span, and optional metadata. |
| 305 | ChannelConfigOf(const Chipset& chipset, fl::span<CRGB> leds, |
| 306 | EOrder rgbOrder = RGB, |
| 307 | const ChannelOptions& options = ChannelOptions()) FL_NOEXCEPT |
| 308 | : chipset(chipset), mLeds(leds), rgb_order(rgbOrder), options(options) {} |
| 309 | |
| 310 | /// @brief Named-channel constructor. |
| 311 | ChannelConfigOf(const fl::string& name, const Chipset& chipset, |
| 312 | fl::span<CRGB> leds, EOrder rgbOrder = RGB, |
| 313 | const ChannelOptions& options = ChannelOptions()) FL_NOEXCEPT |
| 314 | : chipset(chipset), mLeds(leds), rgb_order(rgbOrder), options(options), mName(name) {} |
| 315 | |
| 316 | /// @brief Implicit conversion to the type-erased `ChannelConfig` so the |
| 317 | /// existing non-template `Channel::create()` factory accepts a |
| 318 | /// templated config without any per-call-site change. |
| 319 | operator ChannelConfig() const FL_NOEXCEPT { |
| 320 | ChannelConfig cfg(chipset, mLeds, rgb_order, options); |
| 321 | cfg.mScreenMap = mScreenMap; |
| 322 | if (mName.has_value()) { |
| 323 | cfg.mName = mName; |
| 324 | } |
| 325 | return cfg; |
| 326 | } |
| 327 | |
| 328 | /// @brief Convenience: build the erased form by value (handy in templates |
| 329 | /// where the implicit conversion is suppressed by overload rules). |
| 330 | ChannelConfig toErased() const FL_NOEXCEPT { return static_cast<ChannelConfig>(*this); } |
| 331 | |
| 332 | // ---- Data members (mirror ChannelConfig, but with typed `chipset`) ---- |
| 333 | |
| 334 | /// Typed chipset configuration. No variant -- the `Chipset` template |
| 335 | /// parameter is the source of truth. |
| 336 | Chipset chipset; |
| 337 | |
| 338 | /// LED data span. |
| 339 | fl::span<CRGB> mLeds; |
| 340 | |
| 341 | /// RGB channel ordering. |
| 342 | EOrder rgb_order = RGB; |
| 343 | |
| 344 | /// Optional channel settings (correction, temperature, dither, rgbw, affinity). |
| 345 | ChannelOptions options; |
| 346 | |
| 347 | /// Screen mapping (for JS canvas visualization). |
| 348 | fl::ScreenMap mScreenMap; |
| 349 | |
| 350 | /// Optional user-specified name. If unset, `Channel` auto-generates one. |
| 351 | fl::optional<fl::string> mName; |
| 352 | }; |
| 353 | |
| 354 | /// @brief Multi-channel LED configuration |
| 355 | /// |