diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig index 961be99d75..0d9d5d639d 100644 --- a/drivers/lcd/Kconfig +++ b/drivers/lcd/Kconfig @@ -1179,6 +1179,13 @@ config LCD_RLANDSCAPE refers one of two orientations where the display is wider than it is tall (LCD_LANDSCAPE is the other). +config LCD_DYN_ORIENTATION + bool "Dynamic orientation" + ---help--- + Instead of deciding for a fixed orientation while compile time, choose to + have the possibility to switch the orientation while runtime. Orientation + is a parameter of lcdinitialize(). + endchoice config LCD_LPM013M091A diff --git a/drivers/lcd/st7789.c b/drivers/lcd/st7789.c index 38e2007be5..ffc6c0609b 100644 --- a/drivers/lcd/st7789.c +++ b/drivers/lcd/st7789.c @@ -83,19 +83,24 @@ #if defined(CONFIG_LCD_PORTRAIT) # if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) ||\ - defined(CONFIG_LCD_RPORTRAIT) + defined(CONFIG_LCD_RPORTRAIT) || defined(CONFIG_LCD_DYN_ORIENTATION) # error "Cannot define both portrait and any other orientations" # endif #elif defined(CONFIG_LCD_RPORTRAIT) -# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) ||\ + defined(CONFIG_LCD_DYN_ORIENTATION) # error "Cannot define both rportrait and any other orientations" # endif #elif defined(CONFIG_LCD_LANDSCAPE) -# ifdef CONFIG_LCD_RLANDSCAPE +# if defined(CONFIG_LCD_RLANDSCAPE) || defined(CONFIG_LCD_DYN_ORIENTATION) # error "Cannot define both landscape and any other orientations" # endif -#elif !defined(CONFIG_LCD_RLANDSCAPE) -# define CONFIG_LCD_LANDSCAPE 1 +#elif defined(CONFIG_LCD_DYN_ORIENTATION) +# ifdef CONFIG_LCD_RPORTRAIT +# error "Cannot define both landscape and dynamic orientation" +# endif +#elif !defined(CONFIG_LCD_RPORTRAIT) +# define CONFIG_LCD_RPORTRAIT 1 #endif /* Display Resolution */ @@ -159,6 +164,11 @@ struct st7789_dev_s uint8_t bpp; /* Selected color depth */ uint8_t power; /* Current power setting */ +#ifdef CONFIG_LCD_DYN_ORIENTATION + uint16_t xoff; + uint16_t yoff; +#endif + /* This is working memory allocated by the LCD driver for each LCD device * and for each color plane. This memory will hold one raster line of data. * The size of the allocated run buffer must therefore be at least @@ -185,7 +195,12 @@ static void st7789_deselect(FAR struct spi_dev_s *spi); static inline void st7789_sendcmd(FAR struct st7789_dev_s *dev, uint8_t cmd); static void st7789_sleep(FAR struct st7789_dev_s *dev, bool sleep); +#ifdef CONFIG_LCD_DYN_ORIENTATION +static void st7789_setorientation(FAR struct st7789_dev_s *dev, + uint8_t orientation); +#else static void st7789_setorientation(FAR struct st7789_dev_s *dev); +#endif static void st7789_display(FAR struct st7789_dev_s *dev, bool on); static void st7789_setarea(FAR struct st7789_dev_s *dev, uint16_t x0, uint16_t y0, @@ -356,7 +371,40 @@ static void st7789_display(FAR struct st7789_dev_s *dev, bool on) * Set screen orientation. * ****************************************************************************/ +#ifdef CONFIG_LCD_DYN_ORIENTATION +static void st7789_setorientation(FAR struct st7789_dev_s *dev, + uint8_t orientation) +{ + /* No need to change the orientation in PORTRAIT mode */ + if (orientation != LCD_PORTRAIT) + { + st7789_sendcmd(dev, ST7789_MADCTL); + st7789_select(dev->spi, 8); + } + + if (orientation == LCD_RLANDSCAPE) + { + /* RLANDSCAPE : MY=1 MV=1 */ + + SPI_SEND(dev->spi, 0xa0); + } + else if (orientation == LCD_LANDSCAPE) + { + /* LANDSCAPE : MX=1 MV=1 */ + + SPI_SEND(dev->spi, 0x70); + } + else if (orientation == LCD_RPORTRAIT) + { + /* RPORTRAIT : MX=1 MY=1 */ + + SPI_SEND(dev->spi, 0xc0); + } + + st7789_deselect(dev->spi); +} +#else static void st7789_setorientation(FAR struct st7789_dev_s *dev) { /* Default value on reset */ @@ -400,6 +448,7 @@ static void st7789_setorientation(FAR struct st7789_dev_s *dev) st7789_deselect(dev->spi); } +#endif /**************************************************************************** * Name: st7789_setarea @@ -417,20 +466,34 @@ static void st7789_setarea(FAR struct st7789_dev_s *dev, st7789_sendcmd(dev, ST7789_RASET); st7789_select(dev->spi, 8); +#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); +#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); +#endif st7789_deselect(dev->spi); /* Set column address */ st7789_sendcmd(dev, ST7789_CASET); st7789_select(dev->spi, 8); +#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); +#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); +#endif st7789_deselect(dev->spi); } @@ -446,22 +509,17 @@ static void st7789_bpp(FAR struct st7789_dev_s *dev, int bpp) { uint8_t depth; - /* Don't send any command if the depth hasn't changed. */ + /* REVISIT: Works only for 12 and 16 bpp! */ - if (dev->bpp != bpp) - { - /* REVISIT: Works only for 12 and 16 bpp! */ + depth = bpp >> 2 | 1; + st7789_sendcmd(dev, ST7789_COLMOD); + st7789_select(dev->spi, 8); + SPI_SEND(dev->spi, depth); + st7789_deselect(dev->spi); - depth = bpp >> 2 | 1; - st7789_sendcmd(dev, ST7789_COLMOD); - st7789_select(dev->spi, 8); - SPI_SEND(dev->spi, depth); - st7789_deselect(dev->spi); + /* Cache the new BPP */ - /* Cache the new BPP */ - - dev->bpp = bpp; - } + dev->bpp = bpp; } /**************************************************************************** @@ -807,7 +865,13 @@ static int st7789_setcontrast(FAR struct lcd_dev_s *dev, * ****************************************************************************/ +#ifdef CONFIG_LCD_DYN_ORIENTATION +FAR struct lcd_dev_s *st7789_lcdinitialize(FAR struct spi_dev_s *spi, + uint8_t orientation, + uint16_t xoff, uint16_t yoff) +#else FAR struct lcd_dev_s *st7789_lcdinitialize(FAR struct spi_dev_s *spi) +#endif { FAR struct st7789_dev_s *priv = &g_lcddev; @@ -821,11 +885,20 @@ FAR struct lcd_dev_s *st7789_lcdinitialize(FAR struct spi_dev_s *spi) priv->dev.setcontrast = st7789_setcontrast; priv->spi = spi; +#ifdef CONFIG_LCD_DYN_ORIENTATION + g_lcddev.xoff = xoff; + g_lcddev.yoff = yoff; +#endif + /* Init the hardware and clear the display */ st7789_sleep(priv, false); st7789_bpp(priv, ST7789_BPP); +#ifdef CONFIG_LCD_DYN_ORIENTATION + st7789_setorientation(priv, orientation); +#else st7789_setorientation(priv); +#endif st7789_display(priv, true); st7789_fill(priv, 0xffff); diff --git a/include/nuttx/lcd/st7789.h b/include/nuttx/lcd/st7789.h index 3e0e505f80..254972cb3a 100644 --- a/include/nuttx/lcd/st7789.h +++ b/include/nuttx/lcd/st7789.h @@ -31,6 +31,11 @@ * Pre-processor Definitions ****************************************************************************/ +#define LCD_PORTRAIT 0 +#define LCD_LANDSCAPE 1 +#define LCD_RPORTRAIT 2 +#define LCD_RLANDSCAPE 3 + /**************************************************************************** * Public Types ****************************************************************************/ @@ -63,7 +68,13 @@ extern "C" * ****************************************************************************/ +#ifdef CONFIG_LCD_DYN_ORIENTATION +FAR struct lcd_dev_s *st7789_lcdinitialize(FAR struct spi_dev_s *spi, + uint8_t orientation, + uint16_t xoff, uint16_t yoff); +#else FAR struct lcd_dev_s *st7789_lcdinitialize(FAR struct spi_dev_s *spi); +#endif #ifdef __cplusplus }