Skip to content

Commit

Permalink
Merge pull request #70 from qmsk/artnet-leds-groups
Browse files Browse the repository at this point in the history
Art-NET RGBW+I LED groups
  • Loading branch information
SpComb authored Feb 8, 2024
2 parents acf0654 + 16c68ff commit 19a4ed8
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 118 deletions.
25 changes: 25 additions & 0 deletions components/leds/color.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,28 @@ unsigned leds_colors_active (const struct leds_color *pixels, unsigned count, en

return active;
}

struct leds_color leds_color_intensity (struct leds_color color, enum leds_parameter_type parameter_type, uint8_t intensity)
{
switch (parameter_type) {
case LEDS_PARAMETER_DIMMER:
color.dimmer = intensity;
break;

case LEDS_PARAMETER_NONE:
color.r = color.r * intensity / 255;
color.g = color.g * intensity / 255;
color.b = color.b * intensity / 255;
color.parameter = 0;
break;

case LEDS_PARAMETER_WHITE:
color.r = color.r * intensity / 255;
color.g = color.g * intensity / 255;
color.b = color.b * intensity / 255;
color.w = color.w * intensity / 255;
break;
}

return color;
}
134 changes: 131 additions & 3 deletions components/leds/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@

#include <logging.h>

unsigned leds_format_count(enum leds_format format, size_t len)
unsigned leds_format_count(size_t len, enum leds_format format, unsigned group)
{
if (!group) {
group = 1;
}

switch (format) {
case LEDS_FORMAT_RGB:
case LEDS_FORMAT_BGR:
case LEDS_FORMAT_GRB:
return len / 3;
return len / (3 * group) * group;

case LEDS_FORMAT_RGBA:
case LEDS_FORMAT_RGBW:
return len / 4;
return len / (4 * group) * group;

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

case LEDS_FORMAT_RGBWXI:
return len / (4 + group) * group;

default:
LOG_FATAL("invalid format=%d", format);
Expand Down Expand Up @@ -115,3 +125,121 @@ void leds_set_format_rgbw(struct leds *leds, const uint8_t *data, size_t len, st
}
}
}

void leds_set_format_rgbxi(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.r = data[off++];
group_color.g = 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);

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 + 4 + params.group; g++) {
struct leds_color group_color = {};

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

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

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;
}
}
}
}

int leds_set_format(struct leds *leds, enum leds_format format, const void *data, size_t len, struct leds_format_params params)
{
if (params.count == 0) {
params.count = leds->options.count;
}

if (params.segment == 0) {
params.segment = 1;
}

if (params.group == 0) {
params.group = 1;
}

if (params.offset > leds->options.count) {
LOG_DEBUG("offset=%u is over options.count=%u", params.offset, 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;
}

leds->pixels_limit_dirty = true;

switch(format) {
case LEDS_FORMAT_RGB:
leds_set_format_rgb(leds, data, len, params);
return 0;

case LEDS_FORMAT_BGR:
leds_set_format_bgr(leds, data, len, params);
return 0;

case LEDS_FORMAT_GRB:
leds_set_format_grb(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBA:
leds_set_format_rgba(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBW:
leds_set_format_rgbw(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBXI:
leds_set_format_rgbxi(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBWXI:
leds_set_format_rgbwxi(leds, data, len, params);
return 0;

default:
LOG_ERROR("unknown format=%#x", format);
return -1;
}
}
14 changes: 12 additions & 2 deletions components/leds/include/leds.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,17 @@ enum leds_format {
LEDS_FORMAT_GRB,
LEDS_FORMAT_RGBA,
LEDS_FORMAT_RGBW,

LEDS_FORMAT_RGBXI, // grouped RGB + intensity
LEDS_FORMAT_RGBWXI, // grouped RGBW + intensity
};

/*
* Return count of LEDs that fit into len bytes using the given format.
* Return count of pixels that fit into len bytes using the given format.
*
* This does not consider segments.
*/
unsigned leds_format_count(enum leds_format format, size_t len);
unsigned leds_format_count(size_t len, enum leds_format format, unsigned group);

struct leds_format_params {
/* Limit number of LED (segments) to read */
Expand All @@ -112,6 +117,9 @@ struct leds_format_params {

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

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

/*
Expand Down Expand Up @@ -316,10 +324,12 @@ struct leds_color {
uint8_t parameter;
uint8_t dimmer; // 0-255
uint8_t white; // 0-255
uint8_t w; // 0-255
};
};

bool leds_color_active (struct leds_color color, enum leds_parameter_type parameter_type);
struct leds_color leds_color_intensity (struct leds_color color, enum leds_parameter_type parameter_type, uint8_t intensity);

enum leds_test_mode {
TEST_MODE_NONE = 0,
Expand Down
47 changes: 0 additions & 47 deletions components/leds/leds.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,53 +142,6 @@ int leds_set_all(struct leds *leds, struct leds_color color)
return 0;
}

int leds_set_format(struct leds *leds, enum leds_format format, const void *data, size_t len, struct leds_format_params params)
{
if (params.count == 0) {
params.count = leds->options.count;
}

if (params.segment == 0) {
params.segment = 1;
}

if (params.offset > leds->options.count) {
LOG_DEBUG("offset=%u is over options.count=%u", params.offset, 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;
}

leds->pixels_limit_dirty = true;

switch(format) {
case LEDS_FORMAT_RGB:
leds_set_format_rgb(leds, data, len, params);
return 0;

case LEDS_FORMAT_BGR:
leds_set_format_bgr(leds, data, len, params);
return 0;

case LEDS_FORMAT_GRB:
leds_set_format_grb(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBA:
leds_set_format_rgba(leds, data, len, params);
return 0;

case LEDS_FORMAT_RGBW:
leds_set_format_rgbw(leds, data, len, params);
return 0;

default:
LOG_ERROR("unknown format=%#x", format);
return -1;
}
}

unsigned leds_count_active(struct leds *leds)
{
return leds_colors_active(leds->pixels, leds->options.count, leds->protocol_type->parameter_type);
Expand Down
Loading

0 comments on commit 19a4ed8

Please sign in to comment.