lcd/lcddrv: Implement 3-wire 9-bit SPI

Some display drivers, like ILI9341, support 3-wire 9-bit SPI. In
contrast to 4-wire 8-bit SPI, which uses dedicated CMD/DATA pin to
distinguish between CMD and DATA, 3-wire 9-bit SPI uses MSB of 9-bit
frame for this purpose.

Signed-off-by: Jiri Vlasak <jvlasak@elektroline.cz>
This commit is contained in:
Jiri Vlasak
2025-11-07 14:32:45 +01:00
committed by Xiang Xiao
parent 3a4b53b37c
commit 908ce01386
2 changed files with 42 additions and 0 deletions
+11
View File
@@ -1589,6 +1589,17 @@ config LCD_LCDDRV_SPEED
quite limited, but people have had success with much faster
speeds than the spec sheets say. YMMV.
config LCD_LCDDRV_3WIRE
bool "Use 3-wire 9-bit SPI."
default n
depends on LCD_LCDDRV_SPIIF
---help---
Specifies whether 3-wire or 4-wire (default) SPI is used.
3-wire 9-bit SPI uses MSB to distinguish between CMD (0) or
DATA (1). 4-wire 8-bit SPI uses dedicated CMD/DATA pin to
distinguish between CMD and DATA.
config LCD_RA8875
bool "RA8875 LCD Display Controller"
default n
+31
View File
@@ -39,6 +39,13 @@
#include <nuttx/spi/spi.h>
#include <nuttx/lcd/lcddrv_spiif.h>
/* Define conversions for DATA and CMD when 3-wire 9-bit SPI is used. */
#ifdef CONFIG_LCD_LCDDRV_3WIRE
# define LCD_LCDDRV_3WIRE_DATA(wd) ((1 << 8) | (wd))
# define LCD_LCDDRV_3WIRE_CMD(wd) ((0 << 8) | (wd))
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@@ -117,7 +124,9 @@ static void lcddrv_spiif_deselect(FAR struct lcddrv_lcd_s *lcd)
{
FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
#ifndef CONFIG_LCD_LCDDRV_3WIRE
SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
#endif
SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false);
SPI_LOCK(priv->spi, false);
}
@@ -144,11 +153,21 @@ static int lcddrv_spiif_sendmulti(FAR struct lcddrv_lcd_s *lcd,
uint32_t t;
FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
#ifdef CONFIG_LCD_LCDDRV_3WIRE
SPI_SETBITS(priv->spi, 9);
for (t = 0; t < nwords; t++)
{
SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_DATA((*wd & 0xff00) >> 8));
SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_DATA((*wd & 0x00ff) >> 0));
wd++;
}
#else
SPI_SETBITS(priv->spi, 16);
for (t = 0; t < nwords; t++)
{
SPI_SEND(priv->spi, *wd++);
}
#endif
SPI_SETBITS(priv->spi, 8);
@@ -201,7 +220,13 @@ static int lcddrv_spiif_send(FAR struct lcddrv_lcd_s *lcd,
uint8_t r;
FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
#ifdef CONFIG_LCD_LCDDRV_3WIRE
SPI_SETBITS(priv->spi, 9);
r = SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_DATA(param));
SPI_SETBITS(priv->spi, 8);
#else
r = SPI_SEND(priv->spi, param);
#endif
return r;
}
@@ -227,9 +252,15 @@ static int lcddrv_spiif_sendcmd(FAR struct lcddrv_lcd_s *lcd,
FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
lcdinfo("param=%04x\n", param);
#ifdef CONFIG_LCD_LCDDRV_3WIRE
SPI_SETBITS(priv->spi, 9);
r = SPI_SEND(priv->spi, LCD_LCDDRV_3WIRE_CMD(param));
SPI_SETBITS(priv->spi, 8);
#else
SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), true);
r = SPI_SEND(priv->spi, param);
SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
#endif
return r;
}