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
158 changes: 92 additions & 66 deletions components/leds/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,65 +26,69 @@ unsigned leds_format_count(size_t len, enum leds_format format, unsigned group)
case LEDS_FORMAT_RGBWXI:
return len / (4 + group) * group;

case LEDS_FORMAT_RGBXXI:
return (len - 3 * group) * group;

default:
LOG_FATAL("invalid format=%d", format);
}
}

static inline void set_leds_pixels(struct leds *leds, unsigned i, struct leds_format_params params, struct leds_color color)
{
for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.index + i * params.segment + j] = color;
}
}

void leds_set_format_rgb(struct leds *leds, const uint8_t *data, size_t len, struct leds_format_params params)
{
uint8_t parameter = leds_parameter_default(leds);

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

for (unsigned i = 0; i < params.count && len >= (i + 1) * 3; i++) {
for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + i * params.segment + j] = (struct leds_color) {
.r = data[i * 3 + 0],
.g = data[i * 3 + 1],
.b = data[i * 3 + 2],
set_leds_pixels(leds, i, params, (struct leds_color) {
.r = data[i * 3 + 0],
.g = data[i * 3 + 1],
.b = data[i * 3 + 2],

.parameter = parameter,
};
}
.parameter = parameter,
});
}
}

void leds_set_format_bgr(struct leds *leds, const uint8_t *data, size_t len, struct leds_format_params params)
{
uint8_t parameter = leds_parameter_default(leds);

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

for (unsigned i = 0; i < params.count && len >= (i + 1) * 3; i++) {
for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + i * params.segment + j] = (struct leds_color) {
.b = data[i * 3 + 0],
.g = data[i * 3 + 1],
.r = data[i * 3 + 2],
set_leds_pixels(leds, i, params, (struct leds_color) {
.b = data[i * 3 + 0],
.g = data[i * 3 + 1],
.r = data[i * 3 + 2],

.parameter = parameter,
};
}
.parameter = parameter,
});
}
}

void leds_set_format_grb(struct leds *leds, const uint8_t *data, size_t len, struct leds_format_params params)
{
uint8_t parameter = leds_parameter_default(leds);

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

for (unsigned i = 0; i < params.count && len >= (i + 1) * 3; i++) {
for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + i * params.segment + j] = (struct leds_color) {
.g = data[i * 3 + 0],
.r = data[i * 3 + 1],
.b = data[i * 3 + 2],
set_leds_pixels(leds, i, params, (struct leds_color) {
.g = data[i * 3 + 0],
.r = data[i * 3 + 1],
.b = data[i * 3 + 2],

.parameter = parameter,
};
}
.parameter = parameter,
});
}
}

Expand All @@ -93,18 +97,16 @@ void leds_set_format_rgba(struct leds *leds, const uint8_t *data, size_t len, st
enum leds_parameter_type parameter = leds_parameter_type(leds);
uint8_t parameter_default = leds_parameter_default(leds);

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

for (unsigned i = 0; i < params.count && len >= (i + 1) * 4; i++) {
for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + i * params.segment + j] = (struct leds_color) {
.r = data[i * 4 + 0],
.g = data[i * 4 + 1],
.b = data[i * 4 + 2],
set_leds_pixels(leds, i, params, (struct leds_color) {
.r = data[i * 4 + 0],
.g = data[i * 4 + 1],
.b = data[i * 4 + 2],

.dimmer = (parameter == LEDS_PARAMETER_DIMMER) ? data[i * 4 + 3] : parameter_default,
};
}
.dimmer = (parameter == LEDS_PARAMETER_DIMMER) ? data[i * 4 + 3] : parameter_default,
});
}
}

Expand All @@ -113,18 +115,16 @@ void leds_set_format_rgbw(struct leds *leds, const uint8_t *data, size_t len, st
enum leds_parameter_type parameter = leds_parameter_type(leds);
uint8_t parameter_default = leds_parameter_default(leds);

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

for (unsigned i = 0; i < params.count && len >= (i + 1) * 4; i++) {
for (unsigned j = 0; j < params.segment; j++) {
leds->pixels[params.offset + i * params.segment + j] = (struct leds_color) {
.r = data[i * 4 + 0],
.g = data[i * 4 + 1],
.b = data[i * 4 + 2],
set_leds_pixels(leds, i, params, (struct leds_color) {
.r = data[i * 4 + 0],
.g = data[i * 4 + 1],
.b = data[i * 4 + 2],

.white = (parameter == LEDS_PARAMETER_WHITE) ? data[i * 4 + 3] : parameter_default,
};
}
.white = (parameter == LEDS_PARAMETER_WHITE) ? data[i * 4 + 3] : parameter_default,
});
}
}

Expand All @@ -133,7 +133,7 @@ void leds_set_format_rgbxi(struct leds *leds, const uint8_t *data, size_t len, s
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);
LOG_DEBUG("len=%u index=%u count=%u segment=%u group=%u", len, params.index, params.count, params.segment, params.group);

size_t off = 0;

Expand All @@ -151,9 +151,7 @@ void leds_set_format_rgbxi(struct leds *leds, const uint8_t *data, size_t len, s
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;
}
set_leds_pixels(leds, (g * params.group + i), params, pixel_color);
}
}
}
Expand All @@ -163,7 +161,7 @@ void leds_set_format_bgrxi(struct leds *leds, const uint8_t *data, size_t len, s
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);
LOG_DEBUG("len=%u index=%u count=%u segment=%u group=%u", len, params.index, params.count, params.segment, params.group);

size_t off = 0;

Expand All @@ -181,9 +179,7 @@ void leds_set_format_bgrxi(struct leds *leds, const uint8_t *data, size_t len, s
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;
}
set_leds_pixels(leds, (g * params.group + i), params, pixel_color);
}
}
}
Expand All @@ -193,7 +189,7 @@ void leds_set_format_grbxi(struct leds *leds, const uint8_t *data, size_t len, s
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);
LOG_DEBUG("len=%u index=%u count=%u segment=%u group=%u", len, params.index, params.count, params.segment, params.group);

size_t off = 0;

Expand All @@ -211,9 +207,7 @@ void leds_set_format_grbxi(struct leds *leds, const uint8_t *data, size_t len, s
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;
}
set_leds_pixels(leds, (g * params.group + i), params, pixel_color);
}
}
}
Expand All @@ -222,7 +216,7 @@ void leds_set_format_rgbwxi(struct leds *leds, const uint8_t *data, size_t len,
{
enum leds_parameter_type parameter_type = leds_parameter_type(leds);

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

size_t off = 0;

Expand All @@ -240,9 +234,33 @@ void leds_set_format_rgbwxi(struct leds *leds, const uint8_t *data, size_t len,
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;
}
set_leds_pixels(leds, (g * params.group + i), params, pixel_color);
}
}
}

void leds_set_format_rgbxxi(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 index=%u count=%u segment=%u group=%u offset=%u", len, params.index, params.count, params.segment, params.group, params.offset);

for (unsigned i = 0; i * params.group < params.count && 3 * params.group + params.offset + i < len; i++) {
uint8_t intensity = data[3 * params.group + params.offset + i];

for (unsigned j = 0; j < params.group && i * params.group + j < params.count; j++) {
struct leds_color pixel_color = {
.r = data[j * 3 + 0],
.g = data[j * 3 + 1],
.b = data[j * 3 + 2],

.parameter = parameter_default,
};

pixel_color = leds_color_intensity(pixel_color, parameter_type, intensity);

set_leds_pixels(leds, i * params.group + j, params, pixel_color);
}
}
}
Expand All @@ -261,12 +279,16 @@ int leds_set_format(struct leds *leds, enum leds_format format, const void *data
params.group = 1;
}

if (params.offset > leds->options.count) {
LOG_DEBUG("offset=%u is over options.count=%u", params.offset, leds->options.count);
if (params.offset > 0) {
params.offset -= 1;
}

if (params.index > leds->options.count) {
LOG_DEBUG("index=%u is over options.count=%u", params.index, leds->options.count);
params.count = 0;
} else if (params.offset + (params.count * params.segment) > leds->options.count) {
LOG_DEBUG("offset=%u + count=%u * segment=%u is over options.count=%u", params.offset, params.count, params.segment, leds->options.count);
params.count = (leds->options.count - params.offset) / params.segment;
} else if (params.index + (params.count * params.segment) > leds->options.count) {
LOG_DEBUG("index=%u + count=%u * segment=%u is over options.count=%u", params.index, params.count, params.segment, leds->options.count);
params.count = (leds->options.count - params.index) / params.segment;
}

leds->pixels_limit_dirty = true;
Expand Down Expand Up @@ -308,6 +330,10 @@ int leds_set_format(struct leds *leds, enum leds_format format, const void *data
leds_set_format_rgbwxi(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBXXI:
leds_set_format_rgbxxi(leds, data, len, params);
return 0;

default:
LOG_ERROR("unknown format=%#x", format);
return -1;
Expand Down
21 changes: 13 additions & 8 deletions components/leds/include/leds.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,12 @@ enum leds_format {
LEDS_FORMAT_RGBA,
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
LEDS_FORMAT_RGBXI, // (<RGB> + GROUP * <I>)...
LEDS_FORMAT_BGRXI, // (<BGR> + GROUP * <I>)...
LEDS_FORMAT_GRBXI, // (<GRB> + GROUP * <I>)...
LEDS_FORMAT_RGBWXI, // (<RGBW> + GROUP * <I>)...

LEDS_FORMAT_RGBXXI, // GROUP * <RGB> + <I>[OFFSET]...
};

/*
Expand All @@ -127,17 +129,20 @@ enum leds_format {
unsigned leds_format_count(size_t len, enum leds_format format, unsigned group);

struct leds_format_params {
/* Limit number of LED (segments) to read */
unsigned count;

/* Set LEDs starting at offset */
unsigned offset;
unsigned index;

/* Limit number of LED (segments) to set */
unsigned count;

/* Set segments of multiple consecutive LEDs per channel */
unsigned segment;

/* Set color for group of LEDs */
unsigned group;

/* Starting offset within group, starting at 1 */
unsigned offset;
};

/*
Expand Down
3 changes: 2 additions & 1 deletion main/leds_artnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,10 @@ static int leds_artnet_set(struct leds_state *state, unsigned index, struct artn

struct leds_format_params params = {
.count = count,
.offset = index * count * segment,
.index = index * count * segment,
.segment = segment,
.group = config->artnet_leds_group,
.offset = config->artnet_leds_offset,
};

if ((err = leds_set_format(state->leds, config->artnet_leds_format, data, len, params))) {
Expand Down
1 change: 1 addition & 0 deletions main/leds_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const struct config_enum leds_format_enum[] = {
{ "BGRxI", .value = LEDS_FORMAT_BGRXI },
{ "GRBxI", .value = LEDS_FORMAT_GRBXI },
{ "RGBWxI", .value = LEDS_FORMAT_RGBWXI },
{ "RGBxxI", .value = LEDS_FORMAT_RGBXXI },
{}
};

Expand Down
4 changes: 3 additions & 1 deletion main/leds_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,16 @@ struct leds_config {
int artnet_leds_format;
uint16_t artnet_leds_segment;
uint16_t artnet_leds_group;
uint16_t artnet_leds_offset;

bool sequence_enabled;
int sequence_format;
uint16_t sequence_channel_start;
uint16_t sequence_channel_count;
uint16_t sequence_leds_count;
uint16_t sequence_leds_offset;
uint16_t sequence_leds_group;
uint16_t sequence_leds_segment;
uint16_t sequence_leds_offset;
};

extern struct leds_config leds_configs[LEDS_COUNT];
Expand Down
Loading
Loading