REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
redac.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3//
4// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
5
6#include "redac/calibration.h"
7#include "utils/timer.h"
8
9
10#include <redac/redac.h>
11#include <utils/logging.h>
12
13blocks::TBlockBackplane *platform::REDAC::init_backpanel_tblock(uint8_t baddr, const char *name) {
14 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
15
16 LOG(ANABRID_DEBUG_INIT, utils::small_sprintf("Detecting Backpanel %s Block...", name).c_str());
17 blocks::TBlockBackplane *t_block = entities::detect<blocks::TBlockBackplane>(bus::address_from_tuple(baddr, 0));
18 if (!t_block) {
19 LOG(ANABRID_DEBUG_INIT, "Warning: The backplane T block is missing or unknown...");
20 return nullptr;
21 }
22
23 LOG(ANABRID_DEBUG_INIT, "Initializing the backplane T Block...");
24 t_block->rename_entity(name); // otherwise it appears wrong in the entity tree
25 auto t_block_result = t_block->init();
26 if (!t_block_result) {
27 LOG(ANABRID_DEBUG_INIT, "Backplane T-Block Failed");
28 LOG(ANABRID_DEBUG_INIT, t_block_result.err_value().c_str());
29 return nullptr;
30 }
31
32 LOG(ANABRID_DEBUG_INIT, "Backplane T-Block initialized.");
33 return t_block;
34}
35
36UnitResult platform::REDAC::init() {
37 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
38 TRY(Carrier::init());
39 routing.init(entity_id);
40
41 // Read BP identifier from hardware
42 bp_identifier = BackPanelIdentifier(hardware->read_backplane_and_slot_id());
43
44 // Detect T-block
45 if (!carrier_t_block) {
46 LOG(ANABRID_DEBUG_INIT, "Detecting Carrier T-Block...");
47 carrier_t_block = entities::detect<blocks::TBlock>(bus::address_from_tuple(bus::CARRIER_T_BLOCK_BADDR, 0));
48 if (!carrier_t_block) {
49 LOG(ANABRID_DEBUG_INIT, "Warning: Carrier T-Block is missing or unknown.");
50 } else {
51 LOG(ANABRID_DEBUG_INIT, "Initializing Carrier T-Block...");
52 TRY(carrier_t_block->init());
53 LOG(ANABRID_DEBUG_INIT, "Carrier T-Block initialized.");
54 }
55 }
56 if (!back_panel) {
57 LOG(ANABRID_DEBUG_INIT, "Detecting back panel...");
58 back_panel = entities::detect<platform::REDACBackPanel>(bus::address_from_tuple(bus::BACKPLANE_BADDR, 0));
59 if (!back_panel)
60 LOG(ANABRID_DEBUG_INIT, "Warning: Back panel is missing or unknown.");
61 }
62
63 if (!stack_t0_block)
64 stack_t0_block = init_backpanel_tblock(bus::BPL_T0_BLOCK_BADDR, platform::REDAC::STACK_T0_NAME);
65 if (!stack_t1_block)
66 stack_t1_block = init_backpanel_tblock(bus::BPL_T1_BLOCK_BADDR, platform::REDAC::STACK_T1_NAME);
67 if (!stack_t2_block)
68 stack_t2_block = init_backpanel_tblock(bus::BPL_T2_BLOCK_BADDR, platform::REDAC::STACK_T2_NAME);
69
70 return UnitResult::ok();
71}
72
73platform::REDAC::REDAC(REDAC_HAL *hardware) : Carrier({Cluster(0), Cluster(1), Cluster(2)}, hardware), hardware(hardware) {}
74
75platform::BackPanelIdentifier platform::REDAC::get_back_panel_identifier() const { return bp_identifier; }
76
77void platform::REDAC::reset(entities::ResetAction action) {
78 Carrier::reset(action);
79
80 for (auto *t_block : get_all_tblocks())
81 if (t_block)
82 t_block->reset(action);
83
84 hardware->reset_adc_bus_mux();
85}
86
87void platform::REDAC::power_up() { hardware->set_standby(false); }
88
89void platform::REDAC::power_down() { hardware->set_standby(true); }
90
91UnitResult platform::REDAC::write_to_hardware() {
92 TRY(Carrier::write_to_hardware());
93
94 for (auto t_block : get_all_tblocks()) {
95 if (!t_block) continue;
96 TRY(t_block->write_to_hardware());
97 }
98
99 return UnitResult::ok();
100}
101
102UnitResult platform::REDAC::route_cross_cluster(uint8_t start_cluster, uint8_t end_cluster, uint8_t u_in, uint8_t u_out, float c_factor, uint8_t i_out) {
103 if (start_cluster > 2 || end_cluster > 2)
104 return UnitResult::err("Invalid cluster indices. Valid ranges are 0 to 2");
105
106 if (u_out < 8)
107 return UnitResult::err("Can not connect a lane lower then 8 across multiple clusters");
108
109 auto *ublock = clusters[start_cluster].ublock;
110 auto *cblock = clusters[start_cluster].cblock;
111 auto *iblock = clusters[end_cluster].iblock;
112
113 // Connect different clusters together
114 carrier_t_block->connect(static_cast<blocks::TBlock::Sector>(start_cluster + 1), static_cast<blocks::TBlock::Sector>(end_cluster + 1), u_out - 8);
115
116 if (fabs(c_factor) > 1.0f) {
117 c_factor = c_factor / 8.0f;
118 iblock->set_upscaling(u_out, true);
119 } else
120 iblock->set_upscaling(u_out, false);
121
122 TRY(ublock->connect(u_in, u_out));
123 TRY(cblock->set_factor(u_out, c_factor));
124 TRY(iblock->connect(u_out, i_out));
125 return UnitResult::ok();
126}
127
128UnitResult platform::REDAC::route_to_backplane(uint8_t start_cluster, uint8_t u_in, uint8_t u_out, float c_factor) {
129 if (start_cluster > 2)
130 return UnitResult::err("Invalid cluster index. Valid ranges are 0 to 2");
131
132 if (u_out < 8)
133 return UnitResult::err("Can not connect a lane lower then 8 to backplane");
134
135 auto *ublock = clusters[start_cluster].ublock;
136 auto *cblock = clusters[start_cluster].cblock;
137
138 carrier_t_block->connect(static_cast<blocks::TBlock::Sector>(start_cluster + 1), blocks::TBlock::Sector::BPL, u_out - 8);
139
140 if (!ublock->connect(u_in, u_out))
141 return UnitResult::err("U block connection not possible");
142 if (!cblock->set_factor(u_out, c_factor))
143 return UnitResult::err("C block configuration not possible, remember there is no automatic upscaling");
144 return UnitResult::ok();
145}
146
147UnitResult platform::REDAC::route_from_backplane(uint8_t end_cluster, uint8_t i_in, uint8_t i_out) {
148 if (end_cluster > 2)
149 return UnitResult::err("Invalid cluster index. Valid ranges are 0 to 2");
150
151 if (i_in < 8)
152 return UnitResult::err("Can not connect a lane lower then 8 to backplane");
153
154 auto *iblock = clusters[end_cluster].iblock;
155
156 carrier_t_block->connect(blocks::TBlock::Sector::BPL, static_cast<blocks::TBlock::Sector>(end_cluster + 1), i_in - 8);
157
158 TRY(iblock->connect(i_in, i_out));
159 return UnitResult::ok();
160}
161
162UnitResult platform::REDAC::route_on_backplane(blocks::TBlockBackplane::Sector start_sector, blocks::TBlockBackplane::Sector end_sector,
163 uint8_t lane_idx) {
164 if (!back_panel)
165 return UnitResult::err("No backplane was accessible!");
166 if (back_panel->get_entity_version() < entities::Version(2, 0, 0))
167 return UnitResult::err("The detected backplane is using old topology, which is no longer supported");
168
169 blocks::TBlockBackplane *required_t_block = nullptr;
170 if (lane_idx < 8 || lane_idx > 31)
171 return UnitResult::err("Invalid lane index for backplane signal");
172 else if (lane_idx < 16)
173 required_t_block = stack_t0_block;
174 else if (lane_idx < 24)
175 required_t_block = stack_t1_block;
176 else if (lane_idx < 32)
177 required_t_block = stack_t2_block;
178
179 if (!required_t_block)
180 return UnitResult::err("The required backplane t-block could not be found!");
181
182 return required_t_block->connect(start_sector, end_sector, lane_idx % 8);
183}
184
185UnitResult platform::REDAC::calibrate_offsets() {
186 LOG_ANABRID_DEBUG_CALIBRATION("Halting external signal sources");
187
188 std::vector<std::array<uint32_t, blocks::IBlock::NUM_OUTPUTS>> old_iblock_connections;
189 for (auto &cluster : clusters) {
190 old_iblock_connections.emplace_back(cluster.iblock->get_outputs());
191 // Search for signals that are coming from external sources
192 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
193 for (auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
194 if (i_in_idx <= 7) // No T-Block connections on those lanes
195 continue;
196
197 // Only do something is this lane is connected
198 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
199 continue;
200
201 // Now check where the T-Block connects us to
202 auto dest_sector = static_cast<blocks::TBlock::Sector>(cluster.get_cluster_idx() + 1);
203 auto src = carrier_t_block->src_of_signal(dest_sector, i_in_idx - 8);
204
205 // Carrier internal routing => no problem to take care of
206 if (src != blocks::TBlock::Sector::BPL)
207 continue;
208
209 // Disconnect in I Block
210 cluster.iblock->disconnect(i_in_idx, i_out_idx);
211 }
212 }
213 TRY(cluster.iblock->write_to_hardware());
214 }
215
216 LOG_ANABRID_DEBUG_CALIBRATION("Calibrating all offsets");
217
218 std::vector<std::pair<blocks::UBlock::Transmission_Mode, blocks::UBlock::Transmission_Mode>> old_transmission_modes;
219 std::vector<blocks::UBlock::Reference_Magnitude> old_reference_magnitudes;
220 for (auto &cluster : clusters) {
221 old_transmission_modes.push_back(cluster.ublock->get_all_transmission_modes());
222 old_reference_magnitudes.push_back(cluster.ublock->get_reference_magnitude());
223 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::GROUND);
224
225 TRY(cluster.ublock->write_to_hardware());
226 }
227
228 delay(10);
229
230 for (auto &cluster : clusters)
231 cluster.shblock->compensate_hardware_offsets();
232
233 for (size_t i = 0; i < clusters.size(); i++) {
234 clusters[i].ublock->change_all_transmission_modes(old_transmission_modes[i]);
235 clusters[i].ublock->change_reference_magnitude(old_reference_magnitudes[i]);
236
237 TRY(clusters[i].ublock->write_to_hardware());
238 }
239
240 LOG_ANABRID_DEBUG_CALIBRATION("Resuming external signal sources");
241
242 for (size_t i = 0; i < clusters.size(); i++) {
243 clusters[i].iblock->set_outputs(old_iblock_connections[i]);
244 TRY(clusters[i].iblock->write_to_hardware());
245 }
246
247 delay(10);
248 return UnitResult::ok();
249}
250
251UnitResult platform::REDAC::calibrate_routes() {
252 // Save and change ADC bus selection
253 auto old_adcbus = ctrl_block->get_adc_bus();
254 auto old_adc_channels = get_adc_channels();
255
256 reset_adc_channels();
257
258 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
259 TRY(ctrl_block->write_to_hardware());
260
261 // Save and change cluster block settings
262 LOG_ANABRID_DEBUG_CALIBRATION("Enable u-block reference");
263
264 std::vector<std::pair<blocks::UBlock::Transmission_Mode, blocks::UBlock::Transmission_Mode>> old_transmission_modes;
265 std::vector<blocks::UBlock::Reference_Magnitude> old_reference_magnitudes;
266 for (auto &cluster : clusters) {
267 old_transmission_modes.push_back(cluster.ublock->get_all_transmission_modes());
268 old_reference_magnitudes.push_back(cluster.ublock->get_reference_magnitude());
269 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::POS_REF);
270
271 TRY(cluster.ublock->write_to_hardware());
272 }
273
274 LOG_ANABRID_DEBUG_CALIBRATION("Reset c-blocks");
275 std::vector<std::array<float, blocks::CBlock::NUM_COEFF>> old_c_block_factors;
276 for (auto &cluster : clusters) {
277 old_c_block_factors.push_back(cluster.cblock->get_factors());
278 cluster.cblock->set_factors({});
279
280 TRY(cluster.cblock->write_to_hardware());
281 }
282
283 for (auto &cluster : clusters) {
284 LOG_ANABRID_DEBUG_CALIBRATION(("Calibrating routes ending in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
285
286 // We dont need to worry about clusters that dont have connections
287 if (!cluster.iblock->is_anything_connected())
288 continue;
289
290 // Find an M block usable for its identity lanes
291 blocks::MBlock *id_block = nullptr;
292 if (cluster.m0block && cluster.m0block->has_id_lanes())
293 id_block = cluster.m0block;
294
295 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
296 id_block = cluster.m1block;
297
298 if (!id_block) {
299 return UnitResult::err("No M Block with ID Lanes found, calibration impossible!");
300 }
301
302 uint8_t id_in_lane = 0, id_out_lane = 4;
303 for (auto i = 0; i < id_block->ID_OUTPUT_CONNECTIONS().size(); i++) {
304 if (id_block->ID_OUTPUT_CONNECTIONS()[i] != -1) {
305 id_out_lane = id_block->slot_to_global_io_index(i);
306 id_in_lane = id_block->slot_to_global_io_index(id_block->ID_OUTPUT_CONNECTIONS()[i]);
307 break;
308 }
309 }
310
311 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections;
312 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections_uncalibrated;
313 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
314 for (auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
315 // Only do something is this lane is used in the original I-block configuration
316 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
317 continue;
318
319 uint8_t src_cluster = cluster.get_cluster_idx();
320
321 // Now check where the t-block connects us to but only if the signal actually goes through the t block
322 if (i_in_idx > 7) {
323 auto src = carrier_t_block->src_of_signal(static_cast<blocks::TBlock::Sector>(cluster.get_cluster_idx() + 1), i_in_idx - 8);
324
325 if (src == blocks::TBlock::Sector::BPL) {
326 LOG_ANABRID_DEBUG_CALIBRATION("Signal starts on backplane, we can't work with this");
327 old_i_block_connections_uncalibrated[i_out_idx].emplace_back(i_in_idx);
328 continue;
329 }
330
331 src_cluster = src - 1;
332
333 if (src_cluster >= clusters.size())
334 continue; // This can only happen in debug with less than three clusters
335 }
336
337 // If we don't have a complete connection through the u block, we don't need / we can't calibrate this
338 // route from here
339 if (!clusters[src_cluster].ublock->is_output_connected(i_in_idx))
340 continue;
341
342 // Store this i block input to output connection
343 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
344 }
345 }
346 cluster.iblock->reset_outputs();
347 TRY(cluster.iblock->write_to_hardware());
348
349 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
350 for (auto i_in_idx : old_i_block_connections[i_out_idx])
351 TRY (cluster.iblock->connect(i_in_idx, id_in_lane));
352
353 TRY(cluster.iblock->write_to_hardware());
354
355 // Now switch through all relevant input signals and put one of them to 1.0
356 for (auto i_in_idx : old_i_block_connections[i_out_idx]) {
357 LOG_ANABRID_DEBUG_CALIBRATION(i_in_idx);
358 LOG_ANABRID_DEBUG_CALIBRATION(i_out_idx);
359
360 auto *ublock = cluster.ublock; // U Block might be in different cluster
361 auto *cblock = cluster.cblock; // C Block might be in different cluster
362 auto *iblock = cluster.iblock; // I Block is always in the cluster we are operating in
363 auto *shblock = cluster.shblock; // SH Block is always in the cluster we are operating in
364
365 // First check where the t-block connects us to but only if the signal actually goes through the t
366 // block
367 if (i_in_idx > 7) {
368 auto src = carrier_t_block->src_of_signal(static_cast<blocks::TBlock::Sector>(cluster.get_cluster_idx() + 1), i_in_idx - 8);
369
370 if (src == blocks::TBlock::Sector::BPL) {
371 LOG_ANABRID_DEBUG_CALIBRATION("Signal starts on backplane, we can't work with this");
372 continue;
373 }
374
375 uint8_t src_cluster = src - 1;
376
377 LOG_ANABRID_DEBUG_CALIBRATION(("Signal starts in cluster " + std::to_string(src_cluster)).c_str());
378
379 if (src_cluster >= clusters.size())
380 continue; // This can only happen in debug with less then three clusters
381
382 // Now we now from which cluster the signals start
383 ublock = clusters[src_cluster].ublock;
384 cblock = clusters[src_cluster].cblock;
385 }
386
387 // Setup measure path
388 TRY(set_adc_channel(0, id_out_lane, cluster.get_cluster_idx()));
389 if (!hardware->write_adc_bus_mux(m_adc_channels))
390 return UnitResult::err("Writing adcs failed!");
391
392 // Depending on whether upscaling is enabled for this lane, we apply +1 or +0.1 reference
393 // This is done on all lanes (but no other I-block connection exists, so no other current flows)
394 bool upscaled_channel = iblock->get_upscaling(i_in_idx);
395 ublock->change_reference_magnitude(upscaled_channel ? blocks::UBlock::Reference_Magnitude::ONE_TENTH
396 : blocks::UBlock::Reference_Magnitude::ONE);
397 TRY(cluster.ublock->write_to_hardware());
398
399 // First measure the offset of each measuring lane. The SH Block can not calibrate offsets that occur
400 // after himself so we need to take care of that.
401 TRY(cblock->set_factor(i_in_idx, 0.0f));
402 TRY(cblock->set_gain_correction(i_in_idx, 1.0f));
403 TRY(cblock->write_to_hardware());
404
405 // Calibrate offsets for this specific route
406 TRY(calibrate_offsets());
407
408 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
409 LOG_ANABRID_DEBUG_CALIBRATION(measured_offset);
410
411 // Allow this connection to go up to full scale. Those values are allways legal so we can ignore the
412 // return value
413 TRY(cblock->set_factor(i_in_idx, 1.0f));
414 TRY(cblock->write_to_hardware());
415
416 delay(10);
417
418 // Measure gain output
419 auto measured_gain = -daq::average(daq::sample, 4, 10)[0];
420 LOG_ANABRID_DEBUG_CALIBRATION(measured_gain);
421 // Calculate necessary gain correction
422 auto gain_correction = (upscaled_channel ? 0.8f : 1.0f) / (measured_gain - measured_offset);
423 LOG_ANABRID_DEBUG_CALIBRATION(gain_correction);
424 if (gain_correction > 1.1f) {
425 LOG_ALWAYS("Gain correction is too high, this is probably a problem with the hardware");
426 gain_correction = 1.1f;
427 }
428 // Set gain correction on C-block, which will automatically get applied when writing to hardware
429 TRY(cblock->set_gain_correction(i_in_idx, gain_correction));
430 // Deactivate this lane again
431 TRY(cblock->set_factor(i_in_idx, 0.0f));
432 TRY(cblock->write_to_hardware());
433 LOG_ANABRID_DEBUG_CALIBRATION(" ");
434 }
435
436 cluster.iblock->reset_outputs();
437 reset_adc_channels();
438 }
439
440 // Restore I-block connections
441 LOG_ANABRID_DEBUG_CALIBRATION("Restoring i-block");
442 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
443 for (auto i_in_idx : old_i_block_connections[i_out_idx])
444 TRY(cluster.iblock->connect(i_in_idx, i_out_idx));
445 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
446 for (auto i_in_idx : old_i_block_connections_uncalibrated[i_out_idx])
447 TRY (cluster.iblock->connect(i_in_idx, i_out_idx));
448
449 TRY(cluster.iblock->write_to_hardware());
450 }
451
452 LOG_ANABRID_DEBUG_CALIBRATION("Restoring u-blocks");
453 for (size_t i = 0; i < clusters.size(); i++) {
454 clusters[i].ublock->change_all_transmission_modes(old_transmission_modes[i]);
455 clusters[i].ublock->change_reference_magnitude(old_reference_magnitudes[i]);
456
457 TRY(clusters[i].ublock->write_to_hardware());
458 }
459
460 LOG_ANABRID_DEBUG_CALIBRATION("Restoring c-blocks");
461 for (size_t i = 0; i < clusters.size(); i++) {
462 clusters[i].cblock->set_factors(old_c_block_factors[i]);
463 TRY(clusters[i].cblock->write_to_hardware());
464 }
465
466 // Restore ADC bus selection
467 ctrl_block->set_adc_bus(old_adcbus);
468 TRY(ctrl_block->write_to_hardware());
469
470 TRY(set_adc_channels(old_adc_channels));
471 if (!hardware->write_adc_bus_mux(m_adc_channels))
472 return UnitResult::err("Writing adcs failed");
473
474 // Calibrate offsets for complete path
475 TRY(calibrate_offsets());
476
477 return UnitResult::ok();
478}
479
480std::vector<entities::Entity *> platform::REDAC::get_child_entities() {
481 auto entities = this->carrier::Carrier::get_child_entities();
482 if (back_panel)
483 entities.push_back(back_panel);
484 for (auto *t_block : get_all_tblocks())
485 if (t_block)
486 entities.push_back(t_block);
487 return entities;
488}
489
490entities::Entity *platform::REDAC::get_child_entity(std::string_view child_id) {
491 if (child_id == "BP")
492 return back_panel;
493 if (child_id == "T")
494 return carrier_t_block;
495 if (child_id == platform::REDAC::STACK_T0_NAME)
496 return stack_t0_block;
497 if (child_id == platform::REDAC::STACK_T1_NAME)
498 return stack_t1_block;
499 if (child_id == platform::REDAC::STACK_T2_NAME)
500 return stack_t2_block;
501 return this->Carrier::get_child_entity(child_id);
502}
503
504void platform::REDAC::extract(entities::ExtractVisitor &collector) {
505 Carrier::extract(collector);
506
507 if (!collector.include_configuration()) return;
508 auto &config = collector.create(pb_Item_backpanel_config_tag);
509 auto &backpanel_config = config.kind.backpanel_config;
510
511 auto identifier = get_back_panel_identifier();
512
513 backpanel_config.backpanel_id = identifier.backpanel_id;
514 backpanel_config.backpanel_slot = identifier.backpanel_slot;
515 backpanel_config.is_valid = identifier.valid;
516 backpanel_config.is_isolated = identifier.isolated;
517}
518
519UnitResult platform::REDAC::calibrate(const pb_CalibrationConfig &item)
520{
521 GateTimer timer;
522 TRY(Carrier::calibrate(item));
523 if (!item.gain) return UnitResult::ok();
524
525 std::string_view path_view(item.leader.path);
526 bool is_leader = item.has_leader && path_view == get_entity_id();
527
528 std::unique_ptr<CalibrationBase> base;
529 CalibrationBase::clear(100);
530 timer.release_after_ms(100);
531 if (is_leader) {
532 base = std::make_unique<CalibrationLeader>(*this);
533 } else {
534 base = std::make_unique<CalibrationFollower>(*this);
535 }
536
537 auto do_result = base->do_();
538 if (!do_result) {
539 LOG_ERROR("ERROR during calibration");
540 LOG_ERROR(do_result.err_value().c_str());
541 CalibrationBase::clear(100);
542 return do_result;
543 }
544
545 LOG_ALWAYS("Calibration done.")
546 return UnitResult::ok();
547}
548
549ConfigResult platform::REDAC::config(const pb_Item &item) {
550 if (item.which_kind == pb_Item_dependency_info_tag || item.which_kind == pb_Item_ip_lookup_table_tag) {
551 return routing.config(item);
552 }
553
554 return Carrier::config(item);
555}
uint32_t src
Definition flasher.cpp:63
uint32_t uint32_t size
Definition flasher.cpp:63