aboutsummaryrefslogtreecommitdiff
path: root/jack/color.c
diff options
context:
space:
mode:
Diffstat (limited to 'jack/color.c')
-rw-r--r--jack/color.c152
1 files changed, 80 insertions, 72 deletions
diff --git a/jack/color.c b/jack/color.c
index 4d833f3..9728d99 100644
--- a/jack/color.c
+++ b/jack/color.c
@@ -1,101 +1,110 @@
-// Copyright 2024 [email protected]
+// Copyright 2025 [email protected]
// SPDX-License-Identifier: GPL-2.0-or-later
#include "color.h"
#include <lib/lib8tion/lib8tion.h>
-#define FORCE_REFERENCE(var) __asm__ volatile("" : : "r"(var))
-#define FASTLED_SCALE8_FIXED 1
+#define K255 255
+#define K171 171
+#define K170 170
+#define K85 85
+
+// Adapted from https://fastled.io/docs/hsv2rgb_8cpp_source.html
+// void hsv2rgb_rainbow() function
RGB rgb_matrix_hsv_to_rgb(const HSV hsv) {
- const uint8_t Y1 = 1, Y2 = 0, G_2 = 1, Gscale = 0, hue = hsv.h, sat = hsv.s;
- uint8_t val = hsv.v, offset = hue & 0x1F, offset8 = offset;
- {
-#ifdef __AVR__
- offset8 <<= 1;
- __asm__ volatile("");
- offset8 <<= 1;
- __asm__ volatile("");
- offset8 <<= 1;
-#else
- offset8 <<= 3;
-#endif
- }
- uint8_t third = scale8(offset8, (256 / 3)), r, g, b;
+ // Yellow has a higher inherent brightness than
+ // any other color; 'pure' yellow is perceived to
+ // be 93% as bright as white. In order to make
+ // yellow appear the correct relative brightness,
+ // it has to be rendered brighter than all other
+ // colors.
+ const uint8_t hue = hsv.h;
+ const uint8_t sat = hsv.s;
+ uint8_t val = hsv.v;
+
+ // offset8 = (hue [0..31]) * 8
+ uint8_t offset8 = hue & 0x1F;
+ offset8 <<= 3;
+
+ uint8_t third = scale8(offset8, (256 / 3)); // max = 85
+ uint8_t r, g, b;
if (!(hue & 0x80)) {
+ // 0XX
if (!(hue & 0x40)) {
+ // 00X
+ // section 0-1
if (!(hue & 0x20)) {
- r = 255 - third;
+ // 000
+ // case 0: // R -> O
+ r = K255 - third;
g = third;
b = 0;
- FORCE_REFERENCE(b);
} else {
- if (Y1) {
- r = 171;
- g = 85 + third;
- b = 0;
- FORCE_REFERENCE(b);
- }
- if (Y2) {
- r = 170 + third;
- uint8_t twothirds = scale8(offset8, ((256 * 2) / 3));
- g = 85 + twothirds;
- b = 0;
- FORCE_REFERENCE(b);
- }
+ // 001
+ // case 1: // O -> Y
+ r = K171;
+ g = K85 + third;
+ b = 0;
}
} else {
+ // 01X
+ // section 2-3
if (!(hue & 0x20)) {
- if (Y1) {
- uint8_t twothirds = scale8(offset8, ((256 * 2) / 3));
- r = 171 - twothirds;
- g = 170 + third;
- b = 0;
- FORCE_REFERENCE(b);
- }
- if (Y2) {
- r = 255 - offset8;
- g = 255;
- b = 0;
- FORCE_REFERENCE(b);
- }
+ // 010
+ // case 2: // Y -> G
+ // uint8_t twothirds = (third << 1);
+ uint8_t twothirds = scale8(offset8, ((256 * 2) / 3)); // max=170
+ r = K171 - twothirds;
+ g = K170 + third;
+ b = 0;
} else {
+ // 011
+ // case 3: // G -> A
r = 0;
- FORCE_REFERENCE(r);
- g = 255 - third;
+ g = K255 - third;
b = third;
}
}
} else {
+ // section 4-7
+ // 1XX
if (!(hue & 0x40)) {
+ // 10X
if (!(hue & 0x20)) {
+ // 100
+ // case 4: // A -> B
r = 0;
- FORCE_REFERENCE(r);
- uint8_t twothirds = scale8(offset8, ((256 * 2) / 3));
- g = 171 - twothirds;
- b = 85 + twothirds;
+ // uint8_t twothirds = (third << 1);
+ uint8_t twothirds = scale8(offset8, ((256 * 2) / 3)); // max=170
+ g = K171 - twothirds; // K170?
+ b = K85 + twothirds;
} else {
+ // 101
+ // case 5: // B -> P
r = third;
g = 0;
- FORCE_REFERENCE(g);
- b = 255 - third;
+ b = K255 - third;
}
} else {
if (!(hue & 0x20)) {
- r = 85 + third;
+ // 110
+ // case 6: // P -- K
+ r = K85 + third;
g = 0;
- FORCE_REFERENCE(g);
- b = 171 - third;
+ b = K171 - third;
} else {
- r = 170 + third;
+ // 111
+ // case 7: // K -> R
+ r = K170 + third;
g = 0;
- FORCE_REFERENCE(g);
- b = 85 - third;
+ b = K85 - third;
}
}
}
- if (G_2)
- g = g >> 1;
- if (Gscale)
- g = scale8_video_LEAVING_R1_DIRTY(g, Gscale);
+ // This is one of the good places to scale the green down,
+ // although the client can scale green down as well.
+ g >>= 1;
+ // Scale down colors if we're desaturated at all
+ // and add the brightness_floor to r, g, and b.
if (sat != 255) {
if (sat == 0) {
r = 255;
@@ -105,27 +114,26 @@ RGB rgb_matrix_hsv_to_rgb(const HSV hsv) {
uint8_t desat = 255 - sat;
desat = scale8_video(desat, desat);
uint8_t satscale = 255 - desat;
- r = scale8_LEAVING_R1_DIRTY(r, satscale);
- g = scale8_LEAVING_R1_DIRTY(g, satscale);
- b = scale8_LEAVING_R1_DIRTY(b, satscale);
- cleanup_R1();
+ r = scale8(r, satscale);
+ g = scale8(g, satscale);
+ b = scale8(b, satscale);
uint8_t brightness_floor = desat;
r += brightness_floor;
g += brightness_floor;
b += brightness_floor;
}
}
+ // Now scale everything down if we're at value < 255.
if (val != 255) {
- val = scale8_video_LEAVING_R1_DIRTY(val, val);
+ val = scale8_video(val, val);
if (val == 0) {
r = 0;
g = 0;
b = 0;
} else {
- r = scale8_LEAVING_R1_DIRTY(r, val);
- g = scale8_LEAVING_R1_DIRTY(g, val);
- b = scale8_LEAVING_R1_DIRTY(b, val);
- cleanup_R1();
+ r = scale8(r, val);
+ g = scale8(g, val);
+ b = scale8(b, val);
}
}
return (RGB){.r = r, .g = g, .b = b};