27 const u32 period = timing.T1 + timing.T2 + timing.T3;
33 const float t0h_norm =
static_cast<float>(timing.T1) / period;
34 const float t1h_norm =
static_cast<float>(timing.T1 + timing.T2) / period;
37 u32 ticks_bit0 =
static_cast<u32
>(t0h_norm * 3.0f + 0.5f);
38 u32 ticks_bit1 =
static_cast<u32
>(t1h_norm * 3.0f + 0.5f);
41 if (ticks_bit0 < 1 || ticks_bit0 > 2)
return false;
42 if (ticks_bit1 < 1 || ticks_bit1 > 2)
return false;
45 if (ticks_bit0 == ticks_bit1)
return false;
56 const u32 period = timing.T1 + timing.T2 + timing.T3;
62 return static_cast<u32
>(3000000000ULL / period);
71 Wave3BitExpansionLut lut;
73 const u32 period = timing.T1 + timing.T2 + timing.T3;
76 const float t0h_norm =
static_cast<float>(timing.T1) / period;
77 const float t1h_norm =
static_cast<float>(timing.T1 + timing.T2) / period;
80 u32 ticks_bit0 =
static_cast<u32
>(t0h_norm * 3.0f + 0.5f);
81 u32 ticks_bit1 =
static_cast<u32
>(t1h_norm * 3.0f + 0.5f);
84 if (ticks_bit0 > 3) ticks_bit0 = 3;
85 if (ticks_bit1 > 3) ticks_bit1 = 3;
93 for (u32 i = 0; i < ticks_bit0; i++) {
94 pattern_bit0 |= (0x4 >> i);
96 for (u32 i = 0; i < ticks_bit1; i++) {
97 pattern_bit1 |= (0x4 >> i);
102 for (
u8 nibble = 0; nibble < 16; nibble++) {
105 for (
int bit_pos = 3; bit_pos >= 0; bit_pos--) {
106 bool bit_set = (nibble >> bit_pos) & 1;
107 u8 tick_pattern = bit_set ? pattern_bit1 : pattern_bit0;
108 pattern = (pattern << 3) | (tick_pattern & 0x7);
110 lut.lut[nibble] = pattern;
122 const Wave3BitExpansionLut& lut,
132 const Wave3BitExpansionLut& lut,
135 for (
int lane = 0; lane < 4; lane++) {
143 const Wave3BitExpansionLut& lut,
146 for (
int lane = 0; lane < 8; lane++) {
154 const Wave3BitExpansionLut& lut,
157 for (
int lane = 0; lane < 16; lane++) {
172 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
173 u16 interleaved = ((u16)transposed[symbol_idx * 2] << 8) |
174 transposed[symbol_idx * 2 + 1];
179 for (
int bit = 0; bit < 8; bit++) {
180 if (interleaved & (1 << (bit * 2 + 1))) {
181 lane0_bits |= (1 << bit);
183 if (interleaved & (1 << (bit * 2))) {
184 lane1_bits |= (1 << bit);
188 lane_waves[0].
data[symbol_idx] = lane0_bits;
189 lane_waves[1].
data[symbol_idx] = lane1_bits;
201 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
202 u8 lane_bytes[4] = {0, 0, 0, 0};
204 for (
int byte_idx = 0; byte_idx < 4; byte_idx++) {
205 u8 input_byte = transposed[symbol_idx * 4 + byte_idx];
207 int pulse_bit_hi = 7 - (byte_idx * 2);
208 int pulse_bit_lo = pulse_bit_hi - 1;
210 for (
int lane = 0; lane < 4; lane++) {
211 u8 pulse_hi = (input_byte >> (4 + lane)) & 1;
212 u8 pulse_lo = (input_byte >> lane) & 1;
213 lane_bytes[lane] |= (pulse_hi << pulse_bit_hi);
214 lane_bytes[lane] |= (pulse_lo << pulse_bit_lo);
218 for (
int lane = 0; lane < 4; lane++) {
219 lane_waves[lane].
data[symbol_idx] = lane_bytes[lane];
223 for (
int lane = 0; lane < 4; lane++) {
233 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
234 u8 lane_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
238 for (
int byte_idx = 0; byte_idx < 8; byte_idx++) {
239 u8 input_byte = transposed[symbol_idx * 8 + byte_idx];
241 int pulse_bit = 7 - byte_idx;
243 for (
int lane = 0; lane < 8; lane++) {
244 u8 pulse = (input_byte >> lane) & 1;
245 lane_bytes[lane] |= (pulse << pulse_bit);
249 for (
int lane = 0; lane < 8; lane++) {
250 lane_waves[lane].
data[symbol_idx] = lane_bytes[lane];
254 for (
int lane = 0; lane < 8; lane++) {
264 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
265 u8 lane_bytes[16] = {0};
267 for (
int pulse_idx = 0; pulse_idx < 8; pulse_idx++) {
268 int pulse_bit = 7 - pulse_idx;
269 int input_offset = symbol_idx * 16 + pulse_idx * 2;
270 u16 input_word = (u16)transposed[input_offset] |
271 ((u16)transposed[input_offset + 1] << 8);
273 for (
int lane = 0; lane < 16; lane++) {
274 u8 pulse = (input_word >> lane) & 1;
275 lane_bytes[lane] |= (pulse << pulse_bit);
279 for (
int lane = 0; lane < 16; lane++) {
280 lane_waves[lane].
data[symbol_idx] = lane_bytes[lane];
284 for (
int lane = 0; lane < 16; lane++) {
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FL_OPTIMIZATION_LEVEL_O3_END
#define FL_OPTIMIZE_FUNCTION
#define FL_RESTRICT_PARAM
Out-of-line declarations for wave3 transposition internals.
Centralized LED chipset timing definitions with nanosecond precision.
ISR-safe memory operations (inline, header-only)
FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_4(const Wave3Byte lane_waves[4], u8 output[4 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
Transpose 4 lanes of Wave3Byte data.
FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_convert_byte_to_wave3byte(u8 byte_value, const Wave3BitExpansionLut &lut, Wave3Byte *output) FL_NO_EXCEPT
Convert one byte to a Wave3Byte using the nibble LUT.
FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_2(const Wave3Byte lane_waves[2], u8 output[2 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
Transpose 2 lanes of Wave3Byte data into interleaved format.
FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_8(const Wave3Byte lane_waves[8], u8 output[8 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
Transpose 8 lanes of Wave3Byte data via the spread-LUT path (#2533).
FL_IRAM FL_OPTIMIZE_FUNCTION void wave3_transpose_16(const Wave3Byte lane_waves[16], u8 output[16 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
Transpose 16 lanes of Wave3Byte data via the spread-LUT path (#2533).
FL_OPTIMIZE_FUNCTION FL_IRAM FASTLED_FORCE_INLINE void memcopy(void *FL_RESTRICT_PARAM dst, const void *FL_RESTRICT_PARAM src, size_t num_bytes)
ISR-optimized memcpy with alignment detection and switch dispatch.
FL_OPTIMIZE_FUNCTION FL_IRAM void wave3Transpose_2(const u8(&FL_RESTRICT_PARAM lanes)[2], const Wave3BitExpansionLut &lut, u8(&FL_RESTRICT_PARAM output)[2 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
u8 u8 fract8 blur_amount FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION void wave3Untranspose_2(const u8(&FL_RESTRICT_PARAM transposed)[2 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[2 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION Wave3BitExpansionLut buildWave3ExpansionLUT(const ChipsetTiming &timing) FL_NO_EXCEPT
Build a Wave3BitExpansionLut from chipset timing data.
FL_OPTIMIZE_FUNCTION u32 wave3ClockFrequencyHz(const ChipsetTiming &timing) FL_NO_EXCEPT
Calculate the clock frequency for wave3 encoding.
FL_OPTIMIZE_FUNCTION FL_IRAM void wave3Transpose_16(const u8(&FL_RESTRICT_PARAM lanes)[16], const Wave3BitExpansionLut &lut, u8(&FL_RESTRICT_PARAM output)[16 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION FL_IRAM void wave3Transpose_8(const u8(&FL_RESTRICT_PARAM lanes)[8], const Wave3BitExpansionLut &lut, u8(&FL_RESTRICT_PARAM output)[8 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION void wave3Untranspose_4(const u8(&FL_RESTRICT_PARAM transposed)[4 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[4 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION FL_IRAM void wave3Transpose_4(const u8(&FL_RESTRICT_PARAM lanes)[4], const Wave3BitExpansionLut &lut, u8(&FL_RESTRICT_PARAM output)[4 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION void wave3Untranspose_16(const u8(&FL_RESTRICT_PARAM transposed)[16 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[16 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
FL_OPTIMIZE_FUNCTION bool canUseWave3(const ChipsetTiming &timing) FL_NO_EXCEPT
Check if a chipset timing is eligible for wave3 encoding.
FL_OPTIMIZE_FUNCTION void wave3Untranspose_8(const u8(&FL_RESTRICT_PARAM transposed)[8 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[8 *sizeof(Wave3Byte)]) FL_NO_EXCEPT
Base definition for an LED controller.
Type-safe container for 3-byte wave pulse pattern (wave3 encoding)
Generic chipset timing entry Provides T1, T2, T3 timing parameters in nanoseconds for any LED protoco...