nuttx-apps/examples/ltdc/ltdc_main.c

2180 lines
55 KiB
C
Raw Normal View History

/****************************************************************************
* examples/ltdc/ltdc_main.c
*
* Copyright (C) 2008, 2011-2012, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 "ltdc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* 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
#ifdef CONFIG_FB_TRANSPARENCY
static uint8_t g_color[4*LTDC_EXAMPLE_NCOLORS];
#else
static uint8_t g_color[3*LTDC_EXAMPLE_NCOLORS];
#endif
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]
#ifdef CONFIG_FB_TRANSPARENCY
,.transp = &g_color[3*LTDC_EXAMPLE_NCOLORS]
#endif
};
#endif
/****************************************************************************
* Private Function
****************************************************************************/
#ifdef CONFIG_STM32_LTDC_INTERFACE
/****************************************************************************
* 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)
{
_err("ERROR: up_ltdcgetlayer() failed\n");
return -1;
}
if (sur->layer->getvideoinfo(sur->layer, &sur->vinfo) != OK)
{
_err("ERROR: getvideoinfo() failed\n");
return -1;
}
if (sur->layer->getplaneinfo(sur->layer, 0, &sur->pinfo) != OK)
{
_err("ERROR: getplaneinfo() failed\n");
return -1;
}
_info("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
#ifdef CONFIG_STM32_DMA2D
/* Initialize dma2d layer */
if (sur->layer->getlid(sur->layer, &lid, LTDC_LAYER_DMA2D) != OK)
{
_err("ERROR: getlid() failed\n");
return -1;
}
sur->dma2d = up_dma2dgetlayer(lid);
if (sur->dma2d == NULL)
{
_err("ERROR: up_dma2dgetlayer() failed\n");
return -1;
}
#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);
_info("Perform set and get test\n");
/* setalpha */
ret = sur->layer->setalpha(sur->layer, 0x7f);
if (ret != OK)
{
_err("ERROR: setalpha() failed\n");
}
ret = sur->layer->getalpha(sur->layer, &alpha);
if (ret != OK || alpha != 0x7f)
{
_err("ERROR: getalpha() failed\n");
}
/* setcolor */
ret = sur->layer->setcolor(sur->layer, 0x11223344);
if (ret != OK)
{
_err("ERROR: setcolor() failed\n");
}
ret = sur->layer->getcolor(sur->layer, &color);
if (ret != OK || color != 0x11223344)
{
_err("ERROR: getcolor() failed\n");
}
/* setcolorkey */
ret = sur->layer->setcolorkey(sur->layer, 0x55667788);
if (ret != OK)
{
_err("ERROR: setcolorkey() failed\n");
}
ret = sur->layer->getcolorkey(sur->layer, &color);
if (ret != OK || color != 0x55667788)
{
_err("ERROR: getcolorkey() failed\n");
}
/* setblendmode */
ret = sur->layer->setblendmode(sur->layer, LTDC_BLEND_NONE);
if (ret != OK)
{
_err("ERROR: setblendmode() failed\n");
}
ret = sur->layer->getblendmode(sur->layer, &mode);
if (ret != OK || mode != LTDC_BLEND_NONE)
{
_err("ERROR: 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)
{
_err("ERROR: 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)
{
_err("ERROR: getarea() failed\n");
}
#ifdef CONFIG_FB_CMAP
if (sur->vinfo.fmt == FB_FMT_RGB8)
{
FAR struct fb_cmap_s *cmap = ltdc_createcmap(LTDC_EXAMPLE_NCOLORS);
ltdc_clrcolor(g_cmap.red, 0x11, LTDC_EXAMPLE_NCOLORS);
ltdc_clrcolor(g_cmap.blue, 0x22, LTDC_EXAMPLE_NCOLORS);
ltdc_clrcolor(g_cmap.green, 0x33, LTDC_EXAMPLE_NCOLORS);
#ifdef CONFIG_FB_TRANSPARENCY
ltdc_clrcolor(g_cmap.transp, 0x44, LTDC_EXAMPLE_NCOLORS);
#endif
ret = sur->layer->setclut(sur->layer, &g_cmap);
if (ret != OK)
{
_err("ERROR: setclut() failed\n");
}
/* Clear all colors to black */
ltdc_clrcolor(cmap->red, 0, LTDC_EXAMPLE_NCOLORS);
ltdc_clrcolor(cmap->blue, 0, LTDC_EXAMPLE_NCOLORS);
ltdc_clrcolor(cmap->green, 0, LTDC_EXAMPLE_NCOLORS);
#ifdef CONFIG_FB_TRANSPARENCY
ltdc_clrcolor(cmap->transp, 0, LTDC_EXAMPLE_NCOLORS);
#endif
ret = sur->layer->getclut(sur->layer, cmap);
if (ret != OK)
{
_err("ERROR: getclut() failed\n");
}
#ifdef CONFIG_FB_TRANSPARENCY
if (ltdc_cmpcolor(g_cmap.red, cmap->red, LTDC_EXAMPLE_NCOLORS) ||
ltdc_cmpcolor(g_cmap.blue, cmap->blue, LTDC_EXAMPLE_NCOLORS) ||
ltdc_cmpcolor(g_cmap.green, cmap->green, LTDC_EXAMPLE_NCOLORS) ||
ltdc_cmpcolor(g_cmap.transp, cmap->transp, LTDC_EXAMPLE_NCOLORS))
#else
if (ltdc_cmpcolor(g_cmap.red, cmap->red, LTDC_EXAMPLE_NCOLORS) ||
ltdc_cmpcolor(g_cmap.blue, cmap->blue, LTDC_EXAMPLE_NCOLORS) ||
ltdc_cmpcolor(g_cmap.green, cmap->green, LTDC_EXAMPLE_NCOLORS))
#endif
{
_err("ERROR: getclut() failed, unexpected cmap content\n");
}
ltdc_deletecmap(cmap);
/* Restore the origin cmap */
ltdc_init_cmap();
ret = sur->layer->setclut(sur->layer, &g_cmap);
if (ret != OK)
{
_err("ERROR: setclut() 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 */
_info("Set default color to black\n");
sur->layer->setcolor(sur->layer, 0xff000000);
_info("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 */
_info("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);
_info("Update the layer, should be black outside the colorful rectangle\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
usleep(1000000);
/* Default Color red */
_info("Update the layer, should be red outside the colorful rectangle\n");
sur->layer->setcolor(sur->layer, 0xffff0000);
_info("Update the layer\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
usleep(1000000);
/* Default Color green */
_info("Update the layer, should be green outside the colorful rectangle\n");
sur->layer->setcolor(sur->layer, 0xff00ff00);
_info("Update the layer\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
usleep(1000000);
/* Default Color blue */
_info("Update the layer, should be blue outside the colorful rectangle\n");
sur->layer->setcolor(sur->layer, 0xff0000ff);
_info("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;
_info("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 */
_info("Set default color to black\n");
sur->layer->setcolor(sur->layer, 0);
_info("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 */
_info("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 */
_info("Set colorkey to white\n");
sur->layer->setcolorkey(sur->layer, 0xffffff);
_info("Update the layer\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
usleep(1000000);
/* Color key red */
_info("Set colorkey to red\n");
sur->layer->setcolorkey(sur->layer, 0xff0000);
_info("Update the layer\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
usleep(1000000);
/* Color key green */
_info("Set colorkey to green\n");
sur->layer->setcolorkey(sur->layer, 0xff00);
_info("Update the layer\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
usleep(1000000);
/* Color key red */
_info("Set colorkey to blue\n");
sur->layer->setcolorkey(sur->layer, 0xff);
_info("Update the layer\n");
sur->layer->update(sur->layer, LTDC_SYNC_VBLANK|LTDC_SYNC_WAIT);
_info("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;
_info("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);
_info("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);
_info("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;
_info("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);
_info("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;
_info("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);
_info("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;
_info("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);
_info("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;
_info("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);
_info("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 */
_info("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 */
_info("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 */
_info("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;
_info("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);
_info("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;
_info("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 */
_info("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 */
_info("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 */
_info("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;
_info("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);
_info("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 */
_info("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);
_info("top = %p, bottom = %p\n", top->pinfo.fbmem, bottom->pinfo.fbmem);
ltdc_simple_draw(&top->vinfo, &top->pinfo);
_info("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;
_info("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);
_info("Set alpha blending with bottom layer1\n");
top->layer->setblendmode(top->layer, LTDC_BLEND_ALPHA);
_info("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);
_info("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));
_info("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);
}
_info("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));
_info("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);
}
_info("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));
_info("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);
}
_info("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));
_info("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);
}
_info("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));
_info("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 */
_info("Perform flip test without blending\n");
_info("active->pinfo.fbmem = %p\n", active->pinfo.fbmem);
_info("inactive->pinfo.fbmem = %p\n", inactive->pinfo.fbmem);
_info("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);
_info("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);
_info("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);
_info("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 */
_info("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);
_info("Flip layer to see the green fullscreen\n");
inactive->layer->update(inactive->layer,
LTDC_UPDATE_FLIP|LTDC_SYNC_VBLANK);
usleep(1000000);
_info("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);
_info("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 */
_info("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);
_info("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));
_info("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);
_info("Enter in the flip mode sequence\n");
_info("Set the bottom layer to the active layer\n");
_info("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);
_info("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);
_info("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 */
_info("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);
_info("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 */
_info("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);
_info("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 */
_info("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));
_info("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);
_info("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 */
_info("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));
_info("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);
_info("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
****************************************************************************/
/****************************************************************************
* Name: ltdc_clrcolor
*
* Description:
* Fills the color value table with an specific color.
* This works like memset but for 8-bit aligned memory.
*
* Parameter:
* color - Pointer to the color value table
* value - The color to set
* size - the size of the color value table
*
****************************************************************************/
void ltdc_clrcolor(uint8_t *color, uint8_t value, size_t size)
{
while (size--)
{
*color++ = value;
}
}
/****************************************************************************
* Name: ltdc_cmpcolor
*
* Description:
* Compares two color value tables
*
* Parameter:
* color1 - color value table 1
* color2 - color value table 2
* size - the size of the color value table
*
* Return:
* 0 - if equal otherwise unequal to 0
*
****************************************************************************/
int ltdc_cmpcolor(uint8_t *color1, uint8_t *color2, size_t size)
{
int n;
for (n = 0; !n && size; --size)
{
n = *color1++ - *color2++;
}
return n;
}
/****************************************************************************
* Name: ltdc_init_cmap
*
* Description:
* Initialize the color lookup table
*
****************************************************************************/
#ifdef CONFIG_FB_CMAP
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;
#ifdef CONFIG_FB_TRANSPARENCY
g_cmap.transp[0] = 0xff;
g_cmap.transp[1] = 0xff;
g_cmap.transp[2] = 0xff;
g_cmap.transp[3] = 0xff;
g_cmap.transp[4] = 0xff;
#endif
}
/****************************************************************************
* Name: ltdc_createcmap
*
* Description:
* Initialize
*
****************************************************************************/
FAR struct fb_cmap_s * ltdc_createcmap(uint16_t ncolors)
{
FAR struct fb_cmap_s *cmap = malloc(sizeof(struct fb_cmap_s));
if (cmap)
{
#ifdef CONFIG_FB_TRANSPARENCY
uint8_t *clut = malloc(4 * ncolors * sizeof(uint8_t));
#else
uint8_t *clut = malloc(3 * ncolors * sizeof(uint8_t));
#endif
if (!clut)
{
_err("ERROR: malloc() failed\n");
free(cmap);
return NULL;;
}
#ifdef CONFIG_FB_TRANSPARENCY
cmap->transp = &clut[0];
cmap->red = &clut[1 * ncolors * sizeof(uint8_t)];
cmap->green = &clut[2 * ncolors * sizeof(uint8_t)];
cmap->blue = &clut[3 * ncolors * sizeof(uint8_t)];
#else
cmap->red = &clut[0];
cmap->green = &clut[1 * ncolors * sizeof(uint8_t)];
cmap->blue = &clut[2 * ncolors * sizeof(uint8_t)];
#endif
cmap->first = 0;
cmap->len = ncolors;
}
return cmap;
}
/****************************************************************************
* Name: ltdc_deletecmap
*
* Description:
* Initialize
*
****************************************************************************/
void ltdc_deletecmap(FAR struct fb_cmap_s *cmap)
{
if (cmap)
{
#ifdef CONFIG_FB_TRANSPARENCY
free(cmap->transp);
#else
free(cmap->red);
#endif
free(cmap);
}
}
#endif
/****************************************************************************
* Name: ltdc_color
*
* Description:
* Get the correct color value to the pixel format
*
****************************************************************************/
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:
_err("ERROR: 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
*
****************************************************************************/
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;
_info("draw a red and green rectangle in the upper half\n");
_info("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
*
****************************************************************************/
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 */
_info("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
*
****************************************************************************/
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)
{
_err("ERROR: getlid() failed\n");
_exit(1);
}
if (lid < 0 || lid > 1)
{
_err("ERROR: invalid layer id %d\n", lid);
_exit(1);
}
return &g_surface[lid];
}
#endif
/****************************************************************************
* 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) < 0)
{
_err("ERROR: up_fbinitialize() failed\n");
return -1;
}
fbtable = up_fbgetvplane(0,0);
if (!fbtable)
{
_err("ERROR: up_fbgetvplane() failed\n");
return -1;
}
if (fbtable->getvideoinfo(fbtable, &vinfo)<0)
{
_err("ERROR: getvideoinfo failed\n");
return -1;
}
if (fbtable->getplaneinfo(fbtable, 0, &pinfo)<0)
{
_err("ERROR: getplaneinfo failed\n");
return -1;
}
_info("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)
{
_err("ERROR: 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();
#ifdef CONFIG_STM32_DMA2D
ltdc_dma2d_main();
#endif
#endif /* CONFIG_STM32_LTDC_L2 */
#endif /* CONFIG_STM32_LTDC_INTERFACE */
return 0;
}