1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/ili9341: use common lcd driver

This commit is contained in:
Francisco Molina 2021-03-15 15:13:23 +01:00 committed by Alexandre Abadie
parent 827fa976a6
commit c5cc2966ff
No known key found for this signature in database
GPG Key ID: 1C919A403CAE1405
13 changed files with 193 additions and 556 deletions

View File

@ -244,7 +244,3 @@ ifneq (,$(filter-out netdev_default, $(filter netdev_%,$(USEMODULE))))
USEMODULE += netdev_register
endif
endif
ifneq (,$(filter st7735,$(USEMODULE)))
USEMODULE += lcd
endif

View File

@ -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

View File

@ -1,4 +1,5 @@
FEATURES_REQUIRED += periph_spi
FEATURES_REQUIRED += periph_gpio
USEMODULE += lcd
USEMODULE += ztimer
USEMODULE += ztimer_msec

View File

@ -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, &param, 1);
}
const lcd_driver_t lcd_ili9341_driver = {
.init = _init,
.set_area = _set_area,
};

View File

@ -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 <alexandre.abadie@inria.fr>
* @}
*/
#include <assert.h>
#include <stdint.h>
#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,
};

View File

@ -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 <alexandre.abadie@inria.fr>
*/
#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 */

View File

@ -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
}

View File

@ -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 */
/** @} */

View File

@ -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 <koen@bergzand.net>
* @author Francisco Molina <francois-xavier.molina@inria.fr>
*
* 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
}

View File

@ -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

View File

@ -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)

View File

@ -11,7 +11,7 @@
* @{
*
* @file
* @brief Test application for the ili9431 tft display
* @brief Test application for lcd tft displays
*
* @author Koen Zandberg <koen@bergzand.net>
*
@ -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;
}

View File

@ -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,