| 76 | } |
| 77 | |
| 78 | fl::optional<fl::task::Error> MultiLaneDevice::begin() { |
| 79 | if (!pImpl) { |
| 80 | return fl::task::Error("Device not initialized"); |
| 81 | } |
| 82 | |
| 83 | if (pImpl->initialized) { |
| 84 | // Already initialized - idempotent |
| 85 | return fl::nullopt; |
| 86 | } |
| 87 | |
| 88 | size_t num_lanes = pImpl->config.data_pins.size(); |
| 89 | |
| 90 | // Validate lane count |
| 91 | if (num_lanes < 1 || num_lanes > 8) { |
| 92 | return fl::task::Error("Invalid number of lanes (must be 1-8)"); |
| 93 | } |
| 94 | |
| 95 | // Auto-select appropriate hardware backend based on lane count |
| 96 | if (num_lanes == 1) { |
| 97 | // Try Single-SPI (SpiHw1) |
| 98 | const auto& controllers = SpiHw1::getAll(); |
| 99 | if (controllers.empty()) { |
| 100 | FL_WARN("MultiLaneDevice: No Single-SPI hardware available"); |
| 101 | return fl::task::Error("Single-SPI hardware not available"); |
| 102 | } |
| 103 | |
| 104 | // Find first available controller |
| 105 | fl::shared_ptr<SpiHw1> hw; |
| 106 | for (const auto& ctrl : controllers) { |
| 107 | if (!ctrl->isInitialized()) { |
| 108 | hw = ctrl; |
| 109 | break; |
| 110 | } |
| 111 | } |
| 112 | |
| 113 | if (!hw) { |
| 114 | FL_WARN("MultiLaneDevice: All Single-SPI controllers in use"); |
| 115 | return fl::task::Error("All Single-SPI controllers already in use"); |
| 116 | } |
| 117 | |
| 118 | // Configure Single-SPI |
| 119 | SpiHw1::Config hw_config; |
| 120 | hw_config.bus_num = static_cast<u8>(hw->getBusId()); |
| 121 | hw_config.clock_speed_hz = pImpl->config.clock_speed_hz; |
| 122 | hw_config.clock_pin = pImpl->config.clock_pin; |
| 123 | hw_config.data_pin = pImpl->config.data_pins[0]; |
| 124 | |
| 125 | if (!hw->begin(hw_config)) { |
| 126 | FL_WARN("MultiLaneDevice: Failed to initialize Single-SPI hardware"); |
| 127 | return fl::task::Error("Failed to initialize Single-SPI hardware"); |
| 128 | } |
| 129 | |
| 130 | pImpl->backend = hw; |
| 131 | pImpl->backend_type = 1; |
| 132 | FL_DBG("MultiLaneDevice: Initialized Single-SPI (" << hw->getName() << ")"); |
| 133 | |
| 134 | } else if (num_lanes == 2) { |
| 135 | // Try Dual-SPI (SpiHw2) |