This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 908ce01386a4fbd03249e670bc9b1f58d0489cdb Author: Jiri Vlasak <[email protected]> AuthorDate: Fri Nov 7 14:32:45 2025 +0100 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 <[email protected]> --- drivers/lcd/Kconfig | 11 +++++++++++ drivers/lcd/lcddrv_spiif.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig index 7ff1feb1398..b6894163a31 100644 --- a/drivers/lcd/Kconfig +++ b/drivers/lcd/Kconfig @@ -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 diff --git a/drivers/lcd/lcddrv_spiif.c b/drivers/lcd/lcddrv_spiif.c index 0ad4fc0b02d..9f1eea4dbe5 100644 --- a/drivers/lcd/lcddrv_spiif.c +++ b/drivers/lcd/lcddrv_spiif.c @@ -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; }
