@brief I2S LCD_CAM-based channel driver for parallel LED control on ESP32-S3 Implements IChannelDriver interface using ESP32-S3 LCD_CAM peripheral for LED data transmission. Uses dependency injection pattern for testability. ## Architecture - **Peripheral abstraction**: Uses II2sLcdCamPeripheral* for hardware delegation - **Transpose encoding**: Efficient bit-parallel waveform generation - **Mul
| 107 | /// DRAINING → poll() → READY (transmission complete) |
| 108 | /// ``` |
| 109 | class ChannelEngineI2S : public IChannelDriver { |
| 110 | public: |
| 111 | /// @brief Constructor with dependency injection |
| 112 | /// @param peripheral I2S LCD_CAM peripheral instance (real or mock) |
| 113 | /// |
| 114 | /// Stores a shared pointer to the peripheral to maintain proper lifetime. |
| 115 | /// The peripheral will remain valid for the lifetime of this driver. |
| 116 | explicit ChannelEngineI2S(fl::shared_ptr<detail::II2sLcdCamPeripheral> peripheral) FL_NOEXCEPT; |
| 117 | |
| 118 | /// @brief Destructor - waits for transmission completion |
| 119 | ~ChannelEngineI2S() override; |
| 120 | |
| 121 | /// @brief Check if driver can handle channel data (clockless only) |
| 122 | /// @param data Channel data to check |
| 123 | /// @return true if clockless channel (rejects SPI), false otherwise |
| 124 | bool canHandle(const ChannelDataPtr& data) const FL_NOEXCEPT override; |
| 125 | |
| 126 | /// @brief Enqueue channel data for transmission |
| 127 | /// @param channelData Channel data to transmit |
| 128 | /// |
| 129 | /// Adds channel to internal queue. Transmission happens when show() is called. |
| 130 | void enqueue(ChannelDataPtr channelData) FL_NOEXCEPT override; |
| 131 | |
| 132 | /// @brief Trigger transmission of enqueued data |
| 133 | /// |
| 134 | /// Groups channels by timing configuration and begins transmission of |
| 135 | /// first group. Subsequent groups transmit sequentially via poll(). |
| 136 | void show() FL_NOEXCEPT override; |
| 137 | |
| 138 | /// @brief Query driver state and perform maintenance |
| 139 | /// @return Current driver state (READY, BUSY, DRAINING, or ERROR) |
| 140 | /// |
| 141 | /// Must be called regularly to: |
| 142 | /// - Check transmission completion status |
| 143 | /// - Trigger sequential chipset group transmissions |
| 144 | /// - Clean up completed transmissions |
| 145 | DriverState poll() FL_NOEXCEPT override; |
| 146 | |
| 147 | void setPollNeededCallback(PollNeededCallback callback) FL_NOEXCEPT override; |
| 148 | |
| 149 | /// @brief Get the driver name for affinity binding |
| 150 | /// @return "I2S" |
| 151 | fl::string getName() const FL_NOEXCEPT override { return fl::string::from_literal("I2S"); } |
| 152 | |
| 153 | /// @brief Get driver capabilities (CLOCKLESS protocols only) |
| 154 | /// @return Capabilities with supportsClockless=true, supportsSpi=false |
| 155 | Capabilities getCapabilities() const FL_NOEXCEPT override { |
| 156 | return Capabilities(true, false); // Clockless only |
| 157 | } |
| 158 | |
| 159 | private: |
| 160 | /// @brief Begin LED data transmission for current chipset group |
| 161 | /// @param channelData Span of channel data to transmit |
| 162 | /// @return true if transmission started successfully, false on error |
| 163 | /// |
| 164 | /// This method: |
| 165 | /// 1. Validates channel data |
| 166 | /// 2. Initializes LCD_CAM peripheral if needed |
nothing calls this directly
no test coverage detected