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