REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
ublock.tpl.h
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#pragma once
6
7#include <array>
8#include <cstdint>
9
10// hint: This function could be avoided to be a template if the signature
11// was just transfer(const uint8_t* const outputs, uint8_t num_of_outputs).
12// The template provides little advantage here.
13
14template <size_t num_of_outputs>
15[[nodiscard]] bool
16functions::UMatrixFunction::transfer(const std::array<int8_t, num_of_outputs> &outputs) const {
17 constexpr uint8_t NUM_BYTES = num_of_outputs * 5 / 8;
18 uint8_t buffer[NUM_BYTES] = {}; // initialized with zeros
19
20 /*
21 * Explanation
22 * -----------
23 *
24 * The two XBar chips accept a 80bit binary stream each, resulting in 160bit = 20byte
25 * total. Each output on a chip uses 5bit: [1bit enable][4bit input select]. The
26 * 20byte stream has the last output in front. To set e.g. the last output to input
27 * number 5 (5 because 0-based: 5=B0101), use in binary buffer =
28 * 10101'00000'00000'.....'...
29 * |-8bit--||-8bit---||---
30 *
31 * this->outputs defines which input an output should use.
32 * outputs[i] = zero means the output is disabled (don't set enable bit)
33 * outputs[i] = j means use input j (1-based) => input j-1 (0-based in bit stream)
34 *
35 * Since the output configurations are 5bit wide, we need to do some bit-shifting to
36 * put each at the correct position in the buffer. 1) Place the correct 5bit sequence
37 * _at the end_ of buffer 2) Shift _the whole buffer_ by 5bit 3) Repeat until buffer
38 * is full
39 */
40
41 for (auto idx = num_of_outputs; idx > 0; idx--) {
42 // Start from the back
43 auto selected_input = outputs[idx - 1];
44
45 // If an output is enabled, write correct 5bit sequence to _end_ of buffer
46 if (selected_input >= 0) {
47 // Enable at bit 5
48 buffer[sizeof(buffer) - 1] |= B00010000;
49 // Input number, max 4bits (thus & 0x0F)
50 buffer[sizeof(buffer) - 1] |= (selected_input & 0x0F);
51 }
52
53 // 5-bit shift the whole buffer, but not in last loop
54 if (idx > 1)
55 utils::shift_5_left(buffer, sizeof(buffer));
56 }
57
58 DataFunction::transfer(buffer, nullptr, sizeof(buffer));
59
60#ifdef ANABRID_PEDANTIC
61 uint8_t read_buffer[NUM_BYTES] = {};
62 DataFunction::transfer(buffer, read_buffer, sizeof(buffer));
63
64 return memcmp(buffer, read_buffer, sizeof(buffer)) == 0;
65#endif
66
67 return true;
68
69 // You must trigger the SYNC of the chip with the sync trigger function.
70}
void transfer(const void *mosi_buf, void *miso_buf, size_t count) const
bool transfer(const std::array< int8_t, num_of_outputs > &outputs) const
Convert an output array to data packets and transfer to chip.
Definition ublock.tpl.h:16