REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
cblock.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 <block/cblock.h>
6#include <cstring>
7#include <entity/visitor.h>
8#include <utils/logging.h>
9
10blocks::CBlock::CBlock(CBlockHAL *hardware) : FunctionBlock("C", hardware), hardware(hardware) {
11 classifier.class_enum = CLASS_;
12}
13
14blocks::CBlock::CBlock() : CBlock(new CBlockHALDummy()) {}
15
16float blocks::CBlock::get_factor(uint8_t idx) {
17 if (idx >= NUM_COEFF)
18 return 0.0f;
19 return factors_[idx];
20}
21
22const std::array<float, blocks::CBlock::NUM_COEFF> &blocks::CBlock::get_factors() const {
23 return factors_;
24}
25
26UnitResult blocks::CBlock::set_factor(uint8_t idx, float factor) {
27 if (idx >= NUM_COEFF)
28 return UnitResult::err_fmt("Error c-block factor idx to high %d", idx);
29 if (factor > MAX_FACTOR or factor < MIN_FACTOR)
30 return UnitResult::err_fmt("Error c-block factor outside range %f", factor);
31 factors_[idx] = factor;
32 return UnitResult::ok();
33}
34
35void blocks::CBlock::set_factors(const std::array<float, NUM_COEFF> &factors) { factors_ = factors; }
36
37UnitResult blocks::CBlock::write_to_hardware() {
38 if (!write_factors_to_hardware()) {
39 LOG(ANABRID_PEDANTIC, __PRETTY_FUNCTION__);
40 return UnitResult::err("Writing to c-block factors failed");
41 }
42 return UnitResult::ok();
43}
44
45bool blocks::CBlock::write_factors_to_hardware() {
46 for (size_t i = 0; i < factors_.size(); i++) {
47 auto factor = factors_[i] * gain_corrections_[i];
48 if (!hardware->write_factor(i, factor))
49 return false;
50 }
51 return true;
52}
53
54void blocks::CBlock::reset(entities::ResetAction action) {
55 FunctionBlock::reset(action);
56
57 if (action.has(entities::ResetAction::CIRCUIT_RESET))
58 for (size_t i = 0; i < NUM_COEFF; i++)
59 (void)set_factor(i, 1.0f);
60
61 if (action.has(entities::ResetAction::CALIBRATION_RESET))
62 reset_gain_corrections();
63}
64
65float blocks::CBlock::get_gain_correction(uint8_t idx) const {
66 if (idx > NUM_COEFF)
67 return -2.0f;
68 return gain_corrections_[idx];
69}
70
71const std::array<float, blocks::CBlock::NUM_COEFF> &blocks::CBlock::get_gain_corrections() const {
72 return gain_corrections_;
73}
74
75void blocks::CBlock::reset_gain_corrections() {
76 std::fill(gain_corrections_.begin(), gain_corrections_.end(), 1.0f);
77}
78
79UnitResult blocks::CBlock::set_gain_corrections(const std::array<float, NUM_COEFF> &corrections) {
80 for (size_t idx = 0; idx < NUM_COEFF; idx++) {
81 TRY(set_gain_correction(idx, corrections[idx]));
82 }
83 return UnitResult::ok();
84}
85
86UnitResult blocks::CBlock::set_gain_correction(const uint8_t coeff_idx, const float correction) {
87 if (coeff_idx > NUM_COEFF)
88 return UnitResult::err_fmt("Error c-block coef idx out of range: %d", coeff_idx);
89 // Gain correction must be positive and close to 1
90 if (correction < 0.0f || correction > MAX_GAIN_CORRECTION_ABS + 1.0f)
91 return UnitResult::err_fmt("Error c-block coef gain correction out of range: %d %f", coeff_idx, correction);
92
93 gain_corrections_[coeff_idx] = correction;
94 return UnitResult::ok();
95};
96
97ConfigResult blocks::CBlock::config(const pb_Item &item) {
98#ifdef ANABRID_DEBUG_ENTITY_CONFIG
99 Serial.println(__PRETTY_FUNCTION__);
100#endif
101 if (item.which_kind != pb_Item_coef_config_tag)
102 return ConfigResult::err("expected coef block config");
103
104 auto& coef_config = item.kind.coef_config;
105 return _apply_elements(coef_config);
106}
107
108ConfigResult blocks::CBlock::_apply_elements(const pb_CoefConfig &item) {
109 // Handle an array of factors
110 for (size_t elem_idx = 0; elem_idx < item.elements_count; ++elem_idx) {
111 auto& element = item.elements[elem_idx];
112 TRY(set_factor(element.idx, element.factor));
113 if (element.has_gain_correction )
114 TRY(set_gain_correction(element.idx, element.gain_correction));
115 }
116
117 return ConfigResult::ok(true);
118}
119
120void blocks::CBlock::extract(entities::ExtractVisitor &collector) {
121
122 if (!collector.include_configuration() && !collector.include_calibration()) return;
123 auto& item = collector.create(pb_Item_coef_config_tag);
124 auto& coef_config = item.kind.coef_config;
125 coef_config.elements_count = NUM_COEFF;
126 auto& idx = coef_config.elements_count = 0;
127 for (;idx < NUM_COEFF; ++idx) {
128 auto& elem = coef_config.elements[idx];
129 elem.idx = idx;
130
131 if (collector.include_configuration()) {
132 elem.factor = factors_[idx];
133 }
134
135 if (collector.include_calibration()) {
136 elem.has_gain_correction = true;
137 elem.gain_correction = gain_corrections_[idx];
138 }
139 }
140}