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
26bool blocks::CBlock::set_factor(uint8_t idx, float factor) {
27 if (idx >= NUM_COEFF)
28 return false;
29 if (factor > MAX_FACTOR or factor < MIN_FACTOR)
30 return false;
31 factors_[idx] = factor;
32 return true;
33}
34
35void blocks::CBlock::set_factors(const std::array<float, NUM_COEFF> &factors) { factors_ = factors; }
36
37utils::status blocks::CBlock::write_to_hardware() {
38 if (!write_factors_to_hardware()) {
39 LOG(ANABRID_PEDANTIC, __PRETTY_FUNCTION__);
40 return utils::status::failure();
41 }
42 return utils::status::success();
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
79void blocks::CBlock::set_gain_corrections(const std::array<float, NUM_COEFF> &corrections) {
80 gain_corrections_ = corrections;
81};
82
83bool blocks::CBlock::set_gain_correction(const uint8_t coeff_idx, const float correction) {
84 if (coeff_idx > NUM_COEFF)
85 return false;
86 // Gain correction must be positive and close to 1
87 if (correction < 0.0f || correction > MAX_GAIN_CORRECTION_ABS + 1.0f)
88 return false;
89
90 gain_corrections_[coeff_idx] = correction;
91 return true;
92};
93
94ConfigResult blocks::CBlock::config(const pb_Config &cfg) {
95#ifdef ANABRID_DEBUG_ENTITY_CONFIG
96 Serial.println(__PRETTY_FUNCTION__);
97#endif
98 if (cfg.which_kind != pb_Config_coef_config_tag)
99 return ConfigResult::err("expected coef block config");
100
101 auto& coef_config = cfg.kind.coef_config;
102 return _apply_elements(coef_config);
103}
104
105ConfigResult blocks::CBlock::_apply_elements(const pb_CoefConfig &cfg) {
106 // Handle an array of factors
107 for (size_t elem_idx = 0; elem_idx < cfg.elements_count; ++elem_idx) {
108 auto& element = cfg.elements[elem_idx];
109 if (!set_factor(element.idx, element.factor))
110 return ConfigResult::err_fmt("CBlock factor %f is out of valid bounds", element.factor);
111 }
112
113 return ConfigResult::ok(true);
114}
115
116void blocks::CBlock::extract(entities::ExtractVisitor &collector) {
117 auto& cfg = collector.create(pb_Config_coef_config_tag);
118 auto& coef_config = cfg.kind.coef_config;
119 coef_config.elements_count = NUM_COEFF;
120 auto& idx = coef_config.elements_count = 0;
121 for (;idx < NUM_COEFF; ++idx) {
122 auto& elem = coef_config.elements[idx];
123 elem.idx = idx;
124 elem.factor = factors_[idx];
125 }
126}