FastLED 3.10.8
Loading...
Searching...
No Matches
apa102.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
29// NOTE: The old loadAndScale_APA102_HD<RGB_ORDER>() function has been removed.
30// RGB reordering now happens upstream via ScaledPixelIteratorRGB adapter.
31// The encoder receives wire-ordered RGB data (fl::array<u8, 3>) and brightness separately.
32// For APA102HD usage, the chipset controller uses ScaledPixelIteratorRGB + ScaledPixelIteratorBrightness
33// with the existing encodeAPA102_HD() function that accepts separate RGB and brightness iterators.
34
44template <typename InputIterator, typename OutputIterator>
45void encodeAPA102(InputIterator first, InputIterator last, OutputIterator out,
46 u8 global_brightness = 31) FL_NO_EXCEPT {
47 // Clamp brightness to 5-bit range
48 global_brightness = global_brightness & 0x1F;
49
50 // Start frame: 4 bytes of 0x00
51 *out++ = 0x00;
52 *out++ = 0x00;
53 *out++ = 0x00;
54 *out++ = 0x00;
55
56 // LED data: brightness header + BGR (count pixels as we go)
57 size_t num_leds = 0;
58 while (first != last) {
59 const fl::array<u8, BYTES_PER_PIXEL_RGB>& pixel = *first;
60 *out++ = 0xE0 | global_brightness;
61 *out++ = pixel[0]; // Index 0 (BGR order: Blue)
62 *out++ = pixel[1]; // Index 1 (BGR order: Green)
63 *out++ = pixel[2]; // Index 2 (BGR order: Red)
64 ++first;
65 ++num_leds;
66 }
67
68 // End frame: (num_leds / 32) + 1 DWords of 0xFF
69 size_t end_dwords = (num_leds / 32) + 1;
70 for (size_t i = 0; i < end_dwords * 4; i++) {
71 *out++ = 0xFF;
72 }
73}
74
85template <typename InputIterator, typename BrightnessIterator, typename OutputIterator>
86void encodeAPA102_HD(InputIterator first, InputIterator last,
87 BrightnessIterator brightness_first, OutputIterator out) FL_NO_EXCEPT {
88 // Start frame: 4 bytes of 0x00
89 *out++ = 0x00;
90 *out++ = 0x00;
91 *out++ = 0x00;
92 *out++ = 0x00;
93
94 // LED data: brightness header + BGR (per-LED brightness, count as we go)
95 size_t num_leds = 0;
96 while (first != last) {
97 const fl::array<u8, BYTES_PER_PIXEL_RGB>& pixel = *first;
98 u8 brightness_8bit = *brightness_first;
99 u8 brightness_5bit = mapBrightness8to5(brightness_8bit);
100
101 *out++ = 0xE0 | brightness_5bit;
102 *out++ = pixel[0]; // Index 0 (BGR order: Blue)
103 *out++ = pixel[1]; // Index 1 (BGR order: Green)
104 *out++ = pixel[2]; // Index 2 (BGR order: Red)
105
106 ++first;
107 ++brightness_first;
108 ++num_leds;
109 }
110
111 // End frame: (num_leds / 32) + 1 DWords of 0xFF
112 size_t end_dwords = (num_leds / 32) + 1;
113 for (size_t i = 0; i < end_dwords * 4; i++) {
114 *out++ = 0xFF;
115 }
116}
117
128template <typename InputIterator, typename OutputIterator>
131void encodeAPA102_AutoBrightness(InputIterator first, InputIterator last,
132 OutputIterator out) FL_NO_EXCEPT {
133 if (first == last) {
134 // Preserve a complete frame even at zero LEDs. This matters when a
135 // previously longer cascade is reconfigured through the public API.
136 *out++ = 0x00; *out++ = 0x00; *out++ = 0x00; *out++ = 0x00;
137 *out++ = 0xFF; *out++ = 0xFF; *out++ = 0xFF; *out++ = 0xFF;
138 return;
139 }
140
141 // Start frame
142 *out++ = 0x00;
143 *out++ = 0x00;
144 *out++ = 0x00;
145 *out++ = 0x00;
146
147 // Extract global brightness from first pixel
148 const fl::array<u8, BYTES_PER_PIXEL_RGB>& first_pixel = *first;
149 const u16 maxBrightness = 0x1F;
150 // Use sequential comparisons to avoid nested fl::max (helps AVR register allocation)
151 u8 max_rg = (first_pixel[2] > first_pixel[1]) ? first_pixel[2] : first_pixel[1];
152 u8 max_component = (max_rg > first_pixel[0]) ? max_rg : first_pixel[0];
153 u16 brightness = ((((u16)max_component + 1) * maxBrightness - 1) >> 8) + 1;
154 u8 global_brightness = static_cast<u8>(brightness);
155
156 // Write first LED with extracted brightness (BGR order: 0=B, 1=G, 2=R)
157 u8 s0 = (maxBrightness * first_pixel[2] + (brightness >> 1)) / brightness; // Red
158 u8 s1 = (maxBrightness * first_pixel[1] + (brightness >> 1)) / brightness; // Green
159 u8 s2 = (maxBrightness * first_pixel[0] + (brightness >> 1)) / brightness; // Blue
160
161 *out++ = 0xE0 | (global_brightness & 0x1F);
162 *out++ = s2; // Blue
163 *out++ = s1; // Green
164 *out++ = s0; // Red
165 ++first;
166
167 // Write remaining LEDs (count as we go)
168 size_t num_leds = 1; // Already wrote first pixel
169 while (first != last) {
170 const fl::array<u8, BYTES_PER_PIXEL_RGB>& pixel = *first;
171 *out++ = 0xE0 | (global_brightness & 0x1F);
172 *out++ = pixel[0]; // Index 0 (BGR order: Blue)
173 *out++ = pixel[1]; // Index 1 (BGR order: Green)
174 *out++ = pixel[2]; // Index 2 (BGR order: Red)
175 ++first;
176 ++num_leds;
177 }
178
179 // End frame
180 size_t end_dwords = (num_leds / 32) + 1;
181 for (size_t i = 0; i < end_dwords * 4; i++) {
182 *out++ = 0xFF;
183 }
184}
185
186} // 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
#define FL_OPTIMIZE_O2
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
FL_NO_INLINE_IF_AVR FL_OPTIMIZE_O2 void encodeAPA102_AutoBrightness(InputIterator first, InputIterator last, OutputIterator out) FL_NO_EXCEPT
Encode pixel data in APA102 format (auto-detected brightness from first pixel)
Definition apa102.h:131
void encodeAPA102_HD(InputIterator first, InputIterator last, BrightnessIterator brightness_first, OutputIterator out) FL_NO_EXCEPT
Encode pixel data in APA102 format with per-LED brightness.
Definition apa102.h:86
u8 mapBrightness8to5(u8 brightness_8bit) FL_NO_EXCEPT
Map 8-bit brightness to 5-bit (0-31)
void encodeAPA102(InputIterator first, InputIterator last, OutputIterator out, u8 global_brightness=31) FL_NO_EXCEPT
Encode pixel data in APA102 format with global brightness.
Definition apa102.h:45
Base definition for an LED controller.
Definition crgb.hpp:179