This commit adds apps/examples/pwlines, another test of the pw-window framebuffer lgoic.
Squashed commit of the following:
apps/examples/pwlines: The example is complete and verified.
apps/examples/pwlines: A little more progress between distractions.
apps/examples/pwlines: Beginning of another per-window framebuffer test/examples.
diff --git a/examples/pwfb/Kconfig b/examples/pwfb/Kconfig
index 2da6b85..1a55674 100644
--- a/examples/pwfb/Kconfig
+++ b/examples/pwfb/Kconfig
@@ -4,7 +4,7 @@
#
config EXAMPLES_PWFB
- tristate "NX Per-Window Framebuffer Example"
+ tristate "NX Per-Window Framebuffer Text Example"
default n
depends on NX
select LIB_BOARDCTL
diff --git a/examples/pwfb/pwfb_main.c b/examples/pwfb/pwfb_main.c
index 1fe6c7a..2d13ee2 100644
--- a/examples/pwfb/pwfb_main.c
+++ b/examples/pwfb/pwfb_main.c
@@ -205,7 +205,7 @@
st->wndo[2].color[0] = CONFIG_EXAMPLES_PWFB_COLOR3;
st->color[0] = CONFIG_EXAMPLES_PWFB_TBCOLOR;
- /* Connect each widnow to the font cache. They cannot share the
+ /* Connect each window to the font cache. They cannot share the
* font cache becuse of the differing background colors.
*/
@@ -407,6 +407,13 @@
printf("nxeq_opentoolbar: nxtk_opentoolbar failed: %d\n", errno);
}
+ /* There is a race condition here we resolve by making the main thread
+ * lowest in priority. In order for the size and position to take effect,
+ * a command is sent to server which responds with an event. So we need
+ * to be synchronized at this point or the following fill will fail because
+ * it depends on current knowlede of the size and position.
+ */
+
/* Create a bounding box. This is actually too large because it does not
* account for the boarder widths. However, NX should clip the fill to
* stay within the frame.
@@ -441,13 +448,6 @@
goto errout_with_hwnd;
}
- /* There is a race condition here we resolve by making the main thread
- * lowest in priority. In order for the size and position to take effect,
- * a command is sent to server which responds with an event. So we need
- * to be synchronized at this point or the following fill will fail because
- * it depends on current knowlede of the size and position.
- */
-
/* Add the text to the display, character at a time */
textpos.x = st->spwidth;
@@ -592,7 +592,7 @@
{
printf("pwfb_main: ERROR: "
"pwfb_configure_window failed for window 1\n");
- goto errout_with_fontcache;
+ goto errout_with_hwnd1;
}
/* Open window 2 */
diff --git a/examples/pwlines/.gitignore b/examples/pwlines/.gitignore
new file mode 100644
index 0000000..fa1ec75
--- /dev/null
+++ b/examples/pwlines/.gitignore
@@ -0,0 +1,11 @@
+/Make.dep
+/.depend
+/.built
+/*.asm
+/*.obj
+/*.rel
+/*.lst
+/*.sym
+/*.adb
+/*.lib
+/*.src
diff --git a/examples/pwlines/Kconfig b/examples/pwlines/Kconfig
new file mode 100644
index 0000000..c978eb7
--- /dev/null
+++ b/examples/pwlines/Kconfig
@@ -0,0 +1,138 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config EXAMPLES_PWLINES
+ tristate "NX Per-Window Framebuffer Graphics Example"
+ default n
+ depends on NX
+ select LIB_BOARDCTL
+ select NX_RAMBACKED
+ ---help---
+ Enable the NX per-window framebuffer example
+
+if EXAMPLES_PWLINES
+
+config EXAMPLES_PWLINES_DEFAULT_COLORS
+ bool "Use Default Colors"
+ default y
+
+if !EXAMPLES_PWLINES_DEFAULT_COLORS
+
+config EXAMPLES_PWLINES_BGCOLOR
+ hex "Background Color"
+ ---help---
+ The color of the background. Default depends on config EXAMPLES_PWLINES_BPP.
+
+config EXAMPLES_PWLINES_COLOR1
+ hex "Color of Window 1"
+ ---help---
+ The color of window 1. Default depends on config EXAMPLES_PWLINES_BPP.
+
+config EXAMPLES_PWLINES_COLOR2
+ hex "Color of Window 2"
+ ---help---
+ The color of window 2. Default depends on config EXAMPLES_PWLINES_BPP.
+
+config EXAMPLES_PWLINES_COLOR3
+ hex "Color of Window 3"
+ ---help---
+ The color of window 3. Default depends on config EXAMPLES_PWLINES_BPP.
+
+config EXAMPLES_PWLINES_BORDERCOLOR
+ hex "Circle border Color"
+ ---help---
+ The color of the circular border drawn in the window. Default depends
+ on EXAMPLES_PWLINES_BPP.
+
+config EXAMPLES_PWLINES_FACECOLOR
+ hex "Circle face Color"
+ ---help---
+ The color of the circular region filled in the window. Default depends
+ on EXAMPLES_PWLINES_BPP.
+
+config EXAMPLES_PWLINES_LINECOLOR
+ hex "Line Color"
+ ---help---
+ The color of the central lines drawn in the window. Default depends
+ on EXAMPLES_PWLINES_BPP.
+
+endif
+
+config EXAMPLES_PWLINES_BPP
+ int "Bits-Per-Pixel"
+ default 32
+ ---help---
+ Pixels per pixel to use. Valid options include 2, 4, 8, 16, 24,
+ and 32. Default is 32.
+
+config EXAMPLES_PWLINES_LINEWIDTH
+ int "Line Width"
+ default 8
+ ---help---
+ Selects the width of the lines in pixels (default: 16)
+
+config EXAMPLES_PWLINES_BORDERWIDTH
+ int "Border Width"
+ default 8
+ ---help---
+ The width of the circular border drawn in the background window. (default: 16).
+
+config EXAMPLES_PWLINES_RATECONTROL
+ int "Frame rate control"
+ default 100
+ range 0 1000
+ ---help---
+ This is the inter-frame period in milliseconds that is used to
+ control the framerate. A value of zero will disable frame controls
+ and the rendering will occur as fast as is possible.
+
+ If you run this example with high frame rates, it becomes unstable.
+ This is probably a bug in the example: It may not be accounting
+ for for some asynchronous behaviors.
+
+config EXAMPLES_PWLINES_VERBOSE
+ bool "Verbose output"
+ default n
+
+comment "Tasking options"
+
+config EXAMPLES_PWLINES_PROGNAME
+ string "Program name"
+ default "pwlines"
+ depends on BUILD_LOADABLE
+ ---help---
+ This is the name of the program that will be use when the NSH ELF
+ program is installed.
+
+config EXAMPLES_PWLINES_CLIENT_STACKSIZE
+ int "Example Main Stack Size"
+ default 2048
+ ---help---
+ The stacksize to use when starting the example main().
+ Default 2048
+
+config EXAMPLES_PWLINES_CLIENT_PRIO
+ int "Client Priority"
+ default 90
+ ---help---
+ The priority to use when staring the example main(). This priority
+ should be lower than both the listener and server priorities (See
+ CONFIG_NXSTART_SERVERPRIO). Default: 90
+
+config EXAMPLES_PWLINES_LISTENER_STACKSIZE
+ int "Listener Stack Size"
+ default 2048
+ ---help---
+ The stacksize to use when creating the NX server. Default 2048
+
+config EXAMPLES_PWLINES_LISTENER_PRIO
+ int "Listener Priority"
+ default 100
+ ---help---
+ The priority of the event listener thread. This priority should be
+ above the client priority but below the server priority (See
+ CONFIG_NXSTART_SERVERPRIO). Default 100.
+
+endif
diff --git a/examples/pwlines/Make.defs b/examples/pwlines/Make.defs
new file mode 100644
index 0000000..bec09ae
--- /dev/null
+++ b/examples/pwlines/Make.defs
@@ -0,0 +1,39 @@
+############################################################################
+# apps/examples/pwlines/Make.defs
+# Adds selected applications to apps/ build
+#
+# Copyright (C) 2019 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.
+#
+############################################################################
+
+ifneq ($(CONFIG_EXAMPLES_PWLINES),)
+CONFIGURED_APPS += examples/pwlines
+endif
diff --git a/examples/pwlines/Makefile b/examples/pwlines/Makefile
new file mode 100644
index 0000000..3c71ea7
--- /dev/null
+++ b/examples/pwlines/Makefile
@@ -0,0 +1,58 @@
+############################################################################
+# apps/examples/pwlines/Makefile
+#
+# Copyright (C) 2019 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.
+#
+############################################################################
+
+-include $(TOPDIR)/Make.defs
+
+# NuttX NX Graphics Example.
+
+ASRCS =
+CSRCS = pwlines_events.c pwlines_motion.c pwlines_update.c
+MAINSRC = pwlines_main.c
+
+CONFIG_EXAMPLES_PWLINES_PROGNAME ?= pwlines$(EXEEXT)
+PROGNAME = $(CONFIG_EXAMPLES_PWLINES_PROGNAME)
+
+# NX built-in application info
+
+CONFIG_EXAMPLES_PWLINES_CLIENT_PRIO ?= SCHED_PRIORITY_DEFAULT
+CONFIG_EXAMPLES_PWLINES_CLIENT_STACKSIZE ?= 2048
+
+APPNAME = pwlines
+PRIORITY = $(CONFIG_EXAMPLES_PWLINES_CLIENT_PRIO)
+STACKSIZE = $(CONFIG_EXAMPLES_PWLINES_CLIENT_STACKSIZE)
+
+MODULE = CONFIG_EXAMPLES_PWLINES
+
+include $(APPDIR)/Application.mk
diff --git a/examples/pwlines/pwlines_events.c b/examples/pwlines/pwlines_events.c
new file mode 100644
index 0000000..932eae3
--- /dev/null
+++ b/examples/pwlines/pwlines_events.c
@@ -0,0 +1,187 @@
+/****************************************************************************
+ * examples/pwlines/pwlines_events.c
+ *
+ * Copyright (C) 2019 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 <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <semaphore.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxtk.h>
+#include "pwlines_internal.h"
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void pwlines_wndo_redraw(NXTKWINDOW hwnd,
+ FAR const struct nxgl_rect_s *rect, bool morem, FAR void *arg);
+static void pwlines_wndo_position(NXTKWINDOW hwnd, FAR
+ FAR const struct nxgl_size_s *size,
+ FAR const struct nxgl_point_s *pos,
+ FAR const struct nxgl_rect_s *bounds,
+ FAR void *arg);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct nx_callback_s g_pwlines_wncb =
+{
+ pwlines_wndo_redraw, /* redraw */
+ pwlines_wndo_position /* position */
+#ifdef CONFIG_NX_XYINPUT
+ , NULL /* mousein */
+#endif
+#ifdef CONFIG_NX_KBD
+ , NULL /* kbdin */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_wndo_redraw
+ ****************************************************************************/
+
+static void pwlines_wndo_redraw(NXTKWINDOW hwnd,
+ FAR const struct nxgl_rect_s *rect,
+ bool more, FAR void *arg)
+{
+ /* There should be no redraw requests when using per-window framebuffers */
+
+ printf("pwlines_wndo_redraw: hwnd=%p rect={(%d,%d),(%d,%d)} more=%s\n",
+ hwnd,
+ rect->pt1.x, rect->pt1.y, rect->pt2.x, rect->pt2.y,
+ more ? "true" : "false");
+}
+
+/****************************************************************************
+ * Name: pwlines_wndo_position
+ ****************************************************************************/
+
+static void pwlines_wndo_position(NXTKWINDOW hwnd,
+ FAR const struct nxgl_size_s *size,
+ FAR const struct nxgl_point_s *pos,
+ FAR const struct nxgl_rect_s *bounds,
+ FAR void *arg)
+{
+ FAR struct pwlines_state_s *st = (FAR struct pwlines_state_s *)arg;
+
+#ifdef CONFIG_EXAMPLES_PWLINES_VERBOSE
+ /* Report the position */
+
+ printf("pwlines_wndo_position: hwnd=%p size=(%d,%d) pos=(%d,%d) "
+ "bounds={(%d,%d),(%d,%d)}\n",
+ hwnd, size->w, size->h, pos->x, pos->y,
+ bounds->pt1.x, bounds->pt1.y, bounds->pt2.x, bounds->pt2.y);
+#endif
+
+ /* Have we picked off the window bounds yet? */
+
+ if (!st->haveres)
+ {
+ /* Save the window limits (these should be the same for all places and
+ * all windows.
+ */
+
+ st->xres = bounds->pt2.x + 1;
+ st->yres = bounds->pt2.y + 1;
+
+ st->haveres = true;
+ sem_post(&st->semevent);
+
+ printf("pwlines_wndo_position: Have xres=%d yres=%d\n",
+ st->xres, st->yres);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_listener
+ ****************************************************************************/
+
+FAR void *pwlines_listener(FAR void *arg)
+{
+ FAR struct pwlines_state_s *st = (FAR struct pwlines_state_s *)arg;
+ int ret;
+
+ /* Process events forever */
+
+ for (; ; )
+ {
+ /* Handle the next event. If we were configured blocking, then
+ * we will stay right here until the next event is received. Since
+ * we have dedicated a while thread to servicing events, it would
+ * be most natural to also select CONFIG_NX_BLOCKING -- if not, the
+ * following would be a tight infinite loop (unless we added addition
+ * logic with nx_eventnotify and sigwait to pace it).
+ */
+
+ ret = nx_eventhandler(st->hnx);
+ if (ret < 0)
+ {
+ /* An error occurred... assume that we have lost connection with
+ * the server.
+ */
+
+ printf("pwlines_listener: Lost server connection: %d\n", errno);
+ pthread_exit(NULL);
+ }
+
+ /* If we received a message, we must be connected */
+
+ if (!st->connected)
+ {
+ st->connected = true;
+ sem_post(&st->semevent);
+ printf("pwlines_listener: Connected\n");
+ }
+ }
+}
diff --git a/examples/pwlines/pwlines_internal.h b/examples/pwlines/pwlines_internal.h
new file mode 100644
index 0000000..c9d7064
--- /dev/null
+++ b/examples/pwlines/pwlines_internal.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+ * examples/pwlines/pwlines_internal.h
+ *
+ * Copyright (C) 2019 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.
+ *
+ ****************************************************************************/
+
+#ifndef __EXAMPLES_PWLINES_PWLINES_INTERNAL_H
+#define __EXAMPLES_PWLINES_PWLINES_INTERNAL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <fixedmath.h>
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxtk.h>
+#include <nuttx/video/rgbcolors.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* Required NX Server Settings */
+
+#ifndef CONFIG_NX
+# error "NX is not enabled (CONFIG_NX)"
+#endif
+
+#ifdef CONFIG_DISABLE_MQUEUE
+# error "The multi-threaded example requires MQ support (CONFIG_DISABLE_MQUEUE=n)"
+#endif
+
+#ifdef CONFIG_DISABLE_PTHREAD
+# error "This example requires pthread support (CONFIG_DISABLE_PTHREAD=n)"
+#endif
+
+#ifndef CONFIG_NX_BLOCKING
+# error "This example depends on CONFIG_NX_BLOCKING"
+#endif
+
+/* Task priorities */
+
+#if CONFIG_EXAMPLES_PWLINES_CLIENT_PRIO >= CONFIG_EXAMPLES_PWLINES_LISTENER_PRIO || \
+ CONFIG_EXAMPLES_PWLINES_CLIENT_PRIO >= CONFIG_NXSTART_SERVERPRIO
+# warning Client priority must be lower than both the listener and server priorities
+#endif
+
+#if CONFIG_EXAMPLES_PWLINES_LISTENER_PRIO >= CONFIG_NXSTART_SERVERPRIO
+# warning Listener priority must be lower than the server priority
+#endif
+
+/* Default colors */
+
+#ifndef CONFIG_EXAMPLES_PWLINES_BGCOLOR
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_BGCOLOR 0x007b68ee
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_BGCOLOR 0x7b5d
+# else
+# define CONFIG_EXAMPLES_PWLINES_BGCOLOR ' '
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_COLOR1
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_COLOR1 RGB24_DARKGREEN
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_COLOR1 RGB16_DARKGREEN
+# else
+# define CONFIG_EXAMPLES_PWLINES_COLOR1 RGB8_DARKGREEN
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_COLOR2
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_COLOR2 RGB24_GREEN
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_COLOR2 RGB16_GREEN
+# else
+# define CONFIG_EXAMPLES_PWLINES_COLOR2 RGB8_GREEN
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_COLOR3
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_COLOR3 RGB24_LIGHTGREEN
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_COLOR3 RGB16_LIGHTGREEN
+# else
+# define CONFIG_EXAMPLES_PWLINES_COLOR3 RGB8_LIGHTGREEN
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_BORDERWIDTH
+# define CONFIG_EXAMPLES_PWLINES_BORDERWIDTH 16
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_BORDERCOLOR
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_BORDERCOLOR RGB24_YELLOW
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_BORDERCOLOR RGB16_YELLOW
+# else
+# define CONFIG_EXAMPLES_PWLINES_BORDERCOLOR RGB8_YELLOW
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_FACECOLOR
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_FACECOLOR RGB24_BEIGE
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_FACECOLOR RGB16_BEIGE
+# else
+# define CONFIG_EXAMPLES_PWLINES_FACECOLOR RGB8_BEIGE
+# endif
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_LINEWIDTH
+# define CONFIG_EXAMPLES_PWLINES_LINEWIDTH 16
+#endif
+
+#ifndef CONFIG_EXAMPLES_PWLINES_LINECOLOR
+# if CONFIG_EXAMPLES_PWLINES_BPP == 24 || CONFIG_EXAMPLES_PWLINES_BPP == 32
+# define CONFIG_EXAMPLES_PWLINES_LINECOLOR RGB24_GOLD
+# elif CONFIG_EXAMPLES_PWLINES_BPP == 16
+# define CONFIG_EXAMPLES_PWLINES_LINECOLOR RGB16_GOLD
+# else
+# define CONFIG_EXAMPLES_PWLINES_LINECOLOR RGB8_GOLD
+# endif
+#endif
+
+/* Helpers */
+
+#ifndef MIN
+# define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+# define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Describes the unique state of one window */
+
+struct pwlines_window_s
+{
+ NXTKWINDOW hwnd; /* Window handle */
+ nxgl_mxpixel_t color[CONFIG_NX_NPLANES]; /* Window color */
+ struct nxgl_size_s size; /* Drawable window size */
+ struct nxgl_point_s center; /* Circle center position */
+ struct nxgl_vector_s previous; /* Previous line vector */
+ nxgl_coord_t radius; /* Internal, drawable radius */
+ b16_t angle; /* Current line angle */
+ b16_t xmax; /* Max X position */
+ b16_t ymax; /* Max Y position */
+ b16_t xpos; /* Current X position */
+ b16_t ypos; /* Current Y position */
+ b16_t deltax; /* Current X speed */
+ b16_t deltay; /* Current Y speed */
+};
+
+/* Describes the overall state of the example */
+
+struct pwlines_state_s
+{
+ /* NX server */
+
+ volatile bool haveres; /* True: Have screen resolution */
+ volatile bool connected; /* True: Connected to server */
+ sem_t semevent; /* Event wait semaphore */
+ NXHANDLE hnx; /* Connection handle */
+
+ /* Graphics hardware */
+
+ nxgl_coord_t xres; /* Horizontal resolution */
+ nxgl_coord_t yres; /* Vertical resolution */
+
+ /* Image properties */
+
+ nxgl_mxpixel_t facecolor[CONFIG_NX_NPLANES]; /* Color of circle center region */
+ nxgl_mxpixel_t bordercolor[CONFIG_NX_NPLANES]; /* Color of circle border */
+ nxgl_mxpixel_t linecolor[CONFIG_NX_NPLANES]; /* Color of rotating line */
+
+ /* Window-specific state */
+
+ struct pwlines_window_s wndo[3];
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* NX callback vtables */
+
+extern const struct nx_callback_s g_pwlines_wncb;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+FAR void *pwlines_listener(FAR void *arg);
+void pwlines_circle(FAR struct pwlines_state_s *st);
+void pwlines_update(FAR struct pwlines_state_s *st);
+bool pwlines_motion(FAR struct pwlines_state_s *st);
+
+#endif /* __EXAMPLES_PWLINES_PWLINES_INTERNAL_H */
diff --git a/examples/pwlines/pwlines_main.c b/examples/pwlines/pwlines_main.c
new file mode 100644
index 0000000..fa498d5
--- /dev/null
+++ b/examples/pwlines/pwlines_main.c
@@ -0,0 +1,536 @@
+/****************************************************************************
+ * examples/pwlines/pwlines_main.c
+ *
+ * Copyright (C) 2019 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/types.h>
+#include <sys/boardctl.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <pthread.h>
+#include <fixedmath.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/board.h>
+
+#ifdef CONFIG_VNCSERVER
+# include <nuttx/video/vnc.h>
+#endif
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxtk.h>
+#include <nuttx/nx/nxbe.h>
+
+#include "pwlines_internal.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_server_initialize
+ ****************************************************************************/
+
+static bool pwlines_server_initialize(FAR struct pwlines_state_s *st)
+{
+ struct sched_param param;
+ int ret;
+
+ /* Set the client task priority */
+
+ param.sched_priority = CONFIG_EXAMPLES_PWLINES_CLIENT_PRIO;
+ ret = sched_setparam(0, ¶m);
+ if (ret < 0)
+ {
+ printf("pwlines_server_initialize: ERROR: "
+ "sched_setparam failed: %d\n" ,
+ ret);
+ return false;
+ }
+
+ /* Start the NX server kernel thread */
+
+ ret = boardctl(BOARDIOC_NX_START, 0);
+ if (ret < 0)
+ {
+ printf("pwlines_server_initialize: ERROR: "
+ "Failed to start the NX server: %d\n",
+ errno);
+ return false;
+ }
+
+ /* Connect to the server */
+
+ st->hnx = nx_connect();
+ if (st->hnx)
+ {
+#ifdef CONFIG_VNCSERVER
+ /* Setup the VNC server to support keyboard/mouse inputs */
+
+ ret = vnc_default_fbinitialize(0, st->hnx);
+ if (ret < 0)
+ {
+ printf("pwlines_server_initialize: ERROR: "
+ "vnc_default_fbinitialize failed: %d\n",
+ ret);
+ nx_disconnect(st->hnx);
+ return false;
+ }
+#endif
+ }
+ else
+ {
+ printf("pwlines_server_initialize: ERROR: "
+ "nx_connect failed: %d\n",
+ errno);
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Name: pwlines_listener_initialize
+ ****************************************************************************/
+
+static bool pwlines_listener_initialize(FAR struct pwlines_state_s *st)
+{
+ struct sched_param param;
+ pthread_attr_t attr;
+ pthread_t thread;
+ int ret;
+
+ /* Start a separate thread to listen for server events. This is probably
+ * the least efficient way to do this, but it makes this example flow more
+ * smoothly.
+ */
+
+ (void)pthread_attr_init(&attr);
+ param.sched_priority = CONFIG_EXAMPLES_PWLINES_LISTENER_PRIO;
+ (void)pthread_attr_setschedparam(&attr, ¶m);
+ (void)pthread_attr_setstacksize(&attr, CONFIG_EXAMPLES_PWLINES_LISTENER_STACKSIZE);
+
+ ret = pthread_create(&thread, &attr, pwlines_listener, st);
+ if (ret != 0)
+ {
+ printf("pwlines_listener_initialize: ERROR: "
+ "pthread_create failed: %d\n",
+ ret);
+ return false;
+ }
+
+ /* Don't return until we are connected to the server */
+
+ while (!st->connected)
+ {
+ /* Wait for the listener thread to wake us up when we really
+ * are connected.
+ */
+
+ (void)sem_wait(&st->semevent);
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Name: pwlines_state_initialize
+ ****************************************************************************/
+
+static bool pwlines_state_initialize(FAR struct pwlines_state_s *st)
+{
+ /* Initialize semaphores */
+
+ sem_init(&st->semevent, 0, 0);
+
+ /* Initialize color information (only a single color plane supported) */
+
+ st->wndo[0].color[0] = CONFIG_EXAMPLES_PWLINES_COLOR1;
+ st->wndo[1].color[0] = CONFIG_EXAMPLES_PWLINES_COLOR2;
+ st->wndo[2].color[0] = CONFIG_EXAMPLES_PWLINES_COLOR3;
+
+ st->facecolor[0] = CONFIG_EXAMPLES_PWLINES_FACECOLOR;
+ st->bordercolor[0] = CONFIG_EXAMPLES_PWLINES_BORDERCOLOR;
+ st->linecolor[0] = CONFIG_EXAMPLES_PWLINES_LINECOLOR;
+
+ return true;
+}
+
+/****************************************************************************
+ * Name: pwlines_configure_window
+ ****************************************************************************/
+
+static bool pwlines_configure_window(FAR struct pwlines_state_s *st, int wndx,
+ FAR struct nxgl_size_s *size,
+ FAR struct nxgl_point_s *pos,
+ double deltax, double deltay)
+{
+ FAR struct pwlines_window_s *wndo = &st->wndo[wndx];
+ struct nxgl_rect_s rect;
+ int ret;
+
+ /* Set the total size of the window */
+
+ printf("pwlines_configure_window: Set window %d size to (%d,%d)\n",
+ wndx + 1, size->w, size->h);
+
+ ret = nxtk_setsize(wndo->hwnd, size);
+ if (ret < 0)
+ {
+ printf("pwlines_configure_window: ERROR: "
+ "nxtk_setsize failed: %d\n", errno);
+ goto errout_with_hwnd;
+ }
+
+ /* Set the drawable size (excludes borders) */
+
+ wndo->size.h = size->h - 2 * CONFIG_NXTK_BORDERWIDTH;
+ wndo->size.w = size->w - 2 * CONFIG_NXTK_BORDERWIDTH;
+
+ /* Set the position of window */
+
+ printf("pwlines_configure_window: Set window %d position to (%d,%d)\n",
+ wndx + 1, pos->x, pos->y);
+
+ ret = nxtk_setposition(wndo->hwnd, pos);
+ if (ret < 0)
+ {
+ printf("pwlines_configure_window: ERROR: "
+ "nxtk_setposition failed: %d\n",
+ errno);
+ goto errout_with_hwnd;
+ }
+
+ /* Create a bounding box. This is actually too large because it does not
+ * account for the boarder widths. However, NX should clip the fill to
+ * stay within the frame.
+ *
+ * There is a race condition here we resolve by making the main thread
+ * lowest in priority. In order for the size and position to take effect,
+ * a command is sent to server which responds with an event. So we need
+ * to be synchronized at this point or the following fill will fail because
+ * it depends on current knowlede of the size and position.
+ */
+
+ rect.pt1.x = 0;
+ rect.pt1.y = 0;
+ rect.pt2.x = size->w - 1;
+ rect.pt2.y = size->h - 1;
+
+ /* Fill the window with the selected color */
+
+ ret = nxtk_fillwindow(wndo->hwnd, &rect, wndo->color);
+ if (ret < 0)
+ {
+ printf("pwlines_configure_window: ERROR: "
+ "nxtk_fillwindow failed: %d\n",
+ errno);
+ goto errout_with_hwnd;
+ }
+
+ /* Set up for motion */
+
+ wndo->xmax = itob16(st->xres - size->w - 1);
+ wndo->ymax = itob16(st->yres - size->h - 1);
+ wndo->ypos = itob16(pos->y);
+ wndo->xpos = itob16(pos->x);
+ wndo->deltax = dtob16(deltax);
+ wndo->deltay = dtob16(deltay);
+
+ return true;
+
+errout_with_hwnd:
+ printf("pwlines_configure_window: Close window %d\n", wndx + 1);
+
+ ret = nxtk_closewindow(wndo->hwnd);
+ if (ret < 0)
+ {
+ printf("pwlines_configure_window: ERROR: "
+ "nxtk_closewindow failed: %d\n",
+ errno);
+ }
+
+ return false;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_main
+ ****************************************************************************/
+
+#ifdef BUILD_MODULE
+int main(int argc, FAR char *argv[])
+#else
+int pwlines_main(int argc, char *argv[])
+#endif
+{
+ struct pwlines_state_s wstate;
+ struct nxgl_size_s size;
+ struct nxgl_point_s pos;
+ nxgl_coord_t mindim;
+ nxgl_mxpixel_t color;
+ unsigned int elapsed;
+ int errcode = EXIT_SUCCESS;
+ int ret;
+
+ /* Connect to the NX server */
+
+ memset(&wstate, 0, sizeof(struct pwlines_state_s));
+ if (!pwlines_server_initialize(&wstate) || wstate.hnx == NULL)
+ {
+ printf("pwlines_main: ERROR: "
+ "Failed to get NX handle\n");
+ goto errout;
+ }
+
+ printf("pwlines_main: NX handle=%p\n", wstate.hnx);
+
+ /* Start the listener thread */
+
+ if (!pwlines_listener_initialize(&wstate))
+ {
+ printf("pwlines_main: ERROR: "
+ "pwlines_listener_initialize failed\n");
+ goto errout_with_nx;
+ }
+
+ /* Initialize the window state, colors, cache, etc. */
+
+ if (!pwlines_state_initialize(&wstate))
+ {
+ printf("pwlines_main: ERROR: "
+ "pwlines_state_initialize failed\n");
+ goto errout_with_nx;
+ }
+
+ /* Set the background to the configured background color */
+
+ printf("pwlines_main: Set background color=%d\n",
+ CONFIG_EXAMPLES_PWLINES_BGCOLOR);
+
+ color = CONFIG_EXAMPLES_PWLINES_BGCOLOR;
+ ret = nx_setbgcolor(wstate.hnx, &color);
+ if (ret < 0)
+ {
+ printf("pwlines_main: nx_setbgcolor failed: %d\n", errno);
+ goto errout_with_nx;
+ }
+
+ /* Open window 1 */
+
+ printf("pwlines_main: Open window 1\n");
+
+ wstate.wndo[0].hwnd = nxtk_openwindow(wstate.hnx, NXBE_WINDOW_RAMBACKED,
+ &g_pwlines_wncb, (FAR void *)&wstate);
+ if (wstate.wndo[0].hwnd == NULL)
+ {
+ printf("pwlines_main: ERROR: "
+ "nxtk_openwindow failed: %d\n",
+ errno);
+ goto errout_with_nx;
+ }
+
+ printf("pwlines_main: hwnd1=%p\n", wstate.wndo[0].hwnd);
+
+ /* Wait until we receive the screen resolution from the server. We only
+ * need to do this once after opening the first window.
+ */
+
+ while (!wstate.haveres)
+ {
+ (void)sem_wait(&wstate.semevent);
+ }
+
+ printf("pwlines_main: Screen resolution (%d,%d)\n",
+ wstate.xres, wstate.yres);
+
+ /* Configure window 1 */
+
+ mindim = MIN(wstate.xres, wstate.yres);
+ size.w = mindim / 2;
+ size.h = size.w;
+
+ pos.x = wstate.xres / 8;
+ pos.y = wstate.yres / 8;
+
+ if (!pwlines_configure_window(&wstate, 0, &size, &pos, 4.200, 4.285))
+ {
+ printf("pwlines_main: ERROR: "
+ "pwlines_configure_window failed for window 1\n");
+ goto errout_with_hwnd1;
+ }
+
+ /* Open window 2 */
+
+ printf("pwlines_main: Open window 2\n");
+
+ wstate.wndo[1].hwnd = nxtk_openwindow(wstate.hnx, NXBE_WINDOW_RAMBACKED,
+ &g_pwlines_wncb, (FAR void *)&wstate);
+ if (wstate.wndo[1].hwnd == NULL)
+ {
+ printf("pwlines_main: ERROR: "
+ "nxtk_openwindow failed: %d\n",
+ errno);
+ goto errout_with_hwnd1;
+ }
+
+ printf("pwlines_main: hwnd1=%p\n", wstate.wndo[1].hwnd);
+
+ /* Configure window 2 (same size) */
+
+ pos.x = wstate.xres / 4;
+ pos.y = wstate.yres / 4;
+
+ if (!pwlines_configure_window(&wstate, 1, &size, &pos, -3.317, 5.0))
+ {
+ printf("pwlines_main: ERROR: "
+ "pwlines_configure_window failed for window 2\n");
+ goto errout_with_hwnd2;
+ }
+
+ /* Open window 3 */
+
+ printf("pwlines_main: Open window 3\n");
+
+ wstate.wndo[2].hwnd = nxtk_openwindow(wstate.hnx, NXBE_WINDOW_RAMBACKED,
+ &g_pwlines_wncb, (FAR void *)&wstate);
+ if (wstate.wndo[2].hwnd == NULL)
+ {
+ printf("pwlines_main: ERROR: "
+ "nxtk_openwindow failed: %d\n",
+ errno);
+ goto errout_with_hwnd2;
+ }
+
+ printf("pwlines_main: hwnd2=%p\n", wstate.wndo[2].hwnd);
+
+ /* Configure window 3 (same size) */
+
+ pos.x = (3 * wstate.xres) / 8;
+ pos.y = (3 * wstate.yres) / 8;
+
+ if (!pwlines_configure_window(&wstate, 2, &size, &pos, 4.600, -3.852))
+ {
+ printf("pwlines_main: ERROR: "
+ "pwlines_configure_window failed for window 2\n");
+ goto errout_with_hwnd3;
+ }
+
+ /* Apply the initial graphics */
+
+ pwlines_circle(&wstate);
+ pwlines_update(&wstate);
+
+ /* Now loop animating the windows */
+
+ elapsed = 0;
+ for (; ; )
+ {
+ usleep(CONFIG_EXAMPLES_PWLINES_RATECONTROL * 1000);
+
+ if (!pwlines_motion(&wstate))
+ {
+ printf("pwlines_main: ERROR:"
+ "pwlines_motion failed\n");
+ goto errout_with_hwnd3;
+ }
+
+ elapsed += CONFIG_EXAMPLES_PWLINES_RATECONTROL;
+ if (elapsed >= 1000)
+ {
+ pwlines_update(&wstate);
+ elapsed = 0;
+ }
+ }
+
+ errcode = EXIT_SUCCESS;
+
+ /* Close window 3 */
+
+errout_with_hwnd3:
+ printf("pwlines_main: Close window #2\n");
+
+ ret = nxtk_closewindow(wstate.wndo[2].hwnd);
+ if (ret < 0)
+ {
+ printf("pwlines_main: ERROR: nxtk_closewindow failed: %d\n", errno);
+ }
+
+ /* Close window 2 */
+
+errout_with_hwnd2:
+ printf("pwlines_main: Close window #2\n");
+
+ ret = nxtk_closewindow(wstate.wndo[1].hwnd);
+ if (ret < 0)
+ {
+ printf("pwlines_main: ERROR: nxtk_closewindow failed: %d\n", errno);
+ }
+
+ /* Close window1 */
+
+errout_with_hwnd1:
+ printf("pwlines_main: Close window #1\n");
+
+ ret = nxtk_closewindow(wstate.wndo[0].hwnd);
+ if (ret < 0)
+ {
+ printf("pwlines_main: ERROR: nxtk_closewindow failed: %d\n", errno);
+ }
+
+errout_with_nx:
+ /* Disconnect from the server */
+
+ printf("pwlines_main: Disconnect from the server\n");
+ nx_disconnect(wstate.hnx);
+
+errout:
+ return errcode;
+}
diff --git a/examples/pwlines/pwlines_motion.c b/examples/pwlines/pwlines_motion.c
new file mode 100644
index 0000000..e560d62
--- /dev/null
+++ b/examples/pwlines/pwlines_motion.c
@@ -0,0 +1,202 @@
+/****************************************************************************
+ * examples/pwlines/pwlines_motion.c
+ *
+ * Copyright (C) 2019 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 <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <nuttx/nx/nxglib.h>
+#include <nuttx/nx/nxtk.h>
+
+#include "pwlines_internal.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_move_window
+ ****************************************************************************/
+
+static inline bool pwlines_move_window(FAR struct pwlines_state_s *st, int wndx)
+{
+ FAR struct pwlines_window_s *wndo = &st->wndo[wndx];
+ FAR struct nxgl_point_s pos;
+ b16_t newx;
+ b16_t newy;
+ bool hit = false;
+ int ret;
+
+#ifdef CONFIG_EXAMPLES_PWLINES_VERBOSE
+ printf("pwlines_move_window: Velocity: (%lx.%04lx,%lx.%04lx)\n",
+ (unsigned long)wndo->deltax >> 16,
+ (unsigned long)wndo->deltax & 0xffff,
+ (unsigned long)wndo->deltay >> 16,
+ (unsigned long)wndo->deltay & 0xffff);
+ printf("pwlines_move_window: Max: (%lx.%04lx,%lx.%04lx)\n",
+ (unsigned long)wndo->xmax >> 16,
+ (unsigned long)wndo->xmax & 0xffff,
+ (unsigned long)wndo->ymax >> 16,
+ (unsigned long)wndo->ymax & 0xffff);
+#endif
+
+ /* Update X position */
+
+ newx = wndo->xpos + wndo->deltax;
+
+ /* Check for collision with left or right side */
+
+ if (newx <= 0)
+ {
+ newx = 0;
+ wndo->deltax = -wndo->deltax;
+ hit = true;
+ }
+ else if (newx >= wndo->xmax)
+ {
+ newx = wndo->xmax;
+ wndo->deltax = -wndo->deltax;
+ hit = true;
+ }
+
+ /* Update Y position */
+
+ newy = wndo->ypos + wndo->deltay;
+
+ /* Check for collision with top or bottom side */
+
+ if (newy <= 0)
+ {
+ newy = 0;
+ wndo->deltay = -wndo->deltay;
+ hit = true;
+ }
+ else if (newy >= wndo->ymax)
+ {
+ newy = wndo->ymax;
+ wndo->deltay = -wndo->deltay;
+ hit = true;
+ }
+
+#ifdef CONFIG_EXAMPLES_PWLINES_VERBOSE
+ printf("pwlines_move_window: Old pos: (%lx.%04lx,%lx.%04lx) "
+ "New pos: (%lx.%04lx,%lx.%04lx)\n",
+ (unsigned long)wndo->xpos >> 16,
+ (unsigned long)wndo->xpos & 0xffff,
+ (unsigned long)wndo->ypos >> 16,
+ (unsigned long)wndo->ypos & 0xffff,
+ (unsigned long)newx >> 16,
+ (unsigned long)newx & 0xffff,
+ (unsigned long)newy >> 16,
+ (unsigned long)newy & 0xffff);
+#endif
+
+ /* Set the new window position */
+
+ wndo->xpos = newx;
+ wndo->ypos = newy;
+
+ pos.x = b16toi(newx);
+ pos.y = b16toi(newy);
+
+ printf("pwlines_move_window: Set position (%d,%d)\n", pos.x, pos.y);
+
+ ret = nxtk_setposition(wndo->hwnd, &pos);
+ if (ret < 0)
+ {
+ printf("pwlines_move_window: ERROR:"
+ "nxtk_setposition failed: %d\n",
+ errno);
+ return false;
+ }
+
+ /* If we hit an edge, the raise the window */
+
+ if (hit)
+ {
+#ifdef CONFIG_EXAMPLES_PWLINES_VERBOSE
+ printf("pwlines_move_window: New velocity: (%lx.%04lx,%lx.%04lx)\n",
+ (unsigned long)wndo->deltax >> 16,
+ (unsigned long)wndo->deltax & 0xffff,
+ (unsigned long)wndo->deltay >> 16,
+ (unsigned long)wndo->deltay & 0xffff);
+ printf("pwlines_move_window: Raising window\n");
+#endif
+
+ ret = nxtk_raise(wndo->hwnd);
+ if (ret < 0)
+ {
+ printf("pwlines_move_window: ERROR:"
+ "nxtk_raise failed: %d\n",
+ errno);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_motion
+ ****************************************************************************/
+
+bool pwlines_motion(FAR struct pwlines_state_s *st)
+{
+ int wndx;
+
+ /* Move each window */
+
+ for (wndx = 0; wndx < 3; wndx++)
+ {
+ if (!pwlines_move_window(st, wndx))
+ {
+ printf("pwlines_motion: ERROR:"
+ "pwlines_move_window failed for window %d\n",
+ wndx + 1);
+ }
+ }
+
+ return true;
+}
diff --git a/examples/pwlines/pwlines_update.c b/examples/pwlines/pwlines_update.c
new file mode 100644
index 0000000..cf979b8
--- /dev/null
+++ b/examples/pwlines/pwlines_update.c
@@ -0,0 +1,256 @@
+/****************************************************************************
+ * examples/pwlines/pwlines_update.c
+ *
+ * Copyright (C) 2019 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <debug.h>
+#include <fixedmath.h>
+
+#include <nuttx/nx/nx.h>
+#include <nuttx/nx/nxglib.h>
+
+#include "pwlines_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_NX_ANTIALIASING
+ /* If anti-aliasing is enabled, then we must clear a slightly
+ * larger region to prevent wierd edge effects.
+ */
+
+# define CLEAR_WIDTH (CONFIG_EXAMPLES_PWLINES_LINEWIDTH + 2)
+#else
+# define CLEAR_WIDTH CONFIG_EXAMPLES_PWLINES_LINEWIDTH
+#endif
+
+#ifndef MIN
+# define MIN(a,b) (a < b ? a : b)
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwlines_circle
+ *
+ * Description:
+ * Draw a circle in each window.
+ *
+ ****************************************************************************/
+
+void pwlines_circle(FAR struct pwlines_state_s *st)
+{
+ FAR struct pwlines_window_s *wndo;
+ nxgl_coord_t maxradius;
+ nxgl_coord_t radius;
+ int wndx;
+ int ret;
+
+ for (wndx = 0; wndx < 3; wndx++)
+ {
+ wndo = &st->wndo[wndx];
+
+ /* Get the maximum radius and center of the circle */
+
+ maxradius = MIN(wndo->size.h, wndo->size.h) >> 1;
+ wndo->center.x = wndo->size.w >> 1;
+ wndo->center.y = wndo->size.h >> 1;
+
+ /* Draw a circular background */
+
+ radius = maxradius - ((CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 1) / 2);
+ ret = nxtk_fillcirclewindow(wndo->hwnd, &wndo->center, radius,
+ st->facecolor);
+ if (ret < 0)
+ {
+ printf("pwlines_update: ERROR: nxtk_fillcirclewindow failed: %d\n",
+ ret);
+ }
+
+ /* Draw the circular border */
+
+ ret = nxtk_drawcirclewindow(wndo->hwnd, &wndo->center, radius,
+ CONFIG_EXAMPLES_PWLINES_BORDERWIDTH,
+ st->bordercolor);
+ if (ret < 0)
+ {
+ printf("pwlines_update: ERROR: nxtk_drawcirclewindow failed: %d\n",
+ ret);
+ }
+
+ /* Back off the radius to account for the thickness of border line
+ * and with a big fudge factor that will (hopefully) prevent the corners
+ * of the lines from overwriting the border. This is overly complicated
+ * here because we don't assume anything about the screen resolution or
+ * the borderwidth or the line thickness (and there are certainly some
+ * smarter ways to do this).
+ */
+
+ if (maxradius > (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 80))
+ {
+ wndo->radius = maxradius - (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 40);
+ }
+ else if (maxradius > (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 60))
+ {
+ wndo->radius = maxradius - (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 30);
+ }
+ else if (maxradius > (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 40))
+ {
+ wndo->radius = maxradius - (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 20);
+ }
+ else if (maxradius > (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 20))
+ {
+ wndo->radius = maxradius - (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 10);
+ }
+ else if (maxradius > (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 10))
+ {
+ wndo->radius = maxradius - (CONFIG_EXAMPLES_PWLINES_BORDERWIDTH + 5);
+ }
+ else
+ {
+ wndo->radius = maxradius - CONFIG_EXAMPLES_PWLINES_BORDERWIDTH;
+ }
+
+ wndo->angle = 0;
+ wndo->previous.pt1.x = wndo->center.x;
+ wndo->previous.pt1.y = wndo->center.y;
+ wndo->previous.pt2.x = wndo->center.x;
+ wndo->previous.pt2.y = wndo->center.y;
+ }
+}
+
+/****************************************************************************
+ * Name: pwlines_update
+ *
+ * Description:
+ * Update line motion.
+ *
+ ****************************************************************************/
+
+void pwlines_update(FAR struct pwlines_state_s *st)
+{
+ FAR struct pwlines_window_s *wndo;
+ struct nxgl_vector_s vector;
+ nxgl_coord_t halfx;
+ nxgl_coord_t halfy;
+ b16_t sinangle;
+ b16_t cosangle;
+ int wndx;
+ int ret;
+
+ /* Update each window */
+
+ for (wndx = 0; wndx < 3; wndx++)
+ {
+ wndo = &st->wndo[wndx];
+
+ /* Determine the position of the line on this pass */
+
+ sinangle = b16sin(wndo->angle);
+ halfx = b16toi(b16muli(sinangle, wndo->radius));
+
+ cosangle = b16cos(wndo->angle);
+ halfy = b16toi(b16muli(cosangle, wndo->radius));
+
+ vector.pt1.x = wndo->center.x + halfx;
+ vector.pt1.y = wndo->center.y + halfy;
+ vector.pt2.x = wndo->center.x - halfx;
+ vector.pt2.y = wndo->center.y - halfy;
+
+ printf("Angle: %08x vector: (%d,%d)->(%d,%d)\n",
+ wndo->angle, vector.pt1.x, vector.pt1.y, vector.pt2.x, vector.pt2.y);
+
+ /* Clear the previous line by overwriting it with the circle face color */
+
+ ret = nx_drawline(wndo->hwnd, &wndo->previous, CLEAR_WIDTH, st->facecolor,
+ NX_LINECAP_NONE);
+ if (ret < 0)
+ {
+ printf("pwlines_update: nx_drawline failed clearing: %d\n", ret);
+ }
+
+ /* Draw the new line */
+
+ ret = nx_drawline(wndo->hwnd, &vector,
+ CONFIG_EXAMPLES_PWLINES_LINEWIDTH, st->linecolor,
+ NX_LINECAP_NONE);
+ if (ret < 0)
+ {
+ printf("pwlines_update: nx_drawline failed clearing: %d\n", ret);
+ }
+
+
+#ifdef CONFIG_NX_ANTIALIASING
+ /* If anti-aliasing is enabled, then we must clear a slightly
+ * larger region to prevent wierd edge effects.
+ */
+
+ halfx = b16toi(b16muli(sinangle, wndo->radius + 1));
+ halfy = b16toi(b16muli(cosangle, wndo->radius + 1));
+
+ wndo->previous.pt1.x = wndo->center.x + halfx;
+ wndo->previous.pt1.y = wndo->center.y + halfy;
+ wndo->previous.pt2.x = wndo->center.x - halfx;
+ wndo->previous.pt2.y = wndo->center.y - halfy;
+#else
+ memcpy(&wndo->previous, &vector, sizeof(struct nxgl_vector_s));
+#endif
+
+ /* Set up for the next time through the loop. */
+
+ wndo->angle += b16PI / 16; /* 32 angular positions in full circle */
+
+ /* Check if we have gone all the way around */
+
+ if (wndo->angle > (31 * (2 * b16PI) / 32))
+ {
+ /* Wrap back to zero and continue with the test */
+
+ wndo->angle = 0;
+ }
+ }
+}