REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
iblock.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/iblock.h>
6#include <bus/functions.h>
7#include <entity/meta.h>
8#include <utils/is_number.h>
9#include <utils/logging.h>
10
11#include "teensy/iblock.h"
12#include "teensy/icmd.h"
13
14FLASHMEM blocks::IBlock *blocks::IBlock::from_entity_classifier(entities::EntityClassifier classifier,
15 bus::addr_t block_address) {
16 if (!classifier or classifier.class_enum != CLASS_)
17 return nullptr;
18
19 // Currently, there are no different variants
20 if (classifier.variant != entities::EntityClassifier::DEFAULT_)
21 return nullptr;
22
23 if (classifier.version < entities::Version(1, 2))
24 return nullptr;
25 if (classifier.version < entities::Version(1, 3)) {
26 auto *new_block = new IBlock(new IBlockHAL_V_1_2_X(block_address));
27 new_block->classifier = classifier;
28 return new_block;
29 }
30 return nullptr;
31}
32
33FLASHMEM blocks::IBlockHAL_V_1_2_X::IBlockHAL_V_1_2_X(bus::addr_t block_address)
34 : IBlockHAL_Parent(block_address),
35 f_cmd{bus::replace_function_idx(block_address, 2)},
36 f_imatrix_reset{bus::replace_function_idx(block_address, 4)}, f_imatrix_sync{bus::replace_function_idx(
37 block_address, 3)},
38 scaling_register{bus::replace_function_idx(block_address, 5), true},
39 scaling_register_sync{bus::replace_function_idx(block_address, 6)} {}
40
41FLASHMEM bool blocks::IBlockHAL_V_1_2_X::write_outputs(const std::array<uint32_t, 16> &outputs) {
42 f_imatrix_reset.trigger();
43 delayNanoseconds(420);
44
45 // TODO: This can be further improved by not naively iterating over the output indizes.
46 // For each output, send the corresponding 32bit commands.
47 // For output_idx < 7, the first two MT8816 chips are used, for >8 the later two.
48 // This means, we can set two outputs simultaneously.
49 // When setting later outputs, we need to *not* overwrite previous outputs on the other chips
50 // Thus we remember what we send them and just send them the same thing again
51 uint32_t remembered_command = 0;
52 for (decltype(outputs.size()) output_idx = 0; output_idx < outputs.size() / 2; output_idx++) {
53 uint32_t command = 0;
54 const auto oidx_one_two = output_idx;
55 const auto oidx_three_four = output_idx + outputs.size() / 2;
56 if (!outputs[oidx_one_two] && !outputs[oidx_three_four])
57 continue;
58
59 // We can always set one output in range (0,15) and one in (16,31) in for each output
60 for (uint8_t input_idx = 0; input_idx < NUM_INPUTS / 2; input_idx++) {
61
62 command = 0;
63
64 const auto iidx_one_three = input_idx;
65 const auto iidx_two_four = input_idx + NUM_INPUTS / 2;
66 bool actual_data = false;
67 // First chip combines oidx_one_two and iidx_one_three
68 if (outputs[oidx_one_two] & INPUT_BITMASK(iidx_one_three)) {
69 command |= functions::ICommandRegisterFunction::chip_cmd_word(iidx_one_three, oidx_one_two);
70 actual_data = true;
71 } else {
72 command |= (remembered_command & 0xFF);
73 }
74 // Similar combination for second chip
75 if (outputs[oidx_one_two] & INPUT_BITMASK(iidx_two_four)) {
76 command |= functions::ICommandRegisterFunction::chip_cmd_word(iidx_two_four, oidx_one_two) << 8;
77 actual_data = true;
78 } else {
79 command |= (remembered_command & 0xFF00);
80 }
81 // Third chip
82 if (outputs[oidx_three_four] & INPUT_BITMASK(iidx_one_three)) {
83 command |= functions::ICommandRegisterFunction::chip_cmd_word(iidx_one_three, oidx_three_four) << 16;
84 actual_data = true;
85 } else {
86 command |= (remembered_command & 0xFF0000);
87 }
88 // Fourth chip
89 if (outputs[oidx_three_four] & INPUT_BITMASK(iidx_two_four)) {
90 command |= functions::ICommandRegisterFunction::chip_cmd_word(iidx_two_four, oidx_three_four) << 24;
91 actual_data = true;
92 } else {
93 command |= (remembered_command & 0xFF000000);
94 }
95
96 if (actual_data) {
97 remembered_command = command;
98 // Send out data
99 if (!f_cmd.transfer32(command)) {
100 LOG(ANABRID_PEDANTIC, __PRETTY_FUNCTION__);
101 return false;
102 }
103 // Apply command
104 f_imatrix_sync.trigger();
105 }
106 }
107 }
108 return true;
109}
110
111FLASHMEM bool blocks::IBlockHAL_V_1_2_X::write_upscaling(std::bitset<32> upscaling) {
112 if (!scaling_register.transfer32(upscaling.to_ulong()))
113 return false;
114 scaling_register_sync.trigger();
115 return true;
116}
bool write_upscaling(std::bitset< 32 > upscaling) override
Definition iblock.cpp:111
IBlockHAL_V_1_2_X(bus::addr_t block_address)
Definition iblock.cpp:33
bool write_outputs(const std::array< uint32_t, 16 > &outputs) override
Definition iblock.cpp:41
static uint8_t chip_cmd_word(uint8_t chip_input_idx, uint8_t chip_output_idx, bool connect=true)
Definition icmd.cpp:18
uint32_t
Definition flasher.cpp:195
Definition bus.h:21