8#include "carrier/carrier.h"
9#include "carrier/cluster.h"
11#include "block/mblock.h"
14extern int abs_clamp(
float in,
int min,
int max);
16blocks::MMulBlock *blocks::MMulBlock::from_entity_classifier(entities::EntityClassifier classifier,
17 const bus::addr_t block_address) {
18 if (!classifier or classifier.class_enum != CLASS_ or classifier.type !=
static_cast<uint8_t
>(TYPE))
22 if (classifier.variant != entities::EntityClassifier::DEFAULT_)
25 SLOT slot = block_address % 8 == 4 ? SLOT::M0 : SLOT::M1;
27 if (classifier.version < entities::Version(1))
29 if (classifier.version < entities::Version(1, 1)) {
30 auto *new_block =
new MMulBlock(slot,
new MMulBlockHAL_V_1_0_X(block_address));
31 new_block->classifier = classifier;
34 if (classifier.version <= entities::Version(1, 2)) {
35 auto *new_block =
new MMulBlock_FullAutoCalibration(slot,
new MMulBlockHAL_V_1_1_X(block_address));
36 new_block->classifier = classifier;
39 if (classifier.version == entities::Version(1, -1)) {
40 auto *new_block =
new MMulBlock_FullAutoCalibration(slot,
new MMulBlockHAL_V_1_M1_X(block_address));
41 new_block->classifier = classifier;
47status blocks::MMulBlock::calibrate(platform::Cluster *cluster, carrier::Carrier *
carrier) {
50 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
62 cluster->reset(entities::ResetAction::CIRCUIT_RESET);
65 reset(entities::ResetAction::CALIBRATION_RESET);
68 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating output offsets...");
69 for (
auto idx : SLOT_INPUT_IDX_RANGE())
70 success.attach(cluster->add_constant(UBlock::Transmission_Mode::GROUND, slot_to_global_io_index(idx), 0.0f,
71 slot_to_global_io_index(idx)));
72 success.attach(cluster->write_to_hardware());
78 auto read_outputs = daq::average(daq::sample, 4, 10);
80 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
81 calibration[idx].offset_z = MMulBlockHAL_V_1_0_X::float_to_raw_calibration(-read_outputs[idx]);
82 if (!hardware->write_calibration_output_offset(idx, calibration[idx].offset_z))
83 success.attach(
"Writing output offsets failed");
88 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating x input offsets...");
89 cluster->ublock->change_b_side_transmission_mode(UBlock::Transmission_Mode::POS_REF);
90 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++)
91 (
void)cluster->cblock->set_factor(slot_to_global_io_index(idx * 2), 1.0f);
93 if (!cluster->cblock->write_to_hardware())
94 success.attach(
"Writing to c-block failed");
96 success.attach(cluster->calibrate_offsets());
100 const float target_precision = 0.0005f;
101 const int max_loops = 100;
103 std::bitset<NUM_MULTIPLIERS> done_channels;
107 while (!done_channels.all()) {
108 read_outputs = daq::average(daq::sample, 4, 10);
110 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
111 if (fabs(read_outputs[idx]) < target_precision) {
112 done_channels[idx] =
true;
115 done_channels[idx] =
false;
118 calibration[idx].offset_x +=
abs_clamp(read_outputs[idx] * 6000.0f, 1, 50);
120 if (!hardware->write_calibration_input_offsets(idx, calibration[idx].offset_x,
121 calibration[idx].offset_y)) {
122 calibration[idx].offset_x = std::clamp(
123 calibration[idx].offset_x,
124 MMulBlockHAL_V_1_0_X::RAW_ZERO,
125 MMulBlockHAL_V_1_0_X::RAW_MAX
127 success.attach(
"Input X offsets out of range");
128 done_channels[idx] =
true;
135 if (loop_count > max_loops) {
136 success.attach(
"Calibration timed out!");
141 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating y input offsets...");
142 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
145 (void)cluster->cblock->set_factor(slot_to_global_io_index(idx * 2), 0.0f);
146 (void)cluster->cblock->set_factor(slot_to_global_io_index(idx * 2 + 1), 1.0f);
148 if (!cluster->cblock->write_to_hardware())
149 success.attach(
"Writing to c-block failed");
151 success.attach(cluster->calibrate_offsets());
155 read_outputs = daq::average(daq::sample, 4, 10);
157 done_channels.reset();
161 while (!done_channels.all()) {
162 read_outputs = daq::average(daq::sample, 4, 10);
164 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
165 if (fabs(read_outputs[idx]) < target_precision) {
166 done_channels[idx] =
true;
169 done_channels[idx] =
false;
172 calibration[idx].offset_y +=
abs_clamp(read_outputs[idx] * 6000.0f, 1, 50);
174 if (!hardware->write_calibration_input_offsets(idx, calibration[idx].offset_x,
175 calibration[idx].offset_y)) {
176 calibration[idx].offset_y = std::clamp(calibration[idx].offset_y, MMulBlockHAL_V_1_0_X::RAW_ZERO,
177 MMulBlockHAL_V_1_0_X::RAW_MAX);
178 success.attach(
"Input Y offsets out of range");
179 done_channels[idx] =
true;
186 if (loop_count > max_loops) {
187 success.attach(
"Calibration timed out!");
202 auto res = MMulBlock::write_calibration_to_hardware();
206 for (
size_t i = 0; i < MMulBlock::NUM_MULTIPLIERS; i++) {
207 if (!
hardware->write_calibration_gain(i, calibration[i].gain))
208 return utils::status(777,
"MMulBlock::calibration from json for multiplier %d values gain not accepted",
211 return utils::status::success();
217 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
223 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating output gains...");
226 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++)
227 (
void)cluster->cblock->set_factor(slot_to_global_io_index(idx * 2), 1.0f);
229 if (!cluster->cblock->write_to_hardware())
230 success.attach(
"Writing to c-block failed");
232 success.attach(cluster->calibrate_offsets());
236 const float target_precision = 0.0005f;
237 const int max_loops = 100;
239 std::bitset<NUM_MULTIPLIERS> done_channels;
243 while (!done_channels.all()) {
244 auto read_outputs = daq::average(daq::sample, 4, 10);
246 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
247 if (fabs(read_outputs[idx] - 1.0f) < target_precision) {
248 done_channels[idx] =
true;
251 done_channels[idx] =
false;
254 int step =
abs_clamp((read_outputs[idx] - 1.0f) * -1000.0f, 1, 70);
256 if (calibration[idx].gain + step > 0xff || calibration[idx].gain + step < 0) {
257 success.attach(
"Output gain out of range");
258 done_channels[idx] =
true;
262 calibration[idx].gain += step;
264 if (!
hardware->write_calibration_gain(idx, calibration[idx].gain)) {
265 success.attach(
"Writing output gain failed");
266 done_channels[idx] =
true;
273 if (loop_count > max_loops) {
274 success.attach(
"Calibration timed out!");
290bool blocks::MMulBlockHAL::init() {
return MBlockHAL::init(); }
300 error &= MMulBlockHAL::init();
338 return f_gain.write_channel_raw(2, gain);
340 return f_gain.write_channel_raw(0, gain);
342 return f_gain.write_channel_raw(1, gain);
344 return f_gain.write_channel_raw(3, gain);
bool write_calibration_output_offset(uint8_t idx, uint16_t offset_z) override
const functions::TriggerFunction f_overload_flags_reset
std::bitset< 8 > read_overload_flags() override
void reset_overload_flags() override
const functions::SR74HC16X f_overload_flags
MMulBlockHAL_V_1_0_X(bus::addr_t block_address)
const functions::DAC60508 f_calibration_dac_0
bool write_calibration_input_offsets(uint8_t idx, uint16_t offset_x, uint16_t offset_y) override
const functions::DAC60508 f_calibration_dac_1
MMulBlockHAL_V_1_1_X(bus::addr_t block_address)
bool write_calibration_gain(uint8_t idx, uint8_t gain) override
functions::AD8402 f_gain_ch0_1
functions::AD8402 f_gain_ch2_3
MMulBlockHAL_V_1_M1_X(bus::addr_t block_address)
bool write_calibration_gain(uint8_t idx, uint8_t gain) override
MMulBlock_FullAutoCalibration(SLOT slot, blocks::MMulBlockHAL_FullAutoCalibration *hardware)
MMulBlockHAL_FullAutoCalibration * hardware
status calibrate(platform::Cluster *cluster, carrier::Carrier *carrier) override
status write_calibration_to_hardware() override
int abs_clamp(float in, int min, int max)
int abs_clamp(float in, int min, int max)
static constexpr int success
entities::EntitySharedHardware< MMulBlockHAL > MMulBlockHAL_Parent