diff --git a/examples/ft80x/ft80x.h b/examples/ft80x/ft80x.h index 4487e52fb..83e9e1274 100644 --- a/examples/ft80x/ft80x.h +++ b/examples/ft80x/ft80x.h @@ -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 } diff --git a/examples/ft80x/ft80x_coprocessor.c b/examples/ft80x/ft80x_coprocessor.c index 571e3197a..71dd2dab8 100644 --- a/examples/ft80x/ft80x_coprocessor.c +++ b/examples/ft80x/ft80x_coprocessor.c @@ -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; +} diff --git a/examples/ft80x/ft80x_main.c b/examples/ft80x/ft80x_main.c index ea531ad78..40cf2383e 100644 --- a/examples/ft80x/ft80x_main.c +++ b/examples/ft80x/ft80x_main.c @@ -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); diff --git a/examples/ft80x/ft80x_primitives.c b/examples/ft80x/ft80x_primitives.c index 147017d4d..c8e6f75d6 100644 --- a/examples/ft80x/ft80x_primitives.c +++ b/examples/ft80x/ft80x_primitives.c @@ -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); diff --git a/graphics/ft80x/Kconfig b/graphics/ft80x/Kconfig index 66aee76bb..f6a5fbbcb 100644 --- a/graphics/ft80x/Kconfig +++ b/graphics/ft80x/Kconfig @@ -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 diff --git a/graphics/ft80x/Makefile b/graphics/ft80x/Makefile index bf008d7a5..52f52413b 100644 --- a/graphics/ft80x/Makefile +++ b/graphics/ft80x/Makefile @@ -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)) diff --git a/graphics/ft80x/ft80x.h b/graphics/ft80x/ft80x.h index bf54b1087..1e09b37a4 100644 --- a/graphics/ft80x/ft80x.h +++ b/graphics/ft80x/ft80x.h @@ -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 * diff --git a/graphics/ft80x/ft80x_dl.c b/graphics/ft80x/ft80x_dl.c index ebce30bce..c29c09eb7 100644 --- a/graphics/ft80x/ft80x_dl.c +++ b/graphics/ft80x/ft80x_dl.c @@ -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; -} \ No newline at end of file +} diff --git a/graphics/ft80x/ft80x_ramcmd.c b/graphics/ft80x/ft80x_ramcmd.c new file mode 100644 index 000000000..b0db2949e --- /dev/null +++ b/graphics/ft80x/ft80x_ramcmd.c @@ -0,0 +1,393 @@ +/**************************************************************************** + * apps/graphics/ft80x/ft80x_ramcmd.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#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)¬ify)); + 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)¬ify)); + + /* 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; +} diff --git a/graphics/ft80x/ft80x_ramdl.c b/graphics/ft80x/ft80x_ramdl.c new file mode 100644 index 000000000..9439695d4 --- /dev/null +++ b/graphics/ft80x/ft80x_ramdl.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * apps/graphics/ft80x/ft80x_ramdl.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "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; +} \ No newline at end of file diff --git a/include/graphics/ft80x.h b/include/graphics/ft80x.h index b603ce973..177455400 100644 --- a/include/graphics/ft80x.h +++ b/include/graphics/ft80x.h @@ -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 }