diff --git a/components/leds/format.c b/components/leds/format.c index fef639d9..1f1a5c28 100644 --- a/components/leds/format.c +++ b/components/leds/format.c @@ -26,27 +26,35 @@ 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, + }); } } @@ -54,18 +62,16 @@ void leds_set_format_bgr(struct leds *leds, const uint8_t *data, size_t len, str { 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, + }); } } @@ -73,18 +79,16 @@ void leds_set_format_grb(struct leds *leds, const uint8_t *data, size_t len, str { 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, + }); } } @@ -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, + }); } } @@ -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, + }); } } @@ -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; @@ -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); } } } @@ -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; @@ -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); } } } @@ -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; @@ -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); } } } @@ -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; @@ -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); } } } @@ -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; @@ -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; diff --git a/components/leds/include/leds.h b/components/leds/include/leds.h index 079046d9..51436bc1 100644 --- a/components/leds/include/leds.h +++ b/components/leds/include/leds.h @@ -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, // ( + GROUP * )... + LEDS_FORMAT_BGRXI, // ( + GROUP * )... + LEDS_FORMAT_GRBXI, // ( + GROUP * )... + LEDS_FORMAT_RGBWXI, // ( + GROUP * )... + + LEDS_FORMAT_RGBXXI, // GROUP * + [OFFSET]... }; /* @@ -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; }; /* diff --git a/main/leds_artnet.c b/main/leds_artnet.c index cbeae749..7df50c7c 100644 --- a/main/leds_artnet.c +++ b/main/leds_artnet.c @@ -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))) { diff --git a/main/leds_config.c b/main/leds_config.c index 848ea3fe..02353d47 100644 --- a/main/leds_config.c +++ b/main/leds_config.c @@ -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 }, {} }; diff --git a/main/leds_config.h b/main/leds_config.h index 945ea423..869ee1dc 100644 --- a/main/leds_config.h +++ b/main/leds_config.h @@ -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]; diff --git a/main/leds_configtab.i b/main/leds_configtab.i index 8235cc4d..400091d8 100644 --- a/main/leds_configtab.i +++ b/main/leds_configtab.i @@ -219,6 +219,10 @@ const struct configtab LEDS_CONFIGTAB[] = { .validate_func = validate_artnet_leds_group, .ctx = &LEDS_CONFIG, }, + { CONFIG_TYPE_UINT16, "artnet_leds_offset", + .description = "Offset to first LED inside Art-Net Group data. Default 0 -> all, starting at 1", + .uint16_type = { .value = &LEDS_CONFIG.artnet_leds_offset }, + }, { CONFIG_TYPE_BOOL, "sequence_enabled", .description = "Output LED sequence frames, requires leds-sequence config", @@ -240,14 +244,18 @@ const struct configtab LEDS_CONFIGTAB[] = { .description = "Limit number of LEDs to control. Default 0 -> all LEDs", .uint16_type = { .value = &LEDS_CONFIG.sequence_leds_count }, }, - { CONFIG_TYPE_UINT16, "sequence_leds_offset", - .description = "Set first LED to control. Default 0 -> all LEDs", - .uint16_type = { .value = &LEDS_CONFIG.sequence_leds_offset }, - }, { CONFIG_TYPE_UINT16, "sequence_leds_segment", .description = "Control multiple consecutive LEDs per sequence channel. Default 0 -> control individual LEDs", .uint16_type = { .value = &LEDS_CONFIG.sequence_leds_segment }, }, + { CONFIG_TYPE_UINT16, "sequence_leds_group", + .description = "Group multiple consecutive LEDs for common per-format parameters.", + .uint16_type = { .value = &LEDS_CONFIG.sequence_leds_group }, + }, + { CONFIG_TYPE_UINT16, "sequence_leds_offset", + .description = "Offset to first LED inside per-format Group data.", + .uint16_type = { .value = &LEDS_CONFIG.sequence_leds_offset }, + }, {} }; diff --git a/main/leds_sequence.c b/main/leds_sequence.c index 65b91750..90e1de12 100644 --- a/main/leds_sequence.c +++ b/main/leds_sequence.c @@ -220,8 +220,9 @@ static int set_leds_sequence(struct leds_state *state, const struct fseq_frame * const struct leds_config *config = state->config; struct leds_format_params params = { .count = config->sequence_leds_count, - .offset = config->sequence_leds_offset, .segment = config->sequence_leds_segment, + .group = config->sequence_leds_group, + .offset = config->sequence_leds_offset, }; const uint8_t *ptr = frame->buf; size_t len = frame->size;