Squashed commit of the following:

apps/graphics/ft80x:  Replace polling logic with gentler signal logic when waitinf for the CMD FIFO to become empty.
    apps/examples/ft80x:  Add first co-processor example.
    apps/graphics:  Extend library to manage display lists either in display memory (RAM DL) or provided directly to th co-processor FIFO (RAM CMD).
    apps/examples/ft80x:  Some minor clean-up.  Trivial changes for coprocessor support.
This commit is contained in:
Gregory Nutt 2018-02-20 15:23:05 -06:00
parent 2f2fb92ae3
commit ecfdf073fc
11 changed files with 1215 additions and 172 deletions

View File

@ -141,16 +141,18 @@ extern "C"
/* GPU Primitive display examples */
#ifndef CONFIG_EXAMPLES_FT80X_EXCLUDE_BITMAPS
int ft80x_bitmaps(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_prim_bitmaps(int fd, FAR struct ft80x_dlbuffer_s *buffer);
#endif
int ft80x_points(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_lines(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_linestrip(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_edgestrip_r(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_rectangles(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_prim_points(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_prim_lines(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_prim_linestrip(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_prim_edgestrip_r(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_prim_rectangles(int fd, FAR struct ft80x_dlbuffer_s *buffer);
/* Co-processor display examples */
int ft80x_coproc_progressbar(int fd, FAR struct ft80x_dlbuffer_s *buffer);
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -54,8 +54,322 @@
****************************************************************************/
/****************************************************************************
* Name:
* Name: ft80x_coproc_progressbar
*
* Description:
* Demonstrate the progress bar command
*
****************************************************************************/
int ft80x_coproc_progressbar(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
int16_t xoffset;
int16_t yoffset;
int16_t ydist = FT80X_DISPLAY_WIDTH / 12;
int16_t ysz = FT80X_DISPLAY_WIDTH / 24;
int ret;
/* Formatted output chunks */
union
{
struct
{
struct ft80x_cmd32_s clearrgb;
struct ft80x_cmd32_s clear;
struct ft80x_cmd32_s colorrgb;
} a;
struct
{
struct ft80x_cmd32_s colorrgb;
struct ft80x_cmd_bgcolor_s bgcolor;
struct ft80x_cmd_progress_s progress;
struct ft80x_cmd32_s colora;
struct ft80x_cmd_text_s text;
} b;
struct
{
struct ft80x_cmd32_s colorrgb;
struct ft80x_cmd_bgcolor_s bgcolor;
} c;
struct
{
struct ft80x_cmd_progress_s progress;
struct ft80x_cmd_bgcolor_s bgcolor;
} d;
struct
{
struct ft80x_cmd_progress_s progress;
struct ft80x_cmd_text_s text;
} e;
struct ft80x_cmd_progress_s progress;
} cmds;
/* Create the hardware display list */
ret = ft80x_dl_start(fd, buffer, true);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_start failed: %d\n", ret);
return ret;
}
cmds.a.clearrgb.cmd = FT80X_CLEAR_COLOR_RGB(64, 64, 64);
cmds.a.clear.cmd = FT80X_CLEAR(1 ,1, 1);
cmds.a.colorrgb.cmd = FT80X_COLOR_RGB(0xff, 0xff, 0xff);
/* Copy the commands into the display list */
ret = ft80x_dl_data(fd, buffer, &cmds.a, sizeof(cmds.a));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
/* Draw progress bar with flat effect */
cmds.b.colorrgb.cmd = FT80X_COLOR_RGB(0xff, 0xff, 0xff);
cmds.b.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.b.bgcolor.c = 0x404080;
cmds.b.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.b.progress.x = 20;
cmds.b.progress.y = 10;
cmds.b.progress.w = 120;
cmds.b.progress.h = 20;
cmds.b.progress.options = FT80X_OPT_FLAT;
cmds.b.progress.val = 50;
cmds.b.progress.range = 100;
cmds.b.colora.cmd = FT80X_COLOR_A(255); /* Color A */
cmds.b.text.cmd = FT80X_CMD_TEXT; /* Text */
cmds.b.text.x = 20;
cmds.b.text.y = 40;
cmds.b.text.font = 26;
cmds.b.text.options = 0;
ret = ft80x_dl_data(fd, buffer, &cmds.b, sizeof(cmds.b));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
ret = ft80x_dl_string(fd, buffer, "Flat effect");
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_string failed: %d\n", ret);
return ret;
}
/* Draw progress bar with 3d effect */
cmds.b.colorrgb.cmd = FT80X_COLOR_RGB(0x00, 0xff, 0x00);
cmds.b.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.b.bgcolor.c = 0x800000;
cmds.b.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.b.progress.x = 180;
cmds.b.progress.y = 10;
cmds.b.progress.w = 120;
cmds.b.progress.h = 20;
cmds.b.progress.options = 0;
cmds.b.progress.val = 75;
cmds.b.progress.range = 100;
cmds.b.colora.cmd = FT80X_COLOR_A(255); /* Color A */
cmds.b.text.cmd = FT80X_CMD_TEXT; /* Text */
cmds.b.text.x = 180;
cmds.b.text.y = 40;
cmds.b.text.font = 26;
cmds.b.text.options = 0;
ret = ft80x_dl_data(fd, buffer, &cmds.b, sizeof(cmds.b));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
ret = ft80x_dl_string(fd, buffer, "3D effect");
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_string failed: %d\n", ret);
return ret;
}
/* Draw progress bar with 3d effect and string on top */
cmds.b.colorrgb.cmd = FT80X_COLOR_RGB(0xff, 0x00, 0x00);
cmds.b.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.b.bgcolor.c = 0x000080;
cmds.b.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.b.progress.x = 30;
cmds.b.progress.y = 60;
cmds.b.progress.w = 120;
cmds.b.progress.h = 30;
cmds.b.progress.options = 0;
cmds.b.progress.val = 19660;
cmds.b.progress.range = 65535;
cmds.b.colora.cmd = FT80X_COLOR_RGB(0xff, 0xff, 0xff);
cmds.b.text.cmd = FT80X_CMD_TEXT; /* Text */
cmds.b.text.x = 78;
cmds.b.text.y = 68;
cmds.b.text.font = 26;
cmds.b.text.options = 0;
ret = ft80x_dl_data(fd, buffer, &cmds.b, sizeof(cmds.b));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
ret = ft80x_dl_string(fd, buffer, "3D effect");
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_string failed: %d\n", ret);
return ret;
}
xoffset = 20;
yoffset = 120;
cmds.c.colorrgb.cmd = FT80X_COLOR_RGB(0x00, 0xa0, 0x00);
cmds.c.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.c.bgcolor.c = 0x800000;
ret = ft80x_dl_data(fd, buffer, &cmds.c, sizeof(cmds.c));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
cmds.d.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.d.progress.x = xoffset;
cmds.d.progress.y = yoffset;
cmds.d.progress.w = 150;
cmds.d.progress.h = ysz;
cmds.d.progress.options = 0;
cmds.d.progress.val = 10;
cmds.d.progress.range = 100;
cmds.d.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.d.bgcolor.c = 0x000080;
ret = ft80x_dl_data(fd, buffer, &cmds.d, sizeof(cmds.d));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
yoffset += ydist;
cmds.d.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.d.progress.x = xoffset;
cmds.d.progress.y = yoffset;
cmds.d.progress.w = 150;
cmds.d.progress.h = ysz;
cmds.d.progress.options = 0;
cmds.d.progress.val = 40;
cmds.d.progress.range = 100;
cmds.d.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.d.bgcolor.c = 0xffff00;
ret = ft80x_dl_data(fd, buffer, &cmds.d, sizeof(cmds.d));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
yoffset += ydist;
cmds.d.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.d.progress.x = xoffset;
cmds.d.progress.y = yoffset;
cmds.d.progress.w = 150;
cmds.d.progress.h = ysz;
cmds.d.progress.options = 0;
cmds.d.progress.val = 70;
cmds.d.progress.range = 100;
cmds.d.bgcolor.cmd = FT80X_CMD_BGCOLOR; /* Background color */
cmds.d.bgcolor.c = 0x808080;
ret = ft80x_dl_data(fd, buffer, &cmds.d, sizeof(cmds.d));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
yoffset += ydist;
cmds.e.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.e.progress.x = xoffset;
cmds.e.progress.y = yoffset;
cmds.e.progress.w = 150;
cmds.e.progress.h = ysz;
cmds.e.progress.options = 0;
cmds.e.progress.val = 90;
cmds.e.progress.range = 100;
cmds.e.text.cmd = FT80X_CMD_TEXT; /* Text */
cmds.e.text.x = xoffset + 180;
cmds.e.text.y = 80;
cmds.e.text.font = 26;
cmds.e.text.options = 0;
ret = ft80x_dl_data(fd, buffer, &cmds.e, sizeof(cmds.e));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
ret = ft80x_dl_string(fd, buffer, "40% TopBottom");
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_string failed: %d\n", ret);
return ret;
}
cmds.progress.cmd = FT80X_CMD_PROGRESS; /* Progress bar */
cmds.progress.x = xoffset + 180;
cmds.progress.y = 100;
cmds.progress.w = ysz;
cmds.progress.h = 150;
cmds.progress.options = 0;
cmds.progress.val = 40;
cmds.progress.range = 100;
ret = ft80x_dl_data(fd, buffer, &cmds.progress, sizeof(cmds.progress));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
/* And terminate the display list */
ret = ft80x_dl_end(fd, buffer);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_end failed: %d\n", ret);
}
return ret;
}

View File

@ -66,34 +66,34 @@ struct ft80x_exampleinfo_s
/* GPU Primitive display examples. Most primitives are used, but not many of
* their various options.
*
* FUNCTION PRIMITIVE USED DESCRIPTION
* ---------------------- --------------- ----------------------------------
* ft80x_prim_bitmaps BITMAPS Bitmap drawing primitive
* ft80x_prim_points POINTS Point drawing primitive
* ft80x_prim_lines LINES Line drawing primitive
* ft80x_prim_linestrip LINE_STRIP Line strip drawing primitive
* ft80x_prim_edgestrip_r EDGE_STRIP_R Edge strip right side drawing
primitive
* --None-- EDGE_STRIP_L Edge strip left side drawing
primitive
* --None-- EDGE_STRIP_A Edge strip above side drawing
primitive
* --None-- EDGE_STRIP_B Edge strip below side drawing
primitive
* ft80x_prim_rectangles RECTS Rectangle drawing primitive
*/
static const struct ft80x_exampleinfo_s g_primitives[] =
{
/* NAME EXAMPLE ENTRY PRIMITIVE */
#ifndef CONFIG_EXAMPLES_FT80X_EXCLUDE_BITMAPS
{ "Bitmaps", ft80x_bitmaps }, /* BITMAPS Bitmap drawing
* primitive */
{ "Bitmaps", ft80x_prim_bitmaps },
#endif
{ "Points", ft80x_points }, /* POINTS Point drawing
* primitive */
{ "Lines", ft80x_lines }, /* LINES Line drawing */
{ "Line Strip", ft80x_linestrip }, /* LINE_STRIP Line strip drawing
* primitive */
{ "Edge Strip R", ft80x_edgestrip_r }, /* EDGE_STRIP_R Edge strip right
* side drawing
* primitive */
/* EDGE_STRIP_L Edge strip left
* side drawing
* primitive */
/* EDGE_STRIP_A Edge strip above
* side drawing
* primitive */
/* EDGE_STRIP_B Edge strip below
* side drawing
* primitive */
{ "Rectangles", ft80x_rectangles } /* RECTS Rectangle drawing
* primitive */
{ "Points", ft80x_prim_points },
{ "Lines", ft80x_prim_lines },
{ "Line Strip", ft80x_prim_linestrip },
{ "Edge Strip R", ft80x_prim_edgestrip_r },
{ "Rectangles", ft80x_prim_rectangles }
};
#define NPRIMITIVES (sizeof(g_primitives) / sizeof(ft80x_example_t))
@ -101,39 +101,36 @@ static const struct ft80x_exampleinfo_s g_primitives[] =
/* Co-processor display examples. Only a small, but interesting, subset
* here co-processor command are exercised and these with only a few of the
* possible options.
*
* FUNCTION CoProc CMD USED DESCRIPTION
* ----------------------- --------------- ----------------------------------
* --None-- CMD_TEXT Draw text
* --None-- CMD_BUTTON Draw a button
* --None-- CMD_CLOCK Draw an analog clock
* --None-- CMD_GAUGE Draw a gauge
* --None-- CMD_KEYS Draw a row of keys
* ft80x_coproc_progressbar CMD_PROGRESS Draw a progress bar
* --None-- CMD_SCROLLBAR Draw a scroll bar
* --None-- CMD_SLIDER Draw a slider
* --None-- CMD_DIAL Draw a rotary dial control
* --None-- CMD_TOGGLE Draw a toggle switch
* --None-- CMD_NUMBER Draw a decimal number
* --None-- CMD_CALIBRATE Execute the touch screen
calibration routine
* --None-- CMD_SPINNER Start an animated spinner
* --None-- CMD_SCREENSAVER Start an animated screensaver
* --None-- CMD_SKETCH Start a continuous sketch update
* --None-- CMD_SNAPSHOT Take a snapshot of the current
screen
* --None-- CMD_LOGO Play device log animation
*/
/* CMD_TEXT Draw text */
/* CMD_BUTTON Draw a button */
/* CMD_CLOCK Draw an analog
* clock */
/* CMD_GAUGE Draw a gauge */
/* CMD_KEYS Draw a row of
* keys */
/* CMD_PROGRESS Draw a progress
* bar */
/* CMD_SCROLLBAR Draw a scroll bar */
/* CMD_SLIDER Draw a slider */
/* CMD_DIAL Draw a rotary
* dial control */
/* CMD_TOGGLE Draw a toggle
* switch */
/* CMD_NUMBER Draw a decimal
* number */
/* CMD_CALIBRATE Execute the touch
* screen calibration
* routine */
/* CMD_SPINNER Start an animated
* spinner */
/* CMD_SCREENSAVER Start an animated
* screensaver */
/* CMD_SKETCH Start a continuous
* sketch update */
/* CMD_SNAPSHOT Take a snapshot
* of the current
* screen */
/* CMD_LOGO Play device logo
* animation */
static const struct ft80x_exampleinfo_s g_coproc[] =
{
{ "Progress Bar", ft80x_coproc_progressbar }
};
#define NCOPROC (sizeof(g_primitives) / sizeof(ft80x_example_t))
/****************************************************************************
* Private Functions
@ -155,7 +152,7 @@ static int ft80x_showname(int fd, FAR struct ft80x_dlbuffer_s *buffer,
/* Create the display list */
ret = ft80x_dl_start(fd, buffer);
ret = ft80x_dl_start(fd, buffer, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_start failed: %d\n", ret);
@ -286,7 +283,11 @@ int ft80x_main(int argc, char *argv[])
}
/* Perform tests on a few of the FT80x Co-processor functions */
#warning missing logic
for (i = 0; i < NCOPROC; i++)
{
(void)ft80x_example(fd, buffer, &g_coproc[i]);
}
free(buffer);
close(fd);

View File

@ -62,7 +62,7 @@
****************************************************************************/
#ifndef CONFIG_EXAMPLES_FT80X_EXCLUDE_BITMAPS
int ft80x_bitmaps(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_prim_bitmaps(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
FAR const struct ft80x_bitmaphdr_s *bmhdr = &g_lenaface_bmhdr;
uint32_t cmds[18];
@ -119,7 +119,7 @@ int ft80x_bitmaps(int fd, FAR struct ft80x_dlbuffer_s *buffer)
/* Create the hardware display list */
ret = ft80x_dl_create(fd, buffer, cmds, 18);
ret = ft80x_dl_create(fd, buffer, cmds, 18, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_create failed: %d\n", ret);
@ -138,7 +138,7 @@ int ft80x_bitmaps(int fd, FAR struct ft80x_dlbuffer_s *buffer)
*
****************************************************************************/
int ft80x_points(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_prim_points(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
uint32_t cmds[15];
int ret;
@ -169,7 +169,7 @@ int ft80x_points(int fd, FAR struct ft80x_dlbuffer_s *buffer)
/* Create the hardware display list */
ret = ft80x_dl_create(fd, buffer, cmds, 15);
ret = ft80x_dl_create(fd, buffer, cmds, 15, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_create failed: %d\n", ret);
@ -187,7 +187,7 @@ int ft80x_points(int fd, FAR struct ft80x_dlbuffer_s *buffer)
*
****************************************************************************/
int ft80x_lines(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_prim_lines(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
uint32_t cmds[14];
uint32_t height;
@ -224,7 +224,7 @@ int ft80x_lines(int fd, FAR struct ft80x_dlbuffer_s *buffer)
/* Create the hardware display list */
ret = ft80x_dl_create(fd, buffer, cmds, 14);
ret = ft80x_dl_create(fd, buffer, cmds, 14, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_create failed: %d\n", ret);
@ -242,7 +242,7 @@ int ft80x_lines(int fd, FAR struct ft80x_dlbuffer_s *buffer)
*
****************************************************************************/
int ft80x_linestrip(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_prim_linestrip(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
uint32_t cmds[7];
int ret;
@ -261,7 +261,7 @@ int ft80x_linestrip(int fd, FAR struct ft80x_dlbuffer_s *buffer)
/* Create the hardware display list */
ret = ft80x_dl_create(fd, buffer, cmds, 7);
ret = ft80x_dl_create(fd, buffer, cmds, 7, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_create failed: %d\n", ret);
@ -279,7 +279,7 @@ int ft80x_linestrip(int fd, FAR struct ft80x_dlbuffer_s *buffer)
*
****************************************************************************/
int ft80x_edgestrip_r(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_prim_edgestrip_r(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
uint32_t cmds[7];
int ret;
@ -291,14 +291,14 @@ int ft80x_edgestrip_r(int fd, FAR struct ft80x_dlbuffer_s *buffer)
cmds[2] = FT80X_CLEAR(1 ,1 ,1);
cmds[3] = FT80X_BEGIN(FT80X_PRIM_EDGE_STRIP_R);
cmds[4] = FT80X_VERTEX2F(16 * 16,16 * 16);
cmds[5] = FT80X_VERTEX2F(((FT80X_DISPLAY_WIDTH * 2) / 3 ) * 16,
((FT80X_DISPLAY_HEIGHT * 2) / 3 ) * 16);
cmds[5] = FT80X_VERTEX2F(((FT80X_DISPLAY_WIDTH * 2) / 3) * 16,
((FT80X_DISPLAY_HEIGHT * 2) / 3) * 16);
cmds[6] = FT80X_VERTEX2F((FT80X_DISPLAY_WIDTH - 80) * 16,
(FT80X_DISPLAY_HEIGHT - 20) * 16);
/* Create the hardware display list */
ret = ft80x_dl_create(fd, buffer, cmds, 7);
ret = ft80x_dl_create(fd, buffer, cmds, 7, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_create failed: %d\n", ret);
@ -316,7 +316,7 @@ int ft80x_edgestrip_r(int fd, FAR struct ft80x_dlbuffer_s *buffer)
*
****************************************************************************/
int ft80x_rectangles(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_prim_rectangles(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
uint32_t cmds[14];
uint32_t width;
@ -358,7 +358,7 @@ int ft80x_rectangles(int fd, FAR struct ft80x_dlbuffer_s *buffer)
/* Create the hardware display list */
ret = ft80x_dl_create(fd, buffer, cmds, 14);
ret = ft80x_dl_create(fd, buffer, cmds, 14, false);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_create failed: %d\n", ret);

View File

@ -20,6 +20,14 @@ config GRAPHICS_FT80X_BUFSIZE
This size should be an even multiple of 4 bytes (otherwise, the size
will be truncated to the next lower, aligned size).
config GRAPHICS_FT80X_CMDEMPTY_SIGNAL
int "CMDEMPTY event signal"
default 18
range l 31
---help---
This is the signal that will be received when the co-processor CMD
FIFO becomes empty.
config GRAPHICS_FT80X_DEBUG_ERROR
bool "Enable error output"
default y

View File

@ -40,7 +40,7 @@ include $(APPDIR)/Make.defs
# FTDI/BridgeTek FT80x library
ASRCS =
CSRCS = ft80x_dl.c ft80x_ramg.c ft80x_regs.c
CSRCS = ft80x_dl.c ft80x_ramg.c ft80x_ramdl.c ft80x_ramcmd.c ft80x_regs.c
AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))

View File

@ -114,6 +114,8 @@ extern "C"
#define EXTERN extern
#endif
struct ft80x_dlbuffer_s; /* Forward reference3 */
/****************************************************************************
* Name: ft80x_getreg8/16/32
*
@ -156,6 +158,81 @@ int ft80x_putreg8(int fd, uint32_t addr, uint8_t value);
int ft80x_putreg16(int fd, uint32_t addr, uint16_t value);
int ft80x_putreg32(int fd, uint32_t addr, uint32_t value);
/****************************************************************************
* Name: ft80x_ramdl_rewind
*
* Description:
* Reset to the start of RAM DL memory
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramdl_rewind(int fd, FAR struct ft80x_dlbuffer_s *buffer);
/****************************************************************************
* Name: ft80x_ramdl_append
*
* Description:
* Append new display list data to RAM DL
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramdl_append(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const void *data, size_t len);
/****************************************************************************
* Name: ft80x_ramcmd_append
*
* Description:
* Append new display list data to RAM CMD
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramcmd_append(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const void *data, size_t len);
/****************************************************************************
* Name: ft80x_ramcmd_waitfifoempty
*
* Description:
* Wait until co processor completes the operation and the FIFO is again
* empty.
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramcmd_waitfifoempty(int fd, FAR struct ft80x_dlbuffer_s *buffer);
/****************************************************************************
* Name: ft80x_dl_swap
*

View File

@ -64,6 +64,8 @@
*
* Input Parameters:
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* data - Data being written.
* len - Number of bytes being written
*
* Returned Value:
* None
@ -71,17 +73,22 @@
****************************************************************************/
#ifdef GRAPHICS_FT80X_DEBUG_INFO
static void ft80x_dl_dump(FAR struct ft80x_dlbuffer_s *buffer)
static void ft80x_dl_dump(FAR struct ft80x_dlbuffer_s *buffer,
FAR const void *data, size_t len)
{
uint16_t nwords;
size_t nwords;
int max;
int i;
int j;
printf("Write display list: dlsize=%lu dloffset=%lu\n",
(unsigned long)buffer->dlsize, (unsigned long)buffer->dloffset);
printf("Writing display list:\n");
printf(" buffer: dlsize=%lu dloffset=%lu coproc=%u\n",
(unsigned long)buffer->dlsize, (unsigned long)buffer->dloffset,
buffer->coproc);
printf(" write: data=%p length=%lu\n",
data, (unsigned long)len);
nwords = buffer->dloffset >> 2;
nwords = len >> 2;
for (i = 0; i < nwords; i += 8)
{
printf(" %04x: ", i << 2);
@ -113,8 +120,50 @@ static void ft80x_dl_dump(FAR struct ft80x_dlbuffer_s *buffer)
putchar('\n');
}
}
#else
# define ft80x_dl_dump(b,d,l)
#endif
/****************************************************************************
* Name: ft80x_dl_append
*
* Description:
* Append the display list data to the appropriate memory region.
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* data - A pointer to the start of the data to be written.
* len - The number of bytes to be written.
*
* Returned Value:
* None
*
****************************************************************************/
static int ft80x_dl_append(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const void *data, size_t len)
{
int ret;
ft80x_dl_dump(buffer, data, len);
if (buffer->coproc)
{
/* Append data to RAM CMD */
ret = ft80x_ramcmd_append(fd, buffer, data, len);
}
else
{
/* Append data to RAM DL */
ret = ft80x_ramdl_append(fd, buffer, data, len);
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -129,25 +178,25 @@ static void ft80x_dl_dump(FAR struct ft80x_dlbuffer_s *buffer)
* 2) Set the display list buffer offset to zero
* 3) Reposition the VFS so that subsequent writes will be to the
* beginning of the hardware display list.
* (Only for DL memory commands)
* 4) Write the CMD_DLSTART command into the local display list buffer
* (REVISIT -- unnecessary)
* (Only for co-processor commands)
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* coproc - True: Use co-processor FIFO; false: Use DL memory.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer, bool coproc)
{
#if 0
struct ft80x_cmd_dlstart_s dlstart;
#endif
off_t pos;
int ret;
ft80x_info("fd=%d buffer=%p\n", fd, buffer);
DEBUGASSERT(fd >= 0 && buffer != NULL);
@ -156,30 +205,49 @@ int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer)
* 2) Set the display list buffer offset to zero
*/
buffer->dlsize = 0;
buffer->coproc = coproc;
buffer->dlsize = 0;
buffer->dloffset = 0;
buffer->hwoffset = 0;
/* 3) Reposition the VFS so that subsequent writes will be to the
* beginning of the hardware display list.
*/
pos = lseek(fd, 0, SEEK_SET);
if (pos < 0)
if (!coproc)
{
int errcode = errno;
ft80x_err("ERROR: lseek failed: %d\n", errcode);
return -errcode;
/* 3) Reposition the VFS so that subsequent writes will be to the
* beginning of the hardware display list.
*/
ret = ft80x_ramdl_rewind(fd, buffer);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_ramdl_rewind failed: %d\n", ret);
}
}
else
{
/* Get the initial RAM CMD FIFO offset */
ret = ft80x_getreg16(fd, FT80X_REG_CMD_READ, &buffer->hwoffset);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret);
}
else
{
/* 4) Write the CMD_DLSTART command into the local display list
* buffer. (Only for co-processor commands)
*/
dlstart.cmd = FT80X_CMD_DLSTART;
ret = ft80x_dl_data(fd, buffer, &dlstart,
sizeof(struct ft80x_cmd_dlstart_s));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
}
}
}
#if 0 /* I believe that this is not necessary */
/* 4) Write the CMD_DLSTART command into the local display list buffer. */
dlstart.cmd = FT80X_CMD_DLSTART;
return ft80x_dl_data(fd, buffer, &dlstart,
sizeof(struct ft80x_cmd_dlstart_s));
#else
return OK;
#endif
return ret;
}
/****************************************************************************
@ -190,9 +258,13 @@ int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer)
*
* 1) Add the DISPLAY command to the local display list buffer to finish
* the last display
* 2) Flush the local display buffer to hardware and set the display list
* 2) If using co-processor RAM CMD, add the CMD_SWAP to the DL command
* list
* 3) Flush the local display buffer to hardware and set the display list
* buffer offset to zero.
* 3) Swap to the newly created display list.
* 4) Swap to the newly created display list (DL memory case only).
* 5) For the case of the co-processor RAM CMD, it will also wait for the
* FIFO to be emptied.
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
@ -206,7 +278,13 @@ int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer)
int ft80x_dl_end(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
struct ft80x_dlcmd_s display;
struct
{
struct ft80x_dlcmd_s display;
struct ft80x_cmd32_s swap;
} s;
size_t size;
int ret;
ft80x_info("fd=%d buffer=%p\n", fd, buffer);
@ -216,15 +294,27 @@ int ft80x_dl_end(int fd, FAR struct ft80x_dlbuffer_s *buffer)
* the last display
*/
display.cmd = FT80X_DISPLAY();
ret = ft80x_dl_data(fd, buffer, &display, sizeof(struct ft80x_dlcmd_s));
s.display.cmd = FT80X_DISPLAY();
size = sizeof(struct ft80x_dlcmd_s);
/* 2) If using co-processor RAM CMD, add the CMD_SWAP to the DL command
* list
*/
if (buffer->coproc)
{
s.swap.cmd = FT80X_CMD_SWAP;
size = sizeof(s);
};
ret = ft80x_dl_data(fd, buffer, &s, size);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_data failed: %d\n", ret);
return ret;
}
/* 2) Flush the local display buffer to hardware and set the display list
/* 3) Flush the local display buffer to hardware and set the display list
* buffer offset to zero.
*/
@ -234,13 +324,30 @@ int ft80x_dl_end(int fd, FAR struct ft80x_dlbuffer_s *buffer)
ft80x_err("ERROR: ft80x_dl_flush failed: %d\n", ret);
}
/* 3) Swap to the newly created display list. */
/* 4) Swap to the newly created display list (DL memory case only). */
ret = ft80x_dl_swap(fd);
if (ret < 0)
if (!buffer->coproc)
{
ft80x_err("ERROR: ft80x_dl_swap failed: %d\n", ret);
return ret;
ret = ft80x_dl_swap(fd);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_swap failed: %d\n", ret);
return ret;
}
}
/* 5) For the case of the co-processor RAM CMD, it will also wait for the
* FIFO to be emptied.
*/
if (buffer->coproc)
{
ret = ft80x_ramcmd_waitfifoempty(fd, buffer);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_ramcmd_waitfifoempty failed: %d\n", ret);
return ret;
}
}
return ret;
@ -306,30 +413,28 @@ int ft80x_dl_data(int fd, FAR struct ft80x_dlbuffer_s *buffer,
}
/* Special case: The new data won't fit into our local display list
* buffer. Here we can assume the flush above occurred. We can then
* work around by writing directly, unbuffered from the caller's
* buffer.
*/
if (padlen > FT80X_DL_BUFSIZE)
{
size_t writelen;
size_t nwritten;
/* Write the aligned portion of the data directly to the FT80x
* hardware display list. NOTE: We have inside knowledge that
* the write will complete in a single operation so that no
* piecewise writes will ever be necessary.
* hardware display list.
*/
writelen = datlen & ~3;
nwritten = write(fd, data, writelen);
if (nwritten < 0)
ret = ft80x_dl_append(fd, buffer, data, writelen);
if (ret < 0)
{
int errcode = errno;
ft80x_err("ERROR: write failed: %d\n", errcode);
return -errcode;
ft80x_err("ERROR: ft80x_dl_append failed: %d\n", ret);
return ret;
}
DEBUGASSERT(nwritten == writelen);
buffer->dlsize += writelen;
/* Is there any unaligned remainder? If the original data length
* was aligned, then we should have writelen == datlen == padlen.
@ -353,23 +458,25 @@ int ft80x_dl_data(int fd, FAR struct ft80x_dlbuffer_s *buffer,
}
}
/* Copy the data into the local display list buffer */
/* Copy the data into the local display list buffer */
bufptr = (FAR uint8_t *)buffer->dlbuffer;
bufptr += buffer->dloffset;
memcpy(bufptr, data, datlen);
bufptr = (FAR uint8_t *)buffer->dlbuffer;
bufptr += buffer->dloffset;
memcpy(bufptr, data, datlen);
bufptr += datlen;
buffer->dloffset += datlen;
bufptr += datlen;
buffer->dloffset += datlen;
/* Then append zero bytes as necessary to achieve alignment */
while (datlen < padlen)
{
*bufptr++ = 0;
buffer->dloffset++;
datlen++;
}
while (datlen < padlen)
{
*bufptr++ = 0;
buffer->dloffset++;
datlen++;
}
buffer->dlsize += padlen;
}
return OK;
@ -450,30 +557,28 @@ int ft80x_dl_string(int fd, FAR struct ft80x_dlbuffer_s *buffer,
}
/* Special case: The new string won't fit into our local display list
* buffer. Here we can assume the flush above occurred. We can then
* work around by writing directly, unbuffered from the caller's
* buffer.
*/
if (padlen > FT80X_DL_BUFSIZE)
{
size_t writelen;
size_t nwritten;
/* Write the aligned portion of the string directly to the FT80x
* hardware display list. NOTE: We have inside knowledge that the
* write will complete in a single operation so that no piecewise
* writes will ever be necessary.
* hardware display list.
*/
writelen = datlen & ~3;
nwritten = write(fd, str, writelen);
if (nwritten < 0)
ret = ft80x_dl_append(fd, buffer, str, writelen);
if (ret < 0)
{
int errcode = errno;
ft80x_err("ERROR: write failed: %d\n", errcode);
return -errcode;
ft80x_err("ERROR: ft80x_dl_append failed: %d\n", ret);
return ret;
}
DEBUGASSERT(nwritten == writelen);
buffer->dlsize += writelen;
/* There should always be an unaligned remainder If the original
* string length was aligned, then we should have writelen == datlen <
@ -514,6 +619,7 @@ int ft80x_dl_string(int fd, FAR struct ft80x_dlbuffer_s *buffer,
datlen++;
}
buffer->dlsize += padlen;
return OK;
}
@ -536,25 +642,20 @@ int ft80x_dl_string(int fd, FAR struct ft80x_dlbuffer_s *buffer,
int ft80x_dl_flush(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
size_t nwritten;
int ret;
ft80x_info("fd=%d buffer=%p\n", fd, buffer);
ft80x_info("fd=%d buffer=%p dloffset=%u\n", fd, buffer, buffer->dloffset);
DEBUGASSERT(fd >= 0 && buffer != NULL);
/* Write the content of the local display buffer to hardware. NOTE: We
* have inside knowledge that the write will complete in a single
* operation so that no piecewise writes will ever be necessary.
*/
/* Write the content of the local display buffer to hardware. */
nwritten = write(fd, buffer->dlbuffer, buffer->dloffset);
if (nwritten < 0)
ret = ft80x_dl_append(fd, buffer, buffer->dlbuffer, buffer->dloffset);
if (ret < 0)
{
int errcode = errno;
ft80x_err("ERROR: write failed: %d\n", errcode);
return -errcode;
ft80x_err("ERROR: ft80x_dl_append failed: %d\n", ret);
return ret;
}
DEBUGASSERT(nwritten == buffer->dloffset);
buffer->dloffset = 0;
return OK;
}
@ -576,6 +677,7 @@ int ft80x_dl_flush(int fd, FAR struct ft80x_dlbuffer_s *buffer)
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* data - Pointer to a uint32_t array containing the simple display list
* nwords - The number of 32-bit words in the array.
* coproc - True: Use co-processor FIFO; false: Use DL memory.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
@ -583,16 +685,18 @@ int ft80x_dl_flush(int fd, FAR struct ft80x_dlbuffer_s *buffer)
****************************************************************************/
int ft80x_dl_create(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const uint32_t *cmds, unsigned int nwords)
FAR const uint32_t *cmds, unsigned int nwords,
bool coproc)
{
int ret;
ft80x_info("fd=%d buffer=%p cmds=%p nwords=%u\n", fd, buffer, cmds, nwords);
ft80x_info("fd=%d buffer=%p cmds=%p nwords=%u coproc=%u\n",
fd, buffer, cmds, nwords, coproc);
DEBUGASSERT(fd >= 0 && buffer != NULL && cmds != NULL && nwords > 0);
/* Create the hardware display list */
ret = ft80x_dl_start(fd, buffer);
ret = ft80x_dl_start(fd, buffer, coproc);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_dl_start failed: %d\n", ret);
@ -618,4 +722,4 @@ int ft80x_dl_create(int fd, FAR struct ft80x_dlbuffer_s *buffer,
}
return OK;
}
}

View File

@ -0,0 +1,393 @@
/****************************************************************************
* apps/graphics/ft80x/ft80x_ramcmd.c
*
* Copyright (C) 2018 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 <nuttx/config.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <pthread.h>
#include <signal.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/lcd/ft80x.h>
#include "graphics/ft80x.h"
#include "ft80x.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define FT80X_CMDFIFO_MASK (FT80X_CMDFIFO_SIZE - 1)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_ramcmd_offset
*
* Description:
* Return the offset to next unused location in RAM CMD
*
* Input Parameters:
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* The offset to the next unused location in RAM CMD.
*
****************************************************************************/
static inline uint16_t ft80x_ramcmd_offset(FAR struct ft80x_dlbuffer_s *buffer)
{
register uint32_t tmp = buffer->dlsize + buffer->hwoffset;
return (uint16_t)(tmp & FT80X_CMDFIFO_MASK);
}
/****************************************************************************
* Name: ft80x_ramcmd_fifopos
*
* Description:
* Return the current FIFO position RAM CMD
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* pos - Pointer to location to return the FIFO position
*
* Returned Value:
* The current FIFO position in RAM CMD.
*
****************************************************************************/
static inline int ft80x_ramcmd_fifopos(int fd, FAR uint16_t *pos)
{
int ret = ft80x_getreg16(fd, FT80X_REG_CMD_READ, pos);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret);
}
return ret;
}
/****************************************************************************
* Name: ft80x_ramcmd_freespace
*
* Description:
* Return the free space in RAM CMD memory
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* avail - Pointer to location to return the FIFO free space
*
* Returned Value:
* The (positive) number of free bytes in RAM CMD on success. A negated
* errno value is returned on any failure.
*
****************************************************************************/
static uint16_t ft80x_ramcmd_freespace(int fd,
FAR struct ft80x_dlbuffer_s *buffer,
FAR uint16_t *avail)
{
uint16_t head;
uint16_t tail;
int ret;
/* Index to the next available location in RAM CMD */
head = ft80x_ramcmd_offset(buffer);
/* The index to next unconsumed value in RAM CMD */
ret = ft80x_ramcmd_fifopos(fd, &tail);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_ramcmd_fifopos failed: %d\n", ret);
return ret;
}
/* Return the free space in the FIFO. NOTE that 4 bytes are not available */
*avail = (FT80X_CMDFIFO_SIZE - 4) - ((head - tail) & FT80X_CMDFIFO_MASK);
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_ramcmd_append
*
* Description:
* Append new display list data to RAM CMD
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* data - A pointer to the start of the data to be written.
* len - The number of bytes to be written.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramcmd_append(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const void *data, size_t len)
{
struct ft80x_relmem_s wrdesc;
FAR const uint8_t *src;
ssize_t remaining = 0;
size_t wrsize = 0;
uint16_t maxsize;
int ret;
/* Loop until all of the display list commands have been transferred to
* FIFO.
*/
src = data;
remaining = len;
do
{
/* Write the number of bytes remaining to be transferred */
wrsize = remaining;
/* Get the amount of free space in the FIFO. */
maxsize = 0;
ret = ft80x_ramcmd_freespace(fd, buffer, &maxsize);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_ramcmd_freespace() failed: %d\n", ret);
return ret;
}
/* If the FIFO full?
*
* REVISIT: Will the FIFO be consumed as we generate the display
* list? Is it fatal if it becomes full? Or could we wait for space
* to free up.
*/
if (maxsize == 0)
{
ft80x_err("ERROR: ft80x_ramcmd_freespace() failed: %d\n", ret);
return -ENOSPC;
}
/* Limit the write size to the size of the available FIFO memory */
if (wrsize > (size_t)maxsize)
{
wrsize = (size_t)maxsize;
}
/* Perform the transfer */
wrdesc.offset = ft80x_ramcmd_offset(buffer);
wrdesc.nbytes = wrsize;
wrdesc.value = (FAR void *)src; /* Discards 'const' qualifier */
ret = ioctl(fd, FT80X_IOC_PUTRAMCMD,
(unsigned long)((uintptr_t)&wrdesc));
if (ret < 0)
{
int errcode = errno;
ft80x_err("ERROR: ioctl() FT80X_IOC_PUTRAMCMD failed: %d\n",
errcode)
return -errcode;
}
/* Update the command FIFO */
buffer->dlsize += wrsize;
ret = ft80x_putreg16(fd, FT80X_REG_CMD_WRITE,
ft80x_ramcmd_offset(buffer));
if (ret < 0)
{
ft80x_err("ERROR: ft80x_putreg16() failed: %d\n", ret);
return ret;
}
/* Wait for the FIFO to empty */
ret = ft80x_ramcmd_waitfifoempty(fd, buffer);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_ramcmd_waitfifoempty() failed: %d\n", ret);
return ret;
}
/* Set up for the next time through the loop */
remaining -= wrsize;
}
while (remaining > 0);
return OK;
}
/****************************************************************************
* Name: ft80x_ramcmd_waitfifoempty
*
* Description:
* Wait until co processor completes the operation and the FIFO is again
* empty.
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramcmd_waitfifoempty(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
struct ft80x_notify_s notify;
struct timespec timeout;
sigset_t set;
uint16_t head;
uint16_t tail;
int ret;
/* Block the signal so that it will pend if received asynchronously */
(void)sigemptyset(&set);
(void)sigaddset(&set, CONFIG_GRAPHICS_FT80X_CMDEMPTY_SIGNAL);
ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (ret < 0)
{
ret = -errno;
ft80x_err("ERROR: pthread_sigmask for signal %d failed: %d\n",
CONFIG_GRAPHICS_FT80X_CMDEMPTY_SIGNAL, ret);
return ret;
}
notify.signo = CONFIG_GRAPHICS_FT80X_CMDEMPTY_SIGNAL;
notify.pid = getpid();
notify.event = FT80X_NOTIFY_CMDEMPTY;
notify.enable = false;
for (; ; )
{
/* Check if the FIFO is already empty */
ret = ft80x_getreg16(fd, FT80X_REG_CMD_WRITE, &head);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret);
break;
}
ret = ft80x_getreg16(fd, FT80X_REG_CMD_READ, &tail);
if (ret < 0)
{
ft80x_err("ERROR: ft80x_getreg16 failed: %d\n", ret);
break;
}
if (head == tail)
{
/* The FIFO is empty... return success */
ret = OK;
break;
}
/* Set up to receive a notification when the CMD FIFO becomes empty
* NOTE that there is a race condition here between the preceding test
* and the time when the event is registered. We catch this with a
* timeout below.
*/
notify.enable = true;
ret = ioctl(fd, FT80X_IOC_EVENTNOTIFY,
(unsigned long)((uintptr_t)&notify));
if (ret < 0)
{
ret = -errno;
ft80x_err("ERROR: ioctl(FT80X_IOC_EVENTNOTIFY) failed: %d\n", errcode);
break;
}
/* Now wait for the signal event (or a timeout) */
timeout.tv_sec = 0;
timeout.tv_nsec = 400 * 1000 * 1000;
ret = sigtimedwait(&set, NULL, &timeout);
/* Make sure that the event notification is again disabled */
notify.enable = false;
(void)ioctl(fd, FT80X_IOC_EVENTNOTIFY,
(unsigned long)((uintptr_t)&notify));
/* Check if the signal was received correctly or if the timeout occurred. */
if (ret < 0)
{
int errcode = errno;
if (errcode != EAGAIN)
{
ft80x_err("ERROR: ioctl(FT80X_IOC_EVENTNOTIFY) failed: %d\n",
errcode);
ret = -errcode;
break;
}
}
}
(void)pthread_sigmask(SIG_UNBLOCK, &set, NULL);
return ret;
}

View File

@ -0,0 +1,136 @@
/****************************************************************************
* apps/graphics/ft80x/ft80x_ramdl.c
*
* Copyright (C) 2018 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 <nuttx/config.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/lcd/ft80x.h>
#include "graphics/ft80x.h"
#include "ft80x.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_ramdl_rewind
*
* Description:
* Reset to the start of RAM DL memory
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramdl_rewind(int fd, FAR struct ft80x_dlbuffer_s *buffer)
{
off_t pos;
DEBUGASSERT(fd >= 0 && buffer != NULL);
/* Reposition the VFSso that subsequent writes will be to the beginning of
* the hardware display list.
*/
pos = lseek(fd, 0, SEEK_SET);
if (pos < 0)
{
int errcode = errno;
ft80x_err("ERROR: lseek failed: %d\n", errcode);
return -errcode;
}
return OK;
}
/****************************************************************************
* Name: ft80x_ramdl_append
*
* Description:
* Append new display list data to RAM DL
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* data - A pointer to the start of the data to be written.
* len - The number of bytes to be written.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_ramdl_append(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const void *data, size_t len)
{
size_t nwritten;
DEBUGASSERT(fd >= 0 && buffer != NULL && data != NULL &&
((uintptr_t)data & 3) == 0 && len > 0 && (len & 3) == 0);
/* Write the aligned data directly to the FT80x hardware display list.
*
* NOTE: We have inside knowledge that the write will complete in a
* single operation so that no piecewise writes will ever be necessary.
*/
nwritten = write(fd, data, len);
if (nwritten < 0)
{
int errcode = errno;
ft80x_err("ERROR: write failed: %d\n", errcode);
return -errcode;
}
DEBUGASSERT(nwritten == len);
return OK;
}

View File

@ -64,8 +64,10 @@
struct ft80x_dlbuffer_s
{
bool coproc; /* True: Use co-processor FIFO; false: Use DL memory */
uint16_t dlsize; /* Total sizeof the display list written to hardware */
uint16_t dloffset; /* The number display list bytes buffered locally */
uint16_t hwoffset; /* Initial offset into FIFO memory */
uint32_t dlbuffer[FT80X_DL_BUFWORDS];
};
@ -91,20 +93,21 @@ extern "C"
* 2) Set the display list buffer offset to zero
* 3) Reposition the VFS so that subsequent writes will be to the
* beginning of the hardware display list.
* 4) Write the CMD_DLSTART command into the local display list buffer.
* (REVISIT -- unnecessary)
* 4) Write the CMD_DLSTART command into the local display list buffer
* (Only for co-processor commands)
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
* with write access.
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* coproc - True: Use co-processor FIFO; false: Use DL memory.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer);
int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer, bool coproc);
/****************************************************************************
* Name: ft80x_dl_end
@ -114,9 +117,13 @@ int ft80x_dl_start(int fd, FAR struct ft80x_dlbuffer_s *buffer);
*
* 1) Add the DISPLAY command to the local display list buffer to finish
* the last display
* 2) Flush the local display buffer to hardware and set the display list
* 2) If using co-processor RAM CMD, add the CMD_SWAP to the DL command
* list
* 3) Flush the local display buffer to hardware and set the display list
* buffer offset to zero.
* 3) Swap to the newly created display list.
* 4) Swap to the newly created display list (DL memory case only).
* 5) For the case of the co-processor RAM CMD, it will also wait for the
* FIFO to be emptied.
*
* Input Parameters:
* fd - The file descriptor of the FT80x device. Opened by the caller
@ -220,6 +227,7 @@ int ft80x_dl_flush(int fd, FAR struct ft80x_dlbuffer_s *buffer);
* buffer - An instance of struct ft80x_dlbuffer_s allocated by the caller.
* data - Pointer to a uint32_t array containing the simple display list
* nwords - The number of 32-bit words in the array.
* coproc - True: Use co-processor FIFO; false: Use DL memory.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
@ -227,7 +235,8 @@ int ft80x_dl_flush(int fd, FAR struct ft80x_dlbuffer_s *buffer);
****************************************************************************/
int ft80x_dl_create(int fd, FAR struct ft80x_dlbuffer_s *buffer,
FAR const uint32_t *cmds, unsigned int nwords);
FAR const uint32_t *cmds, unsigned int nwords,
bool coproc);
/****************************************************************************
* Name: ft80x_ramg_write
@ -249,7 +258,6 @@ int ft80x_dl_create(int fd, FAR struct ft80x_dlbuffer_s *buffer,
int ft80x_ramg_write(int fd, unsigned int offset, FAR const void *data,
unsigned int nbytes);
#undef EXTERN
#ifdef __cplusplus
}