diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index d00bd76b07..84dc17307d 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -244,7 +244,3 @@ ifneq (,$(filter-out netdev_default, $(filter netdev_%,$(USEMODULE)))) USEMODULE += netdev_register endif endif - -ifneq (,$(filter st7735,$(USEMODULE))) - USEMODULE += lcd -endif diff --git a/drivers/ili9341/Kconfig b/drivers/ili9341/Kconfig index 578d563474..fbe7285f02 100644 --- a/drivers/ili9341/Kconfig +++ b/drivers/ili9341/Kconfig @@ -12,6 +12,7 @@ config MODULE_ILI9341 depends on TEST_KCONFIG select MODULE_PERIPH_SPI select MODULE_PERIPH_GPIO + select MODULE_LCD select MODULE_ZTIMER select MODULE_ZTIMER_MSEC @@ -55,12 +56,4 @@ config ILI9341_VCOML match the capacitance and performance specifications of the TFT panel to maximize contrast and minimize flickering -config ILI9341_LE_MODE - bool "Enable little endian to big endian conversion" - help - Enable this configuration to convert little endian colors to big endian. - ILI9341 device requires colors to be send in big endian RGB-565 format. - Enabling this option allows for little endian colors. Enabling this - however will slow down the driver as it cannot use DMA anymore. - endif # KCONFIG_USEMODULE_ILI9341 diff --git a/drivers/ili9341/Makefile.dep b/drivers/ili9341/Makefile.dep index 51cd0c5e32..b92a0fe449 100644 --- a/drivers/ili9341/Makefile.dep +++ b/drivers/ili9341/Makefile.dep @@ -1,4 +1,5 @@ FEATURES_REQUIRED += periph_spi FEATURES_REQUIRED += periph_gpio +USEMODULE += lcd USEMODULE += ztimer USEMODULE += ztimer_msec diff --git a/drivers/ili9341/ili9341.c b/drivers/ili9341/ili9341.c index d07d4cf736..46e2bf6b0f 100644 --- a/drivers/ili9341/ili9341.c +++ b/drivers/ili9341/ili9341.c @@ -27,21 +27,22 @@ #include "ili9341.h" #include "ili9341_internal.h" +#include "lcd.h" +#include "lcd_internal.h" #define ENABLE_DEBUG 0 #include "debug.h" -static void _ili9341_spi_acquire(const ili9341_t *dev) -{ - spi_acquire(dev->params->spi, dev->params->cs_pin, dev->params->spi_mode, - dev->params->spi_clk); -} - -static void _ili9341_cmd_start(const ili9341_t *dev, uint8_t cmd, bool cont) +static void _write_cmd(const lcd_t *dev, uint8_t cmd, const uint8_t *data, + size_t len) { gpio_clear(dev->params->dcx_pin); - spi_transfer_byte(dev->params->spi, dev->params->cs_pin, cont, cmd); + spi_transfer_byte(dev->params->spi, dev->params->cs_pin, len ? true : false, cmd); gpio_set(dev->params->dcx_pin); + if (len) { + spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, data, + NULL, len); + } } /* datasheet page 178, table converted to equation. @@ -61,32 +62,8 @@ static uint8_t _ili9341_calc_vml(int16_t vcoml) return (vcoml + 2500) / 25; } -static void _write_cmd(const ili9341_t *dev, uint8_t cmd, const uint8_t *data, - size_t len) -{ - _ili9341_cmd_start(dev, cmd, len ? true : false); - if (len) { - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, data, - NULL, len); - } -} -static void _ili9341_set_area(const ili9341_t *dev, uint16_t x1, uint16_t x2, - uint16_t y1, uint16_t y2) -{ - be_uint16_t params[2]; - - params[0] = byteorder_htons(x1); - params[1] = byteorder_htons(x2); - _write_cmd(dev, ILI9341_CMD_CASET, (uint8_t *)params, - sizeof(params)); - params[0] = byteorder_htons(y1); - params[1] = byteorder_htons(y2); - _write_cmd(dev, ILI9341_CMD_PASET, (uint8_t *)params, - sizeof(params)); -} - -int ili9341_init(ili9341_t *dev, const ili9341_params_t *params) +static int _init(lcd_t *dev, const lcd_params_t *params) { assert(params->lines >= 16 && params->lines <= 320 && !(params->lines & 0x7)); dev->params = params; @@ -107,215 +84,102 @@ int ili9341_init(ili9341_t *dev, const ili9341_params_t *params) ztimer_sleep(ZTIMER_MSEC, 120); /* Acquire once at release at the end */ - _ili9341_spi_acquire(dev); + spi_acquire(dev->params->spi, dev->params->cs_pin, dev->params->spi_mode, + dev->params->spi_clk); + /* Soft Reset */ - _write_cmd(dev, ILI9341_CMD_SWRESET, NULL, 0); + _write_cmd(dev, LCD_CMD_SWRESET, NULL, 0); ztimer_sleep(ZTIMER_MSEC, 120); /* Display off */ - _write_cmd(dev, ILI9341_CMD_DISPOFF, NULL, 0); + _write_cmd(dev, LCD_CMD_DISPOFF, NULL, 0); /* PWRCTL1/2 */ command_params[0] = _ili9341_calc_pwrctl1(CONFIG_ILI9341_GVDD); - _write_cmd(dev, ILI9341_CMD_PWCTRL1, command_params, 1); + _write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 1); command_params[0] = 0x10; /* PWRCTL 0 0 0 */ - _write_cmd(dev, ILI9341_CMD_PWCTRL2, command_params, 1); + _write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1); /* VCOMCTL */ command_params[0] = _ili9341_calc_vmh(CONFIG_ILI9341_VCOMH); command_params[1] = _ili9341_calc_vml(CONFIG_ILI9341_VCOML); - _write_cmd(dev, ILI9341_CMD_VMCTRL1, command_params, 2); + _write_cmd(dev, LCD_CMD_VMCTRL1, command_params, 2); command_params[0] = 0x86; - _write_cmd(dev, ILI9341_CMD_VMCTRL2, command_params, 1); + _write_cmd(dev, LCD_CMD_VMCTRL2, command_params, 1); /* Memory access CTL */ command_params[0] = dev->params->rotation; - command_params[0] |= dev->params->rgb ? 0 : ILI9341_MADCTL_BGR; - _write_cmd(dev, ILI9341_CMD_MADCTL, command_params, 1); + command_params[0] |= dev->params->rgb ? 0 : LCD_MADCTL_BGR; + _write_cmd(dev, LCD_CMD_MADCTL, command_params, 1); /* Frame control */ command_params[0] = 0x00; command_params[1] = 0x18; - _write_cmd(dev, ILI9341_CMD_FRAMECTL1, command_params, 2); + _write_cmd(dev, LCD_CMD_FRAMECTL1, command_params, 2); /* Display function control */ command_params[0] = 0x08; command_params[1] = 0x82; /* number of lines, see datasheet p. 166 (DISCTRL::NL) */ command_params[2] = (params->lines >> 3) - 1; - _write_cmd(dev, ILI9341_CMD_DFUNC, command_params, 3); + _write_cmd(dev, LCD_CMD_DFUNC, command_params, 3); /* Pixel format */ command_params[0] = 0x55; /* 16 bit mode */ - _write_cmd(dev, ILI9341_CMD_PIXSET, command_params, 1); + _write_cmd(dev, LCD_CMD_PIXSET, command_params, 1); command_params[0] = 0x01; - _write_cmd(dev, ILI9341_CMD_GAMSET, command_params, 1); + _write_cmd(dev, LCD_CMD_GAMSET, command_params, 1); /* Gamma correction */ { static const uint8_t gamma_pos[] = { - 0x0F, - 0x31, - 0x2B, - 0x0C, - 0x0E, - 0x08, - 0x4E, - 0xF1, - 0x37, - 0x07, - 0x10, - 0x03, - 0x0E, - 0x09, - 0x00 + 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, + 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00 }; - _write_cmd(dev, ILI9341_CMD_PGAMCTRL, gamma_pos, + _write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos, sizeof(gamma_pos)); } { static const uint8_t gamma_neg[] = { - 0x00, - 0x0E, - 0x14, - 0x03, - 0x11, - 0x07, - 0x31, - 0xC1, - 0x48, - 0x08, - 0x0F, - 0x0C, - 0x31, - 0x36, - 0x0F + 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, + 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F }; - _write_cmd(dev, ILI9341_CMD_NGAMCTRL, gamma_neg, + _write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg, sizeof(gamma_neg)); } if (dev->params->inverted) { - _write_cmd(dev, ILI9341_CMD_DINVON, NULL, 0); + _write_cmd(dev, LCD_CMD_DINVON, NULL, 0); } /* Sleep out (turn off sleep mode) */ - _write_cmd(dev, ILI9341_CMD_SLPOUT, NULL, 0); + _write_cmd(dev, LCD_CMD_SLPOUT, NULL, 0); /* Display on */ - _write_cmd(dev, ILI9341_CMD_DISPON, NULL, 0); + _write_cmd(dev, LCD_CMD_DISPON, NULL, 0); spi_release(dev->params->spi); return 0; } -void ili9341_write_cmd(const ili9341_t *dev, uint8_t cmd, const uint8_t *data, - size_t len) +static void _set_area(const lcd_t *dev, uint16_t x1, uint16_t x2, + uint16_t y1, uint16_t y2) { - _ili9341_spi_acquire(dev); - _write_cmd(dev, cmd, data, len); - spi_release(dev->params->spi); + be_uint16_t params[2]; + + params[0] = byteorder_htons(x1); + params[1] = byteorder_htons(x2); + + _write_cmd(dev, LCD_CMD_CASET, (uint8_t *)params, + sizeof(params)); + params[0] = byteorder_htons(y1); + params[1] = byteorder_htons(y2); + _write_cmd(dev, LCD_CMD_PASET, (uint8_t *)params, + sizeof(params)); } -void ili9341_read_cmd(const ili9341_t *dev, uint8_t cmd, uint8_t *data, size_t len) -{ - assert(len); - _ili9341_spi_acquire(dev); - _ili9341_cmd_start(dev, cmd, true); - /* Dummy transfer */ - spi_transfer_byte(dev->params->spi, dev->params->cs_pin, true, 0x00); - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, NULL, - data, len); - spi_release(dev->params->spi); -} - -void ili9341_fill(const ili9341_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, - uint16_t y2, uint16_t color) -{ - /* Send fill area to the display */ - - /* Calculate number of pixels */ - int32_t num_pix = (x2 - x1 + 1) * (y2 - y1 + 1); - - DEBUG("[ili9341]: Write x1: %" PRIu16 ", x2: %" PRIu16 ", " - "y1: %" PRIu16 ", y2: %" PRIu16 ". Num pixels: %lu\n", - x1, x2, y1, y2, (unsigned long)num_pix); - - /* Send fill area to the display */ - _ili9341_spi_acquire(dev); - - _ili9341_set_area(dev, x1, x2, y1, y2); - /* Memory access command */ - _ili9341_cmd_start(dev, ILI9341_CMD_RAMWR, true); - - if (IS_ACTIVE(CONFIG_ILI9341_LE_MODE)) { - color = htons(color); - } - - for (int i = 0; i < (num_pix - 1); i++) { - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, true, - (uint8_t *)&color, NULL, sizeof(color)); - } - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, - (uint8_t *)&color, NULL, sizeof(color)); - spi_release(dev->params->spi); -} - -void ili9341_pixmap(const ili9341_t *dev, uint16_t x1, uint16_t x2, - uint16_t y1, uint16_t y2, const uint16_t *color) -{ - size_t num_pix = (x2 - x1 + 1) * (y2 - y1 + 1); - - DEBUG("[ili9341]: Write x1: %" PRIu16 ", x2: %" PRIu16 ", " - "y1: %" PRIu16 ", y2: %" PRIu16 ". Num pixels: %lu\n", - x1, x2, y1, y2, (unsigned long)num_pix); - - _ili9341_spi_acquire(dev); - - /* Send fill area to the display */ - _ili9341_set_area(dev, x1, x2, y1, y2); - - /* Memory access command */ - _ili9341_cmd_start(dev, ILI9341_CMD_RAMWR, true); - - if (IS_ACTIVE(CONFIG_ILI9341_LE_MODE)) { - for (size_t i = 0; i < num_pix - 1; i++) { - uint16_t ncolor = htons(*(color + i)); - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, true, - &ncolor, NULL, sizeof(uint16_t)); - } - uint16_t ncolor = htons(*(color + num_pix - 1)); - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, - &ncolor, NULL, sizeof(uint16_t)); - } - else { - spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, - (const uint8_t *)color, NULL, num_pix * 2); - } - - spi_release(dev->params->spi); -} - -void ili9341_invert_on(const ili9341_t *dev) -{ - uint8_t command = (dev->params->inverted) ? ILI9341_CMD_DINVOFF - : ILI9341_CMD_DINVON; - - ili9341_write_cmd(dev, command, NULL, 0); -} - -void ili9341_invert_off(const ili9341_t *dev) -{ - uint8_t command = (dev->params->inverted) ? ILI9341_CMD_DINVON - : ILI9341_CMD_DINVOFF; - - ili9341_write_cmd(dev, command, NULL, 0); -} - -void ili9341_set_brightness(const ili9341_t *dev, uint8_t brightness) -{ - ili9341_write_cmd(dev, ILI9341_CMD_WRDISBV, &brightness, 1); - uint8_t param = 0x26; - ili9341_write_cmd(dev, ILI9341_CMD_WRCTRLD, ¶m, 1); -} +const lcd_driver_t lcd_ili9341_driver = { + .init = _init, + .set_area = _set_area, +}; diff --git a/drivers/ili9341/ili9341_disp_dev.c b/drivers/ili9341/ili9341_disp_dev.c deleted file mode 100644 index 66d3e124eb..0000000000 --- a/drivers/ili9341/ili9341_disp_dev.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2020 Inria - * - * 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_ili9341 - * @{ - * - * @file - * @brief Driver adaption to disp_dev generic interface - * - * @author Alexandre Abadie - * @} - */ - -#include -#include - -#include "ili9341.h" -#include "ili9341_disp_dev.h" - -#ifndef ILI9341_DISP_DEV_HEIGHT -#define ILI9341_DISP_DEV_HEIGHT (240U) -#endif - -#ifndef ILI9341_DISP_COLOR_DEPTH -#define ILI9341_DISP_COLOR_DEPTH (16U) -#endif - -static void _ili9341_map(const disp_dev_t *dev, uint16_t x1, uint16_t x2, - uint16_t y1, uint16_t y2, const uint16_t *color) -{ - ili9341_t *ili9341 = (ili9341_t *)dev; - ili9341_pixmap(ili9341, x1, x2, y1, y2, color); -} - -static uint16_t _ili9341_height(const disp_dev_t *disp_dev) -{ - (void)disp_dev; - return ILI9341_DISP_DEV_HEIGHT; -} - -static uint16_t _ili9341_width(const disp_dev_t *disp_dev) -{ - const ili9341_t *dev = (ili9341_t *)disp_dev; - assert(dev); - - return dev->params->lines; -} - -static uint8_t _ili9341_color_depth(const disp_dev_t *disp_dev) -{ - (void)disp_dev; - return ILI9341_DISP_COLOR_DEPTH; -} - -static void _ili9341_set_invert(const disp_dev_t *disp_dev, bool invert) -{ - const ili9341_t *dev = (ili9341_t *)disp_dev; - - assert(dev); - - if (invert) { - ili9341_invert_on(dev); - } - else { - ili9341_invert_off(dev); - } -} - -const disp_dev_driver_t ili9341_disp_dev_driver = { - .map = _ili9341_map, - .height = _ili9341_height, - .width = _ili9341_width, - .color_depth = _ili9341_color_depth, - .set_invert = _ili9341_set_invert, -}; diff --git a/drivers/ili9341/include/ili9341_disp_dev.h b/drivers/ili9341/include/ili9341_disp_dev.h deleted file mode 100644 index 25751524cf..0000000000 --- a/drivers/ili9341/include/ili9341_disp_dev.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019 Inria - * - * 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_ili9341 - * @{ - * - * @file - * @brief Definition of the driver for the disp_dev generic interface - * - * @author Alexandre Abadie - */ - -#ifndef ILI9341_DISP_DEV_H -#define ILI9341_DISP_DEV_H - -#include "disp_dev.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Reference to the display device driver struct - */ -extern const disp_dev_driver_t ili9341_disp_dev_driver; - -#ifdef __cplusplus -} -#endif - -#endif /* ILI9341_DISP_DEV_H */ diff --git a/drivers/ili9341/include/ili9341_internal.h b/drivers/ili9341/include/ili9341_internal.h index d04499c078..db6d38d686 100644 --- a/drivers/ili9341/include/ili9341_internal.h +++ b/drivers/ili9341/include/ili9341_internal.h @@ -25,48 +25,7 @@ extern "C" { #endif -/** - * @name ILI9341 commands - * - * Not exhaustive, please extend when required - * @{ - */ -#define ILI9341_CMD_SWRESET 0x01 /**< Software reset */ -#define ILI9341_CMD_RDDIDIF 0x04 /**< Read display ID */ -#define ILI9341_CMD_SPLIN 0x10 /**< Enter sleep mode */ -#define ILI9341_CMD_SLPOUT 0x11 /**< Sleep out */ -#define ILI9341_CMD_DINVOFF 0x20 /**< Display inversion off */ -#define ILI9341_CMD_DINVON 0x21 /**< Display inversion on */ - -#define ILI9341_CMD_GAMSET 0x26 /**< Gamma Set */ -#define ILI9341_CMD_DISPOFF 0x28 /**< Display OFF */ -#define ILI9341_CMD_DISPON 0x29 /**< Display ON */ -#define ILI9341_CMD_CASET 0x2A /**< Column Address Set */ -#define ILI9341_CMD_PASET 0x2b /**< Page Address Set */ -#define ILI9341_CMD_RAMWR 0x2c /**< Memory Write */ -#define ILI9341_CMD_RAMRD 0x2e /**< Memory Read */ -#define ILI9341_CMD_MADCTL 0x36 /**< Memory data access control */ -#define ILI9341_CMD_IDMOFF 0x38 /**< Idle Mode OFF */ -#define ILI9341_CMD_IDMON 0x39 /**< Idle Mode ON */ -#define ILI9341_CMD_PIXSET 0x3A /**< COLMOD: Pixel Format Set */ -#define ILI9341_CMD_WRDISBV 0x51 /**< Write Display Brightness */ -#define ILI9341_CMD_WRCTRLD 0x53 /**< Write Control Display */ -#define ILI9341_CMD_RDCTRLD 0x54 /**< Read Control Display */ -#define ILI9341_CMD_FRAMECTL1 0xb1 /**< Frame control normal*/ -#define ILI9341_CMD_FRAMECTL2 0xb2 /**< Frame control idle */ -#define ILI9341_CMD_FRAMECTL3 0xb3 /**< Frame control partial */ -#define ILI9341_CMD_DFUNC 0xb6 /**< Display function control */ -#define ILI9341_CMD_PWCTRL1 0xc0 /**< Power control 1 */ -#define ILI9341_CMD_PWCTRL2 0xc1 /**< Power control 2 */ -#define ILI9341_CMD_VMCTRL1 0xc5 /**< VCOM control 1 */ -#define ILI9341_CMD_VMCTRL2 0xc7 /**< VCOM control 2 */ -#define ILI9341_CMD_PGAMCTRL 0xe0 /**< Positive gamma correction */ -#define ILI9341_CMD_NGAMCTRL 0xe1 /**< Negative gamma correction */ -#define ILI9341_CMD_IFCTL 0xf6 /**< Interface control */ -/** @} */ - -#define ILI9341_PIXSET_16BIT 0x55 /**< MCU and RGB 16 bit interface */ -#define ILI9341_PIXSET_18BIT 0x66 /**< MCU and RGB 18 bit interface (not implemented) */ +#include "lcd_internal.h" #ifdef __cplusplus } diff --git a/drivers/ili9341/include/ili9341_params.h b/drivers/ili9341/include/ili9341_params.h index 6096195ef3..5bee356383 100644 --- a/drivers/ili9341/include/ili9341_params.h +++ b/drivers/ili9341/include/ili9341_params.h @@ -54,15 +54,20 @@ extern "C" { #ifndef ILI9341_PARAM_INVERTED #define ILI9341_PARAM_INVERTED 0 #endif - #ifndef ILI9341_PARAM_NUM_LINES -#define ILI9341_PARAM_NUM_LINES 320U +#define ILI9341_PARAM_NUM_LINES 320U /**< Number of lines */ +#endif +#ifndef ILI9341_PARAM_RGB_CHANNELS +#define ILI9341_PARAM_RGB_CHANNELS 240U /**< Number of RGB channels (e.g. columns) */ #endif #ifndef ILI9341_PARAM_ROTATION -#define ILI9341_PARAM_ROTATION ILI9341_ROTATION_HORZ_FLIP +#define ILI9341_PARAM_ROTATION LCD_ROTATION_HORZ_FLIP #endif +/** + * @brief Default params + */ #ifndef ILI9341_PARAMS #define ILI9341_PARAMS { .spi = ILI9341_PARAM_SPI, \ .spi_clk = ILI9341_PARAM_SPI_CLK, \ @@ -74,14 +79,15 @@ extern "C" { .inverted = ILI9341_PARAM_INVERTED, \ .lines = ILI9341_PARAM_NUM_LINES, \ .rotation = ILI9341_PARAM_ROTATION, \ - } + .rgb_channels = ILI9341_PARAM_RGB_CHANNELS, \ +} #endif -/**@}*/ +/** @} */ /** * @brief Configure ILI9341 */ -static const ili9341_params_t ili9341_params[] = +static const lcd_params_t ili9341_params[] = { ILI9341_PARAMS, }; @@ -101,8 +107,19 @@ static const uint8_t ili9341_screen_ids[] = ILI9341_PARAM_SCREEN_IDS, }; +/** + * @brief Define the number of configured displays + */ +#define ILI9341_NUMOF ARRAY_SIZE(ili9341_params) +/** + * @brief Define the number screens this display driver is attached to + */ +#define ILI9341_SCREEN_NUMOF ARRAY_SIZE(ili9341_screen_ids) + + #ifdef __cplusplus } #endif #endif /* ILI9341_PARAMS_H */ +/** @} */ diff --git a/drivers/include/ili9341.h b/drivers/include/ili9341.h index 8c41c0cd33..01d8a9aa10 100644 --- a/drivers/include/ili9341.h +++ b/drivers/include/ili9341.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2018 Koen Zandberg + * 2021 Francisco Molina * * 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 @@ -13,17 +14,16 @@ * @brief Driver for the ILI9341 display * * @{ - * * @file - * @brief Driver for ili941 display * * @author Koen Zandberg + * @author Francisco Molina * * The ILI9341 is a generic display driver for small RGB displays. The driver * implemented here operates over SPI to communicate with the device. * * The device requires colors to be send in big endian RGB-565 format. The - * @ref CONFIG_ILI9341_LE_MODE compile time option can switch this, but only use this + * @ref CONFIG_LCD_LE_MODE compile time option can switch this, but only use this * when strictly necessary. This option will slow down the driver as it * certainly can't use DMA anymore, every short has to be converted before * transfer. @@ -32,8 +32,7 @@ #ifndef ILI9341_H #define ILI9341_H -#include "periph/spi.h" -#include "periph/gpio.h" +#include "lcd.h" #ifdef MODULE_DISP_DEV #include "disp_dev.h" @@ -43,11 +42,6 @@ extern "C" { #endif -/** - * @defgroup drivers_ili9341_config ILI9341 display driver compile configuration - * @ingroup config_drivers_display - * @{ - */ /** * @brief ILI9341 gvdd level. * @@ -82,158 +76,17 @@ extern "C" { #define CONFIG_ILI9341_VCOML -2000 #endif -/** - * @brief Convert little endian colors to big endian. - * - * Compile time switch to change the driver to convert little endian - * colors to big endian. - */ -#ifdef DOXYGEN -#define CONFIG_ILI9341_LE_MODE -#endif -/** @} */ - -/** - * @name Memory access control bits - * @{ - */ -#define ILI9341_MADCTL_MY 0x80 /**< Row address order */ -#define ILI9341_MADCTL_MX 0x40 /**< Column access order */ -#define ILI9341_MADCTL_MV 0x20 /**< Row column exchange */ -#define ILI9341_MADCTL_ML 0x10 /**< Vertical refresh order */ -#define ILI9341_MADCTL_BGR 0x08 /**< Color selector switch control */ -#define ILI9341_MADCTL_MH 0x04 /**< Horizontal refresh direction */ -/** @} */ - -/** - * @name Display rotation modes - * @{ - */ -#define ILI9341_MADCTL_VERT ILI9341_MADCTL_MX /**< Vertical mode */ -#define ILI9341_MADCTL_VERT_FLIP ILI9341_MADCTL_MY /**< Flipped vertical */ -#define ILI9341_MADCTL_HORZ ILI9341_MADCTL_MV /**< Horizontal mode */ -#define ILI9341_MADCTL_HORZ_FLIP ILI9341_MADCTL_MV | \ - ILI9341_MADCTL_MY | \ - ILI9341_MADCTL_MX /**< Horizontal flipped */ -/** @} */ - -/** - * @brief Display rotation mode - */ -typedef enum { - ILI9341_ROTATION_VERT = ILI9341_MADCTL_VERT, /**< Vertical mode */ - ILI9341_ROTATION_VERT_FLIP = ILI9341_MADCTL_VERT_FLIP, /**< Vertical flipped mode */ - ILI9341_ROTATION_HORZ = ILI9341_MADCTL_HORZ, /**< Horizontal mode */ - ILI9341_ROTATION_HORZ_FLIP = ILI9341_MADCTL_HORZ_FLIP, /**< Horizontal flipped mode */ -} ili9341_rotation_t; - -/** - * @brief Device initialization parameters - */ -typedef struct { - spi_t spi; /**< SPI device that the display is connected to */ - spi_clk_t spi_clk; /**< SPI clock speed to use */ - spi_mode_t spi_mode; /**< SPI mode */ - gpio_t cs_pin; /**< pin connected to the CHIP SELECT line */ - gpio_t dcx_pin; /**< pin connected to the DC line */ - gpio_t rst_pin; /**< pin connected to the reset line */ - bool rgb; /**< True when display is connected in RGB mode - * False when display is connected in BGR mode */ - bool inverted; /**< Display works in inverted color mode */ - uint16_t lines; /**< Number of lines, from 16 to 320 in 8 line steps */ - ili9341_rotation_t rotation; /**< Display rotation mode */ -} ili9341_params_t; - /** * @brief Device descriptor for a ili9341 */ typedef struct { -#ifdef MODULE_DISP_DEV - disp_dev_t *dev; /**< Pointer to the generic display device */ -#endif - const ili9341_params_t *params; /**< Device initialization parameters */ + lcd_t dev; /**< Pointer to the common lcd device */ } ili9341_t; /** - * @brief Setup an ili9341 display device - * - * @param[out] dev device descriptor - * @param[in] params parameters for device initialization + * @brief LCD device operations table */ -int ili9341_init(ili9341_t *dev, const ili9341_params_t *params); - -/** - * @brief Fill a rectangular area with a single pixel color - * - * the rectangular area is defined as x1 being the first column of pixels and - * x2 being the last column of pixels to fill. similar to that, y1 is the first - * row to fill and y2 is the last row to fill. - * - * @param[in] dev device descriptor - * @param[in] x1 x coordinate of the first corner - * @param[in] x2 x coordinate of the opposite corner - * @param[in] y1 y coordinate of the first corner - * @param[in] y2 y coordinate of the opposite corner - * @param[in] color single color to fill the area with - */ -void ili9341_fill(const ili9341_t *dev, uint16_t x1, uint16_t x2, - uint16_t y1, uint16_t y2, uint16_t color); - -/** - * @brief Fill a rectangular area with an array of pixels - * - * the rectangular area is defined as x1 being the first column of pixels and - * x2 being the last column of pixels to fill. similar to that, y1 is the first - * row to fill and y2 is the last row to fill. - * - * @note @p color must have a length equal to `(x2 - x1 + 1) * (y2 - y1 + 1)` - * - * @param[in] dev device descriptor - * @param[in] x1 x coordinate of the first corner - * @param[in] x2 x coordinate of the opposite corner - * @param[in] y1 y coordinate of the first corner - * @param[in] y2 y coordinate of the opposite corner - * @param[in] color array of colors to fill the area with - */ -void ili9341_pixmap(const ili9341_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, - uint16_t y2, const uint16_t *color); - -/** - * @brief Raw write command - * - * @param[in] dev device descriptor - * @param[in] cmd command code - * @param[in] data command data to the device - * @param[in] len length of the command data - */ -void ili9341_write_cmd(const ili9341_t *dev, uint8_t cmd, const uint8_t *data, - size_t len); - -/** - * @brief Raw read command - * - * @pre len > 0 - * - * @param[in] dev device descriptor - * @param[in] cmd command - * @param[out] data data from the device - * @param[in] len length of the returned data - */ -void ili9341_read_cmd(const ili9341_t *dev, uint8_t cmd, uint8_t *data, size_t len); - -/** - * @brief Invert the display colors - * - * @param[in] dev device descriptor - */ -void ili9341_invert_on(const ili9341_t *dev); - -/** - * @brief Disable color inversion - * - * @param[in] dev device descriptor - */ -void ili9341_invert_off(const ili9341_t *dev); +extern const lcd_driver_t lcd_ili9341_driver; #ifdef __cplusplus } diff --git a/drivers/include/lcd.h b/drivers/include/lcd.h index b3129fc606..c609d24a57 100644 --- a/drivers/include/lcd.h +++ b/drivers/include/lcd.h @@ -56,21 +56,57 @@ extern "C" { #define CONFIG_LCD_LE_MODE #endif +/** + * @name Memory access control bits + * @{ + */ +#define LCD_MADCTL_MY 0x80 /**< Row address order */ +#define LCD_MADCTL_MX 0x40 /**< Column access order */ +#define LCD_MADCTL_MV 0x20 /**< Row column exchange */ +#define LCD_MADCTL_ML 0x10 /**< Vertical refresh order */ +#define LCD_MADCTL_BGR 0x08 /**< Color selector switch control */ +#define LCD_MADCTL_MH 0x04 /**< Horizontal refresh direction */ +/** @} */ + +/** + * @name Display rotation modes + * @{ + */ +#define LCD_MADCTL_VERT LCD_MADCTL_MX /**< Vertical mode */ +#define LCD_MADCTL_VERT_FLIP LCD_MADCTL_MY /**< Flipped vertical */ +#define LCD_MADCTL_HORZ LCD_MADCTL_MV /**< Horizontal mode */ +#define LCD_MADCTL_HORZ_FLIP LCD_MADCTL_MV | \ + LCD_MADCTL_MY | \ + LCD_MADCTL_MX /**< Horizontal flipped */ +/** @} */ + + +/** + * @brief Display rotation mode + */ +typedef enum { + LCD_ROTATION_VERT = LCD_MADCTL_VERT, /**< Vertical mode */ + LCD_ROTATION_VERT_FLIP = LCD_MADCTL_VERT_FLIP, /**< Vertical flipped mode */ + LCD_ROTATION_HORZ = LCD_MADCTL_HORZ, /**< Horizontal mode */ + LCD_ROTATION_HORZ_FLIP = LCD_MADCTL_HORZ_FLIP, /**< Horizontal flipped mode */ +} lcd_rotation_t; + /** * @brief Device initialization parameters */ typedef struct { - spi_t spi; /**< SPI device that the display is connected to */ - spi_clk_t spi_clk; /**< SPI clock speed to use */ - spi_mode_t spi_mode;/**< SPI mode */ - gpio_t cs_pin; /**< pin connected to the CHIP SELECT line */ - gpio_t dcx_pin; /**< pin connected to the DC line */ - gpio_t rst_pin; /**< pin connected to the reset line */ - bool rgb; /**< True when display is connected in RGB mode - * False when display is connected in BGR mode */ - bool inverted; /**< Display works in inverted color mode */ - uint16_t lines; /**< Number of lines, from 16 to 320 in 8 line steps */ - uint16_t rgb_channels; /**< Display rgb channels */ + spi_t spi; /**< SPI device that the display is connected to */ + spi_clk_t spi_clk; /**< SPI clock speed to use */ + spi_mode_t spi_mode; /**< SPI mode */ + gpio_t cs_pin; /**< pin connected to the CHIP SELECT line */ + gpio_t dcx_pin; /**< pin connected to the DC line */ + gpio_t rst_pin; /**< pin connected to the reset line */ + bool rgb; /**< True when display is connected in RGB mode + * False when display is connected in BGR mode */ + bool inverted; /**< Display works in inverted color mode */ + uint16_t lines; /**< Number of lines, from 16 to 320 in 8 line steps */ + uint16_t rgb_channels; /**< Display rgb channels */ + lcd_rotation_t rotation; /**< Display rotation mode */ } lcd_params_t; /** @@ -145,7 +181,7 @@ int lcd_init(lcd_t *dev, const lcd_params_t *params); * @param[in] color single color to fill the area with */ void lcd_fill(const lcd_t *dev, uint16_t x1, uint16_t x2, - uint16_t y1, uint16_t y2, uint16_t color); + uint16_t y1, uint16_t y2, uint16_t color); /** * @brief Fill a rectangular area with an array of pixels @@ -164,7 +200,7 @@ void lcd_fill(const lcd_t *dev, uint16_t x1, uint16_t x2, * @param[in] color array of colors to fill the area with */ void lcd_pixmap(const lcd_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, - uint16_t y2, const uint16_t *color); + uint16_t y2, const uint16_t *color); /** * @brief Raw write command @@ -175,7 +211,7 @@ void lcd_pixmap(const lcd_t *dev, uint16_t x1, uint16_t x2, uint16_t y1, * @param[in] len length of the command data */ void lcd_write_cmd(const lcd_t *dev, uint8_t cmd, const uint8_t *data, - size_t len); + size_t len); /** * @brief Raw read command diff --git a/tests/driver_ili9341/Makefile b/tests/driver_ili9341/Makefile index aa686e9ba7..81e9ea2d9c 100644 --- a/tests/driver_ili9341/Makefile +++ b/tests/driver_ili9341/Makefile @@ -1,3 +1,4 @@ +<<<<<<< HEAD BOARD ?= stm32f429i-disc1 include ../Makefile.tests_common @@ -21,3 +22,6 @@ ifndef CONFIG_KCONFIG_USEMODULE_ILI9341 CFLAGS += -DCONFIG_NO_RIOT_IMAGE endif endif +======= +include Makefile.lcd +>>>>>>> b7c02ac672 (drivers/ili9341: use common lcd dirver) diff --git a/tests/driver_ili9341/main.c b/tests/driver_ili9341/main.c index 9e0d6a17c6..d3dc531bab 100644 --- a/tests/driver_ili9341/main.c +++ b/tests/driver_ili9341/main.c @@ -11,7 +11,7 @@ * @{ * * @file - * @brief Test application for the ili9431 tft display + * @brief Test application for lcd tft displays * * @author Koen Zandberg * @@ -22,16 +22,31 @@ #include "timex.h" #include "ztimer.h" #include "board.h" -#include "ili9341.h" -#include "ili9341_params.h" +#include "lcd.h" #include "riot_logo.h" +#if IS_USED(MODULE_ST7735) +#include "st7735.h" +#include "st7735_params.h" +#elif IS_USED(MODULE_ILI9341) +#include "ili9341.h" +#include "ili9341_params.h" +#else +#error "Include either module 'st7735' or 'ili9341'" +#endif + int main(void) { - ili9341_t dev; + lcd_t dev; - puts("ili9341 TFT display test application"); +#if IS_USED(MODULE_ST7735) + dev.driver = &lcd_st7735_driver; +#elif IS_USED(MODULE_ILI9341) + dev.driver = &lcd_ili9341_driver; +#endif + + puts("lcd TFT display test application"); /* initialize the sensor */ printf("Initializing display..."); @@ -41,46 +56,60 @@ int main(void) BACKLIGHT_ON; #endif - if (ili9341_init(&dev, &ili9341_params[0]) == 0) { +#if IS_USED(MODULE_ST7735) + if (lcd_init(&dev, (lcd_params_t *)&st7735_params[0].params) == 0) { puts("[OK]"); } else { puts("[Failed]"); return 1; } +#endif +#if IS_USED(MODULE_ILI9341) + if (lcd_init(&dev, &ili9341_params[0]) == 0) { + puts("[OK]"); + } + else { + puts("[Failed]"); + return 1; + } +#endif - puts("ili9341 TFT display filling map"); - ili9341_fill(&dev, 0, 319, 0, 239, 0x0000); - puts("ili9341 TFT display map filled"); + puts("lcd TFT display filling map"); + lcd_fill(&dev, 0, dev.params->lines, 0, dev.params->rgb_channels, 0x0000); + puts("lcd TFT display map filled"); /* Fill square with blue */ puts("Drawing blue rectangle"); - ili9341_fill(&dev, 10, 59, 10, 109, 0x001F); + lcd_fill(&dev, 0, dev.params->lines / 3, 0, dev.params->rgb_channels, 0x001F); ztimer_sleep(ZTIMER_MSEC, 1 * MS_PER_SEC); puts("Drawing green rectangle"); - ili9341_fill(&dev, 10, 59, 10, 109, 0x07E0); + lcd_fill(&dev, dev.params->lines / 3, 2 * (dev.params->lines / 3), 0, + dev.params->rgb_channels, 0x07E0); ztimer_sleep(ZTIMER_MSEC, 1 * MS_PER_SEC); puts("Drawing red rectangle"); - ili9341_fill(&dev, 10, 59, 10, 109, 0xf800); + lcd_fill(&dev, 2 * (dev.params->lines / 3), dev.params->lines, 0, + dev.params->rgb_channels, 0xf800); ztimer_sleep(ZTIMER_MSEC, 1 * MS_PER_SEC); - ili9341_invert_on(&dev); - puts("ili9341 TFT display inverted"); + lcd_invert_on(&dev); + puts("lcd TFT display inverted"); ztimer_sleep(ZTIMER_MSEC, 1 * MS_PER_SEC); - ili9341_invert_off(&dev); - puts("ili9341 TFT display normal"); - - /* Make the same square black again */ - ili9341_fill(&dev, 10, 59, 10, 109, 0x0000); + lcd_invert_off(&dev); + puts("lcd TFT display normal"); + puts("lcd TFT display clear screen"); + lcd_fill(&dev, 0, dev.params->lines, 0, dev.params->rgb_channels, 0x0000); #ifndef CONFIG_NO_RIOT_IMAGE /* Approximate middle of the display */ - ili9341_pixmap(&dev, 95, 222, 85, 153, (const uint16_t *)picture); + uint8_t x1 = (dev.params->lines / 2) - (RIOT_LOGO_WIDTH / 2); + uint8_t y1 = (dev.params->rgb_channels / 2) - (RIOT_LOGO_HEIGHT / 2); + lcd_pixmap(&dev, x1, x1 + RIOT_LOGO_WIDTH - 1, y1, y1 + RIOT_LOGO_HEIGHT - 1, + (const uint16_t *)picture); #endif - while (1) { - } + while (1) {} return 0; } diff --git a/tests/driver_ili9341/riot_logo.h b/tests/driver_ili9341/riot_logo.h index 937d825c73..85f2a37de5 100644 --- a/tests/driver_ili9341/riot_logo.h +++ b/tests/driver_ili9341/riot_logo.h @@ -13,7 +13,10 @@ extern "C" { #endif -const uint16_t picture[69][128] = { +#define RIOT_LOGO_HEIGHT 69U +#define RIOT_LOGO_WIDTH 128U + +const uint16_t picture[RIOT_LOGO_HEIGHT][RIOT_LOGO_WIDTH] = { { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,