REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
mblock_mul.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
4
5#include <algorithm>
6#include <bitset>
7
8#include "block/mblock.h"
9#include "utils/logging.h"
10
11#include "entity/entity.h"
12#include "etl/crc.h"
13
14#include "carrier/carrier.h"
15#include "carrier/cluster.h"
16
17#include "teensy/mblock_mul.h"
18#include <chips/AD840X.h>
19#include <chips/DAC60508.h>
20#include <chips/SR74HC16X.h>
21#include <chips/SR74HCT595.h>
22
23extern int abs_clamp(float in, int min, int max);
24
25// V1.-1.0
26
28 auto res = MMulBlock::write_calibration_to_hardware();
29 if (!res)
30 return res;
31
32 for (size_t i = 0; i < MMulBlock::NUM_MULTIPLIERS; i++) {
33 if (!hardware->write_calibration_gain(i, calibration[i].gain))
34 return utils::status(777, "MMulBlock::calibration from json for multiplier %d values gain not accepted",
35 i);
36 }
37 return utils::status::success();
38}
39
40FLASHMEM bool blocks::MMulBlock_FullAutoCalibration::calibrate(platform::Cluster *cluster,
41 carrier::Carrier *carrier) {
42 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
43
44 // First do regular calibration
45 bool success = MMulBlock::calibrate(cluster, carrier);
46
47 // Automatic gain calibration can only be done by version 1.1
48 LOG(ANABRID_DEBUG_CALIBRATION, "Calibrating output gains...");
49
50 for (auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
51 if (!cluster->cblock->set_factor(slot_to_global_io_index(idx * 2),
52 1.0f)) // Setting 1.0 to Y inputs which previously were 0.0
53 return false; // fatal error
54 }
55 if (!cluster->cblock->write_to_hardware())
56 return false; // fatal error
57 // When changing a factor, we always have to calibrate offset
58 if (!cluster->calibrate_offsets())
59 return false; // fatal error
60
61 delay(10);
62
63 const float target_precision = 0.0005f;
64 const int max_loops = 100;
65
66 std::bitset<NUM_MULTIPLIERS> done_channels;
67 int loop_count = 0;
68
69 // start varying the gain factors
70 while (!done_channels.all()) {
71 auto read_outputs = daq::average(daq::sample, 4, 10);
72
73 for (auto idx = 0u; idx < NUM_MULTIPLIERS; idx++) {
74 if (fabs(read_outputs[idx] - 1.0f) < target_precision) {
75 done_channels[idx] = true; // Already precice
76 continue;
77 }
78 done_channels[idx] = false;
79
80 // Little bounded proportional controller, to decrease calibration time
81 int step = abs_clamp((read_outputs[idx] - 1.0f) * -1000.0f, 1, 70);
82
83 if (calibration[idx].gain + step > 0xff || calibration[idx].gain + step < 0) {
84 success = false; // Out of bounds for factor
85 done_channels[idx] = true;
86 continue;
87 }
88
89 calibration[idx].gain += step;
90
91 if (!hardware->write_calibration_gain(idx, calibration[idx].gain)) {
92 success = false; // Other issues
93 done_channels[idx] = true;
94 continue;
95 }
96 }
97 delay(10); // Small transient time
98
99 loop_count++;
100 if (loop_count > max_loops) {
101 LOG(ANABRID_DEBUG_CALIBRATION, "Calibration timed out!");
102 break;
103 }
104 }
105
106 return success;
107}
108
109// Hardware abstraction layer
110
111FLASHMEM blocks::MMulBlockHAL_V_1_0_X::MMulBlockHAL_V_1_0_X(bus::addr_t block_address)
112 : f_meta(block_address), f_overload_flags_reset(bus::address_from_tuple(block_address, 3)),
113 f_overload_flags(bus::replace_function_idx(block_address, 2)),
114 f_calibration_dac_0(bus::address_from_tuple(block_address, 4), 2.0f),
115 f_calibration_dac_1(bus::address_from_tuple(block_address, 5), 2.0f) {}
116
117FLASHMEM bool blocks::MMulBlockHAL::init() { return MBlockHAL::init(); }
118
120 bool error = true;
121 error &= f_calibration_dac_0.init();
122 error &= f_calibration_dac_0.set_external_reference();
123 error &= f_calibration_dac_0.set_double_gain();
124 error &= f_calibration_dac_1.init();
125 error &= f_calibration_dac_1.set_external_reference();
126 error &= f_calibration_dac_1.set_double_gain();
127 error &= MMulBlockHAL::init();
128 return error;
129}
130
131FLASHMEM void blocks::MMulBlockHAL_V_1_0_X::reset_overload_flags() { f_overload_flags_reset.trigger(); }
132
133FLASHMEM bool blocks::MMulBlockHAL_V_1_0_X::write_calibration_input_offsets(uint8_t idx, uint16_t offset_x,
134 uint16_t offset_y) {
135 return f_calibration_dac_0.set_channel_raw(idx * 2 + 1, offset_x) and
136 f_calibration_dac_0.set_channel_raw(idx * 2, offset_y);
137}
138
139FLASHMEM bool blocks::MMulBlockHAL_V_1_0_X::write_calibration_output_offset(uint8_t idx, uint16_t offset_z) {
140 return f_calibration_dac_1.set_channel_raw(idx, offset_z);
141}
142
144 return f_overload_flags.read8();
145}
146
149 : MMulBlock(slot, hardware), hardware(hardware) {}
150
152 : MMulBlockHAL_V_1_0_X(block_address), f_gain_ch0_1(bus::replace_function_idx(block_address, 6)),
153 f_gain_ch2_3(bus::replace_function_idx(block_address, 7)) {}
154
155FLASHMEM bool blocks::MMulBlockHAL_V_1_M1_X::write_calibration_gain(uint8_t idx, uint8_t gain) {
156 if (idx < 2)
157 return f_gain_ch0_1.write_channel_raw(idx, gain);
158 else if (idx < 4)
159 return f_gain_ch2_3.write_channel_raw(idx - 2, gain);
160 else
161 return false;
162}
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
bool write_calibration_gain(uint8_t idx, uint8_t gain)
MMulBlockHAL_V_1_M1_X(bus::addr_t block_address)
MMulBlockHAL_V_1_M1_X * hardware
Definition mblock_mul.h:78
bool calibrate(platform::Cluster *cluster, carrier::Carrier *carrier) override
utils::status write_calibration_to_hardware() override
MMulBlock_FullAutoCalibration(SLOT slot, blocks::MMulBlockHAL_V_1_M1_X *hardware)
int abs_clamp(float in, int min, int max)
Definition mblock.cpp:13
int abs_clamp(float in, int min, int max)
Definition mblock.cpp:13
Definition bus.h:21
Definition daq.h:14
static constexpr int success
Definition flasher.cpp:275