6#include "redac/calibration.h"
7#include "run/run_manager.h"
9#include <entity/visitor.h>
10#include <lucidac/lucidac.h>
13#include <net/settings.h>
14#include <redac/redac.h>
15#include <utils/is_number.h>
17carrier::Carrier::Carrier(std::vector<platform::Cluster> clusters, carrier::Carrier_HAL *hardware)
18 : Entity(
"", hardware), hardware(hardware), clusters(std::move(clusters)) {
19 classifier.class_enum = CLASS_;
22carrier::Carrier *carrier::Carrier::from_entity_classifier(entities::EntityClassifier classifier,
23 __attribute__((__unused__))
24 const bus::addr_t block_address) {
25 if (!classifier or classifier.class_enum != entities::EntityClass::CARRIER)
28 auto type = classifier.type_as<TYPES>();
34 return platform::LUCIDAC::from_entity_classifier(classifier, block_address);
36 return platform::REDAC::from_entity_classifier(classifier, block_address);
43carrier::Carrier *carrier::Carrier::detect() {
44 return entities::detect<carrier::Carrier>(bus::address_from_tuple(bus::CARRIER_BADDR, 0));
47UnitResult carrier::Carrier::better_init() {
48 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
50 entity_id = net::StartupConfig::get().mac;
52 if (entity_id.empty())
53 return UnitResult::err(
"Cannot determine Carrier MAC");
56 ctrl_block = entities::detect<blocks::CTRLBlock>(bus::address_from_tuple(bus::CTRL_BLOCK_BADDR, 0));
58 return UnitResult::err(
"Missing CTRL Block");
61 for (
auto &cluster : clusters) {
62 TRY_TRUE(cluster.init());
65 reset(entities::ResetAction::EVERYTHING);
67 return UnitResult::ok();
70uint8_t carrier::Carrier::get_active_adc_channel_range()
const{
71 uint8_t num_adc_channels = 0;
72 for(
size_t idx = 0; idx < m_adc_channels.size(); idx++){
73 if(m_adc_channels[idx].src != ADCChannel::DISABLED)
74 num_adc_channels = idx + 1;
76 return num_adc_channels;
79std::vector<entities::Entity *> carrier::Carrier::get_child_entities() {
80 std::vector<entities::Entity *> children;
81 for (
auto &cluster : clusters) {
82 children.push_back(&cluster);
85 children.push_back(ctrl_block);
89entities::Entity *carrier::Carrier::get_child_entity(std::string_view child_id) {
90 auto opt_int = utils::view_to_number(child_id);
91 if (opt_int.has_value()) {
92 auto cluster_idx = opt_int.value();
93 if (cluster_idx < 0 or clusters.size() < cluster_idx)
95 return &clusters[cluster_idx];
97 if (child_id ==
"CTRL")
99 if (child_id.size() == 17)
104ConfigResult carrier::Carrier::config(
const pb_Item &item) {
105 if (TRY(Entity::config(item)))
106 return ConfigResult::ok(
true);
109 return ConfigResult::err(
"Carrier cannot be configured without hardware");
111 if (item.which_kind == pb_Item_adc_config_tag) {
112 auto& carrier_config = item.kind.adc_config;
114 if (carrier_config.channels_count > m_adc_channels.size())
115 return ConfigResult::err(
"Channel count too large");
117 m_adc_channels.fill(ADCChannel());
118 for (
size_t idx = 0; idx < carrier_config.channels_count; ++idx) {
119 auto& channel = m_adc_channels[idx];
121 auto& config_channel = carrier_config.channels[idx];
122 channel.src = config_channel.idx;
123 channel.gain = config_channel.gain;
124 channel.offset = config_channel.offset;
125 channel.probe = config_channel.probe;
128 if (!hardware->write_adc_bus_mux(m_adc_channels))
129 return ConfigResult::err(
"Could not configure ACLs from configuration");
131 return ConfigResult::ok(
true);
134 return ConfigResult::ok(
false);
137void carrier::Carrier::extract(entities::ExtractVisitor &collector) {
138 Entity::extract(collector);
140 if (collector.include_specification()) {
141 auto& entity_spec = collector.create(pb_Item_entity_specification_tag).kind.entity_specification;
142 entity_spec.has_entity =
true;
143 encode_classifier(entity_spec.entity);
146 if (collector.include_configuration()) {
147 auto& item = collector.create(pb_Item_adc_config_tag);
148 auto& carrier_config = item.kind.adc_config = pb_AdcConfig_init_zero;
149 for (
auto & channel : m_adc_channels) {
150 if (channel.src == ADCChannel::DISABLED)
continue;
151 auto& pb_channel = carrier_config.channels[carrier_config.channels_count++];
152 pb_channel.idx =
static_cast<uint32_t
>(channel.src);
153 pb_channel.gain = channel.gain;
154 pb_channel.offset = channel.offset;
155 pb_channel.probe = channel.probe;
160bool carrier::Carrier::write_to_hardware() {
161 int cluster_index = 1;
162 for (
auto &cluster : clusters) {
163 auto result = cluster.write_to_hardware();
165 return UnitResult::err(
"Cluster " + std::to_string(cluster_index) +
" write failed.");
170 return write_adcs_to_hardware();
173UnitResult carrier::Carrier::calibrate_offsets() {
174 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
176 for (
auto &cluster : clusters)
177 TRY(cluster.calibrate_offsets());
179 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
180 return UnitResult::ok();
183UnitResult carrier::Carrier::calibrate_routes() {
189 auto result = calibrate_routes_raw();
197UnitResult carrier::Carrier::calibrate_routes_raw() {
198 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
200 bool gain_correction_exceeding =
false;
201 for (
auto &cluster : clusters) {
202 LOG_ANABRID_DEBUG_CALIBRATION(
203 (
"Calibrating routes in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
205 auto old_adcbus = ctrl_block->get_adc_bus();
206 auto old_adc_channels = get_adc_channels();
208 reset_adc_channels();
210 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
211 TRY_TRUE(ctrl_block->write_to_hardware());
214 LOG_ANABRID_DEBUG_CALIBRATION(
"Starting calibration");
215 auto old_transmission_modes = cluster.ublock->get_all_transmission_modes();
216 auto old_reference_magnitude = cluster.ublock->get_reference_magnitude();
219 LOG_ANABRID_DEBUG_CALIBRATION(
"Enable u-block reference");
220 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::POS_REF);
221 TRY_TRUE(cluster.ublock->write_to_hardware());
224 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset c-block");
225 auto old_c_block_factors = cluster.cblock->get_factors();
226 cluster.cblock->set_factors({});
227 TRY_TRUE (cluster.cblock->write_to_hardware());
230 blocks::MBlock *id_block =
nullptr;
231 if (cluster.m0block && cluster.m0block->has_id_lanes())
232 id_block = cluster.m0block;
234 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
235 id_block = cluster.m1block;
238 return UnitResult::err(
"No M Block with ID Lanes found, calibration impossible!");
241 uint8_t id_in_lane = 0, id_out_lane = 4;
242 for (
auto i = 0; i < id_block->ID_OUTPUT_CONNECTIONS().
size(); i++) {
243 if (id_block->ID_OUTPUT_CONNECTIONS()[i] != -1) {
244 id_out_lane = id_block->slot_to_global_io_index(i);
245 id_in_lane = id_block->slot_to_global_io_index(id_block->ID_OUTPUT_CONNECTIONS()[i]);
250 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections;
251 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
252 for (
auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
255 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
260 if (!cluster.ublock->is_output_connected(i_in_idx))
264 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
268 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset i-block");
269 cluster.iblock->reset_outputs();
270 TRY_TRUE(cluster.iblock->write_to_hardware());
274 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
275 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
276 TRY(cluster.iblock->connect(i_in_idx, id_in_lane));
278 TRY_TRUE(cluster.iblock->write_to_hardware());
281 for (
auto i_in_idx : old_i_block_connections[i_out_idx]) {
283 TRY(set_adc_channel(0, id_out_lane));
284 if (!hardware->write_adc_bus_mux(m_adc_channels))
285 return UnitResult::err(
"Writing adcs failed!");
289 bool upscaled_channel = cluster.iblock->get_upscaling(i_in_idx);
290 cluster.ublock->change_reference_magnitude(upscaled_channel
291 ? blocks::UBlock::Reference_Magnitude::ONE_TENTH
292 : blocks::UBlock::Reference_Magnitude::ONE);
293 TRY_TRUE(cluster.ublock->write_to_hardware());
297 TRY(cluster.cblock->set_factor(i_in_idx, 0.0f));
298 TRY(cluster.cblock->set_gain_correction(i_in_idx, 1.0f));
299 TRY_TRUE(cluster.cblock->write_to_hardware());
302 TRY(calibrate_offsets());
304 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
308 (void)cluster.cblock->set_factor(i_in_idx, 1.0f);
309 TRY_TRUE(cluster.cblock->write_to_hardware());
314 auto measured_gain = -daq::average(daq::sample, 4, 10)[0];
315 LOG_ANABRID_DEBUG_CALIBRATION(measured_gain);
317 auto gain_correction = (upscaled_channel ? 0.8 : 1.0) / (measured_gain - measured_offset);
318 LOG_ANABRID_DEBUG_CALIBRATION(gain_correction);
319 if (gain_correction > 1.1f) {
320 gain_correction_exceeding =
true;
321 gain_correction = 1.1f;
324 TRY(cluster.cblock->set_gain_correction(i_in_idx, gain_correction));
326 TRY(cluster.cblock->set_factor(i_in_idx, 0.0f));
327 LOG_ANABRID_DEBUG_CALIBRATION(
" ");
330 cluster.iblock->reset_outputs();
331 reset_adc_channels();
335 cluster.ublock->change_all_transmission_modes(old_transmission_modes);
336 cluster.ublock->change_reference_magnitude(old_reference_magnitude);
338 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring u-block");
339 TRY_TRUE(cluster.ublock->write_to_hardware());
342 cluster.cblock->set_factors(old_c_block_factors);
343 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring c-block");
344 TRY_TRUE(cluster.cblock->write_to_hardware());
347 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring i-block");
348 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
349 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
350 TRY(cluster.iblock->connect(i_in_idx, i_out_idx));
352 TRY_TRUE(cluster.iblock->write_to_hardware());
355 ctrl_block->set_adc_bus(old_adcbus);
356 TRY_TRUE(ctrl_block->write_to_hardware());
358 TRY(set_adc_channels(old_adc_channels));
359 if (!hardware->write_adc_bus_mux(m_adc_channels))
360 return UnitResult::err(
"Writing adcs failed");
363 if (gain_correction_exceeding)
364 return UnitResult::err(
"Gain correction is too high, this is probably a problem with the hardware");
367 auto result = Carrier::calibrate_offsets();
368 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
372UnitResult carrier::Carrier::calibrate_mblock(platform::Cluster &cluster, blocks::MBlock &mblock) {
374 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
381 LOG(ANABRID_DEBUG_CALIBRATION,
"Connecting outputs to ADC...");
382 for (
auto output_idx : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE()) {
383 auto lane_idx = mblock.slot_to_global_io_index(output_idx);
384 TRY(set_adc_channel(output_idx, lane_idx, cluster.get_cluster_idx()));
387 TRY_TRUE(write_to_hardware());
390 LOG(ANABRID_DEBUG_CALIBRATION,
"Passing control to M-block...");
391 TRY(mblock.calibrate(&cluster,
this));
393 LOG(ANABRID_DEBUG_CALIBRATION,
"Cleaning up calibration signals...");
394 reset(entities::ResetAction::CIRCUIT_RESET);
397 TRY_TRUE(write_to_hardware());
399 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibration done.");
400 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
402 return UnitResult::ok();
405UnitResult carrier::Carrier::calibrate_m_blocks() {
406 for (
auto &cluster : clusters) {
407 for (
auto mblock : {cluster.m0block, cluster.m1block}) {
408 if (!mblock)
continue;
409 TRY(calibrate_mblock(cluster, *mblock));
413 return UnitResult::ok();
416void carrier::Carrier::reset(entities::ResetAction action) {
417 for (
auto &cluster : clusters) {
418 cluster.reset(action);
421 ctrl_block->reset(action);
422 reset_adc_channels();
425const std::array<carrier::ADCChannel, 8> &carrier::Carrier::get_adc_channels()
const {
return m_adc_channels; }
427UnitResult carrier::Carrier::set_adc_channels(
const std::array<carrier::ADCChannel, 8> &channels) {
429 uint8_t channel_idx = 0;
430 for (
auto channel : channels) {
431 TRY(set_adc_channel(channel_idx, channel));
434 return UnitResult::ok();
437UnitResult carrier::Carrier::set_adc_channels(
const std::array<int8_t, 8> &channels) {
439 uint8_t channel_idx = 0;
440 for (
auto channel : channels) {
441 TRY(set_adc_channel(channel_idx, channel));
444 return UnitResult::ok();
447UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, ADCChannel src_channel) {
448 if (adc_channel >= m_adc_channels.size())
449 return UnitResult::err_fmt(
"Error carrier channel out of range: %d", adc_channel);
451 m_adc_channels[adc_channel] = src_channel;
452 return UnitResult::ok();
455[[nodiscard]] UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx) {
456 return set_adc_channel(adc_channel, ADCChannel{
461UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx, uint8_t cluster_idx) {
462 return set_adc_channel(adc_channel,
static_cast<int8_t
>(src_idx + cluster_idx * 16));
465void carrier::Carrier::reset_adc_channels() {
466 m_adc_channels.fill(ADCChannel());
469UnitResult carrier::Carrier::measure_all_signals(std::array<std::array<float, 8>, 6> &data) {
470 auto old_adc_channels = get_adc_channels();
471 reset_adc_channels();
472 size_t idx =
static_cast<size_t>(-1);
473 for (
const auto &cluster : clusters) {
474 for (
const auto mblock : {cluster.m0block, cluster.m1block}) {
476 if (!mblock)
continue;
478 for (
auto slot : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE())
479 TRY(set_adc_channel(slot, mblock->slot_to_global_io_index(slot), cluster.get_cluster_idx()));
481 TRY_TRUE(write_to_hardware());
482 data[idx] = daq::average();
485 TRY(set_adc_channels(old_adc_channels));
486 return UnitResult::ok();
489UnitResult carrier::Carrier::write_adcs_to_hardware(
const std::array<ADCChannel, 8>& channels) {
491 TRY_TRUE(ctrl_block->write_to_hardware());
493 if (!hardware->write_adc_bus_mux(channels))
494 return UnitResult::err(
"ADC Bus write failed.");
496 return UnitResult::ok();
499UnitResult carrier::Carrier::calibrate(
const pb_CalibrationConfig &item) {
500#ifdef ANABRID_DEBUG_COMMS
501 Serial.println(__PRETTY_FUNCTION__);
504 if(item.math != pb_CalibrationConfig_Kind_Disabled) {
506 entities::Setup
setup;
507 entities::ExtractSettings settings{
508 .include_configuration =
true
510 setup.extract(
this, settings);
511 reset(entities::ResetAction::CIRCUIT_RESET);
512 TRY_TRUE(write_to_hardware());
513 TRY(calibrate_m_blocks());
515 TRY(
setup.apply(
this,
true));
518 if (item.offset != pb_CalibrationConfig_Kind_Disabled)
519 TRY(calibrate_offsets());
521 return UnitResult::ok();
524UnitResult carrier::Carrier::user_get_overload_status(pb_OverloadStatus &overload_status) {
525 entities::OverloadVisitor visitor;
526 visitor.visit(
this,
true);
527 visitor.to(overload_status);
528 return UnitResult::ok();
531UnitResult carrier::Carrier::user_calibrate(
const pb_CalibrationConfig &item) {
532 return calibrate(item);
537 char* eptr =
nullptr;
538 auto result = std::strtol(view.begin(), &eptr, 10);
539 if(eptr - view.begin() != view.length())
540 return Result<uint32_t>::err(
"Invalid path: " + std::string(view));
542 return Result<uint32_t>::ok(result);
546PathResult Routing::index2path(uint32_t node)
const {
547 if (m_idx2path.size() <= node)
548 return PathResult::err_fmt(
"Unable to find path of entity idx: %d", node);
549 return PathResult::ok(m_idx2path.at(node));
552U32Result Routing::path2index(Path path)
const {
553 auto it = m_path2idx.find(path);
554 if (it == m_path2idx.end())
555 return LaneResult::err_fmt(
"Unable to find entity idx of path %s", std::string(path).c_str());
557 return U32Result::ok(m_path2idx.at(path));
560LaneResult Routing::cluster2lane(uint32_t cluster_idx, uint32_t lane_idx)
const {
561 if (!m_self_idx.has_value())
562 return LaneResult::err_fmt(
"Invalid self index for %s", carrier::Carrier::get().get_entity_id().c_str());
563 return LaneResult::ok(Lane(*m_self_idx, cluster_idx, lane_idx));
566UnitResult Routing::config_entity_idx(
const pb_EntityId* carrier_indices, uint32_t count) {
567 m_idx2path.resize(count);
568 m_self_idx = std::nullopt;
569 for (
auto carrier_idx = 0; carrier_idx < count; ++carrier_idx) {
570 auto& carrier_path = carrier_indices[carrier_idx];
571 Path
path = std::string_view(carrier_path.path);
572 if (
path.size() != 1)
573 return ConfigResult::err(
"Expected cluster path in trace config");
574 if (
path.segment(0) == m_self) {
575 m_self_idx = carrier_idx;
578 m_path2idx.emplace(path, carrier_idx);
579 m_idx2path[carrier_idx] =
path;
581 return UnitResult::ok();
584UnitResult Routing::config_trace_config(
const pb_DependencyInfo& dep_info) {
587 TRY(config_entity_idx(dep_info.entity_ids, dep_info.entity_ids_count));
589 for (
auto idx = 0; idx < dep_info.traces_count; ++idx) {
590 auto& trace = dep_info.traces[idx];
591 Lane src_lane(trace.source.carrier, trace.source.cluster, trace.source.lane);
592 Lane sink_lane(trace.sink.carrier, trace.sink.cluster, trace.sink.lane);
593 m_src2uses[src_lane]++;
594 if (trace.sink_upscaled) {
595 m_src_is_upscaled.insert(src_lane);
596 m_sink_is_upscaled.insert(sink_lane);
598 m_sink2src.emplace(sink_lane, src_lane);
599 m_sink_is_present.insert(sink_lane);
602 return UnitResult::ok();
606ConfigResult Routing::config(
const pb_Item &item){
607 if (item.which_kind == pb_Item_dependency_info_tag) {
608 TRY(config_trace_config(item.kind.dependency_info));
609 return ConfigResult::ok(
true);
612 if (item.which_kind == pb_Item_ip_lookup_table_tag) {
613 auto& ip_lookup_table = item.kind.ip_lookup_table;
614 for (
size_t idx = 0; idx < ip_lookup_table.entries_count; ++idx) {
615 auto& entity = ip_lookup_table.entries[idx];
616 if (!entity.has_address || !entity.has_entity_id)
continue;
617 auto& data = entity.address.data.bytes;
618 IPAddress address(data[0], data[1], data[2], data[3]);
619 set_path_address(std::string_view(entity.entity_id.path), address);
623 return ConfigResult::ok(
false);
626bool Routing::is_sink_upscaled(Lane lane)
const {
627 auto it = m_sink_is_upscaled.find(lane);
628 return it != m_sink_is_upscaled.end();
631bool Routing::is_source_upscaled(Lane lane)
const {
632 auto it = m_src_is_upscaled.find(lane);
633 return it != m_src_is_upscaled.end();
636uint32_t Routing::use_count(Lane lane)
const {
637 auto it = m_src2uses.find(lane);
638 if (it == m_src2uses.end())
643LaneResult Routing::source(Lane lane)
const {
644 auto it = m_sink2src.find(lane);
645 if (it == m_sink2src.end())
646 return LaneResult::err(
"Not found source");
647 return LaneResult::ok(it->second);
650bool Routing::is_source_used(Lane lane)
const {
651 return use_count(lane) > 0;
654bool Routing::is_sink_present(Lane lane)
const {
655 auto it = m_sink_is_present.find(lane);
656 return it != m_sink_is_present.end();
659IPAddressResult Routing::ip_address(Path path)
const {
660 auto it = m_path2ip.find(path);
661 if (it != m_path2ip.end())
662 return IPAddressResult::ok(it->second);
663 return UnitResult::err_fmt(
"Ip adress of %s not found", std::string(path).c_str());
667LaneResult Routing::source(uint32_t cluster_idx, uint32_t lane)
const {
668 return source(TRY(cluster2lane(cluster_idx, lane)));
671BoolResult Routing::is_source_upscaled(uint32_t cluster_idx, uint32_t lane)
const {
672 return BoolResult::ok(is_source_upscaled(TRY(cluster2lane(cluster_idx, lane))));
675BoolResult Routing::is_sink_upscaled(uint32_t cluster_idx, uint32_t lane)
const {
676 return BoolResult::ok(is_sink_upscaled(TRY(cluster2lane(cluster_idx, lane))));
679U32Result Routing::use_count(uint32_t cluster_idx, uint32_t lane)
const {
680 return U32Result::ok(use_count(TRY(cluster2lane(cluster_idx, lane))));
683PathResult Routing::source_path(uint32_t cluster_idx, uint32_t lane)
const {
684 return index2path(TRY(source(TRY(cluster2lane(cluster_idx, lane)))).m_carrier);
687BoolResult Routing::is_sink_present(uint32_t cluster_idx, uint32_t lane)
const {
688 return BoolResult::ok(is_sink_present(TRY(cluster2lane(cluster_idx, lane))));
691BoolResult Routing::is_source_used(uint32_t cluster_idx, uint32_t lane)
const {
692 return BoolResult::ok(is_source_used(TRY(cluster2lane(cluster_idx, lane))));
static Result< uint32_t > parse_uint(std::string_view view)