Initialize hardware.
77 {
79 return fl::task::Error("Device not initialized");
80 }
81
82 if (
pImpl->initialized) {
83
85 }
86
87 size_t num_lanes =
pImpl->config.data_pins.size();
88
89
90 if (num_lanes < 1 || num_lanes > 8) {
91 return fl::task::Error("Invalid number of lanes (must be 1-8)");
92 }
93
94
95 if (num_lanes == 1) {
96
97 const auto& controllers = SpiHw1::getAll();
98 if (controllers.empty()) {
99 FL_WARN(
"MultiLaneDevice: No Single-SPI hardware available");
100 return fl::task::Error("Single-SPI hardware not available");
101 }
102
103
104 fl::shared_ptr<SpiHw1> hw;
105 for (const auto& ctrl : controllers) {
106 if (!ctrl->isInitialized()) {
107 hw = ctrl;
108 break;
109 }
110 }
111
112 if (!hw) {
113 FL_WARN(
"MultiLaneDevice: All Single-SPI controllers in use");
114 return fl::task::Error("All Single-SPI controllers already in use");
115 }
116
117
118 SpiHw1::Config hw_config;
119 hw_config.bus_num =
static_cast<u8>(hw->getBusId());
120 hw_config.clock_speed_hz =
pImpl->config.clock_speed_hz;
121 hw_config.clock_pin =
pImpl->config.clock_pin;
122 hw_config.data_pin =
pImpl->config.data_pins[0];
123
124 if (!hw->begin(hw_config)) {
125 FL_WARN(
"MultiLaneDevice: Failed to initialize Single-SPI hardware");
126 return fl::task::Error("Failed to initialize Single-SPI hardware");
127 }
128
130 pImpl->backend_type = 1;
131 FL_DBG(
"MultiLaneDevice: Initialized Single-SPI (" << hw->getName() <<
")");
132
133 } else if (num_lanes == 2) {
134
135 const auto& controllers = SpiHw2::getAll();
136 if (controllers.empty()) {
137 FL_WARN(
"MultiLaneDevice: No Dual-SPI hardware available");
138 return fl::task::Error("Dual-SPI hardware not available");
139 }
140
141
142 fl::shared_ptr<SpiHw2> hw;
143 for (const auto& ctrl : controllers) {
144 if (!ctrl->isInitialized()) {
145 hw = ctrl;
146 break;
147 }
148 }
149
150 if (!hw) {
151 FL_WARN(
"MultiLaneDevice: All Dual-SPI controllers in use");
152 return fl::task::Error("All Dual-SPI controllers already in use");
153 }
154
155
156 SpiHw2::Config hw_config;
157 hw_config.bus_num =
static_cast<u8>(hw->getBusId());
158 hw_config.clock_speed_hz =
pImpl->config.clock_speed_hz;
159 hw_config.clock_pin =
pImpl->config.clock_pin;
160 hw_config.data0_pin =
pImpl->config.data_pins[0];
161 hw_config.data1_pin =
pImpl->config.data_pins[1];
162
163 if (!hw->begin(hw_config)) {
164 FL_WARN(
"MultiLaneDevice: Failed to initialize Dual-SPI hardware");
165 return fl::task::Error("Failed to initialize Dual-SPI hardware");
166 }
167
169 pImpl->backend_type = 2;
170 FL_DBG(
"MultiLaneDevice: Initialized Dual-SPI (" << hw->getName() <<
")");
171
172 } else if (num_lanes >= 3 && num_lanes <= 4) {
173
174 const auto& controllers = SpiHw4::getAll();
175 if (controllers.empty()) {
176 FL_WARN(
"MultiLaneDevice: No Quad-SPI hardware available");
177 return fl::task::Error("Quad-SPI hardware not available");
178 }
179
180
181 fl::shared_ptr<SpiHw4> hw;
182 for (const auto& ctrl : controllers) {
183 if (!ctrl->isInitialized()) {
184 hw = ctrl;
185 break;
186 }
187 }
188
189 if (!hw) {
190 FL_WARN(
"MultiLaneDevice: All Quad-SPI controllers in use");
191 return fl::task::Error("All Quad-SPI controllers already in use");
192 }
193
194
195 SpiHw4::Config hw_config;
196 hw_config.bus_num =
static_cast<u8>(hw->getBusId());
197 hw_config.clock_speed_hz =
pImpl->config.clock_speed_hz;
198 hw_config.clock_pin =
pImpl->config.clock_pin;
199 hw_config.data0_pin =
pImpl->config.data_pins[0];
200 hw_config.data1_pin = (num_lanes > 1) ?
pImpl->config.data_pins[1] : -1;
201 hw_config.data2_pin = (num_lanes > 2) ?
pImpl->config.data_pins[2] : -1;
202 hw_config.data3_pin = (num_lanes > 3) ?
pImpl->config.data_pins[3] : -1;
203
204 if (!hw->begin(hw_config)) {
205 FL_WARN(
"MultiLaneDevice: Failed to initialize Quad-SPI hardware");
206 return fl::task::Error("Failed to initialize Quad-SPI hardware");
207 }
208
210 pImpl->backend_type = 4;
211 FL_DBG(
"MultiLaneDevice: Initialized Quad-SPI (" << hw->getName() <<
")");
212
213 } else if (num_lanes >= 5 && num_lanes <= 8) {
214
215 const auto& controllers = SpiHw8::getAll();
216 if (controllers.empty()) {
217 FL_WARN(
"MultiLaneDevice: No Octal-SPI hardware available");
218 return fl::task::Error("Octal-SPI hardware not available");
219 }
220
221
222 fl::shared_ptr<SpiHw8> hw;
223 for (const auto& ctrl : controllers) {
224 if (!ctrl->isInitialized()) {
225 hw = ctrl;
226 break;
227 }
228 }
229
230 if (!hw) {
231 FL_WARN(
"MultiLaneDevice: All Octal-SPI controllers in use");
232 return fl::task::Error("All Octal-SPI controllers already in use");
233 }
234
235
236 SpiHw8::Config hw_config;
237 hw_config.bus_num =
static_cast<u8>(hw->getBusId());
238 hw_config.clock_speed_hz =
pImpl->config.clock_speed_hz;
239 hw_config.clock_pin =
pImpl->config.clock_pin;
240 hw_config.data0_pin =
pImpl->config.data_pins[0];
241 hw_config.data1_pin = (num_lanes > 1) ?
pImpl->config.data_pins[1] : -1;
242 hw_config.data2_pin = (num_lanes > 2) ?
pImpl->config.data_pins[2] : -1;
243 hw_config.data3_pin = (num_lanes > 3) ?
pImpl->config.data_pins[3] : -1;
244 hw_config.data4_pin = (num_lanes > 4) ?
pImpl->config.data_pins[4] : -1;
245 hw_config.data5_pin = (num_lanes > 5) ?
pImpl->config.data_pins[5] : -1;
246 hw_config.data6_pin = (num_lanes > 6) ?
pImpl->config.data_pins[6] : -1;
247 hw_config.data7_pin = (num_lanes > 7) ?
pImpl->config.data_pins[7] : -1;
248
249 if (!hw->begin(hw_config)) {
250 FL_WARN(
"MultiLaneDevice: Failed to initialize Octal-SPI hardware");
251 return fl::task::Error("Failed to initialize Octal-SPI hardware");
252 }
253
255 pImpl->backend_type = 8;
256 FL_DBG(
"MultiLaneDevice: Initialized Octal-SPI (" << hw->getName() <<
")");
257 }
258
259 pImpl->initialized =
true;
261}
fl::unique_ptr< Impl > pImpl
constexpr nullopt_t nullopt