aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--demos/3rdparty/notepad-2/gfxconf.h58
-rw-r--r--demos/3rdparty/notepad-2/main.c108
-rw-r--r--demos/3rdparty/notepad-2/notepadApp.c471
-rw-r--r--demos/3rdparty/notepad-2/notepadApp.h48
-rw-r--r--demos/3rdparty/notepad-2/notepadCore.c235
-rw-r--r--demos/3rdparty/notepad-2/notepadCore.h66
-rw-r--r--demos/3rdparty/notepad-2/notepadUIDefines.h114
-rw-r--r--demos/3rdparty/notepad-2/readme.txt17
-rw-r--r--demos/3rdparty/notepad-2/toolbarIcons.gifbin0 -> 3184 bytes
-rw-r--r--demos/3rdparty/notepad-2/toolbarIcons.h237
-rw-r--r--docs/src/main.dox12
-rw-r--r--drivers/gdisp/HX8347D/HX8347D.h143
-rw-r--r--drivers/gdisp/HX8347D/gdisp_lld.c495
-rw-r--r--drivers/gdisp/HX8347D/gdisp_lld.mk5
-rw-r--r--drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h202
-rw-r--r--drivers/gdisp/HX8347D/gdisp_lld_config.h39
-rw-r--r--drivers/gdisp/HX8347D/readme.txt24
-rw-r--r--include/gdisp/fonts.h123
-rw-r--r--include/gdisp/image.h3
-rw-r--r--include/gwin/button.h50
-rw-r--r--include/gwin/gwin.h25
-rw-r--r--releases.txt2
-rw-r--r--src/gdisp/fonts.c1
-rw-r--r--src/gdisp/image.c3
-rw-r--r--src/gdisp/image_bmp.c3
-rw-r--r--src/gdisp/image_gif.c7
-rw-r--r--src/gdisp/image_native.c3
-rw-r--r--src/gdisp/image_png.c5
-rw-r--r--src/ginput/mouse.c1140
-rw-r--r--src/gwin/button.c41
-rw-r--r--src/gwin/gwin.c4
-rw-r--r--src/tdisp/tdisp.c2
33 files changed, 3029 insertions, 659 deletions
diff --git a/.gitignore b/.gitignore
index a8ae8ed8..dc11e710 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
docs/html
+*.lst
+*.o
diff --git a/demos/3rdparty/notepad-2/gfxconf.h b/demos/3rdparty/notepad-2/gfxconf.h
new file mode 100644
index 00000000..0768ca22
--- /dev/null
+++ b/demos/3rdparty/notepad-2/gfxconf.h
@@ -0,0 +1,58 @@
+/*
+ * This file has a different license to the rest of the GFX system.
+ * You can copy, modify and distribute this file as you see fit.
+ * You do not need to publish your source modifications to this file.
+ * The only thing you are not permitted to do is to relicense it
+ * under a different license.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GWIN TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+#define GFX_USE_GINPUT TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_TEXT TRUE
+#define GDISP_NEED_CIRCLE TRUE
+#define GDISP_NEED_ELLIPSE FALSE
+#define GDISP_NEED_ARC FALSE
+#define GDISP_NEED_CONVEX_POLYGON FALSE
+#define GDISP_NEED_SCROLL FALSE
+#define GDISP_NEED_PIXELREAD FALSE
+#define GDISP_NEED_CONTROL TRUE
+#define GDISP_NEED_IMAGE TRUE
+#define GDISP_NEED_MULTITHREAD TRUE
+#define GDISP_NEED_ASYNC FALSE
+#define GDISP_NEED_MSGAPI FALSE
+
+/* Builtin Fonts */
+#define GDISP_INCLUDE_FONT_SMALL FALSE
+#define GDISP_INCLUDE_FONT_LARGER FALSE
+#define GDISP_INCLUDE_FONT_UI1 FALSE
+#define GDISP_INCLUDE_FONT_UI2 TRUE
+#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
+
+/* GDISP image decoders */
+#define GDISP_NEED_IMAGE_NATIVE FALSE
+#define GDISP_NEED_IMAGE_GIF TRUE
+#define GDISP_NEED_IMAGE_BMP FALSE
+#define GDISP_NEED_IMAGE_JPG FALSE
+#define GDISP_NEED_IMAGE_PNG FALSE
+
+/* Features for the GWIN sub-system. */
+#define GWIN_NEED_BUTTON TRUE
+#define GWIN_NEED_CONSOLE TRUE
+#define GWIN_NEED_SLIDER TRUE
+
+/* Features for the GINPUT sub-system. */
+#define GINPUT_NEED_MOUSE TRUE
+#define GINPUT_NEED_DIAL FALSE
+
+#endif /* _GFXCONF_H */
diff --git a/demos/3rdparty/notepad-2/main.c b/demos/3rdparty/notepad-2/main.c
new file mode 100644
index 00000000..350cee80
--- /dev/null
+++ b/demos/3rdparty/notepad-2/main.c
@@ -0,0 +1,108 @@
+/*
+ * File: main.c
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * 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 <COPYRIGHT HOLDER> 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 "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#include "notepadApp.h"
+
+const NColorScheme schemeDefault = {
+ .titleBarColor = HTML2COLOR(0x3064D8),
+ .titleTextColor = White,
+
+ .winBgColor = HTML2COLOR(0xFFECB0),
+ .drawingWinBorder = HTML2COLOR(0xCEBA77),
+
+ .toolbarSeparator = HTML2COLOR(0xC09028),
+ .toolbarBgUnsel = HTML2COLOR(0xF0D484),
+ .toolbarBgActive = HTML2COLOR(0xC8B060),
+ .toolbarBgSel = HTML2COLOR(0xDCC06C),
+
+ .statusBarText = HTML2COLOR(0x000000)
+};
+
+const NColorScheme schemeDefault2 = {
+ .titleBarColor = HTML2COLOR(0x3064D8),
+ .titleTextColor = White,
+
+ .winBgColor = HTML2COLOR(0xC8D8F8),
+ .drawingWinBorder = HTML2COLOR(0x8098E0),
+
+ .toolbarSeparator = HTML2COLOR(0x5078F0),
+ .toolbarBgUnsel = HTML2COLOR(0xA0B8F0),
+ .toolbarBgActive = HTML2COLOR(0x6084F0),
+ .toolbarBgSel = HTML2COLOR(0x88A8F8),
+
+ .statusBarText = HTML2COLOR(0x000000)
+};
+
+const char *tsCalibRead(uint16_t instance) {
+ // This will perform a on-spot calibration
+ // Unless you read and add the co-efficients here
+ return NULL;
+}
+
+int main(void) {
+
+ font_t font = gdispOpenFont("UI2");
+
+ /* initialize the hardware and the OS */
+ halInit();
+ chSysInit();
+
+ /* initialize the LCD */
+ gdispInit();
+ gdispClear(Black);
+
+ /* Calibrate the touchscreen */
+ ginputSetMouseCalibrationRoutines(0, NULL, tsCalibRead, FALSE);
+ ginputGetMouse(0);
+
+ // Set the color scheme
+ nSetColorScheme(schemeDefault);
+
+ while (TRUE) {
+
+ chThdWait(nLaunchNotepadApp());
+
+ gdispClear(Black);
+ gdispSetClip(0, 0, gdispGetWidth(), gdispGetHeight());
+ gdispDrawString(3, 3, "Notepad Terminated.", font, White);
+ gdispDrawString(3, 20, "Relaunching Notepad App...", font, White);
+
+ chThdSleepMilliseconds(1000);
+
+ }
+
+ return 0;
+}
diff --git a/demos/3rdparty/notepad-2/notepadApp.c b/demos/3rdparty/notepad-2/notepadApp.c
new file mode 100644
index 00000000..a89b7bf0
--- /dev/null
+++ b/demos/3rdparty/notepad-2/notepadApp.c
@@ -0,0 +1,471 @@
+/*
+ * File: notepadApp.c
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * 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 <COPYRIGHT HOLDER> 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 "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#include "chprintf.h"
+
+#include "notepadApp.h"
+#include "toolbarIcons.h"
+
+// Get the handle for a window object
+#define H(obj) ((GHandle)&obj)
+
+// Static objects
+static GListener gl; // Event listener object
+static GHandle nDrawingArea; // GWindow Drawing Area
+static BaseSequentialStream *gstatusConsole; // GConsole Handle to the Status Bar
+
+static GEventMouse curPtr; // Holder for current pointer location
+
+static font_t font;
+static coord_t swidth, sheight;
+
+// The toolbar buttons - Self-Explanatory
+static GButtonObject btnNew, btnOpen, btnSave;
+static GButtonObject btnColorBar;
+static GButtonObject btnColorBarSel;
+
+static GButtonObject btnPencil, btnFill, btnEraser;
+
+static GButtonObject btnClose;
+/* static GButtonObject btnYes, btnNo; // Reserved for future use */
+
+// Image object
+static gdispImage toolbarImageFilmstrip;
+
+static color_t myColors[] = { Black, Red, Green, Blue, Cyan, Magenta, Yellow, White };
+
+static color_t selColor = Black;
+static int selColorIndex = 0, selPenWidth = 1, tbMode = 1;
+
+static NColorScheme nCurColorScheme;
+
+static msg_t notepadThread(void *param);
+
+// Custom drawing functions for the buttons
+static void nbtnColorBarDraw(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ #define ccs nCurColorScheme
+
+ int i, j, k;
+
+ (void)txt;
+ (void)pstyle;
+ (void)param;
+ (void)enabled;
+
+ ginputGetMouseStatus(0, &curPtr);
+
+ // Draw the toolbars according to the mode
+ if (tbMode == 0) {
+ k = (curPtr.x - gh->x) / (NPAD_COLORBAR_WIDTH / 8);
+
+ for (i = 0; i < 8; i++) {
+ j = gh->x + (NPAD_TOOLBAR_BTN_WIDTH / 2) + NPAD_TOOLBAR_BTN_WIDTH * i;
+
+ if (isdown == TRUE) {
+ // Update selection - this is like lazy release.
+ if (k >= 0 && k <= 7) {
+ selPenWidth = k + 1;
+ ncoreSetPenWidth((uint8_t) selPenWidth);
+ }
+
+ gdispFillArea(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT,
+ selPenWidth - i == 1 ? ccs.toolbarBgActive : ccs.toolbarBgUnsel);
+ }
+ else {
+ gdispFillArea(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT,
+ selPenWidth - i == 1 ? ccs.toolbarBgSel : ccs.toolbarBgUnsel);
+
+ gdispDrawBox(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT,
+ selPenWidth - i == 1 ? ccs.toolbarSeparator: ccs.toolbarBgUnsel);
+ }
+
+ gdispFillCircle(j, gh->y + 10, i + 1, myColors[selColorIndex]);
+ }
+
+ } else {
+ k = (curPtr.x - gh->x) / (NPAD_COLORBAR_WIDTH / 8);
+
+ for (i = 0; i < 8; i++) {
+ j = gh->x + (NPAD_TOOLBAR_BTN_WIDTH / 2) + NPAD_TOOLBAR_BTN_WIDTH * i;
+
+ if (isdown == TRUE) {
+ // Update selection - this is like lazy release.
+ if (k >= 0 && k <= 7) {
+ selColorIndex = k;
+ selColor = myColors[k];
+ ncoreSetPenColor(selColor);
+ }
+
+ gdispFillArea(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT,
+ k == i ? ccs.toolbarBgActive : ccs.toolbarBgUnsel);
+ }
+ else {
+ gdispFillArea(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT,
+ selColorIndex == i ? ccs.toolbarBgSel : ccs.toolbarBgUnsel);
+
+ gdispDrawBox(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT,
+ selColorIndex == i ? ccs.toolbarSeparator: ccs.toolbarBgUnsel);
+ }
+
+ gdispFillCircle(j, gh->y + (NPAD_TOOLBAR_BTN_HEIGHT / 2), 3, myColors[i] );
+ }
+ }
+
+
+ #undef ccs
+}
+
+static void nbtnColorBarSelDraw(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+#define ccs nCurColorScheme
+
+ int i, j = 0, k;
+ color_t ca, cb;
+ GEventMouse ptr;
+
+ (void)txt;
+ (void)pstyle;
+ (void)param;
+ (void)enabled;
+
+ // Get a copy of the pointer location
+ ginputGetMouseStatus(0, &ptr);
+
+ // Get which button the pointer is on right now
+ k = (ptr.x - gh->x) / NPAD_TOOLBAR_BTN_WIDTH;
+
+ gdispDrawBox(gh->x, gh->y, gh->width, gh->height, ccs.toolbarBgUnsel);
+ gdispDrawBox(gh->x + 1, gh->y + 1, gh->width - 2, gh->height - 2, ccs.toolbarBgUnsel);
+
+ for (i = 0; i < 2; i++) {
+ if (isdown == TRUE) {
+ // Update selection - this is like lazy release.
+ if (k == 0 || k == 1) {
+ tbMode = k;
+ j = 1;
+ }
+
+ ca = (tbMode == i ? ccs.toolbarBgActive : ccs.toolbarBgUnsel);
+ }
+ else {
+ ca = (tbMode == i ? ccs.toolbarBgSel : ccs.toolbarBgUnsel);
+ }
+
+ cb = (tbMode == i ? ccs.toolbarSeparator : ccs.toolbarBgUnsel);
+
+ gdispFillArea(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i,
+ gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH,
+ NPAD_TOOLBAR_BTN_HEIGHT,
+ ca);
+
+ gdispImageSetBgColor(&toolbarImageFilmstrip, ca);
+ gdispDrawBox(gh->x + NPAD_TOOLBAR_BTN_WIDTH * i, gh->y,
+ NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, cb);
+
+ /* Draw both the icons */
+ gwinImageDraw(gh, &toolbarImageFilmstrip,
+ 2 + NPAD_TOOLBAR_BTN_WIDTH * i,
+ 2,
+ NPAD_ICON_WIDTH,
+ NPAD_ICON_HEIGHT,
+ NPAD_ICON_START(3 + i),
+ 0);
+ }
+
+ if (j)
+ gwinButtonDraw(H(btnColorBar));
+
+ #undef ccs
+}
+
+static void nToolbarImageButtonDraw(GHandle gh, bool_t isenabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void)txt; (void)pstyle; (void)isenabled;
+
+ color_t cl = isdown ? nCurColorScheme.toolbarBgActive : nCurColorScheme.toolbarBgUnsel;
+
+ gdispImageSetBgColor(&toolbarImageFilmstrip, cl);
+ gdispFillArea(gh->x, gh->y, gh->width, gh->height, cl);
+ gwinImageDraw(gh, &toolbarImageFilmstrip, 2, 2, NPAD_ICON_WIDTH, NPAD_ICON_HEIGHT, NPAD_ICON_START((int) param), 0);
+
+ if (isdown || ((int)param - 5) == ncoreGetMode())
+ gdispDrawBox(gh->x, gh->y, gh->width, gh->height, nCurColorScheme.toolbarSeparator);
+}
+
+static void nCloseButtonDraw(GHandle gh, bool_t isenabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ gwinImageDraw(gh, &toolbarImageFilmstrip, 0, 0, NPAD_ICON_WIDTH, NPAD_ICON_HEIGHT, NPAD_ICON_START(8), 0);
+}
+
+static void initButtons(void) {
+
+ /* Init all the button objects */
+ gwinCreateButton(&btnNew, NPAD_TOOLBAR_1_X(0), NPAD_TOOLBAR_1_Y, NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, font, GBTN_CUSTOM);
+ gwinCreateButton(&btnOpen, NPAD_TOOLBAR_1_X(1), NPAD_TOOLBAR_1_Y, NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, font, GBTN_CUSTOM);
+ gwinCreateButton(&btnSave, NPAD_TOOLBAR_1_X(2), NPAD_TOOLBAR_1_Y, NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, font, GBTN_CUSTOM);
+
+ gwinCreateButton(&btnColorBarSel, NPAD_COLORBAR_SEL_X, NPAD_COLORBAR_SEL_Y, NPAD_COLORBAR_SEL_WIDTH, NPAD_COLORBAR_SEL_HEIGHT, font, GBTN_CUSTOM);
+ gwinCreateButton(&btnColorBar, NPAD_COLORBAR_X, NPAD_TOOLBAR_1_Y, NPAD_COLORBAR_WIDTH, NPAD_COLORBAR_HEIGHT, font, GBTN_CUSTOM);
+
+ gwinCreateButton(&btnPencil, NPAD_TOOLBAR_2_X, NPAD_TOOLBAR_2_Y(0), NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, font, GBTN_CUSTOM);
+ gwinCreateButton(&btnEraser, NPAD_TOOLBAR_2_X, NPAD_TOOLBAR_2_Y(1), NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, font, GBTN_CUSTOM);
+ gwinCreateButton(&btnFill, NPAD_TOOLBAR_2_X, NPAD_TOOLBAR_2_Y(2), NPAD_TOOLBAR_BTN_WIDTH, NPAD_TOOLBAR_BTN_HEIGHT, font, GBTN_CUSTOM);
+
+ gwinCreateButton(&btnClose, swidth - 18, 0, 16, 16, font, GBTN_CUSTOM);
+
+ /* Attach custom renders */
+ gwinSetButtonCustom(H(btnNew), nToolbarImageButtonDraw, (void *)0);
+ gwinSetButtonCustom(H(btnOpen), nToolbarImageButtonDraw, (void *)1);
+ gwinSetButtonCustom(H(btnSave), nToolbarImageButtonDraw, (void *)2);
+
+ gwinSetButtonCustom(H(btnColorBar), nbtnColorBarDraw, (void *)0);
+ gwinSetButtonCustom(H(btnColorBarSel), nbtnColorBarSelDraw, (void *)0);
+
+ gwinSetButtonCustom(H(btnPencil), nToolbarImageButtonDraw, (void *)5);
+ gwinSetButtonCustom(H(btnEraser), nToolbarImageButtonDraw, (void *)6);
+ gwinSetButtonCustom(H(btnFill), nToolbarImageButtonDraw, (void *)7);
+ gwinSetButtonCustom(H(btnClose), nCloseButtonDraw, (void *)0);
+
+ /* Attach listeners */
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnNew)), 0);
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnOpen)), 0);
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnSave)), 0);
+
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnColorBar)), 0);
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnColorBarSel)), 0);
+
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnPencil)), 0);
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnEraser)), 0);
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnFill)), 0);
+ geventAttachSource(&gl, gwinGetButtonSource(H(btnClose)), 0);
+
+ /* Give listeners access to touch events */
+ gwinAttachButtonMouse(H(btnNew), 0);
+ gwinAttachButtonMouse(H(btnOpen), 0);
+ gwinAttachButtonMouse(H(btnSave), 0);
+
+ gwinAttachButtonMouse(H(btnColorBar), 0);
+ gwinAttachButtonMouse(H(btnColorBarSel), 0);
+
+ gwinAttachButtonMouse(H(btnPencil), 0);
+ gwinAttachButtonMouse(H(btnEraser), 0);
+ gwinAttachButtonMouse(H(btnFill), 0);
+ gwinAttachButtonMouse(H(btnClose), 0);
+
+}
+
+static void drawButtons(void) {
+ gwinButtonDraw(H(btnNew));
+ gwinButtonDraw(H(btnOpen));
+ gwinButtonDraw(H(btnSave));
+
+ gwinButtonDraw(H(btnColorBar));
+ gwinButtonDraw(H(btnColorBarSel));
+
+ gwinButtonDraw(H(btnClose));
+}
+
+static void drawVButtons(void) {
+ gwinButtonDraw(H(btnPencil));
+ gwinButtonDraw(H(btnEraser));
+ gwinButtonDraw(H(btnFill));
+}
+
+static WORKING_AREA(waNotepadThread, NPAD_THD_WA_SIZE);
+static msg_t notepadThread(void *param) {
+
+ GEventMouse *pem;
+ GEventGWinButton *peb;
+ GHandle ghc;
+
+ (void)param;
+
+ /* Get the display dimensions */
+ swidth = gdispGetWidth();
+ sheight = gdispGetHeight();
+
+ font = gdispOpenFont("UI2");
+
+ /* Initialize the mouse */
+ geventListenerInit(&gl);
+ ginputGetMouse(0);
+
+ initButtons();
+
+ /* Configure the GIF decoder with the toolbar Icon images */
+ gdispImageSetMemoryReader(&toolbarImageFilmstrip, toolbarIcons);
+ gdispImageOpen(&toolbarImageFilmstrip);
+
+ /* Set clip to the entire screen */
+ gdispSetClip(0, 0, swidth, sheight);
+
+ /* Clear the screen with the window background
+ * Also, draw the title bars */
+ gdispClear(nCurColorScheme.winBgColor);
+ gdispDrawBox(0, 0, swidth, sheight, nCurColorScheme.titleBarColor);
+ gdispFillArea(0, 0, swidth, NPAD_TITLEBAR_HEIGHT, nCurColorScheme.titleBarColor);
+ gdispDrawStringBox(NPAD_TITLETEXT_START_X,
+ NPAD_TITLETEXT_START_Y,
+ swidth,
+ NPAD_TITLEBAR_HEIGHT,
+ NPAD_TITLETEXT_STR,
+ font,
+ nCurColorScheme.titleTextColor,
+ justifyLeft);
+
+ /* Create the drawing window, draw its border */
+ gdispDrawBox(NPAD_DRAWING_AREA_START_X - 1,
+ NPAD_DRAWING_AREA_START_Y - 1,
+ NPAD_DRAWING_AREA_WIDTH + 2,
+ NPAD_DRAWING_AREA_HEIGHT + 2,
+ nCurColorScheme.drawingWinBorder);
+
+ nDrawingArea = gwinCreateWindow(NULL,
+ NPAD_DRAWING_AREA_START_X,
+ NPAD_DRAWING_AREA_START_Y,
+ NPAD_DRAWING_AREA_WIDTH,
+ NPAD_DRAWING_AREA_HEIGHT);
+
+ /* Create the bottom status bar console */
+ ghc = gwinCreateConsole(NULL,
+ NPAD_STATUSBAR_START_X,
+ NPAD_STATUSBAR_START_Y,
+ NPAD_STATUSBAR_WIDTH,
+ NPAD_STATUSBAR_HEIGHT,
+ font);
+
+ gdispImageDraw(&toolbarImageFilmstrip,
+ NPAD_STATUSBAR_ICON_START_X,
+ NPAD_STATUSBAR_ICON_START_Y,
+ NPAD_ICON_WIDTH,
+ NPAD_ICON_HEIGHT,
+ NPAD_ICON_START(12),
+ 0);
+
+ gwinSetBgColor(ghc, nCurColorScheme.winBgColor);
+ gwinSetColor(ghc, Black);
+
+ gstatusConsole = gwinGetConsoleStream(ghc);
+
+ /* draw the buttons */
+ gwinSetColor(nDrawingArea, Black);
+ gwinSetBgColor(nDrawingArea, White);
+
+ gwinClear(nDrawingArea);
+ gwinClear(ghc);
+
+ drawButtons();
+ drawVButtons();
+
+ chprintf(gstatusConsole, "Welcome to ChibiOS/GFX Notepad demo.");
+
+ ncoreSpawnDrawThread(nDrawingArea, gstatusConsole);
+
+ while(TRUE) {
+ pem = (GEventMouse *) geventEventWait(&gl, TIME_INFINITE);
+
+ /* button pressed... */
+ if (pem->type == GEVENT_GWIN_BUTTON) {
+ peb = (GEventGWinButton *)pem;
+
+ if (peb->button == H(btnNew)) {
+ // Reset all the settings
+ selColorIndex = 0;
+ selPenWidth = 0;
+ ncoreSetMode(NCORE_MODE_DRAW);
+
+ gwinSetColor(nDrawingArea, Black);
+ gwinSetBgColor(nDrawingArea, White);
+
+ // Refresh the buttons
+ drawButtons();
+ drawVButtons();
+
+ gwinClear(nDrawingArea);
+ chprintf(gstatusConsole, "\nScreen Cleared.");
+ }
+ else if (peb->button == H(btnOpen)) {
+ chprintf(gstatusConsole, "\nFile Open not implemented.");
+ }
+ else if (peb->button == H(btnSave)) {
+ chprintf(gstatusConsole, "\nFile Save not implemented.");
+ }
+ else if (peb->button == H(btnPencil)) {
+ ncoreSetMode(NCORE_MODE_DRAW);
+ drawVButtons();
+ chprintf(gstatusConsole, "\nPencil Tool Selected.");
+ }
+ else if (peb->button == H(btnEraser)) {
+ ncoreSetMode(NCORE_MODE_ERASE);
+ drawVButtons();
+ chprintf(gstatusConsole, "\nEraser Tool Selected.");
+ }
+ else if (peb->button == H(btnFill)) {
+ ncoreSetMode(NCORE_MODE_FILL);
+ drawVButtons();
+ chprintf(gstatusConsole, "\nFill Tool Selected.");
+ }
+ else if (peb->button == H(btnClose)) {
+ break;
+ }
+ }
+ }
+
+ gwinDestroyWindow(ghc);
+ // No need to destroy the buttons as they are statically allocated
+ gdispCloseFont(font);
+ ncoreTerminateDrawThread();
+ gdispImageClose(&toolbarImageFilmstrip);
+
+ return 0;
+}
+
+// Public methods
+void nSetColorScheme(NColorScheme sch) { nCurColorScheme = sch; }
+NColorScheme nGetColorScheme(void) { return nCurColorScheme; }
+
+Thread *nLaunchNotepadApp(void) {
+
+ return chThdCreateStatic(waNotepadThread,
+ sizeof(waNotepadThread),
+ NPAD_THD_PRIO,
+ notepadThread, NULL);
+
+}
diff --git a/demos/3rdparty/notepad-2/notepadApp.h b/demos/3rdparty/notepad-2/notepadApp.h
new file mode 100644
index 00000000..bae5f59c
--- /dev/null
+++ b/demos/3rdparty/notepad-2/notepadApp.h
@@ -0,0 +1,48 @@
+/*
+ * File: notepadApp.h
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * 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 <COPYRIGHT HOLDER> 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 NOTEPADAPP_H_
+#define NOTEPADAPP_H_
+
+#include "notepadCore.h"
+#include "notepadUIDefines.h"
+
+#define NPAD_THD_PRIO (NORMALPRIO + 2)
+#define NPAD_THD_WA_SIZE 512
+
+void nSetColorScheme(NColorScheme sch);
+NColorScheme nGetColorScheme(void);
+
+
+Thread *nLaunchNotepadApp(void);
+
+#endif /* NOTEPADAPP_H_ */
diff --git a/demos/3rdparty/notepad-2/notepadCore.c b/demos/3rdparty/notepad-2/notepadCore.c
new file mode 100644
index 00000000..abb189bc
--- /dev/null
+++ b/demos/3rdparty/notepad-2/notepadCore.c
@@ -0,0 +1,235 @@
+/*
+ * File: notepadCore.c
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * 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 <COPYRIGHT HOLDER> 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 <stdlib.h>
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#include "notepadCore.h"
+#include "notepadUIDefines.h"
+
+#define PEN_IN_DRAWING_AREA(ev) ((ev.x >= ncoreDrawingArea->x) && (ev.x <= (ncoreDrawingArea->x + ncoreDrawingArea->width)) && \
+ (ev.y >= ncoreDrawingArea->y) && (ev.y <= (ncoreDrawingArea->y + ncoreDrawingArea->height)))
+
+/* This is the drawing core */
+static WORKING_AREA(waDrawThread, NCORE_THD_STACK_SIZE);
+
+static uint8_t nPenWidth = 1;
+static uint8_t nMode = NCORE_MODE_DRAW;
+
+static Thread *nThd;
+
+static GHandle ncoreDrawingArea = NULL;
+static BaseSequentialStream *nStatusConsole = NULL;
+
+static void draw_point(coord_t x, coord_t y) {
+ color_t c = ncoreDrawingArea->color;
+
+ if (nMode == NCORE_MODE_DRAW)
+ c = ncoreDrawingArea->color;
+ else if (nMode == NCORE_MODE_ERASE)
+ c = ncoreDrawingArea->bgcolor;
+
+ if (nPenWidth == 1)
+ gdispDrawPixel(x, y, c);
+ else
+ gdispFillCircle(x, y, nPenWidth, c);
+}
+
+/* Bresenham's Line Drawing Algorithm
+ Modified version to draw line of variable thickness */
+static void draw_line(coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
+ int16_t dy, dx;
+ int16_t addx, addy;
+ int16_t P, diff, i;
+
+ if (x1 >= x0) {
+ dx = x1 - x0;
+ addx = 1;
+ } else {
+ dx = x0 - x1;
+ addx = -1;
+ }
+ if (y1 >= y0) {
+ dy = y1 - y0;
+ addy = 1;
+ } else {
+ dy = y0 - y1;
+ addy = -1;
+ }
+
+ if (dx >= dy) {
+ dy *= 2;
+ P = dy - dx;
+ diff = P - dx;
+
+ for(i=0; i<=dx; ++i) {
+ draw_point(x0, y0);
+ if (P < 0) {
+ P += dy;
+ x0 += addx;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ } else {
+ dx *= 2;
+ P = dx - dy;
+ diff = P - dy;
+
+ for(i=0; i<=dy; ++i) {
+ draw_point(x0, y0);
+ if (P < 0) {
+ P += dx;
+ y0 += addy;
+ } else {
+ P += diff;
+ x0 += addx;
+ y0 += addy;
+ }
+ }
+ }
+}
+
+/* Core thread */
+static msg_t ncoreDrawThread(void *msg) {
+
+ GEventMouse ev, evPrev;
+ coord_t dx, dy;
+
+ int state = 0, dist;
+
+ (void)msg;
+
+ ginputGetMouseStatus(0, &evPrev);
+
+ while (1) {
+
+ // Exit signal received? If yes, terminate.
+ if (chThdShouldTerminate())
+ return 0;
+
+ ginputGetMouseStatus(0, &ev);
+ switch(state) {
+ case 0: if (ev.meta == GMETA_MOUSE_DOWN) {
+ state = 1;
+ if (nMode == NCORE_MODE_FILL && PEN_IN_DRAWING_AREA(ev)) {
+ // Set bgcolor to current color, clear the display.
+ ncoreDrawingArea->bgcolor = ncoreDrawingArea->color;
+ gwinClear(ncoreDrawingArea);
+ }
+ }
+ else
+ chThdYield();
+ break;
+
+
+ case 1: if (ev.meta == GMETA_MOUSE_UP) {
+ state = 0;
+ //chprintf(nStatusConsole, "\nPen Up: (%d, %d)", ev.x, ev.y);
+ break;
+ }
+
+ dx = abs(ev.x - evPrev.x);
+ dy = abs(ev.y - evPrev.y);
+
+ dist = dx * dx + dy * dy;
+
+ if (dist > 0)
+ {
+ gdispSetClip(ncoreDrawingArea->x,
+ ncoreDrawingArea->y,
+ ncoreDrawingArea->width,
+ ncoreDrawingArea->height);
+
+ if (PEN_IN_DRAWING_AREA(ev)){
+ // Do Interpolation
+ if (dist <= 2) {
+ draw_point(ev.x, ev.y);
+ }
+ else if (dist <= 5) {
+ // Line drawing does not give good results for this case.
+ // So draw two pixels directly
+ draw_point(ev.x, ev.y);
+ draw_point((ev.x + evPrev.x) / 2, (ev.y + evPrev.y) / 2);
+ }
+ else if (dx * dx <= MAX_DX && dy * dy <= MAX_DY) {
+ draw_line(ev.x, ev.y, evPrev.x, evPrev.y);
+ }
+ }
+
+ //chprintf(nStatusConsole, "\nPen Down: (%d, %d)", ev.x, ev.y);
+ }
+ break;
+ }
+ evPrev = ev;
+ }
+
+ return 0;
+}
+
+/* Spawn the core thread */
+void ncoreSpawnDrawThread(GHandle drawingArea, BaseSequentialStream *statusConsole) {
+
+ ncoreDrawingArea = drawingArea;
+ nStatusConsole = statusConsole;
+
+ nThd = chThdCreateStatic(waDrawThread,
+ sizeof(waDrawThread),
+ NCORE_THD_PRIO,
+ ncoreDrawThread,
+ NULL);
+
+}
+
+/* Terminate the core thread, wait for control release */
+void ncoreTerminateDrawThread(void) {
+ chThdTerminate(nThd);
+ chThdWait(nThd);
+}
+
+/* Get and set the pen width
+ * Brush is cicular, width is pixel radius */
+void ncoreSetPenWidth(uint8_t penWidth) { nPenWidth = penWidth; }
+uint8_t ncoreGetPenWidth(void) { return nPenWidth; }
+
+/* Get and set the drawing color */
+void ncoreSetPenColor(color_t penColor) { gwinSetColor(ncoreDrawingArea, penColor); }
+color_t ncoreGetPenColor(void) { return ncoreDrawingArea->color; }
+
+/* Set mode */
+void ncoreSetMode(uint8_t mode) { nMode = mode; }
+uint8_t ncoreGetMode(void) { return nMode; }
diff --git a/demos/3rdparty/notepad-2/notepadCore.h b/demos/3rdparty/notepad-2/notepadCore.h
new file mode 100644
index 00000000..b4f1b185
--- /dev/null
+++ b/demos/3rdparty/notepad-2/notepadCore.h
@@ -0,0 +1,66 @@
+/*
+ * File: notepadCore.h
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * 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 <COPYRIGHT HOLDER> 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 NOTEPADCORE_H_
+#define NOTEPADCORE_H_
+
+/* Configuration */
+#define NCORE_THD_STACK_SIZE 256
+#define NCORE_THD_PRIO (NORMALPRIO + 1)
+
+#define NCORE_MODE_DRAW 0
+#define NCORE_MODE_ERASE 1
+#define NCORE_MODE_FILL 2
+
+#define MAX_DX 500
+#define MAX_DY 500
+
+/* Spawn the notepad core thread */
+void ncoreSpawnDrawThread(GHandle drawingArea, BaseSequentialStream *statusConsole);
+
+/* Terminate the core thread, wait for control release */
+void ncoreTerminateDrawThread(void);
+
+/* Get and set the pen width
+ * Brush is cicular, width is pixel radius */
+void ncoreSetPenWidth(uint8_t penWidth);
+uint8_t ncoreGetPenWidth(void);
+
+/* Get and set the drawing color */
+void ncoreSetPenColor(color_t penColor);
+color_t ncoreGetPenColor(void);
+
+/* Get and set the pen mode */
+void ncoreSetMode(uint8_t mode);
+uint8_t ncoreGetMode(void);
+
+#endif /* NOTEPADCORE_H_ */
diff --git a/demos/3rdparty/notepad-2/notepadUIDefines.h b/demos/3rdparty/notepad-2/notepadUIDefines.h
new file mode 100644
index 00000000..5ed08d00
--- /dev/null
+++ b/demos/3rdparty/notepad-2/notepadUIDefines.h
@@ -0,0 +1,114 @@
+/*
+ * File: notepadUIDefines.h
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ * Copyright © 2013, Kumar Abhishek [abhishek.kakkar@edaboard.com].
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * The name of 'Kumar Abhishek' may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * DISCLAIMER OF WARRANTY:
+ * 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 <COPYRIGHT HOLDER> 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 NOTEPADUIDEFINES_H_
+#define NOTEPADUIDEFINES_H_
+
+#define NPAD_TITLETEXT_STR "ChibiOS/GFX Notepad Demo"
+
+/* UI Element dimenstions */
+#define NPAD_TITLEBAR_HEIGHT 18
+#define NPAD_TITLETEXT_START_X 5
+#define NPAD_TITLETEXT_START_Y 0
+
+#define NPAD_TOOLBAR_BTN_WIDTH 20
+#define NPAD_TOOLBAR_BTN_HEIGHT 20
+
+#define NPAD_TOOLBAR_INTERBTN_PADDING_X 2
+#define NPAD_TOOLBAR_1_START_X 5
+#define NPAD_TOOLBAR_1_Y (NPAD_TITLEBAR_HEIGHT + 3)
+#define NPAD_TOOLBAR_1_X(n) (NPAD_TOOLBAR_1_START_X + \
+ (NPAD_TOOLBAR_BTN_WIDTH + \
+ NPAD_TOOLBAR_INTERBTN_PADDING_X) * n)
+
+#define NPAD_TOOLBAR_INTERBTN_PADDING_Y 2
+#define NPAD_TOOLBAR_2_START_Y (NPAD_DRAWING_AREA_START_Y + 6)
+#define NPAD_TOOLBAR_2_X 4
+#define NPAD_TOOLBAR_2_Y(n) (NPAD_TOOLBAR_2_START_Y + \
+ (NPAD_TOOLBAR_BTN_HEIGHT + \
+ NPAD_TOOLBAR_INTERBTN_PADDING_Y) * n)
+
+#define NPAD_DRAWING_AREA_START_X 28
+#define NPAD_DRAWING_AREA_START_Y 46
+#define NPAD_DRAWING_AREA_END_X 10
+#define NPAD_DRAWING_AREA_END_Y 24
+#define NPAD_DRAWING_AREA_WIDTH (swidth - \
+ NPAD_DRAWING_AREA_START_X - \
+ NPAD_DRAWING_AREA_END_X)
+#define NPAD_DRAWING_AREA_HEIGHT (sheight - \
+ NPAD_DRAWING_AREA_START_Y - \
+ NPAD_DRAWING_AREA_END_Y)
+
+#define NPAD_COLORBAR_WIDTH 160
+#define NPAD_COLORBAR_HEIGHT 20
+#define NPAD_COLORBAR_X (swidth - NPAD_DRAWING_AREA_END_X - NPAD_COLORBAR_WIDTH)
+#define NPAD_COLORBAR_Y NPAD_TOOLBAR_1_Y
+
+#define NPAD_COLORBAR_SEL_WIDTH (2 * NPAD_TOOLBAR_BTN_WIDTH)
+#define NPAD_COLORBAR_SEL_HEIGHT (NPAD_TOOLBAR_BTN_HEIGHT)
+#define NPAD_COLORBAR_SEL_X (NPAD_COLORBAR_X - NPAD_COLORBAR_SEL_WIDTH - 24)
+#define NPAD_COLORBAR_SEL_Y NPAD_TOOLBAR_1_Y
+
+#define NPAD_ICON_WIDTH 16
+#define NPAD_ICON_HEIGHT 16
+#define NPAD_ICON_START(x) ((x) * NPAD_ICON_WIDTH)
+
+
+#define NPAD_STATUSBAR_ICON_START_X 5
+#define NPAD_STATUSBAR_ICON_START_Y (sheight - 5 - NPAD_ICON_HEIGHT - 1)
+
+
+#define NPAD_STATUSBAR_PADDING 5
+#define NPAD_STATUSBAR_START_X (NPAD_STATUSBAR_ICON_START_X + NPAD_ICON_WIDTH + NPAD_STATUSBAR_PADDING)
+#define NPAD_STATUSBAR_START_Y (NPAD_STATUSBAR_ICON_START_Y + 3)
+#define NPAD_STATUSBAR_WIDTH (swidth - NPAD_STATUSBAR_START_X - 2)
+#define NPAD_STATUSBAR_HEIGHT 15
+
+/* Color scheme definition */
+typedef struct colScheme {
+ color_t titleBarColor;
+ color_t titleTextColor;
+
+ color_t winBgColor;
+ color_t drawingWinBorder;
+
+ color_t toolbarSeparator;
+ color_t toolbarBgUnsel;
+ color_t toolbarBgActive;
+ color_t toolbarBgSel;
+
+ color_t statusBarText;
+} NColorScheme;
+
+
+
+#endif /* NOTEPADUIDEFINES_H_ */
diff --git a/demos/3rdparty/notepad-2/readme.txt b/demos/3rdparty/notepad-2/readme.txt
new file mode 100644
index 00000000..660d1404
--- /dev/null
+++ b/demos/3rdparty/notepad-2/readme.txt
@@ -0,0 +1,17 @@
+# Notepad-2 Demo for ChibiOS/GFX
+
+This demo showcases an improved Notepad demo for the ChibiOS/GFX project.
+
+## Features:
+
+* 2 Different UI Skins available
+* Draw in 8 different colors in 8 different thickness
+* Pen, Erase and Fill Modes (Fill: Fills the entire canvas, this is not flood fill)
+
+This demo is planned to support Loading and Saving to SD Card the sketches made in the near future.
+
+## License:
+Copyright © 2013 Kumar Abhishek [abhishek.kakkar@edaboard.com]. All Rights Reserved
+This code is made available under the terms of the 3-clause BSD License.
+
+Some of the icons in the set have been taken from the fugue-icons-set by Yusuke Kamiyamane: http://p.yusukekamiyamane.com/ . These icons are covered by a Creative Commons Attribution 3.0 License. \ No newline at end of file
diff --git a/demos/3rdparty/notepad-2/toolbarIcons.gif b/demos/3rdparty/notepad-2/toolbarIcons.gif
new file mode 100644
index 00000000..fb9e7cc9
--- /dev/null
+++ b/demos/3rdparty/notepad-2/toolbarIcons.gif
Binary files differ
diff --git a/demos/3rdparty/notepad-2/toolbarIcons.h b/demos/3rdparty/notepad-2/toolbarIcons.h
new file mode 100644
index 00000000..ad2720a2
--- /dev/null
+++ b/demos/3rdparty/notepad-2/toolbarIcons.h
@@ -0,0 +1,237 @@
+/*
+ * File: toolbarIcons.h
+ *
+ * This file is a part of the Notepad demo application for ChibiOS/GFX
+ *
+ * This file has a different license from the others.
+ *
+ * Icons [0-10 and 15] in this set are taken from the fugue-icons-set
+ * by Yusuke Kamiyamane [http://p.yusukekamiyamane.com/] .These icons
+ * are covered by a Creative Commons Attribution 3.0 License:
+ * http://creativecommons.org/licenses/by/3.0/
+ * and have been used according to the terms of the license.
+ *
+ * The file is in a filmstrip format of 16x16 icons converted to GIF Format
+ * See toolbarIcons.gif for the GIF source
+ *
+ * Total 16 icons (256 x 16)
+ * 0 -> New
+ * 1 -> Open
+ * 2 -> Save
+ * 3 -> Brush
+ * 4 -> Color Palette
+ * 5 -> Pencil
+ * 6 -> Eraser
+ * 7 -> Fill Color
+ * 8 -> Cross
+ * 9 -> Plus
+ * 10 -> Minus
+ * 11 -> Cross (Round)
+ * 12 -> Info
+ * 13 -> Tick
+ * 14 -> Warning
+ * 15 -> 32-bit processor
+ *
+ */
+
+static const unsigned char toolbarIcons[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00, 0x01, 0x10, 0x00, 0xF7, 0x00, 0x00, 0x05, 0x05, 0x05,
+ 0x18, 0x18, 0x18, 0x00, 0x33, 0x00, 0x0B, 0x2A, 0x2A, 0x17, 0x38, 0x38, 0x31, 0x09, 0x09, 0x2A,
+ 0x38, 0x1D, 0x29, 0x29, 0x29, 0x29, 0x35, 0x35, 0x32, 0x2E, 0x26, 0x3A, 0x3A, 0x3A, 0x02, 0x4D,
+ 0x02, 0x00, 0x5B, 0x02, 0x1E, 0x5D, 0x1E, 0x02, 0x70, 0x03, 0x2A, 0x6A, 0x2A, 0x2C, 0x50, 0x50,
+ 0x3E, 0x65, 0x65, 0x5C, 0x01, 0x01, 0x68, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x7D, 0x3C, 0x06, 0x71,
+ 0x27, 0x27, 0x45, 0x00, 0x67, 0x51, 0x02, 0x79, 0x45, 0x36, 0x4E, 0x55, 0x47, 0x0A, 0x4F, 0x57,
+ 0x32, 0x6C, 0x52, 0x01, 0x7A, 0x64, 0x00, 0x46, 0x46, 0x46, 0x52, 0x4F, 0x47, 0x54, 0x54, 0x54,
+ 0x43, 0x51, 0x7C, 0x5E, 0x70, 0x5E, 0x45, 0x6D, 0x6D, 0x4B, 0x74, 0x74, 0x53, 0x7D, 0x7D, 0x6A,
+ 0x48, 0x48, 0x67, 0x67, 0x67, 0x78, 0x78, 0x78, 0x09, 0x2B, 0x91, 0x1B, 0x3D, 0xA3, 0x3B, 0x2B,
+ 0x97, 0x1E, 0x71, 0x8E, 0x19, 0x6C, 0xB7, 0x2A, 0x53, 0xB4, 0x38, 0x6B, 0x9E, 0x37, 0x71, 0xB5,
+ 0x3C, 0x5E, 0xC4, 0x29, 0x78, 0xC5, 0x5B, 0x02, 0x86, 0x49, 0x55, 0xBC, 0x42, 0x75, 0xA8, 0x7C,
+ 0x49, 0x95, 0x50, 0x72, 0xD6, 0x5A, 0x7C, 0xE2, 0x00, 0x91, 0x0F, 0x13, 0x9C, 0x24, 0x00, 0xA7,
+ 0x13, 0x12, 0xA6, 0x23, 0x11, 0xB9, 0x22, 0x2E, 0x83, 0x2E, 0x31, 0x86, 0x31, 0x34, 0x98, 0x34,
+ 0x28, 0xB3, 0x39, 0x34, 0xBC, 0x45, 0x0F, 0xCC, 0x1F, 0x0F, 0xC8, 0x20, 0x12, 0xC9, 0x23, 0x11,
+ 0xD5, 0x22, 0x22, 0xC3, 0x34, 0x3B, 0xC4, 0x4C, 0x48, 0x9D, 0x48, 0x54, 0xA9, 0x54, 0x67, 0xAD,
+ 0x67, 0x60, 0xB5, 0x60, 0x7A, 0xB4, 0x7A, 0x44, 0xCC, 0x55, 0x4D, 0xD5, 0x5E, 0x51, 0xDB, 0x62,
+ 0x5B, 0xE3, 0x6C, 0x6E, 0xC3, 0x6E, 0x1B, 0xA1, 0xE2, 0x3B, 0x8A, 0xD6, 0x3E, 0x9C, 0xE7, 0x38,
+ 0xC5, 0xFF, 0x55, 0x88, 0xBA, 0x70, 0x9E, 0xB9, 0x78, 0xA7, 0xB9, 0x4C, 0x91, 0xCD, 0x52, 0x8F,
+ 0xF6, 0x5F, 0xBC, 0xE8, 0x68, 0x9B, 0xCE, 0x63, 0x85, 0xEB, 0x72, 0xA4, 0xD1, 0x66, 0xA6, 0xFF,
+ 0x5D, 0xD1, 0xFF, 0x75, 0xC8, 0xEE, 0x88, 0x00, 0x00, 0x95, 0x01, 0x01, 0x9B, 0x11, 0x11, 0x9B,
+ 0x02, 0x20, 0xA7, 0x00, 0x00, 0xA7, 0x14, 0x14, 0xB3, 0x01, 0x01, 0xB8, 0x11, 0x11, 0xA7, 0x02,
+ 0x23, 0xB4, 0x02, 0x25, 0xAD, 0x26, 0x26, 0xB5, 0x28, 0x28, 0xBC, 0x34, 0x34, 0x89, 0x45, 0x01,
+ 0x8A, 0x5B, 0x00, 0x93, 0x49, 0x01, 0x9A, 0x50, 0x05, 0x98, 0x55, 0x11, 0x8E, 0x6B, 0x01, 0x89,
+ 0x75, 0x04, 0x98, 0x66, 0x00, 0x96, 0x77, 0x03, 0xB0, 0x5C, 0x06, 0xA7, 0x6F, 0x00, 0xAB, 0x65,
+ 0x13, 0xA6, 0x78, 0x02, 0xA9, 0x7A, 0x1C, 0xBC, 0x61, 0x04, 0xB7, 0x7A, 0x00, 0xB2, 0x78, 0x38,
+ 0x8A, 0x6A, 0x4B, 0xC9, 0x0C, 0x0C, 0xC9, 0x12, 0x12, 0xD8, 0x01, 0x01, 0xD4, 0x11, 0x11, 0xC6,
+ 0x27, 0x27, 0xC7, 0x39, 0x39, 0xE4, 0x13, 0x00, 0xD2, 0x5E, 0x28, 0xC0, 0x62, 0x04, 0xC9, 0x78,
+ 0x26, 0xEA, 0x40, 0x30, 0xCA, 0x42, 0x42, 0xD5, 0x4D, 0x4D, 0xD8, 0x50, 0x50, 0xD1, 0x7B, 0x5A,
+ 0xE4, 0x59, 0x56, 0xEB, 0x69, 0x5C, 0xF1, 0x6C, 0x6A, 0x80, 0x48, 0x9B, 0x89, 0x56, 0xA2, 0x90,
+ 0x5D, 0xA9, 0x96, 0x63, 0xAF, 0xA7, 0x74, 0xC0, 0xD2, 0x7D, 0x8E, 0x99, 0x85, 0x0B, 0xA6, 0x8A,
+ 0x03, 0xAB, 0x94, 0x01, 0xA4, 0x93, 0x1C, 0xB0, 0x82, 0x0B, 0xB8, 0x85, 0x17, 0xB3, 0x9A, 0x03,
+ 0xAF, 0x8E, 0x2E, 0xB7, 0xA6, 0x30, 0x91, 0x83, 0x48, 0x8B, 0x84, 0x66, 0x9A, 0x88, 0x71, 0x9B,
+ 0x9A, 0x75, 0x88, 0xA2, 0x56, 0x97, 0xB3, 0x67, 0xB1, 0x94, 0x44, 0xBA, 0x9F, 0x63, 0xBD, 0xA3,
+ 0x66, 0xA7, 0xC6, 0x79, 0xCA, 0x87, 0x00, 0xD0, 0x88, 0x3C, 0xCE, 0xB0, 0x14, 0xCF, 0xB7, 0x2E,
+ 0xCA, 0x96, 0x56, 0xC7, 0xAF, 0x4C, 0xD6, 0xAE, 0x6D, 0xE7, 0x93, 0x71, 0xEA, 0xBF, 0x5F, 0xE2,
+ 0xB1, 0x79, 0xFE, 0xCC, 0x04, 0xE6, 0xCA, 0x34, 0xDE, 0xCD, 0x56, 0xE3, 0xD2, 0x5E, 0xEB, 0xC4,
+ 0x67, 0xE9, 0xCA, 0x7F, 0xE6, 0xD5, 0x64, 0xFA, 0xF3, 0x58, 0xEB, 0xE0, 0x64, 0xF6, 0xE5, 0x79,
+ 0x83, 0x83, 0x84, 0x8A, 0x86, 0x95, 0x95, 0x95, 0x96, 0x9C, 0x9C, 0xAD, 0x80, 0xBF, 0x80, 0x96,
+ 0xAB, 0xAB, 0xB8, 0xB4, 0x8F, 0xA5, 0xA6, 0xA8, 0xA9, 0xA9, 0xB8, 0xA5, 0xB6, 0xB6, 0xBD, 0xAF,
+ 0xA0, 0xB8, 0xB8, 0xB9, 0x85, 0x80, 0xCB, 0x84, 0xAC, 0xCB, 0x81, 0xB6, 0xE3, 0xBA, 0x87, 0xD3,
+ 0xB6, 0xB9, 0xC5, 0xB0, 0xD1, 0x84, 0xB0, 0xCA, 0xB0, 0x94, 0xC7, 0xF8, 0x92, 0xE3, 0xFF, 0xAD,
+ 0xC3, 0xCD, 0xAA, 0xD3, 0xFD, 0xBF, 0xE1, 0xF1, 0xDA, 0x85, 0x96, 0xC7, 0xB6, 0x80, 0xF1, 0x89,
+ 0x91, 0xE9, 0x9B, 0xAC, 0xE6, 0xB8, 0x84, 0xEB, 0xA4, 0xB5, 0xF2, 0xBE, 0xB9, 0xC3, 0x90, 0xDC,
+ 0xCD, 0x9A, 0xE6, 0xD9, 0xA6, 0xF2, 0xFB, 0xB3, 0xC4, 0xD8, 0xC7, 0x8B, 0xDB, 0xD4, 0xB0, 0xEA,
+ 0xC4, 0x89, 0xEE, 0xC4, 0x91, 0xE9, 0xD3, 0x87, 0xEC, 0xD5, 0x91, 0xF0, 0xC8, 0x95, 0xF1, 0xD5,
+ 0x89, 0xF4, 0xDA, 0x95, 0xFD, 0xEC, 0x84, 0xF8, 0xE2, 0x9B, 0xFF, 0xFF, 0x84, 0xE5, 0xE2, 0xBC,
+ 0xFC, 0xE9, 0xA4, 0xFF, 0xF1, 0xAC, 0xC9, 0xC9, 0xC9, 0xD9, 0xD9, 0xD9, 0xD8, 0xD8, 0xEA, 0xDB,
+ 0xEA, 0xEA, 0xDB, 0xEB, 0xFF, 0xF3, 0xE8, 0xCA, 0xE7, 0xE7, 0xE7, 0xE1, 0xE1, 0xF2, 0xE6, 0xF2,
+ 0xE6, 0xE8, 0xF3, 0xF4, 0xFD, 0xF0, 0xEF, 0xF8, 0xF9, 0xF9, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
+ 0x01, 0x0A, 0x00, 0xFF, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x08,
+ 0xFE, 0x00, 0xFF, 0xFD, 0x2B, 0x41, 0xA2, 0x84, 0xC1, 0x83, 0x06, 0x05, 0x2A, 0xFC, 0xD7, 0xAA,
+ 0xA1, 0xC3, 0x87, 0x0D, 0x17, 0x4A, 0x94, 0x58, 0xA5, 0xCA, 0xC4, 0x8B, 0x0A, 0x0F, 0x8D, 0xC1,
+ 0xC8, 0xB1, 0xE3, 0x3F, 0x44, 0x88, 0x08, 0x75, 0x5C, 0xC3, 0x86, 0x24, 0x46, 0x0F, 0x20, 0x14,
+ 0x1C, 0xF0, 0xC8, 0xB2, 0xA5, 0xCB, 0x97, 0x30, 0x63, 0xB6, 0xA4, 0x77, 0xD1, 0x81, 0xCD, 0x9B,
+ 0x38, 0x73, 0x2A, 0x2C, 0xE1, 0x8F, 0x9F, 0xCF, 0x9F, 0xD6, 0x12, 0x2E, 0x6C, 0xB5, 0x6E, 0x57,
+ 0xAD, 0x75, 0xEE, 0xE2, 0x29, 0x55, 0xDA, 0x4A, 0xE1, 0x8C, 0x19, 0x08, 0xA3, 0x52, 0xA1, 0x42,
+ 0xA3, 0xA5, 0x23, 0x32, 0x63, 0x0E, 0x49, 0xF4, 0xA3, 0xA8, 0xAB, 0x57, 0x45, 0x7E, 0x5A, 0x82,
+ 0x50, 0xB3, 0x2D, 0x4D, 0x1A, 0x8C, 0x6C, 0xD8, 0x8C, 0x1B, 0xB7, 0x66, 0xCD, 0x45, 0x10, 0x02,
+ 0x03, 0x70, 0x3C, 0x43, 0xB7, 0xAE, 0x5D, 0xBA, 0x0B, 0x77, 0xE8, 0xDD, 0xCB, 0x57, 0xEF, 0xC2,
+ 0xBB, 0x80, 0xCF, 0x4C, 0xFC, 0x16, 0x09, 0x24, 0xC8, 0x48, 0xDF, 0x30, 0x62, 0xE3, 0x32, 0xA5,
+ 0xF1, 0x14, 0x2E, 0xD8, 0x2E, 0xD2, 0x9B, 0xB6, 0x04, 0x88, 0x65, 0x20, 0x4B, 0xA6, 0xD1, 0xC4,
+ 0x48, 0xEF, 0xD6, 0xAD, 0xCD, 0x0B, 0x1D, 0xC4, 0x53, 0x22, 0xA5, 0xB4, 0x69, 0xD3, 0x4A, 0xE2,
+ 0x39, 0xD8, 0xE9, 0xD3, 0x1E, 0x3F, 0x7B, 0xF6, 0xE8, 0x29, 0xF3, 0x47, 0x70, 0xA8, 0xBC, 0x78,
+ 0xEE, 0x76, 0xA5, 0x3A, 0xC6, 0x9B, 0xF7, 0x28, 0x52, 0xA4, 0xFE, 0xCD, 0x10, 0xE7, 0xAF, 0x78,
+ 0xF1, 0x67, 0x5A, 0x92, 0x6B, 0xA9, 0x26, 0x43, 0x86, 0x47, 0x32, 0x58, 0x37, 0x2A, 0xF4, 0xE3,
+ 0x27, 0x51, 0xA4, 0x48, 0xB4, 0xBA, 0xD9, 0x92, 0x05, 0xEB, 0x53, 0xD8, 0x8E, 0x20, 0x40, 0xFE,
+ 0xF8, 0x9B, 0x14, 0x49, 0xF0, 0x44, 0x92, 0xE3, 0xBC, 0x79, 0x63, 0xCB, 0x66, 0xA2, 0x07, 0x0F,
+ 0x07, 0x02, 0x00, 0xB8, 0x78, 0xC6, 0xD0, 0xA4, 0xFB, 0xF8, 0xF3, 0x1B, 0x32, 0xBF, 0xE3, 0x48,
+ 0x94, 0xFF, 0x00, 0x02, 0x08, 0x45, 0x10, 0x3B, 0x08, 0x54, 0x5F, 0x7E, 0x08, 0x4E, 0xB2, 0xDF,
+ 0x42, 0x92, 0x18, 0xE6, 0x20, 0x22, 0x93, 0x4C, 0x24, 0x86, 0x63, 0x14, 0x4E, 0x21, 0x86, 0x44,
+ 0xF4, 0x34, 0x71, 0xD9, 0x86, 0x40, 0x34, 0x01, 0x9A, 0x44, 0xE8, 0x78, 0x86, 0xCE, 0x44, 0x0E,
+ 0x28, 0xA1, 0x84, 0x34, 0x27, 0xA6, 0x88, 0x22, 0x8A, 0x4A, 0xAC, 0x26, 0x10, 0x09, 0x3D, 0xBD,
+ 0x06, 0x9B, 0x3D, 0xC6, 0xD4, 0x08, 0xC1, 0x50, 0x4B, 0xC5, 0x33, 0x8B, 0x71, 0x3C, 0x06, 0x37,
+ 0x43, 0x38, 0x3C, 0xFA, 0xB3, 0x9C, 0x18, 0x61, 0x14, 0x29, 0x86, 0x73, 0x1C, 0x41, 0x37, 0xC6,
+ 0x18, 0x8E, 0x08, 0x94, 0x87, 0x1F, 0x8B, 0xD8, 0xE2, 0xC8, 0x7D, 0x86, 0xCC, 0x02, 0x0B, 0x30,
+ 0xC0, 0x84, 0x42, 0x1D, 0x47, 0x9C, 0x68, 0xE2, 0xCF, 0x3C, 0xF4, 0x8C, 0x61, 0xDE, 0x42, 0xE8,
+ 0xA9, 0xA7, 0x1E, 0x5B, 0x6E, 0x2D, 0x04, 0x5F, 0x3E, 0x28, 0x00, 0x30, 0x9F, 0x44, 0x67, 0x90,
+ 0x77, 0xDD, 0x9C, 0x74, 0x96, 0x27, 0xD0, 0x0E, 0x50, 0x3C, 0xA1, 0xE7, 0x13, 0x48, 0x20, 0xB1,
+ 0xE7, 0x13, 0x50, 0x14, 0xF8, 0x4F, 0x9C, 0x75, 0x16, 0x3A, 0xE6, 0x24, 0x88, 0x30, 0xC2, 0x88,
+ 0x83, 0x8A, 0x42, 0xB8, 0xD0, 0x84, 0x8E, 0x15, 0x47, 0xE1, 0x85, 0x0A, 0x69, 0xC8, 0xE1, 0x86,
+ 0x1E, 0x4E, 0xD4, 0x99, 0x67, 0x9F, 0x49, 0xE4, 0x00, 0x13, 0x49, 0x90, 0xF3, 0x40, 0x3C, 0xA3,
+ 0x96, 0x4A, 0x4E, 0x12, 0x4C, 0xB8, 0xF8, 0x0F, 0x8C, 0x3D, 0xF9, 0xE3, 0x1A, 0x6C, 0xFE, 0xF4,
+ 0xF0, 0x33, 0x02, 0x8E, 0x4B, 0x91, 0xB2, 0xC5, 0x16, 0x60, 0x80, 0x71, 0xCD, 0x35, 0xFE, 0xF8,
+ 0x08, 0x64, 0xAB, 0xFC, 0x7C, 0xA1, 0x9C, 0x16, 0x56, 0xB8, 0xD0, 0x42, 0x92, 0x4A, 0x4A, 0xF7,
+ 0x8F, 0x1F, 0xB1, 0x98, 0x63, 0xCB, 0x21, 0x87, 0xB8, 0x01, 0x89, 0x2D, 0xA2, 0x88, 0xD2, 0xC9,
+ 0x2C, 0xAE, 0xE4, 0x81, 0x11, 0x28, 0x9B, 0xB4, 0x23, 0x0A, 0x3D, 0x01, 0x14, 0x30, 0x51, 0x30,
+ 0xC1, 0x8C, 0xC3, 0x0D, 0x37, 0xDE, 0xA0, 0x9B, 0x0D, 0x37, 0x69, 0x0A, 0xB4, 0x26, 0x3D, 0x28,
+ 0xE4, 0xE3, 0x26, 0x9C, 0x93, 0x38, 0xE2, 0x88, 0x3F, 0xF6, 0xDA, 0x8B, 0xAF, 0x23, 0x76, 0xFE,
+ 0x83, 0xA7, 0x13, 0x00, 0x23, 0x51, 0x1C, 0x12, 0x00, 0x3B, 0x11, 0xA8, 0x81, 0xF5, 0xE6, 0xAB,
+ 0xB0, 0xBD, 0xFD, 0x7E, 0x93, 0x68, 0x3F, 0xFD, 0x2C, 0xFA, 0x70, 0xC4, 0x88, 0x24, 0xF6, 0x0F,
+ 0x36, 0x15, 0x4A, 0x4A, 0x61, 0x64, 0xFF, 0x4C, 0x73, 0x29, 0x10, 0xC5, 0xF8, 0xB3, 0x8F, 0x65,
+ 0xD3, 0x4C, 0x14, 0x22, 0xA7, 0x23, 0x86, 0x26, 0x0D, 0x39, 0x1F, 0xBC, 0xE7, 0xF2, 0x7B, 0x1F,
+ 0x90, 0x23, 0x8D, 0xAA, 0x23, 0x00, 0x2B, 0x23, 0x6C, 0xFC, 0x90, 0xB0, 0xD0, 0x1F, 0xB8, 0x25,
+ 0x35, 0x8A, 0x33, 0x40, 0x7F, 0x61, 0xCD, 0x3D, 0xBD, 0x0A, 0x07, 0xA4, 0x6B, 0x3F, 0xBD, 0xC6,
+ 0x0F, 0x0C, 0x30, 0xAC, 0x80, 0x2C, 0x1A, 0x63, 0x50, 0xA0, 0x50, 0x1E, 0xB3, 0x68, 0x67, 0x0B,
+ 0x24, 0x68, 0x4C, 0xBB, 0x9D, 0x26, 0xB2, 0xD8, 0x62, 0x8B, 0xB6, 0x13, 0x71, 0xC2, 0x49, 0x3B,
+ 0xC0, 0xE4, 0x62, 0xC7, 0x9B, 0x0B, 0x91, 0x5B, 0xDC, 0xB9, 0xEA, 0xAE, 0xDB, 0xEE, 0xBB, 0xF3,
+ 0xA0, 0xC0, 0x0C, 0x3D, 0xF3, 0x2A, 0x44, 0x46, 0x24, 0x8D, 0x18, 0xD7, 0x48, 0xFE, 0xDE, 0xC5,
+ 0x35, 0x72, 0x95, 0x40, 0x39, 0x40, 0xD1, 0x27, 0x12, 0x42, 0x14, 0x27, 0xC4, 0xE0, 0x4E, 0xE4,
+ 0x20, 0xD0, 0xDD, 0x7B, 0x37, 0xEE, 0xB8, 0xDF, 0x64, 0x08, 0x54, 0x18, 0x23, 0xFD, 0xF8, 0x13,
+ 0x31, 0xE5, 0x96, 0x2F, 0x1A, 0x89, 0x40, 0x8C, 0x55, 0xE8, 0x39, 0x17, 0x02, 0x55, 0x76, 0xE9,
+ 0x3E, 0xFE, 0x14, 0x63, 0xD9, 0x12, 0x18, 0x7A, 0xE6, 0xA6, 0x67, 0x1F, 0x96, 0xF8, 0x80, 0x07,
+ 0xF4, 0x7C, 0x09, 0xC2, 0x3C, 0xFE, 0xD0, 0xE3, 0xC1, 0x03, 0x2D, 0x2A, 0x54, 0x33, 0xB0, 0xAE,
+ 0x2A, 0x1D, 0xC1, 0xCE, 0xEE, 0xB0, 0xC3, 0x8E, 0x3B, 0xB1, 0xF0, 0x18, 0x0D, 0x3F, 0x45, 0xFF,
+ 0x78, 0xF3, 0x8C, 0xB0, 0x5D, 0xD1, 0xCC, 0x0C, 0x18, 0x41, 0xF7, 0x46, 0x19, 0x52, 0x4F, 0xAD,
+ 0x4E, 0x37, 0xDD, 0x98, 0x83, 0xFD, 0xF6, 0xD8, 0x2F, 0xF3, 0xC5, 0x17, 0x81, 0x4C, 0x04, 0xCA,
+ 0xD8, 0xC0, 0xF4, 0xC2, 0x09, 0x28, 0x13, 0xA1, 0x80, 0x42, 0x71, 0xF9, 0xF8, 0x83, 0x6E, 0x26,
+ 0xD9, 0x6C, 0xB3, 0x86, 0x19, 0xEE, 0x1E, 0x90, 0x0F, 0x3D, 0xF3, 0x20, 0x83, 0xC2, 0x30, 0xC8,
+ 0x80, 0x7B, 0x83, 0x17, 0x8B, 0x7B, 0xC4, 0x1B, 0xDA, 0xC0, 0x3E, 0x7A, 0x18, 0xB0, 0x0C, 0x68,
+ 0x70, 0x43, 0xE4, 0xFE, 0x91, 0x83, 0x27, 0x08, 0x21, 0x08, 0x10, 0xCC, 0x47, 0x3E, 0x74, 0x40,
+ 0x41, 0x1D, 0x04, 0x41, 0x71, 0xFF, 0x20, 0x83, 0x00, 0xDF, 0xC0, 0x41, 0x37, 0xA0, 0x01, 0x0D,
+ 0x65, 0x40, 0xA0, 0x02, 0x05, 0x62, 0x18, 0xCC, 0x41, 0x2C, 0x73, 0x86, 0x11, 0x88, 0xE7, 0x34,
+ 0x46, 0x21, 0x81, 0x7C, 0x2C, 0x64, 0x23, 0xBB, 0x0C, 0x88, 0x54, 0x07, 0x00, 0x11, 0x85, 0x86,
+ 0x15, 0xE9, 0x50, 0x00, 0x08, 0x3C, 0xE0, 0x0F, 0x97, 0xF9, 0x43, 0x01, 0xFE, 0xE9, 0x60, 0x85,
+ 0xAA, 0x22, 0x10, 0x24, 0xE4, 0xE1, 0xCC, 0x04, 0x84, 0x10, 0x84, 0x40, 0xFE, 0x10, 0xBC, 0xE1,
+ 0x6D, 0xE2, 0x15, 0x50, 0xF4, 0x87, 0x31, 0x7C, 0xE2, 0x23, 0x70, 0xD4, 0x23, 0x69, 0x48, 0xE3,
+ 0x47, 0x3D, 0xC0, 0x01, 0xBD, 0x89, 0x40, 0xE7, 0x10, 0x68, 0xA8, 0x9E, 0x42, 0xE6, 0x30, 0x0B,
+ 0x73, 0xC4, 0x22, 0x0F, 0xCD, 0xCA, 0xDE, 0xF6, 0xBA, 0x40, 0x0D, 0x6A, 0x5C, 0x41, 0x22, 0x62,
+ 0x23, 0x9B, 0x2E, 0x36, 0xC1, 0x89, 0xF4, 0xC5, 0x4B, 0x82, 0xFE, 0x90, 0x60, 0x26, 0x32, 0xB1,
+ 0x0D, 0x33, 0xD0, 0xEF, 0x1F, 0x70, 0x63, 0xC6, 0x30, 0xE6, 0x11, 0x0C, 0x62, 0x24, 0xA3, 0x1E,
+ 0x21, 0xC0, 0xC1, 0x0D, 0x32, 0xE8, 0x88, 0x37, 0xB8, 0xA1, 0x0C, 0x60, 0x3A, 0xE0, 0x07, 0xD1,
+ 0xB0, 0xC0, 0x1C, 0x38, 0x21, 0x08, 0x79, 0x34, 0x20, 0x3D, 0x24, 0x98, 0x0F, 0x1E, 0xF0, 0x00,
+ 0x83, 0x64, 0x68, 0x64, 0xED, 0x22, 0xC9, 0xC9, 0x0F, 0x2E, 0x90, 0x51, 0x95, 0x43, 0x61, 0x0A,
+ 0xFF, 0xB1, 0x42, 0x7F, 0x78, 0xCE, 0x85, 0xA3, 0x2B, 0xDD, 0x86, 0x16, 0xB2, 0xA9, 0x5B, 0xAC,
+ 0x8E, 0x75, 0x0A, 0x71, 0x40, 0x12, 0x1E, 0xA0, 0x00, 0x64, 0xF8, 0x63, 0x18, 0x1E, 0x08, 0x46,
+ 0x3E, 0x90, 0xA1, 0x80, 0x07, 0x24, 0x61, 0x88, 0x3C, 0x42, 0x9E, 0x11, 0xED, 0x61, 0x82, 0xB2,
+ 0x2C, 0x51, 0x78, 0xC2, 0xF3, 0x04, 0x2C, 0x60, 0xF1, 0x0A, 0x7F, 0x64, 0xE1, 0x1A, 0xFC, 0x08,
+ 0x0E, 0x06, 0xC0, 0x01, 0x8D, 0x6E, 0x7A, 0xF3, 0x9B, 0xD0, 0xE8, 0xE2, 0x42, 0xA0, 0xE3, 0x88,
+ 0x36, 0x88, 0x71, 0x21, 0x70, 0x48, 0xE7, 0x3F, 0xE0, 0xA0, 0x8E, 0x58, 0xD0, 0x21, 0x15, 0xD8,
+ 0xBB, 0xC2, 0x15, 0x6A, 0x10, 0x3E, 0x85, 0x70, 0xAB, 0x1D, 0xBD, 0xFE, 0xE8, 0x85, 0x26, 0x36,
+ 0x31, 0x91, 0x13, 0xC4, 0x2B, 0x8F, 0x00, 0x05, 0x53, 0x36, 0xFC, 0x58, 0xBF, 0xFB, 0xCD, 0x23,
+ 0x19, 0x82, 0x04, 0x81, 0x30, 0x92, 0x91, 0x8C, 0x7C, 0x28, 0xE0, 0x06, 0x8B, 0x24, 0x43, 0x23,
+ 0x3C, 0x88, 0x06, 0x4D, 0xE6, 0x63, 0x92, 0x6A, 0xA8, 0xE4, 0x25, 0x35, 0xB9, 0x49, 0x4E, 0x7A,
+ 0x12, 0x94, 0x13, 0xC5, 0x9F, 0x01, 0x39, 0x79, 0xD1, 0x8C, 0x92, 0xB0, 0x84, 0xA9, 0xA4, 0xD8,
+ 0x2A, 0x5B, 0xF9, 0xCA, 0x7F, 0x5C, 0x86, 0x74, 0xC5, 0x80, 0x21, 0x87, 0x16, 0x72, 0x32, 0x5B,
+ 0xD6, 0xD0, 0x86, 0x02, 0x61, 0x00, 0x2A, 0xCC, 0xA1, 0x00, 0x0F, 0x28, 0xC0, 0xA1, 0xF9, 0x38,
+ 0x81, 0x4F, 0xCD, 0x81, 0x0A, 0x06, 0x28, 0x04, 0x02, 0x41, 0x2A, 0x0E, 0x3F, 0xE0, 0xE1, 0x4B,
+ 0x09, 0x2C, 0xF0, 0x0F, 0xEC, 0x58, 0xC7, 0x3A, 0xD8, 0xF1, 0x09, 0x5F, 0xE0, 0x02, 0x17, 0xFE,
+ 0xC0, 0x02, 0x35, 0xB2, 0x29, 0x1C, 0x68, 0x54, 0xE2, 0xAB, 0x60, 0x0D, 0x6B, 0x38, 0x30, 0x20,
+ 0x11, 0x0B, 0x84, 0xD2, 0x0D, 0xE7, 0xBC, 0x08, 0x1C, 0x00, 0xC1, 0x0E, 0x3A, 0xFC, 0x83, 0x0E,
+ 0xE7, 0xE8, 0xC6, 0x31, 0x5E, 0x50, 0x0A, 0xB0, 0xFD, 0x23, 0x8E, 0xF9, 0xB4, 0x83, 0x26, 0xFA,
+ 0x79, 0x02, 0x92, 0x4A, 0x70, 0x1E, 0x60, 0x52, 0xC0, 0x1F, 0xFF, 0x61, 0x3F, 0xFC, 0x31, 0x83,
+ 0x19, 0xC9, 0x40, 0x86, 0x21, 0xA3, 0xA1, 0x8F, 0x9E, 0xC6, 0x20, 0x06, 0xFF, 0xC8, 0x8A, 0x1A,
+ 0xD4, 0x60, 0x51, 0x09, 0x4E, 0x56, 0x0D, 0xD2, 0xC9, 0x01, 0x12, 0x7A, 0xE0, 0x49, 0x1E, 0x48,
+ 0xB0, 0xB3, 0x3D, 0xE8, 0x01, 0x06, 0x25, 0x3B, 0xC9, 0xD2, 0xA2, 0x61, 0xB2, 0xD2, 0x41, 0xA9,
+ 0xE5, 0x2A, 0xA7, 0x52, 0x44, 0xA8, 0x30, 0x63, 0xAE, 0xAC, 0xFE, 0x10, 0x2C, 0x41, 0x26, 0x32,
+ 0x98, 0xCE, 0x54, 0x20, 0xB5, 0xB4, 0x29, 0xA7, 0x3A, 0xF5, 0x0F, 0x06, 0x00, 0xE1, 0x01, 0x07,
+ 0x60, 0x46, 0x3E, 0x98, 0xF1, 0x53, 0x09, 0x1E, 0xE0, 0x01, 0x40, 0x30, 0xAA, 0x40, 0x90, 0x5A,
+ 0x44, 0x78, 0xC8, 0x02, 0x18, 0x08, 0x90, 0x8B, 0x40, 0xF8, 0xB0, 0x0E, 0x74, 0xA0, 0x63, 0x1D,
+ 0xA1, 0x78, 0xC7, 0x2F, 0x70, 0xC1, 0x8F, 0x29, 0x72, 0x75, 0x9B, 0x95, 0x00, 0xEC, 0x3C, 0xA2,
+ 0x01, 0x58, 0x4B, 0x60, 0xC2, 0x12, 0xE1, 0x5C, 0xC8, 0x0E, 0x0F, 0xF1, 0x86, 0xB4, 0x4E, 0x44,
+ 0x0E, 0x80, 0x50, 0x47, 0x5C, 0xAB, 0x16, 0xD7, 0x73, 0x98, 0x63, 0x0F, 0xF6, 0x1C, 0x9B, 0x2E,
+ 0x7A, 0x61, 0x07, 0x3C, 0x5C, 0xA4, 0xAF, 0x9C, 0xDC, 0x24, 0x60, 0xE9, 0x71, 0x80, 0x95, 0x28,
+ 0x24, 0x00, 0xF8, 0x43, 0x28, 0x32, 0x92, 0x61, 0xC8, 0x64, 0x34, 0xD6, 0x03, 0xFF, 0x70, 0x81,
+ 0x0B, 0x22, 0x6B, 0x08, 0xCA, 0x1A, 0xF0, 0x83, 0x9C, 0x44, 0x2D, 0xE0, 0x8E, 0x10, 0xDA, 0xD0,
+ 0x4A, 0xB0, 0xC3, 0xA1, 0x1D, 0x6D, 0x85, 0x2F, 0x4B, 0xE2, 0xCB, 0x4A, 0x67, 0x72, 0xAC, 0x55,
+ 0x54, 0x8A, 0x11, 0xB1, 0xB9, 0x7F, 0x74, 0x2E, 0x52, 0xB1, 0x75, 0x0C, 0xE8, 0xFE, 0x21, 0x3A,
+ 0x20, 0x90, 0x4E, 0x64, 0x1C, 0x42, 0x9D, 0x40, 0x6A, 0xBA, 0x5B, 0x94, 0xE5, 0x14, 0x15, 0xAB,
+ 0x48, 0x40, 0x00, 0x86, 0x4C, 0xE4, 0x00, 0x24, 0x60, 0x15, 0x45, 0x3D, 0x6A, 0x52, 0x9D, 0x0B,
+ 0x8C, 0x54, 0x6C, 0x60, 0x21, 0x7A, 0x58, 0x87, 0x39, 0xCC, 0xB1, 0x0E, 0x3E, 0xDC, 0xE2, 0x15,
+ 0xA0, 0xE0, 0x87, 0x08, 0x58, 0x00, 0x9C, 0x7F, 0x60, 0x00, 0x1A, 0x96, 0x88, 0x86, 0x0D, 0x6C,
+ 0x70, 0xD8, 0x68, 0x54, 0x02, 0x13, 0x97, 0x00, 0x07, 0xFE, 0x59, 0x05, 0xB2, 0x43, 0x7F, 0x20,
+ 0xC3, 0xBD, 0xEF, 0xB5, 0xAF, 0x39, 0xCE, 0x21, 0x5F, 0x75, 0xB4, 0xD3, 0xAE, 0x7C, 0xE8, 0x96,
+ 0x2E, 0x74, 0xD1, 0x01, 0x3B, 0x60, 0x04, 0x04, 0x01, 0xCE, 0x87, 0x78, 0x87, 0x2C, 0x11, 0x37,
+ 0xCD, 0x03, 0xB1, 0x8A, 0x4D, 0x46, 0x34, 0xEA, 0xD1, 0x53, 0x81, 0xA8, 0x40, 0x05, 0x91, 0x1D,
+ 0xC4, 0x20, 0x28, 0xAB, 0x06, 0x49, 0xAB, 0x21, 0x1F, 0x95, 0x1E, 0x44, 0x66, 0x8B, 0xC0, 0xE9,
+ 0x22, 0xF4, 0xE0, 0xC3, 0x9D, 0x2E, 0xC2, 0x68, 0x25, 0x4D, 0xEA, 0x52, 0x93, 0x5A, 0x3A, 0x0E,
+ 0xA3, 0x9C, 0x4A, 0x55, 0xBD, 0x28, 0x8B, 0x61, 0x8C, 0x42, 0x2C, 0x6C, 0x0C, 0xC7, 0x3C, 0x66,
+ 0x99, 0x90, 0xC9, 0x72, 0x43, 0x25, 0xFB, 0x47, 0x6E, 0x75, 0xBB, 0x5B, 0x9A, 0xF8, 0xD6, 0x07,
+ 0xAA, 0x68, 0xC0, 0x2C, 0x84, 0x4D, 0x6C, 0x55, 0xF8, 0x20, 0xB9, 0x4A, 0xE6, 0x11, 0x93, 0x53,
+ 0x51, 0x8E, 0x1B, 0x29, 0xE4, 0x0E, 0xE8, 0xE0, 0x05, 0x2F, 0xD0, 0x71, 0x87, 0x57, 0x6C, 0x02,
+ 0x0F, 0xFC, 0x30, 0x45, 0x53, 0x04, 0xF2, 0xE5, 0x4A, 0x30, 0xC3, 0x12, 0x97, 0x60, 0x68, 0x32,
+ 0x2E, 0x81, 0x09, 0x4C, 0x40, 0x63, 0xCD, 0x7B, 0xD8, 0x83, 0x9B, 0xA5, 0xEB, 0x11, 0x39, 0x34,
+ 0x4B, 0xBE, 0xDD, 0x98, 0x05, 0x20, 0xE6, 0xB0, 0x10, 0x3C, 0xD4, 0x01, 0x1F, 0xB2, 0xE0, 0x73,
+ 0x07, 0x38, 0xE2, 0xD3, 0xDA, 0x0D, 0x17, 0xB0, 0xF2, 0xB9, 0x88, 0x9B, 0xA2, 0x91, 0xE8, 0x45,
+ 0x1F, 0x40, 0x01, 0x0A, 0x49, 0x41, 0x0A, 0xFE, 0x41, 0x81, 0x41, 0x14, 0xA2, 0x10, 0x6A, 0x78,
+ 0xF8, 0xC3, 0x23, 0x5E, 0x08, 0x41, 0x54, 0xCF, 0x01, 0x45, 0x30, 0x82, 0xC6, 0x8D, 0x10, 0xDA,
+ 0x8D, 0x1B, 0x81, 0x08, 0x2E, 0x6A, 0xB8, 0xC4, 0xFE, 0x47, 0x2E, 0x71, 0x8B, 0x2B, 0xA4, 0x41,
+ 0x8D, 0x2A, 0xE1, 0xA2, 0x22, 0xA4, 0x10, 0x48, 0x35, 0x26, 0xD6, 0x94, 0x12, 0x88, 0xA5, 0x3E,
+ 0xD6, 0xA1, 0xCD, 0xF0, 0x98, 0xD7, 0x3E, 0x5E, 0xC0, 0x0F, 0x7E, 0x70, 0x0A, 0x9E, 0xFB, 0xBC,
+ 0xE7, 0x3D, 0xFF, 0xC1, 0x02, 0x92, 0x5D, 0x1C, 0x7C, 0x37, 0xB9, 0x1C, 0xFE, 0x70, 0xB6, 0x40,
+ 0xE2, 0x10, 0x8A, 0x32, 0x9A, 0x23, 0x14, 0x49, 0x7B, 0xB2, 0x42, 0x2E, 0x70, 0x01, 0x4A, 0x8C,
+ 0x3B, 0xDC, 0x0C, 0x25, 0xB7, 0xB9, 0x2F, 0x20, 0x90, 0x3D, 0xC4, 0x02, 0x10, 0xEC, 0x66, 0x49,
+ 0x3A, 0xC7, 0x0E, 0x87, 0x89, 0xD4, 0x61, 0x15, 0xF8, 0x28, 0x07, 0x07, 0xF6, 0xDD, 0x91, 0xF8,
+ 0x08, 0x1A, 0xB0, 0x75, 0x13, 0x38, 0x00, 0x18, 0xBA, 0x68, 0x42, 0x27, 0x5C, 0x20, 0x13, 0x20,
+ 0x83, 0xC3, 0x49, 0xFE, 0x70, 0x41, 0x90, 0x61, 0x02, 0x02, 0x71, 0x40, 0x0E, 0x32, 0xEE, 0xF1,
+ 0x8D, 0x0F, 0x21, 0x07, 0x2E, 0xCA, 0xFB, 0xDE, 0xF9, 0xEE, 0x77, 0xC0, 0x2B, 0x04, 0x51, 0x0F,
+ 0x02, 0x09, 0xCB, 0x1F, 0xE5, 0xB9, 0xC6, 0xC4, 0xBC, 0x52, 0x34, 0xCF, 0x94, 0x40, 0x7A, 0xCC,
+ 0x79, 0x4E, 0xFD, 0x43, 0x00, 0xB3, 0xF8, 0x01, 0xCD, 0x81, 0xF0, 0x83, 0x59, 0x08, 0x40, 0x21,
+ 0x04, 0xE0, 0x91, 0x36, 0xF0, 0x91, 0x0A, 0x78, 0x14, 0x87, 0x00, 0x12, 0xB9, 0xC3, 0x1D, 0xFA,
+ 0x20, 0x0B, 0x0E, 0x78, 0xE2, 0xF6, 0xB7, 0x97, 0x08, 0xD5, 0xDD, 0xC4, 0x7B, 0x00, 0x50, 0xFD,
+ 0xF7, 0xFF, 0xC0, 0x81, 0x30, 0x52, 0x51, 0x01, 0x99, 0x74, 0x84, 0x03, 0xAC, 0xE7, 0x00, 0x07,
+ 0x5A, 0x22, 0x9F, 0xDE, 0x7B, 0x64, 0xE0, 0xF5, 0x88, 0xFB, 0x44, 0x24, 0x40, 0xFD, 0xEA, 0x5B,
+ 0x9F, 0xFA, 0x0B, 0x61, 0x80, 0xF6, 0xB7, 0x56, 0xCF, 0x7D, 0xED, 0x2F, 0xE4, 0xFA, 0xE0, 0x97,
+ 0xC0, 0x60, 0x0A, 0x63, 0x18, 0xC4, 0x28, 0xE6, 0xC5, 0x8F, 0xE1, 0x18, 0x86, 0x28, 0xB3, 0xA1,
+ 0xCC, 0x7C, 0xE8, 0xE6, 0x9D, 0x1F, 0x91, 0x00, 0xE6, 0x4F, 0xFF, 0xFA, 0xDB, 0x5F, 0x21, 0x03,
+ 0xC8, 0x7F, 0xFE, 0x01, 0xA0, 0x01, 0x03, 0xE8, 0x7F, 0x00, 0x17, 0x11, 0x07, 0x71, 0xB0, 0x6D,
+ 0xC6, 0xA7, 0x10, 0x5B, 0xE0, 0x02, 0x19, 0x50, 0x80, 0x1C, 0x01, 0x00, 0xCA, 0xB7, 0x7C, 0x0A,
+ 0xD8, 0x11, 0xCE, 0xF7, 0x80, 0x12, 0x38, 0x81, 0x14, 0x58, 0x81, 0x2F, 0x11, 0x10, 0x00, 0x3B,
+};
diff --git a/docs/src/main.dox b/docs/src/main.dox
index 8810abd0..89c8006a 100644
--- a/docs/src/main.dox
+++ b/docs/src/main.dox
@@ -26,12 +26,10 @@
* ChibiOS/GFX is an official add-on library for ChibiOS/RT to
* interface all different types of LCDs and touchscreens.
*
- * <h2>Features</h2>
- * - Modular design to reduce memory footprint
- * - HAL abstractions allows it to easily write new drivers
- * - Completely written in C, usable in C++ without any modifications
- * - Supports hardware accelerated drawing by LCDs
- * - Very flexible interfaces for calibration storage and more
- * - We are having our own homepage: http://chibios-gfx.com
+ * <h2>Documentation</h2>
+ * - http://chibios-gfx.com
+ *
+ * <h2>License</h2>
+ * - http://chibios-gfx.com/license.html
*/
diff --git a/drivers/gdisp/HX8347D/HX8347D.h b/drivers/gdisp/HX8347D/HX8347D.h
new file mode 100644
index 00000000..c0cb18fb
--- /dev/null
+++ b/drivers/gdisp/HX8347D/HX8347D.h
@@ -0,0 +1,143 @@
+/*
+ * This file is subject to the terms of the GFX License, v1.0. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file drivers/gdisp/HX8347D/HX8347D.h
+ * @brief GDISP Graphic Driver support header for the HX8347D display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _HX8347D_H
+#define _HX8347D_H
+
+/* HX8347D registers */
+
+/* page 0 registers */
+#define HX8347D_REG_HID 0x00 /* Himax ID */
+#define HX8347D_REG_DMODE 0x01 /* Display mode control */
+#define HX8347D_REG_SCH 0x02 /* Column address start high */
+#define HX8347D_REG_SCL 0x03 /* Column address start low */
+#define HX8347D_REG_ECH 0x04 /* Column address end high */
+#define HX8347D_REG_ECL 0x05 /* Column address end low */
+#define HX8347D_REG_SPH 0x06 /* Row address start high */
+#define HX8347D_REG_SPL 0x07 /* Row address start low */
+#define HX8347D_REG_EPH 0x08 /* Row address end high */
+#define HX8347D_REG_EPL 0x09 /* Row address end low */
+#define HX8347D_REG_PSLH 0x0a /* Partial area start row high */
+#define HX8347D_REG_PSLL 0x0b /* Partial area start row low */
+#define HX8347D_REG_PELH 0x0c /* Partial area end row high */
+#define HX8347D_REG_PELL 0x0d /* Partial area end row low */
+#define HX8347D_REG_TFAH 0x0e /* Vertical srcoll top fixed area high */
+#define HX8347D_REG_TFAL 0x0f /* Vertical scroll top fixed area low */
+
+#define HX8347D_REG_VSAH 0x10 /* Vertical scroll height area high */
+#define HX8347D_REG_VSAL 0x11 /* Vertical scroll height area low */
+#define HX8347D_REG_BFAH 0x12 /* Vertical scroll button area high */
+#define HX8347D_REG_BFAL 0x13 /* Vertical scroll button area low */
+#define HX8347D_REG_VSPH 0x14 /* Vertical scroll start address high */
+#define HX8347D_REG_VSPL 0x15 /* Vertical scroll start address low */
+#define HX8347D_REG_MAC 0x16 /* Memory access control */
+#define HX8347D_REG_COLMOD 0x17 /* COLMOD */
+#define HX8347D_REG_OSCCH 0x18 /* OSC control 2 */
+#define HX8347D_REG_OSCCL 0x19 /* OSC control 1 */
+#define HX8347D_REG_PWC1 0x1a /* Power control 1 */
+#define HX8347D_REG_PWC2 0x1b /* Power control 2 */
+#define HX8347D_REG_PWC3 0x1c /* Power control 3 */
+#define HX8347D_REG_PWC4 0x1d /* Power control 4 */
+#define HX8347D_REG_PWC5 0x1e /* Power control 5 */
+#define HX8347D_REG_PWC6 0x1f /* Power control 6 */
+
+#define HX8347D_REG_SRAMWC 0x22 /* SRAM write control */
+#define HX8347D_REG_VMF 0x23 /* VCOM control 1 */
+#define HX8347D_REG_VMH 0x24 /* VCOM control 2 */
+#define HX8347D_REG_VML 0x25 /* VCOM control 3 */
+#define HX8347D_REG_DC1 0x26 /* Display control 1 */
+#define HX8347D_REG_DC2 0x27 /* Display control 2 */
+#define HX8347D_REG_DC3 0x28 /* Display control 3 */
+#define HX8347D_REG_FRC1 0x29 /* Frame rate control 1 */
+#define HX8347D_REG_FRC2 0x2a /* Frame rate control 2 */
+#define HX8347D_REG_FRC3 0x2b /* Frame rate control 3 */
+#define HX8347D_REG_FRC4 0x2c /* Frame rate control 4 */
+#define HX8347D_REG_GDON 0x2d /* Cycle control 1 */
+#define HX8347D_REG_GDOF 0x2e /* Cycle control 2 */
+#define HX8347D_REG_DINV 0x2f /* Display inversion */
+
+#define HX8347D_REG_RGB1 0x31 /* RGB interface control 1 */
+#define HX8347D_REG_RGB2 0x32 /* RGB interface control 2 */
+#define HX8347D_REG_RGB3 0x33 /* RGB interface control 3 */
+#define HX8347D_REG_RGB4 0x34 /* RGB interface control 4 */
+#define HX8347D_REG_PCH 0x36 /* Panel characteristic */
+#define HX8347D_REG_OTP1 0x38 /* OTP control 1 */
+#define HX8347D_REG_OTP2 0x39 /* OTP control 2 */
+#define HX8347D_REG_OTP3 0x3a /* OTP control 3 */
+#define HX8347D_REG_CABC1 0x3c /* CABC control 1 */
+#define HX8347D_REG_CABC2 0x3d /* CABC control 2 */
+#define HX8347D_REG_CABC3 0x3e /* CABC control 3 */
+#define HX8347D_REG_CABC4 0x3f /* CABC control 4 */
+
+#define HX8347D_REG_VRP0 0x40 /* Gamma control 1 */
+#define HX8347D_REG_VRP1 0x41 /* Gamma control 2 */
+#define HX8347D_REG_VRP2 0x42 /* Gamma control 3 */
+#define HX8347D_REG_VRP3 0x43 /* Gamma control 4 */
+#define HX8347D_REG_VRP4 0x44 /* Gamma control 5 */
+#define HX8347D_REG_VRP5 0x45 /* Gamma control 6 */
+#define HX8347D_REG_PRP0 0x46 /* Gamma control 7 */
+#define HX8347D_REG_PRP1 0x47 /* Gamma control 8 */
+#define HX8347D_REG_PKP0 0x48 /* Gamma control 9 */
+#define HX8347D_REG_PKP1 0x49 /* Gamma control 10 */
+#define HX8347D_REG_PKP2 0x4a /* Gamma control 11 */
+#define HX8347D_REG_PKP3 0x4b /* Gamma control 12 */
+#define HX8347D_REG_PKP4 0x4c /* Gamma control 13 */
+
+#define HX8347D_REG_VRN0 0x50 /* Gamma control 14 */
+#define HX8347D_REG_VRN1 0x51 /* Gamma control 15 */
+#define HX8347D_REG_VRN2 0x52 /* Gamma control 16 */
+#define HX8347D_REG_VRN3 0x53 /* Gamma control 17 */
+#define HX8347D_REG_VRN4 0x54 /* Gamma control 18 */
+#define HX8347D_REG_VRN5 0x55 /* Gamma control 19 */
+#define HX8347D_REG_PRN0 0x56 /* Gamma control 20 */
+#define HX8347D_REG_PRN1 0x57 /* Gamma control 21 */
+#define HX8347D_REG_PKN0 0x58 /* Gamma control 22 */
+#define HX8347D_REG_PKN1 0x59 /* Gamma control 23 */
+#define HX8347D_REG_PKN2 0x5a /* Gamma control 24 */
+#define HX8347D_REG_PKN3 0x5b /* Gamma control 25 */
+#define HX8347D_REG_PKN4 0x5c /* Gamma control 26 */
+#define HX8347D_REG_CGM 0x5d /* Gamma control 27 */
+
+#define HX8347D_REG_TEC 0x60 /* TE control */
+
+#define HX8347D_REG_PS1 0xe4 /* Power saving 1 */
+#define HX8347D_REG_PS2 0xe5 /* Power saving 2 */
+#define HX8347D_REG_PS3 0xe6 /* Power saving 3 */
+#define HX8347D_REG_PS4 0xe7 /* Power saving 4 */
+#define HX8347D_REG_OPONN 0xe8 /* Source OP control normal */
+#define HX8347D_REG_OPONI 0xe9 /* Source OP control idle */
+#define HX8347D_REG_STBAH 0xea /* Power control internal use 1 */
+#define HX8347D_REG_STBAL 0xeb /* Power control internal use 2 */
+#define HX8347D_REG_PTBAH 0xec /* Source control internal use 1 */
+#define HX8347D_REG_PTBAL 0xed /* Source control internal use 2 */
+
+/* page 1 registers */
+#define HX8347D_REG_CABC5 0xc3 /* CABC control 5 */
+#define HX8347D_REG_CABC6 0xc5 /* CABC control 6 */
+#define HX8347D_REG_CABC7 0xc7 /* CABC control 7 */
+#define HX8347D_REG_DBG0 0xcb /* Gain select register 0 */
+#define HX8347D_REG_DBG1 0xcc /* Gain select register 1 */
+#define HX8347D_REG_DBG2 0xcd /* Gain select register 2 */
+#define HX8347D_REG_DBG3 0xce /* Gain select register 3 */
+#define HX8347D_REG_DBG4 0xcf /* Gain select register 4 */
+#define HX8347D_REG_DBG5 0xd0 /* Gain select register 5 */
+#define HX8347D_REG_DBG6 0xd1 /* Gain select register 6 */
+#define HX8347D_REG_DBG7 0xd2 /* Gain select register 7 */
+#define HX8347D_REG_DBG8 0xd3 /* Gain select register 8 */
+
+#define HX8347D_REG_PGSEL 0xff /* Page select */
+
+#endif /* _HX8347D_H */
+/** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
new file mode 100644
index 00000000..8443ca3d
--- /dev/null
+++ b/drivers/gdisp/HX8347D/gdisp_lld.c
@@ -0,0 +1,495 @@
+/*
+ * This file is subject to the terms of the GFX License, v1.0. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file drivers/gdisp/HX8347D/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for the HX8347D display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#include "HX8347D.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 240
+#endif
+
+#define GDISP_INITIAL_CONTRAST 50
+#define GDISP_INITIAL_BACKLIGHT 50
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#elif defined(BOARD_ST_STM32F4_DISCOVERY)
+ #include "gdisp_lld_board_st_stm32f4_discovery.h"
+#else
+ /* Include the user supplied board definitions */
+ #include "gdisp_lld_board.h"
+#endif
+
+// Some common routines and macros
+#define write_reg(reg, data) { write_index(reg); write_data(data); }
+#define write_ram(color1, color2) { write_index(0x22); write_ram8(color1,color2); }
+#define stream_start() { write_index(0x22); spiStart(&SPID1, &spi1cfg2); }
+#define stream_stop() {while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));palSetPad(GPIOA, 4);spiStart(&SPID1, &spi1cfg1); }
+#define delay(us) chThdSleepMicroseconds(us)
+#define delayms(ms) chThdSleepMilliseconds(ms)
+
+static inline void set_cursor(coord_t x, coord_t y) {
+ write_reg(HX8347D_REG_SCL, (uint8_t) x);
+ write_reg(HX8347D_REG_SCH, (uint8_t) (x >> 8));
+ write_reg(HX8347D_REG_SPL, (uint8_t) y);
+ write_reg(HX8347D_REG_SPH, (uint8_t) (y >> 8));
+}
+
+static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ write_reg(HX8347D_REG_SCL, (uint8_t) x);
+ write_reg(HX8347D_REG_SCH, (uint8_t) (x >> 8));
+ write_reg(HX8347D_REG_ECL, (uint8_t) (x + cx -1));
+ write_reg(HX8347D_REG_ECH, (uint8_t) ((x + cx -1) >> 8));
+ write_reg(HX8347D_REG_SPL, (uint8_t) y);
+ write_reg(HX8347D_REG_SPH, (uint8_t) (y >> 8));
+ write_reg(HX8347D_REG_EPL, (uint8_t) (y + cy -1));
+ write_reg(HX8347D_REG_EPH, (uint8_t) ((y + cy -1) >> 8));
+}
+
+static inline void reset_viewport(void) {
+ set_viewport(0, 0, GDISP.Width, GDISP.Height);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+
+/* ---- Required Routines ---- */
+/*
+ The following 2 routines are required.
+ All other routines are optional.
+*/
+
+/**
+ * @brief Low level GDISP driver initialization.
+ *
+ * @notapi
+ */
+bool_t gdisp_lld_init(void) {
+ /* Initialise your display */
+ init_board();
+
+ // Hardware reset
+ setpin_reset(TRUE);
+ delayms(1);
+ setpin_reset(FALSE);
+ delayms(5);
+
+ // Get the bus for the following initialisation commands
+ acquire_bus();
+
+ /* Start Initial Sequence ----------------------------------------------------*/
+ write_reg(HX8347D_REG_STBAH, 0x00); /* Reset Power Control 1 */
+ write_reg(HX8347D_REG_STBAL, 0x20); /* Power Control 2 */
+ write_reg(HX8347D_REG_PTBAH, 0x0C); /* Power Control 1 */
+ write_reg(HX8347D_REG_PTBAL, 0xC4); /* Power Control 2 */
+ write_reg(HX8347D_REG_OPONN, 0x40); /* Source OPON_N */
+ write_reg(HX8347D_REG_OPONI, 0x38); /* Source OPON_I */
+ write_reg(HX8347D_REG_DC2, 0xA3); /* Display Control 2 */
+
+ /* Power On sequence ---------------------------------------------------------*/
+ write_reg(HX8347D_REG_PWC2, 0x1B); /* Power Control 2 */
+ write_reg(HX8347D_REG_PWC1, 0x01); /* Power Control 1 */
+ write_reg(HX8347D_REG_VMH, 0x2F); /* Vcom Control 2 */
+ write_reg(HX8347D_REG_VML, 0x57); /* Vcom Control 3 */
+ write_reg(HX8347D_REG_VMF, 0x8D); /* Vcom Control 1 */
+
+ /* Gamma settings -----------------------------------------------------------*/
+ write_reg(HX8347D_REG_VRP0,0x01); // default setup
+ write_reg(HX8347D_REG_VRP1,0x0e); //
+ write_reg(HX8347D_REG_VRP2,0x11); //
+ write_reg(HX8347D_REG_VRP3,0x1a); //
+ write_reg(HX8347D_REG_VRP4,0x18); //
+ write_reg(HX8347D_REG_VRP5,0x24); //
+ write_reg(HX8347D_REG_PRP0,0x15); //
+ write_reg(HX8347D_REG_PRP1,0x65); //
+ write_reg(HX8347D_REG_PKP0,0x0b); //
+ write_reg(HX8347D_REG_PKP1,0x18); //
+ write_reg(HX8347D_REG_PKP2,0x19); //
+ write_reg(HX8347D_REG_PKP3,0x1a); //
+ write_reg(HX8347D_REG_PKP4,0x18); //
+ write_reg(HX8347D_REG_VRN0,0x1b); //
+ write_reg(HX8347D_REG_VRN1,0x27); //
+ write_reg(HX8347D_REG_VRN2,0x25); //
+ write_reg(HX8347D_REG_VRN3,0x2e); //
+ write_reg(HX8347D_REG_VRN4,0x31); //
+ write_reg(HX8347D_REG_VRN5,0x3e); //
+ write_reg(HX8347D_REG_PRN0,0x1a); //
+ write_reg(HX8347D_REG_PRN1,0x6a); //
+ write_reg(HX8347D_REG_PKN0,0x07); //
+ write_reg(HX8347D_REG_PKN1,0x05); //
+ write_reg(HX8347D_REG_PKN2,0x06); //
+ write_reg(HX8347D_REG_PKN3,0x0b); //
+ write_reg(HX8347D_REG_PKN4,0x14); //
+ write_reg(HX8347D_REG_CGM,0xcc); //
+
+ /* Power + Osc ---------------------------------------------------------------*/
+ write_reg(HX8347D_REG_OSCCH, 0x36); /* OSC Control 1 */
+ write_reg(HX8347D_REG_OSCCL, 0x01); /* OSC Control 2 */
+ write_reg(HX8347D_REG_DMODE, 0x00); /* Display Mode Control */
+ write_reg(HX8347D_REG_PWC6, 0x88); /* Power Control 6 */
+ delayms(5); /* Delay 5 ms */
+ write_reg(HX8347D_REG_PWC6, 0x80); /* Power Control 6 */
+ delayms(5); /* Delay 5 ms */
+ write_reg(HX8347D_REG_PWC6, 0x90); /* Power Control 6 */
+ delayms(5); /* Delay 5 ms */
+ write_reg(HX8347D_REG_PWC6, 0xD0); /* Power Control 6 */
+ delayms(5); /* Delay 5 ms */
+ write_reg(HX8347D_REG_COLMOD, 0x05); /* Colmod 16Bit/Pixel */
+ write_reg(HX8347D_REG_PCH, 0x00); /* Panel Characteristic */
+ write_reg(HX8347D_REG_DC3, 0x38); /* Display Control 3 */
+ delayms(40);
+ write_reg(HX8347D_REG_DC3, 0x3C); /* Display Control 3 */
+ write_reg(HX8347D_REG_MAC, 0x08); /* Memory access control */
+
+ write_reg(HX8347D_REG_SCL, 0x00);
+ write_reg(HX8347D_REG_SCH, 0x00);
+ write_reg(HX8347D_REG_ECL, 0xef);
+ write_reg(HX8347D_REG_ECH, 0x00);
+ write_reg(HX8347D_REG_SPL, 0x00);
+ write_reg(HX8347D_REG_SPH, 0x00);
+ write_reg(HX8347D_REG_EPL, 0x3f);
+ write_reg(HX8347D_REG_EPH, 0x01);
+
+ // Release the bus
+ release_bus();
+
+ /* Turn on the backlight */
+ set_backlight(GDISP_INITIAL_BACKLIGHT);
+
+ /* Initialise the GDISP structure */
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
+ GDISP.Contrast = GDISP_INITIAL_CONTRAST;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+/**
+ * @brief Draws a pixel on the display.
+ *
+ * @param[in] x X location of the pixel
+ * @param[in] y Y location of the pixel
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+
+ acquire_bus();
+ set_cursor(x, y);
+ write_ram((color >> 8) & 0xFF, color & 0xFF);
+ release_bus();
+}
+
+/* ---- Optional Routines ---- */
+/*
+ All the below routines are optional.
+ Defining them will increase speed but everything
+ will work if they are not defined.
+ If you are not using a routine - turn it off using
+ the appropriate GDISP_HARDWARE_XXXX macro.
+ Don't bother coding for obvious similar routines if
+ there is no performance penalty as the emulation software
+ makes a good job of using similar routines.
+ eg. If gfillarea() is defined there is little
+ point in defining clear() unless the
+ performance bonus is significant.
+ For good performance it is suggested to implement
+ fillarea() and blitarea().
+*/
+
+#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
+ /**
+ * @brief Clear the display.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] color The color of the pixel
+ *
+ * @notapi
+ */
+ void gdisp_lld_clear(color_t color) {
+ unsigned i;
+
+ acquire_bus();
+ reset_viewport();
+ stream_start();
+ for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
+ write_ram16(color);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a color.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] color The color of the fill
+ *
+ * @notapi
+ */
+ void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ unsigned i, area;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ area = cx*cy;
+
+ acquire_bus();
+ set_viewport(x, y, cx, cy);
+ stream_start();
+ for(i = 0; i < area; i++)
+ write_ram16(color);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+ /**
+ * @brief Fill an area with a bitmap.
+ * @note Optional - The high level driver can emulate using software.
+ *
+ * @param[in] x, y The start filled area
+ * @param[in] cx, cy The width and height to be filled
+ * @param[in] srcx, srcy The bitmap position to start the fill from
+ * @param[in] srccx The width of a line in the bitmap.
+ * @param[in] buffer The pixels to use to fill the area.
+ *
+ * @notapi
+ */
+ void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
+ coord_t endx, endy;
+ unsigned lg;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (srcx+cx > srccx) cx = srccx - srcx;
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ acquire_bus();
+ set_viewport(x, y, cx, cy);
+ stream_start();
+
+ endx = srcx + cx;
+ endy = y + cy;
+ lg = srccx - cx;
+ buffer += srcx + srcy * srccx;
+ for(; y < endy; y++, buffer += lg)
+ for(x=srcx; x < endx; x++)
+ write_data(*buffer++);
+ stream_stop();
+ release_bus();
+ }
+#endif
+
+#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
+ /**
+ * @brief Get the color of a particular pixel.
+ * @note Optional.
+ * @note If x,y is off the screen, the result is undefined.
+ *
+ * @param[in] x, y The pixel to be read
+ *
+ * @notapi
+ */
+ color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
+ color_t color;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+ #endif
+}
+#endif
+
+#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
+ /**
+ * @brief Scroll vertically a section of the screen.
+ * @note Optional.
+ * @note If x,y + cx,cy is off the screen, the result is undefined.
+ * @note If lines is >= cy, it is equivelent to a area fill with bgcolor.
+ *
+ * @param[in] x, y The start of the area to be scrolled
+ * @param[in] cx, cy The size of the area to be scrolled
+ * @param[in] lines The number of lines to scroll (Can be positive or negative)
+ * @param[in] bgcolor The color to fill the newly exposed area.
+ *
+ * @notapi
+ */
+ void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
+ static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
+ coord_t row0, row1;
+ unsigned i, abslines, j;
+ static int gap;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ }
+#endif
+
+#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
+ /**
+ * @brief Driver Control
+ * @details Unsupported control codes are ignored.
+ * @note The value parameter should always be typecast to (void *).
+ * @note There are some predefined and some specific to the low level driver.
+ * @note GDISP_CONTROL_POWER - Takes a gdisp_powermode_t
+ * GDISP_CONTROL_ORIENTATION - Takes a gdisp_orientation_t
+ * GDISP_CONTROL_BACKLIGHT - Takes an int from 0 to 100. For a driver
+ * that only supports off/on anything other
+ * than zero is on.
+ *
+ * @param[in] what What to do.
+ * @param[in] value The value to use (always cast to a void *).
+ *
+ * @notapi
+ */
+ void gdisp_lld_control(unsigned what, void *value) {
+ switch(what) {
+ case GDISP_CONTROL_ORIENTATION:
+ if (GDISP.Orientation == (gdisp_orientation_t)value)
+ return;
+ switch((gdisp_orientation_t)value) {
+ case GDISP_ROTATE_0:
+ acquire_bus();
+ write_reg(HX8347D_REG_MAC, 0x08); /* Memory access control */
+ write_reg(HX8347D_REG_ECL, 0xef);
+ write_reg(HX8347D_REG_ECH, 0x00);
+ write_reg(HX8347D_REG_EPL, 0x3f);
+ write_reg(HX8347D_REG_EPH, 0x01);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+
+ case GDISP_ROTATE_90:
+ acquire_bus();
+ write_reg(HX8347D_REG_MAC, 0x68); /* Memory access control */
+ write_reg(HX8347D_REG_ECL, 0x3f);
+ write_reg(HX8347D_REG_ECH, 0x01);
+ write_reg(HX8347D_REG_EPL, 0xef);
+ write_reg(HX8347D_REG_EPH, 0x00);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+
+ case GDISP_ROTATE_180:
+ acquire_bus();
+ write_reg(HX8347D_REG_MAC, 0xc8); /* Memory access control */
+ write_reg(HX8347D_REG_ECL, 0xef);
+ write_reg(HX8347D_REG_ECH, 0x00);
+ write_reg(HX8347D_REG_EPL, 0x3f);
+ write_reg(HX8347D_REG_EPH, 0x01);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ break;
+
+ case GDISP_ROTATE_270:
+ acquire_bus();
+ write_reg(HX8347D_REG_MAC, 0xa8); /* Memory access control */
+ write_reg(HX8347D_REG_ECL, 0x3f);
+ write_reg(HX8347D_REG_ECH, 0x01);
+ write_reg(HX8347D_REG_EPL, 0xef);
+ write_reg(HX8347D_REG_EPH, 0x00);
+ release_bus();
+ GDISP.Height = GDISP_SCREEN_WIDTH;
+ GDISP.Width = GDISP_SCREEN_HEIGHT;
+ break;
+
+ default:
+ return;
+ }
+
+ #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ GDISP.Orientation = (gdisp_orientation_t)value;
+ return;
+
+ case GDISP_CONTROL_BACKLIGHT:
+ if ((unsigned)value > 100)
+ value = (void *)100;
+ set_backlight((unsigned)value);
+ GDISP.Backlight = (unsigned)value;
+ return;
+
+ default:
+ return;
+ }
+ }
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.mk b/drivers/gdisp/HX8347D/gdisp_lld.mk
new file mode 100644
index 00000000..fed905e1
--- /dev/null
+++ b/drivers/gdisp/HX8347D/gdisp_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gdisp/HX8347D/gdisp_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gdisp/HX8347D
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h b/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
new file mode 100644
index 00000000..da078541
--- /dev/null
+++ b/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
@@ -0,0 +1,202 @@
+/*
+ * This file is subject to the terms of the GFX License, v1.0. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file drivers/gdisp/HX8347D/gdisp_lld_board_embest_dmstf4bb.h
+ * @brief GDISP Graphic Driver subsystem board SPI interface for the HX8347D display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#define SET_RST palSetPad(GPIOB, 8);
+#define CLR_RST palClearPad(GPIOB, 8);
+
+/* PWM configuration structure. We use timer 4 channel 2 (orange LED on board). */
+static const PWMConfig pwmcfg = {
+ 1000000, /* 1 MHz PWM clock frequency. */
+ 100, /* PWM period is 100 cycles. */
+ NULL,
+ {
+ {PWM_OUTPUT_ACTIVE_HIGH, NULL},
+ {PWM_OUTPUT_ACTIVE_HIGH, NULL},
+ {PWM_OUTPUT_ACTIVE_HIGH, NULL},
+ {PWM_OUTPUT_ACTIVE_HIGH, NULL}
+ },
+ 0
+};
+
+/*
+ * SPI1 configuration structure.
+ * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
+ * The slave select line is the pin 4 on the port GPIOA.
+ */
+static const SPIConfig spi1cfg1 = {
+ NULL,
+ /* HW dependent part.*/
+ GPIOA,
+ 4,
+ 0 //SPI_CR1_BR_0
+};
+
+/*
+ * SPI1 configuration structure.
+ * Speed 42MHz, CPHA=0, CPOL=0, 16bits frames, MSb transmitted first.
+ * The slave select line is the pin 4 on the port GPIOA.
+ */
+static const SPIConfig spi1cfg2 = {
+ NULL,
+ /* HW dependent part.*/
+ GPIOA,
+ 4,
+ SPI_CR1_DFF //SPI_CR1_BR_0
+};
+
+/**
+ * @brief Initialise the board for the display.
+ * @notes This board definition uses GPIO and assumes exclusive access to these GPIO pins
+ *
+ * @notapi
+ */
+static inline void init_board(void) {
+
+ /* Display backlight control */
+ /* TIM4 is an alternate function 2 (AF2) */
+ pwmStart(&PWMD4, &pwmcfg);
+ palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
+ pwmEnableChannel(&PWMD4, 1, 100);
+
+ palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL |
+ PAL_STM32_OSPEED_HIGHEST); /* RST */
+ palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL |
+ PAL_STM32_OSPEED_HIGHEST); /* RS */
+ /*
+ * Initializes the SPI driver 1. The SPI1 signals are routed as follow:
+ * PB12 - NSS.
+ * PB13 - SCK.
+ * PB14 - MISO.
+ * PB15 - MOSI.
+ */
+ spiStart(&SPID1, &spi1cfg1);
+ palSetPad(GPIOA, 4);
+ palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL |
+ PAL_STM32_OSPEED_HIGHEST); /* NSS. */
+ palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5) |
+ PAL_STM32_OSPEED_HIGHEST); /* SCK. */
+ palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5)); /* MISO. */
+ palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(5) |
+ PAL_STM32_OSPEED_HIGHEST); /* MOSI. */
+
+}
+
+/**
+ * @brief Set or clear the lcd reset pin.
+ *
+ * @param[in] state TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(bool_t state) {
+ if (state) {
+ CLR_RST;
+ } else {
+ SET_RST;
+ }
+}
+
+/**
+ * @brief Set the lcd back-light level.
+ *
+ * @param[in] percent 0 to 100%
+ *
+ * @notapi
+ */
+static inline void set_backlight(uint8_t percent) {
+ pwmEnableChannel(&PWMD4, 1, percent);
+}
+
+/**
+ * @brief Take exclusive control of the bus
+ * @note Not needed, not implemented
+ *
+ * @notapi
+ */
+static inline void acquire_bus(void) {
+ spiAcquireBus(&SPID1);
+}
+
+/**
+ * @brief Release exclusive control of the bus
+ * @note Not needed, not implemented
+ *
+ * @notapi
+ */
+static inline void release_bus(void) {
+ spiReleaseBus(&SPID1);
+}
+
+/**
+ * @brief Send data to the index register.
+ *
+ * @param[in] index The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(uint8_t cmd) {
+ palClearPad(GPIOB, 9);
+ palClearPad(GPIOA, 4);
+ while((SPI1->SR & SPI_SR_TXE) == 0);
+ SPI1->DR = cmd;
+ while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
+ palSetPad(GPIOB, 9);
+}
+
+/**
+ * @brief Send data to the lcd.
+ *
+ * @param[in] data The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(uint8_t data) {
+ SPI1->DR = data;
+ while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
+ palSetPad(GPIOA, 4);
+}
+
+static inline void write_ram8(uint8_t data1, uint8_t data2) {
+ SPI1->DR = data1;
+ while((SPI1->SR & SPI_SR_TXE) == 0);
+ SPI1->DR = data2;
+ while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
+ palSetPad(GPIOA, 4);
+}
+
+static inline void write_ram16(uint16_t data) {
+ while((SPI1->SR & SPI_SR_TXE) == 0);
+ SPI1->DR = data;
+}
+
+#if GDISP_HARDWARE_READPIXEL || defined(__DOXYGEN__)
+/**
+ * @brief Read data from the lcd.
+ *
+ * @return The data from the lcd
+ * @note The chip select may need to be asserted/de-asserted
+ * around the actual spi read
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(void) {
+}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_config.h b/drivers/gdisp/HX8347D/gdisp_lld_config.h
new file mode 100644
index 00000000..b8bf853f
--- /dev/null
+++ b/drivers/gdisp/HX8347D/gdisp_lld_config.h
@@ -0,0 +1,39 @@
+/*
+ * This file is subject to the terms of the GFX License, v1.0. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file drivers/gdisp/HX8347D/gdisp_lld_config.h
+ * @brief GDISP Graphic Driver subsystem low level driver header for the HX8347D display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support. */
+/*===========================================================================*/
+
+#define GDISP_DRIVER_NAME "HX8347D"
+
+#define GDISP_HARDWARE_CLEARS TRUE
+#define GDISP_HARDWARE_FILLS TRUE
+#define GDISP_HARDWARE_BITFILLS TRUE
+#define GDISP_HARDWARE_SCROLL FALSE
+#define GDISP_HARDWARE_PIXELREAD FALSE
+#define GDISP_HARDWARE_CONTROL TRUE
+
+#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
+
+#endif /* GFX_USE_GDISP */
+
+#endif /* _GDISP_LLD_CONFIG_H */
+/** @} */
diff --git a/drivers/gdisp/HX8347D/readme.txt b/drivers/gdisp/HX8347D/readme.txt
new file mode 100644
index 00000000..1725ef60
--- /dev/null
+++ b/drivers/gdisp/HX8347D/readme.txt
@@ -0,0 +1,24 @@
+Description:
+
+Driver for LCD with 4-wire serial interface (65k colors).
+
+To use this driver:
+
+1. Add in your halconf.h:
+ a) #define GFX_USE_GDISP TRUE
+
+ b) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
+
+ c) If you are not using a known board then create a gdisp_lld_board.h file
+ and ensure it is on your include path.
+ Use the gdisp_lld_board_st_stm32f4_discovery.h file as a basis.
+ Currently known boards are:
+ BOARD_ST_STM32F4_DISCOVERY
+ Board configuration assume that you have STM32_PWM_USE_TIM4 set to TRUE in your mcuconf.h.
+
+ d) The following are optional - define them if you are not using the defaults below:
+ #define GDISP_SCREEN_WIDTH 240
+ #define GDISP_SCREEN_HEIGHT 320
+
+2. To your makefile add the following lines:
+ include $(GFXLIB)/drivers/gdisp/HX8347D/gdisp_lld.mk
diff --git a/include/gdisp/fonts.h b/include/gdisp/fonts.h
index f4e6f5dd..ca175b77 100644
--- a/include/gdisp/fonts.h
+++ b/include/gdisp/fonts.h
@@ -4,64 +4,65 @@
*
* http://chibios-gfx.com/license.html
*/
-
-/**
- * @file include/gdisp/fonts.h
- * @brief GDISP internal font definitions.
- * @details This is not generally needed by an application. It is used
- * by the low level drivers that need to understand a font.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_FONTS_H
-#define _GDISP_FONTS_H
-
-/* Don't test against GFX_USE_GDISP as we may want to use this in other non-GDISP utilities. */
-
-/**
- * @brief The type of a font column.
- * @note Set by defining @p GDISP_MAX_FNT_HEIGHT appropriately.
- */
-#if GDISP_MAX_FONT_HEIGHT == 16
- typedef uint16_t fontcolumn_t;
-#elif GDISP_MAX_FONT_HEIGHT == 32
- typedef uint32_t fontcolumn_t;
-#else
- #error "GDISP: GDISP_MAX_FONT_HEIGHT must be either 16 or 32"
-#endif
-
-/**
- * @brief Internal font structure.
- * @note This structure is followed by:
- * 1. An array of character widths (uint8_t)
- * 2. An array of column data offsets (relative to the font structure)
- * 3. Each characters array of column data (fontcolumn_t)
- * Each sub-structure must be padded to a multiple of 8 bytes
- * to allow the tables to work across many different compilers.
- */
-struct font {
- const char * name;
- uint8_t height;
- uint8_t charPadding;
- uint8_t lineSpacing;
- uint8_t descenderHeight;
- uint8_t minWidth;
- uint8_t maxWidth;
- char minChar;
- char maxChar;
- uint8_t xscale;
- uint8_t yscale;
- const uint8_t *widthTable;
- const uint16_t *offsetTable;
- const fontcolumn_t *dataTable;
-};
-
-#define _getCharWidth(f,c) (((c) < (f)->minChar || (c) > (f)->maxChar) ? 0 : (f)->widthTable[(c) - (f)->minChar])
-#define _getCharOffset(f,c) ((f)->offsetTable[(c) - (f)->minChar])
-#define _getCharData(f,c) (&(f)->dataTable[_getCharOffset(f, c)])
-
-#endif /* _GDISP_FONTS_H */
-/** @} */
-
+
+/**
+ * @file include/gdisp/fonts.h
+ * @brief GDISP internal font definitions.
+ * @details This is not generally needed by an application. It is used
+ * by the low level drivers that need to understand a font.
+ *
+ * @addtogroup GDISP
+ *
+ * @{
+ */
+
+#ifndef _GDISP_FONTS_H
+#define _GDISP_FONTS_H
+
+/* Don't test against GFX_USE_GDISP as we may want to use this in other non-GDISP utilities. */
+
+/**
+ * @brief The type of a font column.
+ * @note Set by defining @p GDISP_MAX_FNT_HEIGHT appropriately.
+ */
+#if GDISP_MAX_FONT_HEIGHT == 16
+ typedef uint16_t fontcolumn_t;
+#elif GDISP_MAX_FONT_HEIGHT == 32
+ typedef uint32_t fontcolumn_t;
+#else
+ #error "GDISP: GDISP_MAX_FONT_HEIGHT must be either 16 or 32"
+#endif
+
+/**
+ * @brief Internal font structure.
+ * @note This structure is followed by:
+ * 1. An array of character widths (uint8_t)
+ * 2. An array of column data offsets (relative to the font structure)
+ * 3. Each characters array of column data (fontcolumn_t)
+ * Each sub-structure must be padded to a multiple of 8 bytes
+ * to allow the tables to work across many different compilers.
+ */
+struct font {
+ const char * name;
+ uint8_t height;
+ uint8_t charPadding;
+ uint8_t lineSpacing;
+ uint8_t descenderHeight;
+ uint8_t minWidth;
+ uint8_t maxWidth;
+ char minChar;
+ char maxChar;
+ uint8_t xscale;
+ uint8_t yscale;
+ const uint8_t *widthTable;
+ const uint16_t *offsetTable;
+ const fontcolumn_t *dataTable;
+};
+
+#define _getCharWidth(f,c) (((c) < (f)->minChar || (c) > (f)->maxChar) ? 0 : (f)->widthTable[(c) - (f)->minChar])
+#define _getCharOffset(f,c) ((f)->offsetTable[(c) - (f)->minChar])
+#define _getCharData(f,c) (&(f)->dataTable[_getCharOffset(f, c)])
+
+#endif /* _GDISP_FONTS_H */
+/** @} */
+
diff --git a/include/gdisp/image.h b/include/gdisp/image.h
index d0339e0e..f169a0f1 100644
--- a/include/gdisp/image.h
+++ b/include/gdisp/image.h
@@ -9,7 +9,8 @@
* @file include/gdisp/image.h
* @brief GDISP image header file.
*
- * @addtogroup GDISP
+ * @defgroup Image Image
+ * @ingroup GDISP
* @{
*/
diff --git a/include/gwin/button.h b/include/gwin/button.h
index b96cb83e..ed74a80d 100644
--- a/include/gwin/button.h
+++ b/include/gwin/button.h
@@ -63,7 +63,7 @@ typedef enum GButtonState_e {
GBTN_UP, GBTN_DOWN
} GButtonState;
-typedef void (*GButtonDrawFunction)(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+typedef void (*GButtonDrawFunction)(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
// A button window
typedef struct GButtonObject_t {
@@ -146,6 +146,16 @@ void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc);
void gwinButtonDraw(GHandle gh);
/**
+ * @brief Enable or disable a button
+ *
+ * @param[in] gh The window handle (must be a button window)
+ * @param[in] enabled Enable or disable the button
+ *
+ * @api
+ */
+void gwinButtonSetEnabled(GHandle gh, bool_t enabled);
+
+/**
* @brief Set the callback routine to perform a custom button drawing.
*
* @param[in] gh The window handle (must be a button window)
@@ -156,6 +166,27 @@ void gwinButtonDraw(GHandle gh);
*/
void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param);
+/**
+ * @brief Enable a button
+ *
+ * @api
+ */
+#define gwinEnableButton(gh) gwinButtonSetEnabled( ((GButtonObject *)(gh)), TRUE)
+
+/**
+ * @brief Disable a button
+ *
+ * @api
+ */
+#define gwinDisableButton(gh) gwinButtonSetEnabled( ((GButtonObject *)(gh)), FALSE)
+
+/**
+ * @brief Get the state of a button
+ *
+ * @param[in] gh The window handle (must be a button window)
+ *
+ * @api
+ */
#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state)
/**
@@ -197,6 +228,7 @@ void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param);
* @details These routines are called to draw the standard button styles.
*
* @param[in] gh The button handle
+ * @param[in] enabled Is the button currently enabled or disabled
* @param[in] isdown Is the button currently down (depressed)
* @param[in] txt The text to be display inside the button
* @param[in] pstyle The current drawing style for the state we are in
@@ -213,19 +245,19 @@ void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param);
* @api
* @{
*/
-void gwinButtonDraw_3D(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
-void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+void gwinButtonDraw_3D(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
- void gwinButtonDraw_Rounded(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_Rounded(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#endif
#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
- void gwinButtonDraw_Ellipse(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_Ellipse(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#endif
#if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
- void gwinButtonDraw_ArrowUp(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
- void gwinButtonDraw_ArrowDown(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
- void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
- void gwinButtonDraw_ArrowRight(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_ArrowUp(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_ArrowDown(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
+ void gwinButtonDraw_ArrowRight(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param);
#endif
/** @} */
diff --git a/include/gwin/gwin.h b/include/gwin/gwin.h
index 43095643..710c86ba 100644
--- a/include/gwin/gwin.h
+++ b/include/gwin/gwin.h
@@ -45,6 +45,7 @@ typedef struct GWindowObject_t {
coord_t x, y; // Screen relative position
coord_t width, height; // Dimensions of this window
color_t color, bgcolor; // Current drawing colors
+ bool_t enabled; // Enabled/Disabled state
#if GDISP_NEED_TEXT
font_t font; // Current font
#endif
@@ -87,6 +88,16 @@ GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width,
void gwinDestroyWindow(GHandle gh);
/**
+ * @brief Enable or disable a widget (of any type).
+ *
+ * @param[in] gh The window handle
+ * @param[in] enabled Enable or disable the widget
+ *
+ * @api
+ */
+void gwinSetEnabled(GHandle gh, bool_t enabled);
+
+/**
* @brief Get the X coordinate of the window
* @details Returns the X coordinate of the origin of the window.
* The coordinate is relative to the physical screen zero point.
@@ -137,6 +148,20 @@ void gwinDestroyWindow(GHandle gh);
*/
#define gwinSetBgColor(gh, bgclr) (gh)->bgcolor = (bgclr)
+/**
+ * @brief Enable a window of any type
+ *
+ * @param[in] gh The window handle
+ */
+#define gwinEnable(gh) gwinSetEnabled(gh, TRUE)
+
+/**
+ * @brief Disable a window of any type
+ *
+ * @param[in] gh The window handle
+ */
+#define gwinDisable(gh) gwinSetEnabled(gh, FALSE)
+
/* Set up for text */
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
diff --git a/releases.txt b/releases.txt
index b8d19525..5086ee83 100644
--- a/releases.txt
+++ b/releases.txt
@@ -30,6 +30,8 @@ FEATURE: Added GINPUT Dial support and driver using GADC
FEATURE: Simplified assigning inputs to buttons and sliders
FIX: Some fixes for the HD44780 TDISP driver by the user 'Frysk'
FEATURE: Added ILI9481 by user 'Abhishek'
+FEATURE: Added enable/disable functions for widgets (Buttons)
+FEATURE: Added HX8347D driver by user 'Eddie'
*** changes after 1.4 ***
diff --git a/src/gdisp/fonts.c b/src/gdisp/fonts.c
index f0d9f8fd..3d29e50c 100644
--- a/src/gdisp/fonts.c
+++ b/src/gdisp/fonts.c
@@ -10,6 +10,7 @@
* @brief GDISP Font Handling.
*
* @addtogroup GDISP
+ *
* @{
*/
diff --git a/src/gdisp/image.c b/src/gdisp/image.c
index ce4e1250..2a648e59 100644
--- a/src/gdisp/image.c
+++ b/src/gdisp/image.c
@@ -8,6 +8,9 @@
/**
* @file src/gdisp/image.c
* @brief GDISP generic image code.
+ *
+ * @defgroup Image Image
+ * @ingroup GDISP
*/
#include "ch.h"
#include "hal.h"
diff --git a/src/gdisp/image_bmp.c b/src/gdisp/image_bmp.c
index be97eb39..830ee327 100644
--- a/src/gdisp/image_bmp.c
+++ b/src/gdisp/image_bmp.c
@@ -8,6 +8,9 @@
/**
* @file src/gdisp/image_bmp.c
* @brief GDISP native image code.
+ *
+ * @defgroup Image Image
+ * @ingroup GDISP
*/
#include "ch.h"
#include "hal.h"
diff --git a/src/gdisp/image_gif.c b/src/gdisp/image_gif.c
index 084e2fb7..6c61219a 100644
--- a/src/gdisp/image_gif.c
+++ b/src/gdisp/image_gif.c
@@ -8,7 +8,10 @@
/**
* @file src/gdisp/image_gif.c
* @brief GDISP native image code.
- */
+ *
+ * @defgroup Image Image
+ * @ingroup GDISP
+*/
#include "ch.h"
#include "hal.h"
#include "gfx.h"
@@ -573,6 +576,8 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
priv->palsize = 0;
priv->palette = 0;
priv->frame.flags = 0;
+ priv->cache = 0;
+ priv->curcache = 0;
/* Process the Screen Descriptor structure */
diff --git a/src/gdisp/image_native.c b/src/gdisp/image_native.c
index 43a342cc..6da4e862 100644
--- a/src/gdisp/image_native.c
+++ b/src/gdisp/image_native.c
@@ -8,6 +8,9 @@
/**
* @file src/gdisp/image_native.c
* @brief GDISP native image code.
+ *
+ * @defgroup Image Image
+ * @ingroup GDISP
*/
#include "ch.h"
#include "hal.h"
diff --git a/src/gdisp/image_png.c b/src/gdisp/image_png.c
index 2ea59f8b..1cfba97f 100644
--- a/src/gdisp/image_png.c
+++ b/src/gdisp/image_png.c
@@ -8,7 +8,10 @@
/**
* @file src/gdisp/image_png.c
* @brief GDISP native image code.
- */
+ *
+ * @defgroup Image Image
+ * @ingroup GDISP
+*/
#include "ch.h"
#include "hal.h"
#include "gfx.h"
diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c
index 82f54cae..7320cf2d 100644
--- a/src/ginput/mouse.c
+++ b/src/ginput/mouse.c
@@ -4,573 +4,573 @@
*
* http://chibios-gfx.com/license.html
*/
-
-/**
- * @file src/ginput/mouse.c
- * @brief GINPUT mouse/touch code.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
- */
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) || defined(__DOXYGEN__)
-
-#include "ginput/lld/mouse.h"
-
-#if GINPUT_MOUSE_NEED_CALIBRATION
- #if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
- #error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
- #endif
-
- #define GINPUT_MOUSE_CALIBRATION_FONT "* Double"
- #define GINPUT_MOUSE_CALIBRATION_FONT2 "* Narrow"
- #define GINPUT_MOUSE_CALIBRATION_TEXT "Calibration"
- #define GINPUT_MOUSE_CALIBRATION_ERROR_TEXT "Failed - Please try again!"
- #define GINPUT_MOUSE_CALIBRATION_SAME_TEXT "Error: Same Reading - Check Driver!"
-
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR < 0
- #define GINPUT_MOUSE_CALIBRATION_POINTS 3
- #else
- #define GINPUT_MOUSE_CALIBRATION_POINTS 4
- #endif
-
- typedef struct Calibration_t {
- float ax;
- float bx;
- float cx;
- float ay;
- float by;
- float cy;
- } Calibration;
-#endif
-
-typedef struct MousePoint_t {
- coord_t x, y;
- } MousePoint;
-
-static GTIMER_DECL(MouseTimer);
-
-static struct MouseConfig_t {
- MouseReading t;
- MousePoint movepos;
- MousePoint clickpos;
- systime_t clicktime;
- uint16_t last_buttons;
- uint16_t flags;
- #define FLG_INIT_DONE 0x8000
- #define FLG_CLICK_TIMER 0x0001
- #define FLG_IN_CAL 0x0010
- #define FLG_CAL_OK 0x0020
- #define FLG_CAL_SAVED 0x0040
- #define FLG_CAL_FREE 0x0080
- #if GINPUT_MOUSE_NEED_CALIBRATION
- GMouseCalibrationSaveRoutine fnsavecal;
- GMouseCalibrationLoadRoutine fnloadcal;
- Calibration caldata;
- #endif
- } MouseConfig;
-
-#if GINPUT_MOUSE_NEED_CALIBRATION
- static inline void _tsDrawCross(const MousePoint *pp) {
- gdispDrawLine(pp->x-15, pp->y, pp->x-2, pp->y, White);
- gdispDrawLine(pp->x+2, pp->y, pp->x+15, pp->y, White);
- gdispDrawLine(pp->x, pp->y-15, pp->x, pp->y-2, White);
- gdispDrawLine(pp->x, pp->y+2, pp->x, pp->y+15, White);
-
- gdispDrawLine(pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131));
- gdispDrawLine(pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131));
-
- gdispDrawLine(pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131));
- gdispDrawLine(pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131));
-
- gdispDrawLine(pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
- gdispDrawLine(pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
-
- gdispDrawLine(pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131));
- gdispDrawLine(pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131));
- }
-
- static inline void _tsClearCross(const MousePoint *pp) {
- gdispFillArea(pp->x - 15, pp->y - 15, 42, 42, Blue);
- }
-
- static inline void _tsTransform(MouseReading *pt, const Calibration *c) {
- pt->x = (coord_t) (c->ax * pt->x + c->bx * pt->y + c->cx);
- pt->y = (coord_t) (c->ay * pt->x + c->by * pt->y + c->cy);
- }
-
- static inline void _tsDo3PointCalibration(const MousePoint *cross, const MousePoint *points, Calibration *c) {
- float dx, dx0, dx1, dx2, dy0, dy1, dy2;
-
- /* Compute all the required determinants */
- dx = ((float)(points[0].x - points[2].x)) * ((float)(points[1].y - points[2].y))
- - ((float)(points[1].x - points[2].x)) * ((float)(points[0].y - points[2].y));
-
- dx0 = ((float)(cross[0].x - cross[2].x)) * ((float)(points[1].y - points[2].y))
- - ((float)(cross[1].x - cross[2].x)) * ((float)(points[0].y - points[2].y));
-
- dx1 = ((float)(cross[1].x - cross[2].x)) * ((float)(points[0].x - points[2].x))
- - ((float)(cross[0].x - cross[2].x)) * ((float)(points[1].x - points[2].x));
-
- dx2 = cross[0].x * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) -
- cross[1].x * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) +
- cross[2].x * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y);
-
- dy0 = ((float)(cross[0].y - cross[2].y)) * ((float)(points[1].y - points[2].y))
- - ((float)(cross[1].y - cross[2].y)) * ((float)(points[0].y - points[2].y));
-
- dy1 = ((float)(cross[1].y - cross[2].y)) * ((float)(points[0].x - points[2].x))
- - ((float)(cross[0].y - cross[2].y)) * ((float)(points[1].x - points[2].x));
-
- dy2 = cross[0].y * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) -
- cross[1].y * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) +
- cross[2].y * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y);
-
- /* Now, calculate all the required coefficients */
- c->ax = dx0 / dx;
- c->bx = dx1 / dx;
- c->cx = dx2 / dx;
-
- c->ay = dy0 / dx;
- c->by = dy1 / dx;
- c->cy = dy2 / dx;
- }
-#endif
-
-#if GINPUT_MOUSE_READ_CYCLES > 1
- static void get_raw_reading(MouseReading *pt) {
- int32_t x, y, z;
- unsigned i;
-
- x = y = z = 0;
- for(i = 0; i < GINPUT_MOUSE_READ_CYCLES; i++) {
- ginput_lld_mouse_get_reading(pt);
- x += pt->x;
- y += pt->y;
- z += pt->z;
- }
-
- /* Take the average of the readings */
- pt->x = x / GINPUT_MOUSE_READ_CYCLES;
- pt->y = y / GINPUT_MOUSE_READ_CYCLES;
- pt->z = z / GINPUT_MOUSE_READ_CYCLES;
- }
-#else
- #define get_raw_reading(pt) ginput_lld_mouse_get_reading(pt)
-#endif
-
-static void get_calibrated_reading(MouseReading *pt) {
- #if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL
- coord_t w, h;
- #endif
-
- get_raw_reading(pt);
-
- #if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL
- w = gdispGetWidth();
- h = gdispGetHeight();
- #endif
-
- #if GINPUT_MOUSE_NEED_CALIBRATION
- _tsTransform(pt, &MouseConfig.caldata);
- #endif
-
- #if GDISP_NEED_CONTROL
- switch(gdispGetOrientation()) {
- case GDISP_ROTATE_0:
- break;
- case GDISP_ROTATE_90:
- {
- coord_t t = pt->y;
- pt->y = h - 1 - pt->x;
- pt->x = t;
- }
- break;
- case GDISP_ROTATE_180:
- pt->x = w - 1 - pt->x;
- pt->y = h - 1 - pt->y;
- break;
- case GDISP_ROTATE_270:
- {
- coord_t t = pt->x;
- pt->x = w - 1 - pt->y;
- pt->y = t;
- }
- break;
- }
- #endif
-
- #if GINPUT_MOUSE_NEED_CALIBRATION
- if (pt->x < 0) pt->x = 0;
- else if (pt->x >= w) pt->x = w-1;
- if (pt->y < 0) pt->y = 0;
- else if (pt->y >= h) pt->y = h-1;
- #endif
-}
-
-static void MousePoll(void *param) {
- (void) param;
- GSourceListener *psl;
- GEventMouse *pe;
- unsigned meta;
- uint16_t tbtns;
- uint32_t cdiff;
- uint32_t mdiff;
-
- // Save the last mouse state
- MouseConfig.last_buttons = MouseConfig.t.buttons;
-
- // Get the new mouse reading
- get_calibrated_reading(&MouseConfig.t);
-
- // Calculate out new event meta value and handle CLICK and CXTCLICK
- meta = GMETA_NONE;
-
- // Calculate the position difference from our movement reference (update the reference if out of range)
- mdiff = (MouseConfig.t.x - MouseConfig.movepos.x) * (MouseConfig.t.x - MouseConfig.movepos.x) +
- (MouseConfig.t.y - MouseConfig.movepos.y) * (MouseConfig.t.y - MouseConfig.movepos.y);
- if (mdiff > GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER) {
- MouseConfig.movepos.x = MouseConfig.t.x;
- MouseConfig.movepos.y = MouseConfig.t.y;
- }
-
- // Check if the click has moved outside the click area and if so cancel the click
- if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
- cdiff = (MouseConfig.t.x - MouseConfig.clickpos.x) * (MouseConfig.t.x - MouseConfig.clickpos.x) +
- (MouseConfig.t.y - MouseConfig.clickpos.y) * (MouseConfig.t.y - MouseConfig.clickpos.y);
- if (cdiff > GINPUT_MOUSE_MAX_CLICK_JITTER * GINPUT_MOUSE_MAX_CLICK_JITTER)
- MouseConfig.flags &= ~FLG_CLICK_TIMER;
- }
-
- // Mouse down
- tbtns = MouseConfig.t.buttons & ~MouseConfig.last_buttons;
- if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
- meta |= GMETA_MOUSE_DOWN;
- if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
- MouseConfig.clickpos.x = MouseConfig.t.x;
- MouseConfig.clickpos.y = MouseConfig.t.y;
- MouseConfig.clicktime = chTimeNow();
- MouseConfig.flags |= FLG_CLICK_TIMER;
- }
-
- // Mouse up
- tbtns = ~MouseConfig.t.buttons & MouseConfig.last_buttons;
- if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
- meta |= GMETA_MOUSE_UP;
- if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
- if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
- if ((tbtns & GINPUT_MOUSE_BTN_LEFT)
- #if GINPUT_MOUSE_CLICK_TIME != TIME_INFINITE
- && chTimeNow() - MouseConfig.clicktime < MS2ST(GINPUT_MOUSE_CLICK_TIME)
- #endif
- )
- meta |= GMETA_MOUSE_CLICK;
- else
- meta |= GMETA_MOUSE_CXTCLICK;
- MouseConfig.flags &= ~FLG_CLICK_TIMER;
- }
- }
-
- // Send the event to the listeners that are interested.
- psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
- if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
- // This listener is missing - save the meta events that have happened
- psl->srcflags |= meta;
- continue;
- }
-
- // If we haven't really moved (and there are no meta events) don't bother sending the event
- if (mdiff <= GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER && !psl->srcflags && !meta && !(psl->listenflags & GLISTEN_MOUSENOFILTER))
- continue;
-
- // Send the event if we are listening for it
- if (((MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
- || (!(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
- || (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
- pe->type = GINPUT_MOUSE_EVENT_TYPE;
- pe->instance = 0;
- pe->x = MouseConfig.t.x;
- pe->y = MouseConfig.t.y;
- pe->z = MouseConfig.t.z;
- pe->current_buttons = MouseConfig.t.buttons;
- pe->last_buttons = MouseConfig.last_buttons;
- pe->meta = meta;
- if (psl->srcflags) {
- pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
- pe->meta |= psl->srcflags;
- psl->srcflags = 0;
- }
- geventSendEvent(psl);
- }
- }
-}
-
-GSourceHandle ginputGetMouse(uint16_t instance) {
- #if GINPUT_MOUSE_NEED_CALIBRATION
- Calibration *pc;
- #endif
-
- // We only support a single mouse instance currently
- // Instance 9999 is the same as instance 0 except that it installs
- // a special "raw" calibration if there isn't one we can load.
- if (instance && instance != 9999)
- return 0;
-
- // Do we need to initialise the mouse subsystem?
- if (!(MouseConfig.flags & FLG_INIT_DONE)) {
- ginput_lld_mouse_init();
-
- #if GINPUT_MOUSE_NEED_CALIBRATION
- #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
- if (!MouseConfig.fnloadcal) {
- MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
- MouseConfig.flags &= ~FLG_CAL_FREE;
- }
- if (!MouseConfig.fnsavecal)
- MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
- #endif
- if (MouseConfig.fnloadcal && (pc = (Calibration *)MouseConfig.fnloadcal(instance))) {
- MouseConfig.caldata = pc[0];
- MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
- if ((MouseConfig.flags & FLG_CAL_FREE))
- chHeapFree((void *)pc);
- } else if (instance == 9999) {
- MouseConfig.caldata.ax = 1;
- MouseConfig.caldata.bx = 0;
- MouseConfig.caldata.cx = 0;
- MouseConfig.caldata.ay = 0;
- MouseConfig.caldata.by = 1;
- MouseConfig.caldata.cy = 0;
- MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
- } else
- ginputCalibrateMouse(instance);
- #endif
-
- // Get the first reading
- MouseConfig.last_buttons = 0;
- get_calibrated_reading(&MouseConfig.t);
-
- // Mark init as done and start the Poll timer
- MouseConfig.flags |= FLG_INIT_DONE;
- gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
- }
-
- // Return our structure as the handle
- return (GSourceHandle)&MouseConfig;
-}
-
-bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {
- // Win32 threads don't seem to recognise priority and/or pre-emption
- // so we add a sleep here to prevent 100% polled applications from locking up.
- chThdSleepMilliseconds(1);
-
- if (instance || (MouseConfig.flags & (FLG_INIT_DONE|FLG_IN_CAL)) != FLG_INIT_DONE)
- return FALSE;
-
- pe->type = GINPUT_MOUSE_EVENT_TYPE;
- pe->instance = instance;
- pe->x = MouseConfig.t.x;
- pe->y = MouseConfig.t.y;
- pe->z = MouseConfig.t.z;
- pe->current_buttons = MouseConfig.t.buttons;
- pe->last_buttons = MouseConfig.last_buttons;
- if (pe->current_buttons & ~pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
- pe->meta = GMETA_MOUSE_DOWN;
- else if (~pe->current_buttons & pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
- pe->meta = GMETA_MOUSE_UP;
- else
- pe->meta = GMETA_NONE;
- return TRUE;
-}
-
-bool_t ginputCalibrateMouse(uint16_t instance) {
- #if !GINPUT_MOUSE_NEED_CALIBRATION
- (void) instance;
-
- return FALSE;
- #else
-
- const coord_t height = gdispGetHeight();
- const coord_t width = gdispGetWidth();
- const MousePoint cross[] = {{(width / 4), (height / 4)},
- {(width - (width / 4)) , (height / 4)},
- {(width - (width / 4)) , (height - (height / 4))},
- {(width / 2), (height / 2)}}; /* Check point */
- MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS];
- const MousePoint *pc;
- MousePoint *pt;
- int32_t px, py;
- unsigned i, j;
- font_t font1, font2;
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
- unsigned err;
- #endif
-
- if (instance || (MouseConfig.flags & FLG_IN_CAL))
- return FALSE;
-
- font1 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT);
- font2 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT2);
-
- MouseConfig.flags |= FLG_IN_CAL;
- gtimerStop(&MouseTimer);
- MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED);
-
- #if GDISP_NEED_CONTROL
- gdispSetOrientation(GDISP_ROTATE_0);
- #endif
-
- #if GDISP_NEED_CLIP
- gdispSetClip(0, 0, width, height);
- #endif
-
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
- while(1) {
- #endif
- gdispClear(Blue);
-
- gdispFillStringBox(0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1, White, Blue, justifyCenter);
-
- for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) {
- _tsDrawCross(pc);
-
- do {
-
- /* Wait for the mouse to be pressed */
- while(get_raw_reading(&MouseConfig.t), !(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT))
- chThdSleepMilliseconds(20);
-
- /* Average all the samples while the mouse is down */
- for(px = py = 0, j = 0;
- chThdSleepMilliseconds(20), /* Settling time between readings */
- get_raw_reading(&MouseConfig.t),
- (MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT);
- j++) {
- px += MouseConfig.t.x;
- py += MouseConfig.t.y;
- }
-
- } while(!j);
-
- pt->x = px / j;
- pt->y = py / j;
-
- _tsClearCross(pc);
-
- if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) {
- gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2, Red, Yellow, justifyCenter);
- chThdSleepMilliseconds(5000);
- gdispFillArea(0, 35, width, 40, Blue);
- }
-
- }
-
- /* Apply 3 point calibration algorithm */
- _tsDo3PointCalibration(cross, points, &MouseConfig.caldata);
-
- /* Verification of correctness of calibration (optional) :
- * See if the 4th point (Middle of the screen) coincides with the calibrated
- * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
- * Else, start from the beginning.
- */
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
- /* Transform the co-ordinates */
- MouseConfig.t.x = points[3].x;
- MouseConfig.t.y = points[3].y;
- _tsTransform(&MouseConfig.t, &MouseConfig.caldata);
-
- /* Calculate the delta */
- err = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) +
- (MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y);
-
- if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR)
- break;
-
- gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2, Red, Yellow, justifyCenter);
- chThdSleepMilliseconds(5000);
- }
- #endif
-
- // Restart everything
- gdispCloseFont(font1);
- gdispCloseFont(font2);
- MouseConfig.flags |= FLG_CAL_OK;
- MouseConfig.last_buttons = 0;
- get_calibrated_reading(&MouseConfig.t);
- MouseConfig.flags &= ~FLG_IN_CAL;
- if ((MouseConfig.flags & FLG_INIT_DONE))
- gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
-
- // Save the calibration data (if possible)
- if (MouseConfig.fnsavecal) {
- MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
- MouseConfig.flags |= FLG_CAL_SAVED;
- }
-
- return TRUE;
- #endif
-}
-
-/* Set the routines to save and fetch calibration data.
- * This function should be called before first calling ginputGetMouse() for a particular instance
- * as the gdispGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it.
- * If this is called after gdispGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained.
- * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.
- */
-void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree) {
- #if GINPUT_MOUSE_NEED_CALIBRATION
- if (instance)
- return;
-
- MouseConfig.fnloadcal = fnload;
- MouseConfig.fnsavecal = fnsave;
- if (requireFree)
- MouseConfig.flags |= FLG_CAL_FREE;
- else
- MouseConfig.flags &= ~FLG_CAL_FREE;
- #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
- if (!MouseConfig.fnloadcal) {
- MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
- MouseConfig.flags &= ~FLG_CAL_FREE;
- }
- if (!MouseConfig.fnsavecal)
- MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
- #endif
- if (MouseConfig.fnsavecal && (MouseConfig.flags & (FLG_CAL_OK|FLG_CAL_SAVED)) == FLG_CAL_OK) {
- MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
- MouseConfig.flags |= FLG_CAL_SAVED;
- }
- #else
- (void)instance, (void)fnsave, (void)fnload, (void)requireFree;
- #endif
-}
-
-/* Test if a particular mouse instance requires routines to save its calibration data. */
-bool_t ginputRequireMouseCalibrationStorage(uint16_t instance) {
- if (instance)
- return FALSE;
-
- #if GINPUT_MOUSE_NEED_CALIBRATION && !GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
- return TRUE;
- #else
- return FALSE;
- #endif
-}
-
-/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
-void ginputMouseWakeup(void) {
- gtimerJab(&MouseTimer);
-}
-
-/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
-void ginputMouseWakeupI(void) {
- gtimerJabI(&MouseTimer);
-}
-
-#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
-/** @} */
+
+/**
+ * @file src/ginput/mouse.c
+ * @brief GINPUT mouse/touch code.
+ *
+ * @defgroup Mouse Mouse
+ * @ingroup GINPUT
+ * @{
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) || defined(__DOXYGEN__)
+
+#include "ginput/lld/mouse.h"
+
+#if GINPUT_MOUSE_NEED_CALIBRATION
+ #if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
+ #error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
+ #endif
+
+ #define GINPUT_MOUSE_CALIBRATION_FONT "* Double"
+ #define GINPUT_MOUSE_CALIBRATION_FONT2 "* Narrow"
+ #define GINPUT_MOUSE_CALIBRATION_TEXT "Calibration"
+ #define GINPUT_MOUSE_CALIBRATION_ERROR_TEXT "Failed - Please try again!"
+ #define GINPUT_MOUSE_CALIBRATION_SAME_TEXT "Error: Same Reading - Check Driver!"
+
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR < 0
+ #define GINPUT_MOUSE_CALIBRATION_POINTS 3
+ #else
+ #define GINPUT_MOUSE_CALIBRATION_POINTS 4
+ #endif
+
+ typedef struct Calibration_t {
+ float ax;
+ float bx;
+ float cx;
+ float ay;
+ float by;
+ float cy;
+ } Calibration;
+#endif
+
+typedef struct MousePoint_t {
+ coord_t x, y;
+ } MousePoint;
+
+static GTIMER_DECL(MouseTimer);
+
+static struct MouseConfig_t {
+ MouseReading t;
+ MousePoint movepos;
+ MousePoint clickpos;
+ systime_t clicktime;
+ uint16_t last_buttons;
+ uint16_t flags;
+ #define FLG_INIT_DONE 0x8000
+ #define FLG_CLICK_TIMER 0x0001
+ #define FLG_IN_CAL 0x0010
+ #define FLG_CAL_OK 0x0020
+ #define FLG_CAL_SAVED 0x0040
+ #define FLG_CAL_FREE 0x0080
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ GMouseCalibrationSaveRoutine fnsavecal;
+ GMouseCalibrationLoadRoutine fnloadcal;
+ Calibration caldata;
+ #endif
+ } MouseConfig;
+
+#if GINPUT_MOUSE_NEED_CALIBRATION
+ static inline void _tsDrawCross(const MousePoint *pp) {
+ gdispDrawLine(pp->x-15, pp->y, pp->x-2, pp->y, White);
+ gdispDrawLine(pp->x+2, pp->y, pp->x+15, pp->y, White);
+ gdispDrawLine(pp->x, pp->y-15, pp->x, pp->y-2, White);
+ gdispDrawLine(pp->x, pp->y+2, pp->x, pp->y+15, White);
+
+ gdispDrawLine(pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131));
+
+ gdispDrawLine(pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131));
+
+ gdispDrawLine(pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
+
+ gdispDrawLine(pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131));
+ gdispDrawLine(pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131));
+ }
+
+ static inline void _tsClearCross(const MousePoint *pp) {
+ gdispFillArea(pp->x - 15, pp->y - 15, 42, 42, Blue);
+ }
+
+ static inline void _tsTransform(MouseReading *pt, const Calibration *c) {
+ pt->x = (coord_t) (c->ax * pt->x + c->bx * pt->y + c->cx);
+ pt->y = (coord_t) (c->ay * pt->x + c->by * pt->y + c->cy);
+ }
+
+ static inline void _tsDo3PointCalibration(const MousePoint *cross, const MousePoint *points, Calibration *c) {
+ float dx, dx0, dx1, dx2, dy0, dy1, dy2;
+
+ /* Compute all the required determinants */
+ dx = ((float)(points[0].x - points[2].x)) * ((float)(points[1].y - points[2].y))
+ - ((float)(points[1].x - points[2].x)) * ((float)(points[0].y - points[2].y));
+
+ dx0 = ((float)(cross[0].x - cross[2].x)) * ((float)(points[1].y - points[2].y))
+ - ((float)(cross[1].x - cross[2].x)) * ((float)(points[0].y - points[2].y));
+
+ dx1 = ((float)(cross[1].x - cross[2].x)) * ((float)(points[0].x - points[2].x))
+ - ((float)(cross[0].x - cross[2].x)) * ((float)(points[1].x - points[2].x));
+
+ dx2 = cross[0].x * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) -
+ cross[1].x * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) +
+ cross[2].x * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y);
+
+ dy0 = ((float)(cross[0].y - cross[2].y)) * ((float)(points[1].y - points[2].y))
+ - ((float)(cross[1].y - cross[2].y)) * ((float)(points[0].y - points[2].y));
+
+ dy1 = ((float)(cross[1].y - cross[2].y)) * ((float)(points[0].x - points[2].x))
+ - ((float)(cross[0].y - cross[2].y)) * ((float)(points[1].x - points[2].x));
+
+ dy2 = cross[0].y * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y) -
+ cross[1].y * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y) +
+ cross[2].y * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y);
+
+ /* Now, calculate all the required coefficients */
+ c->ax = dx0 / dx;
+ c->bx = dx1 / dx;
+ c->cx = dx2 / dx;
+
+ c->ay = dy0 / dx;
+ c->by = dy1 / dx;
+ c->cy = dy2 / dx;
+ }
+#endif
+
+#if GINPUT_MOUSE_READ_CYCLES > 1
+ static void get_raw_reading(MouseReading *pt) {
+ int32_t x, y, z;
+ unsigned i;
+
+ x = y = z = 0;
+ for(i = 0; i < GINPUT_MOUSE_READ_CYCLES; i++) {
+ ginput_lld_mouse_get_reading(pt);
+ x += pt->x;
+ y += pt->y;
+ z += pt->z;
+ }
+
+ /* Take the average of the readings */
+ pt->x = x / GINPUT_MOUSE_READ_CYCLES;
+ pt->y = y / GINPUT_MOUSE_READ_CYCLES;
+ pt->z = z / GINPUT_MOUSE_READ_CYCLES;
+ }
+#else
+ #define get_raw_reading(pt) ginput_lld_mouse_get_reading(pt)
+#endif
+
+static void get_calibrated_reading(MouseReading *pt) {
+ #if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL
+ coord_t w, h;
+ #endif
+
+ get_raw_reading(pt);
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL
+ w = gdispGetWidth();
+ h = gdispGetHeight();
+ #endif
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ _tsTransform(pt, &MouseConfig.caldata);
+ #endif
+
+ #if GDISP_NEED_CONTROL
+ switch(gdispGetOrientation()) {
+ case GDISP_ROTATE_0:
+ break;
+ case GDISP_ROTATE_90:
+ {
+ coord_t t = pt->y;
+ pt->y = h - 1 - pt->x;
+ pt->x = t;
+ }
+ break;
+ case GDISP_ROTATE_180:
+ pt->x = w - 1 - pt->x;
+ pt->y = h - 1 - pt->y;
+ break;
+ case GDISP_ROTATE_270:
+ {
+ coord_t t = pt->x;
+ pt->x = w - 1 - pt->y;
+ pt->y = t;
+ }
+ break;
+ }
+ #endif
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ if (pt->x < 0) pt->x = 0;
+ else if (pt->x >= w) pt->x = w-1;
+ if (pt->y < 0) pt->y = 0;
+ else if (pt->y >= h) pt->y = h-1;
+ #endif
+}
+
+static void MousePoll(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventMouse *pe;
+ unsigned meta;
+ uint16_t tbtns;
+ uint32_t cdiff;
+ uint32_t mdiff;
+
+ // Save the last mouse state
+ MouseConfig.last_buttons = MouseConfig.t.buttons;
+
+ // Get the new mouse reading
+ get_calibrated_reading(&MouseConfig.t);
+
+ // Calculate out new event meta value and handle CLICK and CXTCLICK
+ meta = GMETA_NONE;
+
+ // Calculate the position difference from our movement reference (update the reference if out of range)
+ mdiff = (MouseConfig.t.x - MouseConfig.movepos.x) * (MouseConfig.t.x - MouseConfig.movepos.x) +
+ (MouseConfig.t.y - MouseConfig.movepos.y) * (MouseConfig.t.y - MouseConfig.movepos.y);
+ if (mdiff > GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER) {
+ MouseConfig.movepos.x = MouseConfig.t.x;
+ MouseConfig.movepos.y = MouseConfig.t.y;
+ }
+
+ // Check if the click has moved outside the click area and if so cancel the click
+ if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
+ cdiff = (MouseConfig.t.x - MouseConfig.clickpos.x) * (MouseConfig.t.x - MouseConfig.clickpos.x) +
+ (MouseConfig.t.y - MouseConfig.clickpos.y) * (MouseConfig.t.y - MouseConfig.clickpos.y);
+ if (cdiff > GINPUT_MOUSE_MAX_CLICK_JITTER * GINPUT_MOUSE_MAX_CLICK_JITTER)
+ MouseConfig.flags &= ~FLG_CLICK_TIMER;
+ }
+
+ // Mouse down
+ tbtns = MouseConfig.t.buttons & ~MouseConfig.last_buttons;
+ if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
+ meta |= GMETA_MOUSE_DOWN;
+ if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
+ MouseConfig.clickpos.x = MouseConfig.t.x;
+ MouseConfig.clickpos.y = MouseConfig.t.y;
+ MouseConfig.clicktime = chTimeNow();
+ MouseConfig.flags |= FLG_CLICK_TIMER;
+ }
+
+ // Mouse up
+ tbtns = ~MouseConfig.t.buttons & MouseConfig.last_buttons;
+ if ((tbtns & GINPUT_MOUSE_BTN_LEFT))
+ meta |= GMETA_MOUSE_UP;
+ if ((tbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
+ if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
+ if ((tbtns & GINPUT_MOUSE_BTN_LEFT)
+ #if GINPUT_MOUSE_CLICK_TIME != TIME_INFINITE
+ && chTimeNow() - MouseConfig.clicktime < MS2ST(GINPUT_MOUSE_CLICK_TIME)
+ #endif
+ )
+ meta |= GMETA_MOUSE_CLICK;
+ else
+ meta |= GMETA_MOUSE_CXTCLICK;
+ MouseConfig.flags &= ~FLG_CLICK_TIMER;
+ }
+ }
+
+ // Send the event to the listeners that are interested.
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
+ if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save the meta events that have happened
+ psl->srcflags |= meta;
+ continue;
+ }
+
+ // If we haven't really moved (and there are no meta events) don't bother sending the event
+ if (mdiff <= GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER && !psl->srcflags && !meta && !(psl->listenflags & GLISTEN_MOUSENOFILTER))
+ continue;
+
+ // Send the event if we are listening for it
+ if (((MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
+ || (!(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
+ || (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
+ pe->type = GINPUT_MOUSE_EVENT_TYPE;
+ pe->instance = 0;
+ pe->x = MouseConfig.t.x;
+ pe->y = MouseConfig.t.y;
+ pe->z = MouseConfig.t.z;
+ pe->current_buttons = MouseConfig.t.buttons;
+ pe->last_buttons = MouseConfig.last_buttons;
+ pe->meta = meta;
+ if (psl->srcflags) {
+ pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
+ pe->meta |= psl->srcflags;
+ psl->srcflags = 0;
+ }
+ geventSendEvent(psl);
+ }
+ }
+}
+
+GSourceHandle ginputGetMouse(uint16_t instance) {
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ Calibration *pc;
+ #endif
+
+ // We only support a single mouse instance currently
+ // Instance 9999 is the same as instance 0 except that it installs
+ // a special "raw" calibration if there isn't one we can load.
+ if (instance && instance != 9999)
+ return 0;
+
+ // Do we need to initialise the mouse subsystem?
+ if (!(MouseConfig.flags & FLG_INIT_DONE)) {
+ ginput_lld_mouse_init();
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ if (!MouseConfig.fnloadcal) {
+ MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
+ MouseConfig.flags &= ~FLG_CAL_FREE;
+ }
+ if (!MouseConfig.fnsavecal)
+ MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
+ #endif
+ if (MouseConfig.fnloadcal && (pc = (Calibration *)MouseConfig.fnloadcal(instance))) {
+ MouseConfig.caldata = pc[0];
+ MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
+ if ((MouseConfig.flags & FLG_CAL_FREE))
+ chHeapFree((void *)pc);
+ } else if (instance == 9999) {
+ MouseConfig.caldata.ax = 1;
+ MouseConfig.caldata.bx = 0;
+ MouseConfig.caldata.cx = 0;
+ MouseConfig.caldata.ay = 0;
+ MouseConfig.caldata.by = 1;
+ MouseConfig.caldata.cy = 0;
+ MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
+ } else
+ ginputCalibrateMouse(instance);
+ #endif
+
+ // Get the first reading
+ MouseConfig.last_buttons = 0;
+ get_calibrated_reading(&MouseConfig.t);
+
+ // Mark init as done and start the Poll timer
+ MouseConfig.flags |= FLG_INIT_DONE;
+ gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
+ }
+
+ // Return our structure as the handle
+ return (GSourceHandle)&MouseConfig;
+}
+
+bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {
+ // Win32 threads don't seem to recognise priority and/or pre-emption
+ // so we add a sleep here to prevent 100% polled applications from locking up.
+ chThdSleepMilliseconds(1);
+
+ if (instance || (MouseConfig.flags & (FLG_INIT_DONE|FLG_IN_CAL)) != FLG_INIT_DONE)
+ return FALSE;
+
+ pe->type = GINPUT_MOUSE_EVENT_TYPE;
+ pe->instance = instance;
+ pe->x = MouseConfig.t.x;
+ pe->y = MouseConfig.t.y;
+ pe->z = MouseConfig.t.z;
+ pe->current_buttons = MouseConfig.t.buttons;
+ pe->last_buttons = MouseConfig.last_buttons;
+ if (pe->current_buttons & ~pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
+ pe->meta = GMETA_MOUSE_DOWN;
+ else if (~pe->current_buttons & pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
+ pe->meta = GMETA_MOUSE_UP;
+ else
+ pe->meta = GMETA_NONE;
+ return TRUE;
+}
+
+bool_t ginputCalibrateMouse(uint16_t instance) {
+ #if !GINPUT_MOUSE_NEED_CALIBRATION
+ (void) instance;
+
+ return FALSE;
+ #else
+
+ const coord_t height = gdispGetHeight();
+ const coord_t width = gdispGetWidth();
+ const MousePoint cross[] = {{(width / 4), (height / 4)},
+ {(width - (width / 4)) , (height / 4)},
+ {(width - (width / 4)) , (height - (height / 4))},
+ {(width / 2), (height / 2)}}; /* Check point */
+ MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS];
+ const MousePoint *pc;
+ MousePoint *pt;
+ int32_t px, py;
+ unsigned i, j;
+ font_t font1, font2;
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
+ unsigned err;
+ #endif
+
+ if (instance || (MouseConfig.flags & FLG_IN_CAL))
+ return FALSE;
+
+ font1 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT);
+ font2 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT2);
+
+ MouseConfig.flags |= FLG_IN_CAL;
+ gtimerStop(&MouseTimer);
+ MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED);
+
+ #if GDISP_NEED_CONTROL
+ gdispSetOrientation(GDISP_ROTATE_0);
+ #endif
+
+ #if GDISP_NEED_CLIP
+ gdispSetClip(0, 0, width, height);
+ #endif
+
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
+ while(1) {
+ #endif
+ gdispClear(Blue);
+
+ gdispFillStringBox(0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1, White, Blue, justifyCenter);
+
+ for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) {
+ _tsDrawCross(pc);
+
+ do {
+
+ /* Wait for the mouse to be pressed */
+ while(get_raw_reading(&MouseConfig.t), !(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT))
+ chThdSleepMilliseconds(20);
+
+ /* Average all the samples while the mouse is down */
+ for(px = py = 0, j = 0;
+ chThdSleepMilliseconds(20), /* Settling time between readings */
+ get_raw_reading(&MouseConfig.t),
+ (MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT);
+ j++) {
+ px += MouseConfig.t.x;
+ py += MouseConfig.t.y;
+ }
+
+ } while(!j);
+
+ pt->x = px / j;
+ pt->y = py / j;
+
+ _tsClearCross(pc);
+
+ if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) {
+ gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2, Red, Yellow, justifyCenter);
+ chThdSleepMilliseconds(5000);
+ gdispFillArea(0, 35, width, 40, Blue);
+ }
+
+ }
+
+ /* Apply 3 point calibration algorithm */
+ _tsDo3PointCalibration(cross, points, &MouseConfig.caldata);
+
+ /* Verification of correctness of calibration (optional) :
+ * See if the 4th point (Middle of the screen) coincides with the calibrated
+ * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
+ * Else, start from the beginning.
+ */
+ #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
+ /* Transform the co-ordinates */
+ MouseConfig.t.x = points[3].x;
+ MouseConfig.t.y = points[3].y;
+ _tsTransform(&MouseConfig.t, &MouseConfig.caldata);
+
+ /* Calculate the delta */
+ err = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) +
+ (MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y);
+
+ if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR)
+ break;
+
+ gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2, Red, Yellow, justifyCenter);
+ chThdSleepMilliseconds(5000);
+ }
+ #endif
+
+ // Restart everything
+ gdispCloseFont(font1);
+ gdispCloseFont(font2);
+ MouseConfig.flags |= FLG_CAL_OK;
+ MouseConfig.last_buttons = 0;
+ get_calibrated_reading(&MouseConfig.t);
+ MouseConfig.flags &= ~FLG_IN_CAL;
+ if ((MouseConfig.flags & FLG_INIT_DONE))
+ gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
+
+ // Save the calibration data (if possible)
+ if (MouseConfig.fnsavecal) {
+ MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
+ MouseConfig.flags |= FLG_CAL_SAVED;
+ }
+
+ return TRUE;
+ #endif
+}
+
+/* Set the routines to save and fetch calibration data.
+ * This function should be called before first calling ginputGetMouse() for a particular instance
+ * as the gdispGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it.
+ * If this is called after gdispGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained.
+ * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.
+ */
+void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree) {
+ #if GINPUT_MOUSE_NEED_CALIBRATION
+ if (instance)
+ return;
+
+ MouseConfig.fnloadcal = fnload;
+ MouseConfig.fnsavecal = fnsave;
+ if (requireFree)
+ MouseConfig.flags |= FLG_CAL_FREE;
+ else
+ MouseConfig.flags &= ~FLG_CAL_FREE;
+ #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ if (!MouseConfig.fnloadcal) {
+ MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
+ MouseConfig.flags &= ~FLG_CAL_FREE;
+ }
+ if (!MouseConfig.fnsavecal)
+ MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
+ #endif
+ if (MouseConfig.fnsavecal && (MouseConfig.flags & (FLG_CAL_OK|FLG_CAL_SAVED)) == FLG_CAL_OK) {
+ MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
+ MouseConfig.flags |= FLG_CAL_SAVED;
+ }
+ #else
+ (void)instance, (void)fnsave, (void)fnload, (void)requireFree;
+ #endif
+}
+
+/* Test if a particular mouse instance requires routines to save its calibration data. */
+bool_t ginputRequireMouseCalibrationStorage(uint16_t instance) {
+ if (instance)
+ return FALSE;
+
+ #if GINPUT_MOUSE_NEED_CALIBRATION && !GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
+ return TRUE;
+ #else
+ return FALSE;
+ #endif
+}
+
+/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
+void ginputMouseWakeup(void) {
+ gtimerJab(&MouseTimer);
+}
+
+/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
+void ginputMouseWakeupI(void) {
+ gtimerJabI(&MouseTimer);
+}
+
+#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */
+/** @} */
diff --git a/src/gwin/button.c b/src/gwin/button.c
index 96478390..8d77b8ba 100644
--- a/src/gwin/button.c
+++ b/src/gwin/button.c
@@ -55,6 +55,10 @@ static void gwinButtonCallback(void *param, GEvent *pe) {
#define pxe ((GEventToggle *)pe)
#define pbe ((GEventGWinButton *)pe)
+ // check if button is disabled
+ if (gh->enabled == false)
+ return;
+
switch (pe->type) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
@@ -135,6 +139,7 @@ static void gwinButtonCallback(void *param, GEvent *pe) {
GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type) {
if (!(gb = (GButtonObject *)_gwinInit((GWindowObject *)gb, x, y, width, height, sizeof(GButtonObject))))
return 0;
+
gb->gwin.type = GW_BUTTON;
gb->fn = 0;
gb->param = 0;
@@ -145,6 +150,10 @@ GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width,
gb->txt = "";
geventListenerInit(&gb->listener);
geventRegisterCallback(&gb->listener, gwinButtonCallback, gb);
+
+ // buttons are enabled by default
+ gb->gwin.enabled = true;
+
return (GHandle)gb;
}
@@ -225,6 +234,7 @@ void gwinButtonDraw(GHandle gh) {
#endif
gbw->fn(gh,
+ gbw->gwin.enabled,
gbw->state == GBTN_DOWN,
gh->font && gbw->txt ? gbw->txt : "",
gbw->state == GBTN_DOWN ? &gbw->dn : &gbw->up,
@@ -245,7 +255,15 @@ void gwinSetButtonCustom(GHandle gh, GButtonDrawFunction fn, void *param) {
#undef gbw
}
-void gwinButtonDraw_3D(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+void gwinButtonSetEnabled(GHandle gh, bool_t enabled) {
+ if (gh->type != GW_BUTTON)
+ return;
+
+ gh->enabled = enabled;
+}
+
+void gwinButtonDraw_3D(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
@@ -254,7 +272,8 @@ void gwinButtonDraw_3D(GHandle gh, bool_t isdown, const char *txt, const GButton
gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, pstyle->color_edge);
}
-void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+void gwinButtonDraw_Square(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
@@ -263,7 +282,8 @@ void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GBu
}
#if GDISP_NEED_ARC
- void gwinButtonDraw_Rounded(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ void gwinButtonDraw_Rounded(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
@@ -279,7 +299,8 @@ void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GBu
#endif
#if GDISP_NEED_ELLIPSE
- void gwinButtonDraw_Ellipse(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ void gwinButtonDraw_Ellipse(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
@@ -290,7 +311,8 @@ void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GBu
#endif
#if GDISP_NEED_CONVEX_POLYGON
- void gwinButtonDraw_ArrowUp(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ void gwinButtonDraw_ArrowUp(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
point arw[7];
@@ -308,7 +330,8 @@ void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GBu
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
- void gwinButtonDraw_ArrowDown(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ void gwinButtonDraw_ArrowDown(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
point arw[7];
@@ -326,7 +349,8 @@ void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GBu
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
- void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ void gwinButtonDraw_ArrowLeft(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
point arw[7];
@@ -344,7 +368,8 @@ void gwinButtonDraw_Square(GHandle gh, bool_t isdown, const char *txt, const GBu
gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, pstyle->color_txt, justifyCenter);
}
- void gwinButtonDraw_ArrowRight(GHandle gh, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ void gwinButtonDraw_ArrowRight(GHandle gh, bool_t enabled, bool_t isdown, const char *txt, const GButtonDrawStyle *pstyle, void *param) {
+ (void) enabled;
(void) isdown;
(void) param;
point arw[7];
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 70cc12ee..b6340c2d 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -55,6 +55,10 @@ GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width,
return (GHandle)gw;
}
+void gwinSetEnabled(GHandle gh, bool_t enabled) {
+
+}
+
void gwinDestroyWindow(GHandle gh) {
// Clean up any type specific dynamic memory allocations
switch(gh->type) {
diff --git a/src/tdisp/tdisp.c b/src/tdisp/tdisp.c
index a5608acf..42b22cd5 100644
--- a/src/tdisp/tdisp.c
+++ b/src/tdisp/tdisp.c
@@ -72,7 +72,7 @@ void tdispSetCursor(coord_t col, coord_t row) {
MUTEX_LEAVE();
}
-void tdispCreateChar(uint8_t address, uint8_t *charmap) {
+void tdispCreateChar(uint8_t address, char *charmap) {
/* make sure we don't write somewhere we're not supposed to */
if (address < TDISP.maxCustomChars) {
MUTEX_ENTER();