REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
cluster.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 "carrier/cluster.h"
6#include "utils/logging.h"
7
8#include "block/cblock.h"
9#include "block/iblock.h"
10#include "block/mblock.h"
11#include "block/ublock.h"
12
13std::array<blocks::FunctionBlock *, 6> platform::Cluster::get_blocks() const { return {m0block, m1block, ublock, cblock, iblock, shblock}; }
14
15UnitResult platform::Cluster::init() {
16 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
17
18 // Dynamically detect installed blocks
19 // Check if a block is already set, which may happen with a special constructor in the future
20 LOG(ANABRID_DEBUG_INIT, "Detecting installed blocks...");
21 if (!m0block) {
22 m0block = entities::detect<blocks::MBlock>(bus::idx_to_addr(cluster_idx, bus::M0_BLOCK_IDX, 0));
23 if (!m0block)
24 LOG_ERROR("Warning: M0-block is missing or unknown.");
25 }
26 if (!m1block) {
27 m1block = entities::detect<blocks::MBlock>(bus::idx_to_addr(cluster_idx, bus::M1_BLOCK_IDX, 0));
28 if (!m1block)
29 LOG_ERROR("Warning: M1-block is missing or unknown.");
30 }
31
32 if (!ublock) {
33 ublock = entities::detect<blocks::UBlock>(bus::idx_to_addr(cluster_idx, bus::U_BLOCK_IDX, 0));
34 if (!ublock)
35 LOG_ERROR("Error: U-block is missing or unknown.");
36 }
37 if (!cblock) {
38 cblock = entities::detect<blocks::CBlock>(bus::idx_to_addr(cluster_idx, bus::C_BLOCK_IDX, 0));
39 if (!cblock)
40 LOG_ERROR("Error: C-block is missing or unknown.");
41 }
42 if (!iblock) {
43 iblock = entities::detect<blocks::IBlock>(bus::idx_to_addr(cluster_idx, bus::I_BLOCK_IDX, 0));
44 if (!iblock)
45 LOG_ERROR("Error: I-block is missing or unknown.");
46 }
47 if (!shblock) {
48 shblock = entities::detect<blocks::SHBlock>(bus::idx_to_addr(cluster_idx, bus::SH_BLOCK_IDX, 0));
49 if (!shblock)
50 LOG_ERROR("Error: SH-block is missing or unknown.");
51 }
52
53 LOG(ANABRID_DEBUG_INIT, "Initialising detected blocks...");
54 for (auto block : get_blocks()) {
55 if (block)
56 TRY(block->init());
57 }
58 LOG(ANABRID_DEBUG_INIT, "Cluster initialized.");
59 reset(entities::ResetAction::EVERYTHING);
60 return UnitResult::ok();
61}
62
63platform::Cluster::Cluster(uint8_t cluster_idx) : entities::Entity(std::to_string(cluster_idx)), cluster_idx(cluster_idx) {
64 classifier.class_enum = CLASS_;
65}
66
67UnitResult platform::Cluster::calibrate_offsets() {
68 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
69
70 LOG_ANABRID_DEBUG_CALIBRATION("Calibrating offsets");
71 if (!ublock or !shblock)
72 return UnitResult::err("Writing to u-block failed");
73
74 auto old_transmission_modes = ublock->get_all_transmission_modes();
75
76 ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::GROUND);
77 TRY(ublock->write_to_hardware());
78
79 delay(10);
80 shblock->compensate_hardware_offsets();
81
82 ublock->change_all_transmission_modes(old_transmission_modes);
83 TRY(ublock->write_to_hardware());
84
85 delay(10);
86
87 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
88 return UnitResult::ok();
89}
90
91UnitResult platform::Cluster::write_to_hardware() {
92 for (auto block : get_blocks()) {
93 if (!block) continue;
94 TRY(block->write_to_hardware());
95 }
96
97 return UnitResult::ok();
98}
99
100UnitResult platform::Cluster::route(uint8_t u_in, uint8_t u_out, float c_factor, uint8_t i_out) {
101 if (fabs(c_factor) > 1.0f) {
102 c_factor = c_factor / 8.0f;
103 iblock->set_upscaling(u_out, true);
104 } else
105 iblock->set_upscaling(u_out, false);
106
107 TRY (ublock->connect(u_in, u_out));
108 TRY (cblock->set_factor(u_out, c_factor));
109 TRY (iblock->connect(u_out, i_out));
110 return UnitResult::ok();
111}
112
113UnitResult platform::Cluster::add_constant(blocks::UBlock::Transmission_Mode signal_type, uint8_t u_out, float c_factor, uint8_t i_out) {
114 if (fabs(c_factor) > 1.0f) {
115 c_factor = c_factor / 8.0f;
116 iblock->set_upscaling(u_out, true);
117 } else
118 iblock->set_upscaling(u_out, false);
119
120 TRY(ublock->connect_alternative(signal_type, u_out));
121 TRY(cblock->set_factor(u_out, c_factor));
122 TRY(iblock->connect(u_out, i_out));
123 return UnitResult::ok();
124}
125
126void platform::Cluster::reset(entities::ResetAction action) {
127 for (auto block : get_blocks()) {
128 if (block)
129 block->reset(action);
130 }
131}
132
133entities::Entity *platform::Cluster::get_child_entity(std::string_view child_id) {
134 if (child_id == "M0")
135 return m0block;
136 else if (child_id == "M1")
137 return m1block;
138 else if (child_id == "U")
139 return ublock;
140 else if (child_id == "C")
141 return cblock;
142 else if (child_id == "I")
143 return iblock;
144 else if (child_id == "SH")
145 return shblock;
146 return nullptr;
147}
148
149ConfigResult platform::Cluster::config(const pb_Item &item) {
150#ifdef ANABRID_DEBUG_ENTITY_CONFIG
151 Serial.println(__PRETTY_FUNCTION__);
152#endif
153 // Cluster has no own configuration parameters currently
154 return ConfigResult::ok(false);
155}
156
157std::vector<entities::Entity *> platform::Cluster::get_child_entities() {
158#ifdef ANABRID_DEBUG_ENTITY_CONFIG
159 Serial.println(__PRETTY_FUNCTION__);
160#endif
161 return {m0block, m1block, ublock, cblock, iblock, shblock};
162}
163
164uint8_t platform::Cluster::get_cluster_idx() const { return cluster_idx; }
165
166std::pair<uint8_t, uint8_t> platform::Cluster::get_id_connection() const {
167 blocks::MBlock *id_block = nullptr;
168 if (m0block->has_id_lanes())
169 id_block = m0block;
170 if (m1block->has_id_lanes())
171 id_block = m1block;
172
173 if (id_block == nullptr)
174 return {0xff, 0xff};
175
176
177 for (uint8_t out = 0; out < 8; out++) {
178 int8_t in = id_block->ID_OUTPUT_CONNECTIONS()[out];
179 if (in != -1)
180 return {id_block->slot_to_global_io_index(in), id_block->slot_to_global_io_index(out)};
181 }
182 return {0xff, 0xff};
183}