Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions components/leds/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ unsigned leds_format_count(size_t len, enum leds_format format, unsigned group)
return len / (4 * group) * group;

case LEDS_FORMAT_RGBXI:
case LEDS_FORMAT_BGRXI:
case LEDS_FORMAT_GRBXI:
return len / (3 + group) * group;

case LEDS_FORMAT_RGBWXI:
Expand Down Expand Up @@ -156,6 +158,66 @@ void leds_set_format_rgbxi(struct leds *leds, const uint8_t *data, size_t len, s
}
}

void leds_set_format_bgrxi(struct leds *leds, const uint8_t *data, size_t len, struct leds_format_params params)
{
enum leds_parameter_type parameter_type = leds_parameter_type(leds);
uint8_t parameter_default = leds_parameter_default(leds);

LOG_DEBUG("len=%u offset=%u count=%u segment=%u group=%u", len, params.offset, params.count, params.segment, params.group);

size_t off = 0;

for (unsigned g = 0; g * params.group < params.count && len >= off + 3 + params.group; g++) {
struct leds_color group_color = {};

group_color.b = data[off++];
group_color.g = data[off++];
group_color.r = data[off++];
group_color.parameter = parameter_default;

LOG_DEBUG("\tg=%u off=%u rgb=%02x%02x%02x", g, off, group_color.r, group_color.g, group_color.b);

for (unsigned i = 0; i < params.group && g * params.group + i < params.count; i++) {
uint8_t intensity = data[off++];
struct leds_color pixel_color = leds_color_intensity(group_color, parameter_type, intensity);

for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + (g * params.group + i) * params.segment + j] = pixel_color;
}
}
}
}

void leds_set_format_grbxi(struct leds *leds, const uint8_t *data, size_t len, struct leds_format_params params)
{
enum leds_parameter_type parameter_type = leds_parameter_type(leds);
uint8_t parameter_default = leds_parameter_default(leds);

LOG_DEBUG("len=%u offset=%u count=%u segment=%u group=%u", len, params.offset, params.count, params.segment, params.group);

size_t off = 0;

for (unsigned g = 0; g * params.group < params.count && len >= off + 3 + params.group; g++) {
struct leds_color group_color = {};

group_color.g = data[off++];
group_color.r = data[off++];
group_color.b = data[off++];
group_color.parameter = parameter_default;

LOG_DEBUG("\tg=%u off=%u rgb=%02x%02x%02x", g, off, group_color.r, group_color.g, group_color.b);

for (unsigned i = 0; i < params.group && g * params.group + i < params.count; i++) {
uint8_t intensity = data[off++];
struct leds_color pixel_color = leds_color_intensity(group_color, parameter_type, intensity);

for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + (g * params.group + i) * params.segment + j] = pixel_color;
}
}
}
}

void leds_set_format_rgbwxi(struct leds *leds, const uint8_t *data, size_t len, struct leds_format_params params)
{
enum leds_parameter_type parameter_type = leds_parameter_type(leds);
Expand Down Expand Up @@ -234,6 +296,14 @@ int leds_set_format(struct leds *leds, enum leds_format format, const void *data
leds_set_format_rgbxi(leds, data, len, params);
return 0;

case LEDS_FORMAT_BGRXI:
leds_set_format_bgrxi(leds, data, len, params);
return 0;

case LEDS_FORMAT_GRBXI:
leds_set_format_grbxi(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBWXI:
leds_set_format_rgbwxi(leds, data, len, params);
return 0;
Expand Down
12 changes: 10 additions & 2 deletions components/leds/include/leds.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,19 @@ enum leds_protocol {
LEDS_PROTOCOL_APA102,
LEDS_PROTOCOL_P9813,

LEDS_PROTOCOL_WS2812B,
LEDS_PROTOCOL_WS2812B_GRB,
LEDS_PROTOCOL_WS2812B_RGB,
LEDS_PROTOCOL_SK6812_GRBW,
LEDS_PROTOCOL_WS2811,
LEDS_PROTOCOL_WS2811_RGB,
LEDS_PROTOCOL_WS2811_GRB,
LEDS_PROTOCOL_SK9822,
LEDS_PROTOCOL_SM16703,

LEDS_PROTOCOLS_COUNT,

// compat
LEDS_PROTOCOL_WS2812B = LEDS_PROTOCOL_WS2812B_GRB,
LEDS_PROTOCOL_WS2811 = LEDS_PROTOCOL_WS2811_RGB,
};

enum leds_format {
Expand All @@ -98,6 +104,8 @@ enum leds_format {
LEDS_FORMAT_RGBW,

LEDS_FORMAT_RGBXI, // grouped RGB + intensity
LEDS_FORMAT_BGRXI, // grouped BGR + intensity
LEDS_FORMAT_GRBXI, // grouped GRB + intensity
LEDS_FORMAT_RGBWXI, // grouped RGBW + intensity
};

Expand Down
59 changes: 59 additions & 0 deletions components/leds/pixel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include <leds.h>
#include "limit.h"

union leds_pixel_rgb {
struct {
uint8_t b, g, r;
};

// aligned with 0xXXRRGGBB on little-endian architectures
uint32_t _rgb;
};

static inline union leds_pixel_rgb leds_pixel_rgb(struct leds_color color, unsigned index, const struct leds_limit *limit)
{
return (union leds_pixel_rgb) {
.b = leds_limit_uint8(limit, index, color.b),
.g = leds_limit_uint8(limit, index, color.g),
.r = leds_limit_uint8(limit, index, color.r),
};
}

union leds_pixel_grb {
struct {
uint8_t b, r, g;
};

// aligned with 0xXXGGRRBB on little-endian architectures
uint32_t _grb;
};

static inline union leds_pixel_grb leds_pixel_grb(struct leds_color color, unsigned index, const struct leds_limit *limit)
{
return (union leds_pixel_grb) {
.b = leds_limit_uint8(limit, index, color.b),
.r = leds_limit_uint8(limit, index, color.r),
.g = leds_limit_uint8(limit, index, color.g),
};
}

union leds_pixel_grbw {
struct {
uint8_t w, b, r, g;
};

// aligned with 0xGGRRBBWW on little-endian architectures
uint32_t grbw;
};

static inline union leds_pixel_grbw leds_pixel_grbw(struct leds_color color, unsigned index, const struct leds_limit *limit)
{
return (union leds_pixel_grbw) {
.w = leds_limit_uint8(limit, index, color.white),
.b = leds_limit_uint8(limit, index, color.b),
.r = leds_limit_uint8(limit, index, color.r),
.g = leds_limit_uint8(limit, index, color.g),
};
}
6 changes: 4 additions & 2 deletions components/leds/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ const struct leds_protocol_type *leds_protocol_types[LEDS_PROTOCOLS_COUNT] = {
[LEDS_PROTOCOL_APA102] = &leds_protocol_apa102,
[LEDS_PROTOCOL_P9813] = &leds_protocol_p9813,

[LEDS_PROTOCOL_WS2812B] = &leds_protocol_ws2812b,
[LEDS_PROTOCOL_WS2812B_GRB] = &leds_protocol_ws2812b_grb,
[LEDS_PROTOCOL_WS2812B_RGB] = &leds_protocol_ws2812b_rgb,
[LEDS_PROTOCOL_SK6812_GRBW] = &leds_protocol_sk6812grbw,
[LEDS_PROTOCOL_WS2811] = &leds_protocol_ws2811,
[LEDS_PROTOCOL_WS2811_RGB] = &leds_protocol_ws2811_rgb,
[LEDS_PROTOCOL_WS2811_GRB] = &leds_protocol_ws2811_grb,
[LEDS_PROTOCOL_SK9822] = &leds_protocol_sk9822,
[LEDS_PROTOCOL_SM16703] = &leds_protocol_sm16703,
};
Expand Down
19 changes: 0 additions & 19 deletions components/leds/protocols/sk6812grbw.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,6 @@
#include <leds.h>
#include "../protocol.h"

union sk6812grbw_pixel {
struct {
uint8_t w, b, r, g;
};

// aligned with 0xGGRRBBWW on little-endian architectures
uint32_t grbw;
};

static inline union sk6812grbw_pixel sk6812grbw_pixel(struct leds_color color, unsigned index, const struct leds_limit *limit)
{
return (union sk6812grbw_pixel) {
.w = leds_limit_uint8(limit, index, color.white),
.b = leds_limit_uint8(limit, index, color.b),
.r = leds_limit_uint8(limit, index, color.r),
.g = leds_limit_uint8(limit, index, color.g),
};
}

extern struct leds_protocol_type leds_protocol_sk6812grbw;

#if CONFIG_LEDS_I2S_ENABLED
Expand Down
3 changes: 2 additions & 1 deletion components/leds/protocols/sk6812grbw_i2s.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "sk6812grbw.h"
#include "../leds.h"
#include "../pixel.h"
#include "../interfaces/i2s.h"

#include <logging.h>
Expand Down Expand Up @@ -40,7 +41,7 @@

void leds_protocol_sk6812grbw_i2s_out(uint16_t buf[8], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit)
{
union sk6812grbw_pixel pixel = sk6812grbw_pixel(pixels[index], index, limit);
union leds_pixel_grbw pixel = leds_pixel_grbw(pixels[index], index, limit);

// 16-bit little-endian
buf[0] = sk6812_i2s_lut[(pixel.grbw >> 28) & 0xf];
Expand Down
3 changes: 2 additions & 1 deletion components/leds/protocols/sk6812grbw_uart.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "sk6812grbw.h"
#include "../leds.h"
#include "../pixel.h"
#include "../interfaces/uart.h"

#include <logging.h>
Expand Down Expand Up @@ -68,7 +69,7 @@

void leds_protocol_sk6812grbw_uart_out(uint16_t buf[8], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit)
{
union sk6812grbw_pixel pixel = sk6812grbw_pixel(pixels[index], index, limit);
union leds_pixel_grbw pixel = leds_pixel_grbw(pixels[index], index, limit);

// 16-bit little-endian
buf[0] = sk6812_lut[(pixel.grbw >> 28) & 0xf];
Expand Down
18 changes: 0 additions & 18 deletions components/leds/protocols/sm16703.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,6 @@
#include <leds.h>
#include "../protocol.h"

union sm16703_pixel {
struct {
uint8_t b, g, r;
};

// aligned with 0xXXRRGGBB on little-endian architectures
uint32_t _rgb;
};

static inline union sm16703_pixel sm16703_pixel(struct leds_color color, unsigned index, const struct leds_limit *limit)
{
return (union sm16703_pixel) {
.b = leds_limit_uint8(limit, index, color.b),
.g = leds_limit_uint8(limit, index, color.g),
.r = leds_limit_uint8(limit, index, color.r),
};
}

extern struct leds_protocol_type leds_protocol_sm16703;

#if CONFIG_LEDS_I2S_ENABLED
Expand Down
3 changes: 2 additions & 1 deletion components/leds/protocols/sm16703_i2s.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "sm16703.h"
#include "../leds.h"
#include "../pixel.h"
#include "../interfaces/i2s.h"

#include <logging.h>
Expand Down Expand Up @@ -38,7 +39,7 @@

void leds_protocol_sm16703_i2s_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit)
{
union sm16703_pixel pixel = sm16703_pixel(pixels[index], index, limit);
union leds_pixel_rgb pixel = leds_pixel_rgb(pixels[index], index, limit);

// 16-bit little-endian
buf[0] = sm16703_lut[(pixel._rgb >> 20) & 0xf];
Expand Down
15 changes: 12 additions & 3 deletions components/leds/protocols/ws2811.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,23 @@
#include "../interfaces/i2s.h"
#include "../interfaces/uart.h"

struct leds_protocol_type leds_protocol_ws2811 = {
struct leds_protocol_type leds_protocol_ws2811_rgb = {
#if CONFIG_LEDS_I2S_ENABLED
.i2s_interface_mode = LEDS_INTERFACE_I2S_MODE_24BIT_1U250_4X4_80UL,
.i2s_interface_func = LEDS_INTERFACE_I2S_FUNC(i2s_mode_24bit_4x4, leds_protocol_ws2811_i2s_out),
.i2s_interface_func = LEDS_INTERFACE_I2S_FUNC(i2s_mode_24bit_4x4, leds_protocol_ws2811_i2s_rgb_out),
#endif
#if CONFIG_LEDS_UART_ENABLED
.uart_interface_mode = LEDS_INTERFACE_UART_MODE_24B2I8_0U25_50U,
.uart_interface_func = LEDS_INTERFACE_UART_FUNC(uart_mode_24B2I8, leds_protocol_ws2811_uart_out),
.uart_interface_func = LEDS_INTERFACE_UART_FUNC(uart_mode_24B2I8, leds_protocol_ws2811_uart_rgb_out),
#endif
.parameter_type = LEDS_PARAMETER_NONE,
.power_mode = LEDS_POWER_RGB,
};

struct leds_protocol_type leds_protocol_ws2811_grb = {
#if CONFIG_LEDS_I2S_ENABLED
.i2s_interface_mode = LEDS_INTERFACE_I2S_MODE_24BIT_1U250_4X4_80UL,
.i2s_interface_func = LEDS_INTERFACE_I2S_FUNC(i2s_mode_24bit_4x4, leds_protocol_ws2811_i2s_grb_out),
#endif
.parameter_type = LEDS_PARAMETER_NONE,
.power_mode = LEDS_POWER_RGB,
Expand Down
26 changes: 5 additions & 21 deletions components/leds/protocols/ws2811.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,18 @@
#include <leds.h>
#include "../protocol.h"

union ws2811_pixel {
struct {
uint8_t b, g, r;
};

// aligned with 0xXXRRGGBB on little-endian architectures
uint32_t _rgb;
};

static inline union ws2811_pixel ws2811_pixel(struct leds_color color, unsigned index, const struct leds_limit *limit)
{
return (union ws2811_pixel) {
.b = leds_limit_uint8(limit, index, color.b),
.g = leds_limit_uint8(limit, index, color.g),
.r = leds_limit_uint8(limit, index, color.r),
};
}

extern struct leds_protocol_type leds_protocol_ws2811;
extern struct leds_protocol_type leds_protocol_ws2811_rgb;
extern struct leds_protocol_type leds_protocol_ws2811_grb;

#if CONFIG_LEDS_I2S_ENABLED
#include "../interfaces/i2s.h"

void leds_protocol_ws2811_i2s_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit);
void leds_protocol_ws2811_i2s_rgb_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit);
void leds_protocol_ws2811_i2s_grb_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit);
#endif

#if CONFIG_LEDS_UART_ENABLED
#include "../interfaces/uart.h"

void leds_protocol_ws2811_uart_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit);
void leds_protocol_ws2811_uart_rgb_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit);
#endif
18 changes: 16 additions & 2 deletions components/leds/protocols/ws2811_i2s.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "ws2811.h"
#include "../leds.h"
#include "../pixel.h"
#include "../interfaces/i2s.h"

#include <logging.h>
Expand Down Expand Up @@ -36,9 +37,9 @@
[0b1111] = WS2811_LUT(0b1111),
};

void leds_protocol_ws2811_i2s_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit)
void leds_protocol_ws2811_i2s_rgb_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit)
{
union ws2811_pixel pixel = ws2811_pixel(pixels[index], index, limit);
union leds_pixel_rgb pixel = leds_pixel_rgb(pixels[index], index, limit);

// 16-bit little-endian
buf[0] = ws2811_lut[(pixel._rgb >> 20) & 0xf];
Expand All @@ -49,4 +50,17 @@
buf[5] = ws2811_lut[(pixel._rgb >> 0) & 0xf];
}

void leds_protocol_ws2811_i2s_grb_out(uint16_t buf[6], const struct leds_color *pixels, unsigned index, const struct leds_limit *limit)
{
union leds_pixel_grb pixel = leds_pixel_grb(pixels[index], index, limit);

// 16-bit little-endian
buf[0] = ws2811_lut[(pixel._grb >> 20) & 0xf];
buf[1] = ws2811_lut[(pixel._grb >> 16) & 0xf];
buf[2] = ws2811_lut[(pixel._grb >> 12) & 0xf];
buf[3] = ws2811_lut[(pixel._grb >> 8) & 0xf];
buf[4] = ws2811_lut[(pixel._grb >> 4) & 0xf];
buf[5] = ws2811_lut[(pixel._grb >> 0) & 0xf];
}

#endif
Loading
Loading