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 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 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 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 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 + +#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 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 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 Binary files /dev/null and b/demos/3rdparty/notepad-2/toolbarIcons.gif 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. * - *

Features

- * - 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 + *

Documentation

+ * - http://chibios-gfx.com + * + *

License

+ * - 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 { @@ -145,6 +145,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. * @@ -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 @@ -86,6 +87,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. @@ -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();