diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig index 4a364c8755..4fdef82dee 100644 --- a/drivers/lcd/Kconfig +++ b/drivers/lcd/Kconfig @@ -95,9 +95,9 @@ config P14201_FRAMEBUFFER buffer is 128 * 96 / 2 = 6Kb. If this is defined, then the driver will be fully functional. If not, then it will have the following limitations: - + Reading graphics memory cannot be supported, and - + All pixel writes must be aligned to byte boundaries. The latter limitation effectively reduces the 128x96 disply to 64x96. @@ -718,6 +718,60 @@ config LCD_ILI9341_IFACE1_RGB565 endchoice endif +config LCD_RA8875 + bool "RA8875 LCD Display Controller" + default n + ---help--- + LCD controller driver for RA8875 by RAiO Technologies Inc. + +if LCD_RA8875 + +choice + prompt "MCU Interface width" + default LCD_RA8875_8BIT + ---help--- + Bit-width of MCU interface (8 or 16) + +config LCD_RA8875_8BIT + bool "8 bit" + +config LCD_RA8875_16BIT + bool "16 bit" + +endchoice # MCU Interface width + +choice + prompt "Colors" + default LCD_RA8875_65K + ---help--- + Number of colors/color depth + +config LCD_RA8875_256 + bool "256 / 8 bit" + +config LCD_RA8875_65K + bool "65k / 16 bit" + +endchoice # Colors + +config LCD_RA8875_EXTENDED + bool "Extended drawing interfaces" + default n + depends on BUILD_FLAT + ---help--- + Build in some non-standard, custom drawing interfaces for the RA8875 + including the following: ra8875_drawrectangle(), ra8875_drawline(), + ra8875_drawtriangle(), and ra8875_drawcircle(). NOTE that these + will not be accessible by applications in protected or kernel build + configurations. + + NOTE: The non-standard ra8875_clear(), ra8875_drawrectangle(), + ra8875_drawline() interfaces are always built and available for use + because within the OS because these are used internally by the + driver anyway. + +endif # LCD_RA8875 + comment "Alphanumeric/Segment LCD Devices" config LCD_LCD1602 diff --git a/drivers/lcd/Make.defs b/drivers/lcd/Make.defs index 08a1264b50..03134c81b7 100644 --- a/drivers/lcd/Make.defs +++ b/drivers/lcd/Make.defs @@ -87,6 +87,10 @@ ifeq ($(CONFIG_LCD_ILI9341),y) CSRCS += ili9341.c endif +ifeq ($(CONFIG_LCD_RA8875),y) + CSRCS += ra8875.c +endif + # Include LCD driver build support DEPPATH += --dep-path lcd diff --git a/drivers/lcd/ra8875.c b/drivers/lcd/ra8875.c new file mode 100644 index 0000000000..53fb973619 --- /dev/null +++ b/drivers/lcd/ra8875.c @@ -0,0 +1,1455 @@ +/************************************************************************************** + * drivers/lcd/ra8875.c + * + * Driver for the RAiO Technologies RA8875 LCD controller + * + * Copyright (C) 2015 Intuitive Aerial AB. All rights reserved. + * Author: Marten Svanfeldt + * + * References: RA8875, Rev 1.6, Apr 2013, RAiO Technologies Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ra8875.h" + +#ifdef CONFIG_LCD_RA8875 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Configuration **********************************************************************/ + +/* Check contrast selection */ + +#if !defined(CONFIG_LCD_MAXCONTRAST) +# define CONFIG_LCD_MAXCONTRAST 1 +#endif + +/* Check power setting */ + +#if !defined(CONFIG_LCD_MAXPOWER) || CONFIG_LCD_MAXPOWER < 1 +# define CONFIG_LCD_MAXPOWER 1 +#endif + +#if CONFIG_LCD_MAXPOWER > 255 +# error "CONFIG_LCD_MAXPOWER must be less than 256 to fit in uint8_t" +#endif + +/* Check orientation */ + +#if defined(CONFIG_LCD_PORTRAIT) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) || \ + defined(CONFIG_LCD_RPORTRAIT) +# error "Cannot define both portrait and any other orientations" +# endif +#elif defined(CONFIG_LCD_RPORTRAIT) +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# error "Cannot define both rportrait and any other orientations" +# endif +#elif defined(CONFIG_LCD_LANDSCAPE) +# ifdef CONFIG_LCD_RLANDSCAPE +# error "Cannot define both landscape and any other orientations" +# endif +#elif !defined(CONFIG_LCD_RLANDSCAPE) +# define CONFIG_LCD_LANDSCAPE 1 +#endif + +/* Define CONFIG_DEBUG_LCD to enable detailed LCD debug output. Verbose debug must + * also be enabled. + */ + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_GRAPHICS +# undef CONFIG_DEBUG_LCD +#endif + +#ifndef CONFIG_DEBUG_VERBOSE +# undef CONFIG_DEBUG_LCD +#endif + +/* Display/Color Properties ***********************************************************/ +/* Display Resolution */ + +#if defined(CONFIG_RA8875_XRES) +# define RA8875_XRES CONFIG_RA8875_XRES +#else +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# define RA8875_XRES 800 +# else +# define RA8875_XRES 480 +# endif +#endif + +#if defined(CONFIG_RA8875_YRES) +# define RA8875_YRES CONFIG_RA8875_YRES +#else +# if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# define RA8875_YRES 480 +# else +# define RA8875_YRES 800 +# endif +#endif + +#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) +# define RA8875_HW_XRES RA8875_XRES +# define RA8875_HW_YRES RA8875_YRES +#else +# define RA8875_HW_XRES RA8875_YRES +# define RA8875_HW_YRES RA8875_XRES +#endif + +/* Color depth and format */ + +#if defined(CONFIG_LCD_RA8875_65K) +# define RA8875_BPP 16 +# define RA8875_COLORFMT FB_FMT_RGB16_565 + +# define RA8875_UNPACK_RED(p) (((p)>>11) & 0x1f) +# define RA8875_UNPACK_GREEN(p) (((p)>>5) & 0x3f) +# define RA8875_UNPACK_BLUE(p) ((p) & 0x1f) + +# define RA8875_PACK_RGB(r,g,b) ((r) << 11 | (g) << 5 | (b)) +#else /* LCD_RA8875_256 */ +# define RA8875_BPP 8 +# define RA8875_COLORFMT FB_FMT_RGB8_332 + +# define RA8875_UNPACK_RED(p) (((p)>>5) & 0x7) +# define RA8875_UNPACK_GREEN(p) (((p)>>2) & 0x7) +# define RA8875_UNPACK_BLUE(p) ((p) & 0x3) + +# define RA8875_PACK_RGB(r,g,b) (((r)&0x7) << 5 | ((g)&0x7) << 2 | ((b)&0x3)) +#endif + +#if RA8875_HW_XRES >= 800 && RA8875_HW_YRES >= 480 && RA8875_BPP > 8 +# undef RA8875_2LAYER_POSSIBLE +#else +# define RA8875_2LAYER_POSSIBLE 1 +#endif + +/* Debug ******************************************************************************/ + +#ifdef CONFIG_DEBUG_LCD +# define lcddbg dbg +# define lcdvdbg vdbg +#else +# define lcddbg(x...) +# define lcdvdbg(x...) +#endif + +/************************************************************************************** + * Private Type Definition + **************************************************************************************/ + +/* This structure describes the state of this driver */ + +struct ra8875_dev_s +{ + /* Publicly visible device structure */ + + struct lcd_dev_s dev; + + /* Private LCD-specific information follows */ + + FAR struct ra8875_lcd_s *lcd; /* The contained platform-specific, LCD interface */ + uint8_t power; /* Current power setting */ + +#if defined(RA8875_2LAYER_POSSIBLE) + uint8_t current_layer; /* Current drawing layer, 0=disabled */ +#endif + + /* Shadow these registers to speed up rendering */ + uint8_t shadow_mwcr0; + uint16_t shadow_w_curh, shadow_w_curv; + + /* These fields simplify and reduce debug output */ + +#ifdef CONFIG_DEBUG_LCD + bool put; /* Last raster operation was a putrun */ + fb_coord_t firstrow; /* First row of the run */ + fb_coord_t lastrow; /* Last row of the run */ + fb_coord_t col; /* Column of the run */ + size_t npixels; /* Length of the run */ +#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 + * (bpp * xres / 8). Actual alignment of the buffer must conform to the + * bitwidth of the underlying pixel type. + * + * If there are multiple planes, they may share the same working buffer + * because different planes will not be operate on concurrently. However, + * if there are multiple LCD devices, they must each have unique run buffers. + */ + + uint16_t runbuffer[RA8875_XRES]; +}; + +/************************************************************************************** + * Private Function Prototypes + **************************************************************************************/ +/* Low Level LCD access */ + +static inline void ra8875_putreg(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr, + uint8_t regval); +static inline void ra8875_putreg16(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr, + uint16_t regval); +#ifndef CONFIG_LCD_NOGETRUN +static inline uint8_t ra8875_readreg(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr); +static inline void ra8875_waitreg(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr, + uint8_t mask); +#endif +static void ra8875_set_writecursor(FAR struct ra8875_dev_s *dev, uint16_t column, + uint16_t row); +static void ra8875_set_readcursor(FAR struct ra8875_lcd_s *lcd, uint16_t column, + uint16_t row); +static void ra8875_set_mwcr0(FAR struct ra8875_dev_s *dev, uint8_t value); +static void ra8875_setwindow(FAR struct ra8875_lcd_s *lcd, uint16_t x, uint16_t y, + uint16_t width, uint16_t height); +static inline void ra8875_setbackground(FAR struct ra8875_lcd_s *lcd, uint16_t color); +static inline void ra8875_setforeground(FAR struct ra8875_lcd_s *lcd, uint16_t color); +static void ra8875_clearmem(FAR struct ra8875_lcd_s *lcd); + +/* LCD Data Transfer Methods */ + +#if 0 /* Sometimes useful */ +static void ra8875_dumprun(FAR const char *msg, FAR uint16_t *run, size_t npixels); +#else +# define ra8875_dumprun(m,r,n) +#endif + +#ifdef CONFIG_DEBUG_LCD +static void ra8875_showrun(FAR struct ra8875_dev_s *priv, fb_coord_t row, + fb_coord_t col, size_t npixels, bool put); +#else +# define ra8875_showrun(p,r,c,n,b) +#endif + +static int ra8875_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int ra8875_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); + +/* LCD Configuration */ + +static int ra8875_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int ra8875_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); + +/* LCD RGB Mapping */ + +#ifdef CONFIG_FB_CMAP +# error "RGB color mapping not supported by this driver" +#endif + +/* Cursor Controls */ + +#ifdef CONFIG_FB_HWCURSOR +# error "Cursor control not supported by this driver" +#endif + +/* LCD Specific Controls */ + +static int ra8875_getpower(FAR struct lcd_dev_s *dev); +static int ra8875_setpower(FAR struct lcd_dev_s *dev, int power); +static int ra8875_getcontrast(FAR struct lcd_dev_s *dev); +static int ra8875_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast); + +/* Initialization */ + +static inline int ra8875_hwinitialize(FAR struct ra8875_dev_s *priv); + +/************************************************************************************** + * Private Data + **************************************************************************************/ + +/* This driver can support only a signal RA8875 device. This is due to an + * unfortunate decision made when the getrun and putrun methods were designed. The + * following is the single RA8875 driver state instance: + */ + +static struct ra8875_dev_s g_lcddev; + +/************************************************************************************** + * Private Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: ra8875_putreg(lcd, + * + * Description: + * Write to an LCD register + * + **************************************************************************************/ + +static void ra8875_putreg(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr, + uint8_t regval) +{ + /* Set the index register to the register address and write the register contents */ + + lcdvdbg("putreg 0x%02x = 0x%02x\n", regaddr, regval); + + lcd->write_reg(lcd, regaddr, regval); +} + +/************************************************************************************** + * Name: ra8875_putreg16(lcd, + * + * Description: + * Write to an LCD register + * + **************************************************************************************/ + +static void ra8875_putreg16(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr, + uint16_t regval) +{ + /* Set the index register to the register address and write the register contents */ + + lcdvdbg("putreg 0x%02x = 0x%04x\n", regaddr, regval); + + lcd->write_reg16(lcd, regaddr, regval); +} + +/************************************************************************************** + * Name: ra8875_readreg + * + * Description: + * Read from an LCD register + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static uint8_t ra8875_readreg(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr) +{ + uint8_t regval; + /* Set the index register to the register address and read the register contents */ + + regval = lcd->read_reg(lcd, regaddr); + + lcdvdbg("readreg 0x%02x = 0x%02x\n", regaddr, regval); + return regval; +} +#endif + +/************************************************************************************** + * Name: ra8875_waitreg + * + * Description: + * Wait while an LCD register match set mask + * + **************************************************************************************/ + +#ifndef CONFIG_LCD_NOGETRUN +static void ra8875_waitreg(FAR struct ra8875_lcd_s *lcd, uint8_t regaddr, uint8_t mask) +{ + int i = 20000/100; + + while (i-- && ra8875_readreg(lcd, regaddr) & mask) { + up_udelay(100); + } +} +#endif + +/************************************************************************************** + * Name: ra8875_set_writecursor + * + * Description: + * Set the position to use for the write cursor + * + **************************************************************************************/ + +static void ra8875_set_writecursor(FAR struct ra8875_dev_s *dev, uint16_t column, + uint16_t row) +{ + FAR struct ra8875_lcd_s *lcd = dev->lcd; + +#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) + if (dev->shadow_w_curh != row) + { + ra8875_putreg16(lcd, RA8875_CURH0, row); + dev->shadow_w_curh = row; + } + + if (dev->shadow_w_curv != column) + { + ra8875_putreg16(lcd, RA8875_CURV0, column); + dev->shadow_w_curv = column; + } +#elif defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + if (dev->shadow_w_curh != column) + { + ra8875_putreg16(lcd, RA8875_CURH0, column); + dev->shadow_w_curh = column; + } + + if (dev->shadow_w_curv != row) + { + ra8875_putreg16(lcd, RA8875_CURV0, row); + dev->shadow_w_curv = row; + } +#endif +} + +/************************************************************************************** + * Name: ra8875_set_readcursor + * + * Description: + * Set the position to use for the read cursor + * + **************************************************************************************/ + +static void ra8875_set_readcursor(FAR struct ra8875_lcd_s *lcd, uint16_t column, + uint16_t row) +{ +#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) + ra8875_putreg16(lcd, RA8875_RCURH0, row); + ra8875_putreg16(lcd, RA8875_RCURV0, column); +#elif defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + ra8875_putreg16(lcd, RA8875_RCURH0, column); + ra8875_putreg16(lcd, RA8875_RCURV0, row); +#endif +} + +static void ra8875_set_mwcr0(FAR struct ra8875_dev_s *dev, uint8_t value) +{ + FAR struct ra8875_lcd_s *lcd = dev->lcd; + + if (dev->shadow_mwcr0 != value) + { + ra8875_putreg(lcd, RA8875_MWCR0, value); + dev->shadow_mwcr0 = value; + } +} + +/************************************************************************************** + * Name: ra8875_setwindow + * + * Description: + * Set hardware clipping window + * + **************************************************************************************/ + +static void ra8875_setwindow(FAR struct ra8875_lcd_s *lcd, uint16_t x, uint16_t y, + uint16_t width, uint16_t height) +{ +#if defined(CONFIG_LCD_PORTRAIT) || defined(CONFIG_LCD_RPORTRAIT) + ra8875_putreg16(lcd, RA8875_HSAW0, y); + ra8875_putreg16(lcd, RA8875_VSAW0, x); + ra8875_putreg16(lcd, RA8875_HEAW0, (y+height-1)); + ra8875_putreg16(lcd, RA8875_VEAW0, (x+width-1)); +#elif defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + ra8875_putreg16(lcd, RA8875_HSAW0, x); + ra8875_putreg16(lcd, RA8875_VSAW0, y); + ra8875_putreg16(lcd, RA8875_HEAW0, (x+width-1)); + ra8875_putreg16(lcd, RA8875_VEAW0, (y+height-1)); +#endif +} + +/************************************************************************************** + * Name: ra8875_setbackground + * + * Description: + * Set the background color to use for the BTE engine + * + **************************************************************************************/ + +static inline void ra8875_setbackground(FAR struct ra8875_lcd_s *lcd, uint16_t color) +{ + ra8875_putreg(lcd, RA8875_BGCR0, RA8875_UNPACK_RED(color)); + ra8875_putreg(lcd, RA8875_BGCR1, RA8875_UNPACK_GREEN(color)); + ra8875_putreg(lcd, RA8875_BGCR2, RA8875_UNPACK_BLUE(color)); +} + +/************************************************************************************** + * Name: ra8875_setforeground + * + * Description: + * Set the foreground color to use for the BTE engine + * + **************************************************************************************/ + +static inline void ra8875_setforeground(FAR struct ra8875_lcd_s *lcd, uint16_t color) +{ + ra8875_putreg(lcd, RA8875_FGCR0, RA8875_UNPACK_RED(color)); + ra8875_putreg(lcd, RA8875_FGCR1, RA8875_UNPACK_GREEN(color)); + ra8875_putreg(lcd, RA8875_FGCR2, RA8875_UNPACK_BLUE(color)); +} + +/************************************************************************************** + * Name: ra8875_clearmem + * + * Description: + * + * + **************************************************************************************/ + +static void ra8875_clearmem(FAR struct ra8875_lcd_s *lcd) +{ + lcdvdbg("clearmem start\n"); + ra8875_putreg(lcd, RA8875_MCLR, RA8875_MCLR_CLEAR | RA8875_MCLR_FULL); + + /* Wait for operation to finish */ + + ra8875_waitreg(lcd, RA8875_MCLR, RA8875_MCLR_CLEAR); + lcdvdbg("clearmem done\n"); +} + +/************************************************************************************** + * Name: ra8875_showrun + * + * Description: + * When LCD debug is enabled, try to reduce then amount of ouptut data generated by + * ra8875_putrun and ra8875_getrun + * + **************************************************************************************/ + +#ifdef CONFIG_DEBUG_LCD +static void ra8875_showrun(FAR struct ra8875_dev_s *priv, fb_coord_t row, + fb_coord_t col, size_t npixels, bool put) +{ + fb_coord_t nextrow = priv->lastrow + 1; + + /* Has anything changed (other than the row is the next row in the sequence)? */ + + if (put == priv->put && row == nextrow && col == priv->col && + npixels == priv->npixels) + { + /* No, just update the last row */ + + priv->lastrow = nextrow; + } + else + { + /* Yes... then this is the end of the preceding sequence. Output the last run + * (if there were more than one run in the sequence). + */ + + if (priv->firstrow != priv->lastrow) + { + lcddbg("...\n"); + lcddbg("%s row: %d col: %d npixels: %d\n", + priv->put ? "PUT" : "GET", + priv->lastrow, priv->col, priv->npixels); + } + + /* And we are starting a new sequence. Output the first run of the + * new sequence + */ + + lcddbg("%s row: %d col: %d npixels: %d\n", + put ? "PUT" : "GET", row, col, npixels); + + /* And save information about the run so that we can detect continuations + * of the sequence. + */ + + priv->put = put; + priv->firstrow = row; + priv->lastrow = row; + priv->col = col; + priv->npixels = npixels; + } +} +#endif + +/************************************************************************************** + * Name: ra8875_putrun + * + * Description: + * This method can be used to write a partial raster line to the LCD: + * + * row - Starting row to write to (range: 0 <= row < yres) + * col - Starting column to write to (range: 0 <= col <= xres-npixels) + * buffer - The buffer containing the run to be written to the LCD + * npixels - The number of pixels to write to the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int ra8875_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + FAR struct ra8875_dev_s *priv = &g_lcddev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + int16_t curhinc = 0; + int16_t curvinc = 0; + +#if RA8875_BPP == 16 + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + FAR const uint16_t *src = (FAR const uint16_t*)buffer; +#else + FAR const uint8_t *src = (FAR const uint8_t*)buffer; +#endif + int i; + + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + ra8875_showrun(priv, row, col, npixels, true); + +#ifdef CONFIG_LCD_LANDSCAPE + + /* Set the cursor position */ + + ra8875_set_mwcr0(priv, RA8875_MWCR0_MODE_GRAPHICS | RA8875_MWCR0_MEMDIR_LEFTRIGHT | + RA8875_MWCR0_WINC_ENABLE); + ra8875_set_writecursor(priv, col, row); + + curhinc = npixels; + curvinc = 0; + +#elif defined(CONFIG_LCD_RLANDSCAPE) + + /* Retransform coordinates, write right to left */ + + col = (RA8875_XRES-1) - col; + row = (RA8875_YRES-1) - row; + + /* Set the cursor position */ + + ra8875_set_mwcr0(priv, RA8875_MWCR0_MODE_GRAPHICS | RA8875_MWCR0_MEMDIR_RIGHTLEFT | RA8875_MWCR0_WINC_ENABLE); + ra8875_set_writecursor(priv, col, row); + + curhinc = -npixels; + curvinc = 0; + +#elif defined(CONFIG_LCD_PORTRAIT) + + row = (RA8875_YRES-1) - row; + + /* Set the cursor position */ + + ra8875_set_mwcr0(priv, RA8875_MWCR0_MODE_GRAPHICS | RA8875_MWCR0_MEMDIR_TOPDOWN | + RA8875_MWCR0_WINC_ENABLE); + ra8875_set_writecursor(priv, col, row); + + curhinc = 0; + curvinc = npixels; + +#else /* CONFIG_LCD_RPORTRAIT */ + + col = (RA8875_XRES-1) - col; + + /* Set the cursor position */ + + ra8875_set_mwcr0(priv, RA8875_MWCR0_MODE_GRAPHICS | RA8875_MWCR0_MEMDIR_DOWNTOP | + RA8875_MWCR0_WINC_ENABLE); + ra8875_set_writecursor(priv, col, row); + + curhinc = 0; + curvinc = -npixels; + +#endif + + /* Write data, handle order automatically */ + + lcd->pwrite_prepare(lcd, RA8875_MRWC); + + for (i = 0; i < npixels; i++) + { + /* Write the next pixel to this position */ + +#if RA8875_BPP == 8 + lcd->pwrite_data8(lcd, *src++); +#else + lcd->pwrite_data16(lcd, *src++); +#endif + } + + lcd->pwrite_finish(lcd); + + /* Update shadowed cursor */ + + priv->shadow_w_curh += curhinc; + priv->shadow_w_curv += curvinc; + + return OK; +} + +/************************************************************************************** + * Name: ra8875_getrun + * + * Description: + * This method can be used to read a partial raster line from the LCD: + * + * row - Starting row to read from (range: 0 <= row < yres) + * col - Starting column to read read (range: 0 <= col <= xres-npixels) + * buffer - The buffer in which to return the run read from the LCD + * npixels - The number of pixels to read from the LCD + * (range: 0 < npixels <= xres-col) + * + **************************************************************************************/ + +static int ra8875_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ +#ifndef CONFIG_LCD_NOGETRUN + FAR struct ra8875_dev_s *priv = &g_lcddev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + FAR uint16_t *dest = (FAR uint16_t*)buffer; + int i; + + /* Buffer must be provided and aligned to a 16-bit address boundary */ + + ra8875_showrun(priv, row, col, npixels, false); + DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); + + +#ifdef CONFIG_LCD_LANDSCAPE + /* Set the cursor position */ + + ra8875_putreg(lcd, RA8875_MWCR0, RA8875_MWCR0_MODE_GRAPHICS | + RA8875_MWCR0_MEMDIR_LEFTRIGHT | + RA8875_MWCR0_RINC_ENABLE); + ra8875_putreg(lcd, RA8875_MRDC, RA8875_MRCD_MEMDIR_LEFTRIGHT); + + ra8875_set_readcursor(lcd, col, row); + +#elif defined(CONFIG_LCD_RLANDSCAPE) + /* Retransform coordinates, write right to left */ + + col = (RA8875_XRES-1) - col; + row = (RA8875_YRES-1) - row; + + /* Set the cursor position */ + + ra8875_putreg(lcd, RA8875_MWCR0, RA8875_MWCR0_MODE_GRAPHICS | + RA8875_MWCR0_MEMDIR_RIGHTLEFT | + RA8875_MWCR0_RINC_ENABLE); + ra8875_putreg(lcd, RA8875_MRDC, RA8875_MRCD_MEMDIR_RIGHTLEFT); + + ra8875_set_readcursor(lcd, col, row); + +#elif defined(CONFIG_LCD_PORTRAIT) + /* Retransform coordinates, write right to left */ + + row = (RA8875_YRES-1) - row; + + /* Set the cursor position */ + + ra8875_putreg(lcd, RA8875_MWCR0, RA8875_MWCR0_MODE_GRAPHICS | + RA8875_MWCR0_MEMDIR_TPDOWN | + RA8875_MWCR0_RINC_ENABLE); + ra8875_putreg(lcd, RA8875_MRDC, RA8875_MRCD_MEMDIR_TOPDOWN); + + ra8875_set_readcursor(lcd, col, row); + +#else /* CONFIG_LCD_RPORTRAIT */ + /* Retransform coordinates, write right to left */ + + col = (RA8875_XRES-1) - col; + + /* Set the cursor position */ + + ra8875_putreg(lcd, RA8875_MWCR0, RA8875_MWCR0_MODE_GRAPHICS | + RA8875_MWCR0_MEMDIR_DOWNTOP | + RA8875_MWCR0_RINC_ENABLE); + ra8875_putreg(lcd, RA8875_MRDC, RA8875_MRCD_MEMDIR_DOWNTOP); + + ra8875_set_readcursor(lcd, col, row); + +#endif + + /* Read data, handle order automatically */ + + lcd->pread_prepare(lcd, RA8875_MRWC); + + for (i = 0; i < npixels; i++) + { + /* Read the next pixel from this position */ + + *dest++ = lcd->pread_data16(lcd); + } + + lcd->pread_finish(lcd); + + return OK; +#else + return -ENOSYS; +#endif +} + +/************************************************************************************** + * Name: ra8875_getvideoinfo + * + * Description: + * Get information about the LCD video controller configuration. + * + **************************************************************************************/ + +static int ra8875_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(dev && vinfo); + lcdvdbg("fmt: %d xres: %d yres: %d nplanes: 1\n", + RA8875_COLORFMT, RA8875_XRES, RA8875_YRES); + + vinfo->fmt = RA8875_COLORFMT; /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */ + vinfo->xres = RA8875_XRES; /* Horizontal resolution in pixel columns */ + vinfo->yres = RA8875_YRES; /* Vertical resolution in pixel rows */ + vinfo->nplanes = 1; /* Number of color planes supported */ + return OK; +} + +/************************************************************************************** + * Name: ra8875_getplaneinfo + * + * Description: + * Get information about the configuration of each LCD color plane. + * + **************************************************************************************/ + +static int ra8875_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + + DEBUGASSERT(dev && pinfo && planeno == 0); + lcdvdbg("planeno: %d bpp: %d\n", planeno, RA8875_BPP); + + pinfo->putrun = ra8875_putrun; /* Put a run into LCD memory */ + pinfo->getrun = ra8875_getrun; /* Get a run from LCD memory */ + pinfo->buffer = (uint8_t*)priv->runbuffer; /* Run scratch buffer */ + pinfo->bpp = RA8875_BPP; /* Bits-per-pixel */ + return OK; +} + +/************************************************************************************** + * Name: ra8875_getpower + * + * Description: + * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ra8875_getpower(FAR struct lcd_dev_s *dev) +{ + lcdvdbg("power: %d\n", 0); + return g_lcddev.power; +} + +/************************************************************************************** + * Name: ra8875_poweroff + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ra8875_poweroff(FAR struct ra8875_lcd_s *lcd) +{ + /* Set the backlight off */ + + ra8875_putreg(lcd, RA8875_P1CR, RA8875_P1CR_PWM_DISABLE); + ra8875_putreg(lcd, RA8875_P1DCR, 0); + + /* Turn the display off */ + + ra8875_putreg(lcd, RA8875_PWRR, RA8875_PWRR_DISPLAY_OFF); + + /* Remember the power off state */ + + g_lcddev.power = 0; + return OK; +} + +/************************************************************************************** + * Name: ra8875_setpower + * + * Description: + * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On + * backlit LCDs, this setting may correspond to the backlight setting. + * + **************************************************************************************/ + +static int ra8875_setpower(FAR struct lcd_dev_s *dev, int power) +{ + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + lcdvdbg("power: %d\n", power); + DEBUGASSERT((unsigned)power <= CONFIG_LCD_MAXPOWER); + + /* Set new power level */ + + if (power > 0) + { + if (g_lcddev.power == 0) + { + /* Set the backlight level */ + + ra8875_putreg(lcd, RA8875_P1CR, RA8875_P1CR_PWM_ENABLE); + ra8875_putreg(lcd, RA8875_P1CR, RA8875_P1CR_PWM_ENABLE | RA8875_P1CR_CSDIV(1)); + } + + ra8875_putreg(lcd, RA8875_P1DCR, power); + + /* Turn on display */ + + ra8875_putreg(lcd, RA8875_PWRR, RA8875_PWRR_DISPLAY_ON); + + g_lcddev.power = power; + } + else + { + /* Turn the display off */ + + ra8875_poweroff(lcd); + } + + return OK; +} + +/************************************************************************************** + * Name: ra8875_getcontrast + * + * Description: + * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int ra8875_getcontrast(FAR struct lcd_dev_s *dev) +{ + lcdvdbg("Not implemented\n"); + return -ENOSYS; +} + +/************************************************************************************** + * Name: ra8875_setcontrast + * + * Description: + * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). + * + **************************************************************************************/ + +static int ra8875_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast) +{ + lcdvdbg("contrast: %d\n", contrast); + return -ENOSYS; +} + +/************************************************************************************** + * Name: ra8875_hwinitialize + * + * Description: + * Initialize the LCD hardware. + * + **************************************************************************************/ + +static inline int ra8875_hwinitialize(FAR struct ra8875_dev_s *priv) +{ + uint8_t rv; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + /*@@TODO: Maybe some of these values needs to be configurable?? */ + + lcdvdbg("hwinitialize\n"); + + /* Reset */ + + ra8875_putreg(lcd, RA8875_PWRR, RA8875_PWRR_SWRESET); + up_mdelay(100); + ra8875_putreg(lcd, RA8875_PWRR, 0); + + /* Setup the PLL config */ + + ra8875_putreg(lcd, RA8875_PLLC1, RA8875_PLLC1_PLLDIVN(11)); + up_mdelay(10); + ra8875_putreg(lcd, RA8875_PLLC2, RA8875_PLLC2_PLLDIVK(2)); + up_mdelay(10); + + /* Interface and color depth */ + +#if RA8875_BPP == 16 + rv = RA8875_SYSR_COLOR_65K; +#else + rv = RA8875_SYSR_COLOR_256; +#endif +#if defined(CONFIG_LCD_RA8875_8BIT) + rv |= RA8875_SYSR_MCUIF_8BIT; +#elif defined(CONFIG_LCD_RA8875_16BIT) + rv |= RA8875_SYSR_MCUIF_16BIT; +#endif + ra8875_putreg(lcd, RA8875_SYSR, rv); + + /* Pixel clock, invert + 4*SYS */ + + ra8875_putreg(lcd, RA8875_PCSR, RA8875_PCSR_PCLK_INV | RA8875_PCSR_PERIOD_4SYS); + up_mdelay(1); + + /* Horizontal Settings */ + + ra8875_putreg(lcd, RA8875_HDWR, RA8875_HDWR_WIDTH(RA8875_HW_XRES)); + ra8875_putreg(lcd, RA8875_HNDFTR, 0x02); + ra8875_putreg(lcd, RA8875_HNDR, 0x03); + ra8875_putreg(lcd, RA8875_HSTR, 0x01); + ra8875_putreg(lcd, RA8875_HPWR, 0x03); + + /* Vertical Settings */ + + ra8875_putreg(lcd, RA8875_VDHR0, RA8875_VDHR0_HEIGHT(RA8875_HW_YRES)); + ra8875_putreg(lcd, RA8875_VDHR1, RA8875_VDHR1_HEIGHT(RA8875_HW_YRES)); + ra8875_putreg(lcd, RA8875_VNDR0, 0x0f); + ra8875_putreg(lcd, RA8875_VNDR1, 0x00); + ra8875_putreg(lcd, RA8875_VSTR0, 0x0e); + ra8875_putreg(lcd, RA8875_VSTR1, 0x06); + ra8875_putreg(lcd, RA8875_VPWR, 0x01); + +#if !defined(RA8875_2LAYER_POSSIBLE) + /* Too high, only one layer possible */ + + ra8875_putreg(lcd, RA8875_DPCR, RA8875_DPCR_LAYERS_ONE); +#else + /* Two layers */ + + ra8875_putreg(lcd, RA8875_DPCR, RA8875_DPCR_LAYERS_TWO); +#endif + + /* Setup window to be full screen */ + + ra8875_setwindow(lcd, 0, 0, RA8875_XRES, RA8875_YRES); + + /* Set background and foreground colors to black and white (respectively) */ + + ra8875_setbackground(lcd, 0x0000); + ra8875_setforeground(lcd, 0xffff); + + /* Clear the memory */ + + ra8875_clearmem(lcd); + + ra8875_setpower(&priv->dev, 0x0); + + /* Initialize the shadow registers */ + + priv->shadow_mwcr0 = 0; + priv->shadow_w_curh = 0; + priv->shadow_w_curv = 0; + + lcdvdbg("hwinitialize done\n"); + return OK; +} + + /************************************************************************************* + * Public Functions + **************************************************************************************/ + +/************************************************************************************** + * Name: ra8875_lcdinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +FAR struct lcd_dev_s *ra8875_lcdinitialize(FAR struct ra8875_lcd_s *lcd) +{ + int ret; + + lcdvdbg("Initializing\n"); + + /* If we could support multiple RA8875 devices, this is where we would allocate + * a new driver data structure... but we can't. Why not? Because of a bad should + * the form of the getrun() and putrun methods. + */ + + FAR struct ra8875_dev_s *priv = &g_lcddev; + + /* Initialize the driver data structure */ + + priv->dev.getvideoinfo = ra8875_getvideoinfo; + priv->dev.getplaneinfo = ra8875_getplaneinfo; + priv->dev.getpower = ra8875_getpower; + priv->dev.setpower = ra8875_setpower; + priv->dev.getcontrast = ra8875_getcontrast; + priv->dev.setcontrast = ra8875_setcontrast; + priv->lcd = lcd; + + /* Configure and enable LCD */ + + ret = ra8875_hwinitialize(priv); + if (ret == OK) + { + /* Clear the display (setting it to the color 0=black) */ + + ra8875_clear(&priv->dev, 0); + + /* Turn the display off */ + + ra8875_poweroff(lcd); + + lcdvdbg("Initialized\n"); + + return &g_lcddev.dev; + } + + return NULL; +} + +/************************************************************************************** + * Name: ra8875_clear + * + * Description: + * This is a non-standard LCD interface just for the RA8875. Because + * of the various rotations, clearing the display in the normal way by writing a + * sequences of runs that covers the entire display can be very slow. Here the + * display is cleared by simply setting all video memory to the specified color. + * + * NOTE: This function is not available to applications in the protected or kernel + * build modes. + * + **************************************************************************************/ + +void ra8875_clear(FAR struct lcd_dev_s *dev, uint16_t color) +{ +#if 0 + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + /* Set the color to use for filling */ + + ra8875_setforeground(lcd, color); + + /* Draw a rectangle over entire screen */ + + ra8875_putreg16(lcd, RA8875_DLHSR0, 0); + ra8875_putreg16(lcd, RA8875_DLVSR0, 0); + ra8875_putreg16(lcd, RA8875_DLHER0, RA8875_XRES); + ra8875_putreg16(lcd, RA8875_DLVER0, RA8875_YRES); + + ra8875_putreg(lcd, RA8875_DCR, RA8875_DCR_FILL | RA8875_DCR_SQUARE); + ra8875_putreg(lcd, RA8875_DCR, RA8875_DCR_FILL | RA8875_DCR_SQUARE | + RA8875_DCR_LINE_START); + + ra8875_waitreg(lcd, RA8875_DCR, RA8875_DCR_LINE_START); +#endif + + /* Draw a rectangle over entire screen */ + + ra8875_drawrectangle(dev, 0, 0, RA8875_XRES, RA8875_YRES, color, true); +} + +/************************************************************************************** + * Name: ra8875_drawrectangle + * + * This is a non-standard function to draw a rectangle on the LCD. This function is + * also used internally as part of the ra8875_clear implementation + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +void ra8875_drawrectangle(FAR struct lcd_dev_s *dev, uint16_t x, uint16_t y, + uint16_t width, uint16_t height, uint16_t color, bool fill) +{ + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + uint8_t draw_cmd = RA8875_DCR_SQUARE; + uint16_t sx, sy, ex, ey; + + /* Set the color to use for filling */ + + ra8875_setforeground(lcd, color); + + /* Handle degenerate cases */ + + if (width == 1) + { + ra8875_drawline(dev, x, y, x, y+height, color); + } + else if (height == 1) + { + ra8875_drawline(dev, x, y, x+width, y, color); + } + + if (fill) + { + draw_cmd |= RA8875_DCR_FILL; + } + + /* Setup coordinates */ + +#ifdef CONFIG_LCD_LANDSCAPE + + sx = x; + sy = y; + ex = x + width - 1; + ey = y + height - 1; + +#elif defined(CONFIG_LCD_RLANDSCAPE) + + sx = (RA8875_XRES - 1) - x - width + 1; + sy = (RA8875_YRES - 1) - y - height + 1; + ex = (RA8875_XRES - 1) - x; + ey = (RA8875_YRES - 1) - y; + +#elif defined(CONFIG_LCD_PORTRAIT) + + sx = (RA8875_YRES - 1) - y - height + 1; + sy = x; + ex = (RA8875_YRES - 1) - y; + ey = x + width - 1; + +#else /* CONFIG_LCD_RPORTRAIT */ + + sx = y; + sy = (RA8875_XRES - 1) - x - width + 1; + ex = y + height - 1; + ey = (RA8875_XRES - 1) - x; + +#endif + + ra8875_putreg16(lcd, RA8875_DLHSR0, sx); + ra8875_putreg16(lcd, RA8875_DLVSR0, sy); + ra8875_putreg16(lcd, RA8875_DLHER0, ex); + ra8875_putreg16(lcd, RA8875_DLVER0, ey); + + /* Run drawing */ + + ra8875_putreg(lcd, RA8875_DCR, draw_cmd); + ra8875_putreg(lcd, RA8875_DCR, draw_cmd | RA8875_DCR_LINE_START); + + ra8875_waitreg(lcd, RA8875_DCR, RA8875_DCR_LINE_START); +} + +/************************************************************************************** + * Name: ra8875_drawline + * + * Description: + * This is a non-standard function to draw a line on the LCD. This function is + * also used internally as part of the ra8875_rectandle implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +void ra8875_drawline(FAR struct lcd_dev_s *dev, uint16_t x1, uint16_t y1, uint16_t x2, + uint16_t y2, uint16_t color) +{ + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + uint8_t draw_cmd = RA8875_DCR_LINE; + uint16_t sx, sy, ex, ey; + + /* Set the color to use for filling */ + + ra8875_setforeground(lcd, color); + + /* Handle degenerate cases */ + /* Setup coordinates */ + +#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + + sx = x1; + sy = y1; + ex = x2; + ey = y2; + +#else /* CONFIG_LCD_PORTRAIT or CONFIG_LCD_RPORTRAIT */ + + sx = y1; + sy = x1; + ex = y2; + ey = x2; + +#endif + + ra8875_putreg16(lcd, RA8875_DLHSR0, sx); + ra8875_putreg16(lcd, RA8875_DLVSR0, sy); + ra8875_putreg16(lcd, RA8875_DLHER0, ex); + ra8875_putreg16(lcd, RA8875_DLVER0, ey); + + /* Run drawing */ + + ra8875_putreg(lcd, RA8875_DCR, draw_cmd); + ra8875_putreg(lcd, RA8875_DCR, draw_cmd | RA8875_DCR_LINE_START); + + ra8875_waitreg(lcd, RA8875_DCR, RA8875_DCR_LINE_START); +} + +/************************************************************************************** + * Name: ra8875_drawtriangle + * + * Description: + * This is a non-standard function to draw a triangle on the LCD. This function is + * also used internally as part of the ra8875_rectandle implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +#ifdef CONFIG_LCD_RA8875_EXTENDED +void ra8875_drawtriangle(FAR struct lcd_dev_s *dev, uint16_t x0, uint16_t y0, uint16_t x1, + uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color, bool fill) +{ + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + uint8_t draw_cmd = RA8875_DCR_TRIANGLE; + uint16_t _x0, _x1, _x2; + uint16_t _y0, _y1, _y2; + + /* Set the color to use for filling */ + + ra8875_setforeground(lcd, color); + + if (fill) + { + draw_cmd |= RA8875_DCR_FILL; + } + + /* Setup coordinates */ + +#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + + _x0 = x0; + _x1 = x1; + _x2 = x2; + + _y0 = y0; + _y1 = y1; + _y2 = y2; + +#else /* CONFIG_LCD_PORTRAIT or CONFIG_LCD_RPORTRAIT */ + + _x0 = y0; + _x1 = y1; + _x2 = y2; + + _y0 = x0; + _y1 = x1; + _y2 = x2; + +#endif + + ra8875_putreg16(lcd, RA8875_DLHSR0, _x0); + ra8875_putreg16(lcd, RA8875_DLVSR0, _y0); + ra8875_putreg16(lcd, RA8875_DLHER0, _x1); + ra8875_putreg16(lcd, RA8875_DLVER0, _y1); + ra8875_putreg16(lcd, RA8875_DTPH0, _x2); + ra8875_putreg16(lcd, RA8875_DTPV0, _y2); + + /* Run drawing */ + + ra8875_putreg(lcd, RA8875_DCR, draw_cmd); + ra8875_putreg(lcd, RA8875_DCR, draw_cmd | RA8875_DCR_LINE_START); + + ra8875_waitreg(lcd, RA8875_DCR, RA8875_DCR_LINE_START); +} +#endif + +/************************************************************************************** + * Name: ra8875_drawcircle + * + * Description: + * This is a non-standard function to draw a circle on the LCD. This function is + * also used internally as part of the ra8875_rectandle implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +#ifdef CONFIG_LCD_RA8875_EXTENDED +void ra8875_drawcircle(FAR struct lcd_dev_s *dev, uint16_t x, uint16_t y, uint8_t radius, + uint16_t color, bool fill) +{ + FAR struct ra8875_dev_s *priv = (FAR struct ra8875_dev_s *)dev; + FAR struct ra8875_lcd_s *lcd = priv->lcd; + + uint8_t draw_cmd = 0; + uint16_t _x, _y; + + /* Set the color to use for filling */ + + ra8875_setforeground(lcd, color); + + if (fill) + { + draw_cmd |= RA8875_DCR_FILL; + } + + /* Setup coordinates */ + +#if defined(CONFIG_LCD_LANDSCAPE) || defined(CONFIG_LCD_RLANDSCAPE) + + _x = x; + _y = y; + +#else /* CONFIG_LCD_PORTRAIT or CONFIG_LCD_RPORTRAIT */ + + _x = y; + _y = x; + +#endif + + ra8875_putreg16(lcd, RA8875_DCHR0, _x); + ra8875_putreg16(lcd, RA8875_DCVR0, _y); + ra8875_putreg(lcd, RA8875_DCRR, radius); + + /* Run drawing */ + + ra8875_putreg(lcd, RA8875_DCR, draw_cmd); + ra8875_putreg(lcd, RA8875_DCR, draw_cmd | RA8875_DCR_CIRCLE_START); + + ra8875_waitreg(lcd, RA8875_DCR, RA8875_DCR_CIRCLE_START); +} +#endif + +#endif /* CONFIG_LCD_RA8875 */ diff --git a/drivers/lcd/ra8875.h b/drivers/lcd/ra8875.h new file mode 100644 index 0000000000..0560351ae0 --- /dev/null +++ b/drivers/lcd/ra8875.h @@ -0,0 +1,276 @@ +/************************************************************************************** + * drivers/lcd/ra8875.h + * Definitions for the RAiO Technologies RA8875 LCD controller + * + * Copyright (C) 2015 Intuitive Aerial AB. All rights reserved. + * Author: Marten Svanfeldt + * + * References: RA8875, Rev 1.6, Apr 2013, RAiO Technologies Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __DRIVERS_LCD_RA8875_H +#define __DRIVERS_LCD_RA8875_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#ifdef CONFIG_LCD_RA8875 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ + +/* RA8875 Register Addresses (All with RS=1) */ + +/* System and Configuration Addresses */ + +#define RA8875_PWRR 0x01 /* Power and display control */ +#define RA8875_MRWC 0x02 /* Memory Read/Write Control/command */ +#define RA8875_PCSR 0x04 /* Pixel Clock Setting Register */ +#define RA8875_SROC 0x05 /* Serial Flash/ROM Configuration */ +#define RA8875_SFCLR 0x06 /* Serial Flash/ROM CLK Setting */ +#define RA8875_SYSR 0x10 /* System configuration Register */ +#define RA8875_GPI 0x12 /* General Purpose Input */ +#define RA8875_GPO 0x13 /* General Purpose Output */ +#define RA8875_HDWR 0x14 /* LCD Horizontal Display Width Register */ +#define RA8875_HNDFTR 0x15 /* LCD Horizontal Non-Display Period Fine Tuning Register */ +#define RA8875_HNDR 0x16 /* LCD Horizontal Non-Display Period Register */ +#define RA8875_HSTR 0x17 /* HSYNC Start Position Register */ +#define RA8875_HPWR 0x18 /* HSYNC Pulse Width Register */ +#define RA8875_VDHR0 0x19 /* LCD Vertical Display Height Register 0 */ +#define RA8875_VDHR1 0x1A /* LCD Vertical Display Height Register 1 */ +#define RA8875_VNDR0 0x1B /* LCD Vertical Non-Display Period Register 0 */ +#define RA8875_VNDR1 0x1C /* LCD Vertical Non-Display Period Register 1 */ +#define RA8875_VSTR0 0x1D /* VSYNC Start Position Register 0 */ +#define RA8875_VSTR1 0x1E /* VSYNC Start Position Register 1 */ +#define RA8875_VPWR 0x1F /* VSYNC Pulse Width Register */ + +/* LCD Display Control Registers */ + +#define RA8875_DPCR 0x20 /* Display Configuration Registers */ + +/* Active Window and Scroll Window Settings */ + +#define RA8875_HSAW0 0x30 /* Horizontal Start Point of Active Window 0 */ +#define RA8875_HSAW1 0x31 /* Horizontal Start Point of Active Window 1 */ +#define RA8875_VSAW0 0x32 /* Vertical Start Point of Active Window 0 */ +#define RA8875_VSAW1 0x33 /* Vertical Start Point of Active Window 1 */ +#define RA8875_HEAW0 0x34 /* Horizontal End Point of Active Window 0 */ +#define RA8875_HEAW1 0x35 /* Horizontal End Point of Active Window 1 */ +#define RA8875_VEAW0 0x36 /* Vertical End Point of Active Window 0 */ +#define RA8875_VEAW1 0x37 /* Vertical End Point of Active Window 1 */ + +/* Cursor Setting Registers */ + +#define RA8875_MWCR0 0x40 /* Memory Write Control Register 0 */ +#define RA8875_MWCR1 0x41 /* Memory Write Control Register 1 */ +#define RA8875_BTCR 0x44 /* Blink Time Control Register */ +#define RA8875_MRDC 0x45 /* Memory Read Cursor Direction */ +#define RA8875_CURH0 0x46 /* Memory Write Cursor Horizontal Position Register 0 */ +#define RA8875_CURH1 0x47 /* Memory Write Cursor Horizontal Position Register 1 */ +#define RA8875_CURV0 0x48 /* Memory Write Cursor Vertical Position Register 0 */ +#define RA8875_CURV1 0x49 /* Memory Write Cursor Vertical Position Register 1 */ +#define RA8875_RCURH0 0x4A /* Memory Read Cursor Horizontal Position Register 0 */ +#define RA8875_RCURH1 0x4B /* Memory Read Cursor Horizontal Position Register 1 */ +#define RA8875_RCURV0 0x4C /* Memory Read Cursor Vertical Position Register 0 */ +#define RA8875_RCURV1 0x4D /* Memory Read Cursor Vertical Position Register 1 */ + +/* BTE Control Registers */ + +#define RA8875_LTPR0 0x50 /* Layer Transparency Register 0 */ +#define RA8875_BGCR0 0x60 /* Background Color Register 0 */ +#define RA8875_BGCR1 0x61 /* Background Color Register 1 */ +#define RA8875_BGCR2 0x62 /* Background Color Register 2 */ +#define RA8875_FGCR0 0x63 /* Foreground Color Register 0 */ +#define RA8875_FGCR1 0x64 /* Foreground Color Register 1 */ +#define RA8875_FGCR2 0x65 /* Foreground Color Register 2 */ + +/* PWM Control Registers */ + +#define RA8875_P1CR 0x8A /* PWM1 Control Register */ +#define RA8875_P1DCR 0x8B /* PWM1 Duty Cycle Register */ + +#define RA8875_MCLR 0x8E /* Memory Clear Control Register */ + +/* PLL Setting Registers */ + +#define RA8875_PLLC1 0x88 /* PLL Control Register 1 */ +#define RA8875_PLLC2 0x89 /* PLL Control Register 2 */ + +/* Drawing Control Registers */ + +#define RA8875_DCR 0x90 /* Draw Line/Circle/Square Control Register */ +#define RA8875_DLHSR0 0x91 /* Draw Horizontal Start Address Register 0 */ +#define RA8875_DLHSR1 0x92 /* Draw Horizontal Start Address Register 1 */ +#define RA8875_DLVSR0 0x93 /* Draw Vertical Start Address Register 0 */ +#define RA8875_DLVSR1 0x94 /* Draw Vertical Start Address Register 1 */ +#define RA8875_DLHER0 0x95 /* Draw Horizontal End Address Register 0 */ +#define RA8875_DLHER1 0x96 /* Draw Horizontal End Address Register 1 */ +#define RA8875_DLVER0 0x97 /* Draw Vertical End Address Register 0 */ +#define RA8875_DLVER1 0x98 /* Draw Vertical End Address Register 1 */ +#define RA8875_DCHR0 0x99 /* Draw Circle Center Horizontal Address Register 0 */ +#define RA8875_DCHR1 0x9A /* Draw Circle Center Horizontal Address Register 1 */ +#define RA8875_DCVR0 0x9B /* Draw Circle Center Vertical Address Register 0 */ +#define RA8875_DCVR1 0x9C /* Draw Circle Center Vertical Address Register 1 */ +#define RA8875_DCRR 0x9D /* Draw Circle Radius Register */ +#define RA8875_DTPH0 0xA9 /* Draw Triangle Point 2 Horizontal Address Register 0 */ +#define RA8875_DTPH1 0xAA /* Draw Triangle Point 2 Horizontal Address Register 1 */ +#define RA8875_DTPV0 0xAB /* Draw Triangle Point 2 Vertical Address Register 0 */ +#define RA8875_DTPV1 0xAC /* Draw Triangle Point 2 Vertical Address Register 1 */ + +/* Bit definitions */ +/* Power and display control */ + +#define RA8875_PWRR_DISPLAY_OFF (0) +#define RA8875_PWRR_DISPLAY_ON (1<<7) +#define RA8875_PWRR_SLEEP (1<<1) +#define RA8875_PWRR_SWRESET (1<<0) + +/* Pixel Clock Setting Register */ + +#define RA8875_PCSR_PCLK_INV (1<<7) +#define RA8875_PCSR_PERIOD_MASK (3) +# define RA8875_PCSR_PERIOD_SYS (0) +# define RA8875_PCSR_PERIOD_2SYS (1) +# define RA8875_PCSR_PERIOD_4SYS (2) +# define RA8875_PCSR_PERIOD_8SYS (3) + +/* System configuration Register */ + +#define RA8875_SYSR_COLOR_SHIFT (2) +#define RA8875_SYSR_COLOR_MASK (3<>8) + +/* Display Configuration Registers */ + +#define RA8875_DPCR_LAYERS_ONE (0) +#define RA8875_DPCR_LAYERS_TWO (1<<7) +#define RA8875_DPCR_HSCAN_INC (0) +#define RA8875_DPCR_HSCAN_DEC (1<<3) +#define RA8875_DPCR_VSCAN_INC (0) +#define RA8875_DPCR_VSCAN_DEC (1<<2) + +/* Memory Write Control Register 0 */ + +#define RA8875_MWCR0_MODE_GRAPHICS (0) +#define RA8875_MWCR0_MODE_TEXT (1<<7) +#define RA8875_MWCR0_CURSOR_INVISIBLE (0) +#define RA8875_MWCR0_CURSOR_VISIBLE (1<<6) +#define RA8875_MWCR0_CURSOR_NORMAL (0) +#define RA8875_MWCR0_CURSOR_BLINK (1<<5) +#define RA8875_MWCR0_MEMDIR_SHIFT (2) +#define RA8875_MWCR0_MEMDIR_MASK (3< + * + * References: RA8875, Rev 1.6, Apr 2013, RAiO Technologies Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LCD_RA8875_H +#define __INCLUDE_NUTTX_LCD_RA8875_H + +/************************************************************************************** + * Included Files + **************************************************************************************/ + +#include + +#ifdef CONFIG_LCD_RA8875 + +/************************************************************************************** + * Pre-processor Definitions + **************************************************************************************/ +/* Configuration **********************************************************************/ +/* CONFIG_LCD_RA8875 - Enables support for the RA8875-based LCD. + * CONFIG_LCD_NOGETRUN + * NX components need to know if it can read from the LCD or not. If reading from the + * LCD is supported then some graphic operations can be improved. Default: Supported + * CONFIG_LCD_LANDSCAPE - Define for 320x240 display "landscape" support. Default is + * this 320x240 "landscape" orientation. + * CONFIG_LCD_RLANDSCAPE - Define for 320x240 display "reverse landscape" support. + * Default is this 320x240 "landscape" orientation + * CONFIG_LCD_PORTRAIT - Define for 240x320 display "portrait" orientation support. + * Default is this 320x240 "landscape" orientation + * CONFIG_LCD_RPORTRAIT - Define for 240x320 display "reverse portrait" orientation + * support. Default is this 320x240 "landscape" orientation + */ + +/************************************************************************************** + * Public Types + **************************************************************************************/ + +/* This structure defines the interface to the LCD provided by the platform. The + * nature of this interface is hidden from the RA8875 driver. + */ + +struct ra8875_lcd_s +{ + void (*write_reg)(FAR struct ra8875_lcd_s *dev, uint8_t regnum, uint8_t data); + void (*write_reg16)(FAR struct ra8875_lcd_s *dev, uint8_t regnum, uint16_t data); + + uint8_t (*read_reg)(FAR struct ra8875_lcd_s *dev, uint8_t regnum); + uint8_t (*read_status)(FAR struct ra8875_lcd_s *dev); + + /* Interface for fast pixel access */ + + void (*pwrite_prepare)(FAR struct ra8875_lcd_s *dev, uint8_t regnum); + void (*pwrite_data8)(FAR struct ra8875_lcd_s *dev, uint8_t data); + void (*pwrite_data16)(FAR struct ra8875_lcd_s *dev, uint16_t data); + void (*pwrite_finish)(FAR struct ra8875_lcd_s *dev); + + void (*pread_prepare)(FAR struct ra8875_lcd_s *dev, uint8_t regnum); + uint16_t (*pread_data16)(FAR struct ra8875_lcd_s *dev); + void (*pread_finish)(FAR struct ra8875_lcd_s *dev); + + /* platform-specific data may follow */ +}; + +/************************************************************************************** + * Public Data + **************************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/************************************************************************************** + * Public Function Prototypes + **************************************************************************************/ + +/************************************************************************************** + * Name: ra8875_lcdinitialize + * + * Description: + * Initialize the LCD video hardware. The initial state of the LCD is fully + * initialized, display memory cleared, and the LCD ready to use, but with the power + * setting at 0 (full off). + * + **************************************************************************************/ + +FAR struct lcd_dev_s *ra8875_lcdinitialize(FAR struct ra8875_lcd_s *lcd); + +/************************************************************************************** + * Name: ra8875_clear + * + * Description: + * This is a non-standard LCD interface just for the RA8875. Because + * of the various rotations, clearing the display in the normal way by writing a + * sequences of runs that covers the entire display can be very slow. Here the + * display is cleared by simply setting all video memory to the specified color. + * + * NOTE: This function is not available to applications in the protected or kernel + * build modes. + * + **************************************************************************************/ + +void ra8875_clear(FAR struct lcd_dev_s *dev, uint16_t color); + +/************************************************************************************** + * Name: ra8875_drawrectangle + * + * Description: + * This is a non-standard function to draw a rectangle on the LCD. This function is + * also used internally as part of the ra8875_clear implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +void ra8875_drawrectangle(FAR struct lcd_dev_s *dev, uint16_t x, uint16_t y, + uint16_t width, uint16_t height, uint16_t color, bool fill); + +/************************************************************************************** + * Name: ra8875_drawline + * + * Description: + * This is a non-standard function to draw a line on the LCD. This function is + * also used internally as part of the ra8875_rectandle implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +void ra8875_drawline(FAR struct lcd_dev_s *dev, uint16_t x1, uint16_t y1, uint16_t x2, + uint16_t y2, uint16_t color); + +/************************************************************************************** + * Name: ra8875_drawtriangle + * + * Description: + * This is a non-standard function to draw a triangle on the LCD. This function is + * also used internally as part of the ra8875_rectandle implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +#ifdef CONFIG_LCD_RA8875_EXTENDED +void ra8875_drawtriangle(FAR struct lcd_dev_s *dev, uint16_t x0, uint16_t y0, + uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, + uint16_t color, bool fill); +#endif + +/************************************************************************************** + * Name: ra8875_drawcircle + * + * Description: + * This is a non-standard function to draw a circle on the LCD. This function is + * also used internally as part of the ra8875_rectandle implementation. + * + * NOTE: This non-standard function is not available to applications in the + * protected or kernel build modes. + * + **************************************************************************************/ + +#ifdef CONFIG_LCD_RA8875_EXTENDED +void ra8875_drawcircle(FAR struct lcd_dev_s *dev, uint16_t x, uint16_t y, + uint8_t radius, uint16_t color, bool fill); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_LCD_SRA8875 */ +#endif /* __INCLUDE_NUTTX_LCD_SRA8875_H */