Skip to content

Commit

Permalink
Merge pull request #8623 from basilfx/feature/pkg_ucglib
Browse files Browse the repository at this point in the history
pkg: ucglib: add support for color graphics library
  • Loading branch information
basilfx committed Apr 5, 2018
2 parents afe44e3 + bfccf31 commit ec564c0
Show file tree
Hide file tree
Showing 14 changed files with 1,868 additions and 0 deletions.
15 changes: 15 additions & 0 deletions pkg/ucglib/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
PKG_NAME=ucglib
PKG_URL=https://github.com/olikraus/ucglib
PKG_VERSION=bf48515702dd7c87cbacdd17989738f33f003df2
PKG_LICENSE=BSD-2-Clause

.PHONY: all

all: git-download
cp $(RIOTBASE)/pkg/ucglib/src/Makefile $(PKG_BUILDDIR)/Makefile
cp $(RIOTBASE)/pkg/ucglib/src/csrc/Makefile $(PKG_BUILDDIR)/csrc/Makefile
cp $(RIOTBASE)/pkg/ucglib/src/csrc/ucg_riotos.c $(PKG_BUILDDIR)/csrc/ucg_riotos.c
cp $(RIOTBASE)/pkg/ucglib/src/sys/sdl/dev/Makefile $(PKG_BUILDDIR)/sys/sdl/dev/Makefile
"$(MAKE)" -C $(PKG_BUILDDIR)

include $(RIOTBASE)/pkg/pkg.mk
6 changes: 6 additions & 0 deletions pkg/ucglib/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
INCLUDES += -I$(PKGDIRBASE)/ucglib/csrc

# Link SDL if enabled.
ifneq (,$(filter ucglib_sdl,$(USEMODULE)))
LINKFLAGS += `sdl2-config --libs`
endif
57 changes: 57 additions & 0 deletions pkg/ucglib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Ucglib

## Introduction
[Ucglib](https://github.com/olikraus/ucglib) is a color graphics library for LCDs and OLEDs. It contains both drivers and high-level drawing routines.

The library is originally written for Arduino boards, but it runs just fine on other platforms, as long as the right drivers are available.

## Usage
Just put `USEPKG += ucglib` in your Makefile and `#include "ucg.h"` to your code. Refer to the [Ucglib wiki](https://github.com/olikraus/ucglib/wiki) for more information on the API.

## RIOT-OS interface
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`

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.

* `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.

### Example
```
ucg_t ucg;
gpio_t pins[] = {
[UCG_PIN_CS] = GPIO(PA, 0),
[UCG_PIN_CD] = GPIO(PA, 1),
[UCG_PIN_RESET] = GPIO(PA, 2)
};
uint32_t bitmap = (
(1 << UCG_PIN_CS) +
(1 << UCG_PIN_CD) +
(1 << UCG_PIN_RESET)
);
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);
```

## 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.

* 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
```
ucg_t ucg;
ucg_Init(&ucg, ucg_sdl_dev_cb, ucg_ext_none, NULL);
```
6 changes: 6 additions & 0 deletions pkg/ucglib/doc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @defgroup pkg_ucglib Color graphics library for embedded systems
* @ingroup pkg
* @brief Provides a color graphics library for OLED and LCD displays
* @see https://github.com/olikraus/ucglib
*/
88 changes: 88 additions & 0 deletions pkg/ucglib/patches/0001-add-RIOT-OS-interface.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
From a3187bd1bbf0d11f73d6108daff89f7ab009dd35 Mon Sep 17 00:00:00 2001
From: Bas Stottelaar <basstottelaar@gmail.com>
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 <stdint.h>
#include <stddef.h>

+#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

19 changes: 19 additions & 0 deletions pkg/ucglib/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
MODULE = pkg-ucglib

DIRS += csrc

# SDL can be used as a virtual display, but is for native target only.
ifneq (,$(filter ucglib_sdl,$(USEMODULE)))
DIRS += sys/sdl/dev
endif

# Compiling Ucglib will generate a lot of compiler warnings, which are treated
# as errors. For the sake of simplicity, ignore them.
CFLAGS += -Wno-empty-translation-unit \
-Wno-newline-eof \
-Wno-unused-parameter \
-Wno-unused \
-Wno-overlength-strings \
-Wno-pointer-arith

include $(RIOTBASE)/Makefile.base
3 changes: 3 additions & 0 deletions pkg/ucglib/src/csrc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = ucglib

include $(RIOTBASE)/Makefile.base
173 changes: 173 additions & 0 deletions pkg/ucglib/src/csrc/ucg_riotos.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
* Copyright (C) 2018 Bas Stottelaar <basstottelaar@gmail.com>
*
* 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 to interact with RIOT-OS drivers.
*
* @author Bas Stottelaar <basstottelaar@gmail.com>
*
* @}
*/

#include "ucg.h"

#include "xtimer.h"

#include "periph/spi.h"
#include "periph/i2c.h"
#include "periph/gpio.h"

#include <stdio.h>

#ifdef SPI_NUMOF
static spi_clk_t ucg_serial_clk_speed_to_spi_speed(uint32_t serial_clk_speed)
{
if (serial_clk_speed < 100) {
return SPI_CLK_10MHZ;
}
else if (serial_clk_speed < 200) {
return SPI_CLK_5MHZ;
}
else if (serial_clk_speed < 1000) {
return SPI_CLK_1MHZ;
}
else if (serial_clk_speed < 2500) {
return SPI_CLK_400KHZ;
}

return SPI_CLK_100KHZ;
}
#endif /* SPI_NUMOF */

static void ucg_enable_pins(gpio_t *pins, uint32_t pins_enabled)
{
uint8_t i;

for (i = 0; i < 32; i++) {
if (pins_enabled & (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);
}
}
}
}
}

#ifdef SPI_NUMOF
int16_t ucg_com_riotos_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data)
{
spi_t dev = (spi_t) ucg->dev;

switch (msg) {
case UCG_COM_MSG_POWER_UP:
/* setup pins */
ucg_enable_pins(ucg->pin_list, ucg->pins_enabled);

/* setup Arduino 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));

break;
case UCG_COM_MSG_POWER_DOWN:
spi_release(dev);
break;
case UCG_COM_MSG_DELAY:
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);
}
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);
}
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);
}
break;
case UCG_COM_MSG_SEND_BYTE:
spi_transfer_byte(dev, GPIO_UNDEF, true, (uint8_t) arg);
break;
case UCG_COM_MSG_REPEAT_1_BYTE:
while (arg--) {
spi_transfer_byte(dev, GPIO_UNDEF, true, ((uint8_t *) data)[0]);
}
break;
case UCG_COM_MSG_REPEAT_2_BYTES:
while (arg--) {
spi_transfer_bytes(dev, GPIO_UNDEF, true, data, NULL, 2);
}
break;
case UCG_COM_MSG_REPEAT_3_BYTES:
while (arg--) {
spi_transfer_bytes(dev, GPIO_UNDEF, true, data, NULL, 3);
}
break;
case UCG_COM_MSG_SEND_STR:
spi_transfer_bytes(dev, GPIO_UNDEF, true, data, NULL, arg);
break;
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);
}
}

data++;
spi_transfer_bytes(dev, GPIO_UNDEF, true, data, NULL, 1);
data++;
}
break;
}

return 1;
}
#endif /* SPI_NUMOF */

ucg_int_t ucg_dev_dummy_cb(ucg_t *ucg, ucg_int_t msg, void *data)
{
static uint32_t pixels;

switch (msg) {
case UCG_MSG_DEV_POWER_UP:
puts("ucg: UCG_MSG_DEV_POWER_UP");
return 1;
case UCG_MSG_DEV_POWER_DOWN:
puts("ucg: UCG_MSG_DEV_POWER_DOWN");
return 1;
case UCG_MSG_GET_DIMENSION:
puts("ucg: UCG_MSG_GET_DIMENSION");
((ucg_wh_t *)data)->w = 128;
((ucg_wh_t *)data)->h = 128;
return 1;
case UCG_MSG_DRAW_PIXEL:
pixels++;

/* log each 128th draw */
if (pixels % 128 == 0) {
printf("ucg: UCG_MSG_DRAW_PIXEL (%" PRIu32 ")\n", pixels);
}

return 1;
}
return ucg_dev_default_cb(ucg, msg, data);
}
5 changes: 5 additions & 0 deletions pkg/ucglib/src/sys/sdl/dev/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MODULE = ucglib_sdl

CFLAGS += `sdl2-config --cflags`

include $(RIOTBASE)/Makefile.base
Loading

0 comments on commit ec564c0

Please sign in to comment.