diff --git a/drivers/saul/init_devs/auto_init_ws281x.c b/drivers/saul/init_devs/auto_init_ws281x.c new file mode 100644 index 0000000000000..d54d71d5c7675 --- /dev/null +++ b/drivers/saul/init_devs/auto_init_ws281x.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2024 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + */ + +/** + * @ingroup sys_auto_init_saul + * @{ + * + * @file + * @brief Auto initialization of ws281x RGB LED devices + * + * @author Kevin Weiss + * + * @} + */ + +#include "assert.h" +#include "log.h" +#include "saul_reg.h" + +#include "ws281x.h" +#include "ws281x_params.h" + +/** + * @brief Define the number of configured sensors + */ +#define WS281X_NUM ARRAY_SIZE(ws281x_params) + +/** + * @brief Allocate memory for the device descriptors + */ +static ws281x_t ws281x_devs[WS281X_NUM]; + +/** + * @brief Memory for the SAUL registry entries + */ +static saul_reg_t saul_entries[WS281X_NUM]; + +/** + * @brief Define the number of saul info + */ +#define WS281X_INFO_NUM ARRAY_SIZE(ws281x_saul_info) + +/** + * @brief Reference the driver struct + */ +extern const saul_driver_t ws281x_saul_driver; + +void auto_init_ws281x(void) +{ + assert(WS281X_NUM == WS281X_INFO_NUM); + + for (unsigned i = 0; i < WS281X_NUM; i++) { + LOG_DEBUG("[auto_init_saul] initializing WS281x #%u: ", i); + + if (ws281x_init(&ws281x_devs[i], &ws281x_params[i]) != 0) { + LOG_ERROR("ERROR\n"); + continue; + } + LOG_DEBUG("SUCCESS\n"); + saul_entries[i].dev = &(ws281x_devs[i]); + saul_entries[i].name = ws281x_saul_info[i].name; + saul_entries[i].driver = &ws281x_saul_driver; + saul_reg_add(&(saul_entries[i])); + } +} diff --git a/drivers/saul/init_devs/init.c b/drivers/saul/init_devs/init.c index ad4d4704447ed..1e9146fce5203 100644 --- a/drivers/saul/init_devs/init.c +++ b/drivers/saul/init_devs/init.c @@ -343,4 +343,8 @@ void saul_init_devs(void) extern void auto_init_servo(void); auto_init_servo(); } + if (IS_USED(MODULE_WS281X)) { + extern void auto_init_ws281x(void); + auto_init_ws281x(); + } } diff --git a/drivers/ws281x/Makefile b/drivers/ws281x/Makefile index de0e17ec3b8ed..35d1f8508ba23 100644 --- a/drivers/ws281x/Makefile +++ b/drivers/ws281x/Makefile @@ -1,3 +1,14 @@ SRC := ws281x.c # All other sources files provide ws281x_write as submodule SUBMODULES := 1 + +# Since we have submodules we need to manually handle saul instead of +# including driver_with_saul.mk +MODULE ?= $(shell basename $(CURDIR)) +SAUL_INTERFACE ?= $(MODULE)_saul.c + +# only include _saul.c if saul module is used +ifneq (,$(filter saul,$(USEMODULE))) + SRC += $(SAUL_INTERFACE) +endif + include $(RIOTBASE)/Makefile.base diff --git a/drivers/ws281x/Makefile.dep b/drivers/ws281x/Makefile.dep index f539c4de83d72..31f00f6c33f0e 100644 --- a/drivers/ws281x/Makefile.dep +++ b/drivers/ws281x/Makefile.dep @@ -37,3 +37,6 @@ endif ifneq (,$(filter ws281x_timer_gpio_ll,$(USEMODULE))) FEATURES_REQUIRED += periph_gpio_ll periph_timer periph_timer_poll endif + +# It would seem xtimer is always required as it is used in the header... +USEMODULE += xtimer diff --git a/drivers/ws281x/include/ws281x_params.h b/drivers/ws281x/include/ws281x_params.h index e68b8f91839b2..1f7d0262155de 100644 --- a/drivers/ws281x/include/ws281x_params.h +++ b/drivers/ws281x/include/ws281x_params.h @@ -20,6 +20,8 @@ #define WS281X_PARAMS_H #include "board.h" +#include "saul_reg.h" + #include "ws281x.h" #ifdef __cplusplus @@ -105,6 +107,21 @@ static const ws281x_params_t ws281x_params[] = #define WS281X_TIMER_FREQ 16000000 #endif +/** + * @brief SAUL info + */ +#ifndef WS281X_SAUL_INFO +#define WS281X_SAUL_INFO { .name = "WS281X RGB LED" } +#endif + +/** + * @brief Additional meta information to keep in the SAUL registry + */ +static const saul_reg_info_t ws281x_saul_info[] = +{ + WS281X_SAUL_INFO +}; + #ifdef __cplusplus } #endif diff --git a/drivers/ws281x/ws281x_saul.c b/drivers/ws281x/ws281x_saul.c new file mode 100644 index 0000000000000..b85f7a3abf8e6 --- /dev/null +++ b/drivers/ws281x/ws281x_saul.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_ws281x + * @{ + * + * @file + * @brief NEOPixel/ws281x adaption to SAUL + * + * @author Kevin Weiss + * + * @} + */ + +#include +#include + +#include "saul.h" +#include "ws281x.h" + +static int set_rgb_led(const void *dev, const phydat_t *res) +{ + ws281x_t *ws281x = (ws281x_t *)dev; + color_rgb_t color = { + .r = res->val[0], + .g = res->val[1], + .b = res->val[2] + }; + for (int i = 0; i < ws281x->params.numof; i++) { + puts("Setting LED"); + ws281x_set(ws281x, i, color); + } + ws281x_write(ws281x); + return 1; +} + +const saul_driver_t ws281x_saul_driver = { + .read = saul_read_notsup, + .write = set_rgb_led, + .type = SAUL_ACT_LED_RGB, +};