7#include <entity/visitor.h>
8#include <lucidac/lucidac.h>
10#include <net/settings.h>
11#include <redac/redac.h>
12#include <utils/is_number.h>
14carrier::Carrier::Carrier(std::vector<platform::Cluster> clusters, carrier::Carrier_HAL *hardware)
15 : Entity(
"", hardware), hardware(hardware), clusters(std::move(clusters)) {
16 classifier.class_enum = CLASS_;
19carrier::Carrier *carrier::Carrier::from_entity_classifier(entities::EntityClassifier classifier,
21 const bus::addr_t block_address) {
22 if (!classifier or classifier.class_enum != entities::EntityClass::CARRIER)
25 auto type = classifier.type_as<TYPES>();
31 return platform::LUCIDAC::from_entity_classifier(classifier, block_address);
33 return platform::REDAC::from_entity_classifier(classifier, block_address);
40carrier::Carrier *carrier::Carrier::detect() {
41 return entities::detect<carrier::Carrier>(bus::address_from_tuple(bus::CARRIER_BADDR, 0));
44status carrier::Carrier::better_init() {
45 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
47 entity_id = net::StartupConfig::get().mac;
49 if (entity_id.empty())
50 return status(
"Cannot determine Carrier MAC");
53 ctrl_block = entities::detect<blocks::CTRLBlock>(bus::address_from_tuple(bus::CTRL_BLOCK_BADDR, 0));
55 return status(
"Missing CTRL Block");
58 for (
auto &cluster : clusters) {
60 return status(
"Cannot initialize cluster");
63 reset(entities::ResetAction::EVERYTHING);
65 return status::success();
68uint8_t carrier::Carrier::get_active_adc_channel_range()
const{
69 uint8_t num_adc_channels = 0;
70 for(
size_t idx = 0; idx < adc_channels.size(); idx++){
71 if(adc_channels[idx] != ADC_CHANNEL_DISABLED)
72 num_adc_channels = idx + 1;
74 return num_adc_channels;
77std::vector<entities::Entity *> carrier::Carrier::get_child_entities() {
78 std::vector<entities::Entity *> children;
79 for (
auto &cluster : clusters) {
80 children.push_back(&cluster);
83 children.push_back(ctrl_block);
87entities::Entity *carrier::Carrier::get_child_entity(std::string_view child_id) {
88 auto opt_int = utils::view_to_number(child_id);
89 if (opt_int.has_value()) {
90 auto cluster_idx = opt_int.value();
91 if (cluster_idx < 0 or clusters.size() < cluster_idx)
93 return &clusters[cluster_idx];
95 if (child_id ==
"CTRL")
97 if (child_id.size() == 17)
102ConfigResult carrier::Carrier::config(
const pb_Config &cfg) {
104 return ConfigResult::err(
"Carrier cannot be configured without hardware");
106 if (cfg.which_kind == pb_Config_adc_config_tag) {
107 auto& carrier_config = cfg.kind.adc_config;
109 adc_channels.fill(ADC_CHANNEL_DISABLED);
110 size_t min_size = std::min(
111 static_cast<size_t>(carrier_config.channels_count),
115 for (
size_t idx = 0; idx < min_size; ++idx) {
116 auto& config_channel = carrier_config.channels[idx];
117 adc_channels[idx] = config_channel.idx;
118 adc_gains[idx] = config_channel.gain;
119 adc_offsets[idx] = config_channel.offset;
122 auto res = hardware->write_adc_bus_mux(adc_channels);
124 return ConfigResult::err(
"Could not configure ACLs from configuration");
126 return ConfigResult::ok(
true);
129 return ConfigResult::ok(
false);
132void carrier::Carrier::extract(entities::ExtractVisitor &collector) {
133 Entity::extract(collector);
135 auto& cfg = collector.create(pb_Config_adc_config_tag);
136 auto& carrier_config = cfg.kind.adc_config;
137 for (
size_t idx = 0; idx < adc_channels.size(); ++idx) {
138 auto channel = adc_channels[idx];
139 if (channel == ADC_CHANNEL_DISABLED)
continue;
140 carrier_config.channels[carrier_config.channels_count++] = {
141 .idx =
static_cast<uint32_t>(channel),
142 .gain = adc_gains[idx],
143 .offset = adc_offsets[idx],
148status carrier::Carrier::write_to_hardware() {
150 int cluster_index = 1;
151 for (
auto &cluster : clusters) {
152 if (!cluster.write_to_hardware()) {
153 error.code += cluster_index;
154 error.msg +=
"Cluster write failed.";
159 error.attach(write_adcs_to_hardware());
164status carrier::Carrier::calibrate_offsets() {
165 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
168 for (
auto &cluster : clusters)
169 success.attach(cluster.calibrate_offsets());
172 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
175status carrier::Carrier::calibrate_routes() {
176 entities::Setup
setup;
178 status result = calibrate_routes_raw();
179 setup.apply(
this,
true);
186status carrier::Carrier::calibrate_routes_raw() {
187 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
191 bool gain_correction_exceeding =
false;
192 for (
auto &cluster : clusters) {
193 LOG_ANABRID_DEBUG_CALIBRATION(
194 (
"Calibrating routes in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
196 auto old_adcbus = ctrl_block->get_adc_bus();
197 auto old_adc_channels = get_adc_channels();
199 reset_adc_channels();
201 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
202 if (!ctrl_block->write_to_hardware())
203 success.attach(
"Writing to ctrl-block failed");
206 LOG_ANABRID_DEBUG_CALIBRATION(
"Starting calibration");
207 auto old_transmission_modes = cluster.ublock->get_all_transmission_modes();
208 auto old_reference_magnitude = cluster.ublock->get_reference_magnitude();
211 LOG_ANABRID_DEBUG_CALIBRATION(
"Enable u-block reference");
212 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::POS_REF);
213 if (!cluster.ublock->write_to_hardware())
214 success.attach(
"Resetting u-block failed");
217 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset c-block");
218 auto old_c_block_factors = cluster.cblock->get_factors();
219 cluster.cblock->set_factors({});
220 if (!cluster.cblock->write_to_hardware())
221 success.attach(
"Resetting c-block failed");
224 blocks::MBlock *id_block =
nullptr;
225 if (cluster.m0block && cluster.m0block->has_id_lanes())
226 id_block = cluster.m0block;
228 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
229 id_block = cluster.m1block;
232 success.attach(
"No M Block with ID Lanes found, calibration impossible!");
236 uint8_t id_in_lane = 0, id_out_lane = 4;
237 for (
auto i = 0; i < id_block->ID_OUTPUT_CONNECTIONS().
size(); i++) {
238 if (id_block->ID_OUTPUT_CONNECTIONS()[i] != -1) {
239 id_out_lane = id_block->slot_to_global_io_index(i);
240 id_in_lane = id_block->slot_to_global_io_index(id_block->ID_OUTPUT_CONNECTIONS()[i]);
245 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections;
246 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
247 for (
auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
250 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
255 if (!cluster.ublock->is_output_connected(i_in_idx))
259 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
263 LOG_ANABRID_DEBUG_CALIBRATION(
"Reset i-block");
264 cluster.iblock->reset_outputs();
265 if (!cluster.iblock->write_to_hardware())
266 success.attach(
"Resetting i-block failed");
270 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
271 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
272 if (!cluster.iblock->connect(i_in_idx, id_in_lane))
273 LOG_ANABRID_DEBUG_CALIBRATION(
"Connecting i-block failed");
275 if (!cluster.iblock->write_to_hardware())
276 success.attach(
"Writing to i-block failed");
279 for (
auto i_in_idx : old_i_block_connections[i_out_idx]) {
281 if (!set_adc_channel(0, id_out_lane))
282 success.attach(
"id_out_lane invalid");
283 if (!hardware->write_adc_bus_mux(adc_channels))
284 success.attach(
"Writing adcs failed!");
288 bool upscaled_channel = cluster.iblock->get_upscaling(i_in_idx);
289 cluster.ublock->change_reference_magnitude(upscaled_channel
290 ? blocks::UBlock::Reference_Magnitude::ONE_TENTH
291 : blocks::UBlock::Reference_Magnitude::ONE);
292 if (!cluster.ublock->write_to_hardware())
293 success.attach(
"Writing to u-block failed");
297 (void)cluster.cblock->set_factor(i_in_idx, 0.0f);
298 (void)cluster.cblock->set_gain_correction(i_in_idx, 1.0f);
299 if (!cluster.cblock->write_to_hardware())
300 success.attach(
"Writing to c-block failed");
303 success.attach(calibrate_offsets());
305 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
309 (void)cluster.cblock->set_factor(i_in_idx, 1.0f);
310 if (!cluster.cblock->write_to_hardware())
311 success.attach(
"Writing to c-block failed");
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 if (!cluster.cblock->set_gain_correction(i_in_idx, gain_correction)) {
327 (void)cluster.cblock->set_gain_correction(i_in_idx, 1.0f);
328 success.attach(
"Gain correction could not be set as it is out of range. Resetting this "
329 "channel to default correction");
332 (void)cluster.cblock->set_factor(i_in_idx, 0.0f);
334 LOG_ANABRID_DEBUG_CALIBRATION(
" ");
337 cluster.iblock->reset_outputs();
338 reset_adc_channels();
342 cluster.ublock->change_all_transmission_modes(old_transmission_modes);
343 cluster.ublock->change_reference_magnitude(old_reference_magnitude);
345 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring u-block");
346 if (!cluster.ublock->write_to_hardware())
347 success.attach(
"Restoring u-block failed");
350 cluster.cblock->set_factors(old_c_block_factors);
351 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring c-block");
352 if (!cluster.cblock->write_to_hardware())
353 success.attach(
"Restoring c-block failed");
356 LOG_ANABRID_DEBUG_CALIBRATION(
"Restoring i-block");
357 for (
auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
358 for (
auto i_in_idx : old_i_block_connections[i_out_idx])
359 if (!cluster.iblock->connect(i_in_idx, i_out_idx))
360 LOG_ANABRID_DEBUG_CALIBRATION(
"Connecting i-block failed");
362 if (!cluster.iblock->write_to_hardware())
363 success.attach(
"Restoring i-block failed");
366 ctrl_block->set_adc_bus(old_adcbus);
367 if (!ctrl_block->write_to_hardware())
368 success.attach(
"Writing to ctrl-block failed");
370 (void)set_adc_channels(old_adc_channels);
371 if (!hardware->write_adc_bus_mux(adc_channels))
372 success.attach(
"Writing adcs failed");
375 if (gain_correction_exceeding)
376 success.attach(
"Gain correction is too high, this is probably a problem with the hardware");
380 success.attach(Carrier::calibrate_offsets());
381 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
385status carrier::Carrier::calibrate_mblock(platform::Cluster &cluster, blocks::MBlock &mblock) {
387 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
396 LOG(ANABRID_DEBUG_CALIBRATION,
"Connecting outputs to ADC...");
397 for (
auto output_idx : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE()) {
398 auto lane_idx = mblock.slot_to_global_io_index(output_idx);
399 if (!set_adc_channel(output_idx, lane_idx, cluster.get_cluster_idx()))
400 success.attach(
"Writing adc select failed");
403 success.attach(write_to_hardware());
406 LOG(ANABRID_DEBUG_CALIBRATION,
"Passing control to M-block...");
407 success.attach(mblock.calibrate(&cluster,
this));
409 LOG(ANABRID_DEBUG_CALIBRATION,
"Cleanup ADC connections...");
410 reset_adc_channels();
412 LOG(ANABRID_DEBUG_CALIBRATION,
"Cleaning up calibration signals...");
413 reset(entities::ResetAction::CIRCUIT_RESET);
416 success.attach(write_to_hardware());
418 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibration done.");
419 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
424status carrier::Carrier::calibrate_m_blocks() {
426 for (
auto &cluster : clusters)
427 for (
auto mblock : {cluster.m0block, cluster.m1block})
429 success.attach(calibrate_mblock(cluster, *mblock));
434void carrier::Carrier::reset(entities::ResetAction action) {
435 for (
auto &cluster : clusters) {
436 cluster.reset(action);
439 ctrl_block->reset(action);
440 reset_adc_channels();
443const std::array<int8_t, 8> &carrier::Carrier::get_adc_channels()
const {
return adc_channels; }
444const std::array<double, 8> &carrier::Carrier::get_adc_gains()
const {
return adc_gains; }
445const std::array<double, 8> &carrier::Carrier::get_adc_offsets()
const {
return adc_offsets; }
447bool carrier::Carrier::set_adc_channels(
const std::array<int8_t, 8> &channels) {
449 for (
auto channel : channels) {
452 if (channel >= clusters.size() * 16)
458 for (
auto &channel : channels) {
461 for (
auto &other_channel : channels) {
462 if (std::addressof(channel) == std::addressof(other_channel))
464 if (channel == other_channel)
468 adc_channels = channels;
472bool carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_channel) {
473 if (adc_channel >= adc_channels.size())
476 src_channel = ADC_CHANNEL_DISABLED;
480 if (src_channel != ADC_CHANNEL_DISABLED)
481 for (
auto other_idx = 0u; other_idx < adc_channels.size(); other_idx++)
482 if (adc_channel != other_idx and adc_channels[other_idx] == src_channel)
485 adc_channels[adc_channel] = src_channel;
489bool carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx, uint8_t cluster_idx) {
490 return Carrier::set_adc_channel(adc_channel, src_idx + cluster_idx * 16);
493void carrier::Carrier::reset_adc_channels() {
494 adc_channels.fill(ADC_CHANNEL_DISABLED);
497status carrier::Carrier::measure_all_signals(std::array<std::array<float, 8>, 6> &data) {
498 auto old_adc_channels = get_adc_channels();
499 reset_adc_channels();
500 size_t idx =
static_cast<size_t>(-1);
501 for (
const auto &cluster : clusters) {
502 for (
const auto mblock : {cluster.m0block, cluster.m1block}) {
504 if (!mblock)
continue;
506 for (
auto slot : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE())
507 if (!set_adc_channel(slot, mblock->slot_to_global_io_index(slot), cluster.get_cluster_idx()))
508 return status(
"Error while setting ADC channels.");
509 if (!write_to_hardware())
510 return status(
"Error while writing ADC channels.");
511 data[idx] = daq::average();
514 if (!set_adc_channels(old_adc_channels) or !write_to_hardware())
515 LOG_ERROR(
"Error while restoring ADC channels.");
516 return status::success();
519status carrier::Carrier::write_adcs_to_hardware() {
522 if (ctrl_block && !ctrl_block->write_to_hardware()) {
524 error.msg +=
"CTRL Block write failed.";
526 if (!hardware->write_adc_bus_mux(adc_channels)) {
528 error.msg +=
"ADC Bus write failed.";
534status carrier::Carrier::user_set_extended_config(Carrier*
carrier,
const pb_ConfigCommand& msg_in, pb_ConfigResponse &msg_out) {
535#ifdef ANABRID_DEBUG_COMMS
536 Serial.println(__PRETTY_FUNCTION__);
539 bool default_reset_before =
true, default_calibrate_mblock =
false, default_calibrate_offset =
false, default_calibrate_routes =
true;
541 if (msg_in.reset_before | default_reset_before) {
542 carrier->reset(entities::ResetAction::CIRCUIT_RESET | entities::ResetAction::OVERLOAD_RESET);
543 (void)
carrier->write_to_hardware();
546 if(msg_in.calibrate_mblock || default_calibrate_mblock)
547 RETURN_IF_FAILED(
carrier->calibrate_m_blocks());
554 if (msg_in.calibrate_offset || default_calibrate_offset)
555 RETURN_IF_FAILED(
carrier->calibrate_offsets());
557 if (msg_in.calibrate_routes || default_calibrate_routes)
558 RETURN_IF_FAILED(
carrier->calibrate_routes());
560 return status::success();
563status carrier::Carrier::user_get_overload_status(pb_OverloadStatus &overload_status) {
564 entities::OverloadVisitor visitor;
565 visitor.visit(
this,
true);
566 visitor.to(overload_status);
567 return status::success();
static constexpr int success
__attribute__((section(".fastrun"), noinline, noclone, optimize("Os"))) int flash_sector_not_erased(uint32_t address)