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,
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) {
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].idx != 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) {
106 return ConfigResult::err(
"Carrier cannot be configured without hardware");
108 if (item.which_kind == pb_Item_adc_config_tag) {
109 auto& carrier_config = item.kind.adc_config;
111 m_adc_channels.fill(ADCChannel());
112 size_t min_size = std::min(
113 static_cast<size_t>(carrier_config.channels_count),
114 m_adc_channels.size()
117 for (
size_t idx = 0; idx < min_size; ++idx) {
118 auto& config_channel = carrier_config.channels[idx];
119 auto& channel = m_adc_channels[idx];
120 channel.idx = config_channel.idx;
121 channel.gain = config_channel.gain;
122 channel.offset = config_channel.offset;
123 channel.probe = config_channel.probe;
126 auto res = hardware->write_adc_bus_mux(m_adc_channels);
128 return ConfigResult::err(
"Could not configure ACLs from configuration");
130 return ConfigResult::ok(
true);
133 return ConfigResult::ok(
false);
136void carrier::Carrier::extract(entities::ExtractVisitor &collector) {
137 Entity::extract(collector);
139 if (collector.include_specification()) {
140 auto& entity_spec = collector.create(pb_Item_entity_specification_tag).kind.entity_specification;
141 entity_spec.has_entity =
true;
142 encode_classifier(entity_spec.entity);
145 if (collector.include_configuration()) {
146 auto& item = collector.create(pb_Item_adc_config_tag);
147 auto& carrier_config = item.kind.adc_config;
148 for (
size_t idx = 0; idx < m_adc_channels.size(); ++idx) {
149 auto& channel = m_adc_channels[idx];
150 if (channel.idx == ADCChannel::DISABLED)
continue;
151 if (channel.probe < 0)
continue;
152 carrier_config.channels[carrier_config.channels_count++] = {
153 .idx =
static_cast<uint32_t>(channel.idx),
154 .gain = channel.gain,
155 .offset = channel.offset,
156 .probe =
static_cast<uint32_t>(channel.probe)
162UnitResult carrier::Carrier::write_to_hardware() {
163 int cluster_index = 1;
164 for (
auto &cluster : clusters) {
165 auto result = cluster.write_to_hardware();
167 return UnitResult::err(
"Cluster " + std::to_string(cluster_index) +
" write failed. (" + result.err_value() +
")");
172 return write_adcs_to_hardware();
175UnitResult carrier::Carrier::calibrate_offsets() {
176 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
178 for (
auto &cluster : clusters)
179 TRY(cluster.calibrate_offsets());
181 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
182 return UnitResult::ok();
185UnitResult carrier::Carrier::calibrate_routes() {
186 entities::Setup
setup;
187 entities::ExtractSettings settings{
188 .include_configuration =
true
190 setup.extract(
this, settings);
191 auto result = calibrate_routes_raw();
192 setup.apply(
this,
true);
199UnitResult carrier::Carrier::calibrate_routes_raw() {
200 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
202 bool gain_correction_exceeding =
false;
203 for (
auto &cluster : clusters) {
204 LOG_ANABRID_DEBUG_CALIBRATION(
205 (
"Calibrating routes in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
207 auto old_adcbus = ctrl_block->get_adc_bus();
208 auto old_adc_channels = get_adc_channels();
210 reset_adc_channels();
212 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
213 TRY(ctrl_block->write_to_hardware());
216 LOG_ANABRID_DEBUG_CALIBRATION(
"Starting calibration");
217 auto old_transmission_modes = cluster.ublock->get_all_transmission_modes();
218 auto old_reference_magnitude = cluster.ublock->get_reference_magnitude();
221 LOG_ANABRID_DEBUG_CALIBRATION(
"Enable u-block reference");
222 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::POS_REF);
223 TRY(cluster.ublock->write_to_hardware());
226 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset c-block");
227 auto old_c_block_factors = cluster.cblock->get_factors();
228 cluster.cblock->set_factors({});
229 TRY (cluster.cblock->write_to_hardware());
232 blocks::MBlock *id_block =
nullptr;
233 if (cluster.m0block && cluster.m0block->has_id_lanes())
234 id_block = cluster.m0block;
236 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
237 id_block = cluster.m1block;
240 return UnitResult::err(
"No M Block with ID Lanes found, calibration impossible!");
243 uint8_t id_in_lane = 0, id_out_lane = 4;
244 for (
auto i = 0; i < id_block->ID_OUTPUT_CONNECTIONS().
size(); i++) {
245 if (id_block->ID_OUTPUT_CONNECTIONS()[i] != -1) {
246 id_out_lane = id_block->slot_to_global_io_index(i);
247 id_in_lane = id_block->slot_to_global_io_index(id_block->ID_OUTPUT_CONNECTIONS()[i]);
252 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections;
253 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
254 for (
auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
257 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
262 if (!cluster.ublock->is_output_connected(i_in_idx))
266 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
270 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset i-block");
271 cluster.iblock->reset_outputs();
272 TRY(cluster.iblock->write_to_hardware());
276 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
277 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
278 TRY(cluster.iblock->connect(i_in_idx, id_in_lane));
280 TRY(cluster.iblock->write_to_hardware());
283 for (
auto i_in_idx : old_i_block_connections[i_out_idx]) {
285 TRY(set_adc_channel(0, id_out_lane));
286 if (!hardware->write_adc_bus_mux(m_adc_channels))
287 return UnitResult::err(
"Writing adcs failed!");
291 bool upscaled_channel = cluster.iblock->get_upscaling(i_in_idx);
292 cluster.ublock->change_reference_magnitude(upscaled_channel
293 ? blocks::UBlock::Reference_Magnitude::ONE_TENTH
294 : blocks::UBlock::Reference_Magnitude::ONE);
295 TRY(cluster.ublock->write_to_hardware());
299 TRY(cluster.cblock->set_factor(i_in_idx, 0.0f));
300 TRY(cluster.cblock->set_gain_correction(i_in_idx, 1.0f));
301 TRY(cluster.cblock->write_to_hardware());
304 TRY(calibrate_offsets());
306 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
310 (void)cluster.cblock->set_factor(i_in_idx, 1.0f);
311 TRY(cluster.cblock->write_to_hardware());
316 auto measured_gain = -daq::average(daq::sample, 4, 10)[0];
317 LOG_ANABRID_DEBUG_CALIBRATION(measured_gain);
319 auto gain_correction = (upscaled_channel ? 0.8f : 1.0f) / (measured_gain - measured_offset);
320 LOG_ANABRID_DEBUG_CALIBRATION(gain_correction);
321 if (gain_correction > 1.1f) {
322 gain_correction_exceeding =
true;
323 gain_correction = 1.1f;
326 TRY(cluster.cblock->set_gain_correction(i_in_idx, gain_correction));
328 TRY(cluster.cblock->set_factor(i_in_idx, 0.0f));
329 LOG_ANABRID_DEBUG_CALIBRATION(
" ");
332 cluster.iblock->reset_outputs();
333 reset_adc_channels();
337 cluster.ublock->change_all_transmission_modes(old_transmission_modes);
338 cluster.ublock->change_reference_magnitude(old_reference_magnitude);
340 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring u-block");
341 TRY(cluster.ublock->write_to_hardware());
344 cluster.cblock->set_factors(old_c_block_factors);
345 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring c-block");
346 TRY(cluster.cblock->write_to_hardware());
349 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring i-block");
350 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
351 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
352 TRY(cluster.iblock->connect(i_in_idx, i_out_idx));
354 TRY(cluster.iblock->write_to_hardware());
357 ctrl_block->set_adc_bus(old_adcbus);
358 TRY(ctrl_block->write_to_hardware());
360 TRY(set_adc_channels(old_adc_channels));
361 if (!hardware->write_adc_bus_mux(m_adc_channels))
362 return UnitResult::err(
"Writing adcs failed");
365 if (gain_correction_exceeding)
366 return UnitResult::err(
"Gain correction is too high, this is probably a problem with the hardware");
369 auto result = Carrier::calibrate_offsets();
370 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
374UnitResult carrier::Carrier::calibrate_mblock(platform::Cluster &cluster, blocks::MBlock &mblock) {
376 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
383 LOG(ANABRID_DEBUG_CALIBRATION,
"Connecting outputs to ADC...");
384 for (
auto output_idx : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE()) {
385 auto lane_idx = mblock.slot_to_global_io_index(output_idx);
386 TRY(set_adc_channel(output_idx, lane_idx, cluster.get_cluster_idx()));
389 TRY(write_to_hardware());
392 LOG(ANABRID_DEBUG_CALIBRATION,
"Passing control to M-block...");
393 TRY(mblock.calibrate(&cluster,
this));
395 LOG(ANABRID_DEBUG_CALIBRATION,
"Cleaning up calibration signals...");
396 reset(entities::ResetAction::CIRCUIT_RESET);
399 TRY(write_to_hardware());
401 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibration done.");
402 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
404 return UnitResult::ok();
407UnitResult carrier::Carrier::calibrate_m_blocks() {
408 for (
auto &cluster : clusters) {
409 for (
auto mblock : {cluster.m0block, cluster.m1block}) {
410 if (!mblock)
continue;
411 TRY(calibrate_mblock(cluster, *mblock));
415 return UnitResult::ok();
418void carrier::Carrier::reset(entities::ResetAction action) {
419 for (
auto &cluster : clusters) {
420 cluster.reset(action);
423 ctrl_block->reset(action);
424 reset_adc_channels();
427const std::array<carrier::ADCChannel, 8> &carrier::Carrier::get_adc_channels()
const {
return m_adc_channels; }
429UnitResult carrier::Carrier::set_adc_channels(
const std::array<carrier::ADCChannel, 8> &channels) {
431 uint8_t channel_idx = 0;
432 for (
auto channel : channels) {
433 TRY(set_adc_channel(channel_idx, channel));
436 return UnitResult::ok();
439UnitResult carrier::Carrier::set_adc_channels(
const std::array<int8_t, 8> &channels) {
441 uint8_t channel_idx = 0;
442 for (
auto channel : channels) {
443 TRY(set_adc_channel(channel_idx, channel));
446 return UnitResult::ok();
449UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, ADCChannel src_channel) {
450 if (adc_channel >= m_adc_channels.size())
451 return UnitResult::err_fmt(
"Error carrier channel out of range: %d", adc_channel);
453 m_adc_channels[adc_channel] = src_channel;
454 return UnitResult::ok();
457[[nodiscard]] UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx) {
458 return set_adc_channel(adc_channel, ADCChannel{
463UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx, uint8_t cluster_idx) {
464 return set_adc_channel(adc_channel,
static_cast<int8_t
>(src_idx + cluster_idx * 16));
467void carrier::Carrier::reset_adc_channels() {
468 m_adc_channels.fill(ADCChannel());
471UnitResult carrier::Carrier::measure_all_signals(std::array<std::array<float, 8>, 6> &data) {
472 auto old_adc_channels = get_adc_channels();
473 reset_adc_channels();
474 size_t idx =
static_cast<size_t>(-1);
475 for (
const auto &cluster : clusters) {
476 for (
const auto mblock : {cluster.m0block, cluster.m1block}) {
478 if (!mblock)
continue;
480 for (
auto slot : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE())
481 TRY(set_adc_channel(slot, mblock->slot_to_global_io_index(slot), cluster.get_cluster_idx()));
483 TRY(write_to_hardware());
484 data[idx] = daq::average();
487 TRY(set_adc_channels(old_adc_channels));
488 return UnitResult::ok();
491UnitResult carrier::Carrier::write_adcs_to_hardware() {
493 TRY(ctrl_block->write_to_hardware());
495 if (!hardware->write_adc_bus_mux(m_adc_channels))
496 return UnitResult::err(
"ADC Bus write failed.");
498 return UnitResult::ok();
501UnitResult carrier::Carrier::calibrate(
const pb_CalibrationConfig &item) {
502#ifdef ANABRID_DEBUG_COMMS
503 Serial.println(__PRETTY_FUNCTION__);
507 if(item.math == pb_CalibrationConfig_Kind_Disabled && item.offset == pb_CalibrationConfig_Kind_Disabled)
508 return UnitResult::ok();
511 entities::Setup
setup;
512 entities::ExtractSettings settings{
513 .include_configuration =
true
515 setup.extract(
this, settings);
516 reset(entities::ResetAction::CIRCUIT_RESET);
517 auto reset_write = write_to_hardware();
519 if (reset_write.is_ok()) {
520 if(item.math != pb_CalibrationConfig_Kind_Disabled)
521 TRY(calibrate_m_blocks());
523 if (item.offset != pb_CalibrationConfig_Kind_Disabled)
524 TRY(calibrate_offsets());
527 setup.apply(
this,
true);
531UnitResult carrier::Carrier::user_get_overload_status(pb_OverloadStatus &overload_status) {
532 entities::OverloadVisitor visitor;
533 visitor.visit(
this,
true);
534 visitor.to(overload_status);
535 return UnitResult::ok();
538UnitResult carrier::Carrier::user_calibrate(
const pb_CalibrationConfig &item) {
539 return calibrate(item);
544 char* eptr =
nullptr;
545 auto result = std::strtol(view.begin(), &eptr, 10);
546 if(eptr - view.begin() != view.length())
547 return Result<uint32_t>::err(
"Invalid path: " + std::string(view));
549 return Result<uint32_t>::ok(result);
553PathResult Routing::node2path(
uint32_t node)
const {
554 if (idx2entity.size() <= node)
555 return PathResult::err_fmt(
"Unable to find path of entity idx: %d", node);
556 return PathResult::ok(idx2entity.at(node));
559U32Result Routing::path2node(Path path)
const {
560 auto it = entity2node.find(path);
561 if (it == entity2node.end())
562 return LaneResult::err_fmt(
"Unable to find entity idx of path %s", std::string(path).c_str());
564 return U32Result::ok(entity2node.at(path));
567U32Result Routing::cluster2node(
uint32_t cluster_idx)
const {
568 auto it = m_cluster2node.find(cluster_idx);
569 if (it == m_cluster2node.end())
570 return U32Result::err_fmt(
"Unable to find entity idx of %d", cluster_idx);
571 return U32Result::ok(it->second);
574LaneResult Routing::cluster2lane(
uint32_t cluster_idx,
uint32_t lane_idx)
const {
575 return LaneResult::ok(Lane(TRY(cluster2node(cluster_idx)), lane_idx));
578UnitResult Routing::config_entity_idx(
const pb_EntityId* entity_ids,
uint32_t ids_count) {
579 idx2entity.resize(ids_count);
581 for (
auto node = 0; node < ids_count; ++node) {
582 auto& entity_id = entity_ids[node];
583 Path
path = std::string(entity_id.path);
584 if (
path.size() != 2)
585 return ConfigResult::err(
"Expected cluster path in trace config");
586 if (
path.segment(0) == self) {
590 entity2node.emplace(path, node);
591 idx2entity[node] =
path;
593 return UnitResult::ok();
596UnitResult Routing::config_trace_config(
const pb_DependencyInfo& dep_info) {
599 TRY(config_entity_idx(dep_info.entity_ids, dep_info.entity_ids_count));
601 for (
auto idx = 0; idx < dep_info.traces_count; ++idx) {
602 auto& trace = dep_info.traces[idx];
603 Lane src_lane(trace.source_node, trace.source_lane);
604 Lane sink_lane(trace.sink_node, trace.sink_lane);
605 m_src2uses[src_lane]++;
606 if (trace.sink_upscaled) {
607 m_is_upscaled.insert(src_lane);
608 m_is_upscaled.insert(sink_lane);
610 m_sink2src.emplace(sink_lane, src_lane);
611 m_sink_is_present.insert(sink_lane);
614 return UnitResult::ok();
618ConfigResult Routing::config(
const pb_Item &item){
619 if (item.which_kind == pb_Item_dependency_info_tag) {
620 TRY(config_trace_config(item.kind.dependency_info));
621 return ConfigResult::ok(
true);
624 if (item.which_kind == pb_Item_ip_lookup_table_tag) {
625 auto& ip_lookup_table = item.kind.ip_lookup_table;
626 for (
size_t idx = 0; idx < ip_lookup_table.entries_count; ++idx) {
627 auto& entity = ip_lookup_table.entries[idx];
628 if (!entity.has_address || !entity.has_entity_id)
continue;
629 auto& data = entity.address.data.bytes;
630 IPAddress address(data[0], data[1], data[2], data[3]);
631 set_path_address(std::string_view(entity.entity_id.path), address);
635 return ConfigResult::ok(
false);
638bool Routing::is_upscaled(Lane lane)
const {
639 auto it = m_is_upscaled.find(lane);
640 return it != m_is_upscaled.end();
643uint32_t Routing::use_count(Lane lane)
const {
644 auto it = m_src2uses.find(lane);
645 if (it == m_src2uses.end())
650LaneResult Routing::source(Lane lane)
const {
651 auto it = m_sink2src.find(lane);
652 if (it == m_sink2src.end())
653 return LaneResult::err(
"Not found source");
654 return LaneResult::ok(it->second);
657bool Routing::is_source_used(Lane lane)
const {
658 return use_count(lane) > 0;
661bool Routing::is_sink_present(Lane lane)
const {
662 auto it = m_sink_is_present.find(lane);
663 return it != m_sink_is_present.end();
666IPAddressResult Routing::ip_address(Path path)
const {
667 auto it = m_path2ip.find(path);
668 if (it != m_path2ip.end())
669 return IPAddressResult::ok(it->second);
670 return UnitResult::err_fmt(
"Ip adress of %s not found", std::string(path).c_str());
675 return source(TRY(cluster2lane(cluster_idx, lane)));
679 return BoolResult::ok(is_upscaled(TRY(cluster2lane(cluster_idx, lane))));
683 return U32Result::ok(use_count(TRY(cluster2lane(cluster_idx, lane))));
687 return node2path(TRY(source(TRY(cluster2lane(cluster_idx, lane)))).m_node);
690BoolResult Routing::is_sink_present(
uint32_t cluster_idx,
uint32_t lane)
const {
691 return BoolResult::ok(is_sink_present(TRY(cluster2lane(cluster_idx, lane))));
694BoolResult Routing::is_source_used(
uint32_t cluster_idx,
uint32_t lane)
const {
695 return BoolResult::ok(is_source_used(TRY(cluster2lane(cluster_idx, lane))));
static Result< uint32_t > parse_uint(std::string_view view)
__attribute__((section(".fastrun"), noinline, noclone, optimize("Os"))) int flash_sector_not_erased(uint32_t address)