FastLED 3.10.6
Loading...
Searching...
No Matches
device_solve.h
Go to the documentation of this file.
1#pragma once
2
3// Device solve: XYZ -> per-emitter light (P7, #4041).
4//
5// For a three-emitter device the solve is exact and linear: the emitter
6// matrix is inverted once when a profile is bound, and each pixel is one
7// matrix multiply. A3/B11 forbid iterative solvers such as nnls3 on the
8// per-pixel path; nothing here is iterative, and a structural test enforces
9// that the implementation stays that way.
10
12#include "fl/stl/int.h"
13#include "fl/stl/noexcept.h"
14
15namespace fl {
16
17// These three symbols are public for the same reason the P6 stage headers
18// are: the pipeline is being landed stage by stage, and the `show()` wiring
19// that will call them needs P7's gamut mapper first. They are not exposed
20// through `fl/gfx/gfx.h` and are not part of the sketch-facing API.
21//
22// The existing colorimetric API cannot carry this. `solve_rgb_colorimetric`
23// is float and may fall back to `nnls3`, which A3/B11 forbid per pixel --
24// that is precisely what this replaces on the streaming path, and
25// ci/tests/test_no_iterative_solver_per_pixel.py enforces the separation.
26
32 i32 m[3][3];
33};
34
44 i32 xy_r[2];
45 i32 xy_g[2];
46 i32 xy_b[2];
48 i32 lum_r;
49 i32 lum_g;
50 i32 lum_b;
51};
52
71
83bool invert3x3Q16(const i32 (&in)[3][3], i32 (&out)[3][3]) FL_NO_EXCEPT;
84
88bool q16FromFloatBits(float value, i32* out) FL_NO_EXCEPT;
89
90namespace detail {
92i64 roundedDivideQ16(i64 numerator, i64 denominator) FL_NO_EXCEPT;
95bool xyzColumnQ16(const i32 (&xy)[2], i32 luminance, i64 (&column)[3]) FL_NO_EXCEPT;
97i32 dotRowQ16(const i32 (&row)[3], const i32 (&v)[3]) FL_NO_EXCEPT;
98} // namespace detail
99
109bool buildRgbSolveMatrixQ16(const colorimetric_response::EmitterProfile& profile,
110 EmitterSolveMatrixQ16* out) FL_NO_EXCEPT;
111
117void solveRgbDrivesQ16(const EmitterSolveMatrixQ16& matrix,
118 const i32 (&xyz)[3], i32 (&drives)[3]) FL_NO_EXCEPT;
119
120} // namespace fl
unsigned int xy(unsigned int x, unsigned int y)
Shared colorimetric primitives reusable by the RGBW and (future) RGB colorimetric paths (issue #3255)...
i32 dotRowQ16(const i32(&row)[3], const i32(&v)[3]) FL_NO_EXCEPT
One s16.16 matrix row against a vector, rounded and saturated.
i64 roundedDivideQ16(i64 numerator, i64 denominator) FL_NO_EXCEPT
The s16.16 building blocks the bind-time builders share.
bool xyzColumnQ16(const i32(&xy)[2], i32 luminance, i64(&column)[3]) FL_NO_EXCEPT
XYZ of chromaticity xy at luminance luminance, all s16.16; false for a non-positive or out-of-simplex...
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_info.h:57
bool buildRgbSolveMatrixFromQ16(const EmitterChromaticitiesQ16 &profile, EmitterSolveMatrixQ16 *out) FL_NO_EXCEPT
Build the inverse emitter matrix from a Q16 profile, without floats.
constexpr int type_rank< T >::value
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
bool invert3x3Q16(const i32(&in)[3][3], i32(&out)[3][3]) FL_NO_EXCEPT
Inverse of an s16.16 3x3 matrix, in s16.16, computed without floats.
bool buildRgbSolveMatrixQ16(const colorimetric_response::EmitterProfile &profile, EmitterSolveMatrixQ16 *out) FL_NO_EXCEPT
Invert the emitter matrix for a three-emitter profile.
bool q16FromFloatBits(float value, i32 *out) FL_NO_EXCEPT
s16.16 of a float, rounded to nearest, computed from its IEEE-754 bits with integer arithmetic only –...
void solveRgbDrivesQ16(const EmitterSolveMatrixQ16 &matrix, const i32(&xyz)[3], i32(&drives)[3]) FL_NO_EXCEPT
One pixel: XYZ in s16.16 to three emitter drives in s16.16.
Base definition for an LED controller.
Definition crgb.hpp:179
i32 lum_r
Peak luminance per emitter relative to source white, s16.16.
i32 xy_r[2]
CIE 1931 xy per emitter, s16.16, so 0.64 is 41943.
Inverse emitter matrix in s16.16, mapping XYZ to three emitter drives.
A three-emitter profile with every field in s16.16.
#define FL_NO_EXCEPT
fl::i64 i64
Definition stdint.h:221