8#include "block/mblock.h"
9#include "utils/logging.h"
11#include "entity/entity.h"
14#include "carrier/carrier.h"
15#include "carrier/cluster.h"
23extern int abs_clamp(
float in,
int min,
int max);
25FLASHMEM blocks::MMulBlock *blocks::MMulBlock::from_entity_classifier(entities::EntityClassifier classifier,
26 const bus::addr_t block_address) {
27 if (!classifier or classifier.class_enum != CLASS_ or classifier.type !=
static_cast<uint8_t
>(TYPE))
31 if (classifier.variant != entities::EntityClassifier::DEFAULT_)
34 SLOT slot = block_address % 8 == 4 ? SLOT::M0 : SLOT::M1;
36 if (classifier.version < entities::Version(1))
38 if (classifier.version < entities::Version(1, 1)) {
39 auto *new_block =
new MMulBlock(slot,
new MMulBlockHAL_V_1_0_X(block_address));
40 new_block->classifier = classifier;
43 if (classifier.version <= entities::Version(1, 2)) {
44 auto *new_block =
new MMulBlock_FullAutoCalibration(slot,
new MMulBlockHAL_V_1_1_X(block_address));
45 new_block->classifier = classifier;
48 if (classifier.version == entities::Version(1, -1)) {
49 auto *new_block =
new MMulBlock_FullAutoCalibration(slot,
new MMulBlockHAL_V_1_M1_X(block_address));
50 new_block->classifier = classifier;
56FLASHMEM
bool blocks::MMulBlock::calibrate(platform::Cluster *cluster, carrier::Carrier *
carrier) {
57 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
66 if (!MBlock::calibrate(cluster,
carrier))
70 cluster->reset(entities::ResetAction::CIRCUIT_RESET);
73 reset(entities::ResetAction::CALIBRATION_RESET);
77 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating output offsets...");
78 for (
auto idx : SLOT_INPUT_IDX_RANGE())
79 if (!cluster->add_constant(UBlock::Transmission_Mode::GROUND, slot_to_global_io_index(idx), 0.0f,
80 slot_to_global_io_index(idx)))
82 if (!cluster->write_to_hardware())
86 if (!
carrier->calibrate_routes_in_cluster(*cluster))
87 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating routes failed!");
90 auto read_outputs = daq::average(daq::sample, 4, 10);
92 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
93 calibration[idx].offset_z = MMulBlockHAL_V_1_0_X::float_to_raw_calibration(-read_outputs[idx]);
94 if (!hardware->write_calibration_output_offset(idx, calibration[idx].offset_z))
100 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating x input offsets...");
101 cluster->ublock->change_b_side_transmission_mode(UBlock::Transmission_Mode::POS_REF);
102 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
103 if (!cluster->cblock->set_factor(slot_to_global_io_index(idx * 2), 1.0f))
106 if (!cluster->cblock->write_to_hardware())
109 if (!cluster->calibrate_offsets())
114 const float target_precision = 0.0005f;
115 const int max_loops = 100;
117 std::bitset<NUM_MULTIPLIERS> done_channels;
121 while (!done_channels.all()) {
122 read_outputs = daq::average(daq::sample, 4, 10);
124 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
125 if (fabs(read_outputs[idx]) < target_precision) {
126 done_channels[idx] =
true;
129 done_channels[idx] =
false;
132 calibration[idx].offset_x +=
abs_clamp(read_outputs[idx] * 6000.0f, 1, 50);
134 if (!hardware->write_calibration_input_offsets(idx, calibration[idx].offset_x,
135 calibration[idx].offset_y)) {
136 calibration[idx].offset_x = std::clamp(calibration[idx].offset_x, MMulBlockHAL_V_1_0_X::RAW_ZERO,
137 MMulBlockHAL_V_1_0_X::RAW_MAX);
139 done_channels[idx] =
true;
140 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating out of bounds!");
147 if (loop_count > max_loops) {
148 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibration timed out!");
153 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating y input offsets...");
154 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
155 if (!cluster->cblock->set_factor(slot_to_global_io_index(idx * 2),
159 if (!cluster->cblock->set_factor(slot_to_global_io_index(idx * 2 + 1), 1.0f))
162 if (!cluster->cblock->write_to_hardware())
165 if (!cluster->calibrate_offsets())
170 read_outputs = daq::average(daq::sample, 4, 10);
172 done_channels.reset();
176 while (!done_channels.all()) {
177 read_outputs = daq::average(daq::sample, 4, 10);
179 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
180 if (fabs(read_outputs[idx]) < target_precision) {
181 done_channels[idx] =
true;
184 done_channels[idx] =
false;
187 calibration[idx].offset_y +=
abs_clamp(read_outputs[idx] * 6000.0f, 1, 50);
189 if (!hardware->write_calibration_input_offsets(idx, calibration[idx].offset_x,
190 calibration[idx].offset_y)) {
191 calibration[idx].offset_y = std::clamp(calibration[idx].offset_y, MMulBlockHAL_V_1_0_X::RAW_ZERO,
192 MMulBlockHAL_V_1_0_X::RAW_MAX);
194 done_channels[idx] =
true;
195 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating out of bounds!");
202 if (loop_count > max_loops) {
203 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibration timed out!");
215 : MMulBlock(slot, hardware), hardware(hardware) {}
218 auto res = MMulBlock::write_calibration_to_hardware();
222 for (
size_t i = 0; i < MMulBlock::NUM_MULTIPLIERS; i++) {
223 if (!hardware->write_calibration_gain(i, calibration[i].gain))
224 return utils::status(777,
"MMulBlock::calibration from json for multiplier %d values gain not accepted",
227 return utils::status::success();
232 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
238 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating output gains...");
240 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
241 if (!cluster->cblock->set_factor(slot_to_global_io_index(idx * 2),
245 if (!cluster->cblock->write_to_hardware())
248 if (!cluster->calibrate_offsets())
253 const float target_precision = 0.0005f;
254 const int max_loops = 100;
256 std::bitset<NUM_MULTIPLIERS> done_channels;
260 while (!done_channels.all()) {
261 auto read_outputs = daq::average(daq::sample, 4, 10);
263 for (
auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
264 if (fabs(read_outputs[idx] - 1.0f) < target_precision) {
265 done_channels[idx] =
true;
268 done_channels[idx] =
false;
271 int step =
abs_clamp((read_outputs[idx] - 1.0f) * -1000.0f, 1, 70);
273 if (calibration[idx].gain + step > 0xff || calibration[idx].gain + step < 0) {
275 done_channels[idx] =
true;
276 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibrating out of bounds!");
280 calibration[idx].gain += step;
282 if (!hardware->write_calibration_gain(idx, calibration[idx].gain)) {
284 done_channels[idx] =
true;
291 if (loop_count > max_loops) {
292 LOG(ANABRID_DEBUG_CALIBRATION,
"Calibration timed out!");
304 f_overload_flags_reset(
bus::address_from_tuple(block_address, 3)),
305 f_overload_flags(
bus::replace_function_idx(block_address, 2)),
306 f_calibration_dac_0(
bus::address_from_tuple(block_address, 4), 2.0f),
307 f_calibration_dac_1(
bus::address_from_tuple(block_address, 5), 2.0f) {}
309FLASHMEM
bool blocks::MMulBlockHAL::init() {
return MBlockHAL::init(); }
313 error &= f_calibration_dac_0.init();
314 error &= f_calibration_dac_0.set_external_reference();
315 error &= f_calibration_dac_0.set_double_gain();
316 error &= f_calibration_dac_1.init();
317 error &= f_calibration_dac_1.set_external_reference();
318 error &= f_calibration_dac_1.set_double_gain();
319 error &= MMulBlockHAL::init();
327 return f_calibration_dac_0.set_channel_raw(idx * 2 + 1, offset_x) and
328 f_calibration_dac_0.set_channel_raw(idx * 2, offset_y);
332 return f_calibration_dac_1.set_channel_raw(idx, offset_z);
336 return f_overload_flags.read8();
341 f_gain_ch2_3(
bus::replace_function_idx(block_address, 7)) {}
345 return f_gain_ch0_1.write_channel_raw(idx, gain);
347 return f_gain_ch2_3.write_channel_raw(idx - 2, gain);
357 return f_gain.write_channel_raw(2, gain);
359 return f_gain.write_channel_raw(0, gain);
361 return f_gain.write_channel_raw(1, gain);
363 return f_gain.write_channel_raw(3, gain);
std::bitset< 8 > read_overload_flags() override
bool write_calibration_output_offset(uint8_t idx, uint16_t offset_z) override
MMulBlockHAL_V_1_0_X(bus::addr_t block_address)
void reset_overload_flags() override
bool write_calibration_input_offsets(uint8_t idx, uint16_t offset_x, uint16_t offset_y) override
MMulBlockHAL_V_1_1_X(bus::addr_t block_address)
bool write_calibration_gain(uint8_t idx, uint8_t gain) override
bool write_calibration_gain(uint8_t idx, uint8_t gain) override
MMulBlockHAL_V_1_M1_X(bus::addr_t block_address)
MMulBlock_FullAutoCalibration(SLOT slot, blocks::MMulBlockHAL_FullAutoCalibration *hardware)
bool calibrate(platform::Cluster *cluster, carrier::Carrier *carrier) override
utils::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