Skip to content

Commit ae2118c

Browse files
bors[bot]gschorcht
andauthored
Merge #19816
19816: drivers/lcd: code deduplication for st7735 and ili9341 r=aabadie a=gschorcht ### Contribution description In preparation for the parallel interface support the following changes were made: 1. The code for basic communication (acquire/release SPI device, SPI transfers), which were always duplicated by copy & paste in each display driver again and again, has been moved to the LCD driver as low-level functions that are now used by the display drivers. These low level function allow - code deduplication and - to define a more abstract communication interface that can then be extended later by parallel communication interface 2. Identical GPIO initializations has also been moved from display drivers to the LCD driver. 3. Using a default implementation of `lcd_set_area` function allows further code deduplication. Finally, the `ili9341` and `st7735` drivers only implement the inialization sequence for the LCD driver IC. ### Testing procedure `tests/drivers/ili9341` should still work for a board with an ILI9341. Tested with `esp32-wrover-kit`. `tests/drivers/st7735` should still work for a board with a ST77xx. Tested with `esp32s3-usb-otg`. ### Issues/PRs references Co-authored-by: Gunar Schorcht <[email protected]>
2 parents 82f4154 + 5cb51b1 commit ae2118c

File tree

6 files changed

+273
-198
lines changed

6 files changed

+273
-198
lines changed

drivers/ili9341/ili9341.c

+28-71
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (C) 2018 Koen Zandberg
3+
* 2023 Gunar Schorcht
34
*
45
* This file is subject to the terms and conditions of the GNU Lesser
56
* General Public License v2.1. See the file LICENSE in the top level
@@ -14,6 +15,7 @@
1415
* @brief Device driver implementation for the ili9341 display controller
1516
*
1617
* @author Koen Zandberg <[email protected]>
18+
* @author Gunar Schorcht <[email protected]>
1719
*
1820
* @}
1921
*/
@@ -22,8 +24,8 @@
2224
#include <string.h>
2325
#include "byteorder.h"
2426
#include "periph/spi.h"
25-
#include "ztimer.h"
2627
#include "kernel_defines.h"
28+
#include "ztimer.h"
2729

2830
#include "ili9341.h"
2931
#include "ili9341_internal.h"
@@ -33,18 +35,6 @@
3335
#define ENABLE_DEBUG 0
3436
#include "debug.h"
3537

36-
static void _write_cmd(const lcd_t *dev, uint8_t cmd, const uint8_t *data,
37-
size_t len)
38-
{
39-
gpio_clear(dev->params->dcx_pin);
40-
spi_transfer_byte(dev->params->spi, dev->params->cs_pin, len ? true : false, cmd);
41-
gpio_set(dev->params->dcx_pin);
42-
if (len) {
43-
spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, data,
44-
NULL, len);
45-
}
46-
}
47-
4838
/* datasheet page 178, table converted to equation.
4939
* gvdd in 1mv increments: 4850 = 4.85V */
5040
static uint8_t _ili9341_calc_pwrctl1(uint16_t gvdd)
@@ -66,125 +56,92 @@ static uint8_t _ili9341_calc_vml(int16_t vcoml)
6656
static int _init(lcd_t *dev, const lcd_params_t *params)
6757
{
6858
assert(params->lines >= 16 && params->lines <= 320 && !(params->lines & 0x7));
69-
dev->params = params;
70-
uint8_t command_params[4] = { 0 };
71-
gpio_init(dev->params->dcx_pin, GPIO_OUT);
72-
int res = spi_init_cs(dev->params->spi, dev->params->cs_pin);
73-
if (res != SPI_OK) {
74-
DEBUG("[ili9341] init: error initializing the CS pin [%i]\n", res);
75-
return -1;
76-
}
7759

78-
if (gpio_is_valid(dev->params->rst_pin)) {
79-
gpio_init(dev->params->rst_pin, GPIO_OUT);
80-
gpio_clear(dev->params->rst_pin);
81-
ztimer_sleep(ZTIMER_MSEC, 120);
82-
gpio_set(dev->params->rst_pin);
83-
}
84-
ztimer_sleep(ZTIMER_MSEC, 120);
60+
uint8_t command_params[4] = { 0 };
8561

8662
/* Acquire once at release at the end */
87-
spi_acquire(dev->params->spi, dev->params->cs_pin, dev->params->spi_mode,
88-
dev->params->spi_clk);
63+
lcd_ll_acquire(dev);
8964

9065
/* Soft Reset */
91-
_write_cmd(dev, LCD_CMD_SWRESET, NULL, 0);
66+
lcd_ll_write_cmd(dev, LCD_CMD_SWRESET, NULL, 0);
9267
ztimer_sleep(ZTIMER_MSEC, 120);
9368

9469
/* Display off */
95-
_write_cmd(dev, LCD_CMD_DISPOFF, NULL, 0);
70+
lcd_ll_write_cmd(dev, LCD_CMD_DISPOFF, NULL, 0);
9671

9772
/* PWRCTL1/2 */
9873
command_params[0] = _ili9341_calc_pwrctl1(CONFIG_ILI9341_GVDD);
99-
_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 1);
74+
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL1, command_params, 1);
10075

10176
command_params[0] = 0x10; /* PWRCTL 0 0 0 */
102-
_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1);
77+
lcd_ll_write_cmd(dev, LCD_CMD_PWCTRL2, command_params, 1);
10378

10479
/* VCOMCTL */
10580
command_params[0] = _ili9341_calc_vmh(CONFIG_ILI9341_VCOMH);
10681
command_params[1] = _ili9341_calc_vml(CONFIG_ILI9341_VCOML);
107-
_write_cmd(dev, LCD_CMD_VMCTRL1, command_params, 2);
82+
lcd_ll_write_cmd(dev, LCD_CMD_VMCTRL1, command_params, 2);
10883

10984
command_params[0] = 0x86;
110-
_write_cmd(dev, LCD_CMD_VMCTRL2, command_params, 1);
85+
lcd_ll_write_cmd(dev, LCD_CMD_VMCTRL2, command_params, 1);
11186

11287
/* Memory access CTL */
11388
command_params[0] = dev->params->rotation;
11489
command_params[0] |= dev->params->rgb ? 0 : LCD_MADCTL_BGR;
115-
_write_cmd(dev, LCD_CMD_MADCTL, command_params, 1);
90+
lcd_ll_write_cmd(dev, LCD_CMD_MADCTL, command_params, 1);
11691

11792
/* Frame control */
11893
command_params[0] = 0x00;
11994
command_params[1] = 0x18;
120-
_write_cmd(dev, LCD_CMD_FRAMECTL1, command_params, 2);
95+
lcd_ll_write_cmd(dev, LCD_CMD_FRAMECTL1, command_params, 2);
12196

12297
/* Display function control */
12398
command_params[0] = 0x08;
12499
command_params[1] = 0x82;
125100
/* number of lines, see datasheet p. 166 (DISCTRL::NL) */
126101
command_params[2] = (params->lines >> 3) - 1;
127-
_write_cmd(dev, LCD_CMD_DFUNC, command_params, 3);
102+
lcd_ll_write_cmd(dev, LCD_CMD_DFUNC, command_params, 3);
128103

129104
/* Pixel format */
130105
command_params[0] = 0x55; /* 16 bit mode */
131-
_write_cmd(dev, LCD_CMD_PIXSET, command_params, 1);
106+
lcd_ll_write_cmd(dev, LCD_CMD_PIXSET, command_params, 1);
132107

133108
command_params[0] = 0x01;
134-
_write_cmd(dev, LCD_CMD_GAMSET, command_params, 1);
109+
lcd_ll_write_cmd(dev, LCD_CMD_GAMSET, command_params, 1);
135110

136111
/* Gamma correction */
137112
{
138113
static const uint8_t gamma_pos[] = {
139114
0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1,
140115
0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00
141116
};
142-
_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos,
143-
sizeof(gamma_pos));
117+
lcd_ll_write_cmd(dev, LCD_CMD_PGAMCTRL, gamma_pos,
118+
sizeof(gamma_pos));
144119
}
145120
{
146121
static const uint8_t gamma_neg[] = {
147122
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1,
148123
0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F
149124
};
150-
_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg,
151-
sizeof(gamma_neg));
125+
lcd_ll_write_cmd(dev, LCD_CMD_NGAMCTRL, gamma_neg,
126+
sizeof(gamma_neg));
152127

153128
}
154129

155130
if (dev->params->inverted) {
156-
_write_cmd(dev, LCD_CMD_DINVON, NULL, 0);
131+
lcd_ll_write_cmd(dev, LCD_CMD_DINVON, NULL, 0);
157132
}
158133
/* Sleep out (turn off sleep mode) */
159-
_write_cmd(dev, LCD_CMD_SLPOUT, NULL, 0);
134+
lcd_ll_write_cmd(dev, LCD_CMD_SLPOUT, NULL, 0);
160135
/* Display on */
161-
_write_cmd(dev, LCD_CMD_DISPON, NULL, 0);
162-
spi_release(dev->params->spi);
163-
return 0;
164-
}
136+
lcd_ll_write_cmd(dev, LCD_CMD_DISPON, NULL, 0);
165137

166-
static void _set_area(const lcd_t *dev, uint16_t x1, uint16_t x2,
167-
uint16_t y1, uint16_t y2)
168-
{
169-
be_uint16_t params[2];
170-
171-
x1 += dev->params->offset_x;
172-
x2 += dev->params->offset_x;
173-
y1 += dev->params->offset_y;
174-
y2 += dev->params->offset_y;
175-
176-
params[0] = byteorder_htons(x1);
177-
params[1] = byteorder_htons(x2);
178-
179-
_write_cmd(dev, LCD_CMD_CASET, (uint8_t *)params,
180-
sizeof(params));
181-
params[0] = byteorder_htons(y1);
182-
params[1] = byteorder_htons(y2);
183-
_write_cmd(dev, LCD_CMD_PASET, (uint8_t *)params,
184-
sizeof(params));
138+
/* Finally release the device */
139+
lcd_ll_release(dev);
140+
141+
return 0;
185142
}
186143

187144
const lcd_driver_t lcd_ili9341_driver = {
188145
.init = _init,
189-
.set_area = _set_area,
146+
.set_area = NULL, /* default implementation is used */
190147
};

drivers/include/lcd.h

+51
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ struct lcd_driver {
126126
/**
127127
* @brief Set area LCD work area
128128
*
129+
* This function pointer can be NULL if the controller specific driver
130+
* does not require anything special. In this case the default
131+
* implementation is used which sets the column addresses and the row
132+
* addresses of the area including the coordinates of the opposite corner.
133+
*
129134
* @param[in] dev Pointer to the selected driver
130135
* @param[in] x1 x coordinate of the first corner
131136
* @param[in] x2 x coordinate of the opposite corner
@@ -137,6 +142,52 @@ struct lcd_driver {
137142
uint16_t y2);
138143
};
139144

145+
/**
146+
* @brief Low Level to acquire the device
147+
*
148+
* @param[out] dev device descriptor
149+
*/
150+
void lcd_ll_acquire(const lcd_t *dev);
151+
152+
/**
153+
* @brief Low Level function to release the device
154+
*
155+
* @param[out] dev device descriptor
156+
*/
157+
void lcd_ll_release(const lcd_t *dev);
158+
159+
/**
160+
* @brief Low level function to write a command
161+
*
162+
* @pre The device must have already been acquired with @ref lcd_ll_acquire
163+
* before this function can be called.
164+
*
165+
* @param[in] dev device descriptor
166+
* @param[in] cmd command code
167+
* @param[in] data command data to the device
168+
* @param[in] len length of the command data
169+
*/
170+
void lcd_ll_write_cmd(const lcd_t *dev, uint8_t cmd, const uint8_t *data,
171+
size_t len);
172+
173+
/**
174+
* @brief Low level function for read command command
175+
*
176+
* @note Very often the SPI MISO signal of the serial interface or the RDX
177+
* signal of the MCU 8080 parallel interface are not connected to the
178+
* display. In this case the read command does not provide valid data.
179+
*
180+
* @pre The device must have already been acquired with @ref lcd_ll_acquire
181+
* before this function can be called.
182+
* @pre len > 0
183+
*
184+
* @param[in] dev device descriptor
185+
* @param[in] cmd command
186+
* @param[out] data data from the device
187+
* @param[in] len length of the returned data
188+
*/
189+
void lcd_ll_read_cmd(const lcd_t *dev, uint8_t cmd, uint8_t *data, size_t len);
190+
140191
/**
141192
* @brief Setup an lcd display device
142193
*

drivers/include/st7735.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ extern "C" {
8383
#endif
8484

8585
/**
86-
* @name ILI9341 display rotation modes
86+
* @name ST7735 display rotation modes
8787
* @{
8888
*/
8989
#define ST7735_ROTATION_VERT 0 /**< Vertical mode */

0 commit comments

Comments
 (0)