6#include <redac/redac.h>
7#include <utils/logging.h>
9blocks::TBlockBackplane *platform::REDAC::init_backpanel_tblock(uint8_t baddr,
const char *name) {
10 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
12 LOG(ANABRID_DEBUG_INIT, utils::small_sprintf(
"Detecting Backpanel %s Block...", name).c_str());
13 blocks::TBlockBackplane *t_block = entities::detect<blocks::TBlockBackplane>(bus::address_from_tuple(baddr, 0));
15 LOG(ANABRID_DEBUG_INIT,
"Warning: The backplane T block is missing or unknown...");
19 LOG(ANABRID_DEBUG_INIT,
"Initializing the backplane T Block...");
20 t_block->rename_entity(name);
21 if (!t_block->init()) {
22 LOG(ANABRID_DEBUG_INIT,
"Backplane T-Block Failed");
26 LOG(ANABRID_DEBUG_INIT,
"Backplane T-Block initialized.");
30bool platform::REDAC::init() {
31 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
36 bp_identifier = BackPanelIdentifier(hardware->read_backplane_and_slot_id());
39 if (!carrier_t_block) {
40 LOG(ANABRID_DEBUG_INIT,
"Detecting Carrier T-Block...");
41 carrier_t_block = entities::detect<blocks::TBlock>(bus::address_from_tuple(bus::CARRIER_T_BLOCK_BADDR, 0));
42 if (!carrier_t_block) {
43 LOG(ANABRID_DEBUG_INIT,
"Warning: Carrier T-Block is missing or unknown.");
45 LOG(ANABRID_DEBUG_INIT,
"Initializing Carrier T-Block...");
46 if (!carrier_t_block->init())
48 LOG(ANABRID_DEBUG_INIT,
"Carrier T-Block initialized.");
52 LOG(ANABRID_DEBUG_INIT,
"Detecting back panel...");
53 back_panel = entities::detect<platform::REDACBackPanel>(bus::address_from_tuple(bus::BACKPLANE_BADDR, 0));
55 LOG(ANABRID_DEBUG_INIT,
"Warning: Back panel is missing or unknown.");
59 stack_t0_block = init_backpanel_tblock(bus::BPL_T0_BLOCK_BADDR, platform::REDAC::STACK_T0_NAME);
61 stack_t1_block = init_backpanel_tblock(bus::BPL_T1_BLOCK_BADDR, platform::REDAC::STACK_T1_NAME);
63 stack_t2_block = init_backpanel_tblock(bus::BPL_T2_BLOCK_BADDR, platform::REDAC::STACK_T2_NAME);
68platform::REDAC::REDAC(REDAC_HAL *hardware) : Carrier({Cluster(0), Cluster(1), Cluster(2)}, hardware), hardware(hardware) {}
70platform::BackPanelIdentifier platform::REDAC::get_back_panel_identifier()
const {
return bp_identifier; }
72void platform::REDAC::reset(entities::ResetAction action) {
73 Carrier::reset(action);
75 for (
auto *t_block : get_all_tblocks())
77 t_block->reset(action);
79 hardware->reset_adc_bus_mux();
82void platform::REDAC::power_up() { hardware->set_standby(
false); }
84void platform::REDAC::power_down() { hardware->set_standby(
true); }
86status platform::REDAC::write_to_hardware() {
87 RETURN_IF_FAILED(Carrier::write_to_hardware());
89 for (
auto *t_block : get_all_tblocks())
91 RETURN_IF_FAILED(t_block->write_to_hardware());
93 return status::success();
96status 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) {
97 if (start_cluster > 2 || end_cluster > 2)
98 return status(
"Invalid cluster indices. Valid ranges are 0 to 2");
101 return status(
"Can not connect a lane lower then 8 across multiple clusters");
103 auto *ublock = clusters[start_cluster].ublock;
104 auto *cblock = clusters[start_cluster].cblock;
105 auto *iblock = clusters[end_cluster].iblock;
108 carrier_t_block->connect(
static_cast<blocks::TBlock::Sector
>(start_cluster + 1),
static_cast<blocks::TBlock::Sector
>(end_cluster + 1), u_out - 8);
110 if (fabs(c_factor) > 1.0f) {
111 c_factor = c_factor / 8.0f;
112 iblock->set_upscaling(u_out,
true);
114 iblock->set_upscaling(u_out,
false);
116 if (!ublock->connect(u_in, u_out))
117 return status(
"U block connection not possible");
118 if (!cblock->set_factor(u_out, c_factor))
119 return status(
"C block configuration not possible");
120 if (!iblock->connect(u_out, i_out))
121 return status(
"I block connection not possible");
122 return status::success();
125status platform::REDAC::route_to_backplane(uint8_t start_cluster, uint8_t u_in, uint8_t u_out,
float c_factor) {
126 if (start_cluster > 2)
127 return status(
"Invalid cluster index. Valid ranges are 0 to 2");
130 return status(
"Can not connect a lane lower then 8 to backplane");
132 auto *ublock = clusters[start_cluster].ublock;
133 auto *cblock = clusters[start_cluster].cblock;
135 carrier_t_block->connect(
static_cast<blocks::TBlock::Sector
>(start_cluster + 1), blocks::TBlock::Sector::BPL, u_out - 8);
137 if (!ublock->connect(u_in, u_out))
138 return status(
"U block connection not possible");
139 if (!cblock->set_factor(u_out, c_factor))
140 return status(
"C block configuration not possible, remember there is no automatic upscaling");
141 return status::success();
144status platform::REDAC::route_from_backplane(uint8_t end_cluster, uint8_t i_in, uint8_t i_out) {
146 return status(
"Invalid cluster index. Valid ranges are 0 to 2");
149 return status(
"Can not connect a lane lower then 8 to backplane");
151 auto *iblock = clusters[end_cluster].iblock;
153 carrier_t_block->connect(blocks::TBlock::Sector::BPL,
static_cast<blocks::TBlock::Sector
>(end_cluster + 1), i_in - 8);
155 if (!iblock->connect(i_in, i_out))
156 return status(
"I block connection not possible");
157 return status::success();
160status platform::REDAC::route_on_backplane(blocks::TBlockBackplane::Sector start_sector, blocks::TBlockBackplane::Sector end_sector,
163 return status(
"No backplane was accessible!");
164 if (back_panel->get_entity_version() < entities::Version(2, 0, 0))
165 return status(
"The detected backplane is using old topology, which is no longer supported");
167 blocks::TBlockBackplane *required_t_block =
nullptr;
168 if (lane_idx < 8 || lane_idx > 31)
169 return status(
"Invalid lane index for backplane signal");
170 else if (lane_idx < 16)
171 required_t_block = stack_t0_block;
172 else if (lane_idx < 24)
173 required_t_block = stack_t1_block;
174 else if (lane_idx < 32)
175 required_t_block = stack_t2_block;
177 if (!required_t_block)
178 return status(
"The required backplane t-block could not be found!");
180 return required_t_block->connect(start_sector, end_sector, lane_idx % 8);
183status 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 success.attach(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 if (!cluster.ublock->write_to_hardware())
226 success.attach(
"Resetting u-block failed");
231 for (
auto &cluster : clusters)
232 cluster.shblock->compensate_hardware_offsets();
234 for (
size_t i = 0; i < clusters.size(); i++) {
235 clusters[i].ublock->change_all_transmission_modes(old_transmission_modes[i]);
236 clusters[i].ublock->change_reference_magnitude(old_reference_magnitudes[i]);
238 if (!clusters[i].ublock->write_to_hardware())
239 success.attach(
"Resetting u-block failed");
242 LOG_ANABRID_DEBUG_CALIBRATION(
"Resuming external signal sources");
244 for (
size_t i = 0; i < clusters.size(); i++) {
245 clusters[i].iblock->set_outputs(old_iblock_connections[i]);
246 if (!clusters[i].iblock->write_to_hardware())
247 success.attach(
"Resetting i-block failed");
255status platform::REDAC::calibrate_routes() {
259 auto old_adcbus = ctrl_block->get_adc_bus();
260 auto old_adc_channels = get_adc_channels();
262 reset_adc_channels();
264 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
265 if (!ctrl_block->write_to_hardware())
266 success.attach(
"Writing to ctrl-block failed");
269 LOG_ANABRID_DEBUG_CALIBRATION(
"Enable u-block reference");
271 std::vector<std::pair<blocks::UBlock::Transmission_Mode, blocks::UBlock::Transmission_Mode>> old_transmission_modes;
272 std::vector<blocks::UBlock::Reference_Magnitude> old_reference_magnitudes;
273 for (
auto &cluster : clusters) {
274 old_transmission_modes.push_back(cluster.ublock->get_all_transmission_modes());
275 old_reference_magnitudes.push_back(cluster.ublock->get_reference_magnitude());
276 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::POS_REF);
278 if (!cluster.ublock->write_to_hardware())
279 success.attach(
"Resetting u-block failed");
282 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset c-blocks");
283 std::vector<std::array<float, blocks::CBlock::NUM_COEFF>> old_c_block_factors;
284 for (
auto &cluster : clusters) {
285 old_c_block_factors.push_back(cluster.cblock->get_factors());
286 cluster.cblock->set_factors({});
288 if (!cluster.cblock->write_to_hardware())
289 success.attach(
"Resetting c-block failed");
292 for (
auto &cluster : clusters) {
293 LOG_ANABRID_DEBUG_CALIBRATION((
"Calibrating routes ending in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
296 if (!cluster.iblock->is_anything_connected())
300 blocks::MBlock *id_block =
nullptr;
301 if (cluster.m0block && cluster.m0block->has_id_lanes())
302 id_block = cluster.m0block;
304 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
305 id_block = cluster.m1block;
308 success.attach(
"No M Block with ID Lanes found, calibration impossible!");
312 uint8_t id_in_lane = 0, id_out_lane = 4;
313 for (
auto i = 0; i < id_block->ID_OUTPUT_CONNECTIONS().
size(); i++) {
314 if (id_block->ID_OUTPUT_CONNECTIONS()[i] != -1) {
315 id_out_lane = id_block->slot_to_global_io_index(i);
316 id_in_lane = id_block->slot_to_global_io_index(id_block->ID_OUTPUT_CONNECTIONS()[i]);
321 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections;
322 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections_uncalibrated;
323 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
324 for (
auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
326 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
329 uint8_t src_cluster = cluster.get_cluster_idx();
333 auto src = carrier_t_block->src_of_signal(
static_cast<blocks::TBlock::Sector
>(cluster.get_cluster_idx() + 1), i_in_idx - 8);
335 if (
src == blocks::TBlock::Sector::BPL) {
336 LOG_ANABRID_DEBUG_CALIBRATION(
"Signal starts on backplane, we can't work with this");
337 old_i_block_connections_uncalibrated[i_out_idx].emplace_back(i_in_idx);
341 src_cluster =
src - 1;
343 if (src_cluster >= clusters.size())
349 if (!clusters[src_cluster].ublock->is_output_connected(i_in_idx))
353 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
356 cluster.iblock->reset_outputs();
357 if (!cluster.iblock->write_to_hardware())
358 success.attach(
"Resetting i-block failed");
360 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
361 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
362 if (!cluster.iblock->connect(i_in_idx, id_in_lane))
363 LOG_ANABRID_DEBUG_CALIBRATION(
"Connecting i-block failed");
365 if (!cluster.iblock->write_to_hardware())
366 success.attach(
"Writing to i-block failed");
369 for (
auto i_in_idx : old_i_block_connections[i_out_idx]) {
370 LOG_ANABRID_DEBUG_CALIBRATION(i_in_idx);
371 LOG_ANABRID_DEBUG_CALIBRATION(i_out_idx);
373 auto *ublock = cluster.ublock;
374 auto *cblock = cluster.cblock;
375 auto *iblock = cluster.iblock;
376 auto *shblock = cluster.shblock;
381 auto src = carrier_t_block->src_of_signal(
static_cast<blocks::TBlock::Sector
>(cluster.get_cluster_idx() + 1), i_in_idx - 8);
383 if (
src == blocks::TBlock::Sector::BPL) {
384 LOG_ANABRID_DEBUG_CALIBRATION(
"Signal starts on backplane, we can't work with this");
388 uint8_t src_cluster =
src - 1;
390 LOG_ANABRID_DEBUG_CALIBRATION((
"Signal starts in cluster " + std::to_string(src_cluster)).c_str());
392 if (src_cluster >= clusters.size())
396 ublock = clusters[src_cluster].ublock;
397 cblock = clusters[src_cluster].cblock;
401 if (!set_adc_channel(0, id_out_lane, cluster.get_cluster_idx()))
402 success.attach(
"id_out_lane invalid");
403 if (!hardware->write_adc_bus_mux(adc_channels))
404 success.attach(
"Writing adcs failed!");
408 bool upscaled_channel = iblock->get_upscaling(i_in_idx);
409 ublock->change_reference_magnitude(upscaled_channel ? blocks::UBlock::Reference_Magnitude::ONE_TENTH
410 : blocks::UBlock::Reference_Magnitude::ONE);
411 if (!cluster.ublock->write_to_hardware())
412 success.attach(
"Writing to u-block failed");
416 (void)cblock->set_factor(i_in_idx, 0.0f);
417 (void)cblock->set_gain_correction(i_in_idx, 1.0f);
418 if (!cblock->write_to_hardware())
419 success.attach(
"Writing to c-block failed");
422 success.attach(calibrate_offsets());
424 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
425 LOG_ANABRID_DEBUG_CALIBRATION(measured_offset);
429 (void)cblock->set_factor(i_in_idx, 1.0f);
430 if (!cblock->write_to_hardware())
431 success.attach(
"Writing to c-block failed");
436 auto measured_gain = -daq::average(daq::sample, 4, 10)[0];
437 LOG_ANABRID_DEBUG_CALIBRATION(measured_gain);
439 auto gain_correction = (upscaled_channel ? 0.8f : 1.0f) / (measured_gain - measured_offset);
440 LOG_ANABRID_DEBUG_CALIBRATION(gain_correction);
441 if (gain_correction > 1.1f) {
442 success.attach(
"Gain correction is too high, this is probably a problem with the hardware");
443 gain_correction = 1.1f;
446 if (!cblock->set_gain_correction(i_in_idx, gain_correction)) {
447 (void)cblock->set_gain_correction(i_in_idx, 1.0f);
448 success.attach(
"Gain correction could not be set as it is out of range. Resetting this "
449 "channel to default correction");
452 (void)cblock->set_factor(i_in_idx, 0.0f);
453 if (!cblock->write_to_hardware())
454 success.attach(
"Writing to c-block failed");
456 LOG_ANABRID_DEBUG_CALIBRATION(
" ");
459 cluster.iblock->reset_outputs();
460 reset_adc_channels();
464 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring i-block");
465 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
466 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
467 if (!cluster.iblock->connect(i_in_idx, i_out_idx))
468 LOG_ANABRID_DEBUG_CALIBRATION(
"Connecting i-block failed");
469 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
470 for (
auto i_in_idx : old_i_block_connections_uncalibrated[i_out_idx])
471 if (!cluster.iblock->connect(i_in_idx, i_out_idx))
472 LOG_ANABRID_DEBUG_CALIBRATION(
"Connecting i-block failed");
474 if (!cluster.iblock->write_to_hardware())
475 success.attach(
"Restoring i-block failed");
478 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring u-blocks");
479 for (
size_t i = 0; i < clusters.size(); i++) {
480 clusters[i].ublock->change_all_transmission_modes(old_transmission_modes[i]);
481 clusters[i].ublock->change_reference_magnitude(old_reference_magnitudes[i]);
483 if (!clusters[i].ublock->write_to_hardware())
484 success.attach(
"Resetting u-block failed");
487 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring c-blocks");
488 for (
size_t i = 0; i < clusters.size(); i++) {
489 clusters[i].cblock->set_factors(old_c_block_factors[i]);
490 if (!clusters[i].cblock->write_to_hardware())
491 success.attach(
"Restoring c-block failed");
495 ctrl_block->set_adc_bus(old_adcbus);
496 if (!ctrl_block->write_to_hardware())
497 success.attach(
"Writing to ctrl-block failed");
499 (void)set_adc_channels(old_adc_channels);
500 if (!hardware->write_adc_bus_mux(adc_channels))
501 success.attach(
"Writing adcs failed");
504 success.attach(calibrate_offsets());
509std::vector<entities::Entity *> platform::REDAC::get_child_entities() {
510 auto entities = this->carrier::Carrier::get_child_entities();
513 for (
auto *t_block : get_all_tblocks())
519entities::Entity *platform::REDAC::get_child_entity(std::string_view child_id) {
520 if (child_id ==
"BP")
523 return carrier_t_block;
524 if (child_id == platform::REDAC::STACK_T0_NAME)
525 return stack_t0_block;
526 if (child_id == platform::REDAC::STACK_T1_NAME)
527 return stack_t1_block;
528 if (child_id == platform::REDAC::STACK_T2_NAME)
529 return stack_t2_block;
530 return this->carrier::Carrier::get_child_entity(child_id);
533void platform::REDAC::extract(entities::ExtractVisitor &collector) {
534 Carrier::extract(collector);
536 auto &config = collector.create(pb_Config_backpanel_config_tag);
537 auto &backpanel_config = config.kind.backpanel_config;
539 auto identifier = get_back_panel_identifier();
541 backpanel_config.backpanel_id = identifier.backpanel_id;
542 backpanel_config.backpanel_slot = identifier.backpanel_slot;
543 backpanel_config.is_valid = identifier.valid;
544 backpanel_config.is_isolated = identifier.isolated;
static constexpr int success