diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index ddc5541d76c7..34e91a56fb90 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -164,8 +164,17 @@ ifneq (,$(filter mpu9150,$(USEMODULE))) endif ifneq (,$(filter mtd_sdcard,$(USEMODULE))) - USEMODULE += mtd - USEMODULE += sdcard_spi + USEMODULE += mtd + USEMODULE += sdcard_spi +endif + +ifneq (,$(filter grove_ledbar,$(USEMODULE))) + USEMODULE += my9221 +endif + +ifneq (,$(filter my9221,$(USEMODULE))) + FEATURES_REQUIRED += periph_gpio + USEMODULE += xtimer endif ifneq (,$(filter nrfmin,$(USEMODULE))) diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 2ce48e8c877f..dcbd298cfa6a 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -13,6 +13,9 @@ endif ifneq (,$(filter ds1307,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ds1307/include endif +ifneq (,$(filter grove_ledbar,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/grove_ledbar/include +endif ifneq (,$(filter kw2xrf,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/kw2xrf/include endif @@ -52,6 +55,9 @@ endif ifneq (,$(filter mpu9150,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/mpu9150/include endif +ifneq (,$(filter my9221,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/my9221/include +endif ifneq (,$(filter ina220,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ina220/include endif diff --git a/drivers/grove_ledbar/Makefile b/drivers/grove_ledbar/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/drivers/grove_ledbar/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/grove_ledbar/grove_ledbar.c b/drivers/grove_ledbar/grove_ledbar.c new file mode 100644 index 000000000000..b50129c20caf --- /dev/null +++ b/drivers/grove_ledbar/grove_ledbar.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 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_grove_ledbar + * + * @{ + * @file + * @brief Driver for the Grove ledbar + * + * @author Sebastian Meiling + * + * @} + */ + +#include +#include +#include + +#include "log.h" +#include "xtimer.h" + +#include "grove_ledbar.h" +#include "my9221.h" + +#define DEV_LEDS (dev->params.leds) +#define DEV_STATE(x) (dev->state[x]) + +int grove_ledbar_init(grove_ledbar_t *dev, const grove_ledbar_params_t *params) +{ + assert(dev && params); + + return my9221_init((my9221_t *)dev, (my9221_params_t *)params); +} + +void grove_ledbar_set(grove_ledbar_t *dev, uint8_t level) +{ + assert(dev); + + uint8_t frac = GROVE_LEDBAR_MAX / DEV_LEDS; + + for (unsigned i = 0; i < DEV_LEDS; ++i) { + if (level > frac) { + DEV_STATE(i) = MY9221_LED_ON; + level -= frac; + } + else if (level > 0) { + DEV_STATE(i) = ~(MY9221_LED_ON << ((level << 3) / frac)); + level = 0; + } + else { + DEV_STATE(i) = MY9221_LED_OFF; + } + } + my9221_set_state((my9221_t *)dev, NULL, 0); +} + +void grove_ledbar_clear(grove_ledbar_t *dev) +{ + assert(dev); + + grove_ledbar_set(dev, 0); +} diff --git a/drivers/grove_ledbar/grove_ledbar_saul.c b/drivers/grove_ledbar/grove_ledbar_saul.c new file mode 100644 index 000000000000..11a2eb03a2fc --- /dev/null +++ b/drivers/grove_ledbar/grove_ledbar_saul.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 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_grove_ledbar + * @{ + * + * @file + * @brief Grove LED bar adaption to SAUL + * + * @author Sebastian Meiling + * + * @} + */ + +#include +#include + +#include "saul.h" +#include "grove_ledbar.h" + +static int set_ledbar(const void *dev, phydat_t *res) +{ + uint8_t lvl = (uint8_t)res->val[0]; + grove_ledbar_set((grove_ledbar_t *)dev, lvl); + return 1; +} + +const saul_driver_t grove_ledbar_saul_driver = { + .read = saul_notsup, + .write = set_ledbar, + .type = SAUL_ACT_LED_RGB, +}; diff --git a/drivers/grove_ledbar/include/grove_ledbar_params.h b/drivers/grove_ledbar/include/grove_ledbar_params.h new file mode 100644 index 000000000000..f9089595c05e --- /dev/null +++ b/drivers/grove_ledbar/include/grove_ledbar_params.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2017 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_grove_ledbar + * + * @{ + * @file + * @brief Config for the Grove LED bar based on MY9221 LED controller + * + * @author Sebastian Meiling + */ +#ifndef GROVE_LEDBAR_PARAMS_H +#define GROVE_LEDBAR_PARAMS_H + +#include "board.h" +#include "periph/gpio.h" +#include "saul_reg.h" + +#include "grove_ledbar.h" +#include "my9221.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Clock GPIO pin + */ +#ifndef GROVE_LEDBAR_CLK +#define GROVE_LEDBAR_CLK (GPIO_PIN(0,1)) +#endif + +/** + * @brief Data GPIO pin + */ +#ifndef GROVE_LEDBAR_DAT +#define GROVE_LEDBAR_DAT (GPIO_PIN(0,2)) +#endif + +/** + * @brief Direction of LEDs + */ +#ifndef GROVE_LEDBAR_DIR +#define GROVE_LEDBAR_DIR GROVE_LEDBAR_G2R +#endif + +/** + * @brief Default parameter settings + */ +#define GROVE_LEDBAR_PARAMS { \ + .leds = 10, \ + .dir = GROVE_LEDBAR_DIR, \ + .clk = GROVE_LEDBAR_CLK, \ + .dat = GROVE_LEDBAR_DAT, \ +} + +/** + * @brief Grove LED bar configuration + */ +static const grove_ledbar_params_t grove_ledbar_params[] = +{ +#ifdef GROVE_LEDBAR_CUSTOM + GROVE_LEDBAR_CUSTOM, +#else + GROVE_LEDBAR_PARAMS, +#endif +}; + +/** + * @brief Additional meta information to keep in the SAUL registry + */ +static const saul_reg_info_t grove_ledbar_saul_info[] = +{ + { + .name = "Grove LED bar" + } +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GROVE_LEDBAR_PARAMS_H */ +/** @} */ diff --git a/drivers/include/grove_ledbar.h b/drivers/include/grove_ledbar.h new file mode 100644 index 000000000000..a28d97a83de3 --- /dev/null +++ b/drivers/include/grove_ledbar.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @defgroup drivers_grove_ledbar Grove ledbar + * @ingroup drivers_actuators + * @brief Driver for the Grove ledbar + * + * @{ + * @file + * @brief Interface for the Grove ledbar driver + * + * @author Sebastian Meiling + */ + +#ifndef GROVE_LEDBAR_H +#define GROVE_LEDBAR_H + +#include + +#include "my9221.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Ledbar direction, either red to green, or vice versa. + * @{ + */ +#define GROVE_LEDBAR_R2G MY9221_DIR_FWD +#define GROVE_LEDBAR_G2R MY9221_DIR_REV +/** @} */ + +/** + * @brief Maximum value for ledbar level + */ +#define GROVE_LEDBAR_MAX UINT8_MAX + +/** + * @brief Parameters needed for device initialization + */ +typedef my9221_params_t grove_ledbar_params_t; + +/** + * @brief Device descriptor for grove ledbar, alias for MY9221 LED controller + */ +typedef my9221_t grove_ledbar_t; + +/** + * @brief Initialize the given driver + * + * @pre `dev != NULL` and `params != NULL` + * + * @param[out] dev device descriptor grove ledbar + * @param[in] params configuration parameters + * + * @return 0 on success, otherwise error + */ +int grove_ledbar_init(grove_ledbar_t *dev, const grove_ledbar_params_t *params); + +/** + * @brief Set overall (brightness) level distributed over all LEDs + * + * @pre `dev != NULL` + * + * @param[in] dev device descriptor grove ledbar + * @param[in] level overall brightness level + */ +void grove_ledbar_set(grove_ledbar_t *dev, uint8_t level); + +/** + * @brief Clear ledbar, i.e. set all LEDs off + * + * @pre `dev != NULL` + * + * @param[in] dev device descriptor grove ledbar + */ +void grove_ledbar_clear(grove_ledbar_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* GROVE_LEDBAR_H */ +/** @} */ diff --git a/drivers/include/my9221.h b/drivers/include/my9221.h new file mode 100644 index 000000000000..1cf72ca03534 --- /dev/null +++ b/drivers/include/my9221.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @defgroup drivers_my9221 MY9221 LED controller + * @ingroup drivers_actuators + * @brief Driver for the MY-Semi MY9221 LED controller + * + * @{ + * @file + * @brief Interface for the MY9221 LED controller driver + * + * @author Sebastian Meiling + */ + +#ifndef MY9221_H +#define MY9221_H + +#include + +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Maximum number of distinct LEDs the controller can operate + */ +#define MY9221_LED_MAX (12U) + +/** + * @brief Max brightness value to turn LED full on + */ +#define MY9221_LED_ON (0xFF) + +/** + * @brief Min brightness value to turn LED off + */ +#define MY9221_LED_OFF (0x00) + +/** + * @name Direction the controller accesses LEDs + * @{ + */ +enum { + MY9221_DIR_FWD, /**< forward */ + MY9221_DIR_REV, /**< backward */ +}; +/** @} */ + +/** + * @name Driver specific return codes + * @{ + */ +enum { + MY9221_OK, /**< success */ + MY9221_ERR, /**< failure */ +}; +/** @} */ + +/** + * @brief Parameters needed for device initialization + */ +typedef struct { + uint8_t leds; /**< number of LEDs */ + uint8_t dir; /**< led direction */ + gpio_t clk; /**< clock gpio pin */ + gpio_t dat; /**< data gpio pin */ +} my9221_params_t; + +/** + * @brief Device descriptor for MY9221 LED controller + */ +typedef struct { + my9221_params_t params; /**< config parameters */ + uint8_t state[MY9221_LED_MAX]; /**< state of individual leds */ +} my9221_t; + +/** + * @brief Initialize the given driver + * + * @param[out] dev device descriptor of MY9221 LED controller + * @param[in] params configuration parameters + * + * @return 0 on success, otherwise error + */ +int my9221_init(my9221_t *dev, const my9221_params_t *params); + +/** + * @brief Set device state + * + * @note If @p state is NULL or @p len is 0, current device state is set + * otherwise, current state is overwritten by @p state. + * + * @param[in] dev device descriptor of MY9221 LED controller + * @param[in] state new device state array + * @param[in] len length of state array + */ +void my9221_set_state(my9221_t *dev, const uint8_t *state, uint8_t len); + +/** + * @brief Set brightness of distinct LED + * + * @param[in] dev device descriptor of MY9221 LED controller + * @param[in] led led number, start with 0 + * @param[in] alpha brightness level for led + */ +void my9221_set_led(my9221_t *dev, const uint8_t led, const uint8_t alpha); + +/** + * @brief Toggle a distinct LED + * + * @param[in] dev device descriptor of MY9221 LED controller + * @param[in] led led number, start with 0 + */ +void my9221_toggle_led(my9221_t *dev, const uint8_t led); + +#ifdef __cplusplus +} +#endif + +#endif /* MY9221_H */ +/** @} */ diff --git a/drivers/my9221/Makefile b/drivers/my9221/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/drivers/my9221/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/my9221/include/my9221_internal.h b/drivers/my9221/include/my9221_internal.h new file mode 100644 index 000000000000..ecc895faeaba --- /dev/null +++ b/drivers/my9221/include/my9221_internal.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 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_my9221 + * + * @{ + * @file + * @brief Internal config and parameters for the MY9221 LED controller + * + * @author Sebastian Meiling + */ + +#ifndef MY9221_INTERNAL_H +#define MY9221_INTERNAL_H + +#include "xtimer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Time to wait until latch register is processed + */ +#define MY9221_LATCH_WAIT (10U * US_PER_MS) + +/** + * @brief Number of write loops for latch register + */ +#define MY9221_LATCH_LOOP (4U) + +/** + * @brief Enable command mode on LED controller + */ +#define MY9221_CMDMODE (0x00) + +#ifdef __cplusplus +} +#endif + +#endif /* MY9221_INTERNAL_H */ +/** @} */ diff --git a/drivers/my9221/my9221.c b/drivers/my9221/my9221.c new file mode 100644 index 000000000000..797cb8a0af9e --- /dev/null +++ b/drivers/my9221/my9221.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 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_my9221 + * + * @{ + * @file + * @brief Driver for the MY9221 LED controller + * + * @author Sebastian Meiling + * + * @} + */ + +#include +#include +#include + +#include "log.h" +#include "periph/gpio.h" +#include "xtimer.h" + +#include "my9221.h" +#include "my9221_internal.h" + +#define DEV_DIR (dev->params.dir) +#define DEV_LEDS (dev->params.leds) +#define DEV_STATE(x) (dev->state[x]) +#define PIN_CLK (dev->params.clk) +#define PIN_DAT (dev->params.dat) + +/** + * @brief Write a single data to the LED controller + */ +void _write(my9221_t *dev, uint16_t data) +{ + assert(dev); + + for (unsigned i = 0; i < 16; ++i) { + (data & 0x8000) ? gpio_set(PIN_DAT) : gpio_clear(PIN_DAT); + gpio_toggle(PIN_CLK); + data <<= 1; + } +} + +/** + * @brief Load data into the latch register of the LED controller + */ +void _latch(my9221_t *dev) +{ + assert(dev); + + gpio_clear(PIN_DAT); + xtimer_usleep(MY9221_LATCH_WAIT); + + for (unsigned i = 0; i < MY9221_LATCH_LOOP; ++i) { + gpio_set(PIN_DAT); + gpio_clear(PIN_DAT); + } +} + +/** + * @brief Write state data of all LEDs to the controller + */ +void _set_state(my9221_t *dev) +{ + assert(dev); + + _write(dev, MY9221_CMDMODE); + for (unsigned i = 0; i < DEV_LEDS; ++i) { + if (DEV_DIR == MY9221_DIR_REV) { + /* Write LED state in reverse order */ + _write(dev, DEV_STATE(DEV_LEDS-i-1)); + } + else { + /* Write LED state in forward order */ + _write(dev, DEV_STATE(i)); + } + } + /* set unused LED pins to off */ + for (unsigned j = DEV_LEDS; j < MY9221_LED_MAX; ++j) { + _write(dev, MY9221_LED_OFF); + } + + _latch(dev); +} + +int my9221_init(my9221_t *dev, const my9221_params_t *params) +{ + assert(dev); + assert(params); + /* write config params to device descriptor */ + memcpy(&dev->params, params, sizeof(my9221_params_t)); + /* init clock and data pins as output */ + gpio_init(PIN_CLK, GPIO_OUT); + gpio_init(PIN_DAT, GPIO_OUT); + /* reset state, i.e., all LEDs off */ + memset(dev->state, 0, sizeof(dev->state)); + _set_state(dev); + + return MY9221_OK; +} + +void my9221_set_state(my9221_t *dev, const uint8_t *state, uint8_t len) +{ + if ((state != NULL) && (len > 0)) { + if (len > MY9221_LED_MAX) { + len = MY9221_LED_MAX; + } + memcpy(dev->state, state, len); + } + _set_state(dev); +} + +void my9221_set_led(my9221_t *dev, const uint8_t led, const uint8_t alpha) +{ + assert(dev); + assert(led < DEV_LEDS); + + DEV_STATE(led) = ~(MY9221_LED_ON << ((uint16_t)(alpha << 3) >> 8)); + _set_state(dev); +} + +void my9221_toggle_led(my9221_t *dev, const uint8_t led) +{ + assert(dev); + assert(led < DEV_LEDS); + + DEV_STATE(led) = DEV_STATE(led) ? MY9221_LED_OFF : MY9221_LED_ON; + _set_state(dev); +} diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 21f392cbe7cc..7eb0635afc9e 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -291,6 +291,10 @@ void auto_init(void) extern void auto_init_mpl3115a2(void); auto_init_mpl3115a2(); #endif +#ifdef MODULE_GROVE_LEDBAR + extern void auto_init_grove_ledbar(void); + auto_init_grove_ledbar(); +#endif #ifdef MODULE_SI70XX extern void auto_init_si70xx(void); auto_init_si70xx(); diff --git a/sys/auto_init/saul/auto_init_grove_ledbar.c b/sys/auto_init/saul/auto_init_grove_ledbar.c new file mode 100644 index 000000000000..6c644970387b --- /dev/null +++ b/sys/auto_init/saul/auto_init_grove_ledbar.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 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 auto_init_saul + * @{ + * + * @file + * @brief Auto initialization of Grove LED bar + * + * @author Sebastian Meiling + * + * @} + */ + +#ifdef MODULE_GROVE_LEDBAR + +#include "log.h" +#include "saul_reg.h" + +#include "grove_ledbar.h" +#include "grove_ledbar_params.h" + +/** + * @brief Define the number of configured sensors + */ +#define GROVE_LEDBAR_NUM (sizeof(grove_ledbar_params) / sizeof(grove_ledbar_params[0])) + +/** + * @brief Allocate memory for the device descriptors + */ +static grove_ledbar_t grove_ledbar_devs[GROVE_LEDBAR_NUM]; + +/** + * @brief Memory for the SAUL registry entries + */ +static saul_reg_t saul_entries[GROVE_LEDBAR_NUM]; + +/** + * @brief Reference the driver struct + */ +extern const saul_driver_t grove_ledbar_saul_driver; + +void auto_init_grove_ledbar(void) +{ + for (unsigned i = 0; i < GROVE_LEDBAR_NUM; i++) { + LOG_DEBUG("[auto_init_saul] initializing Grove LED bar #%u: ", i); + + if (my9221_init(&grove_ledbar_devs[i], &grove_ledbar_params[i]) != MY9221_OK) { + LOG_ERROR("ERROR\n"); + continue; + } + LOG_DEBUG("SUCCESS\n"); + saul_entries[i].dev = &(grove_ledbar_devs[i]); + saul_entries[i].name = grove_ledbar_saul_info[i].name; + saul_entries[i].driver = &grove_ledbar_saul_driver; + saul_reg_add(&(saul_entries[i])); + } +} + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_GROVE_LEDBAR */ diff --git a/tests/driver_grove_ledbar/Makefile b/tests/driver_grove_ledbar/Makefile new file mode 100644 index 000000000000..af7efb5136e8 --- /dev/null +++ b/tests/driver_grove_ledbar/Makefile @@ -0,0 +1,20 @@ +APPLICATION = driver_grove_ledbar +include ../Makefile.tests_common + +USEMODULE += grove_ledbar + +# set default device parameters in case they are undefined +# the following params are for board pba-d-01-kw2x and pins PA01 and PA02 +TEST_GROVE_LEDBAR_CLK ?= GPIO_PIN\(0,1\) +TEST_GROVE_LEDBAR_DAT ?= GPIO_PIN\(0,2\) +TEST_GROVE_LEDBAR_DIR ?= GROVE_LEDBAR_G2R + +# export parameters +CFLAGS += -DGROVE_LEDBAR_CLK=$(TEST_GROVE_LEDBAR_CLK) +CFLAGS += -DGROVE_LEDBAR_DAT=$(TEST_GROVE_LEDBAR_DAT) +CFLAGS += -DGROVE_LEDBAR_DIR=$(TEST_GROVE_LEDBAR_DIR) + +test: + tests/01-run.py + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_grove_ledbar/README.md b/tests/driver_grove_ledbar/README.md new file mode 100644 index 000000000000..a3c0cd5bedaa --- /dev/null +++ b/tests/driver_grove_ledbar/README.md @@ -0,0 +1,22 @@ +# About + +This is a test application for the Seeed Studio Grove LED bar module [1]. + +# Details + +This test application will initialize a Groove LED bar with the configuration +as specified in the `grove_ledbar_params.h` file. To connect the LED bar with +your board use the following pinout: + +- Pin GND is connected directly to GND. +- Pin VCC is connected directly to VCC +3.3V, or 5V if your board allows that. +- Pin DCKI is the clock pin and is connected to a free GPIO +- Pin DI is the data pin and is connected to a free GPIO, too + +for the 2 latter pins note the port and pin number and adapt the Makefile +accordingly. + +The test application will light up the LED bar several times, running from 0% +up to 100% and down to 0% again. + +[1]: https://www.seeedstudio.com/Grove-LED-Bar-v2.0-p-2474.html diff --git a/tests/driver_grove_ledbar/main.c b/tests/driver_grove_ledbar/main.c new file mode 100644 index 000000000000..0ef9afb4bf2e --- /dev/null +++ b/tests/driver_grove_ledbar/main.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2017 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 tests + * @{ + * + * @file + * @brief Test application for the Grove ledbar + * + * @author Sebastian Meiling + * + * @} + */ + +#include + +#include "log.h" +#include "xtimer.h" +#include "grove_ledbar.h" +#include "grove_ledbar_params.h" + +#define TEST_RUNS (5U) +#define TEST_STEP (5U) +#define TEST_WAIT (42*US_PER_MS) + +int main(void) +{ + grove_ledbar_t dev; + /* init display */ + puts("[START]"); + if (grove_ledbar_init(&dev, &grove_ledbar_params[0]) != 0) { + puts("[FAILED]"); + return 1; + } + LOG_INFO(" stepwise increase LED bar to 100%% and then decrease to 0%%.\n\n"); + for (unsigned r = 0; r < TEST_RUNS; ++r) { + LOG_INFO(" >>> round %u\n", (r+1)); + uint8_t lvl = 0; + while (lvl < GROVE_LEDBAR_MAX - TEST_STEP) { + grove_ledbar_set(&dev, lvl); + lvl += TEST_STEP; + xtimer_usleep(TEST_WAIT); + } + grove_ledbar_set(&dev, GROVE_LEDBAR_MAX); + /* turn all off */ + xtimer_usleep(TEST_WAIT); + lvl = GROVE_LEDBAR_MAX; + while (lvl > TEST_STEP) { + grove_ledbar_set(&dev, lvl); + lvl -= TEST_STEP; + xtimer_usleep(TEST_WAIT); + } + /* turn all off */ + grove_ledbar_clear(&dev); + } + puts("[SUCCESS]"); + + return 0; +} diff --git a/tests/driver_grove_ledbar/tests/01-run.py b/tests/driver_grove_ledbar/tests/01-run.py new file mode 100755 index 000000000000..70e38e81acb4 --- /dev/null +++ b/tests/driver_grove_ledbar/tests/01-run.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2016 Kaspar Schleiser +# 2017 Sebastian Meiling +# +# 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. + +import os +import sys + +sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) +import testrunner + +def testfunc(child): + child.expect_exact(u"[SUCCESS]", timeout=60) + +if __name__ == "__main__": + sys.exit(testrunner.run(testfunc)) diff --git a/tests/driver_my9221/Makefile b/tests/driver_my9221/Makefile new file mode 100644 index 000000000000..0f1bce3a5812 --- /dev/null +++ b/tests/driver_my9221/Makefile @@ -0,0 +1,22 @@ +APPLICATION = driver_my9221 +include ../Makefile.tests_common + +USEMODULE += my9221 + +# set default device parameters in case they are undefined +# the following params are for board pba-d-01-kw2x and pins PA01 and PA02 +TEST_MY9221_CLK ?= GPIO_PIN\(0,1\) +TEST_MY9221_DAT ?= GPIO_PIN\(0,2\) +TEST_MY9221_DIR ?= MY9221_DIR_FWD +TEST_MY9221_NUM ?= 10 + +# export parameters +CFLAGS += -DTEST_MY9221_CLK=$(TEST_MY9221_CLK) +CFLAGS += -DTEST_MY9221_DAT=$(TEST_MY9221_DAT) +CFLAGS += -DTEST_MY9221_DIR=$(TEST_MY9221_DIR) +CFLAGS += -DTEST_MY9221_NUM=$(TEST_MY9221_NUM) + +test: + tests/01-run.py + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_my9221/README.md b/tests/driver_my9221/README.md new file mode 100644 index 000000000000..e5b4eb57e0bb --- /dev/null +++ b/tests/driver_my9221/README.md @@ -0,0 +1,16 @@ +# About + +This is a test application for the MY9221 LED controller driver, which is found +on the Seeed Studio Grove LED bar module [1]. + +# Details + +For this test application you can use e.g. the Groove LED bar which has 10 LEDs. +The default settings in the Makefile are suited for the Grove ledbar, adapt them +as needed for any other device or number of LEDs. + +The test application runs several test sequence, first toggling all LEDs +one by one, and secondly setting all LEDs to 33%, 66%, and 100% brightness. +Finally all LEDs are turned of again. + +[1]: https://www.seeedstudio.com/Grove-LED-Bar-v2.0-p-2474.html diff --git a/tests/driver_my9221/main.c b/tests/driver_my9221/main.c new file mode 100644 index 000000000000..96223591b144 --- /dev/null +++ b/tests/driver_my9221/main.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 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 tests + * @{ + * + * @file + * @brief Test application for the MY9221 LED controller + * + * @author Sebastian Meiling + * + * @} + */ + +#include + +#include "log.h" +#include "xtimer.h" +#include "my9221.h" + +#define TEST_STEP (5U) +#define TEST_WAIT (42*US_PER_MS) + +static my9221_params_t params = { + .leds = TEST_MY9221_NUM, + .dir = TEST_MY9221_DIR, + .clk = TEST_MY9221_CLK, + .dat = TEST_MY9221_DAT, +}; + +int main(void) +{ + my9221_t dev; + /* init display */ + puts("[START]"); + if (my9221_init(&dev, ¶ms) != 0) { + puts("[FAILED]"); + return 1; + } + /* run some tests */ + LOG_INFO("- light up all LEDs one by one.\n"); + for (unsigned i=0; i < dev.params.leds; ++i) { + my9221_set_led(&dev, i, MY9221_LED_ON); + xtimer_usleep(TEST_WAIT); + my9221_set_led(&dev, i, MY9221_LED_OFF); + } + xtimer_usleep(TEST_WAIT); + for (unsigned i=dev.params.leds; i > 0 ; --i) { + my9221_set_led(&dev, i, MY9221_LED_ON); + xtimer_usleep(TEST_WAIT); + my9221_set_led(&dev, i, MY9221_LED_OFF); + } + xtimer_usleep(TEST_WAIT); + LOG_INFO("- light up all LEDs to 33%%.\n"); + for (unsigned i=0; i < dev.params.leds; ++i) { + my9221_set_led(&dev, i, MY9221_LED_ON/3); + xtimer_usleep(TEST_WAIT); + } + xtimer_usleep(TEST_WAIT); + LOG_INFO("- light up all LEDs to 66%%.\n"); + for (unsigned i=0; i < dev.params.leds; ++i) { + my9221_set_led(&dev, i, (MY9221_LED_ON/3)*2); + xtimer_usleep(TEST_WAIT); + } + xtimer_usleep(TEST_WAIT); + LOG_INFO("- light up all LEDs to 100%%.\n"); + for (unsigned i=0; i < dev.params.leds; ++i) { + my9221_set_led(&dev, i, MY9221_LED_ON); + xtimer_usleep(TEST_WAIT); + } + xtimer_usleep(TEST_WAIT); + LOG_INFO("- turn off all LEDs\n"); + for (unsigned i=dev.params.leds; i > 0 ; --i) { + my9221_toggle_led(&dev, i-1); + xtimer_usleep(TEST_WAIT); + } + puts("[SUCCESS]"); + + return 0; +} diff --git a/tests/driver_my9221/tests/01-run.py b/tests/driver_my9221/tests/01-run.py new file mode 100755 index 000000000000..5801a4475cb6 --- /dev/null +++ b/tests/driver_my9221/tests/01-run.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2016 Kaspar Schleiser +# 2017 Sebastian Meiling +# +# 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. + +import os +import sys + +sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) +import testrunner + +def testfunc(child): + child.expect_exact("[SUCCESS]", timeout=60) + +if __name__ == "__main__": + sys.exit(testrunner.run(testfunc))