From e26d78f40a668c5d4f5a2ebf5b160e63f74d1610 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 20 Mar 2019 12:36:46 -0600 Subject: [PATCH] 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. --- examples/pwfb/Kconfig | 2 +- examples/pwfb/pwfb_main.c | 18 +- examples/pwlines/.gitignore | 11 + examples/pwlines/Kconfig | 138 +++++++ examples/pwlines/Make.defs | 39 ++ examples/pwlines/Makefile | 58 +++ examples/pwlines/pwlines_events.c | 187 ++++++++++ examples/pwlines/pwlines_internal.h | 246 +++++++++++++ examples/pwlines/pwlines_main.c | 536 ++++++++++++++++++++++++++++ examples/pwlines/pwlines_motion.c | 202 +++++++++++ examples/pwlines/pwlines_update.c | 256 +++++++++++++ 11 files changed, 1683 insertions(+), 10 deletions(-) create mode 100644 examples/pwlines/.gitignore create mode 100644 examples/pwlines/Kconfig create mode 100644 examples/pwlines/Make.defs create mode 100644 examples/pwlines/Makefile create mode 100644 examples/pwlines/pwlines_events.c create mode 100644 examples/pwlines/pwlines_internal.h create mode 100644 examples/pwlines/pwlines_main.c create mode 100644 examples/pwlines/pwlines_motion.c create mode 100644 examples/pwlines/pwlines_update.c diff --git a/examples/pwfb/Kconfig b/examples/pwfb/Kconfig index 2da6b8574..1a5567487 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 1fe6c7a55..2d13ee2b4 100644 --- a/examples/pwfb/pwfb_main.c +++ b/examples/pwfb/pwfb_main.c @@ -205,7 +205,7 @@ static bool pwfb_state_initialize(FAR struct pwfb_state_s *st) 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 @@ static bool pwfb_configure_window(FAR struct pwfb_state_s *st, int wndx, 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 @@ static bool pwfb_configure_window(FAR struct pwfb_state_s *st, int wndx, 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 @@ int pwfb_main(int argc, char *argv[]) { 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 000000000..fa1ec7579 --- /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 000000000..c978eb7fd --- /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 000000000..bec09aef7 --- /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 +# +# 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 000000000..3c71ea7f3 --- /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 +# +# 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 000000000..932eae3ef --- /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 + * + * 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 +#include +#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 000000000..c9d706482 --- /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 + * + * 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 + +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * 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 000000000..fa498d5bb --- /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 + * + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_VNCSERVER +# include +#endif + +#include +#include +#include + +#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 000000000..e560d62b1 --- /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 + * + * 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 "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 000000000..cf979b8b2 --- /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 + * + * 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 +#include + +#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; + } + } +}