From bb7fc5497f7b833887ee2493cbdb8235d2bc9425 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 25 Oct 2025 16:36:30 +0300 Subject: [PATCH 1/6] leds: split LEDS_INTERFACE_I2S0/1 --- components/leds/i2s.c | 18 ++++++++++++++++++ components/leds/include/leds.h | 19 ++++++++++++++++--- components/leds/interface.c | 7 ++++++- components/leds/leds.c | 9 +++++++-- components/leds/protocol.c | 8 +++++++- 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/components/leds/i2s.c b/components/leds/i2s.c index a8cc04b6..55f5f694 100644 --- a/components/leds/i2s.c +++ b/components/leds/i2s.c @@ -4,6 +4,24 @@ #include #if CONFIG_LEDS_I2S_ENABLED + i2s_port_t leds_interface_i2s_port(enum leds_interface interface) + { + switch(interface) { + #if LEDS_I2S_INTERFACE_COUNT > 0 + case LEDS_INTERFACE_I2S0: + return I2S_PORT_0; + #endif + + #if LEDS_I2S_INTERFACE_COUNT > 1 + case LEDS_INTERFACE_I2S1: + return I2S_PORT_1; + #endif + + default: + LOG_FATAL("%u", interface); + } + } + size_t leds_i2s_serial_buffer_size(enum leds_protocol protocol, unsigned led_count) { const struct leds_protocol_type *protocol_type = leds_protocol_type(protocol); diff --git a/components/leds/include/leds.h b/components/leds/include/leds.h index 316cde24..079046d9 100644 --- a/components/leds/include/leds.h +++ b/components/leds/include/leds.h @@ -8,11 +8,14 @@ #if CONFIG_LEDS_I2S_ENABLED # include +# define LEDS_I2S_INTERFACE_COUNT I2S_PORT_MAX # define LEDS_I2S_GPIO_PINS_ENABLED I2S_OUT_GPIO_PINS_SUPPORTED # define LEDS_I2S_GPIO_PINS_SIZE I2S_OUT_GPIO_PINS_MAX # define LEDS_I2S_PARALLEL_ENABLED I2S_OUT_PARALLEL_SUPPORTED # define LEDS_I2S_PARALLEL_MAX I2S_OUT_PARALLEL_DATA_BITS_MAX # define LEDS_I2S_REPEAT_MAX 64 + +# define LEDS_INTERFACE_I2S(i) (LEDS_INTERFACE_I2S0 + (i)) #endif #if CONFIG_LEDS_SPI_ENABLED && CONFIG_IDF_TARGET_ESP8266 @@ -47,7 +50,7 @@ enum leds_interface { * - LEDS_PROTOCOL_APA102 * - LEDS_PROTOCOL_P9813 */ - LEDS_INTERFACE_SPI = 1, + LEDS_INTERFACE_SPI, #endif #if CONFIG_LEDS_UART_ENABLED @@ -56,7 +59,7 @@ enum leds_interface { * - LEDS_PROTOCOL_SK6812_GRBW * - LEDS_PROTOCOL_WS2811 */ - LEDS_INTERFACE_UART = 2, + LEDS_INTERFACE_UART, #endif #if CONFIG_LEDS_I2S_ENABLED @@ -66,7 +69,12 @@ enum leds_interface { * - LEDS_PROTOCOL_SK6812_GRBW * - LEDS_PROTOCOL_SK9822 */ - LEDS_INTERFACE_I2S = 3, +#if LEDS_I2S_INTERFACE_COUNT > 0 + LEDS_INTERFACE_I2S0, +#endif +#if LEDS_I2S_INTERFACE_COUNT > 1 + LEDS_INTERFACE_I2S1, +#endif #endif LEDS_INTERFACE_COUNT @@ -244,6 +252,11 @@ enum leds_interface leds_interface_for_protocol(enum leds_protocol protocol); unsigned repeat; // LEDS_I2S_REPEAT_MAX }; + /* + * Return port for interface + */ + i2s_port_t leds_interface_i2s_port(enum leds_interface interface); + /* * Returns total TX buffer size, align required for protocol with `led_count` LEDs on one serial pin. * diff --git a/components/leds/interface.c b/components/leds/interface.c index f6902176..b38847d9 100644 --- a/components/leds/interface.c +++ b/components/leds/interface.c @@ -42,7 +42,12 @@ int leds_interface_init(union leds_interface_state *interface, const struct leds #endif #if CONFIG_LEDS_I2S_ENABLED - case LEDS_INTERFACE_I2S: + # if LEDS_I2S_INTERFACE_COUNT > 0 + case LEDS_INTERFACE_I2S0: + # endif + # if LEDS_I2S_INTERFACE_COUNT > 1 + case LEDS_INTERFACE_I2S1: + # endif if (!protocol_type->i2s_interface_mode) { LOG_ERROR("unsupported interface=I2S for protocol=%d", options->protocol); return -1; diff --git a/components/leds/leds.c b/components/leds/leds.c index b41f2acb..353245a0 100644 --- a/components/leds/leds.c +++ b/components/leds/leds.c @@ -178,8 +178,13 @@ int leds_tx(struct leds *leds) #endif #if CONFIG_LEDS_I2S_ENABLED - case LEDS_INTERFACE_I2S: - return leds_interface_i2s_tx(&leds->interface.i2s, leds->pixels, leds->options.count, &leds->limit); + # if LEDS_I2S_INTERFACE_COUNT > 0 + case LEDS_INTERFACE_I2S0: + # endif + # if LEDS_I2S_INTERFACE_COUNT > 1 + case LEDS_INTERFACE_I2S1: + # endif + return leds_interface_i2s_tx(&leds->interface.i2s, leds->pixels, leds->options.count, &leds->limit); #endif default: diff --git a/components/leds/protocol.c b/components/leds/protocol.c index d06d6eb6..27d21cf1 100644 --- a/components/leds/protocol.c +++ b/components/leds/protocol.c @@ -37,7 +37,13 @@ enum leds_interface leds_interface_for_protocol(enum leds_protocol protocol) #if CONFIG_LEDS_I2S_ENABLED if (protocol_type->i2s_interface_mode) { - return LEDS_INTERFACE_I2S; +# if LEDS_I2S_INTERFACE_COUNT > 1 + return LEDS_INTERFACE_I2S1; +# elif LEDS_I2S_INTERFACE_COUNT > 0 + return LEDS_INTERFACE_I2S0; +# else + return LEDS_INTERFACE_NONE; +# endif } #endif From 9dfbfef9ab5cdcb375996f721f3b6687bfd15b64 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 25 Oct 2025 16:37:14 +0300 Subject: [PATCH 2/6] main: only check_leds_l2s() on ESP8266 --- main/leds.c | 4 +++- main/leds_i2s.c | 6 +++--- main/leds_state.h | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/main/leds.c b/main/leds.c index d67e2839..e1976c99 100644 --- a/main/leds.c +++ b/main/leds.c @@ -155,8 +155,10 @@ int check_leds_interface(struct leds_state *state) } switch (leds_interface(state->leds)) { - case LEDS_INTERFACE_I2S: + #if CONFIG_IDF_TARGET_ESP8266 + case LEDS_INTERFACE_I2S0: return check_leds_i2s(state); + #endif default: return 0; diff --git a/main/leds_i2s.c b/main/leds_i2s.c index 23dc6448..4981108d 100644 --- a/main/leds_i2s.c +++ b/main/leds_i2s.c @@ -231,9 +231,9 @@ return 0; } +# if CONFIG_IDF_TARGET_ESP8266 int check_leds_i2s(struct leds_state *state) { - #if CONFIG_IDF_TARGET_ESP8266 const struct leds_options *options = leds_options(state->leds); if (is_console_running()) { @@ -242,8 +242,8 @@ return 1; } } - #endif - + return 0; } +# endif #endif diff --git a/main/leds_state.h b/main/leds_state.h index aa05a669..60b97052 100644 --- a/main/leds_state.h +++ b/main/leds_state.h @@ -45,7 +45,10 @@ extern struct leds_state leds_states[LEDS_COUNT]; #if CONFIG_LEDS_I2S_ENABLED int init_leds_i2s(); + +# if CONFIG_IDF_TARGET_ESP8266 int check_leds_i2s(struct leds_state *state); +# endif #endif /* From b535d2cc9576b3a701dafa11d4810fe34f1dfa77 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 25 Oct 2025 16:37:48 +0300 Subject: [PATCH 3/6] leds: support separate I2S0, I2S1 interfaces --- main/config.c | 4 --- main/leds.c | 8 +++-- main/leds.h | 1 - main/leds_config.c | 18 ++++++++--- main/leds_config.h | 7 ----- main/leds_configtab.i | 4 +++ main/leds_gpio.c | 7 ++++- main/leds_i2s.c | 70 ++++++++++--------------------------------- main/leds_state.h | 2 +- 9 files changed, 45 insertions(+), 76 deletions(-) diff --git a/main/config.c b/main/config.c index 29adf73b..21eccc9c 100644 --- a/main/config.c +++ b/main/config.c @@ -86,10 +86,6 @@ const struct configmod config_modules[] = { .description = "LEDS UART interface", .table = leds_uart_configtab, }, - { "leds-i2s", - .description = "LEDS I2S interface", - .table = leds_i2s_configtab, - }, { "leds-sequence", .description = "LEDS Sequence support", .table = leds_sequence_configtab, diff --git a/main/leds.c b/main/leds.c index e1976c99..015707af 100644 --- a/main/leds.c +++ b/main/leds.c @@ -53,9 +53,11 @@ int init_leds() #endif #if CONFIG_LEDS_I2S_ENABLED - if ((err = init_leds_i2s())) { - LOG_ERROR("init_leds_i2s"); - return 0; + for (unsigned i = 0; i < LEDS_I2S_INTERFACE_COUNT; i++) { + if ((err = init_leds_i2s(i))) { + LOG_ERROR("init_leds_i2s%u", i); + return 0; + } } #endif diff --git a/main/leds.h b/main/leds.h index 4752c9ce..ccd0d607 100644 --- a/main/leds.h +++ b/main/leds.h @@ -8,7 +8,6 @@ extern const struct configtab leds_gpio_configtab[]; extern const struct configtab leds_spi_configtab[]; extern const struct configtab leds_uart_configtab[]; -extern const struct configtab leds_i2s_configtab[]; extern const struct configtab leds_sequence_configtab[]; extern const struct configtab *leds_configtabs[LEDS_COUNT]; extern const struct cmdtab leds_cmdtab; diff --git a/main/leds_config.c b/main/leds_config.c index fde5f7d6..93ffa690 100644 --- a/main/leds_config.c +++ b/main/leds_config.c @@ -18,13 +18,18 @@ struct leds_config leds_configs[LEDS_COUNT] = {}; const struct config_enum leds_interface_enum[] = { { "DEFAULT", .value = LEDS_INTERFACE_NONE }, #if CONFIG_LEDS_SPI_ENABLED - { "SPI", .value = LEDS_INTERFACE_SPI }, + { "SPI", .value = LEDS_INTERFACE_SPI }, #endif #if CONFIG_LEDS_UART_ENABLED { "UART", .value = LEDS_INTERFACE_UART }, #endif #if CONFIG_LEDS_I2S_ENABLED - { "I2S", .value = LEDS_INTERFACE_I2S }, +# if LEDS_I2S_INTERFACE_COUNT > 1 + { "I2S0", .value = LEDS_INTERFACE_I2S0 }, + { "I2S1", .value = LEDS_INTERFACE_I2S1, .alias = "I2S" }, +# elif LEDS_I2S_INTERFACE_COUNT > 0 + { "I2S0", .value = LEDS_INTERFACE_I2S0, .alias = "I2S" }, +# endif #endif {} }; @@ -287,13 +292,18 @@ int config_leds(struct leds_state *state, const struct leds_config *config) #endif #if CONFIG_LEDS_I2S_ENABLED - case LEDS_INTERFACE_I2S: + # if LEDS_I2S_INTERFACE_COUNT > 0 + case LEDS_INTERFACE_I2S0: + # endif + # if LEDS_I2S_INTERFACE_COUNT > 1 + case LEDS_INTERFACE_I2S1: + # endif if ((err = config_leds_i2s(state, config, &options.i2s))) { LOG_ERROR("leds%d: config_leds_i2s", state->index + 1); return err; } - if ((err = config_leds_gpio(state, config, LEDS_INTERFACE_I2S, &options.i2s.gpio))) { + if ((err = config_leds_gpio(state, config, options.interface, &options.i2s.gpio))) { LOG_ERROR("leds%d: config_leds_gpio", state->index + 1); return err; } diff --git a/main/leds_config.h b/main/leds_config.h index bedda6f6..7db7be79 100644 --- a/main/leds_config.h +++ b/main/leds_config.h @@ -97,13 +97,6 @@ struct leds_state *state; #define I2S_CLOCK_DEFAULT (I2S_CLOCK_1MHZ) - struct leds_i2s_config { - int port; - }; - - extern struct leds_i2s_config leds_i2s_config; - - extern const struct config_enum leds_i2s_port_enum[]; extern const struct config_enum leds_i2s_clock_enum[]; #endif diff --git a/main/leds_configtab.i b/main/leds_configtab.i index f24ef35e..767160ec 100644 --- a/main/leds_configtab.i +++ b/main/leds_configtab.i @@ -4,6 +4,10 @@ const struct configtab LEDS_CONFIGTAB[] = { .bool_type = { .value = &LEDS_CONFIG.enabled }, }, { CONFIG_TYPE_ENUM, "interface", + .description = ( + "Select phyiscal interface driver to use for output.\n" + "Multiple led instances can share the same interface with different gpio output enables, but this will limit performance.\n" + ), .enum_type = { .value = &LEDS_CONFIG.interface, .values = leds_interface_enum }, }, { CONFIG_TYPE_ENUM, "protocol", diff --git a/main/leds_gpio.c b/main/leds_gpio.c index ae6921c8..37278b9a 100644 --- a/main/leds_gpio.c +++ b/main/leds_gpio.c @@ -18,7 +18,12 @@ [LEDS_INTERFACE_UART] = { }, #endif #if CONFIG_LEDS_I2S_ENABLED - [LEDS_INTERFACE_I2S] = { }, + # if LEDS_I2S_INTERFACE_COUNT > 0 + [LEDS_INTERFACE_I2S0] = { }, + # endif + # if LEDS_I2S_INTERFACE_COUNT > 1 + [LEDS_INTERFACE_I2S1] = { }, + # endif #endif }; diff --git a/main/leds_i2s.c b/main/leds_i2s.c index 4981108d..dc6c44b2 100644 --- a/main/leds_i2s.c +++ b/main/leds_i2s.c @@ -10,39 +10,6 @@ #define LEDS_I2S_PIN_TIMEOUT portMAX_DELAY #if CONFIG_LEDS_I2S_ENABLED - - // config - struct leds_i2s_config leds_i2s_config = { - - }; - - const struct config_enum leds_i2s_port_enum[] = { - { "", .value = -1 }, - #if defined(I2S_PORT_0) - { "I2S0", .value = I2S_PORT_0 }, - #endif - #if defined(I2S_PORT_1) - { "I2S1", .value = I2S_PORT_1 }, - #endif - {}, - }; - - #if defined(I2S_PORT_1) - #define LEDS_I2S_PORT_DEFAULT_VALUE I2S_PORT_1 - #elif defined(I2S_PORT_0) - #define LEDS_I2S_PORT_DEFAULT_VALUE I2S_PORT_0 - #else - #define LEDS_I2S_PORT_DEFAULT_VALUE -1 - #endif - - const struct configtab leds_i2s_configtab[] = { - { CONFIG_TYPE_ENUM, "port", - .description = "Select host peripherial for I2S interface.", - .enum_type = { .value = &leds_i2s_config.port, .values = leds_i2s_port_enum, .default_value = LEDS_I2S_PORT_DEFAULT_VALUE }, - }, - {}, - }; - #if LEDS_I2S_PARALLEL_ENABLED unsigned config_leds_i2s_data_width(const struct leds_config *config) { @@ -64,21 +31,15 @@ #endif // state - struct i2s_out *leds_i2s_out; + struct i2s_out *leds_i2s_out[LEDS_I2S_INTERFACE_COUNT]; - int init_leds_i2s() + int init_leds_i2s(unsigned port) { - const struct leds_i2s_config *i2s_config = &leds_i2s_config; size_t buffer_size = 0, buffer_align = 0; unsigned data_repeat = 0; bool enabled = false; int err; - if (i2s_config->port < 0) { - LOG_INFO("leds: i2s disabled"); - return 0; - } - for (int i = 0; i < LEDS_COUNT; i++) { const struct leds_config *config = &leds_configs[i]; @@ -87,7 +48,7 @@ continue; } - if (config->interface != LEDS_INTERFACE_I2S) { + if (config->interface != LEDS_INTERFACE_I2S(port)) { continue; } @@ -103,23 +64,23 @@ size = leds_i2s_parallel_buffer_size(config->protocol, config->count, data_width); align = leds_i2s_parallel_buffer_align(config->protocol, data_width); - LOG_INFO("leds%d: i2s%d configured for %u parallel leds on %u pins, data buffer size=%u align=%u", i + 1, i2s_config->port, config->count, data_width, size, align); + LOG_INFO("leds%d: i2s%u configured for %u parallel leds on %u pins, data buffer size=%u align=%u", i + 1, port, config->count, data_width, size, align); } else if (data_width) { size = leds_i2s_serial_buffer_size(config->protocol, config->count); align = leds_i2s_serial_buffer_align(config->protocol); - LOG_INFO("leds%d: i2s%d configured for %u serial leds, data buffer size=%u align=%u", i + 1, i2s_config->port, config->count, size, align); + LOG_INFO("leds%d: i2s%u configured for %u serial leds, data buffer size=%u align=%u", i + 1, port, config->count, size, align); } else { size = 0; align = 0; - LOG_WARN("leds%d: i2s%d configured for %u leds without data outputs", i + 1, i2s_config->port, config->count); + LOG_WARN("leds%d: i2s%u configured for %u leds without data outputs", i + 1, port, config->count); } #else size = leds_i2s_serial_buffer_size(config->protocol, config->count); align = leds_i2s_serial_buffer_align(config->protocol); - LOG_INFO("leds%d: i2s%d configured for %u serial leds, data buffer size=%u align=%u", i + 1, i2s_config->port, config->count, size, align); + LOG_INFO("leds%d: i2s%u configured for %u serial leds, data buffer size=%u align=%u", i + 1, port, config->count, size, align); #endif if (size > buffer_size) { @@ -134,16 +95,16 @@ } if (!enabled) { - LOG_INFO("leds: i2s%d not configured", i2s_config->port); + LOG_INFO("leds: i2s%u not configured", port); return 0; } - LOG_INFO("leds: i2s port=%d -> buffer_size=%u buffer_align=%u repeat_data_count=%u", i2s_config->port, + LOG_INFO("leds: i2s%u -> buffer_size=%u buffer_align=%u repeat_data_count=%u", port, buffer_size, buffer_align, data_repeat ); - if ((err = i2s_out_new(&leds_i2s_out, i2s_config->port, buffer_size, buffer_align, data_repeat))) { - LOG_ERROR("i2s_out_new(port=%d)", i2s_config->port); + if ((err = i2s_out_new(&leds_i2s_out[port], port, buffer_size, buffer_align, data_repeat))) { + LOG_ERROR("i2s_out_new(port=%d)", port); return err; } @@ -152,14 +113,14 @@ int config_leds_i2s(struct leds_state *state, const struct leds_config *config, struct leds_interface_i2s_options *options) { - const struct leds_i2s_config *i2s_config = &leds_i2s_config; + unsigned port = leds_interface_i2s_port(config->interface); - if (!leds_i2s_out) { + if (!leds_i2s_out[port]) { LOG_ERROR("leds%d: i2s out not initialized", state->index + 1); return -1; } - options->i2s_out = leds_i2s_out; + options->i2s_out = leds_i2s_out[port]; #if CONFIG_IDF_TARGET_ESP8266 // TODO: use i2s_pin_mutex for arbitrary gpio pins with LEDS_I2S_GPIO_PINS_ENABLED? options->pin_mutex = pin_mutex[PIN_MUTEX_I2S0_DATA]; // shared with console uart0 @@ -211,8 +172,7 @@ options->repeat = config->i2s_data_copies - 1; } - LOG_INFO("leds%d: i2s port=%d: pin_mutex=%p clock_rate=%d gpio_pins_count=%u parallel=%u repeat=%u", state->index + 1, - i2s_config->port, + LOG_INFO("leds%d: i2s%d pin_mutex=%p clock_rate=%d gpio_pins_count=%u parallel=%u repeat=%u", state->index + 1, port, options->pin_mutex, options->clock_rate, #if LEDS_I2S_GPIO_PINS_ENABLED diff --git a/main/leds_state.h b/main/leds_state.h index 60b97052..67435d2b 100644 --- a/main/leds_state.h +++ b/main/leds_state.h @@ -44,7 +44,7 @@ extern struct leds_state leds_states[LEDS_COUNT]; #endif #if CONFIG_LEDS_I2S_ENABLED - int init_leds_i2s(); + int init_leds_i2s(unsigned port); # if CONFIG_IDF_TARGET_ESP8266 int check_leds_i2s(struct leds_state *state); From 903b769a43a1ffff44df44b92be6ee3723492b91 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 25 Oct 2025 16:49:28 +0300 Subject: [PATCH 4/6] leds: validate I2S1 parallel --- main/leds_config.c | 26 ++++++++++++++++++++++++++ main/leds_config.h | 1 + main/leds_configtab.i | 5 +++++ 3 files changed, 32 insertions(+) diff --git a/main/leds_config.c b/main/leds_config.c index 93ffa690..a4d1c6eb 100644 --- a/main/leds_config.c +++ b/main/leds_config.c @@ -141,6 +141,32 @@ const struct config_enum leds_parameter_enum[] = { {} }; +#if CONFIG_LEDS_I2S_ENABLED + static int validate_leds_i2s_parallel (config_invalid_handler_t *handler, const struct config_path path, void *ctx) + { + struct leds_config *config = path.tab->ctx; + unsigned data_width = config_leds_i2s_data_width(config); + + if (config->enabled && data_width > 1) { + switch (config->interface) { + #if CONFIG_IDF_TARGET_ESP32 + case LEDS_INTERFACE_I2S1: + break; // ok + #endif + + default: + handler(path, ctx, "LEDs interface %s does not support parallel output", + config_enum_to_string(leds_interface_enum, config->interface) + ); + + return 1; + } + } + + return 0; + } +#endif + static int validate_artnet_leds_group (config_invalid_handler_t *handler, const struct config_path path, void *ctx) { struct leds_config *config = path.tab->ctx; diff --git a/main/leds_config.h b/main/leds_config.h index 7db7be79..945ea423 100644 --- a/main/leds_config.h +++ b/main/leds_config.h @@ -203,5 +203,6 @@ unsigned config_leds_artnet_universe_count(const struct leds_config *config); #endif #if CONFIG_LEDS_I2S_ENABLED + unsigned config_leds_i2s_data_width(const struct leds_config *config); int config_leds_i2s(struct leds_state *state, const struct leds_config *config, struct leds_interface_i2s_options *options); #endif diff --git a/main/leds_configtab.i b/main/leds_configtab.i index 767160ec..8235cc4d 100644 --- a/main/leds_configtab.i +++ b/main/leds_configtab.i @@ -7,6 +7,9 @@ const struct configtab LEDS_CONFIGTAB[] = { .description = ( "Select phyiscal interface driver to use for output.\n" "Multiple led instances can share the same interface with different gpio output enables, but this will limit performance.\n" + #if CONFIG_IDF_TARGET_ESP32 + "\tNOTE: Only I2S1 supports parallel outputs.\n" + #endif ), .enum_type = { .value = &LEDS_CONFIG.interface, .values = leds_interface_enum }, }, @@ -88,6 +91,8 @@ const struct configtab LEDS_CONFIGTAB[] = { "\tN -> parallel mode with multiple data signals, separate leds on each gpio pin.\n" ), .uint16_type = { .value = &LEDS_CONFIG.i2s_data_width, .max = LEDS_I2S_PARALLEL_MAX }, + .validate_func = validate_leds_i2s_parallel, + .ctx = &LEDS_CONFIG, }, # endif # if LEDS_I2S_GPIO_PINS_ENABLED From 1d03d2b11b5b5b721f65d259b8bbc694380b2554 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 25 Oct 2025 17:02:32 +0300 Subject: [PATCH 5/6] leds: split i2s0/i2s1 interface stats --- components/leds/include/leds_stats.h | 20 ++++++++++++------ components/leds/interface.c | 3 ++- components/leds/interfaces/i2s.h | 3 ++- components/leds/interfaces/i2s/tx.c | 10 ++++----- components/leds/stats.c | 31 ++++++++++++++++++++++++---- components/leds/stats.h | 2 ++ main/leds_cmd.c | 14 +++++++++---- 7 files changed, 62 insertions(+), 21 deletions(-) diff --git a/components/leds/include/leds_stats.h b/components/leds/include/leds_stats.h index ede25259..b3acff71 100644 --- a/components/leds/include/leds_stats.h +++ b/components/leds/include/leds_stats.h @@ -1,9 +1,18 @@ #pragma once +#include #include #include +#if CONFIG_LEDS_I2S_ENABLED +struct leds_interface_i2s_stats { + struct stats_timer open; + struct stats_timer write; + struct stats_timer flush; +}; +#endif + struct leds_interface_stats { #if CONFIG_LEDS_SPI_ENABLED struct leds_interface_spi_stats { @@ -17,12 +26,11 @@ struct leds_interface_stats { struct stats_timer tx; } uart; #endif -#if CONFIG_LEDS_I2S_ENABLED - struct leds_interface_i2s_stats { - struct stats_timer open; - struct stats_timer write; - struct stats_timer flush; - } i2s; +#if LEDS_I2S_INTERFACE_COUNT > 0 + struct leds_interface_i2s_stats i2s0; +#endif +#if LEDS_I2S_INTERFACE_COUNT > 1 + struct leds_interface_i2s_stats i2s1; #endif }; diff --git a/components/leds/interface.c b/components/leds/interface.c index b38847d9..9266a7d3 100644 --- a/components/leds/interface.c +++ b/components/leds/interface.c @@ -1,6 +1,7 @@ #include #include "leds.h" #include "interface.h" +#include "stats.h" #include @@ -52,7 +53,7 @@ int leds_interface_init(union leds_interface_state *interface, const struct leds LOG_ERROR("unsupported interface=I2S for protocol=%d", options->protocol); return -1; - } else if ((err = leds_interface_i2s_init(&interface->i2s, &options->i2s, protocol_type->i2s_interface_mode, protocol_type->i2s_interface_func))) { + } else if ((err = leds_interface_i2s_init(&interface->i2s, &options->i2s, protocol_type->i2s_interface_mode, protocol_type->i2s_interface_func, leds_interface_i2s_stats(options->interface)))) { LOG_ERROR("leds_interface_i2s_init"); return err; } diff --git a/components/leds/interfaces/i2s.h b/components/leds/interfaces/i2s.h index ff9678d1..7850e046 100644 --- a/components/leds/interfaces/i2s.h +++ b/components/leds/interfaces/i2s.h @@ -62,12 +62,13 @@ struct leds_interface_i2s { struct i2s_out_options i2s_out_options; struct leds_interface_options_gpio gpio; + struct leds_interface_i2s_stats *stats; }; size_t leds_interface_i2s_buffer_size(enum leds_interface_i2s_mode mode, unsigned led_count, unsigned pin_count); size_t leds_interface_i2s_buffer_align(enum leds_interface_i2s_mode mode, unsigned pin_count); -int leds_interface_i2s_init(struct leds_interface_i2s *interface, const struct leds_interface_i2s_options *options, enum leds_interface_i2s_mode mode, union leds_interface_i2s_func func); +int leds_interface_i2s_init(struct leds_interface_i2s *interface, const struct leds_interface_i2s_options *options, enum leds_interface_i2s_mode mode, union leds_interface_i2s_func func, struct leds_interface_i2s_stats *stats); int leds_interface_i2s_tx(struct leds_interface_i2s *interface, const struct leds_color *pixels, unsigned count, const struct leds_limit *limit); #endif diff --git a/components/leds/interfaces/i2s/tx.c b/components/leds/interfaces/i2s/tx.c index eaf0850a..95e44709 100644 --- a/components/leds/interfaces/i2s/tx.c +++ b/components/leds/interfaces/i2s/tx.c @@ -177,7 +177,7 @@ static int leds_interface_i2s_tx_write(struct leds_interface_i2s *interface, con } } -int leds_interface_i2s_init(struct leds_interface_i2s *interface, const struct leds_interface_i2s_options *options, enum leds_interface_i2s_mode mode, union leds_interface_i2s_func func) +int leds_interface_i2s_init(struct leds_interface_i2s *interface, const struct leds_interface_i2s_options *options, enum leds_interface_i2s_mode mode, union leds_interface_i2s_func func, struct leds_interface_i2s_stats *stats) { interface->mode = mode; interface->func = func; @@ -283,13 +283,13 @@ int leds_interface_i2s_init(struct leds_interface_i2s *interface, const struct l #endif interface->gpio = options->gpio; + interface->stats = stats; return 0; } int leds_interface_i2s_tx(struct leds_interface_i2s *interface, const struct leds_color *pixels, unsigned count, const struct leds_limit *limit) { - struct leds_interface_i2s_stats *stats = &leds_interface_stats.i2s; int err; switch (interface->mode) { @@ -317,7 +317,7 @@ int leds_interface_i2s_tx(struct leds_interface_i2s *interface, const struct led LOG_FATAL("unknown mode=%d", interface->mode); } - WITH_STATS_TIMER(&stats->open) { + WITH_STATS_TIMER(&interface->stats->open) { if ((err = i2s_out_open(interface->i2s_out, &interface->i2s_out_options))) { LOG_ERROR("i2s_out_open"); return err; @@ -328,7 +328,7 @@ int leds_interface_i2s_tx(struct leds_interface_i2s *interface, const struct led leds_gpio_setup(&interface->gpio); #endif - WITH_STATS_TIMER(&stats->write) { + WITH_STATS_TIMER(&interface->stats->write) { if ((err = leds_interface_i2s_tx_write(interface, pixels, count, limit))) { goto error; } @@ -341,7 +341,7 @@ int leds_interface_i2s_tx(struct leds_interface_i2s *interface, const struct led } } - WITH_STATS_TIMER(&stats->flush) { + WITH_STATS_TIMER(&interface->stats->flush) { if ((err = i2s_out_flush(interface->i2s_out))) { LOG_ERROR("i2s_out_flush"); goto error; diff --git a/components/leds/stats.c b/components/leds/stats.c index a361d2a7..7bfa424a 100644 --- a/components/leds/stats.c +++ b/components/leds/stats.c @@ -2,6 +2,8 @@ #include "leds.h" #include "leds_stats.h" +#include + struct leds_interface_stats leds_interface_stats; void leds_reset_interface_stats() @@ -14,10 +16,15 @@ void leds_reset_interface_stats() stats_timer_init(&leds_interface_stats.uart.open); stats_timer_init(&leds_interface_stats.uart.tx); #endif -#if CONFIG_LEDS_I2S_ENABLED - stats_timer_init(&leds_interface_stats.i2s.open); - stats_timer_init(&leds_interface_stats.i2s.write); - stats_timer_init(&leds_interface_stats.i2s.flush); +#if LEDS_I2S_INTERFACE_COUNT > 0 + stats_timer_init(&leds_interface_stats.i2s0.open); + stats_timer_init(&leds_interface_stats.i2s0.write); + stats_timer_init(&leds_interface_stats.i2s0.flush); +#endif +#if LEDS_I2S_INTERFACE_COUNT > 1 + stats_timer_init(&leds_interface_stats.i2s1.open); + stats_timer_init(&leds_interface_stats.i2s1.write); + stats_timer_init(&leds_interface_stats.i2s1.flush); #endif } @@ -25,3 +32,19 @@ void leds_get_interface_stats(struct leds_interface_stats *stats) { *stats = leds_interface_stats; } + +struct leds_interface_i2s_stats *leds_interface_i2s_stats(enum leds_interface interface) +{ + switch(interface) { + #if LEDS_I2S_INTERFACE_COUNT > 0 + case LEDS_INTERFACE_I2S0: + return &leds_interface_stats.i2s0; + #endif + #if LEDS_I2S_INTERFACE_COUNT > 1 + case LEDS_INTERFACE_I2S1: + return &leds_interface_stats.i2s1; + #endif + default: + LOG_FATAL("%u", interface); + } +} diff --git a/components/leds/stats.h b/components/leds/stats.h index 1785f449..bf92c002 100644 --- a/components/leds/stats.h +++ b/components/leds/stats.h @@ -3,3 +3,5 @@ #include extern struct leds_interface_stats leds_interface_stats; + +struct leds_interface_i2s_stats *leds_interface_i2s_stats(enum leds_interface interface); diff --git a/main/leds_cmd.c b/main/leds_cmd.c index 0d2f6fe7..da36a16c 100644 --- a/main/leds_cmd.c +++ b/main/leds_cmd.c @@ -365,10 +365,16 @@ int leds_cmd_stats(int argc, char **argv, void *ctx) printf("\n"); #endif - #if CONFIG_LEDS_I2S_ENABLED - print_stats_timer("i2s", "open", &stats.i2s.open); - print_stats_timer("i2s", "write", &stats.i2s.write); - print_stats_timer("i2s", "flush", &stats.i2s.flush); + #if LEDS_I2S_INTERFACE_COUNT > 0 + print_stats_timer("i2s0", "open", &stats.i2s0.open); + print_stats_timer("i2s0", "write", &stats.i2s0.write); + print_stats_timer("i2s0", "flush", &stats.i2s0.flush); + printf("\n"); + #endif + #if LEDS_I2S_INTERFACE_COUNT > 1 + print_stats_timer("i2s1", "open", &stats.i2s1.open); + print_stats_timer("i2s1", "write", &stats.i2s1.write); + print_stats_timer("i2s1", "flush", &stats.i2s1.flush); printf("\n"); #endif } From b56430ff914cb576399e6b9d56e630137a4b6a63 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 25 Oct 2025 17:05:59 +0300 Subject: [PATCH 6/6] leds: fix esp8266 build warning --- main/leds_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/leds_config.c b/main/leds_config.c index a4d1c6eb..848ea3fe 100644 --- a/main/leds_config.c +++ b/main/leds_config.c @@ -141,7 +141,7 @@ const struct config_enum leds_parameter_enum[] = { {} }; -#if CONFIG_LEDS_I2S_ENABLED +#if LEDS_I2S_PARALLEL_ENABLED static int validate_leds_i2s_parallel (config_invalid_handler_t *handler, const struct config_path path, void *ctx) { struct leds_config *config = path.tab->ctx;