FastLED 3.9.15
Loading...
Searching...
No Matches
wave3.hpp
Go to the documentation of this file.
1
6
7#pragma once
8
9#include "fl/channels/wave3.h"
12#include "fl/stl/isr/memcpy.h"
13
15
16namespace fl {
17
18namespace detail {
19
20// ============================================================================
21// Byte to Wave3Byte Conversion (Force Inline Helper)
22// ============================================================================
23
28 const Wave3BitExpansionLut& lut,
29 Wave3Byte* output) {
30 // High nibble → 12 bits, low nibble → 12 bits, total 24 bits = 3 bytes
31 u16 high_pattern = lut.lut[(byte_value >> 4) & 0xF];
32 u16 low_pattern = lut.lut[byte_value & 0xF];
33
34 // Pack 24 bits into 3 bytes (MSB first):
35 // Byte 0: bits [23..16] = high_pattern[11..4]
36 // Byte 1: bits [15..8] = high_pattern[3..0] | low_pattern[11..8]
37 // Byte 2: bits [7..0] = low_pattern[7..0]
38 output->data[0] = (u8)(high_pattern >> 4);
39 output->data[1] = (u8)(((high_pattern & 0xF) << 4) | ((low_pattern >> 8) & 0xF));
40 output->data[2] = (u8)(low_pattern & 0xFF);
41}
42
43// ============================================================================
44// 2-Lane Transposition (Force Inline)
45// ============================================================================
46
51void wave3_transpose_2(const Wave3Byte lane_waves[2],
52 u8 output[2 * sizeof(Wave3Byte)]) {
53 // Wave3 produces 3 symbols per LED byte (one byte per symbol for each lane).
54 // For 2 lanes: interleave bits from both lanes into 2 bytes per symbol.
55 // Each symbol byte has 8 bits. With 2 lanes we produce 2 bytes per symbol
56 // using the same bit-spreading as wave8_transpose_2.
57
58 for (int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
59 u8 l0 = lane_waves[0].data[symbol_idx];
60 u8 l1 = lane_waves[1].data[symbol_idx];
61
62 // Interleave bits: for each bit position, lane0 goes to odd bits, lane1 to even bits
63 u16 interleaved = 0;
64 for (int bit = 0; bit < 8; bit++) {
65 u16 b0 = (l0 >> bit) & 1;
66 u16 b1 = (l1 >> bit) & 1;
67 interleaved |= (b1 << (bit * 2)); // even positions
68 interleaved |= (b0 << (bit * 2 + 1)); // odd positions
69 }
70
71 output[symbol_idx * 2] = (u8)(interleaved >> 8);
72 output[symbol_idx * 2 + 1] = (u8)(interleaved & 0xFF);
73 }
74}
75
76// ============================================================================
77// 4-Lane Transposition (Force Inline)
78// ============================================================================
79
84void wave3_transpose_4(const Wave3Byte lane_waves[4],
85 u8 output[4 * sizeof(Wave3Byte)]) {
86 for (int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
87 u8 l0 = lane_waves[0].data[symbol_idx];
88 u8 l1 = lane_waves[1].data[symbol_idx];
89 u8 l2 = lane_waves[2].data[symbol_idx];
90 u8 l3 = lane_waves[3].data[symbol_idx];
91
92 // 4 output bytes per symbol (2 pulses per byte × 4 lanes)
93 // Same bit layout as wave8_transpose_4
94 output[symbol_idx * 4 + 0] =
95 ((l3 >> 7) & 1) << 7 |
96 ((l2 >> 7) & 1) << 6 |
97 ((l1 >> 7) & 1) << 5 |
98 ((l0 >> 7) & 1) << 4 |
99 ((l3 >> 6) & 1) << 3 |
100 ((l2 >> 6) & 1) << 2 |
101 ((l1 >> 6) & 1) << 1 |
102 ((l0 >> 6) & 1);
103
104 output[symbol_idx * 4 + 1] =
105 ((l3 >> 5) & 1) << 7 |
106 ((l2 >> 5) & 1) << 6 |
107 ((l1 >> 5) & 1) << 5 |
108 ((l0 >> 5) & 1) << 4 |
109 ((l3 >> 4) & 1) << 3 |
110 ((l2 >> 4) & 1) << 2 |
111 ((l1 >> 4) & 1) << 1 |
112 ((l0 >> 4) & 1);
113
114 output[symbol_idx * 4 + 2] =
115 ((l3 >> 3) & 1) << 7 |
116 ((l2 >> 3) & 1) << 6 |
117 ((l1 >> 3) & 1) << 5 |
118 ((l0 >> 3) & 1) << 4 |
119 ((l3 >> 2) & 1) << 3 |
120 ((l2 >> 2) & 1) << 2 |
121 ((l1 >> 2) & 1) << 1 |
122 ((l0 >> 2) & 1);
123
124 output[symbol_idx * 4 + 3] =
125 ((l3 >> 1) & 1) << 7 |
126 ((l2 >> 1) & 1) << 6 |
127 ((l1 >> 1) & 1) << 5 |
128 ((l0 >> 1) & 1) << 4 |
129 ((l3 >> 0) & 1) << 3 |
130 ((l2 >> 0) & 1) << 2 |
131 ((l1 >> 0) & 1) << 1 |
132 ((l0 >> 0) & 1);
133 }
134}
135
136// ============================================================================
137// 8-Lane Transposition (Force Inline)
138// ============================================================================
139
147void wave3_transpose_8(const Wave3Byte lane_waves[8],
148 u8 output[8 * sizeof(Wave3Byte)]) {
149 for (int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
150 u8 l[8];
151 for (int lane = 0; lane < 8; lane++) {
152 l[lane] = lane_waves[lane].data[symbol_idx];
153 }
154 spread_transpose8_symbol(l, output + symbol_idx * 8);
155 }
156}
157
158// ============================================================================
159// 16-Lane Transposition (Force Inline)
160// ============================================================================
161
170void wave3_transpose_16(const Wave3Byte lane_waves[16],
171 u8 output[16 * sizeof(Wave3Byte)]) {
172 for (int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
173 u8 l[16];
174 for (int lane = 0; lane < 16; lane++) {
175 l[lane] = lane_waves[lane].data[symbol_idx];
176 }
177 spread_transpose16_symbol(l, output + symbol_idx * 16);
178 }
179}
180
181} // namespace detail
182
183// ============================================================================
184// Public wave3() Function (Force Inline)
185// ============================================================================
186
190void wave3(u8 lane,
191 const Wave3BitExpansionLut& lut,
192 u8 (&FL_RESTRICT_PARAM output)[sizeof(Wave3Byte)]) {
193 Wave3Byte wave3_output;
194 detail::wave3_convert_byte_to_wave3byte(lane, lut, &wave3_output);
195 output[0] = wave3_output.data[0];
196 output[1] = wave3_output.data[1];
197 output[2] = wave3_output.data[2];
198}
199
200} // namespace fl
201
Shared u32 "spread LUT" bit-matrix transpose primitive (no SIMD, no u64).
ISR-safe memory operations (inline, header-only)
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void spread_transpose16_symbol(const u8 l[16], u8 out[16])
Transpose one symbol of 16 lanes (16 input bytes) into 16 output bytes: 8 pulses × 2 bytes,...
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_8(const Wave3Byte lane_waves[8], u8 output[8 *sizeof(Wave3Byte)])
Transpose 8 lanes of Wave3Byte data into interleaved format.
Definition wave3.hpp:147
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_2(const Wave3Byte lane_waves[2], u8 output[2 *sizeof(Wave3Byte)])
Transpose 2 lanes of Wave3Byte data into interleaved format.
Definition wave3.hpp:51
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void spread_transpose8_symbol(const u8 l[8], u8 out[8])
Transpose one symbol of 8 lanes (8 input bytes) into 8 output bytes: 8 pulses × 1 byte (bit L = lane ...
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_16(const Wave3Byte lane_waves[16], u8 output[16 *sizeof(Wave3Byte)])
Transpose 16 lanes of Wave3Byte data into interleaved format.
Definition wave3.hpp:170
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_convert_byte_to_wave3byte(u8 byte_value, const Wave3BitExpansionLut &lut, Wave3Byte *output)
Helper: Convert byte to Wave3Byte using nibble LUT (internal use only)
Definition wave3.hpp:27
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_4(const Wave3Byte lane_waves[4], u8 output[4 *sizeof(Wave3Byte)])
Transpose 4 lanes of Wave3Byte data into interleaved format.
Definition wave3.hpp:84
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_traits.h:48
unsigned char u8
Definition stdint.h:131
FASTLED_FORCE_INLINE FL_IRAM FL_OPTIMIZE_FUNCTION void wave3(u8 lane, const Wave3BitExpansionLut &lut, u8(&FL_RESTRICT_PARAM output)[sizeof(Wave3Byte)])
Convert byte to 3 wave3 bytes using nibble LUT.
Definition wave3.hpp:190
Base definition for an LED controller.
Definition crgb.hpp:179
u8 data[3]
Definition wave3.h:21
Type-safe container for 3-byte wave pulse pattern (wave3 encoding)
Definition wave3.h:20
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FASTLED_FORCE_INLINE
#define FL_OPTIMIZATION_LEVEL_O3_END
#define FL_OPTIMIZE_FUNCTION
#define FL_IRAM
#define FL_RESTRICT_PARAM