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