FastLED 3.9.15
Loading...
Searching...
No Matches
ucs7604.h
Go to the documentation of this file.
1#pragma once
2
19
20#include "fl/stl/stdint.h"
21#include "fl/math/ease.h"
23#include "fl/stl/noexcept.h"
24
25namespace fl {
26
28enum class UCS7604Mode {
31 UCS7604_MODE_16BIT_1600KHZ = 0x9B // not implemented because of timing difference.
32};
33
36 u8 r;
37 u8 g;
38 u8 b;
39 u8 w;
40
42 UCS7604CurrentControl() FL_NOEXCEPT : r(0xF), g(0xF), b(0xF), w(0xF) {}
43
46 : r(brightness & 0xF), g(brightness & 0xF), b(brightness & 0xF), w(brightness & 0xF) {}
47
50 : r(r_ & 0xF), g(g_ & 0xF), b(b_ & 0xF), w(w_ & 0xF) {}
51};
52
68template <typename OutputIterator>
69void buildUCS7604Preamble(OutputIterator out, UCS7604Mode mode,
70 u8 r_current, u8 g_current,
71 u8 b_current, u8 w_current) {
72 // Sync pattern (6 bytes)
73 *out++ = 0xFF;
74 *out++ = 0xFF;
75 *out++ = 0xFF;
76 *out++ = 0xFF;
77 *out++ = 0xFF;
78 *out++ = 0xFF;
79
80 // Header (2 bytes)
81 *out++ = 0x00;
82 *out++ = 0x03;
83
84 // Mode byte
85 *out++ = static_cast<u8>(mode);
86
87 // Current control (4 bytes, 4-bit each, wire order RGBW)
88 *out++ = r_current & 0x0F;
89 *out++ = g_current & 0x0F;
90 *out++ = b_current & 0x0F;
91 *out++ = w_current & 0x0F;
92
93 // Reserved (2 bytes)
94 *out++ = 0x00;
95 *out++ = 0x00;
96}
97
105template <typename InputIterator, typename OutputIterator>
106void encodeUCS7604_8bit_RGB(InputIterator first, InputIterator last, OutputIterator out) {
107 while (first != last) {
108 const auto& pixel = *first;
109 *out++ = pixel[0]; // R
110 *out++ = pixel[1]; // G
111 *out++ = pixel[2]; // B
112 ++first;
113 }
114}
115
123template <typename InputIterator, typename OutputIterator>
124void encodeUCS7604_8bit_RGBW(InputIterator first, InputIterator last, OutputIterator out) {
125 while (first != last) {
126 const auto& pixel = *first;
127 *out++ = pixel[0]; // R
128 *out++ = pixel[1]; // G
129 *out++ = pixel[2]; // B
130 *out++ = pixel[3]; // W
131 ++first;
132 }
133}
134
143template <typename InputIterator, typename OutputIterator>
144void encodeUCS7604_16bit_RGB(InputIterator first, InputIterator last, OutputIterator out,
145 const Gamma8& gamma) {
146 while (first != last) {
147 const auto& pixel = *first;
148
149 // Apply gamma correction for 16-bit output
150 u8 rgb_in[3] = { pixel[0], pixel[1], pixel[2] };
151 u16 rgb_out[3];
152 gamma.convert(fl::span<const u8>(rgb_in, 3), fl::span<u16>(rgb_out, 3));
153
154 // Write big-endian 16-bit values
155 *out++ = rgb_out[0] >> 8;
156 *out++ = rgb_out[0] & 0xFF;
157 *out++ = rgb_out[1] >> 8;
158 *out++ = rgb_out[1] & 0xFF;
159 *out++ = rgb_out[2] >> 8;
160 *out++ = rgb_out[2] & 0xFF;
161 ++first;
162 }
163}
164
173template <typename InputIterator, typename OutputIterator>
174void encodeUCS7604_16bit_RGBW(InputIterator first, InputIterator last, OutputIterator out,
175 const Gamma8& gamma) {
176 while (first != last) {
177 const auto& pixel = *first;
178
179 // Apply gamma correction for 16-bit output
180 u8 rgbw_in[4] = { pixel[0], pixel[1], pixel[2], pixel[3] };
181 u16 rgbw_out[4];
182 gamma.convert(fl::span<const u8>(rgbw_in, 4), fl::span<u16>(rgbw_out, 4));
183
184 // Write big-endian 16-bit values
185 *out++ = rgbw_out[0] >> 8;
186 *out++ = rgbw_out[0] & 0xFF;
187 *out++ = rgbw_out[1] >> 8;
188 *out++ = rgbw_out[1] & 0xFF;
189 *out++ = rgbw_out[2] >> 8;
190 *out++ = rgbw_out[2] & 0xFF;
191 *out++ = rgbw_out[3] >> 8;
192 *out++ = rgbw_out[3] & 0xFF;
193 ++first;
194 }
195}
196
208template <typename OutputIterator>
209void encodeUCS7604(PixelIterator& pixel_iter, size_t num_leds, OutputIterator out,
210 UCS7604Mode mode, const UCS7604CurrentControl& current, bool is_rgbw,
211 const Gamma8* gamma = nullptr) {
212 constexpr size_t PREAMBLE_LEN = 15;
213
214 // Calculate bytes per LED based on mode and RGB/RGBW
215 size_t bytes_per_led;
217 bytes_per_led = is_rgbw ? 4 : 3;
218 } else {
219 bytes_per_led = is_rgbw ? 8 : 6;
220 }
221
222 // Calculate total data size and padding
223 size_t led_data_size = num_leds * bytes_per_led;
224 size_t total_data_size = PREAMBLE_LEN + led_data_size;
225 size_t padding = (3 - (total_data_size % 3)) % 3;
226
227 // Build preamble (15 bytes) with current control
228 buildUCS7604Preamble(out, mode, current.r, current.g, current.b, current.w);
229
230 // Add padding (0-2 zero bytes)
231 for (size_t i = 0; i < padding; ++i) {
232 *out++ = 0;
233 }
234
235 // Encode LED data based on mode and RGB/RGBW
237 if (is_rgbw) {
238 auto range = makeScaledPixelRangeRGBW(&pixel_iter);
239 encodeUCS7604_8bit_RGBW(range.first, range.second, out);
240 } else {
241 auto range = makeScaledPixelRangeRGB(&pixel_iter);
242 encodeUCS7604_8bit_RGB(range.first, range.second, out);
243 }
244 } else {
245 // 16-bit modes — fall back to gamma 2.8 if no gamma provided
246 static fl::shared_ptr<const Gamma8> default_gamma;
247 const Gamma8& g = gamma ? *gamma : *(default_gamma ? default_gamma : (default_gamma = Gamma8::getOrCreate(2.8f)));
248 if (is_rgbw) {
249 auto range = makeScaledPixelRangeRGBW(&pixel_iter);
250 encodeUCS7604_16bit_RGBW(range.first, range.second, out, g);
251 } else {
252 auto range = makeScaledPixelRangeRGB(&pixel_iter);
253 encodeUCS7604_16bit_RGB(range.first, range.second, out, g);
254 }
255 }
256}
257
258} // namespace fl
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
static fl::shared_ptr< const Gamma8 > getOrCreate(float gamma) FL_NOEXCEPT
Definition ease.cpp.hpp:459
pair< detail::ScaledPixelIteratorRGB, detail::ScaledPixelIteratorRGB > makeScaledPixelRangeRGB(PixelIterator *pixels) FL_NOEXCEPT
Create RGB input iterator range from PixelIterator.
unsigned char u8
Definition stdint.h:131
void buildUCS7604Preamble(OutputIterator out, UCS7604Mode mode, u8 r_current, u8 g_current, u8 b_current, u8 w_current)
Build UCS7604 preamble (15 bytes)
Definition ucs7604.h:69
void encodeUCS7604_8bit_RGB(InputIterator first, InputIterator last, OutputIterator out)
Encode RGB pixels in UCS7604 8-bit format.
Definition ucs7604.h:106
void encodeUCS7604_16bit_RGBW(InputIterator first, InputIterator last, OutputIterator out, const Gamma8 &gamma)
Encode RGBW pixels in UCS7604 16-bit format with gamma correction.
Definition ucs7604.h:174
pair< detail::ScaledPixelIteratorRGBW, detail::ScaledPixelIteratorRGBW > makeScaledPixelRangeRGBW(PixelIterator *pixels) FL_NOEXCEPT
Create RGBW input iterator range from PixelIterator.
UCS7604Mode
UCS7604 protocol configuration modes.
Definition ucs7604.h:28
@ UCS7604_MODE_8BIT_800KHZ
Definition ucs7604.h:29
@ UCS7604_MODE_16BIT_1600KHZ
Definition ucs7604.h:31
@ UCS7604_MODE_16BIT_800KHZ
Definition ucs7604.h:30
constexpr u32 gamma(float g) FL_NOEXCEPT
Definition gamma_lut.h:36
void encodeUCS7604_8bit_RGBW(InputIterator first, InputIterator last, OutputIterator out)
Encode RGBW pixels in UCS7604 8-bit format.
Definition ucs7604.h:124
void encodeUCS7604_16bit_RGB(InputIterator first, InputIterator last, OutputIterator out, const Gamma8 &gamma)
Encode RGB pixels in UCS7604 16-bit format with gamma correction.
Definition ucs7604.h:144
void encodeUCS7604(PixelIterator &pixel_iter, size_t num_leds, OutputIterator out, UCS7604Mode mode, const UCS7604CurrentControl &current, bool is_rgbw, const Gamma8 *gamma=nullptr)
Encode complete UCS7604 frame (preamble + padding + pixel data)
Definition ucs7604.h:209
Base definition for an LED controller.
Definition crgb.hpp:179
Adapter layer bridging PixelIterator to encoder input iterators.
#define FL_NOEXCEPT
UCS7604CurrentControl(u8 brightness)
Construct from single brightness value (all channels)
Definition ucs7604.h:45
u8 g
Green channel current (0x0-0xF)
Definition ucs7604.h:37
u8 b
Blue channel current (0x0-0xF)
Definition ucs7604.h:38
UCS7604CurrentControl() FL_NOEXCEPT
Default constructor - maximum brightness.
Definition ucs7604.h:42
u8 w
White channel current (0x0-0xF)
Definition ucs7604.h:39
UCS7604CurrentControl(u8 r_, u8 g_, u8 b_, u8 w_)
Construct from individual channel values.
Definition ucs7604.h:49
u8 r
Red channel current (0x0-0xF)
Definition ucs7604.h:36
UCS7604 current control structure with 4-bit fields for each channel.
Definition ucs7604.h:35