From 7d73e8acaf95b45b18b328427549cc41ab94d35f Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Sun, 12 Jan 2020 18:24:06 +0100 Subject: [PATCH] pkg/ucglib: refactor the Ucglib package - Passing RIOT-OS specific data as user_ptr - Added necessary macros to Makefile.dep - Added missing explicit dependency to xtimer module - Added ucg_riotos.h with the RIOT-OS specific functionality - Removed the now-obsolete patch of Ucglib - Other minor fixes --- pkg/ucglib/Makefile | 2 +- pkg/ucglib/Makefile.dep | 4 + pkg/ucglib/Makefile.include | 4 + pkg/ucglib/README.md | 36 +++----- pkg/ucglib/contrib/ucg_riotos.c | 79 ++++++++++------- pkg/ucglib/contrib/ucg_riotos.h | 65 ++++++++++++++ .../patches/0001-add-RIOT-OS-interface.patch | 88 ------------------- 7 files changed, 133 insertions(+), 145 deletions(-) create mode 100644 pkg/ucglib/contrib/ucg_riotos.h delete mode 100644 pkg/ucglib/patches/0001-add-RIOT-OS-interface.patch diff --git a/pkg/ucglib/Makefile b/pkg/ucglib/Makefile index 7d3239033d..8731e57efa 100644 --- a/pkg/ucglib/Makefile +++ b/pkg/ucglib/Makefile @@ -1,6 +1,6 @@ PKG_NAME=ucglib PKG_URL=https://github.com/olikraus/ucglib -PKG_VERSION=bf48515702dd7c87cbacdd17989738f33f003df2 +PKG_VERSION=230f15e3bcd3c84977780e84bd855ac89c1959ee PKG_LICENSE=BSD-2-Clause include $(RIOTBASE)/pkg/pkg.mk diff --git a/pkg/ucglib/Makefile.dep b/pkg/ucglib/Makefile.dep index beb31d0fac..29d5db25a0 100644 --- a/pkg/ucglib/Makefile.dep +++ b/pkg/ucglib/Makefile.dep @@ -1,2 +1,6 @@ +USEMODULE += xtimer + +FEATURES_REQUIRED += periph_gpio + USEMODULE += ucglib_riot USEMODULE += ucglib_csrc diff --git a/pkg/ucglib/Makefile.include b/pkg/ucglib/Makefile.include index 46fd0d7ae1..ea3874136d 100644 --- a/pkg/ucglib/Makefile.include +++ b/pkg/ucglib/Makefile.include @@ -1,4 +1,8 @@ INCLUDES += -I$(PKGDIRBASE)/ucglib/csrc +INCLUDES += -I$(RIOTBASE)/pkg/ucglib/contrib + +# The RIOT-OS interface needs this to store peripheral information. +CFLAGS += -DWITH_USER_PTR # Link SDL if enabled. ifneq (,$(filter ucglib_sdl,$(USEMODULE))) diff --git a/pkg/ucglib/README.md b/pkg/ucglib/README.md index 263ec40ff2..2879fd487a 100644 --- a/pkg/ucglib/README.md +++ b/pkg/ucglib/README.md @@ -13,44 +13,36 @@ This package patches the original source to add an interface for RIOT-OS. Only the callback for SPI peripherals is supported: -* `ucg_com_riotos_hw_spi` +* `ucg_com_hw_spi_riotos` -Ucglib needs to map pin numbers to RIOT-OS pin numbers. It also needs to know which peripheral to use. The following two methods can be used to set this information. +These methods require a structure containing peripheral information (`ucg_riotos_t`), that is set using the `ucg_SetUserPtr` function. This structure contains the peripheral and pin mapping. -* `ucg_SetPins(ucg_dev, pins, bitmap)` -* `ucg_SetDevice(ucg_dev, dev)` - -Note: `pins` should point to `gpio_t` array of Ucglib pin numbers to RIOT-OS pins. Due to this, `pins` can take up an additional 100 bytes, because it will use memory for the pins you do not map. You can overcome this limitation by implementing `ucg_com_riotos_hw_spi` yourself and hardcode the pins. +If the above interface is not sufficient, it is still possible to write a dedicated interface by (re-)implementing the methods above. Refer to the [Ucglib wiki](https://github.com/olikraus/ucglib/wiki) for more information. ### Example -``` +```c ucg_t ucg; -gpio_t pins[] = { - [UCG_PIN_CS] = GPIO(PA, 0), - [UCG_PIN_CD] = GPIO(PA, 1), - [UCG_PIN_RESET] = GPIO(PA, 2) +ucg_riotos_t user_data = +{ + .device_index = SPI_DEV(0), + .pin_cs = GPIO_PIN(PA, 0), + .pin_cd = GPIO_PIN(PA, 1), + .pin_reset = GPIO_PIN(PA, 2) }; -uint32_t bitmap = ( - (1 << UCG_PIN_CS) + - (1 << UCG_PIN_CD) + - (1 << UCG_PIN_RESET) -); +ucg_SetUserPtr(&ucg, &user_data); -ucg_SetPins(&ucg, pins, bitmap); -ucg_SetDevice(&ucg, SPI_DEV(0)); - -ucg_Init(&ucg, ucg_dev_ssd1331_18x96x64_univision, ucg_ext_ssd1331_18, ucg_com_riotos_hw_spi); +ucg_Init(&ucg, ucg_dev_ssd1331_18x96x64_univision, ucg_ext_ssd1331_18, ucg_com_hw_spi_riotos); ``` ## Virtual displays -For targets without an I2C or SPI, a virtual display is available. Support for a virtual display is not compiled in by default. +For targets without SPI, a virtual display is available. Support for a virtual display is not compiled by default. * By adding `USEMODULE += ucglib_sdl`, a SDL virtual display will be used. This is only available on native targets that have SDL2 installed. It uses `sdl2-config` to find the headers and libraries. Note that RIOT-OS builds 32-bit binaries and requires 32-bit SDL2 libraries. ### Example -``` +```c ucg_t ucg; ucg_Init(&ucg, ucg_sdl_dev_cb, ucg_ext_none, NULL); diff --git a/pkg/ucglib/contrib/ucg_riotos.c b/pkg/ucglib/contrib/ucg_riotos.c index bf10f22e75..6a415cdced 100644 --- a/pkg/ucglib/contrib/ucg_riotos.c +++ b/pkg/ucglib/contrib/ucg_riotos.c @@ -18,17 +18,18 @@ * @} */ -#include "ucg.h" +#include + +#include "ucg_riotos.h" #include "xtimer.h" +#ifdef MODULE_PERIPH_SPI #include "periph/spi.h" -#include "periph/i2c.h" +#endif #include "periph/gpio.h" -#include - -#ifdef SPI_NUMOF +#ifdef MODULE_PERIPH_SPI static spi_clk_t ucg_serial_clk_speed_to_spi_speed(uint32_t serial_clk_speed) { if (serial_clk_speed < 100) { @@ -46,37 +47,47 @@ static spi_clk_t ucg_serial_clk_speed_to_spi_speed(uint32_t serial_clk_speed) return SPI_CLK_100KHZ; } -#endif /* SPI_NUMOF */ +#endif /* MODULE_PERIPH_SPI */ -static void ucg_enable_pins(gpio_t *pins, uint32_t pins_enabled) +/** + * @brief Enable the selected pins in RIOT-OS. + */ +static void _enable_pins(const ucg_riotos_t *ucg_riot_ptr) { - uint8_t i; + /* no hardware peripheral is being used, nothing to be done */ + if (ucg_riot_ptr == NULL) { + return; + } - for (i = 0; i < 32; i++) { - if (pins_enabled & ((uint32_t)1 << i)) { - if (pins[i] != GPIO_UNDEF) { - if (i < UCG_PIN_COUNT) { - gpio_init(pins[i], GPIO_OUT); - } - else { - gpio_init(pins[i], GPIO_IN); - } - } - } + if (ucg_riot_ptr->pin_cs != GPIO_UNDEF) { + gpio_init(ucg_riot_ptr->pin_cs, GPIO_OUT); + } + + if (ucg_riot_ptr->pin_cd != GPIO_UNDEF) { + gpio_init(ucg_riot_ptr->pin_cd, GPIO_OUT); + } + + if (ucg_riot_ptr->pin_reset != GPIO_UNDEF) { + gpio_init(ucg_riot_ptr->pin_reset, GPIO_OUT); } } -#ifdef SPI_NUMOF -int16_t ucg_com_riotos_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data) +#ifdef MODULE_PERIPH_SPI +int16_t ucg_com_hw_spi_riotos(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data) { - spi_t dev = (spi_t) ucg->dev; + const ucg_riotos_t *ucg_riot_ptr = ucg_GetUserPtr(ucg); + + /* assert that user_ptr is correctly set */ + assert(ucg_riot_ptr != NULL); + + spi_t dev = SPI_DEV(ucg_riot_ptr->device_index); switch (msg) { case UCG_COM_MSG_POWER_UP: /* setup pins */ - ucg_enable_pins(ucg->pin_list, ucg->pins_enabled); + _enable_pins(ucg_riot_ptr); - /* setup Arduino SPI */ + /* setup SPI */ spi_init_pins(dev); spi_acquire(dev, GPIO_UNDEF, SPI_MODE_0, ucg_serial_clk_speed_to_spi_speed(((ucg_com_info_t *)data)->serial_clk_speed)); @@ -89,18 +100,18 @@ int16_t ucg_com_riotos_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *da xtimer_usleep(arg); break; case UCG_COM_MSG_CHANGE_RESET_LINE: - if (ucg->pins_enabled & (1 << UCG_PIN_RST)) { - gpio_write(ucg->pin_list[UCG_PIN_RST], arg); + if (ucg_riot_ptr != NULL && ucg_riot_ptr->pin_reset != GPIO_UNDEF) { + gpio_write(ucg_riot_ptr->pin_reset, arg); } break; case UCG_COM_MSG_CHANGE_CS_LINE: - if (ucg->pins_enabled & (1 << UCG_PIN_CS)) { - gpio_write(ucg->pin_list[UCG_PIN_CS], arg); + if (ucg_riot_ptr != NULL && ucg_riot_ptr->pin_cs != GPIO_UNDEF) { + gpio_write(ucg_riot_ptr->pin_cs, arg); } break; case UCG_COM_MSG_CHANGE_CD_LINE: - if (ucg->pins_enabled & (1 << UCG_PIN_CD)) { - gpio_write(ucg->pin_list[UCG_PIN_CD], arg); + if (ucg_riot_ptr != NULL && ucg_riot_ptr->pin_cd != GPIO_UNDEF) { + gpio_write(ucg_riot_ptr->pin_cd, arg); } break; case UCG_COM_MSG_SEND_BYTE: @@ -127,8 +138,8 @@ int16_t ucg_com_riotos_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *da case UCG_COM_MSG_SEND_CD_DATA_SEQUENCE: while (arg--) { if (*data != 0) { - if (ucg->pins_enabled & (1 << UCG_PIN_CD)) { - gpio_write(ucg->pin_list[UCG_PIN_CD], *data); + if (ucg_riot_ptr != NULL && ucg_riot_ptr->pin_cd != GPIO_UNDEF) { + gpio_write(ucg_riot_ptr->pin_cd, *data); } } @@ -141,9 +152,9 @@ int16_t ucg_com_riotos_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *da return 1; } -#endif /* SPI_NUMOF */ +#endif /* MODULE_PERIPH_SPI */ -ucg_int_t ucg_dev_dummy_cb(ucg_t *ucg, ucg_int_t msg, void *data) +ucg_int_t ucg_dev_dummy_riotos(ucg_t *ucg, ucg_int_t msg, void *data) { static uint32_t pixels; diff --git a/pkg/ucglib/contrib/ucg_riotos.h b/pkg/ucglib/contrib/ucg_riotos.h new file mode 100644 index 0000000000..9e6c87069b --- /dev/null +++ b/pkg/ucglib/contrib/ucg_riotos.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 Bas Stottelaar + * + * 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 pkg_ucglib + * @{ + * + * @file + * @brief Ucglib driver for interacting with RIOT-OS peripherals + * + * @author Bas Stottelaar + + * + * @} + */ + +#ifndef UCG_RIOTOS_H +#define UCG_RIOTOS_H + +#include "ucg.h" + +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Holds RIOT-OS specific peripheral data. + * + * This structure has to be set via the Ucglib function @p ucg_SetUserPtr, + * prior to the call to @p ucg_Init. + * + * The structure can be easily extended with further required definitions (e.g + * other pins) if necessary, without breaking the RIOT-OS adaptation of Ucglib. + */ +typedef struct { + void *user_ptr; /**< Pointer to optionally store any additional user-data */ + + unsigned int device_index; /**< Index of the SPI device */ + gpio_t pin_cs; /**< Pin for SPI CS, GPIO_UNDEF if not used */ + gpio_t pin_cd; /**< Pin for SPI CD, GPIO_UNDEF if not used */ + gpio_t pin_reset; /**< Pin for RESET, GPIO_UNDEF if not used */ +} ucg_riotos_t; + +/** + * To be used as the u8x8_msg_cb as gpio_and_delay_cb in u8x8_Setup() for use with RIOT-OS + */ +int16_t ucg_com_hw_spi_riotos(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data); + +/** + * To be used as the u8x8_msg_cb as gpio_and_delay_cb in u8x8_Setup() for use with RIOT-OS. + */ +ucg_int_t ucg_dev_dummy_riotos(ucg_t *ucg, ucg_int_t msg, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* UCG_RIOTOS_H */ diff --git a/pkg/ucglib/patches/0001-add-RIOT-OS-interface.patch b/pkg/ucglib/patches/0001-add-RIOT-OS-interface.patch deleted file mode 100644 index 0dccbf1ba6..0000000000 --- a/pkg/ucglib/patches/0001-add-RIOT-OS-interface.patch +++ /dev/null @@ -1,88 +0,0 @@ -From a3187bd1bbf0d11f73d6108daff89f7ab009dd35 Mon Sep 17 00:00:00 2001 -From: Bas Stottelaar -Date: Fri, 2 Mar 2018 00:16:43 +0100 -Subject: [PATCH 1/1] add RIOT-OS interface. - ---- - csrc/ucg.h | 29 +++++++++++++++++++---------- - 1 file changed, 19 insertions(+), 10 deletions(-) - -diff --git a/csrc/ucg.h b/csrc/ucg.h -index c070a77..553562c 100644 ---- a/csrc/ucg.h -+++ b/csrc/ucg.h -@@ -84,17 +84,19 @@ - #include - #include - -+#include "periph/gpio.h" -+ - - #ifdef __cplusplus - extern "C" - { - #endif - --#if defined(ARDUINO) --#ifndef USE_PIN_LIST -+//#if defined(ARDUINO) -+//#ifndef USE_PIN_LIST - #define USE_PIN_LIST --#endif --#endif -+//#endif -+//#endif - - #ifdef __GNUC__ - # define UCG_NOINLINE __attribute__((noinline)) -@@ -413,12 +415,14 @@ struct _ucg_t - - /* only for Arduino/C++ Interface */ - #ifdef USE_PIN_LIST -- uint8_t pin_list[UCG_PIN_COUNT]; -+ gpio_t* pin_list; -+ uint32_t pins_enabled; -+ uint32_t dev; - --#ifdef __AVR__ -- volatile uint8_t *data_port[UCG_PIN_COUNT]; -- uint8_t data_mask[UCG_PIN_COUNT]; --#endif -+//#ifdef __AVR__ -+// volatile uint8_t *data_port[UCG_PIN_COUNT]; -+// uint8_t data_mask[UCG_PIN_COUNT]; -+//#endif - - #endif - -@@ -434,6 +438,9 @@ struct _ucg_t - - }; - -+#define ucg_SetPins(ucg,pins,pins_enabled) {(ucg)->pin_list = (pins); (ucg)->pins_enabled = (pins_enabled);} -+#define ucg_SetDevice(ucg,device) ((ucg)->dev = device) -+ - #define ucg_GetWidth(ucg) ((ucg)->dimension.w) - #define ucg_GetHeight(ucg) ((ucg)->dimension.h) - -@@ -574,6 +581,7 @@ ucg_int_t ucg_Init(ucg_t *ucg, ucg_dev_fnptr device_cb, ucg_dev_fnptr ext_cb, uc - /*================================================*/ - /* ucg_dev_sdl.c */ - ucg_int_t ucg_sdl_dev_cb(ucg_t *ucg, ucg_int_t msg, void *data); -+int ucg_sdl_get_key(void); - - /*================================================*/ - /* ucg_pixel.c */ -@@ -2172,7 +2180,8 @@ extern const ucg_fntpgm_uint8_t ucg_font_osr41_tr[] UCG_FONT_SECTION("ucg_font_o - - #endif - -- -+int16_t ucg_com_riotos_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data); -+ucg_int_t ucg_dev_dummy_cb(ucg_t *ucg, ucg_int_t msg, void *data); - - #ifdef __cplusplus - } --- -2.14.2 -