aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Rinkel <[email protected]>2023-11-04 14:37:28 +0100
committerLeon Rinkel <[email protected]>2023-11-04 14:37:28 +0100
commitfb2e4369d0854384287e7c0406f1df8fbb1db606 (patch)
tree8005ea70e82cff8b3386203be1169c12441405ae
parent9dc5b296672299eadbbc631a84df122390bfd386 (diff)
Move RGBW conversion to separate file, fix dimming to zero
-rw-r--r--drivers/ws2812/CMakeLists.txt2
-rw-r--r--drivers/ws2812/rgbw.c69
-rw-r--r--drivers/ws2812/rgbw.h11
-rw-r--r--drivers/ws2812/ws2812_gpio.c54
-rw-r--r--drivers/ws2812/ws2812_i2s.c54
-rw-r--r--drivers/ws2812/ws2812_spi.c54
6 files changed, 100 insertions, 144 deletions
diff --git a/drivers/ws2812/CMakeLists.txt b/drivers/ws2812/CMakeLists.txt
index dfafd93..c5f985d 100644
--- a/drivers/ws2812/CMakeLists.txt
+++ b/drivers/ws2812/CMakeLists.txt
@@ -2,6 +2,8 @@
zephyr_library()
+zephyr_library_sources(rgbw.c)
+
zephyr_library_sources_ifdef(CONFIG_LUMEN_WS2812_STRIP_GPIO ws2812_gpio.c)
zephyr_library_sources_ifdef(CONFIG_LUMEN_WS2812_STRIP_SPI ws2812_spi.c)
zephyr_library_sources_ifdef(CONFIG_LUMEN_WS2812_STRIP_I2S ws2812_i2s.c)
diff --git a/drivers/ws2812/rgbw.c b/drivers/ws2812/rgbw.c
new file mode 100644
index 0000000..ca34713
--- /dev/null
+++ b/drivers/ws2812/rgbw.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2023 Leon Rinkel
+ *
+ * RGB to RGBW conversion according to Wang et al.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <math.h>
+
+#include "rgbw.h"
+
+void rgbw_conversion(
+ /* outs: */ uint8_t* ro, uint8_t* go, uint8_t* bo, uint8_t* wo,
+ /* ins: */ uint8_t ri, uint8_t gi, uint8_t bi, uint8_t algo
+)
+{
+ float m; /** min */
+ float M; /** max */
+ float w; /** white */
+ float k; /** gain */
+ float r; /** red */
+ float g; /** green */
+ float b; /** blue */
+
+ if (ri == 0 && gi == 0 && bi == 0)
+ {
+ *ro = 0;
+ *go = 0;
+ *bo = 0;
+ *wo = 0;
+ return;
+ }
+
+ m = fmin(ri, fmin(gi, bi));
+ M = fmax(ri, fmax(gi, bi));
+
+ switch (algo)
+ {
+ case 1:
+ w = m;
+ break;
+ case 2:
+ w = pow(m, 2);
+ break;
+ case 3:
+ w = -pow(m, 3) + pow(m, 2) + m;
+ break;
+ case 4:
+ w = (m / M >= 0.5) ? M :
+ (m * M) / (M - m);
+ break;
+
+ default:
+ return;
+ }
+
+ k = (w + M) / M;
+
+ r = k * ri - w;
+ g = k * gi - w;
+ b = k * bi - w;
+
+ *wo = fmax(fmin(floor(w), 255), 0);
+ *ro = fmax(fmin(floor(r), 255), 0);
+ *go = fmax(fmin(floor(g), 255), 0);
+ *bo = fmax(fmin(floor(b), 255), 0);
+}
diff --git a/drivers/ws2812/rgbw.h b/drivers/ws2812/rgbw.h
new file mode 100644
index 0000000..f34a136
--- /dev/null
+++ b/drivers/ws2812/rgbw.h
@@ -0,0 +1,11 @@
+#ifndef LUMEN_WS2812_RGBW_H
+#define LUMEN_WS2812_RGBW_H
+
+#include <stdint.h>
+
+void rgbw_conversion(
+ /* outs: */ uint8_t* ro, uint8_t* go, uint8_t* bo, uint8_t* wo,
+ /* ins: */ uint8_t ri, uint8_t gi, uint8_t bi, uint8_t algo
+);
+
+#endif /* LUMEN_WS2812_RGBW_H */
diff --git a/drivers/ws2812/ws2812_gpio.c b/drivers/ws2812/ws2812_gpio.c
index d5837d4..fa875b9 100644
--- a/drivers/ws2812/ws2812_gpio.c
+++ b/drivers/ws2812/ws2812_gpio.c
@@ -12,7 +12,6 @@
#include <zephyr/drivers/led_strip.h>
#include <string.h>
-#include <math.h>
#define LOG_LEVEL CONFIG_LED_STRIP_LOG_LEVEL
#include <zephyr/logging/log.h>
@@ -26,6 +25,8 @@ LOG_MODULE_REGISTER(ws2812_gpio);
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#include <zephyr/dt-bindings/led/led.h>
+#include "rgbw.h"
+
struct ws2812_gpio_cfg {
struct gpio_dt_spec in_gpio;
uint8_t num_colors;
@@ -145,49 +146,6 @@ static int send_buf(const struct device *dev, uint8_t *buf, size_t len)
return rc;
}
-/** RGB to RGBW conversion according to Wang et al. */
-void do_rgbw_conversion(
- uint8_t* ro, uint8_t* go, uint8_t* bo, uint8_t* wo,
- uint8_t ri, uint8_t gi, uint8_t bi,
- uint8_t algo
-)
-{
- float m = fmin(ri, fmin(gi, bi));
- float M = fmax(ri, fmax(gi, bi));
-
- float w;
- switch (algo)
- {
- case 1:
- w = m;
- break;
- case 2:
- w = pow(m, 2);
- break;
- case 3:
- w = -pow(m, 3) + pow(m, 2) + m;
- break;
- case 4:
- w = (m / M >= 0.5) ? M :
- (m * M) / (M - m);
- break;
-
- default:
- return;
- }
-
- float k = (w + M) / M;
-
- float r = k * ri - w;
- float g = k * gi - w;
- float b = k * bi - w;
-
- *wo = fmax(fmin(floor(w), 255), 0);
- *ro = fmax(fmin(floor(r), 255), 0);
- *go = fmax(fmin(floor(g), 255), 0);
- *bo = fmax(fmin(floor(b), 255), 0);
-}
-
static int ws2812_gpio_update_rgb(const struct device *dev,
struct led_rgb *pixels,
size_t num_pixels)
@@ -201,10 +159,10 @@ static int ws2812_gpio_update_rgb(const struct device *dev,
uint8_t j;
uint8_t ro, go, bo, wo;
- do_rgbw_conversion(
- &ro, &go, &bo, &wo,
- pixels[i].r, pixels[i].g, pixels[i].b,
- 1
+ rgbw_conversion(
+ /* outs: */ &ro, &go, &bo, &wo,
+ /* ins: */ pixels[i].r, pixels[i].g, pixels[i].b,
+ /* algo: */ 1
);
for (j = 0; j < config->num_colors; j++) {
diff --git a/drivers/ws2812/ws2812_i2s.c b/drivers/ws2812/ws2812_i2s.c
index 25d33f8..64f6df7 100644
--- a/drivers/ws2812/ws2812_i2s.c
+++ b/drivers/ws2812/ws2812_i2s.c
@@ -19,7 +19,6 @@
#define DT_DRV_COMPAT worldsemi_ws2812_i2s
#include <string.h>
-#include <math.h>
#include <zephyr/drivers/led_strip.h>
@@ -33,6 +32,8 @@ LOG_MODULE_REGISTER(ws2812_i2s);
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>
+#include "rgbw.h"
+
#define WS2812_I2S_PRE_DELAY_WORDS 1
struct ws2812_i2s_cfg {
@@ -68,49 +69,6 @@ static inline void ws2812_i2s_ser(uint32_t *word, uint8_t color, const uint8_t s
*word = (*word >> 16) | (*word << 16);
}
-/** RGB to RGBW conversion according to Wang et al. */
-void do_rgbw_conversion(
- uint8_t* ro, uint8_t* go, uint8_t* bo, uint8_t* wo,
- uint8_t ri, uint8_t gi, uint8_t bi,
- uint8_t algo
-)
-{
- float m = fmin(ri, fmin(gi, bi));
- float M = fmax(ri, fmax(gi, bi));
-
- float w;
- switch (algo)
- {
- case 1:
- w = m;
- break;
- case 2:
- w = pow(m, 2);
- break;
- case 3:
- w = -pow(m, 3) + pow(m, 2) + m;
- break;
- case 4:
- w = (m / M >= 0.5) ? M :
- (m * M) / (M - m);
- break;
-
- default:
- return;
- }
-
- float k = (w + M) / M;
-
- float r = k * ri - w;
- float g = k * gi - w;
- float b = k * bi - w;
-
- *wo = fmax(fmin(floor(w), 255), 0);
- *ro = fmax(fmin(floor(r), 255), 0);
- *go = fmax(fmin(floor(g), 255), 0);
- *bo = fmax(fmin(floor(b), 255), 0);
-}
-
static int ws2812_strip_update_rgb(const struct device *dev, struct led_rgb *pixels,
size_t num_pixels)
{
@@ -152,10 +110,10 @@ static int ws2812_strip_update_rgb(const struct device *dev, struct led_rgb *pix
*/
for (uint16_t i = 0; i < num_pixels; i++) {
uint8_t ro, go, bo, wo;
- do_rgbw_conversion(
- &ro, &go, &bo, &wo,
- pixels[i].r, pixels[i].g, pixels[i].b,
- 1
+ rgbw_conversion(
+ /* outs: */ &ro, &go, &bo, &wo,
+ /* ins: */ pixels[i].r, pixels[i].g, pixels[i].b,
+ /* algo: */ 1
);
for (uint16_t j = 0; j < cfg->num_colors; j++) {
diff --git a/drivers/ws2812/ws2812_spi.c b/drivers/ws2812/ws2812_spi.c
index 9bebb13..71f3c95 100644
--- a/drivers/ws2812/ws2812_spi.c
+++ b/drivers/ws2812/ws2812_spi.c
@@ -12,7 +12,6 @@
#include <zephyr/drivers/led_strip.h>
#include <string.h>
-#include <math.h>
#define LOG_LEVEL CONFIG_LED_STRIP_LOG_LEVEL
#include <zephyr/logging/log.h>
@@ -25,6 +24,8 @@ LOG_MODULE_REGISTER(ws2812_spi);
#include <zephyr/sys/util.h>
#include <zephyr/dt-bindings/led/led.h>
+#include "rgbw.h"
+
/* spi-one-frame and spi-zero-frame in DT are for 8-bit frames. */
#define SPI_FRAME_BITS 8
@@ -93,49 +94,6 @@ static inline void ws2812_reset_delay(uint16_t delay)
k_usleep(delay);
}
-/** RGB to RGBW conversion according to Wang et al. */
-void do_rgbw_conversion(
- uint8_t* ro, uint8_t* go, uint8_t* bo, uint8_t* wo,
- uint8_t ri, uint8_t gi, uint8_t bi,
- uint8_t algo
-)
-{
- float m = fmin(ri, fmin(gi, bi));
- float M = fmax(ri, fmax(gi, bi));
-
- float w;
- switch (algo)
- {
- case 1:
- w = m;
- break;
- case 2:
- w = pow(m, 2);
- break;
- case 3:
- w = -pow(m, 3) + pow(m, 2) + m;
- break;
- case 4:
- w = (m / M >= 0.5) ? M :
- (m * M) / (M - m);
- break;
-
- default:
- return;
- }
-
- float k = (w + M) / M;
-
- float r = k * ri - w;
- float g = k * gi - w;
- float b = k * bi - w;
-
- *wo = fmax(fmin(floor(w), 255), 0);
- *ro = fmax(fmin(floor(r), 255), 0);
- *go = fmax(fmin(floor(g), 255), 0);
- *bo = fmax(fmin(floor(b), 255), 0);
-}
-
static int ws2812_strip_update_rgb(const struct device *dev,
struct led_rgb *pixels,
size_t num_pixels)
@@ -166,10 +124,10 @@ static int ws2812_strip_update_rgb(const struct device *dev,
uint8_t j;
uint8_t ro, go, bo, wo;
- do_rgbw_conversion(
- &ro, &go, &bo, &wo,
- pixels[i].r, pixels[i].g, pixels[i].b,
- 1
+ rgbw_conversion(
+ /* outs: */ &ro, &go, &bo, &wo,
+ /* ins: */ pixels[i].r, pixels[i].g, pixels[i].b,
+ /* algo: */ 1
);
for (j = 0; j < cfg->num_colors; j++) {