339 {
340 if (channels.
empty()) {
341 return true;
342 }
343
344
345 const auto& chipset = channels[0]->getChipset();
346 if (!chipset.is<SpiChipsetConfig>()) {
347 FL_WARN(
"SpiChannelEngineAdapter: Non-SPI chipset in transmitBatch");
348 return false;
349 }
350
351 const SpiChipsetConfig& spiConfig = chipset.get<SpiChipsetConfig>();
352 int clockPin = spiConfig.clockPin;
353 int dataPin = channels[0]->getPin();
354
355
357 if (controllerIndex < 0) {
358 FL_WARN(
"SpiChannelEngineAdapter: No available controller for clock pin " << clockPin);
359 return false;
360 }
361
363
364
366 return false;
367 }
368
369
370 for (const auto& channel : channels) {
371 if (!channel) {
372 continue;
373 }
374
375
376 channel->setInUse(true);
377
378
379 const auto& data = channel->getData();
380 if (data.empty()) {
381 FL_WARN(
"SpiChannelEngineAdapter: Empty channel data");
382 channel->setInUse(false);
383 continue;
384 }
385
386 FL_DBG(
"SpiChannelEngineAdapter: Transmitting channel via " << ctrl.name <<
" (pin " << channel->getPin() <<
", " << data.size() <<
" bytes)");
387
388
389 DMABuffer dmaBuffer = ctrl.controller->acquireDMABuffer(data.size());
390 if (!dmaBuffer.ok()) {
391 FL_WARN(
"SpiChannelEngineAdapter: Failed to acquire DMA buffer (error " << (
static_cast<int>(dmaBuffer.error())) <<
")");
392 channel->setInUse(false);
393 return false;
394 }
395
396
397 fl::span<u8> buffer = dmaBuffer.data();
398 if (buffer.
size() < data.size()) {
399 FL_WARN(
"SpiChannelEngineAdapter: DMA buffer too small (" << buffer.
size() <<
" < " << data.size() <<
")");
400 channel->setInUse(false);
401 return false;
402 }
403
405
406
407 if (!ctrl.controller->transmit(TransmitMode::ASYNC)) {
408 FL_WARN(
"SpiChannelEngineAdapter: Transmission failed");
409 channel->setInUse(false);
410 return false;
411 }
412
413 FL_DBG(
"SpiChannelEngineAdapter: Transmission queued successfully");
414 }
415
416
417
418 if (!ctrl.controller->waitComplete(1000)) {
419 FL_WARN(
"SpiChannelEngineAdapter: Transmission timeout");
420 return false;
421 }
422
423 FL_DBG(
"SpiChannelEngineAdapter: Batch transmission complete");
424 return true;
425}
fl::vector< ControllerInfo > mControllers
All managed controllers.
int selectControllerForClockPin(int clockPin, Esp32SpiBus requestedBus) FL_NO_EXCEPT
Select best controller for a given clock pin.
bool initializeControllerIfNeeded(ControllerInfo &ctrl, int clockPin, int dataPin) FL_NO_EXCEPT
Initialize controller if needed for this clock pin.
constexpr bool empty() const FL_NO_EXCEPT
const T * data() const FL_NO_EXCEPT
constexpr fl::size size() const FL_NO_EXCEPT
FASTLED_FORCE_INLINE void * memcpy(void *dest, const void *src, size_t n) FL_NO_EXCEPT
Information about a registered SPI hardware controller.