st7789: add support for 3 wire interface
3 wire interface for ST7789 LCD controller does not use CMD/DATA pin to specify whether data or command is send but uses 9th bit of SPI transfer. This commit adds support for 3 wire interface to ST7789 controller. Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
parent
8706d68318
commit
548f4b652c
@ -705,6 +705,14 @@ config LCD_ST7789
|
||||
default n
|
||||
|
||||
if LCD_ST7789
|
||||
config LCD_ST7789_3WIRE
|
||||
bool "Use 3 wire interface"
|
||||
default n
|
||||
---help---
|
||||
Specifies whether 3 wire or 4 wire (default) interface is
|
||||
used. 3 wire interface drops CMD/DATA pin and uses 9th bit
|
||||
to determine data/command message.
|
||||
|
||||
config LCD_ST7789_XRES
|
||||
int "ST7789 X Resolution"
|
||||
default 240
|
||||
|
@ -45,9 +45,9 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* CONFIG_SPI_CMDDATA has to be set */
|
||||
/* CONFIG_SPI_CMDDATA has to be set for 4 wire interface */
|
||||
|
||||
#ifndef CONFIG_SPI_CMDDATA
|
||||
#if !defined(CONFIG_LCD_ST7789_3WIRE) && !defined(CONFIG_SPI_CMDDATA)
|
||||
# error "CONFIG_SPI_CMDDATA option has to be set for SPI communication"
|
||||
#endif
|
||||
|
||||
@ -103,6 +103,18 @@
|
||||
# define CONFIG_LCD_RPORTRAIT 1
|
||||
#endif
|
||||
|
||||
/* Define prefixes for 3 wire communication if used */
|
||||
|
||||
#ifdef CONFIG_LCD_ST7789_3WIRE
|
||||
# define LCD_ST7789_SPI_BITS 9
|
||||
# define LCD_ST7789_DATA_PREFIX (1 << 8)
|
||||
# define LCD_ST7789_CMD_PREFIX (0 << 8)
|
||||
#else
|
||||
# define LCD_ST7789_SPI_BITS 8
|
||||
# define LCD_ST7789_DATA_PREFIX (0)
|
||||
# define LCD_ST7789_CMD_PREFIX (0)
|
||||
#endif
|
||||
|
||||
/* Display Resolution */
|
||||
|
||||
#if !defined(CONFIG_LCD_ST7789_XRES)
|
||||
@ -184,6 +196,18 @@ struct st7789_dev_s
|
||||
uint16_t runbuffer[ST7789_LUT_SIZE];
|
||||
};
|
||||
|
||||
/* 3 wire interface for ST7789 requires the driver to send information
|
||||
* about command/data transfer as 9th bit of SPI transfer. This would
|
||||
* require non standard SPI interface that is not supported so a little
|
||||
* workaround is used here (inspire by SSD1351 driver). We split our
|
||||
* buffer into rows and send those rows separately with added 9th bit.
|
||||
* The price for this is a small overhead in SPI communication.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LCD_ST7789_3WIRE
|
||||
uint16_t rowbuff[ST7789_XRES * ST7789_BYTESPP];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Protototypes
|
||||
****************************************************************************/
|
||||
@ -325,11 +349,23 @@ static void st7789_deselect(FAR struct spi_dev_s *spi)
|
||||
|
||||
static inline void st7789_sendcmd(FAR struct st7789_dev_s *dev, uint8_t cmd)
|
||||
{
|
||||
st7789_select(dev->spi, 8);
|
||||
#ifdef CONFIG_LCD_ST7789_3WIRE
|
||||
uint16_t txbuf;
|
||||
|
||||
/* Add command prefix (9th bit shoudl be 0 ) */
|
||||
|
||||
txbuf = LCD_ST7789_CMD_PREFIX | cmd;
|
||||
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
SPI_SEND(dev->spi, txbuf);
|
||||
st7789_deselect(dev->spi);
|
||||
#else
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
SPI_CMDDATA(dev->spi, SPIDEV_DISPLAY(0), true);
|
||||
SPI_SEND(dev->spi, cmd);
|
||||
SPI_CMDDATA(dev->spi, SPIDEV_DISPLAY(0), false);
|
||||
st7789_deselect(dev->spi);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -380,26 +416,26 @@ static void st7789_setorientation(FAR struct st7789_dev_s *dev,
|
||||
if (orientation != LCD_PORTRAIT)
|
||||
{
|
||||
st7789_sendcmd(dev, ST7789_MADCTL);
|
||||
st7789_select(dev->spi, 8);
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
}
|
||||
|
||||
if (orientation == LCD_RLANDSCAPE)
|
||||
{
|
||||
/* RLANDSCAPE : MY=1 MV=1 */
|
||||
|
||||
SPI_SEND(dev->spi, 0xa0);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | 0xa0);
|
||||
}
|
||||
else if (orientation == LCD_LANDSCAPE)
|
||||
{
|
||||
/* LANDSCAPE : MX=1 MV=1 */
|
||||
|
||||
SPI_SEND(dev->spi, 0x70);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | 0x70);
|
||||
}
|
||||
else if (orientation == LCD_RPORTRAIT)
|
||||
{
|
||||
/* RPORTRAIT : MX=1 MY=1 */
|
||||
|
||||
SPI_SEND(dev->spi, 0xc0);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | 0xc0);
|
||||
}
|
||||
|
||||
st7789_deselect(dev->spi);
|
||||
@ -412,7 +448,7 @@ static void st7789_setorientation(FAR struct st7789_dev_s *dev)
|
||||
uint8_t madctl = 0x00;
|
||||
|
||||
st7789_sendcmd(dev, ST7789_MADCTL);
|
||||
st7789_select(dev->spi, 8);
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
|
||||
#if !defined(CONFIG_LCD_PORTRAIT)
|
||||
|
||||
@ -444,7 +480,7 @@ static void st7789_setorientation(FAR struct st7789_dev_s *dev)
|
||||
madctl ^= 0x80;
|
||||
#endif
|
||||
|
||||
SPI_SEND(dev->spi, madctl);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | madctl);
|
||||
|
||||
st7789_deselect(dev->spi);
|
||||
}
|
||||
@ -465,34 +501,38 @@ static void st7789_setarea(FAR struct st7789_dev_s *dev,
|
||||
/* Set row address */
|
||||
|
||||
st7789_sendcmd(dev, ST7789_RASET);
|
||||
st7789_select(dev->spi, 8);
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
#ifdef CONFIG_LCD_DYN_ORIENTATION
|
||||
SPI_SEND(dev->spi, (y0 + g_lcddev.yoff) >> 8);
|
||||
SPI_SEND(dev->spi, (y0 + g_lcddev.yoff) & 0xff);
|
||||
SPI_SEND(dev->spi, (y1 + g_lcddev.yoff) >> 8);
|
||||
SPI_SEND(dev->spi, (y1 + g_lcddev.yoff) & 0xff);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((y0 + g_lcddev.yoff) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((y0 + g_lcddev.yoff) & 0xff));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((y1 + g_lcddev.yoff) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((y1 + g_lcddev.yoff) & 0xff));
|
||||
#else
|
||||
SPI_SEND(dev->spi, (y0 + ST7789_YOFFSET) >> 8);
|
||||
SPI_SEND(dev->spi, (y0 + ST7789_YOFFSET) & 0xff);
|
||||
SPI_SEND(dev->spi, (y1 + ST7789_YOFFSET) >> 8);
|
||||
SPI_SEND(dev->spi, (y1 + ST7789_YOFFSET) & 0xff);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((y0 + ST7789_YOFFSET) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX |
|
||||
((y0 + ST7789_YOFFSET) & 0xff));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((y1 + ST7789_YOFFSET) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX |
|
||||
((y1 + ST7789_YOFFSET) & 0xff));
|
||||
#endif
|
||||
st7789_deselect(dev->spi);
|
||||
|
||||
/* Set column address */
|
||||
|
||||
st7789_sendcmd(dev, ST7789_CASET);
|
||||
st7789_select(dev->spi, 8);
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
#ifdef CONFIG_LCD_DYN_ORIENTATION
|
||||
SPI_SEND(dev->spi, (x0 + g_lcddev.xoff) >> 8);
|
||||
SPI_SEND(dev->spi, (x0 + g_lcddev.xoff) & 0xff);
|
||||
SPI_SEND(dev->spi, (x1 + g_lcddev.xoff) >> 8);
|
||||
SPI_SEND(dev->spi, (x1 + g_lcddev.xoff) & 0xff);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((x0 + g_lcddev.xoff) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((x0 + g_lcddev.xoff) & 0xff));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((x1 + g_lcddev.xoff) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((x1 + g_lcddev.xoff) & 0xff));
|
||||
#else
|
||||
SPI_SEND(dev->spi, (x0 + ST7789_XOFFSET) >> 8);
|
||||
SPI_SEND(dev->spi, (x0 + ST7789_XOFFSET) & 0xff);
|
||||
SPI_SEND(dev->spi, (x1 + ST7789_XOFFSET) >> 8);
|
||||
SPI_SEND(dev->spi, (x1 + ST7789_XOFFSET) & 0xff);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((x0 + ST7789_XOFFSET) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX |
|
||||
((x0 + ST7789_XOFFSET) & 0xff));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | ((x1 + ST7789_XOFFSET) >> 8));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX |
|
||||
((x1 + ST7789_XOFFSET) & 0xff));
|
||||
#endif
|
||||
st7789_deselect(dev->spi);
|
||||
}
|
||||
@ -513,8 +553,8 @@ static void st7789_bpp(FAR struct st7789_dev_s *dev, int bpp)
|
||||
|
||||
depth = bpp >> 2 | 1;
|
||||
st7789_sendcmd(dev, ST7789_COLMOD);
|
||||
st7789_select(dev->spi, 8);
|
||||
SPI_SEND(dev->spi, depth);
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | depth);
|
||||
st7789_deselect(dev->spi);
|
||||
|
||||
/* Cache the new BPP */
|
||||
@ -536,16 +576,52 @@ static void st7789_wrram(FAR struct st7789_dev_s *dev,
|
||||
size_t count)
|
||||
{
|
||||
size_t i;
|
||||
#ifdef CONFIG_LCD_ST7789_3WIRE
|
||||
size_t j;
|
||||
#endif
|
||||
|
||||
st7789_sendcmd(dev, ST7789_RAMWR);
|
||||
|
||||
st7789_select(dev->spi, ST7789_BYTESPP * 8);
|
||||
#ifdef CONFIG_LCD_ST7789_3WIRE
|
||||
if (count == 1)
|
||||
{
|
||||
/* We cannot send the entire buffer at once, split it to
|
||||
* separate rows.
|
||||
*/
|
||||
|
||||
count = ST7789_YRES;
|
||||
size = ST7789_XRES * ST7789_BYTESPP;
|
||||
}
|
||||
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
|
||||
/* For each row */
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
/* Copy data to rowbuff and add 9th bit */
|
||||
|
||||
for (j = 0; j < ST7789_XRES * ST7789_BYTESPP; j += 2)
|
||||
{
|
||||
/* Take care of correct byte order. */
|
||||
|
||||
rowbuff[j] = LCD_ST7789_DATA_PREFIX |
|
||||
(uint16_t)buff[j + 1 + (i * (size + skip))];
|
||||
rowbuff[j + 1] = LCD_ST7789_DATA_PREFIX |
|
||||
(uint16_t)buff[j + (i * (size + skip))];
|
||||
}
|
||||
|
||||
SPI_SNDBLOCK(dev->spi, rowbuff, size);
|
||||
}
|
||||
#else
|
||||
st7789_select(dev->spi, ST7789_BYTESPP * LCD_ST7789_SPI_BITS);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
SPI_SNDBLOCK(dev->spi, buff + (i * (size + skip)),
|
||||
size / ST7789_BYTESPP);
|
||||
}
|
||||
#endif
|
||||
|
||||
st7789_deselect(dev->spi);
|
||||
}
|
||||
@ -585,12 +661,22 @@ static void st7789_fill(FAR struct st7789_dev_s *dev, uint16_t color)
|
||||
st7789_setarea(dev, 0, 0, ST7789_XRES - 1, ST7789_YRES - 1);
|
||||
|
||||
st7789_sendcmd(dev, ST7789_RAMWR);
|
||||
st7789_select(dev->spi, ST7789_BYTESPP *8);
|
||||
#ifdef CONFIG_LCD_ST7789_3WIRE
|
||||
st7789_select(dev->spi, LCD_ST7789_SPI_BITS);
|
||||
|
||||
for (i = 0; i < ST7789_XRES * ST7789_YRES; i++)
|
||||
{
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | (color & 0xff));
|
||||
SPI_SEND(dev->spi, LCD_ST7789_DATA_PREFIX | (color & 0xff00) >> 8);
|
||||
}
|
||||
#else
|
||||
st7789_select(dev->spi, ST7789_BYTESPP * LCD_ST7789_SPI_BITS);
|
||||
|
||||
for (i = 0; i < ST7789_XRES * ST7789_YRES; i++)
|
||||
{
|
||||
SPI_SEND(dev->spi, color);
|
||||
}
|
||||
#endif
|
||||
|
||||
st7789_deselect(dev->spi);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user