6#include "redac/calibration.h"
7#include "utils/timer.h"
10#include <redac/redac.h>
11#include <utils/logging.h>
13blocks::TBlockBackplane *platform::REDAC::init_backpanel_tblock(uint8_t baddr,
const char *name) {
14 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
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));
19 LOG(ANABRID_DEBUG_INIT,
"Warning: The backplane T block is missing or unknown...");
23 LOG(ANABRID_DEBUG_INIT,
"Initializing the backplane T Block...");
24 t_block->rename_entity(name);
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());
32 LOG(ANABRID_DEBUG_INIT,
"Backplane T-Block initialized.");
36UnitResult platform::REDAC::init() {
37 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
39 routing.init(entity_id);
42 bp_identifier = BackPanelIdentifier(hardware->read_backplane_and_slot_id());
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.");
51 LOG(ANABRID_DEBUG_INIT,
"Initializing Carrier T-Block...");
52 TRY(carrier_t_block->init());
53 LOG(ANABRID_DEBUG_INIT,
"Carrier T-Block initialized.");
57 LOG(ANABRID_DEBUG_INIT,
"Detecting back panel...");
58 back_panel = entities::detect<platform::REDACBackPanel>(bus::address_from_tuple(bus::BACKPLANE_BADDR, 0));
60 LOG(ANABRID_DEBUG_INIT,
"Warning: Back panel is missing or unknown.");
64 stack_t0_block = init_backpanel_tblock(bus::BPL_T0_BLOCK_BADDR, platform::REDAC::STACK_T0_NAME);
66 stack_t1_block = init_backpanel_tblock(bus::BPL_T1_BLOCK_BADDR, platform::REDAC::STACK_T1_NAME);
68 stack_t2_block = init_backpanel_tblock(bus::BPL_T2_BLOCK_BADDR, platform::REDAC::STACK_T2_NAME);
70 return UnitResult::ok();
73platform::REDAC::REDAC(REDAC_HAL *hardware) : Carrier({Cluster(0), Cluster(1), Cluster(2)}, hardware), hardware(hardware) {}
75platform::BackPanelIdentifier platform::REDAC::get_back_panel_identifier()
const {
return bp_identifier; }
77void platform::REDAC::reset(entities::ResetAction action) {
78 Carrier::reset(action);
80 for (
auto *t_block : get_all_tblocks())
82 t_block->reset(action);
84 hardware->reset_adc_bus_mux();
87void platform::REDAC::power_up() { hardware->set_standby(
false); }
89void platform::REDAC::power_down() { hardware->set_standby(
true); }
91UnitResult platform::REDAC::write_to_hardware() {
92 TRY(Carrier::write_to_hardware());
94 for (
auto t_block : get_all_tblocks()) {
95 if (!t_block)
continue;
96 TRY(t_block->write_to_hardware());
99 return UnitResult::ok();
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");
107 return UnitResult::err(
"Can not connect a lane lower then 8 across multiple clusters");
109 auto *ublock = clusters[start_cluster].ublock;
110 auto *cblock = clusters[start_cluster].cblock;
111 auto *iblock = clusters[end_cluster].iblock;
114 carrier_t_block->connect(
static_cast<blocks::TBlock::Sector
>(start_cluster + 1),
static_cast<blocks::TBlock::Sector
>(end_cluster + 1), u_out - 8);
116 if (fabs(c_factor) > 1.0f) {
117 c_factor = c_factor / 8.0f;
118 iblock->set_upscaling(u_out,
true);
120 iblock->set_upscaling(u_out,
false);
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();
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");
133 return UnitResult::err(
"Can not connect a lane lower then 8 to backplane");
135 auto *ublock = clusters[start_cluster].ublock;
136 auto *cblock = clusters[start_cluster].cblock;
138 carrier_t_block->connect(
static_cast<blocks::TBlock::Sector
>(start_cluster + 1), blocks::TBlock::Sector::BPL, u_out - 8);
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();
147UnitResult platform::REDAC::route_from_backplane(uint8_t end_cluster, uint8_t i_in, uint8_t i_out) {
149 return UnitResult::err(
"Invalid cluster index. Valid ranges are 0 to 2");
152 return UnitResult::err(
"Can not connect a lane lower then 8 to backplane");
154 auto *iblock = clusters[end_cluster].iblock;
156 carrier_t_block->connect(blocks::TBlock::Sector::BPL,
static_cast<blocks::TBlock::Sector
>(end_cluster + 1), i_in - 8);
158 TRY(iblock->connect(i_in, i_out));
159 return UnitResult::ok();
162UnitResult platform::REDAC::route_on_backplane(blocks::TBlockBackplane::Sector start_sector, blocks::TBlockBackplane::Sector end_sector,
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");
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;
179 if (!required_t_block)
180 return UnitResult::err(
"The required backplane t-block could not be found!");
182 return required_t_block->connect(start_sector, end_sector, lane_idx % 8);
185UnitResult platform::REDAC::calibrate_offsets() {
186 LOG_ANABRID_DEBUG_CALIBRATION(
"Halting external signal sources");
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());
192 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
193 for (
auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
198 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
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);
206 if (
src != blocks::TBlock::Sector::BPL)
210 cluster.iblock->disconnect(i_in_idx, i_out_idx);
213 TRY(cluster.iblock->write_to_hardware());
216 LOG_ANABRID_DEBUG_CALIBRATION(
"Calibrating all offsets");
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);
225 TRY(cluster.ublock->write_to_hardware());
230 for (
auto &cluster : clusters)
231 cluster.shblock->compensate_hardware_offsets();
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]);
237 TRY(clusters[i].ublock->write_to_hardware());
240 LOG_ANABRID_DEBUG_CALIBRATION(
"Resuming external signal sources");
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());
248 return UnitResult::ok();
251UnitResult platform::REDAC::calibrate_routes() {
253 auto old_adcbus = ctrl_block->get_adc_bus();
254 auto old_adc_channels = get_adc_channels();
256 reset_adc_channels();
258 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
259 TRY(ctrl_block->write_to_hardware());
262 LOG_ANABRID_DEBUG_CALIBRATION(
"Enable u-block reference");
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);
271 TRY(cluster.ublock->write_to_hardware());
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({});
280 TRY(cluster.cblock->write_to_hardware());
283 for (
auto &cluster : clusters) {
284 LOG_ANABRID_DEBUG_CALIBRATION((
"Calibrating routes ending in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
287 if (!cluster.iblock->is_anything_connected())
291 blocks::MBlock *id_block =
nullptr;
292 if (cluster.m0block && cluster.m0block->has_id_lanes())
293 id_block = cluster.m0block;
295 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
296 id_block = cluster.m1block;
299 return UnitResult::err(
"No M Block with ID Lanes found, calibration impossible!");
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]);
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()) {
316 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
319 uint8_t src_cluster = cluster.get_cluster_idx();
323 auto src = carrier_t_block->src_of_signal(
static_cast<blocks::TBlock::Sector
>(cluster.get_cluster_idx() + 1), i_in_idx - 8);
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);
331 src_cluster =
src - 1;
333 if (src_cluster >= clusters.size())
339 if (!clusters[src_cluster].ublock->is_output_connected(i_in_idx))
343 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
346 cluster.iblock->reset_outputs();
347 TRY(cluster.iblock->write_to_hardware());
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));
353 TRY(cluster.iblock->write_to_hardware());
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);
360 auto *ublock = cluster.ublock;
361 auto *cblock = cluster.cblock;
362 auto *iblock = cluster.iblock;
363 auto *shblock = cluster.shblock;
368 auto src = carrier_t_block->src_of_signal(
static_cast<blocks::TBlock::Sector
>(cluster.get_cluster_idx() + 1), i_in_idx - 8);
370 if (
src == blocks::TBlock::Sector::BPL) {
371 LOG_ANABRID_DEBUG_CALIBRATION(
"Signal starts on backplane, we can't work with this");
375 uint8_t src_cluster =
src - 1;
377 LOG_ANABRID_DEBUG_CALIBRATION((
"Signal starts in cluster " + std::to_string(src_cluster)).c_str());
379 if (src_cluster >= clusters.size())
383 ublock = clusters[src_cluster].ublock;
384 cblock = clusters[src_cluster].cblock;
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!");
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());
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());
406 TRY(calibrate_offsets());
408 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
409 LOG_ANABRID_DEBUG_CALIBRATION(measured_offset);
413 TRY(cblock->set_factor(i_in_idx, 1.0f));
414 TRY(cblock->write_to_hardware());
419 auto measured_gain = -daq::average(daq::sample, 4, 10)[0];
420 LOG_ANABRID_DEBUG_CALIBRATION(measured_gain);
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;
429 TRY(cblock->set_gain_correction(i_in_idx, gain_correction));
431 TRY(cblock->set_factor(i_in_idx, 0.0f));
432 TRY(cblock->write_to_hardware());
433 LOG_ANABRID_DEBUG_CALIBRATION(
" ");
436 cluster.iblock->reset_outputs();
437 reset_adc_channels();
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));
449 TRY(cluster.iblock->write_to_hardware());
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]);
457 TRY(clusters[i].ublock->write_to_hardware());
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());
467 ctrl_block->set_adc_bus(old_adcbus);
468 TRY(ctrl_block->write_to_hardware());
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");
475 TRY(calibrate_offsets());
477 return UnitResult::ok();
480std::vector<entities::Entity *> platform::REDAC::get_child_entities() {
481 auto entities = this->carrier::Carrier::get_child_entities();
484 for (
auto *t_block : get_all_tblocks())
490entities::Entity *platform::REDAC::get_child_entity(std::string_view child_id) {
491 if (child_id ==
"BP")
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);
504void platform::REDAC::extract(entities::ExtractVisitor &collector) {
505 Carrier::extract(collector);
507 if (!collector.include_configuration())
return;
508 auto &config = collector.create(pb_Item_backpanel_config_tag);
509 auto &backpanel_config = config.kind.backpanel_config;
511 auto identifier = get_back_panel_identifier();
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;
519UnitResult platform::REDAC::calibrate(
const pb_CalibrationConfig &item)
522 TRY(Carrier::calibrate(item));
523 if (!item.gain)
return UnitResult::ok();
525 std::string_view path_view(item.leader.path);
526 bool is_leader = item.has_leader && path_view == get_entity_id();
528 std::unique_ptr<CalibrationBase> base;
529 CalibrationBase::clear(100);
530 timer.release_after_ms(100);
532 base = std::make_unique<CalibrationLeader>(*
this);
534 base = std::make_unique<CalibrationFollower>(*
this);
537 auto do_result = base->do_();
539 LOG_ERROR(
"ERROR during calibration");
540 LOG_ERROR(do_result.err_value().c_str());
541 CalibrationBase::clear(100);
545 LOG_ALWAYS(
"Calibration done.")
546 return UnitResult::ok();
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);
554 return Carrier::config(item);