26 const u32 period = timing.
T1 + timing.
T2 + timing.
T3;
32 const float t0h_norm =
static_cast<float>(timing.
T1) / period;
33 const float t1h_norm =
static_cast<float>(timing.
T1 + timing.
T2) / period;
36 u32 ticks_bit0 =
static_cast<u32
>(t0h_norm * 3.0f + 0.5f);
37 u32 ticks_bit1 =
static_cast<u32
>(t1h_norm * 3.0f + 0.5f);
40 if (ticks_bit0 < 1 || ticks_bit0 > 2)
return false;
41 if (ticks_bit1 < 1 || ticks_bit1 > 2)
return false;
44 if (ticks_bit0 == ticks_bit1)
return false;
55 const u32 period = timing.
T1 + timing.
T2 + timing.
T3;
61 return static_cast<u32
>(3000000000ULL / period);
70 Wave3BitExpansionLut lut;
72 const u32 period = timing.
T1 + timing.
T2 + timing.
T3;
75 const float t0h_norm =
static_cast<float>(timing.
T1) / period;
76 const float t1h_norm =
static_cast<float>(timing.
T1 + timing.
T2) / period;
79 u32 ticks_bit0 =
static_cast<u32
>(t0h_norm * 3.0f + 0.5f);
80 u32 ticks_bit1 =
static_cast<u32
>(t1h_norm * 3.0f + 0.5f);
83 if (ticks_bit0 > 3) ticks_bit0 = 3;
84 if (ticks_bit1 > 3) ticks_bit1 = 3;
92 for (u32 i = 0; i < ticks_bit0; i++) {
93 pattern_bit0 |= (0x4 >> i);
95 for (u32 i = 0; i < ticks_bit1; i++) {
96 pattern_bit1 |= (0x4 >> i);
101 for (
u8 nibble = 0; nibble < 16; nibble++) {
104 for (
int bit_pos = 3; bit_pos >= 0; bit_pos--) {
105 bool bit_set = (nibble >> bit_pos) & 1;
106 u8 tick_pattern = bit_set ? pattern_bit1 : pattern_bit0;
107 pattern = (pattern << 3) | (tick_pattern & 0x7);
109 lut.lut[nibble] = pattern;
121 const Wave3BitExpansionLut& lut,
131 const Wave3BitExpansionLut& lut,
134 for (
int lane = 0; lane < 4; lane++) {
142 const Wave3BitExpansionLut& lut,
145 for (
int lane = 0; lane < 8; lane++) {
153 const Wave3BitExpansionLut& lut,
156 for (
int lane = 0; lane < 16; lane++) {
171 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
172 u16 interleaved = ((u16)transposed[symbol_idx * 2] << 8) |
173 transposed[symbol_idx * 2 + 1];
178 for (
int bit = 0; bit < 8; bit++) {
179 if (interleaved & (1 << (bit * 2 + 1))) {
180 lane0_bits |= (1 << bit);
182 if (interleaved & (1 << (bit * 2))) {
183 lane1_bits |= (1 << bit);
187 lane_waves[0].
data[symbol_idx] = lane0_bits;
188 lane_waves[1].
data[symbol_idx] = lane1_bits;
200 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
201 u8 lane_bytes[4] = {0, 0, 0, 0};
203 for (
int byte_idx = 0; byte_idx < 4; byte_idx++) {
204 u8 input_byte = transposed[symbol_idx * 4 + byte_idx];
206 int pulse_bit_hi = 7 - (byte_idx * 2);
207 int pulse_bit_lo = pulse_bit_hi - 1;
209 for (
int lane = 0; lane < 4; lane++) {
210 u8 pulse_hi = (input_byte >> (4 + lane)) & 1;
211 u8 pulse_lo = (input_byte >> lane) & 1;
212 lane_bytes[lane] |= (pulse_hi << pulse_bit_hi);
213 lane_bytes[lane] |= (pulse_lo << pulse_bit_lo);
217 for (
int lane = 0; lane < 4; lane++) {
218 lane_waves[lane].
data[symbol_idx] = lane_bytes[lane];
222 for (
int lane = 0; lane < 4; lane++) {
232 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
233 u8 lane_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
237 for (
int byte_idx = 0; byte_idx < 8; byte_idx++) {
238 u8 input_byte = transposed[symbol_idx * 8 + byte_idx];
240 int pulse_bit = 7 - byte_idx;
242 for (
int lane = 0; lane < 8; lane++) {
243 u8 pulse = (input_byte >> lane) & 1;
244 lane_bytes[lane] |= (pulse << pulse_bit);
248 for (
int lane = 0; lane < 8; lane++) {
249 lane_waves[lane].
data[symbol_idx] = lane_bytes[lane];
253 for (
int lane = 0; lane < 8; lane++) {
263 for (
int symbol_idx = 0; symbol_idx < 3; symbol_idx++) {
264 u8 lane_bytes[16] = {0};
266 for (
int pulse_idx = 0; pulse_idx < 8; pulse_idx++) {
267 int pulse_bit = 7 - pulse_idx;
268 int input_offset = symbol_idx * 16 + pulse_idx * 2;
269 u16 input_word = (u16)transposed[input_offset] |
270 ((u16)transposed[input_offset + 1] << 8);
272 for (
int lane = 0; lane < 16; lane++) {
273 u8 pulse = (input_word >> lane) & 1;
274 lane_bytes[lane] |= (pulse << pulse_bit);
278 for (
int lane = 0; lane < 16; lane++) {
279 lane_waves[lane].
data[symbol_idx] = lane_bytes[lane];
283 for (
int lane = 0; lane < 16; lane++) {
Centralized LED chipset timing definitions with nanosecond precision.
ISR-safe memory operations (inline, header-only)
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.
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.
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.
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)
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.
FL_OPTIMIZE_FUNCTION FL_IRAM FASTLED_FORCE_INLINE void memcpy(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 void wave3Untranspose_4(const u8(&FL_RESTRICT_PARAM transposed)[4 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[4 *sizeof(Wave3Byte)])
FL_OPTIMIZE_FUNCTION Wave3BitExpansionLut buildWave3ExpansionLUT(const ChipsetTiming &timing)
Build a Wave3BitExpansionLut from chipset timing data.
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_OPTIMIZE_FUNCTION void wave3Untranspose_8(const u8(&FL_RESTRICT_PARAM transposed)[8 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[8 *sizeof(Wave3Byte)])
FL_OPTIMIZE_FUNCTION void wave3Untranspose_2(const u8(&FL_RESTRICT_PARAM transposed)[2 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[2 *sizeof(Wave3Byte)])
FL_OPTIMIZE_FUNCTION u32 wave3ClockFrequencyHz(const ChipsetTiming &timing)
Calculate the clock frequency for wave3 encoding.
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_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_OPTIMIZE_FUNCTION bool canUseWave3(const ChipsetTiming &timing)
Check if a chipset timing is eligible 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_OPTIMIZE_FUNCTION void wave3Untranspose_16(const u8(&FL_RESTRICT_PARAM transposed)[16 *sizeof(Wave3Byte)], u8(&FL_RESTRICT_PARAM output)[16 *sizeof(Wave3Byte)])
Base definition for an LED controller.
u32 T2
Additional high time for bit 1 (nanoseconds)
u32 T3
Low tail duration (nanoseconds)
u32 T1
High time for bit 0 (nanoseconds)
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...
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FL_OPTIMIZATION_LEVEL_O3_END
#define FL_OPTIMIZE_FUNCTION
#define FL_RESTRICT_PARAM
Inline implementation details for wave3 transposition.