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 | Bin 2164 -> 0 bytes 7 files changed, 133 insertions(+), 57 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 0dccbf1ba6cedcadeac1c259e6980c41836866b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2164 zcmbtV+iu%95Pj!Y4AK`XvTRYlCTW9Yol6b0b`U$e4?#dkB4u+cOM*nF3A*|B9nz9* z#qC2;!548jm&0?0{f7gt`V9;vydYxY13o)77?{+oPS}Z}3P>a8~0B6{3 zBFVP?JAsP}0v}`&#%nI%W1%>%ytO=kXXGL>Mq+P$k1~r^#27+`5+^*2ZrNlyo_rZku5p#V zQn?J)N-)-FB&kedT#RKA&2pD^n$!ckOM6Y)MV_Hh`8rgey#)t!e-fGAcWHMo~EYzb$rzsmvA13psGhzd1b(lKd`WT}Q z?0B2Vf{DZrV!`V(Ts)tZ8f^r<{QDlMz^cz_>?_^dRrzD?E1zX)eh6R>q;XpL#kT{L z`)X9}v#Exv{9Zj1P~rM@#k$&6KN`_G-DV#(>kONEYrK~XP_#GAi(U1X)^aA)9d7Oh zzBf^e!u(XUTJS?pSk8GR6MTY(cC*f4H?x(Yn%%~qy&Y7$63;RerXK2quNE}QR5->A zrB(0AeW15O{UfbE);+I`IE2M#RXXBvW~bmW9Fl2|PJUE5V)e={Fy}b8vrY0J>Je@q#ehsSXb9 zWlF49r8y|Gx;J)pt>PFI`EKE z+oMCbIn>ma$7zW7$Oc4|sBE!fRom-DL@9Eg7I~L4l|Me2W9w!*nX}pTXg;1!8b>=X zjd*t^o3+t?DI8v?ESITD3%2~uicHohLKcjtAxM`uBR|&y<47M(TgK{~Yd!dSwR%N) cYbkebhpcOy)%mb@y}aSA2gGa9Zp$O&e