From 9638964ba3fb95c3f29d455f9c4af07d39606ee1 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 19 Dec 2014 14:32:08 -0600 Subject: example: add ltdc test example Signed-off-by: Marco Krahl --- apps/examples/Kconfig | 1 + apps/examples/Make.defs | 4 + apps/examples/Makefile | 16 +- apps/examples/README.txt | 11 + apps/examples/ltdc/.gitignore | 11 + apps/examples/ltdc/Kconfig | 11 + apps/examples/ltdc/Makefile | 135 +++ apps/examples/ltdc/ltdc_main.c | 2022 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 2203 insertions(+), 8 deletions(-) create mode 100644 apps/examples/ltdc/.gitignore create mode 100644 apps/examples/ltdc/Kconfig create mode 100644 apps/examples/ltdc/Makefile create mode 100644 apps/examples/ltdc/ltdc_main.c (limited to 'apps') diff --git a/apps/examples/Kconfig b/apps/examples/Kconfig index 73d5890c6..9acffdfd8 100644 --- a/apps/examples/Kconfig +++ b/apps/examples/Kconfig @@ -26,6 +26,7 @@ source "$APPSDIR/examples/keypadtest/Kconfig" source "$APPSDIR/examples/igmp/Kconfig" source "$APPSDIR/examples/i2schar/Kconfig" source "$APPSDIR/examples/lcdrw/Kconfig" +source "$APPSDIR/examples/ltdc/Kconfig" source "$APPSDIR/examples/mm/Kconfig" source "$APPSDIR/examples/modbus/Kconfig" source "$APPSDIR/examples/mount/Kconfig" diff --git a/apps/examples/Make.defs b/apps/examples/Make.defs index cc252c083..b7a73da15 100644 --- a/apps/examples/Make.defs +++ b/apps/examples/Make.defs @@ -130,6 +130,10 @@ ifeq ($(CONFIG_EXAMPLES_LCDRW),y) CONFIGURED_APPS += examples/lcdrw endif +ifeq ($(CONFIG_EXAMPLES_LTDC),y) +CONFIGURED_APPS += examples/ltdc +endif + ifeq ($(CONFIG_EXAMPLES_MM),y) CONFIGURED_APPS += examples/mm endif diff --git a/apps/examples/Makefile b/apps/examples/Makefile index bef81f89d..9b1445716 100644 --- a/apps/examples/Makefile +++ b/apps/examples/Makefile @@ -39,10 +39,10 @@ SUBDIRS = adc ajoystick bastest bridge buttons can cc3000 cpuhog cxxtest SUBDIRS += dhcpd discover djoystick elf flash_test ftpc ftpd hello helloxx -SUBDIRS += hidkbd igmp i2schar json keypadtest lcdrw mm modbus mount mtdpart -SUBDIRS += mtdrwb netpkt nettest nrf24l01_term nsh null nx nxterm nxffs -SUBDIRS += nxflat nxhello nximage nxlines nxtext ostest pashello pipe poll -SUBDIRS += posix_spawn pwm qencoder random relays rgmp romfs sendmail +SUBDIRS += hidkbd igmp i2schar json keypadtest lcdrw ltdc mm modbus mount +SUBDIRS += mtdpart mtdrwb netpkt nettest nrf24l01_term nsh null nx nxterm +SUBDIRS += nxffs nxflat nxhello nximage nxlines nxtext ostest pashello pipe +SUBDIRS += poll posix_spawn pwm qencoder random relays rgmp romfs sendmail SUBDIRS += serialblaster serloop serialrx slcd smart smart_test tcpecho SUBDIRS += telnetd thttpd tiff touchscreen udp usbserial usbterm watchdog SUBDIRS += webserver wget wgetjson xmlrpc @@ -56,10 +56,10 @@ CNTXTDIRS = pwm ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) CNTXTDIRS += adc ajoystick bridge can cc3000 cpuhog cxxtest dhcpd discover CNTXTDIRS += djoystick flash_test ftpd hello helloxx i2schar json keypadtest -CNTXTDIRS += modbus lcdrw mtdpart mtdrwb netpkt nettest nx nxhello nximage -CNTXTDIRS += nxlines nxtext nrf24l01_term ostest random relays qencoder -CNTXTDIRS += serialblasters lcd serialrx smart_test tcpecho telnetd tiff -CNTXTDIRS += touchscreen usbterm watchdog wgetjson +CNTXTDIRS += ltdc modbus lcdrw mtdpart mtdrwb netpkt nettest nx nxhello +CNTXTDIRS += nximage nxlines nxtext nrf24l01_term ostest random relays +CNTXTDIRS += qencoder serialblasters lcd serialrx smart_test tcpecho telnetd +CNTXTDIRS += tiff touchscreen usbterm watchdog wgetjson endif all: nothing diff --git a/apps/examples/README.txt b/apps/examples/README.txt index 58470f313..05c51e25b 100644 --- a/apps/examples/README.txt +++ b/apps/examples/README.txt @@ -680,6 +680,17 @@ examples/lcdrw NuttX is built as a protected, supervisor kernel (CONFIG_BUILD_PROTECTED or CONFIG_BUILD_KERNEL). +examples/ltdc +^^^^^^^^^^^^^ + + STM32 LTDC framebuffer example. Depends on: + + * CONFIG_STM32_LTDC + + Enabled with: + + * CONFIG_EXAMPLES_LTDC + examples/mm ^^^^^^^^^^^ diff --git a/apps/examples/ltdc/.gitignore b/apps/examples/ltdc/.gitignore new file mode 100644 index 000000000..fa1ec7579 --- /dev/null +++ b/apps/examples/ltdc/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.obj +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src diff --git a/apps/examples/ltdc/Kconfig b/apps/examples/ltdc/Kconfig new file mode 100644 index 000000000..d2a57b313 --- /dev/null +++ b/apps/examples/ltdc/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see misc/tools/kconfig-language.txt. +# + +config EXAMPLES_LTDC + bool "STM32 LTDC framebuffer example" + default n + depends on STM32_LTDC + ---help--- + Enable the LTDC example diff --git a/apps/examples/ltdc/Makefile b/apps/examples/ltdc/Makefile new file mode 100644 index 000000000..bf08a7ba8 --- /dev/null +++ b/apps/examples/ltdc/Makefile @@ -0,0 +1,135 @@ +############################################################################ +# apps/examples/ltdc/Makefile +# +# Copyright (C) 2014 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# ltdc framebuffer example + +APPNAME = ltdc +PRIORITY = SCHED_PRIORITY_DEFAULT +STACKSIZE = 2048 + +ASRCS = +CSRCS = +MAINSRC = ltdc_main.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +MAINOBJ = $(MAINSRC:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(MAINSRC) +OBJS = $(AOBJS) $(COBJS) + +ifneq ($(CONFIG_BUILD_KERNEL),y) + OBJS += $(MAINOBJ) +endif + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ifeq ($(WINTOOL),y) + INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}" +else + INSTALL_DIR = $(BIN_DIR) +endif + +CONFIG_XYZ_PROGNAME ?= slcd$(EXEEXT) +PROGNAME = $(CONFIG_XYZ_PROGNAME) + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: clean depend distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + @touch .built + +ifeq ($(CONFIG_BUILD_KERNEL),y) +$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) + @echo "LD: $(PROGNAME)" + $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) + $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) + +install: $(BIN_DIR)$(DELIM)$(PROGNAME) + +else +install: + +endif + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + +context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat +else +context: +endif + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +depend: .depend + +clean: + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep diff --git a/apps/examples/ltdc/ltdc_main.c b/apps/examples/ltdc/ltdc_main.c new file mode 100644 index 000000000..5d93c67f0 --- /dev/null +++ b/apps/examples/ltdc/ltdc_main.c @@ -0,0 +1,2022 @@ +/**************************************************************************** + * examples/ltdc/ltdc_main.c + * + * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LTDC_EXAMPLE_NCOLORS 5 + +#ifdef CONFIG_STM32_LTDC_INTERFACE +struct surface +{ + struct fb_videoinfo_s vinfo; + struct fb_planeinfo_s pinfo; + FAR struct ltdc_layer_s *layer; +}; +#endif + +enum example_colors +{ + LTDC_BLACK, + LTDC_RED, + LTDC_GREEN, + LTDC_BLUE, + LTDC_WHITE +}; + +static const uint32_t g_rgb24[LTDC_EXAMPLE_NCOLORS] = +{ + RGB24_BLACK, + RGB24_RED, + RGB24_GREEN, + RGB24_BLUE, + RGB24_WHITE, +}; + +static const uint32_t g_rgb16[LTDC_EXAMPLE_NCOLORS] = +{ + RGB16_BLACK, + RGB16_RED, + RGB16_GREEN, + RGB16_BLUE, + RGB16_WHITE, +}; + +/**************************************************************************** + * Private Data +****************************************************************************/ + +#ifdef CONFIG_STM32_LTDC_INTERFACE +#ifdef CONFIG_STM32_LTDC_L2 +static struct surface g_surface[2]; +#else +static struct surface g_surface[1]; +#endif +#endif + +#ifdef CONFIG_FB_CMAP +static uint8_t g_color[3*LTDC_EXAMPLE_NCOLORS]; + +static struct fb_cmap_s g_cmap = +{ + .first = 0, + .len = LTDC_EXAMPLE_NCOLORS, + .red = &g_color[0], + .green = &g_color[LTDC_EXAMPLE_NCOLORS], + .blue = &g_color[2*LTDC_EXAMPLE_NCOLORS] +}; +#endif + +/**************************************************************************** + * Private Function +****************************************************************************/ + +/**************************************************************************** + * Name: ltdc_init_cmap + * + * Description: + * Initialize the color lookup table + * + ***************************************************************************/ + +#ifdef CONFIG_FB_CMAP +static void ltdc_init_cmap(void) +{ + memset(&g_color, 0, sizeof(g_color)); + + /* CLUT color format definition + * + * Position value + * 00 0x000000 black + * 01 0xff0000 red + * 02 0x00ff00 green + * 03 0x0000ff blue + * 04 0xffffff white + * + */ + + g_cmap.red[1] = 0xff; + g_cmap.green[2] = 0xff; + g_cmap.blue[3] = 0xff; + g_cmap.red[4] = 0xff; + g_cmap.green[4] = 0xff; + g_cmap.blue[4] = 0xff; +} +#endif + +/**************************************************************************** + * Name: ltdc_color + * + * Description: + * Get the correct color value to the pixel format + * + ***************************************************************************/ + +static uint32_t ltdc_color(FAR struct fb_videoinfo_s *vinfo, uint8_t color) +{ + uint32_t value; + + switch (vinfo->fmt) + { +#if defined(CONFIG_STM32_LTDC_L1_L8) || defined(CONFIG_STM32_LTDC_L2_L8) + case FB_FMT_RGB8: + value = color; + break; +#endif +#if defined(CONFIG_STM32_LTDC_L1_RGB565) || defined(CONFIG_STM32_LTDC_L2_RGB565) + case FB_FMT_RGB16_565: + value = g_rgb16[color]; + break; +#endif +#if defined(CONFIG_STM32_LTDC_L1_RGB888) || \ + defined(CONFIG_STM32_LTDC_L2_RGB888) + case FB_FMT_RGB24: + value = g_rgb24[color]; + break; +#endif + default: + dbg("Unsupported pixel format %d\n", vinfo->fmt); + value = 0; + break; + } + + return value; +} + +/*************************************************************************** + * Name: ltdc_simple_draw + * + * Description: + * Draw four different colored rectangles on the whole screen + * + ***************************************************************************/ + +static void ltdc_simple_draw(FAR struct fb_videoinfo_s *vinfo, + FAR struct fb_planeinfo_s *pinfo) +{ + volatile int x, y; + uint16_t xres = vinfo->xres; + uint16_t yres = vinfo->yres; + + dbg("draw a red and green rectangle in the upper half\n"); + dbg("draw a white and blue rectangle in the lower half\n"); + +#if defined(CONFIG_STM32_LTDC_L1_L8) || defined(CONFIG_STM32_LTDC_L2_L8) + if (vinfo->fmt == FB_FMT_RGB8) + { + uint8_t color; + uint8_t *buf = (uint8_t *)pinfo->fbmem; + + for (y = 0; y < yres/2; y++) + { + color = ltdc_color(vinfo, LTDC_RED); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + + color = ltdc_color(vinfo, LTDC_GREEN); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + } + + for (y = 0; y < yres/2; y++) + { + color = ltdc_color(vinfo, LTDC_WHITE); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + + color = ltdc_color(vinfo, LTDC_BLUE); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + } + } +#endif + +#if defined(CONFIG_STM32_LTDC_L1_RGB565) || defined(CONFIG_STM32_LTDC_L2_RGB565) + if(vinfo->fmt == FB_FMT_RGB16_565) + { + uint16_t color; + uint16_t *buf = (uint16_t *)pinfo->fbmem; + + for (y = 0; y < yres/2; y++) + { + color = ltdc_color(vinfo, LTDC_RED); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + + color = ltdc_color(vinfo, LTDC_GREEN); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + } + + for (y = 0; y < yres/2; y++) + { + color = ltdc_color(vinfo, LTDC_WHITE); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + + color = ltdc_color(vinfo, LTDC_BLUE); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + } + } + } +#endif + +#if defined(CONFIG_STM32_LTDC_L1_RGB888) || defined(CONFIG_STM32_LTDC_L2_RGB888) + if(vinfo->fmt == FB_FMT_RGB24) + { + uint32_t color; + uint8_t *buf = (uint8_t *)pinfo->fbmem; + + for (y = 0; y < yres/2; y++) + { + color = ltdc_color(vinfo, LTDC_RED); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + *buf++ = (color >> 8); + *buf++ = (color >> 16); + } + + color = ltdc_color(vinfo, LTDC_GREEN); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + *buf++ = (color >> 8); + *buf++ = (color >> 16); + } + } + + for (y = 0; y < yres/2; y++) + { + color = ltdc_color(vinfo, LTDC_WHITE); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + *buf++ = (color >> 8); + *buf++ = (color >> 16); + } + + color = ltdc_color(vinfo, LTDC_BLUE); + + for (x = 0; x < xres/2; x++) + { + *buf++ = color; + *buf++ = (color >> 8); + *buf++ = (color >> 16); + } + } + } +#endif +} + +#ifdef CONFIG_STM32_LTDC_L2 +/****************************************************************************** + * Name: ltdc_drawcolor + * + * Description: + * Draw a specific color to the framebuffer + * + *****************************************************************************/ + +static void ltdc_drawcolor(FAR struct fb_videoinfo_s *vinfo, void *buffer, + uint16_t xres, uint16_t yres, uint32_t color) +{ + int x,y; + + /* draw a blue rectangle */ + + dbg("draw a full screen rectangle with color %08x\n", color); + +#if defined(CONFIG_STM32_LTDC_L1_L8) || defined(CONFIG_STM32_LTDC_L2_L8) + if (vinfo->fmt == FB_FMT_RGB8) + { + uint8_t *buf = (uint8_t *)buffer; + + for (y = 0; y < yres; y++) + { + for (x = 0; x < xres; x++) + { + *buf++ = color; + } + } + } +#endif + +#if defined(CONFIG_STM32_LTDC_L1_RGB565) || defined(CONFIG_STM32_LTDC_L2_RGB565) + if (vinfo->fmt == FB_FMT_RGB16_565) + { + uint16_t *buf = (uint16_t *)buffer; + + for (y = 0; y < yres; y++) + { + for (x = 0; x < xres; x++) + { + *buf++ = color; + } + } + } +#endif + +#if defined(CONFIG_STM32_LTDC_L1_RGB888) || defined(CONFIG_STM32_LTDC_L2_RGB888) + if (vinfo->fmt == FB_FMT_RGB24) + { + uint8_t *buf = (uint8_t *)buffer; + uint8_t r; + uint8_t g; + uint8_t b; + + r = (uint8_t)(color >> 16); + g = (uint8_t)(color >> 8); + b = (uint8_t)color; + + for (y = 0; y < yres; y++) + { + for (x = 0; x < xres; x++) + { + *buf++ = b; + *buf++ = g; + *buf++ = r; + } + } + } +#endif +} +#endif + +#ifdef CONFIG_STM32_LTDC_INTERFACE +/****************************************************************************** + * Name: ltdc_get_surface + * + * Description: + * Get a reference to a specific layer + * + *****************************************************************************/ + +static struct surface * ltdc_get_surface(uint32_t mode) +{ + int ret; + int lid; + FAR struct surface *sur = &g_surface[0]; + + ret = sur->layer->getlid(sur->layer, &lid, mode); + + if (ret != OK) + { + dbg("getlid() failed\n"); + _exit(1); + } + + if (lid < 0 || lid > 1) + { + dbg("invalid layer id %d\n", lid); + _exit(1); + } + + return &g_surface[lid]; +} + +/****************************************************************************** + * Name: ltdc_init_surface + * + * Description: + * Initialize layer and the layers videoinfo and planeinfo + * + *****************************************************************************/ + +static int ltdc_init_surface(int lid, uint32_t mode) +{ + FAR struct surface *sur = &g_surface[lid]; + + sur->layer = up_ltdcgetlayer(lid); + + if (!sur->layer) + { + dbg("up_ltdcgetlayer() failed\n"); + return -1; + } + + if (sur->layer->getvideoinfo(sur->layer, &sur->vinfo) != OK) + { + dbg("getvideoinfo() failed\n"); + return -1; + } + + if (sur->layer->getplaneinfo(sur->layer, 0, &sur->pinfo) != OK) + { + dbg("getplaneinfo() failed\n"); + return -1; + } + + dbg("layer %d is configured with: xres = %d, yres = %d," + "fb start address = %p, fb size = %d, fmt = %d, bpp = %d\n", + lid, sur->vinfo.xres, sur->vinfo.yres, sur->pinfo.fbmem, sur->pinfo.fblen, + sur->vinfo.fmt, sur->pinfo.bpp); + +#ifdef CONFIG_FB_CMAP + + /* Initialize the clut table */ + + if (sur->vinfo.fmt == FB_FMT_RGB8) + { + sur->layer->setclut(sur->layer, &g_cmap); + sur->layer->update(sur->layer, LTDC_UPDATE_NONE); + } +#endif + return OK; +} + + +/****************************************************************************** + * Name: ltdc_setget_test + * + * Description: + * Perform layer area positioning test + * + *****************************************************************************/ + +static void ltdc_setget_test(void) +{ + uint8_t alpha; + uint16_t xpos; + uint16_t ypos; + uint32_t color; + uint32_t mode; + int ret; + FAR struct ltdc_area_s area; + FAR struct surface *sur = ltdc_get_surface(LTDC_LAYER_ACTIVE); + + dbg("Perform set and get test\n"); + + /* setalpha */ + + ret = sur->layer->setalpha(sur->layer, 0x7f); + + if (ret != OK) + { + dbg("setalpha() failed\n"); + } + + ret = sur->layer->getalpha(sur->layer, &alpha); + + if (ret != OK || alpha != 0x7f) + { + dbg("getalpha() failed\n"); + } + + /* setcolor */ + + ret = sur->layer->setcolor(sur->layer, 0x11223344); + + if (ret != OK) + { + dbg("setcolor() failed\n"); + } + + ret = sur->layer->getcolor(sur->layer, &color); + + if (ret != OK || color != 0x11223344) + { + dbg("getcolor() failed\n"); + } + + /* setcolorkey */ + + ret = sur->layer->setcolorkey(sur->layer, 0x55667788); + + if (ret != OK) + { + dbg("setcolorkey() failed\n"); + } + + ret = sur->layer->getcolorkey(sur->layer, &color); + + if (ret != OK || color != 0x55667788) + { + dbg("getcolorkey() failed\n"); + } + + /* setblendmode */ + + ret = sur->layer->setblendmode(sur->layer, LTDC_BLEND_NONE); + + if (ret != OK) + { + dbg("setblendmode() failed\n"); + } + + ret = sur->layer->getblendmode(sur->layer, &mode); + + if (ret != OK || mode != LTDC_BLEND_NONE) + { + dbg("getblendmode() failed\n"); + } + + /* setarea */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + ret = sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/8, sur->vinfo.yres/8); + + if (ret != OK) + { + dbg("setarea() failed\n"); + } + + ret = sur->layer->getarea(sur->layer, &area, &xpos, &ypos); + + if (ret != OK || xpos != sur->vinfo.xres/8 || ypos != sur->vinfo.yres/8 || + area.xpos != sur->vinfo.xres/4 || area.ypos != sur->vinfo.yres/4 || + area.xres != sur->vinfo.xres/2 || area.yres != sur->vinfo.yres/2) + { + dbg("getarea() failed\n"); + } + +#ifdef CONFIG_FB_CMAP + if (sur->vinfo.fmt == FB_FMT_RGB8) + { + ret = sur->layer->setclut(sur->layer, &g_cmap); + + if (ret != OK) + { + dbg("setclut() failed\n"); + } + + ret = sur->layer->getclut(sur->layer, &g_cmap); + + if (ret != OK) + { + dbg("getclut() failed\n"); + } + } +#endif + + /* Restore to default state */ + + area.xpos = 0; + area.ypos = 0; + area.xres = sur->vinfo.xres; + area.yres = sur->vinfo.yres; + + sur->layer->setalpha(sur->layer, 0xff); + sur->layer->setcolor(sur->layer, 0); + sur->layer->setcolorkey(sur->layer, 0); + sur->layer->setarea(sur->layer, &area, 0, 0); + sur->layer->setblendmode(sur->layer, LTDC_BLEND_NONE); + sur->layer->update(sur->layer, 0); +} + +/****************************************************************************** + * Name: ltdc_color_test + * + * Description: + * Perform layer color test + * + *****************************************************************************/ + +static void ltdc_color_test(void) +{ + struct ltdc_area_s area; + + FAR struct surface *sur = ltdc_get_surface(LTDC_LAYER_ACTIVE); + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + ltdc_simple_draw(&sur->vinfo, &sur->pinfo); + + usleep(1000000); + + /* Default Color black */ + + dbg("Set default color to black\n"); + + sur->layer->setcolor(sur->layer, 0xff000000); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + /* Set active layer to the upper half of the screen */ + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + dbg("Update the layer, should be black outside the white rectangle\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Default Color red */ + + dbg("Update the layer, should be red outside the white rectangle\n"); + + sur->layer->setcolor(sur->layer, 0xffff0000); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Default Color green */ + + dbg("Update the layer, should be green outside the white rectangle\n"); + + sur->layer->setcolor(sur->layer, 0xff00ff00); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Default Color blue */ + + dbg("Update the layer, should be blue outside the white rectangle\n"); + + sur->layer->setcolor(sur->layer, 0xff0000ff); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Restore original size */ + + area.xpos = 0; + area.ypos = 0; + area.xres = sur->vinfo.xres; + area.yres = sur->vinfo.yres; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + /* Default Color black */ + + dbg("Set default color to black\n"); + + sur->layer->setcolor(sur->layer, 0); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); +} + +/****************************************************************************** + * Name: ltdc_colorkey_test + * + * Description: + * Perform layer colorkey test + * + *****************************************************************************/ + +static void ltdc_colorkey_test(void) +{ + struct ltdc_area_s area; + + FAR struct surface *sur = ltdc_get_surface(LTDC_LAYER_ACTIVE); + + ltdc_simple_draw(&sur->vinfo, &sur->pinfo); + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + /* Resize active layer */ + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + /* Enable colorkey */ + + sur->layer->setblendmode(sur->layer, LTDC_BLEND_COLORKEY); + + /* Color key white */ + + dbg("Set colorkey to white\n"); + + sur->layer->setcolorkey(sur->layer, 0xffffff); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Color key red */ + + dbg("Set colorkey to red\n"); + + sur->layer->setcolorkey(sur->layer, 0xff0000); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Color key green */ + + dbg("Set colorkey to green\n"); + + sur->layer->setcolorkey(sur->layer, 0xff00); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); + + /* Color key red */ + + dbg("Set colorkey to blue\n"); + + sur->layer->setcolorkey(sur->layer, 0xff); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + dbg("Disable colorkey\n"); + + usleep(1000000); + + sur->layer->setcolorkey(sur->layer, 0); + + /* Restore original size */ + + area.xpos = 0; + area.ypos = 0; + area.xres = sur->vinfo.xres; + area.yres = sur->vinfo.yres; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, 0, 0); + + /* Disable colorkeying */ + + sur->layer->setblendmode(sur->layer, LTDC_BLEND_NONE); + + dbg("Update the layer\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT); + + usleep(1000000); +} + +/****************************************************************************** + * Name: ltdc_area_test + * + * Description: + * Perform layer area positioning test + * + *****************************************************************************/ + +static void ltdc_area_test(void) +{ + int n; + int x; + int y; + struct ltdc_area_s area; + FAR struct surface *sur = ltdc_get_surface(LTDC_LAYER_ACTIVE); + + dbg("Perform area test\n"); + + ltdc_simple_draw(&sur->vinfo, &sur->pinfo); + + usleep(1000000); + + /* Set active layer to the upper left rectangle of the screen */ + + area.xpos = 0; + area.ypos = 0; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + dbg("Update the layer, to show the upper left rectangle of the screen\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Set active layer to the upper rigth rectangle of the screen */ + + area.xpos = sur->vinfo.xres/2; + area.ypos = 0; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + dbg("Update the layer, to show the upper right rectangle of the screen\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Set active layer to the upper left rectangle of the screen */ + + area.xpos = 0; + area.ypos = sur->vinfo.yres/2; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + dbg("Update the layer, to show the lower left rectangle of the screen\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Set active layer to the upper right rectangle of the screen */ + + area.xpos = sur->vinfo.xres/2; + area.ypos = sur->vinfo.yres/2; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + dbg("Update the layer, to show the lower right rectangle of the screen\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Perform layer positioning */ + + dbg("Perform positioning test\n"); + + /* Set layer in the middle of the screen */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + /* Move right */ + + for (n = 0; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move down */ + + for (n = 0; n < sur->vinfo.yres/8; n++) + { + area.ypos++; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move left */ + + for (n = 0; n < sur->vinfo.xres/4; n++) + { + area.xpos--; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move up */ + + for (n = 0; n < sur->vinfo.yres/8; n++) + { + area.ypos--; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move back to the middle */ + + for (n = 0; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Perform move */ + + dbg("Perform move test\n"); + + /* Set layer in the middle of the screen */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + /* Move right */ + + for (n = 0; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, + sur->vinfo.yres/4); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move down */ + + for (n = 0; n < sur->vinfo.yres/8; n++) + { + area.ypos++; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, + sur->vinfo.yres/4); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move left */ + + for (n = 0; n < sur->vinfo.xres/4; n++) + { + area.xpos--; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, + sur->vinfo.yres/4); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move up */ + + for (n = 0; n < sur->vinfo.yres/8; n++) + { + area.ypos--; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, + sur->vinfo.yres/4); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move back to the middle */ + + for (n = 0; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, + sur->vinfo.yres/4); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Perform Reference position */ + + dbg("Perform reference positioning test\n"); + + /* Set layer in the middle of the screen */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + /* Move right */ + + for (x = 0; x < sur->vinfo.xres/8; x++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - x, + sur->vinfo.yres/4); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move down */ + + for (y = 0; y < sur->vinfo.yres/8; y++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - x, + sur->vinfo.yres/4 - y); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move left */ + + for (x = 0; x < sur->vinfo.xres/4; x++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - sur->vinfo.xres/8 + x, + sur->vinfo.yres/4 - y); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move up */ + + for (y = 0; y < sur->vinfo.yres/8; y++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - sur->vinfo.xres/8 + x, + sur->vinfo.yres/4 - sur->vinfo.yres/8 + y); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + /* Move back to the middle */ + + for (x = 0; x < sur->vinfo.xres/8; x++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 + sur->vinfo.xres/8 - x, + sur->vinfo.yres/4 - sur->vinfo.yres/8 + y); + sur->layer->update(sur->layer, LTDC_SYNC_NONE); + usleep(5); + } + + usleep(1000000); + + /* Restore original size */ + + area.xpos = 0; + area.ypos = 0; + area.xres = sur->vinfo.xres; + area.yres = sur->vinfo.yres; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + dbg("Update the layer to fullscreen\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + usleep(1000000); +} + +/****************************************************************************** + * Name: ltdc_common_test + * + * Description: + * Perform test with all layer operations at once + * Todo: add alpha blending and default color + * + *****************************************************************************/ + +static void ltdc_common_test(void) +{ + int n; + int c; + int x; + int y; + uint32_t colorkey; + struct ltdc_area_s area; + FAR struct surface *sur; + + dbg("Set layer 2 to the active layer, blend with subjacent layer 1\n"); + + sur = ltdc_get_surface(LTDC_LAYER_TOP); + + ltdc_simple_draw(&sur->vinfo, &sur->pinfo); + + usleep(1000000); + + colorkey = LTDC_EXAMPLE_NCOLORS; + + /* Perform area test */ + + dbg("Perform area test\n"); + + /* Set layer in the middle of the screen */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + /* Enable colorkeying */ + + sur->layer->setblendmode(sur->layer, LTDC_BLEND_COLORKEY); + + /* Update the layer */ + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + /* Move right */ + + for (n = 0, c = 4; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move down */ + + for (n = 0, c = 4; n < sur->vinfo.yres/8; n++) + { + area.ypos++; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move left */ + + for (n = 0, c = 4; n < sur->vinfo.xres/4; n++) + { + area.xpos--; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move up */ + + for (n = 0, c = 4; n < sur->vinfo.yres/8; n++) + { + area.ypos--; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move back to the middle */ + + for (n = 0, c = 4; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Perform positioning test */ + + dbg("Perform positioning test\n"); + + /* Set layer in the middle of the screen */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + /* Move right */ + + for (n = 0, c = 4; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, sur->vinfo.yres/4); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move down */ + + for (n = 0, c = 4; n < sur->vinfo.yres/8; n++) + { + area.ypos++; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, sur->vinfo.yres/4); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move left */ + + for (n = 0, c = 4; n < sur->vinfo.xres/4; n++) + { + area.xpos--; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, sur->vinfo.yres/4); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move up */ + + for (n = 0, c = 4; n < sur->vinfo.yres/8; n++) + { + area.ypos--; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, sur->vinfo.yres/4); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move back to the middle */ + + for (n = 0, c = 4; n < sur->vinfo.xres/8; n++) + { + area.xpos++; + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4, sur->vinfo.yres/4); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Perform Reference position */ + + dbg("Perform reference positioning test\n"); + + /* Set layer in the middle of the screen */ + + area.xpos = sur->vinfo.xres/4; + area.ypos = sur->vinfo.yres/4; + area.xres = sur->vinfo.xres/2; + area.yres = sur->vinfo.yres/2; + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + /* Move right */ + + for (x = 0, c = 4; x < sur->vinfo.xres/8; x++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - x, + sur->vinfo.yres/4); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move down */ + + for (y = 0, c = 4; y < sur->vinfo.yres/8; y++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - x, + sur->vinfo.yres/4 - y); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move left */ + + for (x = 0, c = 4; x < sur->vinfo.xres/4; x++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - sur->vinfo.xres/8 + x, + sur->vinfo.yres/4 - y); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move up */ + + for (y = 0, c = 4; y < sur->vinfo.yres/8; y++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 - sur->vinfo.xres/8 + x, + sur->vinfo.yres/4 - sur->vinfo.yres/8 + y); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + /* Move back to the middle */ + + for (x = 0, c = 4; x < sur->vinfo.xres/8; x++) + { + sur->layer->setarea(sur->layer, &area, + sur->vinfo.xres/4 + sur->vinfo.xres/8 - x, + sur->vinfo.yres/4 - sur->vinfo.yres/8 + y); + if (c++ == 4) + { + c = 0; + if (colorkey == LTDC_EXAMPLE_NCOLORS) + colorkey = LTDC_RED; + else + colorkey++; + + sur->layer->setcolorkey(sur->layer, 0xff000000 | g_rgb24[colorkey]); + } + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + } + + usleep(1000000); + + /* Restore original size */ + + area.xpos = 0; + area.ypos = 0; + area.xres = sur->vinfo.xres; + area.yres = sur->vinfo.yres; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + sur->layer->setarea(sur->layer, &area, area.xpos, area.ypos); + + /* Disable colorkeying */ + + sur->layer->setcolorkey(sur->layer, 0); + sur->layer->setblendmode(sur->layer, LTDC_BLEND_NONE); + + dbg("Update the layer to fullscreen\n"); + + sur->layer->update(sur->layer, LTDC_SYNC_VBLANK); + + usleep(1000000); +} + +#ifdef CONFIG_STM32_LTDC_L2 +/****************************************************************************** + * Name: ltdc_alpha_blend_test + * + * Description: + * Perform layer blend test + * + *****************************************************************************/ + +static void ltdc_alpha_blend_test(void) +{ + int i; + FAR struct surface *top; + FAR struct surface *bottom; + struct ltdc_area_s area; + + /* Ensure operation on layer 2 */ + + dbg("Set layer 2 to the active layer, blend with subjacent layer 1\n"); + + top = ltdc_get_surface(LTDC_LAYER_TOP); + bottom = ltdc_get_surface(LTDC_LAYER_BOTTOM); + + dbg("top = %p, bottom = %p\n", top->pinfo.fbmem, bottom->pinfo.fbmem); + + ltdc_simple_draw(&top->vinfo, &top->pinfo); + + dbg("Fill layer1 with color black\n"); + + ltdc_drawcolor(&bottom->vinfo, bottom->pinfo.fbmem, + bottom->vinfo.xres, bottom->vinfo.yres, + ltdc_color(&bottom->vinfo, LTDC_BLACK)); + + area.xpos = top->vinfo.xres/4; + area.ypos = top->vinfo.yres/4; + area.xres = top->vinfo.xres/2; + area.yres = top->vinfo.yres/2; + + dbg("Set area to xpos = %d, ypos = %d, xres = %d, yres = %d\n", + area.xpos, area.ypos, area.xres, area.yres); + + top->layer->setarea(top->layer, &area, area.xpos, area.ypos); + + dbg("Set alpha blending with bottom layer1\n"); + + top->layer->setblendmode(top->layer, LTDC_BLEND_ALPHA); + dbg("Disable blending for bottom layer1 to make the layer color visible\n"); + + bottom->layer->setblendmode(bottom->layer, LTDC_BLEND_NONE); + bottom->layer->setalpha(bottom->layer, 0xff); + + dbg("Fill bottom layer1 with color black\n"); + + ltdc_drawcolor(&bottom->vinfo, bottom->pinfo.fbmem, + bottom->vinfo.xres, bottom->vinfo.yres, + ltdc_color(&bottom->vinfo, LTDC_BLACK)); + + dbg("Blend in black subjacent layer\n"); + + for (i = 255; i >= 0; i--) + { + top->layer->setalpha(top->layer, i); + top->layer->update(top->layer, LTDC_UPDATE_SIM|LTDC_SYNC_VBLANK); + } + + dbg("Fill bottom layer1 with color red\n"); + + ltdc_drawcolor(&bottom->vinfo, bottom->pinfo.fbmem, + bottom->vinfo.xres, bottom->vinfo.yres, + ltdc_color(&bottom->vinfo, LTDC_RED)); + + dbg("Blend in red subjacent layer\n"); + + for (i = 255; i >= 0; i--) + { + top->layer->setalpha(top->layer, i); + top->layer->update(top->layer, LTDC_UPDATE_SIM|LTDC_SYNC_VBLANK); + } + + dbg("Fill bottom layer1 with color green\n"); + + ltdc_drawcolor(&bottom->vinfo, bottom->pinfo.fbmem, + bottom->vinfo.xres, bottom->vinfo.yres, + ltdc_color(&bottom->vinfo, LTDC_GREEN)); + + dbg("Blend in green subjacent layer\n"); + + for (i = 255; i >= 0; i--) + { + top->layer->setalpha(top->layer, i); + top->layer->update(top->layer, LTDC_UPDATE_SIM|LTDC_SYNC_VBLANK); + } + + dbg("Fill bottom layer1 with color blue\n"); + + ltdc_drawcolor(&bottom->vinfo, bottom->pinfo.fbmem, + bottom->vinfo.xres, bottom->vinfo.yres, + ltdc_color(&bottom->vinfo, LTDC_BLUE)); + + dbg("Blend in blue subjacent layer\n"); + + for (i = 255; i >= 0; i--) + { + top->layer->setalpha(top->layer, i); + top->layer->update(top->layer, LTDC_UPDATE_SIM|LTDC_SYNC_VBLANK); + } + + dbg("Fill bottom layer1 with color white\n"); + + ltdc_drawcolor(&bottom->vinfo, bottom->pinfo.fbmem, + bottom->vinfo.xres, bottom->vinfo.yres, + ltdc_color(&bottom->vinfo, LTDC_WHITE)); + + dbg("Blend in white subjacent layer\n"); + + for (i = 255; i >= 0; i--) + { + top->layer->setalpha(top->layer, i); + top->layer->update(top->layer, LTDC_UPDATE_SIM|LTDC_SYNC_VBLANK); + } + + /* Restore settings */ + + area.xpos = 0; + area.ypos = 0; + area.xres = top->vinfo.xres; + area.yres = top->vinfo.yres; + + top->layer->setarea(top->layer, &area, area.xpos, area.ypos); + top->layer->setalpha(top->layer, 255); + top->layer->setblendmode(top->layer, LTDC_BLEND_NONE); + top->layer->update(top->layer, LTDC_UPDATE_SIM|LTDC_SYNC_VBLANK); +} + +/****************************************************************************** + * Name: ltdc_flip_test + * + * Description: + * Perform layer flip test + * + *****************************************************************************/ + +static void ltdc_flip_test(void) +{ + FAR struct surface *active = ltdc_get_surface(LTDC_LAYER_ACTIVE); + FAR struct surface *inactive = ltdc_get_surface(LTDC_LAYER_INACTIVE); + + /* Flip with non blend */ + + dbg("Perform flip test without blending\n"); + + dbg("active->pinfo.fbmem = %p\n", active->pinfo.fbmem); + dbg("inactive->pinfo.fbmem = %p\n", inactive->pinfo.fbmem); + + dbg("Ensure that both layer opaque\n"); + active->layer->setalpha(active->layer, 0xff); + inactive->layer->setalpha(inactive->layer, 0xff); + active->layer->setblendmode(active->layer, LTDC_BLEND_NONE); + inactive->layer->setblendmode(inactive->layer, LTDC_BLEND_NONE); + + dbg("Set the active layer to fullscreen black\n"); + ltdc_drawcolor(&active->vinfo, active->pinfo.fbmem, + active->vinfo.xres, active->vinfo.yres, + ltdc_color(&active->vinfo, LTDC_BLACK)); + + usleep(1000000); + + dbg("Set invisible layer to fullscreen blue\n"); + ltdc_drawcolor(&inactive->vinfo, inactive->pinfo.fbmem, + inactive->vinfo.xres, inactive->vinfo.yres, + ltdc_color(&inactive->vinfo, LTDC_BLUE)); + + usleep(1000000); + + dbg("Flip layer to see the blue fullscreen\n"); + inactive->layer->update(inactive->layer, + LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Active layer is now inactive */ + + dbg("Set invisible layer to fullscreen green\n"); + ltdc_drawcolor(&active->vinfo, active->pinfo.fbmem, + active->vinfo.xres, active->vinfo.yres, + ltdc_color(&active->vinfo, LTDC_GREEN)); + + usleep(1000000); + + dbg("Flip layer to see the green fullscreen\n"); + inactive->layer->update(inactive->layer, + LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + usleep(1000000); + + dbg("Set invisible layer to fullscreen red\n"); + ltdc_drawcolor(&inactive->vinfo, inactive->pinfo.fbmem, + inactive->vinfo.xres, inactive->vinfo.yres, + ltdc_color(&inactive->vinfo, LTDC_RED)); + + usleep(1000000); + + dbg("Flip layer to see the red fullscreen\n"); + inactive->layer->update(inactive->layer, LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Flip with alpha blend */ + + dbg("Perform flip test with alpha blending\n"); + + /* Set the bottom layer to the current active layer */ + + active = ltdc_get_surface(LTDC_LAYER_BOTTOM); + inactive = ltdc_get_surface(LTDC_LAYER_TOP); + + dbg("Ensure that both layer fullscreen black\n"); + ltdc_drawcolor(&active->vinfo, active->pinfo.fbmem, + active->vinfo.xres, active->vinfo.yres, + ltdc_color(&active->vinfo, LTDC_BLACK)); + ltdc_drawcolor(&inactive->vinfo, inactive->pinfo.fbmem, + inactive->vinfo.xres, inactive->vinfo.yres, + ltdc_color(&inactive->vinfo, LTDC_BLACK)); + + dbg("Ensure that both layer semitransparent\n"); + active->layer->setalpha(active->layer, 0x7f); + inactive->layer->setalpha(inactive->layer, 0x7f); + active->layer->setblendmode(active->layer, LTDC_BLEND_ALPHA); + inactive->layer->setblendmode(inactive->layer, LTDC_BLEND_ALPHA); + + dbg("Enter in the flip mode sequence\n"); + dbg("Set the bottom layer to the active layer\n"); + dbg("Also update both layer simultaneous\n"); + active->layer->update(active->layer,LTDC_UPDATE_ACTIVATE| + LTDC_UPDATE_SIM| + LTDC_UPDATE_FLIP| + LTDC_SYNC_VBLANK); + + usleep(1000000); + + dbg("Set invisible layer to fullscreen blue\n"); + ltdc_drawcolor(&inactive->vinfo, inactive->pinfo.fbmem, + inactive->vinfo.xres, inactive->vinfo.yres, + ltdc_color(&inactive->vinfo, LTDC_BLUE)); + + usleep(1000000); + + dbg("Flip layer to see the blue fullscreen\n"); + inactive->layer->update(active->layer, LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Active layer is top now */ + + dbg("Set invisible layer to fullscreen green\n"); + ltdc_drawcolor(&active->vinfo, active->pinfo.fbmem, + active->vinfo.xres, active->vinfo.yres, + ltdc_color(&active->vinfo, LTDC_GREEN)); + + usleep(1000000); + + dbg("Flip layer to see the green fullscreen\n"); + inactive->layer->update(active->layer, + LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Active layer is bottom now */ + + dbg("Set invisible layer to fullscreen red\n"); + ltdc_drawcolor(&inactive->vinfo, inactive->pinfo.fbmem, + inactive->vinfo.xres, inactive->vinfo.yres, + ltdc_color(&inactive->vinfo, LTDC_RED)); + + usleep(1000000); + + dbg("Flip layer to see the red fullscreen\n"); + inactive->layer->update(active->layer, LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + usleep(1000000); + + /* Active layer is top now */ + + dbg("Set bottom layer back to fullscreen black\n"); + ltdc_drawcolor(&active->vinfo, active->pinfo.fbmem, + active->vinfo.xres, active->vinfo.yres, + ltdc_color(&active->vinfo, LTDC_BLACK)); + + dbg("Set bottom layer to alpha %d and disable blend mode\n", 0xff); + inactive->layer->setalpha(active->layer, 0xff); + inactive->layer->setblendmode(active->layer, LTDC_BLEND_NONE); + + usleep(1000000); + + dbg("Flip layer to see the black fullscreen\n"); + inactive->layer->update(active->layer, + LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK); + + /* Active layer is bottom now */ + + usleep(1000000); + + /* Disable flip sequence. Restore layers with there current settings and + * activate them. + */ + + /* Restore settings */ + + dbg("Finally set the top layer back to fullscreen black\n"); + ltdc_drawcolor(&inactive->vinfo, inactive->pinfo.fbmem, + inactive->vinfo.xres, inactive->vinfo.yres, + ltdc_color(&inactive->vinfo, LTDC_BLACK)); + + dbg("Set top layer to alpha %d and disable blend mode\n", 0xff); + inactive->layer->setalpha(inactive->layer, 0xff); + inactive->layer->setblendmode(inactive->layer, LTDC_BLEND_NONE); + + dbg("Flip to the top layer\n"); + inactive->layer->update(inactive->layer, + LTDC_UPDATE_ACTIVATE|LTDC_SYNC_VBLANK); + +} +#endif /* CONFIG_STM32_LTDC_L2 */ +#endif /* CONFIG_STM32_LTDC_INTERFACE */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * ltdc_main + ****************************************************************************/ + +int ltdc_main(int argc, char *argv[]) +{ + FAR struct fb_planeinfo_s pinfo; + FAR struct fb_videoinfo_s vinfo; + FAR struct fb_vtable_s *fbtable; + + if (up_fbinitialize()<0) + { + dbg("up_fbinitialize() failed\n"); + return -1; + } + + fbtable = up_fbgetvplane(0); + + if (!fbtable) + { + dbg("up_fbgetvplane() failed\n"); + return -1; + } + + if (fbtable->getvideoinfo(fbtable, &vinfo)<0) + { + dbg("getvideoinfo failed\n"); + return -1; + } + + if (fbtable->getplaneinfo(fbtable, 0, &pinfo)<0) + { + dbg("getplaneinfo failed\n"); + return -1; + } + + dbg("fb is configured with: xres = %d, yres = %d, \ + fb start address = %p, fb size = %d, fmt = %d, bpp = %d\n", + vinfo.xres, vinfo.yres, pinfo.fbmem, pinfo.fblen, + vinfo.fmt, pinfo.bpp); + +#ifdef CONFIG_FB_CMAP + ltdc_init_cmap(); + + if (vinfo.fmt == FB_FMT_RGB8) + { + if (fbtable->putcmap(fbtable, &g_cmap) != OK) + { + dbg("putcmap() failed\n"); + return -1; + } + } +#endif + + /* Tests */ + + ltdc_simple_draw(&vinfo, &pinfo); + + usleep(1000000); + +#ifdef CONFIG_STM32_LTDC_INTERFACE + ltdc_init_surface(0, LTDC_LAYER_ACTIVE); +#ifdef CONFIG_STM32_LTDC_L2 + ltdc_init_surface(1, LTDC_LAYER_INACTIVE); +#endif + + usleep(1000000); + + ltdc_setget_test(); + + usleep(1000000); + + ltdc_area_test(); + + usleep(1000000); + + ltdc_color_test(); + + usleep(1000000); + + ltdc_colorkey_test(); + + usleep(1000000); + + ltdc_common_test(); + +#ifdef CONFIG_STM32_LTDC_L2 + usleep(1000000); + + ltdc_alpha_blend_test(); + + usleep(1000000); + + ltdc_flip_test(); + +#endif /* CONFIG_STM32_LTDC_L2 */ +#endif /* CONFIG_STM32_LTDC_INTERFACE */ + return 0; +} -- cgit v1.2.3