FastLED 3.9.15
Loading...
Searching...
No Matches
sk9822.h
Go to the documentation of this file.
1#pragma once
2
19
20#include "fl/stl/stdint.h"
21#include "fl/stl/array.h"
25#include "fl/stl/noexcept.h"
26
27namespace fl {
28
37template <typename InputIterator, typename OutputIterator>
38void encodeSK9822(InputIterator first, InputIterator last, OutputIterator out,
39 u8 global_brightness = 31) FL_NOEXCEPT {
40 // Clamp brightness to 5-bit range
41 global_brightness = global_brightness & 0x1F;
42
43 // Start frame: 4 bytes of 0x00
44 *out++ = 0x00;
45 *out++ = 0x00;
46 *out++ = 0x00;
47 *out++ = 0x00;
48
49 // LED data: brightness header + BGR (count as we go)
50 size_t num_leds = 0;
51 while (first != last) {
52 const fl::array<u8, BYTES_PER_PIXEL_RGB>& pixel = *first;
53 *out++ = 0xE0 | global_brightness;
54 *out++ = pixel[0]; // Index 0 (BGR order: Blue)
55 *out++ = pixel[1]; // Index 1 (BGR order: Green)
56 *out++ = pixel[2]; // Index 2 (BGR order: Red)
57 ++first;
58 ++num_leds;
59 }
60
61 // SK9822 difference: end frame uses 0x00 instead of 0xFF
62 size_t end_dwords = (num_leds / 32) + 1;
63 for (size_t i = 0; i < end_dwords * 4; i++) {
64 *out++ = 0x00;
65 }
66}
67
77template <typename InputIterator, typename BrightnessIterator, typename OutputIterator>
78void encodeSK9822_HD(InputIterator first, InputIterator last,
79 BrightnessIterator brightness_first, OutputIterator out) FL_NOEXCEPT {
80 // Start frame: 4 bytes of 0x00
81 *out++ = 0x00;
82 *out++ = 0x00;
83 *out++ = 0x00;
84 *out++ = 0x00;
85
86 // LED data: brightness header + BGR (per-LED brightness, count as we go)
87 size_t num_leds = 0;
88 while (first != last) {
89 const fl::array<u8, BYTES_PER_PIXEL_RGB>& pixel = *first;
90 u8 brightness_8bit = *brightness_first;
91 u8 brightness_5bit = mapBrightness8to5(brightness_8bit);
92
93 *out++ = 0xE0 | brightness_5bit;
94 *out++ = pixel[0]; // Index 0 (BGR order: Blue)
95 *out++ = pixel[1]; // Index 1 (BGR order: Green)
96 *out++ = pixel[2]; // Index 2 (BGR order: Red)
97
98 ++first;
99 ++brightness_first;
100 ++num_leds;
101 }
102
103 // SK9822 difference: end frame uses 0x00
104 size_t end_dwords = (num_leds / 32) + 1;
105 for (size_t i = 0; i < end_dwords * 4; i++) {
106 *out++ = 0x00;
107 }
108}
109
119template <typename InputIterator, typename OutputIterator>
121void encodeSK9822_AutoBrightness(InputIterator first, InputIterator last,
122 OutputIterator out) FL_NOEXCEPT {
123 if (first == last) {
124 // Empty range - just write start frame
125 *out++ = 0x00; *out++ = 0x00; *out++ = 0x00; *out++ = 0x00;
126 return;
127 }
128
129 // Start frame
130 *out++ = 0x00;
131 *out++ = 0x00;
132 *out++ = 0x00;
133 *out++ = 0x00;
134
135 // Extract global brightness from first pixel
136 const fl::array<u8, BYTES_PER_PIXEL_RGB>& first_pixel = *first;
137 const u16 maxBrightness = 0x1F;
138 // Use sequential comparisons to avoid nested fl::max (helps AVR register allocation)
139 u8 max_rg = (first_pixel[2] > first_pixel[1]) ? first_pixel[2] : first_pixel[1];
140 u8 max_component = (max_rg > first_pixel[0]) ? max_rg : first_pixel[0];
141 u16 brightness = ((((u16)max_component + 1) * maxBrightness - 1) >> 8) + 1;
142 u8 global_brightness = static_cast<u8>(brightness);
143
144 // Write first LED with extracted brightness (BGR order: 0=B, 1=G, 2=R)
145 u8 s0 = (maxBrightness * first_pixel[2] + (brightness >> 1)) / brightness; // Red
146 u8 s1 = (maxBrightness * first_pixel[1] + (brightness >> 1)) / brightness; // Green
147 u8 s2 = (maxBrightness * first_pixel[0] + (brightness >> 1)) / brightness; // Blue
148
149 *out++ = 0xE0 | (global_brightness & 0x1F);
150 *out++ = s2; // Blue
151 *out++ = s1; // Green
152 *out++ = s0; // Red
153 ++first;
154
155 // Write remaining LEDs (count as we go)
156 size_t num_leds = 1; // Already wrote first pixel
157 while (first != last) {
158 const fl::array<u8, BYTES_PER_PIXEL_RGB>& pixel = *first;
159 *out++ = 0xE0 | (global_brightness & 0x1F);
160 *out++ = pixel[0]; // Index 0 (BGR order: Blue)
161 *out++ = pixel[1]; // Index 1 (BGR order: Green)
162 *out++ = pixel[2]; // Index 2 (BGR order: Red)
163 ++first;
164 ++num_leds;
165 }
166
167 // End frame (SK9822 uses 0x00)
168 size_t end_dwords = (num_leds / 32) + 1;
169 for (size_t i = 0; i < end_dwords * 4; i++) {
170 *out++ = 0x00;
171 }
172}
173
174} // namespace fl
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
A fixed-size array implementation similar to std::array.
Definition array.h:27
Constants for SPI chipset encoders.
Shared utilities for SPI chipset encoders.
unsigned char u8
Definition stdint.h:131
FL_NO_INLINE_IF_AVR void encodeSK9822_AutoBrightness(InputIterator first, InputIterator last, OutputIterator out) FL_NOEXCEPT
Encode pixel data in SK9822 format (auto-detected brightness from first pixel)
Definition sk9822.h:121
u8 mapBrightness8to5(u8 brightness_8bit) FL_NOEXCEPT
Map 8-bit brightness to 5-bit (0-31)
void encodeSK9822_HD(InputIterator first, InputIterator last, BrightnessIterator brightness_first, OutputIterator out) FL_NOEXCEPT
Encode pixel data in SK9822 format with per-LED brightness.
Definition sk9822.h:78
void encodeSK9822(InputIterator first, InputIterator last, OutputIterator out, u8 global_brightness=31) FL_NOEXCEPT
Encode pixel data in SK9822 format with global brightness.
Definition sk9822.h:38
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NO_INLINE_IF_AVR
#define FL_NOEXCEPT