From 8275c8820f230342939a2410dd0b24c0f26a14e5 Mon Sep 17 00:00:00 2001 From: Andrew Hannam Date: Mon, 26 Nov 2012 18:45:26 +1000 Subject: Ginput and structure changes GINPUT Touch including drivers GTIMER fixes GEVENT fixes GWIN button completion Structure changes to better seperate sections of a sub-system --- drivers/gdisp/ILI9320/gdisp_lld.c | 9 +- drivers/gdisp/Nokia6610/gdisp_lld.c | 7 +- drivers/gdisp/S6D1121/gdisp_lld.c | 7 +- drivers/gdisp/SSD1289/gdisp_lld.c | 7 +- drivers/gdisp/SSD1963/gdisp_lld.c | 2 +- drivers/gdisp/TestStub/gdisp_lld.c | 2 +- drivers/gdisp/VMT/gdisp_lld.c | 2 +- drivers/gdisp/Win32/gdisp_lld.c | 952 --------------------- drivers/gdisp/Win32/gdisp_lld.mk | 5 - drivers/gdisp/Win32/gdisp_lld_config.h | 54 -- drivers/gdisp/Win32/readme.txt | 21 - drivers/gdisp/Win32/touchscreen_lld_config.h | 50 -- drivers/ginput/toggle/Pal/ginput_lld.mk | 5 + drivers/ginput/toggle/Pal/ginput_lld_toggle.c | 62 ++ .../toggle/Pal/ginput_lld_toggle_board_example.h | 65 ++ .../Pal/ginput_lld_toggle_board_olimexsam7ex256.h | 60 ++ .../ginput/toggle/Pal/ginput_lld_toggle_config.h | 44 + drivers/ginput/toggle/Pal/readme.txt | 13 + drivers/ginput/touch/ADS7843/ginput_lld.mk | 5 + drivers/ginput/touch/ADS7843/ginput_lld_mouse.c | 139 +++ .../touch/ADS7843/ginput_lld_mouse_board_example.h | 87 ++ .../touch/ADS7843/ginput_lld_mouse_board_unknown.h | 97 +++ .../ginput/touch/ADS7843/ginput_lld_mouse_config.h | 41 + drivers/ginput/touch/ADS7843/readme.txt | 9 + drivers/ginput/touch/MCU/ginput_lld.mk | 5 + drivers/ginput/touch/MCU/ginput_lld_mouse.c | 136 +++ .../touch/MCU/ginput_lld_mouse_board_example.h | 96 +++ .../touch/MCU/ginput_lld_mouse_board_unknown.h | 174 ++++ drivers/ginput/touch/MCU/ginput_lld_mouse_config.h | 41 + drivers/ginput/touch/MCU/readme.txt | 9 + drivers/multiple/Win32/gdisp_lld.c | 910 ++++++++++++++++++++ drivers/multiple/Win32/gdisp_lld.mk | 5 + drivers/multiple/Win32/gdisp_lld_config.h | 54 ++ drivers/multiple/Win32/ginput_lld_mouse_config.h | 58 ++ drivers/multiple/Win32/readme.txt | 22 + gfx.mk | 4 +- include/gdisp.h | 2 +- include/gdisp/fonts.h | 92 ++ include/gdisp_emulation.c | 770 ----------------- include/gdisp_fonts.h | 92 -- include/gdisp_lld.h | 650 -------------- include/gdisp_lld_msgs.h | 195 ----- include/gevent.h | 29 +- include/ginput.h | 253 +----- include/ginput/ginput_dial.h | 89 ++ include/ginput/ginput_keyboard.h | 143 ++++ include/ginput/ginput_mouse.h | 135 +++ include/ginput/ginput_toggle.h | 93 ++ include/gtimer.h | 5 +- include/gwin.h | 133 +-- include/gwin/gwin_button.h | 142 +++ include/gwin/gwin_console.h | 102 +++ include/lld/gdisp/emulation.c | 770 +++++++++++++++++ include/lld/gdisp/gdisp_lld.h | 650 ++++++++++++++ include/lld/gdisp/gdisp_lld_msgs.h | 195 +++++ include/lld/ginput/mouse.h | 125 +++ include/lld/ginput/toggle.h | 71 ++ include/lld/touchscreen/touchscreen_lld.h | 130 +++ include/touchscreen.h | 2 +- include/touchscreen_lld.h | 130 --- src/gdisp.c | 10 +- src/gdisp_fonts.c | 3 +- src/gevent.c | 54 +- src/ginput.c | 37 - src/ginput/dial.c | 35 + src/ginput/ginput.mk | 4 + src/ginput/keyboard.c | 35 + src/ginput/mouse.c | 554 ++++++++++++ src/ginput/toggle.c | 161 ++++ src/gtimer.c | 54 +- src/gwin.c | 368 +------- src/gwin/button.c | 331 +++++++ src/gwin/console.c | 210 +++++ src/gwin/gwin.mk | 2 + src/gwin/gwin_internal.h | 53 ++ 75 files changed, 6437 insertions(+), 3731 deletions(-) delete mode 100644 drivers/gdisp/Win32/gdisp_lld.c delete mode 100644 drivers/gdisp/Win32/gdisp_lld.mk delete mode 100644 drivers/gdisp/Win32/gdisp_lld_config.h delete mode 100644 drivers/gdisp/Win32/readme.txt delete mode 100644 drivers/gdisp/Win32/touchscreen_lld_config.h create mode 100644 drivers/ginput/toggle/Pal/ginput_lld.mk create mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle.c create mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h create mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h create mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h create mode 100644 drivers/ginput/toggle/Pal/readme.txt create mode 100644 drivers/ginput/touch/ADS7843/ginput_lld.mk create mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse.c create mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h create mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_unknown.h create mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h create mode 100644 drivers/ginput/touch/ADS7843/readme.txt create mode 100644 drivers/ginput/touch/MCU/ginput_lld.mk create mode 100644 drivers/ginput/touch/MCU/ginput_lld_mouse.c create mode 100644 drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h create mode 100644 drivers/ginput/touch/MCU/ginput_lld_mouse_board_unknown.h create mode 100644 drivers/ginput/touch/MCU/ginput_lld_mouse_config.h create mode 100644 drivers/ginput/touch/MCU/readme.txt create mode 100644 drivers/multiple/Win32/gdisp_lld.c create mode 100644 drivers/multiple/Win32/gdisp_lld.mk create mode 100644 drivers/multiple/Win32/gdisp_lld_config.h create mode 100644 drivers/multiple/Win32/ginput_lld_mouse_config.h create mode 100644 drivers/multiple/Win32/readme.txt create mode 100644 include/gdisp/fonts.h delete mode 100644 include/gdisp_emulation.c delete mode 100644 include/gdisp_fonts.h delete mode 100644 include/gdisp_lld.h delete mode 100644 include/gdisp_lld_msgs.h create mode 100644 include/ginput/ginput_dial.h create mode 100644 include/ginput/ginput_keyboard.h create mode 100644 include/ginput/ginput_mouse.h create mode 100644 include/ginput/ginput_toggle.h create mode 100644 include/gwin/gwin_button.h create mode 100644 include/gwin/gwin_console.h create mode 100644 include/lld/gdisp/emulation.c create mode 100644 include/lld/gdisp/gdisp_lld.h create mode 100644 include/lld/gdisp/gdisp_lld_msgs.h create mode 100644 include/lld/ginput/mouse.h create mode 100644 include/lld/ginput/toggle.h create mode 100644 include/lld/touchscreen/touchscreen_lld.h delete mode 100644 include/touchscreen_lld.h delete mode 100644 src/ginput.c create mode 100644 src/ginput/dial.c create mode 100644 src/ginput/ginput.mk create mode 100644 src/ginput/keyboard.c create mode 100644 src/ginput/mouse.c create mode 100644 src/ginput/toggle.c create mode 100644 src/gwin/button.c create mode 100644 src/gwin/console.c create mode 100644 src/gwin/gwin.mk create mode 100644 src/gwin/gwin_internal.h diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c index 0641985a..0d1e969c 100644 --- a/drivers/gdisp/ILI9320/gdisp_lld.c +++ b/drivers/gdisp/ILI9320/gdisp_lld.c @@ -33,12 +33,15 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" -#if defined(BOARD_OLIMEX_STM32_LCD) +#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD + /* Include the user supplied board definitions */ + #include "gdisp_lld_board.h" +#elif defined(BOARD_OLIMEX_STM32_LCD) #include "gdisp_lld_board_olimex_stm32_lcd.h" #else - #include "gdisp_lld_board_example.h" + #include "gdisp_lld_board.h" #endif /*===========================================================================*/ diff --git a/drivers/gdisp/Nokia6610/gdisp_lld.c b/drivers/gdisp/Nokia6610/gdisp_lld.c index 04a39545..661d6a77 100644 --- a/drivers/gdisp/Nokia6610/gdisp_lld.c +++ b/drivers/gdisp/Nokia6610/gdisp_lld.c @@ -33,7 +33,7 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" /*===========================================================================*/ /* Driver local definitions. */ @@ -73,7 +73,10 @@ /* Driver local functions. */ /*===========================================================================*/ -#if defined(BOARD_OLIMEX_SAM7_EX256) +#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD + /* Include the user supplied board definitions */ + #include "gdisp_lld_board.h" +#elif defined(BOARD_OLIMEX_SAM7_EX256) #include "gdisp_lld_board_olimexsam7ex256.h" #else /* Include the user supplied board definitions */ diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c index 585899d2..49116ec1 100644 --- a/drivers/gdisp/S6D1121/gdisp_lld.c +++ b/drivers/gdisp/S6D1121/gdisp_lld.c @@ -33,7 +33,7 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" /*===========================================================================*/ /* Driver local definitions. */ @@ -56,7 +56,10 @@ /* Driver local definitions. */ /*===========================================================================*/ -#if defined(BOARD_OLIMEX_STM32_E407) +#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD + /* Include the user supplied board definitions */ + #include "gdisp_lld_board.h" +#elif defined(BOARD_OLIMEX_STM32_E407) #include "gdisp_lld_board_olimex_e407.h" #else #include "gdisp_lld_board.h" diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c index 0d05ede8..6ac55865 100644 --- a/drivers/gdisp/SSD1289/gdisp_lld.c +++ b/drivers/gdisp/SSD1289/gdisp_lld.c @@ -33,7 +33,7 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" /*===========================================================================*/ /* Driver local definitions. */ @@ -53,7 +53,10 @@ /* Driver local functions. */ /*===========================================================================*/ -#if defined(BOARD_FIREBULL_STM32_F103) +#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD + /* Include the user supplied board definitions */ + #include "gdisp_lld_board.h" +#elif defined(BOARD_FIREBULL_STM32_F103) #include "gdisp_lld_board_firebullstm32f103.h" #else /* Include the user supplied board definitions */ diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c index aceeb4a7..cc8e776e 100644 --- a/drivers/gdisp/SSD1963/gdisp_lld.c +++ b/drivers/gdisp/SSD1963/gdisp_lld.c @@ -33,7 +33,7 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" /* All the board specific code should go in these include file so the driver * can be ported to another board just by creating a suitable file. diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c index 7084737a..f1373ccd 100644 --- a/drivers/gdisp/TestStub/gdisp_lld.c +++ b/drivers/gdisp/TestStub/gdisp_lld.c @@ -33,7 +33,7 @@ #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" /* ---- Required Routines ---- */ /* diff --git a/drivers/gdisp/VMT/gdisp_lld.c b/drivers/gdisp/VMT/gdisp_lld.c index 6a7d0cfb..6291f3ce 100644 --- a/drivers/gdisp/VMT/gdisp_lld.c +++ b/drivers/gdisp/VMT/gdisp_lld.c @@ -35,7 +35,7 @@ #define GDISP_LLD_NO_STRUCT /* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" /*===========================================================================*/ /* Driver local definitions. */ diff --git a/drivers/gdisp/Win32/gdisp_lld.c b/drivers/gdisp/Win32/gdisp_lld.c deleted file mode 100644 index 8aff8efc..00000000 --- a/drivers/gdisp/Win32/gdisp_lld.c +++ /dev/null @@ -1,952 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file drivers/gdisp/Win32/gdisp_lld.c - * @brief GDISP Graphics Driver subsystem low level driver source for Win32. - * - * @addtogroup GDISP - * @{ - */ - -#include "ch.h" -#include "hal.h" -#include "gdisp.h" -#include "touchscreen.h" - -#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ - -/* Include the emulation code for things we don't support */ -#include "gdisp_emulation.c" - -#include -#include -#include -#include -#include -#include - -/*===========================================================================*/ -/* Driver local routines . */ -/*===========================================================================*/ - -#define WIN32_USE_MSG_REDRAW FALSE - -#define APP_NAME "GDISP" - -#define COLOR2BGR(c) ((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF)) -#define BGR2COLOR(c) COLOR2BGR(c) - -static HWND winRootWindow = NULL; -static HDC dcBuffer = NULL; -static HBITMAP dcBitmap = NULL; -static HBITMAP dcOldBitmap; -static volatile bool_t isReady = FALSE; -static coord_t mousex, mousey; -static bool_t mousedn; - -static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - HDC dc; - PAINTSTRUCT ps; - - switch (Msg) { - case WM_CREATE: - break; - case WM_LBUTTONDOWN: - mousedn = TRUE; - mousex = (coord_t)LOWORD(lParam); - mousey = (coord_t)HIWORD(lParam); - break; - case WM_LBUTTONUP: - mousedn = FALSE; - mousex = (coord_t)LOWORD(lParam); - mousey = (coord_t)HIWORD(lParam); - break; - case WM_MOUSEMOVE: - mousex = (coord_t)LOWORD(lParam); - mousey = (coord_t)HIWORD(lParam); - break; - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_RBUTTONDBLCLK: - break; - case WM_SYSKEYDOWN: - case WM_KEYDOWN: - case WM_SYSKEYUP: - case WM_KEYUP: - break; - case WM_CHAR: - case WM_DEADCHAR: - case WM_SYSCHAR: - case WM_SYSDEADCHAR: - break; - case WM_PAINT: - dc = BeginPaint(hWnd, &ps); - BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right - ps.rcPaint.left, - ps.rcPaint.bottom - ps.rcPaint.top, - dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); - EndPaint(hWnd, &ps); - break; - case WM_DESTROY: - PostQuitMessage(0); - SelectObject(dcBuffer, dcOldBitmap); - DeleteDC(dcBuffer); - DeleteObject(dcBitmap); - winRootWindow = NULL; - break; - default: - return DefWindowProc(hWnd, Msg, wParam, lParam); - } - return 0; -} - -static DWORD WINAPI WindowThread(LPVOID lpParameter) { - (void)lpParameter; - - MSG msg; - HANDLE hInstance; - WNDCLASS wc; - RECT rect; - HDC dc; - - hInstance = GetModuleHandle(NULL); - - wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC; - wc.lpfnWndProc = (WNDPROC)myWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = GetStockObject(WHITE_BRUSH); - wc.lpszMenuName = NULL; - wc.lpszClassName = APP_NAME; - RegisterClass(&wc); - - rect.top = 0; rect.bottom = GDISP.Height; - rect.left = 0; rect.right = GDISP.Width; - AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0); - winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0, - rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL); - assert(winRootWindow != NULL); - - - GetClientRect(winRootWindow, &rect); - GDISP.Width = rect.right-rect.left; - GDISP.Height = rect.bottom - rect.top; - - dc = GetDC(winRootWindow); - dcBitmap = CreateCompatibleBitmap(dc, GDISP.Width, GDISP.Height); - dcBuffer = CreateCompatibleDC(dc); - ReleaseDC(winRootWindow, dc); - dcOldBitmap = SelectObject(dcBuffer, dcBitmap); - - ShowWindow(winRootWindow, SW_SHOW); - UpdateWindow(winRootWindow); - isReady = TRUE; - - while(GetMessage(&msg, NULL, 0, 0) > 0) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - ExitProcess(0); - return msg.wParam; -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/* ---- Required Routines ---- */ -/* - The following 2 routines are required. - All other routines are optional. -*/ - -/** - * @brief Low level GDISP driver initialisation. - * @return TRUE if successful, FALSE on error. - * - * @notapi - */ -bool_t GDISP_LLD(init)(void) { - RECT rect; - - /* Set the window dimensions */ - GetWindowRect(GetDesktopWindow(), &rect); - GDISP.Width = rect.right - rect.left; - GDISP.Height = rect.bottom - rect.top; - if (GDISP.Width > GDISP_SCREEN_WIDTH) - GDISP.Width = GDISP_SCREEN_WIDTH; - if (GDISP.Height > GDISP_SCREEN_HEIGHT) - GDISP.Height = GDISP_SCREEN_HEIGHT; - - /* Initialise the window */ - CreateThread(0, 0, WindowThread, 0, 0, 0); - while (!isReady) - Sleep(1); - - /* Initialise the GDISP structure to match */ - GDISP.Orientation = GDISP_ROTATE_0; - GDISP.Powermode = powerOn; - GDISP.Backlight = 100; - GDISP.Contrast = 50; - #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(drawpixel)(coord_t x, coord_t y, color_t color) { - HDC dc; - #if WIN32_USE_MSG_REDRAW - RECT rect; - #endif - #if GDISP_NEED_CONTROL - coord_t t; - #endif - - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - // Clip pre orientation change - if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; - #endif - - #if GDISP_NEED_CONTROL - switch(GDISP.Orientation) { - case GDISP_ROTATE_0: - break; - case GDISP_ROTATE_90: - t = GDISP.Height - 1 - y; - y = x; - x = t; - break; - case GDISP_ROTATE_180: - x = GDISP.Width - 1 - x; - y = GDISP.Height - 1 - y; - break; - case GDISP_ROTATE_270: - t = GDISP.Width - 1 - x; - x = y; - y = t; - break; - } - #endif - - // Draw the pixel in the buffer - color = COLOR2BGR(color); - SetPixel(dcBuffer, x, y, color); - - #if WIN32_USE_MSG_REDRAW - rect.left = x; rect.right = x+1; - rect.top = y; rect.bottom = y+1; - InvalidateRect(winRootWindow, &rect, FALSE); - UpdateWindow(winRootWindow); - #else - // Draw the pixel again directly on the screen. - // This is cheaper than invalidating a single pixel in the window - dc = GetDC(winRootWindow); - SetPixel(dc, x, y, color); - ReleaseDC(winRootWindow, dc); - #endif -} - -/* ---- Optional Routines ---- */ - -#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) - /** - * @brief Draw a line. - * @note Optional - The high level driver can emulate using software. - * - * @param[in] x0, y0 The start of the line - * @param[in] x1, y1 The end of the line - * @param[in] color The color of the line - * - * @notapi - */ - void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - POINT p; - HPEN pen; - HDC dc; - HGDIOBJ old; - #if GDISP_NEED_CLIP - HRGN clip; - #endif - #if WIN32_USE_MSG_REDRAW - RECT rect; - #endif - #if GDISP_NEED_CONTROL - coord_t t; - #endif - - #if GDISP_NEED_CLIP - clip = NULL; - #endif - - #if GDISP_NEED_CONTROL - switch(GDISP.Orientation) { - case GDISP_ROTATE_0: - #if GDISP_NEED_CLIP - // Clip post orientation change - if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) - clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1); - #endif - break; - case GDISP_ROTATE_90: - t = GDISP.Height - 1 - y0; - y0 = x0; - x0 = t; - t = GDISP.Height - 1 - y1; - y1 = x1; - x1 = t; - #if GDISP_NEED_CLIP - // Clip post orientation change - if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) - clip = CreateRectRgn(GDISP.Height-1-GDISP.clipy1, GDISP.clipx0, GDISP.Height-1-GDISP.clipy0, GDISP.clipx1); - #endif - break; - case GDISP_ROTATE_180: - x0 = GDISP.Width - 1 - x0; - y0 = GDISP.Height - 1 - y0; - x1 = GDISP.Width - 1 - x1; - y1 = GDISP.Height - 1 - y1; - #if GDISP_NEED_CLIP - // Clip post orientation change - if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) - clip = CreateRectRgn(GDISP.Width-1-GDISP.clipx1, GDISP.Height-1-GDISP.clipy1, GDISP.Width-1-GDISP.clipx0, GDISP.Height-1-GDISP.clipy0); - #endif - break; - case GDISP_ROTATE_270: - t = GDISP.Width - 1 - x0; - x0 = y0; - y0 = t; - t = GDISP.Width - 1 - x1; - x1 = y1; - y1 = t; - #if GDISP_NEED_CLIP - // Clip post orientation change - if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) - clip = CreateRectRgn(GDISP.clipy0, GDISP.Width-1-GDISP.clipx1, GDISP.clipy1, GDISP.Width-1-GDISP.clipx0); - #endif - break; - } - #else - #if GDISP_NEED_CLIP - clip = NULL; - if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) - clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1); - #endif - #endif - - color = COLOR2BGR(color); - pen = CreatePen(PS_SOLID, 1, color); - if (pen) { - // Draw the line in the buffer - #if GDISP_NEED_CLIP - if (clip) SelectClipRgn(dcBuffer, clip); - #endif - old = SelectObject(dcBuffer, pen); - MoveToEx(dcBuffer, x0, y0, &p); - LineTo(dcBuffer, x1, y1); - SelectObject(dcBuffer, old); - SetPixel(dcBuffer, x1, y1, color); - #if GDISP_NEED_CLIP - if (clip) SelectClipRgn(dcBuffer, NULL); - #endif - - #if WIN32_USE_MSG_REDRAW - rect.left = x0; rect.right = x1+1; - rect.top = y0; rect.bottom = y1+1; - InvalidateRect(winRootWindow, &rect, FALSE); - UpdateWindow(winRootWindow); - #else - // Redrawing the line on the screen is cheaper than invalidating the whole rectangular area - dc = GetDC(winRootWindow); - #if GDISP_NEED_CLIP - if (clip) SelectClipRgn(dc, clip); - #endif - old = SelectObject(dc, pen); - MoveToEx(dc, x0, y0, &p); - LineTo(dc, x1, y1); - SelectObject(dc, old); - SetPixel(dc, x1, y1, color); - #if GDISP_NEED_CLIP - if (clip) SelectClipRgn(dc, NULL); - #endif - ReleaseDC(winRootWindow, dc); - #endif - - DeleteObject(pen); - } - } -#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(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - HDC dc; - RECT rect; - HBRUSH hbr; - - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - // Clip pre orientation change - 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 - - #if GDISP_NEED_CONTROL - switch(GDISP.Orientation) { - case GDISP_ROTATE_0: - rect.top = y; - rect.bottom = rect.top+cy; - rect.left = x; - rect.right = rect.left+cx; - break; - case GDISP_ROTATE_90: - rect.top = x; - rect.bottom = rect.top+cx; - rect.right = GDISP.Height - y; - rect.left = rect.right-cy; - break; - case GDISP_ROTATE_180: - rect.bottom = GDISP.Height - y; - rect.top = rect.bottom-cy; - rect.right = GDISP.Width - x; - rect.left = rect.right-cx; - break; - case GDISP_ROTATE_270: - rect.bottom = GDISP.Width - x; - rect.top = rect.bottom-cx; - rect.left = y; - rect.right = rect.left+cy; - break; - } - #else - rect.top = y; - rect.bottom = rect.top+cy; - rect.left = x; - rect.right = rect.left+cx; - #endif - - color = COLOR2BGR(color); - hbr = CreateSolidBrush(color); - - if (hbr) { - // Fill the area - FillRect(dcBuffer, &rect, hbr); - - #if WIN32_USE_MSG_REDRAW - InvalidateRect(winRootWindow, &rect, FALSE); - UpdateWindow(winRootWindow); - #else - // Filling the area directly on the screen is likely to be cheaper than invalidating it - dc = GetDC(winRootWindow); - FillRect(dc, &rect, hbr); - ReleaseDC(winRootWindow, dc); - #endif - - DeleteObject(hbr); - } - } -#endif - -#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) - static pixel_t *rotateimg(coord_t cx, coord_t cy, coord_t srcx, coord_t srccx, const pixel_t *buffer) { - pixel_t *dstbuf; - pixel_t *dst; - const pixel_t *src; - size_t sz; - coord_t i, j; - - // Shortcut. - if (GDISP.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx) - return (pixel_t *)buffer; - - // Allocate the destination buffer - sz = (size_t)cx * (size_t)cy; - if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t)))) - return 0; - - // Copy the bits we need - switch(GDISP.Orientation) { - case GDISP_ROTATE_0: - for(dst = dstbuf, src = buffer+srcx, j = 0; j < cy; j++) - for(i = 0; i < cx; i++, src += srccx - cx) - *dst++ = *src++; - break; - case GDISP_ROTATE_90: - for(src = buffer+srcx, j = 0; j < cy; j++) { - dst = dstbuf+cy-j-1; - for(i = 0; i < cx; i++, src += srccx - cx, dst += cy) - *dst = *src++; - } - break; - case GDISP_ROTATE_180: - for(dst = dstbuf+sz, src = buffer+srcx, j = 0; j < cy; j++) - for(i = 0; i < cx; i++, src += srccx - cx) - *--dst = *src++; - break; - case GDISP_ROTATE_270: - for(src = buffer+srcx, j = 0; j < cy; j++) { - dst = dstbuf+sz-cy+j; - for(i = 0; i < cx; i++, src += srccx - cx, dst -= cy) - *dst = *src++; - } - break; - } - return dstbuf; - } - - /** - * @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(blitareaex)(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) { - BITMAPV4HEADER bmpInfo; - RECT rect; - #if GDISP_NEED_CONTROL - pixel_t *srcimg; - #endif - - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - // Clip pre orientation change - 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 - - // Make everything relative to the start of the line - buffer += srccx*srcy; - srcy = 0; - - memset(&bmpInfo, 0, sizeof(bmpInfo)); - bmpInfo.bV4Size = sizeof(bmpInfo); - bmpInfo.bV4Planes = 1; - bmpInfo.bV4BitCount = 32; - bmpInfo.bV4AlphaMask = 0; - bmpInfo.bV4RedMask = RGB2COLOR(255,0,0); - bmpInfo.bV4GreenMask = RGB2COLOR(0,255,0); - bmpInfo.bV4BlueMask = RGB2COLOR(0,0,255); - bmpInfo.bV4V4Compression = BI_BITFIELDS; - bmpInfo.bV4XPelsPerMeter = 3078; - bmpInfo.bV4YPelsPerMeter = 3078; - bmpInfo.bV4ClrUsed = 0; - bmpInfo.bV4ClrImportant = 0; - bmpInfo.bV4CSType = 0; //LCS_sRGB; - - #if GDISP_NEED_CONTROL - bmpInfo.bV4SizeImage = (cy*cx) * sizeof(pixel_t); - srcimg = rotateimg(cx, cy, srcx, srccx, buffer); - if (!srcimg) return; - - switch(GDISP.Orientation) { - case GDISP_ROTATE_0: - bmpInfo.bV4Width = cx; - bmpInfo.bV4Height = -cy; /* top-down image */ - rect.top = y; - rect.bottom = rect.top+cy; - rect.left = x; - rect.right = rect.left+cx; - break; - case GDISP_ROTATE_90: - bmpInfo.bV4Width = cy; - bmpInfo.bV4Height = -cx; /* top-down image */ - rect.top = x; - rect.bottom = rect.top+cx; - rect.right = GDISP.Height - y; - rect.left = rect.right-cy; - break; - case GDISP_ROTATE_180: - bmpInfo.bV4Width = cx; - bmpInfo.bV4Height = -cy; /* top-down image */ - rect.bottom = GDISP.Height - y; - rect.top = rect.bottom-cy; - rect.right = GDISP.Width - x; - rect.left = rect.right-cx; - break; - case GDISP_ROTATE_270: - bmpInfo.bV4Width = cy; - bmpInfo.bV4Height = -cx; /* top-down image */ - rect.bottom = GDISP.Width - x; - rect.top = rect.bottom-cx; - rect.left = y; - rect.right = rect.left+cy; - break; - } - SetDIBitsToDevice(dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); - if (srcimg != (pixel_t *)buffer) - free(srcimg); - - #else - bmpInfo.bV4Width = srccx; - bmpInfo.bV4Height = -cy; /* top-down image */ - bmpInfo.bV4SizeImage = (cy*srccx) * sizeof(pixel_t); - rect.top = y; - rect.bottom = rect.top+cy; - rect.left = x; - rect.right = rect.left+cx; - SetDIBitsToDevice(dcBuffer, x, y, cx, cy, srcx, 0, 0, cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); - #endif - - // Invalidate the region to get it on the screen. - InvalidateRect(winRootWindow, &rect, FALSE); - UpdateWindow(winRootWindow); - } -#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. - * @return The color of the specified pixel. - * - * @param[in] x, y The start of the text - * - * @notapi - */ - color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { - color_t color; - - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - // Clip pre orientation change - if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0; - #endif - - #if GDISP_NEED_CONTROL - switch(GDISP.Orientation) { - case GDISP_ROTATE_90: - t = GDISP.Height - 1 - y; - y = x; - x = t; - break; - case GDISP_ROTATE_180: - x = GDISP.Width - 1 - x; - y = GDISP.Height - 1 - y; - break; - case GDISP_ROTATE_270: - t = GDISP.Width - 1 - x; - x = y; - y = t; - break; - } - #endif - - color = GetPixel(dcBuffer, x, y); - return BGR2COLOR(color); - } -#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(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { - RECT rect, frect, srect; - HBRUSH hbr; - - #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP - // Clip pre orientation change - 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 - - if (lines > cy) lines = cy; - else if (-lines > cy) lines = -cy; - - bgcolor = COLOR2BGR(bgcolor); - hbr = CreateSolidBrush(bgcolor); - - #if GDISP_NEED_CONTROL - switch(GDISP.Orientation) { - case GDISP_ROTATE_0: - rect.top = y; - rect.bottom = rect.top+cy; - rect.left = x; - rect.right = rect.left+cx; - lines = -lines; - goto vertical_scroll; - case GDISP_ROTATE_90: - rect.top = x; - rect.bottom = rect.top+cx; - rect.right = GDISP.Height - y; - rect.left = rect.right-cy; - goto horizontal_scroll; - case GDISP_ROTATE_180: - rect.bottom = GDISP.Height - y; - rect.top = rect.bottom-cy; - rect.right = GDISP.Width - x; - rect.left = rect.right-cx; - vertical_scroll: - srect.left = frect.left = rect.left; - srect.right = frect.right = rect.right; - if (lines > 0) { - srect.top = frect.top = rect.top; - frect.bottom = rect.top+lines; - srect.bottom = rect.bottom-lines; - } else { - srect.bottom = frect.bottom = rect.bottom; - frect.top = rect.bottom+lines; - srect.top = rect.top-lines; - } - if (cy >= lines && cy >= -lines) - ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0); - break; - case GDISP_ROTATE_270: - rect.bottom = GDISP.Width - x; - rect.top = rect.bottom-cx; - rect.left = y; - rect.right = rect.left+cy; - lines = -lines; - horizontal_scroll: - srect.top = frect.top = rect.top; - srect.bottom = frect.bottom = rect.bottom; - if (lines > 0) { - srect.left = frect.left = rect.left; - frect.right = rect.left+lines; - srect.right = rect.right-lines; - } else { - srect.right = frect.right = rect.right; - frect.left = rect.right+lines; - srect.left = rect.left-lines; - } - if (cy >= lines && cy >= -lines) - ScrollDC(dcBuffer, lines, 0, &srect, 0, 0, 0); - break; - } - #else - rect.top = y; - rect.bottom = rect.top+cy; - rect.left = x; - rect.right = rect.left+cx; - lines = -lines; - srect.left = frect.left = rect.left; - srect.right = frect.right = rect.right; - if (lines > 0) { - srect.top = frect.top = rect.top; - frect.bottom = rect.top+lines; - srect.bottom = rect.bottom-lines; - } else { - srect.bottom = frect.bottom = rect.bottom; - frect.top = rect.bottom+lines; - srect.top = rect.top-lines; - } - if (cy >= lines && cy >= -lines) - ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0); - #endif - - if (hbr) - FillRect(dcBuffer, &frect, hbr); - InvalidateRect(winRootWindow, &rect, FALSE); - UpdateWindow(winRootWindow); - } -#endif - -#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) - /** - * @brief Driver Control - * @detail 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. - * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. - * GDISP_CONTROL_LLD - Low level driver control constants start at - * this value. - * - * @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) { - RECT rect; - - switch(what) { - case GDISP_CONTROL_ORIENTATION: - if (GDISP.Orientation == (gdisp_orientation_t)value) - return; - GetClientRect(winRootWindow, &rect); - switch((gdisp_orientation_t)value) { - case GDISP_ROTATE_0: - /* Code here */ - GDISP.Width = rect.right-rect.left; - GDISP.Height = rect.bottom - rect.top; - break; - case GDISP_ROTATE_90: - /* Code here */ - GDISP.Height = rect.right-rect.left; - GDISP.Width = rect.bottom - rect.top; - break; - case GDISP_ROTATE_180: - /* Code here */ - GDISP.Width = rect.right-rect.left; - GDISP.Height = rect.bottom - rect.top; - break; - case GDISP_ROTATE_270: - /* Code here */ - GDISP.Height = rect.right-rect.left; - GDISP.Width = rect.bottom - rect.top; - 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_POWER: - case GDISP_CONTROL_BACKLIGHT: - case GDISP_CONTROL_CONTRAST: -*/ - } - } -#endif - -#if GFX_USE_TOUCHSCREEN /*|| defined(__DOXYGEN__)*/ - -void ts_store_calibration_lld(struct cal_t *cal) { - (void) cal; - // Just ignore the calibration data - we implicitly know the calibration -} - -struct cal_t *ts_restore_calibration_lld(void) { - static struct cal_t cal = { 1.0, 0.0, 0.0, 0.0, 1.0, 0.0 }; - // Our x,y is always already calibrated. - return &cal; -} - -/** - * @brief Low level touchscreen driver initialization. - * - * @param[in] ts The touchscreen driver - * - * @notapi - */ -void ts_lld_init(const TouchscreenDriver *ts) { - (void) ts; - // Just ignore everything -} - -/** - * @brief Reads out the X direction. - * - * @notapi - */ -uint16_t ts_lld_read_x(void) { - return mousex; -} - -/** - * @brief Reads out the Y direction. - * - * @notapi - */ -uint16_t ts_lld_read_y(void) { - return mousey; -} - -/** - * @brief Reads out the Z direction. - * - * @notapi - */ -uint16_t ts_lld_read_z(void) { - return 0; -} - -/* - * @brief for checking if touchpad is pressed or not. - * - * @return 1 if pressed / 0 if not pressed - * - * @notapi - */ -uint8_t ts_lld_pressed(void) { - return (uint8_t)mousedn; -} - -#endif /* GFX_USE_TOUCHSCREEN */ - -#endif /* GFX_USE_GDISP */ -/** @} */ - diff --git a/drivers/gdisp/Win32/gdisp_lld.mk b/drivers/gdisp/Win32/gdisp_lld.mk deleted file mode 100644 index 57b15eb4..00000000 --- a/drivers/gdisp/Win32/gdisp_lld.mk +++ /dev/null @@ -1,5 +0,0 @@ -# List the required driver. -GFXSRC += $(GFXLIB)/drivers/gdisp/Win32/gdisp_lld.c - -# Required include directories -GFXINC += $(GFXLIB)/drivers/gdisp/Win32 diff --git a/drivers/gdisp/Win32/gdisp_lld_config.h b/drivers/gdisp/Win32/gdisp_lld_config.h deleted file mode 100644 index bf018eea..00000000 --- a/drivers/gdisp/Win32/gdisp_lld_config.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS-LCD-Driver. - - ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS-LCD-Driver is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file drivers/gdisp/Win32/gdisp_lld_config.h - * @brief GDISP Graphic Driver subsystem low level driver header for Win32. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_CONFIG_H -#define _GDISP_LLD_CONFIG_H - -#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ - -/*===========================================================================*/ -/* Driver hardware support. */ -/*===========================================================================*/ - -#define GDISP_DRIVER_NAME "Win32" -#define GDISP_LLD(x) gdisp_lld_##x##_Win32 - -#define GDISP_HARDWARE_LINES TRUE -#define GDISP_HARDWARE_FILLS TRUE -#define GDISP_HARDWARE_BITFILLS TRUE -#define GDISP_HARDWARE_SCROLL TRUE -#define GDISP_HARDWARE_PIXELREAD TRUE -#define GDISP_HARDWARE_CONTROL TRUE - -#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 - -#endif /* GFX_USE_GDISP */ - -#endif /* _GDISP_LLD_CONFIG_H */ -/** @} */ - diff --git a/drivers/gdisp/Win32/readme.txt b/drivers/gdisp/Win32/readme.txt deleted file mode 100644 index a475118b..00000000 --- a/drivers/gdisp/Win32/readme.txt +++ /dev/null @@ -1,21 +0,0 @@ -To use this driver: - -This driver is special in that it implements both the gdisp low level driver -and a touchscreen driver. - -1. Add in your halconf.h: - a) #define GFX_USE_GDISP TRUE - b) #define GFX_USE_TOUCHSCREEN TRUE - c) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD - d) All of the following (with appropriate values): - #define GDISP_SCREEN_WIDTH 640 - #define GDISP_SCREEN_HEIGHT 480 - - -2. To your makefile add the following lines: - include $(GFXLIB)/gfx.mk - include $(GFXLIB)/drivers/gdisp/Win32/gdisp_lld.mk - -3. Modify your makefile to add -lgdi32 to the DLIBS line. i.e. - DLIBS = -lws2_32 -lgdi32 - diff --git a/drivers/gdisp/Win32/touchscreen_lld_config.h b/drivers/gdisp/Win32/touchscreen_lld_config.h deleted file mode 100644 index ef5d5a27..00000000 --- a/drivers/gdisp/Win32/touchscreen_lld_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file drivers/gdisp/Win32/touchscreen_lld_config.h - * @brief Touchscreen Driver subsystem low level driver. - * - * @addtogroup TOUCHSCREEN - * @{ - */ - -#ifndef TOUCHSCREEN_LLD_CONFIG_H -#define TOUCHSCREEN_LLD_CONFIG_H - -#if GFX_USE_TOUCHSCREEN /*|| defined(__DOXYGEN__)*/ - -/*===========================================================================*/ -/* Driver hardware support. */ -/*===========================================================================*/ - -#define TOUCHSCREEN_HAS_PRESSED TRUE -#define TOUCHSCREEN_HAS_PRESSURE FALSE -#define TOUCHSCREEN_XY_INVERTED FALSE -#define TOUCHSCREEN_STORE_CALIBRATION TRUE -#define TOUCHSCREEN_CONVERSIONS 1 - -struct TouchscreenDriver {}; - -#endif /* GFX_USE_TOUCHSCREEN */ - -#endif /* TOUCHSCREEN_LLD_CONFIG_H */ -/** @} */ - diff --git a/drivers/ginput/toggle/Pal/ginput_lld.mk b/drivers/ginput/toggle/Pal/ginput_lld.mk new file mode 100644 index 00000000..d398da9d --- /dev/null +++ b/drivers/ginput/toggle/Pal/ginput_lld.mk @@ -0,0 +1,5 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/ginput/toggle/Pal/ginput_lld_toggle.c + +# Required include directories +GFXINC += $(GFXLIB)/drivers/ginput/toggle/Pal diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle.c b/drivers/ginput/toggle/Pal/ginput_lld_toggle.c new file mode 100644 index 00000000..98c2f61b --- /dev/null +++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle.c @@ -0,0 +1,62 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/togglePal/ginput_lld_toggle.c + * @brief GINPUT Toggle low level driver source for the ChibiOS PAL hardware. + * + * @addtogroup GINPUT_TOGGLE + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) /*|| defined(__DOXYGEN__)*/ + +// Declare the static members in the following include file +#define GINPUT_TOGGLE_DECLARE_CONFIG + +#include "lld/ginput/toggle.h" + +/** + * @brief Initialise the port. + * + * @param[in] ptc A pointer to one of the entries in GInputToggleConfigTable + * + * @notapi + */ +void ginput_lld_toggle_init(const GToggleConfig *ptc) { + palSetGroupMode(((IOBus *)ptc->id)->portid, ptc->mask, 0, ptc->mode); +} + +/** + * @brief Get the bits from the port. + * + * @param[in] ptc A pointer to one of the entries in GInputToggleConfigTable + * + * @notapi + */ +unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { + return palReadBus((IOBus *)ptc->id); +} + +#endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */ +/** @} */ diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h new file mode 100644 index 00000000..e8262b9a --- /dev/null +++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h @@ -0,0 +1,65 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/togglePal/ginput_lld_toggle_board_example.h + * @brief GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the example board. + * + * @addtogroup GINPUT_TOGGLE + * @{ + */ + +#ifndef _GDISP_LLD_TOGGLE_BOARD_H +#define _GDISP_LLD_TOGGLE_BOARD_H + +#ifndef _GINPUT_LLD_TOGGLE_CONFIG_H + // Visible in ginput.h + + #define GINPUT_TOGGLE_SW1 0 // Switch 1 + #define GINPUT_TOGGLE_SW2 1 // Switch 2 + #define GINPUT_TOGGLE_UP 2 // Joystick Up + #define GINPUT_TOGGLE_DOWN 3 // Joystick Down + #define GINPUT_TOGGLE_LEFT 4 // Joystick Left + #define GINPUT_TOGGLE_RIGHT 5 // Joystick Right + #define GINPUT_TOGGLE_CENTER 6 // Joystick Center + +#elif !defined(GINPUT_TOGGLE_DECLARE_CONFIG) + // Visible in ginput_lld.h + + #define GINPUT_TOGGLE_NUM_PORTS 7 // The total number of toggle inputs + +#else + // Visible in ginput_lld_toggle.c + + GToggleConfig GInputToggleConfigTable[] = { + {AT91C_BASE_PIOB, // Switch 1 and Switch 2 + PIOB_SW1_MASK|PIOB_SW2_MASK, + PIOB_SW1_MASK|PIOB_SW2_MASK, + PAL_MODE_INPUT}, + {AT91C_BASE_PIOA, // B1..4 Joystick + PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, + PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, + PAL_MODE_INPUT}, + }; + +#endif + +#endif /* _GDISP_LLD_TOGGLE_BOARD_H */ +/** @} */ diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h new file mode 100644 index 00000000..3858ad0c --- /dev/null +++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h @@ -0,0 +1,60 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/togglePal/ginput_lld_toggle_board_olimexsam7ex256.h + * @brief GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the Olimex SAM7EX256 board. + * + * @addtogroup GINPUT_TOGGLE + * @{ + */ + +#ifndef _GDISP_LLD_TOGGLE_BOARD_H +#define _GDISP_LLD_TOGGLE_BOARD_H + +#define GINPUT_TOGGLE_NUM_PORTS 7 // The total number of toggle inputs +#define GINPUT_TOGGLE_CONFIG_ENTRIES 2 // The total number of GToggleConfig entries + +#define GINPUT_TOGGLE_SW1 0 // Switch 1 +#define GINPUT_TOGGLE_SW2 1 // Switch 2 +#define GINPUT_TOGGLE_UP 2 // Joystick Up +#define GINPUT_TOGGLE_DOWN 3 // Joystick Down +#define GINPUT_TOGGLE_LEFT 4 // Joystick Left +#define GINPUT_TOGGLE_RIGHT 5 // Joystick Right +#define GINPUT_TOGGLE_CENTER 6 // Joystick Center + +#ifdef GINPUT_TOGGLE_DECLARE_CONFIG + // Visible in ginput_lld_toggle.c + + const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = { + {AT91C_BASE_PIOB, // Switch 1 and Switch 2 + PIOB_SW1_MASK|PIOB_SW2_MASK, + PIOB_SW1_MASK|PIOB_SW2_MASK, + PAL_MODE_INPUT}, + {AT91C_BASE_PIOA, // B1..4 Joystick + PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, + PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK, + PAL_MODE_INPUT}, + }; + +#endif + +#endif /* _GDISP_LLD_TOGGLE_BOARD_H */ +/** @} */ diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h new file mode 100644 index 00000000..f58221f9 --- /dev/null +++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h @@ -0,0 +1,44 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/togglePal/ginput_lld_toggle_config.h + * @brief GINPUT Toggle Driver configuration header. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GINPUT_LLD_TOGGLE_CONFIG_H +#define _GINPUT_LLD_TOGGLE_CONFIG_H + +#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE + +#if defined(BOARD_OLIMEX_SAM7_EX256) + #include "ginput_lld_toggle_board_olimexsam7ex256.h" +#else + /* Include the user supplied board definitions */ + #include "ginput_lld_toggle_board.h" +#endif + +#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */ + +#endif /* _GINPUT_LLD_TOGGLE_CONFIG_H */ +/** @} */ diff --git a/drivers/ginput/toggle/Pal/readme.txt b/drivers/ginput/toggle/Pal/readme.txt new file mode 100644 index 00000000..e6976f7d --- /dev/null +++ b/drivers/ginput/toggle/Pal/readme.txt @@ -0,0 +1,13 @@ +To use this driver: + +1. Add in your halconf.h: + a) #define GFX_USE_GINPUT TRUE + #define GINPUT_NEED_TOGGLE TRUE + d) If you are not using a known board then create a ginput_lld_toggle_board.h file + and ensure it is on your include path. + Use the ginput_lld_toggle_board_example.h file as a basis. + Currently known boards are: + Olimex SAM7-EX256 + +2. To your makefile add the following lines: + include $(GFXLIB)/drivers/ginput/togglePal/ginput_lld.mk diff --git a/drivers/ginput/touch/ADS7843/ginput_lld.mk b/drivers/ginput/touch/ADS7843/ginput_lld.mk new file mode 100644 index 00000000..b6ac0ea6 --- /dev/null +++ b/drivers/ginput/touch/ADS7843/ginput_lld.mk @@ -0,0 +1,5 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c + +# Required include directories +GFXINC += $(GFXLIB)/drivers/ginput/touch/ADS7843 diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c b/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c new file mode 100644 index 00000000..de32c493 --- /dev/null +++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c @@ -0,0 +1,139 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse.c + * @brief GINPUT Touch low level driver source for the ADS7843. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/ + +#include "lld/ginput/mouse.h" + +#if defined(GINPUT_MOUSE_USE_CUSTOM_BOARD) && GINPUT_MOUSE_USE_CUSTOM_BOARD + /* Include the user supplied board definitions */ + #include "ginput_lld_mouse_board.h" +//#elif defined(BOARD_OLIMEX_SAM7_EX256) +// #include "ginput_lld_mouse_board_olimexsam7ex256.h" +#else + #include "ginput_lld_mouse_board.h" +#endif + +static uint16_t sampleBuf[7]; +static coord_t lastx, lasty; + +/** + * @brief 7-point median filtering code for touch samples + * + * @note This is an internally used routine only. + * + * @notapi + */ +static void filter(void) { + uint16_t temp; + int i,j; + + for(i = 0; i < 4; i++) { + for(j = i; j < 7; j++) { + if(sampleBuf[i] > sampleBuf[j]) { + /* Swap the values */ + temp = sampleBuf[i]; + sampleBuf[i] = sampleBuf[j]; + sampleBuf[j] = temp; + } + } + } +} + +/** + * @brief Initialise the mouse/touch. + * + * @notapi + */ +void ginput_lld_mouse_init(void) { + init_board(); +} + +/** + * @brief Read the mouse/touch position. + * + * @param[in] pt A pointer to the structure to fill + * + * @note For drivers that don't support returning a position + * when the touch is up (most touch devices), it should + * return the previous position with the new Z value. + * The z value is the pressure for those touch devices + * that support it (-100 to 100 where > 0 is touched) + * or, 0 or 100 for those drivers that don't. + * + * @notapi + */ +void ginput_lld_mouse_get_reading(MouseReading *pt) { + // If touch-off return the previous results + if (!getpin_pressed()) { + pt->x = lastx; + pt->y = lasty; + pt->z = 0; + pt->buttons = 0; + return; + } + + // Read the port to get the touch settings + aquire_bus(); + + /* Get the X value + * Discard the first conversion - very noisy and keep the ADC on hereafter + * till we are done with the sampling. Note that PENIRQ is disabled while reading. + * Finally switch on PENIRQ once again - perform a dummy read. + * Once we have the readings, find the medium using our filter function + */ + read_value(0xD1); + for(i = 0; i < 7; i++) + sampleBuf[i] = read_value(0xD1); + read_value(0xD0); + filter(); + lastx = (coord_t)sampleBuf[3]; + + /* Get the Y value using the same process as above */ + read_value(0x91); + for(i = 0; i < 7; i++) + sampleBuf[i] = read_value(0x91); + read_value(0x90); + filter(); + lasty = (coord_t)sampleBuf[3]; + + // Release the bus + release_bus(); + + // Return the results + pt->x = lastx; + pt->y = lasty; + pt->z = 100; + pt->buttons = GINPUT_TOUCH_PRESSED; +} + +#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */ +/** @} */ diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h new file mode 100644 index 00000000..45563bee --- /dev/null +++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h @@ -0,0 +1,87 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_example.h + * @brief GINPUT Touch low level driver source for the ADS7843 on the example board. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ + +#ifndef _GINPUT_LLD_MOUSE_BOARD_H +#define _GINPUT_LLD_MOUSE_BOARD_H + +/** + * @brief Initialise the board for the touch. + * + * @notapi + */ +static __inline void init_board(void) { + /* Code here */ + #error "ginputADS7843: You must supply a definition for init_board for your board" +} + +/** + * @brief Check whether the surface is currently touched + * @return TRUE if the surface is currently touched + * + * @notapi + */ +static __inline bool_t getpin_pressed(void) { + /* Code here */ + #error "ginputADS7843: You must supply a definition for getpin_pressed for your board" +} + +/** + * @brief Aquire the bus ready for readings + * + * @notapi + */ +static __inline void aquire_bus(void) { + /* Code here */ + #error "ginputADS7843: You must supply a definition for aquire_bus for your board" +} + +/** + * @brief Release the bus after readings + * + * @notapi + */ +static __inline void release_bus(void) { + /* Code here */ + #error "ginputADS7843: You must supply a definition for release_bus for your board" +} + +/** + * @brief Read a value from touch controller + * @return The value read from the controller + * + * params[in] port The controller port to read. + * + * @notapi + */ +static __inline uint16_t read_value(uint16_t port) { + /* Code here */ + #error "ginputADS7843: You must supply a definition for read_value for your board" +} + +#endif /* _GINPUT_LLD_MOUSE_BOARD_H */ +/** @} */ diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_unknown.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_unknown.h new file mode 100644 index 00000000..2c23472a --- /dev/null +++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_unknown.h @@ -0,0 +1,97 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_unknown.h + * @brief GINPUT Touch low level driver source for the ADS7843 on some unknown board. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ + +#ifndef _GINPUT_LLD_MOUSE_BOARD_H +#define _GINPUT_LLD_MOUSE_BOARD_H + +/** + * @brief Initialise the board for the touch. + * + * @notapi + */ +static __inline void init_board(void) { + spiStart(TOUCH_SPIDriver, TOUCH_SPIConfig); +} + +/** + * @brief Check whether the surface is currently touched + * @return TRUE if the surface is currently touched + * + * @notapi + */ +static __inline bool_t getpin_pressed(void) { + return !palReadPad(TOUCH_PressedPort, TOUCH_PressedPin); +} + +/** + * @brief Aquire the bus ready for readings + * + * @notapi + */ +static __inline void aquire_bus(void) { + #if defined(SPI_USE_MUTUAL_EXCLUSION) + spiAcquireBus(TOUCH_SPIDriver); + #endif + + GINPUT_TOUCH_SPI_PROLOGUE(); + palClearPad(TOUCH_SPIConfig->ssport, TOUCH_SPIConfig->sspad); +} + +/** + * @brief Release the bus after readings + * + * @notapi + */ +static __inline void release_bus(void) { + palSetPad(TOUCH_SPIConfig->ssport, TOUCH_SPIConfig->sspad); + GINPUT_TOUCH_SPI_EPILOGUE(); + + #if defined(SPI_USE_MUTUAL_EXCLUSION) + spiReleaseBus(tsDriver->spip); + #endif +} + +/** + * @brief Read a value from touch controller + * @return The value read from the controller + * + * params[in] port The controller port to read. + * + * @notapi + */ +static __inline uint16_t read_value(uint16_t port) { + static uint8_t txbuf[3] = {0}; + static uint8_t rxbuf[3] = {0}; + + txbuf[0] = cmd; + spiExchange(TOUCH_SPIDriver, 3, txbuf, rxbuf); + return (rxbuf[1] << 5) | (rxbuf[2] >> 3); +} + +#endif /* _GINPUT_LLD_MOUSE_BOARD_H */ +/** @} */ diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h new file mode 100644 index 00000000..1ab568f5 --- /dev/null +++ b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h @@ -0,0 +1,41 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h + * @brief GINPUT LLD header file for mouse/touch driver. + * + * @addtogroup GINPUT_LLD_MOUSE + * @{ + */ +#ifndef _LLD_GINPUT_MOUSE_CONFIG_H +#define _LLD_GINPUT_MOUSE_CONFIG_H + +#define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH +#define GINPUT_MOUSE_NEED_CALIBRATION TRUE +#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE +#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 2 +#define GINPUT_MOUSE_READ_CYCLES 4 +#define GINPUT_MOUSE_POLL_PERIOD 100 +#define GINPUT_MOUSE_MAX_CLICK_JITTER 2 +#define GINPUT_MOUSE_MAX_MOVE_JITTER 2 +#define GINPUT_MOUSE_CLICK_TIME 700 + +#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */ +/** @} */ diff --git a/drivers/ginput/touch/ADS7843/readme.txt b/drivers/ginput/touch/ADS7843/readme.txt new file mode 100644 index 00000000..852a1ea0 --- /dev/null +++ b/drivers/ginput/touch/ADS7843/readme.txt @@ -0,0 +1,9 @@ +To use this driver: + +1. Add in your halconf.h: + a) #define GFX_USE_GINPUT TRUE + b) #define GINPUT_NEED_MOUSE TRUE + +2. To your makefile add the following lines: + include $(GFXLIB)/drivers/ginput/touch/ADS7843/ginput_lld.mk + diff --git a/drivers/ginput/touch/MCU/ginput_lld.mk b/drivers/ginput/touch/MCU/ginput_lld.mk new file mode 100644 index 00000000..eb8fb2d8 --- /dev/null +++ b/drivers/ginput/touch/MCU/ginput_lld.mk @@ -0,0 +1,5 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld_mouse.c + +# Required include directories +GFXINC += $(GFXLIB)/drivers/ginput/touch/MCU diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse.c b/drivers/ginput/touch/MCU/ginput_lld_mouse.c new file mode 100644 index 00000000..ac42033b --- /dev/null +++ b/drivers/ginput/touch/MCU/ginput_lld_mouse.c @@ -0,0 +1,136 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/touch/MCU/ginput_lld_mouse.c + * @brief GINPUT Touch low level driver source for the MCU. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/ + +#include "lld/ginput/touch.h" + +#if defined(GINPUT_MOUSE_USE_CUSTOM_BOARD) && GINPUT_MOUSE_USE_CUSTOM_BOARD + /* Include the user supplied board definitions */ + #include "ginput_lld_mouse_board.h" +//#elif defined(BOARD_OLIMEX_SAM7_EX256) +// #include "ginput_lld_mouse_board_olimexsam7ex256.h" +#else + #include "ginput_lld_mouse_board.h" +#endif + +static uint16_t sampleBuf[7]; +static coord_t lastx, lasty; + +/** + * @brief 7-point median filtering code for touchscreen samples + * + * @note This is an internally used routine only. + * + * @notapi + */ +static void filter(void) { + uint16_t temp; + int i,j; + + for(i = 0; i < 4; i++) { + for(j = i; j < 7; j++) { + if(sampleBuf[i] > sampleBuf[j]) { + /* Swap the values */ + temp = sampleBuf[i]; + sampleBuf[i] = sampleBuf[j]; + sampleBuf[j] = temp; + } + } + } +} + +/** + * @brief Initialise the mouse/touch. + * + * @notapi + */ +void ginput_lld_mouse_init(void) { + init_board(); +} + +/** + * @brief Read the mouse/touch position. + * + * @param[in] pt A pointer to the structure to fill + * + * @note For drivers that don't support returning a position + * when the touch is up (most touch devices), it should + * return the previous position with the new Z value. + * The z value is the pressure for those touch devices + * that support it (-100 to 100 where > 0 is touched) + * or, 0 or 100 for those drivers that don't. + * + * @notapi + */ +void ginput_lld_mouse_get_reading(MouseReading *pt) { + // If touch-off return the previous results + if (!getpin_pressed()) { + pt->x = lastx; + pt->y = lasty; + pt->z = 0; + pt->buttons = 0; + return; + } + + // Read the port to get the touch settings + aquire_bus(); + + /* Get the X value + * Discard the first conversion - very noisy and keep the ADC on hereafter + * till we are done with the sampling. + * Once we have the readings, find the medium using our filter function + */ + read_x_value(); + for(i = 0; i < 7; i++) + sampleBuf[i] = read_x_value(); + filter(); + lastx = (coord_t)sampleBuf[3]; + + /* Get the Y value using the same process as above */ + read_y_value(); + for(i = 0; i < 7; i++) + sampleBuf[i] = read_y_value(); + filter(); + lasty = (coord_t)sampleBuf[3]; + + // Release the bus + release_bus(); + + // Return the results + pt->x = lastx; + pt->y = lasty; + pt->z = 100; + pt->buttons = GINPUT_TOUCH_PRESSED; +} + +#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */ +/** @} */ diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h new file mode 100644 index 00000000..21e55e74 --- /dev/null +++ b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h @@ -0,0 +1,96 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/touch/MCU/ginput_lld_mouse_board_example.h + * @brief GINPUT Touch low level driver source for the MCU on the example board. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ + +#ifndef _GINPUT_LLD_MOUSE_BOARD_H +#define _GINPUT_LLD_MOUSE_BOARD_H + +/** + * @brief Initialise the board for the touch. + * + * @notapi + */ +static __inline void init_board(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for init_board for your board" +} + +/** + * @brief Check whether the surface is currently touched + * @return TRUE if the surface is currently touched + * + * @notapi + */ +static __inline bool_t getpin_pressed(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for getpin_pressed for your board" +} + +/** + * @brief Aquire the bus ready for readings + * + * @notapi + */ +static __inline void aquire_bus(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for aquire_bus for your board" +} + +/** + * @brief Release the bus after readings + * + * @notapi + */ +static __inline void release_bus(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for release_bus for your board" +} + +/** + * @brief Read an x value from touch controller + * @return The value read from the controller + * + * @notapi + */ +static __inline uint16_t read_x_value(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for read_x_value for your board" +} + +/** + * @brief Read an y value from touch controller + * @return The value read from the controller + * + * @notapi + */ +static __inline uint16_t read_y_value(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for read_y_value for your board" +} + +#endif /* _GINPUT_LLD_MOUSE_BOARD_H */ +/** @} */ diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_unknown.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_unknown.h new file mode 100644 index 00000000..4780806e --- /dev/null +++ b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_unknown.h @@ -0,0 +1,174 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/ginput/touch/MCU/ginput_lld_mouse_board_unknown.h + * @brief GINPUT Touch low level driver source for the MCU on some unknown board. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ + +#ifndef _GINPUT_LLD_MOUSE_BOARD_H +#define _GINPUT_LLD_MOUSE_BOARD_H + +#define ADC_NUM_CHANNELS 2 +#define ADC_BUF_DEPTH 1 + +static const ADCConversionGroup adc_y_config = { + FALSE, + ADC_NUM_CHANNELS, + NULL, + NULL, + 0, 0, + 0, 0, + ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS), + 0, + ADC_SQR3_SQ2_N(ADC_CHANNEL_IN12) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN13) +}; + +static const ADCConversionGroup adc_x_config = { + FALSE, + ADC_NUM_CHANNELS, + NULL, + NULL, + 0, 0, + 0, 0, + ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS), + 0, + ADC_SQR3_SQ2_N(ADC_CHANNEL_IN10) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN11) +}; + +/** + * @brief Initialise the board for the mouse/touch. + * + * @notapi + */ +static __inline void init_board(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for init_board for your board + + adcStart(ts->adc_driver, NULL); +} + +/** + * @brief Check whether the surface is currently touched + * @return TRUE if the surface is currently touched + * + * @notapi + */ +static __inline bool_t getpin_pressed(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for getpin_pressed for your board" + palSetPadMode(ts->yd_port, ts->yd_pin, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(ts->yu_port, ts->yu_pin, PAL_MODE_INPUT); + palSetPadMode(ts->xl_port, ts->xl_pin, PAL_MODE_INPUT); + palSetPadMode(ts->xr_port, ts->xr_pin, PAL_MODE_OUTPUT_PUSHPULL); + palSetPad(ts->xr_port, ts->xr_pin); + + return palReadPad(ts->yd_port, ts->yd_pin); +} + +/** + * @brief Aquire the bus ready for readings + * + * @notapi + */ +static __inline void aquire_bus(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for aquire_bus for your board" +} + +/** + * @brief Release the bus after readings + * + * @notapi + */ +static __inline void release_bus(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for release_bus for your board" +} + +/** + * @brief Read an x value from touch controller + * @return The value read from the controller + * + * @notapi + */ +static __inline uint16_t read_x_value(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for read_x_value for your board" + uint16_t val1, val2; + adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH]; + + palSetPadMode(ts->yd_port, ts->yd_pin, PAL_MODE_INPUT_ANALOG); + palSetPadMode(ts->yu_port, ts->yu_pin, PAL_MODE_INPUT_ANALOG); + palSetPadMode(ts->xl_port, ts->xl_pin, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(ts->xr_port, ts->xr_pin, PAL_MODE_OUTPUT_PUSHPULL); + + palSetPad(ts->xl_port, ts->xl_pin); + palClearPad(ts->xr_port, ts->xr_pin); + chThdSleepMilliseconds(1); + adcConvert(ts->adc_driver, &adc_x_config, samples, ADC_BUF_DEPTH); + val1 = ((samples[0] + samples[1])/2); + + palClearPad(ts->xl_port, ts->xl_pin); + palSetPad(ts->xr_port, ts->xr_pin); + chThdSleepMilliseconds(1); + adcConvert(ts->adc_driver, &adc_x_config, samples, ADC_BUF_DEPTH); + val2 = ((samples[0] + samples[1])/2); + + return ((val1+((1<<12)-val2))/4); +} + +/** + * @brief Read an y value from touch controller + * @return The value read from the controller + * + * @notapi + */ +static __inline uint16_t read_y_value(void) { + /* Code here */ + #error "ginputMCU: You must supply a definition for read_y_value for your board" + uint16_t val1, val2; + adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH]; + + palSetPadMode(ts->xl_port, ts->xl_pin, PAL_MODE_INPUT_ANALOG); + palSetPadMode(ts->xr_port, ts->xr_pin, PAL_MODE_INPUT_ANALOG); + palSetPadMode(ts->yd_port, ts->yd_pin, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(ts->yu_port, ts->yu_pin, PAL_MODE_OUTPUT_PUSHPULL); + + palSetPad(ts->yu_port, ts->yu_pin); + palClearPad(ts->yd_port, ts->yd_pin); + chThdSleepMilliseconds(1); + adcConvert(ts->adc_driver, &adc_y_config, samples, ADC_BUF_DEPTH); + val1 = ((samples[0] + samples[1])/2); + + palClearPad(ts->yu_port, ts->yu_pin); + palSetPad(ts->yd_port, ts->yd_pin); + chThdSleepMilliseconds(1); + adcConvert(ts->adc_driver, &adc_y_config, samples, ADC_BUF_DEPTH); + val2 = ((samples[0] + samples[1])/2); + + return ((val1+((1<<12)-val2))/4); +} + +#endif /* _GINPUT_LLD_MOUSE_BOARD_H */ +/** @} */ diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_config.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_config.h new file mode 100644 index 00000000..d56be229 --- /dev/null +++ b/drivers/ginput/touch/MCU/ginput_lld_mouse_config.h @@ -0,0 +1,41 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file drivers/ginput/touch/MCU/ginput_lld_mouse_config.h + * @brief GINPUT LLD header file for touch driver. + * + * @addtogroup GINPUT_LLD_MOUSE + * @{ + */ +#ifndef _LLD_GINPUT_MOUSE_CONFIG_H +#define _LLD_GINPUT_MOUSE_CONFIG_H + +#define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH +#define GINPUT_MOUSE_NEED_CALIBRATION TRUE +#define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE +#define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 2 +#define GINPUT_MOUSE_READ_CYCLES 4 +#define GINPUT_MOUSE_POLL_PERIOD 100 +#define GINPUT_MOUSE_MAX_CLICK_JITTER 2 +#define GINPUT_MOUSE_MAX_MOVE_JITTER 2 +#define GINPUT_MOUSE_CLICK_TIME 700 + +#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */ +/** @} */ diff --git a/drivers/ginput/touch/MCU/readme.txt b/drivers/ginput/touch/MCU/readme.txt new file mode 100644 index 00000000..4dbe5543 --- /dev/null +++ b/drivers/ginput/touch/MCU/readme.txt @@ -0,0 +1,9 @@ +To use this driver: + +1. Add in your halconf.h: + a) #define GFX_USE_GINPUT TRUE + b) #define GINPUT_NEED_MOUSE TRUE + +2. To your makefile add the following lines: + include $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld.mk + diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c new file mode 100644 index 00000000..72ad0554 --- /dev/null +++ b/drivers/multiple/Win32/gdisp_lld.c @@ -0,0 +1,910 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/gdisp/Win32/gdisp_lld.c + * @brief GDISP Graphics Driver subsystem low level driver source for Win32. + * + * @addtogroup GDISP + * @{ + */ + +#include "ch.h" +#include "hal.h" +#include "gdisp.h" + +#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ + +/* Include mouse support code */ +#include "lld/ginput/mouse.h" + +/* Include the emulation code for things we don't support */ +#include "lld/gdisp/emulation.c" + +#include +#include +#include +#include +#include +#include + +/*===========================================================================*/ +/* Driver local routines . */ +/*===========================================================================*/ + +#define WIN32_USE_MSG_REDRAW FALSE + +#define APP_NAME "GDISP" + +#define COLOR2BGR(c) ((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF)) +#define BGR2COLOR(c) COLOR2BGR(c) + +static HWND winRootWindow = NULL; +static HDC dcBuffer = NULL; +static HBITMAP dcBitmap = NULL; +static HBITMAP dcOldBitmap; +static volatile bool_t isReady = FALSE; +static coord_t mousex, mousey; +static uint16_t mousebuttons; + +static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + HDC dc; + PAINTSTRUCT ps; + + switch (Msg) { + case WM_CREATE: + break; +#if GINPUT_NEED_MOUSE + case WM_LBUTTONDOWN: + mousebuttons = 0x0001; + goto mousemove; + case WM_LBUTTONUP: + mousebuttons &= ~0x0001; + goto mousemove; + case WM_MBUTTONDOWN: + mousebuttons = 0x0004; + goto mousemove; + case WM_MBUTTONUP: + mousebuttons &= ~0x0004; + goto mousemove; + case WM_RBUTTONDOWN: + mousebuttons = 0x0002; + goto mousemove; + case WM_RBUTTONUP: + mousebuttons &= ~0x0002; + goto mousemove; + case WM_MOUSEMOVE: + mousemove: + mousex = (coord_t)LOWORD(lParam); + mousey = (coord_t)HIWORD(lParam); + #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE + ginputMouseWakeup(); + #endif + break; +#endif + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + case WM_SYSKEYUP: + case WM_KEYUP: + break; + case WM_CHAR: + case WM_DEADCHAR: + case WM_SYSCHAR: + case WM_SYSDEADCHAR: + break; + case WM_PAINT: + dc = BeginPaint(hWnd, &ps); + BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top, + ps.rcPaint.right - ps.rcPaint.left, + ps.rcPaint.bottom - ps.rcPaint.top, + dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); + EndPaint(hWnd, &ps); + break; + case WM_DESTROY: + PostQuitMessage(0); + SelectObject(dcBuffer, dcOldBitmap); + DeleteDC(dcBuffer); + DeleteObject(dcBitmap); + winRootWindow = NULL; + break; + default: + return DefWindowProc(hWnd, Msg, wParam, lParam); + } + return 0; +} + +static DWORD WINAPI WindowThread(LPVOID lpParameter) { + (void)lpParameter; + + MSG msg; + HANDLE hInstance; + WNDCLASS wc; + RECT rect; + HDC dc; + + hInstance = GetModuleHandle(NULL); + + wc.style = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)myWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = APP_NAME; + RegisterClass(&wc); + + rect.top = 0; rect.bottom = GDISP.Height; + rect.left = 0; rect.right = GDISP.Width; + AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0); + winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0, + rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL); + assert(winRootWindow != NULL); + + + GetClientRect(winRootWindow, &rect); + GDISP.Width = rect.right-rect.left; + GDISP.Height = rect.bottom - rect.top; + + dc = GetDC(winRootWindow); + dcBitmap = CreateCompatibleBitmap(dc, GDISP.Width, GDISP.Height); + dcBuffer = CreateCompatibleDC(dc); + ReleaseDC(winRootWindow, dc); + dcOldBitmap = SelectObject(dcBuffer, dcBitmap); + + ShowWindow(winRootWindow, SW_SHOW); + UpdateWindow(winRootWindow); + isReady = TRUE; + + while(GetMessage(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ExitProcess(0); + return msg.wParam; +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/* ---- Required Routines ---- */ +/* + The following 2 routines are required. + All other routines are optional. +*/ + +/** + * @brief Low level GDISP driver initialisation. + * @return TRUE if successful, FALSE on error. + * + * @notapi + */ +bool_t GDISP_LLD(init)(void) { + RECT rect; + + /* Set the window dimensions */ + GetWindowRect(GetDesktopWindow(), &rect); + GDISP.Width = rect.right - rect.left; + GDISP.Height = rect.bottom - rect.top; + if (GDISP.Width > GDISP_SCREEN_WIDTH) + GDISP.Width = GDISP_SCREEN_WIDTH; + if (GDISP.Height > GDISP_SCREEN_HEIGHT) + GDISP.Height = GDISP_SCREEN_HEIGHT; + + /* Initialise the window */ + CreateThread(0, 0, WindowThread, 0, 0, 0); + while (!isReady) + Sleep(1); + + /* Initialise the GDISP structure to match */ + GDISP.Orientation = GDISP_ROTATE_0; + GDISP.Powermode = powerOn; + GDISP.Backlight = 100; + GDISP.Contrast = 50; + #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(drawpixel)(coord_t x, coord_t y, color_t color) { + HDC dc; + #if WIN32_USE_MSG_REDRAW + RECT rect; + #endif + #if GDISP_NEED_CONTROL + coord_t t; + #endif + + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + // Clip pre orientation change + if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return; + #endif + + #if GDISP_NEED_CONTROL + switch(GDISP.Orientation) { + case GDISP_ROTATE_0: + break; + case GDISP_ROTATE_90: + t = GDISP.Height - 1 - y; + y = x; + x = t; + break; + case GDISP_ROTATE_180: + x = GDISP.Width - 1 - x; + y = GDISP.Height - 1 - y; + break; + case GDISP_ROTATE_270: + t = GDISP.Width - 1 - x; + x = y; + y = t; + break; + } + #endif + + // Draw the pixel in the buffer + color = COLOR2BGR(color); + SetPixel(dcBuffer, x, y, color); + + #if WIN32_USE_MSG_REDRAW + rect.left = x; rect.right = x+1; + rect.top = y; rect.bottom = y+1; + InvalidateRect(winRootWindow, &rect, FALSE); + UpdateWindow(winRootWindow); + #else + // Draw the pixel again directly on the screen. + // This is cheaper than invalidating a single pixel in the window + dc = GetDC(winRootWindow); + SetPixel(dc, x, y, color); + ReleaseDC(winRootWindow, dc); + #endif +} + +/* ---- Optional Routines ---- */ + +#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__) + /** + * @brief Draw a line. + * @note Optional - The high level driver can emulate using software. + * + * @param[in] x0, y0 The start of the line + * @param[in] x1, y1 The end of the line + * @param[in] color The color of the line + * + * @notapi + */ + void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { + POINT p; + HPEN pen; + HDC dc; + HGDIOBJ old; + #if GDISP_NEED_CLIP + HRGN clip; + #endif + #if WIN32_USE_MSG_REDRAW + RECT rect; + #endif + #if GDISP_NEED_CONTROL + coord_t t; + #endif + + #if GDISP_NEED_CLIP + clip = NULL; + #endif + + #if GDISP_NEED_CONTROL + switch(GDISP.Orientation) { + case GDISP_ROTATE_0: + #if GDISP_NEED_CLIP + // Clip post orientation change + if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) + clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1); + #endif + break; + case GDISP_ROTATE_90: + t = GDISP.Height - 1 - y0; + y0 = x0; + x0 = t; + t = GDISP.Height - 1 - y1; + y1 = x1; + x1 = t; + #if GDISP_NEED_CLIP + // Clip post orientation change + if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) + clip = CreateRectRgn(GDISP.Height-1-GDISP.clipy1, GDISP.clipx0, GDISP.Height-1-GDISP.clipy0, GDISP.clipx1); + #endif + break; + case GDISP_ROTATE_180: + x0 = GDISP.Width - 1 - x0; + y0 = GDISP.Height - 1 - y0; + x1 = GDISP.Width - 1 - x1; + y1 = GDISP.Height - 1 - y1; + #if GDISP_NEED_CLIP + // Clip post orientation change + if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) + clip = CreateRectRgn(GDISP.Width-1-GDISP.clipx1, GDISP.Height-1-GDISP.clipy1, GDISP.Width-1-GDISP.clipx0, GDISP.Height-1-GDISP.clipy0); + #endif + break; + case GDISP_ROTATE_270: + t = GDISP.Width - 1 - x0; + x0 = y0; + y0 = t; + t = GDISP.Width - 1 - x1; + x1 = y1; + y1 = t; + #if GDISP_NEED_CLIP + // Clip post orientation change + if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) + clip = CreateRectRgn(GDISP.clipy0, GDISP.Width-1-GDISP.clipx1, GDISP.clipy1, GDISP.Width-1-GDISP.clipx0); + #endif + break; + } + #else + #if GDISP_NEED_CLIP + clip = NULL; + if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height) + clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1); + #endif + #endif + + color = COLOR2BGR(color); + pen = CreatePen(PS_SOLID, 1, color); + if (pen) { + // Draw the line in the buffer + #if GDISP_NEED_CLIP + if (clip) SelectClipRgn(dcBuffer, clip); + #endif + old = SelectObject(dcBuffer, pen); + MoveToEx(dcBuffer, x0, y0, &p); + LineTo(dcBuffer, x1, y1); + SelectObject(dcBuffer, old); + SetPixel(dcBuffer, x1, y1, color); + #if GDISP_NEED_CLIP + if (clip) SelectClipRgn(dcBuffer, NULL); + #endif + + #if WIN32_USE_MSG_REDRAW + rect.left = x0; rect.right = x1+1; + rect.top = y0; rect.bottom = y1+1; + InvalidateRect(winRootWindow, &rect, FALSE); + UpdateWindow(winRootWindow); + #else + // Redrawing the line on the screen is cheaper than invalidating the whole rectangular area + dc = GetDC(winRootWindow); + #if GDISP_NEED_CLIP + if (clip) SelectClipRgn(dc, clip); + #endif + old = SelectObject(dc, pen); + MoveToEx(dc, x0, y0, &p); + LineTo(dc, x1, y1); + SelectObject(dc, old); + SetPixel(dc, x1, y1, color); + #if GDISP_NEED_CLIP + if (clip) SelectClipRgn(dc, NULL); + #endif + ReleaseDC(winRootWindow, dc); + #endif + + DeleteObject(pen); + } + } +#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(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + HDC dc; + RECT rect; + HBRUSH hbr; + + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + // Clip pre orientation change + 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 + + #if GDISP_NEED_CONTROL + switch(GDISP.Orientation) { + case GDISP_ROTATE_0: + rect.top = y; + rect.bottom = rect.top+cy; + rect.left = x; + rect.right = rect.left+cx; + break; + case GDISP_ROTATE_90: + rect.top = x; + rect.bottom = rect.top+cx; + rect.right = GDISP.Height - y; + rect.left = rect.right-cy; + break; + case GDISP_ROTATE_180: + rect.bottom = GDISP.Height - y; + rect.top = rect.bottom-cy; + rect.right = GDISP.Width - x; + rect.left = rect.right-cx; + break; + case GDISP_ROTATE_270: + rect.bottom = GDISP.Width - x; + rect.top = rect.bottom-cx; + rect.left = y; + rect.right = rect.left+cy; + break; + } + #else + rect.top = y; + rect.bottom = rect.top+cy; + rect.left = x; + rect.right = rect.left+cx; + #endif + + color = COLOR2BGR(color); + hbr = CreateSolidBrush(color); + + if (hbr) { + // Fill the area + FillRect(dcBuffer, &rect, hbr); + + #if WIN32_USE_MSG_REDRAW + InvalidateRect(winRootWindow, &rect, FALSE); + UpdateWindow(winRootWindow); + #else + // Filling the area directly on the screen is likely to be cheaper than invalidating it + dc = GetDC(winRootWindow); + FillRect(dc, &rect, hbr); + ReleaseDC(winRootWindow, dc); + #endif + + DeleteObject(hbr); + } + } +#endif + +#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__) + static pixel_t *rotateimg(coord_t cx, coord_t cy, coord_t srcx, coord_t srccx, const pixel_t *buffer) { + pixel_t *dstbuf; + pixel_t *dst; + const pixel_t *src; + size_t sz; + coord_t i, j; + + // Shortcut. + if (GDISP.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx) + return (pixel_t *)buffer; + + // Allocate the destination buffer + sz = (size_t)cx * (size_t)cy; + if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t)))) + return 0; + + // Copy the bits we need + switch(GDISP.Orientation) { + case GDISP_ROTATE_0: + for(dst = dstbuf, src = buffer+srcx, j = 0; j < cy; j++) + for(i = 0; i < cx; i++, src += srccx - cx) + *dst++ = *src++; + break; + case GDISP_ROTATE_90: + for(src = buffer+srcx, j = 0; j < cy; j++) { + dst = dstbuf+cy-j-1; + for(i = 0; i < cx; i++, src += srccx - cx, dst += cy) + *dst = *src++; + } + break; + case GDISP_ROTATE_180: + for(dst = dstbuf+sz, src = buffer+srcx, j = 0; j < cy; j++) + for(i = 0; i < cx; i++, src += srccx - cx) + *--dst = *src++; + break; + case GDISP_ROTATE_270: + for(src = buffer+srcx, j = 0; j < cy; j++) { + dst = dstbuf+sz-cy+j; + for(i = 0; i < cx; i++, src += srccx - cx, dst -= cy) + *dst = *src++; + } + break; + } + return dstbuf; + } + + /** + * @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(blitareaex)(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) { + BITMAPV4HEADER bmpInfo; + RECT rect; + #if GDISP_NEED_CONTROL + pixel_t *srcimg; + #endif + + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + // Clip pre orientation change + 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 + + // Make everything relative to the start of the line + buffer += srccx*srcy; + srcy = 0; + + memset(&bmpInfo, 0, sizeof(bmpInfo)); + bmpInfo.bV4Size = sizeof(bmpInfo); + bmpInfo.bV4Planes = 1; + bmpInfo.bV4BitCount = 32; + bmpInfo.bV4AlphaMask = 0; + bmpInfo.bV4RedMask = RGB2COLOR(255,0,0); + bmpInfo.bV4GreenMask = RGB2COLOR(0,255,0); + bmpInfo.bV4BlueMask = RGB2COLOR(0,0,255); + bmpInfo.bV4V4Compression = BI_BITFIELDS; + bmpInfo.bV4XPelsPerMeter = 3078; + bmpInfo.bV4YPelsPerMeter = 3078; + bmpInfo.bV4ClrUsed = 0; + bmpInfo.bV4ClrImportant = 0; + bmpInfo.bV4CSType = 0; //LCS_sRGB; + + #if GDISP_NEED_CONTROL + bmpInfo.bV4SizeImage = (cy*cx) * sizeof(pixel_t); + srcimg = rotateimg(cx, cy, srcx, srccx, buffer); + if (!srcimg) return; + + switch(GDISP.Orientation) { + case GDISP_ROTATE_0: + bmpInfo.bV4Width = cx; + bmpInfo.bV4Height = -cy; /* top-down image */ + rect.top = y; + rect.bottom = rect.top+cy; + rect.left = x; + rect.right = rect.left+cx; + break; + case GDISP_ROTATE_90: + bmpInfo.bV4Width = cy; + bmpInfo.bV4Height = -cx; /* top-down image */ + rect.top = x; + rect.bottom = rect.top+cx; + rect.right = GDISP.Height - y; + rect.left = rect.right-cy; + break; + case GDISP_ROTATE_180: + bmpInfo.bV4Width = cx; + bmpInfo.bV4Height = -cy; /* top-down image */ + rect.bottom = GDISP.Height - y; + rect.top = rect.bottom-cy; + rect.right = GDISP.Width - x; + rect.left = rect.right-cx; + break; + case GDISP_ROTATE_270: + bmpInfo.bV4Width = cy; + bmpInfo.bV4Height = -cx; /* top-down image */ + rect.bottom = GDISP.Width - x; + rect.top = rect.bottom-cx; + rect.left = y; + rect.right = rect.left+cy; + break; + } + SetDIBitsToDevice(dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); + if (srcimg != (pixel_t *)buffer) + free(srcimg); + + #else + bmpInfo.bV4Width = srccx; + bmpInfo.bV4Height = -cy; /* top-down image */ + bmpInfo.bV4SizeImage = (cy*srccx) * sizeof(pixel_t); + rect.top = y; + rect.bottom = rect.top+cy; + rect.left = x; + rect.right = rect.left+cx; + SetDIBitsToDevice(dcBuffer, x, y, cx, cy, srcx, 0, 0, cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS); + #endif + + // Invalidate the region to get it on the screen. + InvalidateRect(winRootWindow, &rect, FALSE); + UpdateWindow(winRootWindow); + } +#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. + * @return The color of the specified pixel. + * + * @param[in] x, y The start of the text + * + * @notapi + */ + color_t GDISP_LLD(getpixelcolor)(coord_t x, coord_t y) { + color_t color; + + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + // Clip pre orientation change + if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0; + #endif + + #if GDISP_NEED_CONTROL + switch(GDISP.Orientation) { + case GDISP_ROTATE_90: + t = GDISP.Height - 1 - y; + y = x; + x = t; + break; + case GDISP_ROTATE_180: + x = GDISP.Width - 1 - x; + y = GDISP.Height - 1 - y; + break; + case GDISP_ROTATE_270: + t = GDISP.Width - 1 - x; + x = y; + y = t; + break; + } + #endif + + color = GetPixel(dcBuffer, x, y); + return BGR2COLOR(color); + } +#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(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { + RECT rect, frect, srect; + HBRUSH hbr; + + #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + // Clip pre orientation change + 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 + + if (lines > cy) lines = cy; + else if (-lines > cy) lines = -cy; + + bgcolor = COLOR2BGR(bgcolor); + hbr = CreateSolidBrush(bgcolor); + + #if GDISP_NEED_CONTROL + switch(GDISP.Orientation) { + case GDISP_ROTATE_0: + rect.top = y; + rect.bottom = rect.top+cy; + rect.left = x; + rect.right = rect.left+cx; + lines = -lines; + goto vertical_scroll; + case GDISP_ROTATE_90: + rect.top = x; + rect.bottom = rect.top+cx; + rect.right = GDISP.Height - y; + rect.left = rect.right-cy; + goto horizontal_scroll; + case GDISP_ROTATE_180: + rect.bottom = GDISP.Height - y; + rect.top = rect.bottom-cy; + rect.right = GDISP.Width - x; + rect.left = rect.right-cx; + vertical_scroll: + srect.left = frect.left = rect.left; + srect.right = frect.right = rect.right; + if (lines > 0) { + srect.top = frect.top = rect.top; + frect.bottom = rect.top+lines; + srect.bottom = rect.bottom-lines; + } else { + srect.bottom = frect.bottom = rect.bottom; + frect.top = rect.bottom+lines; + srect.top = rect.top-lines; + } + if (cy >= lines && cy >= -lines) + ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0); + break; + case GDISP_ROTATE_270: + rect.bottom = GDISP.Width - x; + rect.top = rect.bottom-cx; + rect.left = y; + rect.right = rect.left+cy; + lines = -lines; + horizontal_scroll: + srect.top = frect.top = rect.top; + srect.bottom = frect.bottom = rect.bottom; + if (lines > 0) { + srect.left = frect.left = rect.left; + frect.right = rect.left+lines; + srect.right = rect.right-lines; + } else { + srect.right = frect.right = rect.right; + frect.left = rect.right+lines; + srect.left = rect.left-lines; + } + if (cy >= lines && cy >= -lines) + ScrollDC(dcBuffer, lines, 0, &srect, 0, 0, 0); + break; + } + #else + rect.top = y; + rect.bottom = rect.top+cy; + rect.left = x; + rect.right = rect.left+cx; + lines = -lines; + srect.left = frect.left = rect.left; + srect.right = frect.right = rect.right; + if (lines > 0) { + srect.top = frect.top = rect.top; + frect.bottom = rect.top+lines; + srect.bottom = rect.bottom-lines; + } else { + srect.bottom = frect.bottom = rect.bottom; + frect.top = rect.bottom+lines; + srect.top = rect.top-lines; + } + if (cy >= lines && cy >= -lines) + ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0); + #endif + + if (hbr) + FillRect(dcBuffer, &frect, hbr); + InvalidateRect(winRootWindow, &rect, FALSE); + UpdateWindow(winRootWindow); + } +#endif + +#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__) + /** + * @brief Driver Control + * @detail 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. + * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. + * GDISP_CONTROL_LLD - Low level driver control constants start at + * this value. + * + * @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) { + RECT rect; + + switch(what) { + case GDISP_CONTROL_ORIENTATION: + if (GDISP.Orientation == (gdisp_orientation_t)value) + return; + GetClientRect(winRootWindow, &rect); + switch((gdisp_orientation_t)value) { + case GDISP_ROTATE_0: + /* Code here */ + GDISP.Width = rect.right-rect.left; + GDISP.Height = rect.bottom - rect.top; + break; + case GDISP_ROTATE_90: + /* Code here */ + GDISP.Height = rect.right-rect.left; + GDISP.Width = rect.bottom - rect.top; + break; + case GDISP_ROTATE_180: + /* Code here */ + GDISP.Width = rect.right-rect.left; + GDISP.Height = rect.bottom - rect.top; + break; + case GDISP_ROTATE_270: + /* Code here */ + GDISP.Height = rect.right-rect.left; + GDISP.Width = rect.bottom - rect.top; + 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_POWER: + case GDISP_CONTROL_BACKLIGHT: + case GDISP_CONTROL_CONTRAST: +*/ + } + } +#endif + +#if GINPUT_NEED_MOUSE + +#include "lld/ginput/mouse.h" + +void ginput_lld_mouse_init(void) {} + +void ginput_lld_mouse_get_reading(MouseReading *pt) { + pt->x = mousex; + pt->y = mousey; + pt->z = (mousebuttons & 0x0001) ? 100 : 0; + pt->buttons = mousebuttons; // We auto-magicaly know that the mousebutton bits match the MouseReading bits. +} + +#endif /* GINPUT_NEED_MOUSE */ + +#endif /* GFX_USE_GDISP */ +/** @} */ + diff --git a/drivers/multiple/Win32/gdisp_lld.mk b/drivers/multiple/Win32/gdisp_lld.mk new file mode 100644 index 00000000..b116088b --- /dev/null +++ b/drivers/multiple/Win32/gdisp_lld.mk @@ -0,0 +1,5 @@ +# List the required driver. +GFXSRC += $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.c + +# Required include directories +GFXINC += $(GFXLIB)/drivers/multiple/Win32 diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h new file mode 100644 index 00000000..bf018eea --- /dev/null +++ b/drivers/multiple/Win32/gdisp_lld_config.h @@ -0,0 +1,54 @@ +/* + ChibiOS/RT - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS-LCD-Driver. + + ChibiOS-LCD-Driver is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS-LCD-Driver is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file drivers/gdisp/Win32/gdisp_lld_config.h + * @brief GDISP Graphic Driver subsystem low level driver header for Win32. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_CONFIG_H +#define _GDISP_LLD_CONFIG_H + +#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/ + +/*===========================================================================*/ +/* Driver hardware support. */ +/*===========================================================================*/ + +#define GDISP_DRIVER_NAME "Win32" +#define GDISP_LLD(x) gdisp_lld_##x##_Win32 + +#define GDISP_HARDWARE_LINES TRUE +#define GDISP_HARDWARE_FILLS TRUE +#define GDISP_HARDWARE_BITFILLS TRUE +#define GDISP_HARDWARE_SCROLL TRUE +#define GDISP_HARDWARE_PIXELREAD TRUE +#define GDISP_HARDWARE_CONTROL TRUE + +#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 + +#endif /* GFX_USE_GDISP */ + +#endif /* _GDISP_LLD_CONFIG_H */ +/** @} */ + diff --git a/drivers/multiple/Win32/ginput_lld_mouse_config.h b/drivers/multiple/Win32/ginput_lld_mouse_config.h new file mode 100644 index 00000000..bf063d6d --- /dev/null +++ b/drivers/multiple/Win32/ginput_lld_mouse_config.h @@ -0,0 +1,58 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file drivers/gdisp/Win32/ginput_lld_mouse_config.h + * @brief GINPUT LLD header file for mouse/touch driver. + * + * @addtogroup GINPUT_LLD_MOUSE + * @{ + */ +#ifndef _LLD_GINPUT_MOUSE_CONFIG_H +#define _LLD_GINPUT_MOUSE_CONFIG_H + +// This driver supports being both a mouse or a touch device (we don't actually know which it really is) +// When operating in mouse mode a long left button click does not generate a context click. +// When operating in touch mode we allow sloppier clicks etc +#if GINPUT_NEED_MOUSE + #define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE + #define GINPUT_MOUSE_CLICK_TIME TIME_INFINITE // Long click != Context Click + #define GINPUT_MOUSE_NEED_CALIBRATION FALSE + #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE + #define GINPUT_MOUSE_READ_CYCLES 1 + #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1 + #define GINPUT_MOUSE_MAX_CLICK_JITTER 0 + #define GINPUT_MOUSE_MAX_MOVE_JITTER 0 +#else + #define GINPUT_MOUSE_EVENT_TYPE GEVENT_TOUCH + #define GINPUT_MOUSE_CLICK_TIME 700 // Long click = Context Click + #define GINPUT_MOUSE_NEED_CALIBRATION FALSE // Can be set to TRUE just for testing + #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE + #define GINPUT_MOUSE_READ_CYCLES 1 + #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR 2 + #define GINPUT_MOUSE_MAX_CLICK_JITTER 2 + #define GINPUT_MOUSE_MAX_MOVE_JITTER 2 +#endif + +// This driver supports both an "interrupt" mode, and a polled mode +#define GINPUT_MOUSE_POLL_PERIOD TIME_INFINITE // Interrupt driven by the Window thread +//#define GINPUT_MOUSE_POLL_PERIOD 100 // Poll driven + +#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */ +/** @} */ diff --git a/drivers/multiple/Win32/readme.txt b/drivers/multiple/Win32/readme.txt new file mode 100644 index 00000000..6151f2f2 --- /dev/null +++ b/drivers/multiple/Win32/readme.txt @@ -0,0 +1,22 @@ +To use this driver: + +This driver is special in that it implements both the gdisp low level driver +and a touchscreen driver. + +1. Add in your halconf.h: + a) #define GFX_USE_GDISP TRUE + b) #define GFX_USE_GINPUT TRUE + #define GINPUT_USE_MOUSE TRUE + c) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD + d) All of the following (with appropriate values): + #define GDISP_SCREEN_WIDTH 640 + #define GDISP_SCREEN_HEIGHT 480 + + +2. To your makefile add the following lines: + include $(GFXLIB)/gfx.mk + include $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.mk + +3. Modify your makefile to add -lgdi32 to the DLIBS line. i.e. + DLIBS = -lws2_32 -lgdi32 + diff --git a/gfx.mk b/gfx.mk index 6f199fb0..8b369958 100644 --- a/gfx.mk +++ b/gfx.mk @@ -7,9 +7,11 @@ GFXSRC += $(GFXLIB)/src/gdisp.c \ $(GFXLIB)/src/gdisp_fonts.c \ $(GFXLIB)/src/gevent.c \ $(GFXLIB)/src/gtimer.c \ - $(GFXLIB)/src/ginput.c \ $(GFXLIB)/src/gwin.c \ $(GFXLIB)/src/touchscreen.c \ $(GFXLIB)/src/graph.c \ GFXINC += $(GFXLIB)/include + +include $(GFXLIB)/src/gwin/gwin.mk +include $(GFXLIB)/src/ginput/ginput.mk diff --git a/include/gdisp.h b/include/gdisp.h index 7656e777..53848e16 100644 --- a/include/gdisp.h +++ b/include/gdisp.h @@ -114,7 +114,7 @@ /*===========================================================================*/ /* Include the low level driver information */ -#include "gdisp_lld.h" +#include "lld/gdisp/gdisp_lld.h" /*===========================================================================*/ /* Type definitions */ diff --git a/include/gdisp/fonts.h b/include/gdisp/fonts.h new file mode 100644 index 00000000..e3b07e86 --- /dev/null +++ b/include/gdisp/fonts.h @@ -0,0 +1,92 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @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 maximum height of a font. + * @details Either 16 or 32. Defaults to 16 + * @note Setting this to 32 causes the font tables to take + * twice the internal program memory. + */ +#ifndef GDISP_MAX_FONT_HEIGHT + #define GDISP_MAX_FONT_HEIGHT 16 +#endif + +/** + * @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 { + 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; +}; + +/** + * @brief Macros to get to the complex parts of the font structure. + */ +#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_emulation.c b/include/gdisp_emulation.c deleted file mode 100644 index 31ca1a03..00000000 --- a/include/gdisp_emulation.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - Emulation routines included into gdisp_lld.c -*/ - -/* - Even though this is a software emulation of a low level driver - most validation doesn't need to happen here as eventually - we call a real low level driver routine and if validation is - required - it will do it. -*/ -#ifndef GDISP_EMULATION_C -#define GDISP_EMULATION_C - -#if GFX_USE_GDISP || defined(__DOXYGEN__) - -#ifndef GDISP_LLD_NO_STRUCT - static struct GDISPDriver { - coord_t Width; - coord_t Height; - gdisp_orientation_t Orientation; - gdisp_powermode_t Powermode; - uint8_t Backlight; - uint8_t Contrast; - #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION - coord_t clipx0, clipy0; - coord_t clipx1, clipy1; /* not inclusive */ - #endif - } GDISP; -#endif - -#if !GDISP_HARDWARE_CLEARS - void GDISP_LLD(clear)(color_t color) { - GDISP_LLD(fillarea)(0, 0, GDISP.Width, GDISP.Height, color); - } -#endif - -#if !GDISP_HARDWARE_LINES - void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { - int16_t dy, dx; - int16_t addx, addy; - int16_t P, diff, i; - - #if GDISP_HARDWARE_FILLS || GDISP_HARDWARE_SCROLL - // speed improvement if vertical or horizontal - if (x0 == x1) { - if (y1 > y0) - GDISP_LLD(fillarea)(x0, y0, 1, y1-y0+1, color); - else - GDISP_LLD(fillarea)(x0, y1, 1, y0-y1+1, color); - return; - } - if (y0 == y1) { - if (x1 > x0) - GDISP_LLD(fillarea)(x0, y0, x1-x0+1, 1, color); - else - GDISP_LLD(fillarea)(x0, y1, x0-x1+1, 1, color); - return; - } - #endif - - 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) { - GDISP_LLD(drawpixel)(x0, y0, color); - 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) { - GDISP_LLD(drawpixel)(x0, y0, color); - if (P < 0) { - P += dx; - y0 += addy; - } else { - P += diff; - x0 += addx; - y0 += addy; - } - } - } - } -#endif - -#if !GDISP_HARDWARE_FILLS - void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { - #if GDISP_HARDWARE_SCROLL - GDISP_LLD(verticalscroll)(x, y, cx, cy, cy, color); - #elif GDISP_HARDWARE_LINES - coord_t x1, y1; - - x1 = x + cx - 1; - y1 = y + cy; - for(; y < y1; y++) - GDISP_LLD(drawline)(x, y, x1, y, color); - #else - coord_t x0, x1, y1; - - x0 = x; - x1 = x + cx; - y1 = y + cy; - for(; y < y1; y++) - for(x = x0; x < x1; x++) - GDISP_LLD(drawpixel)(x, y, color); - #endif - } -#endif - -#if !GDISP_HARDWARE_BITFILLS - void GDISP_LLD(blitareaex)(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 x0, x1, y1; - - x0 = x; - x1 = x + cx; - y1 = y + cy; - buffer += srcy*srccx+srcx; - srccx -= cx; - for(; y < y1; y++, buffer += srccx) - for(x=x0; x < x1; x++) - GDISP_LLD(drawpixel)(x, y, *buffer++); - } -#endif - -#if GDISP_NEED_CLIP && !GDISP_HARDWARE_CLIP - void GDISP_LLD(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy) { - #if GDISP_NEED_VALIDATION - if (x >= GDISP.Width || y >= GDISP.Height || cx < 0 || cy < 0) - return; - if (x < 0) x = 0; - if (y < 0) y = 0; - if (x+cx > GDISP.Width) cx = GDISP.Width - x; - if (y+cy > GDISP.Height) cy = GDISP.Height - y; - #endif - GDISP.clipx0 = x; - GDISP.clipy0 = y; - GDISP.clipx1 = x+cx; - GDISP.clipy1 = y+cy; - } -#endif - -#if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLES - void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - coord_t a, b, P; - - a = 0; - b = radius; - P = 1 - radius; - - do { - GDISP_LLD(drawpixel)(x+a, y+b, color); - GDISP_LLD(drawpixel)(x+b, y+a, color); - GDISP_LLD(drawpixel)(x-a, y+b, color); - GDISP_LLD(drawpixel)(x-b, y+a, color); - GDISP_LLD(drawpixel)(x+b, y-a, color); - GDISP_LLD(drawpixel)(x+a, y-b, color); - GDISP_LLD(drawpixel)(x-a, y-b, color); - GDISP_LLD(drawpixel)(x-b, y-a, color); - if (P < 0) - P += 3 + 2*a++; - else - P += 5 + 2*(a++ - b--); - } while(a <= b); - } -#endif - -#if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLEFILLS - void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { - coord_t a, b, P; - - a = 0; - b = radius; - P = 1 - radius; - - do { - GDISP_LLD(drawline)(x-a, y+b, x+a, y+b, color); - GDISP_LLD(drawline)(x-a, y-b, x+a, y-b, color); - GDISP_LLD(drawline)(x-b, y+a, x+b, y+a, color); - GDISP_LLD(drawline)(x-b, y-a, x+b, y-a, color); - if (P < 0) - P += 3 + 2*a++; - else - P += 5 + 2*(a++ - b--); - } while(a <= b); - } -#endif - -#if GDISP_NEED_ELLIPSE && !GDISP_HARDWARE_ELLIPSES - void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - int dx = 0, dy = b; /* im I. Quadranten von links oben nach rechts unten */ - long a2 = a*a, b2 = b*b; - long err = b2-(2*b-1)*a2, e2; /* Fehler im 1. Schritt */ - - do { - GDISP_LLD(drawpixel)(x+dx, y+dy, color); /* I. Quadrant */ - GDISP_LLD(drawpixel)(x-dx, y+dy, color); /* II. Quadrant */ - GDISP_LLD(drawpixel)(x-dx, y-dy, color); /* III. Quadrant */ - GDISP_LLD(drawpixel)(x+dx, y-dy, color); /* IV. Quadrant */ - - e2 = 2*err; - if(e2 < (2*dx+1)*b2) { - dx++; - err += (2*dx+1)*b2; - } - if(e2 > -(2*dy-1)*a2) { - dy--; - err -= (2*dy-1)*a2; - } - } while(dy >= 0); - - while(dx++ < a) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */ - GDISP_LLD(drawpixel)(x+dx, y, color); /* -> Spitze der Ellipse vollenden */ - GDISP_LLD(drawpixel)(x-dx, y, color); - } - } -#endif - -#if GDISP_NEED_ELLIPSE && !GDISP_HARDWARE_ELLIPSEFILLS - void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { - int dx = 0, dy = b; /* im I. Quadranten von links oben nach rechts unten */ - long a2 = a*a, b2 = b*b; - long err = b2-(2*b-1)*a2, e2; /* Fehler im 1. Schritt */ - - do { - GDISP_LLD(drawline)(x-dx,y+dy,x+dx,y+dy, color); - GDISP_LLD(drawline)(x-dx,y-dy,x+dx,y-dy, color); - - e2 = 2*err; - if(e2 < (2*dx+1)*b2) { - dx++; - err += (2*dx+1)*b2; - } - if(e2 > -(2*dy-1)*a2) { - dy--; - err -= (2*dy-1)*a2; - } - } while(dy >= 0); - - while(dx++ < a) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */ - GDISP_LLD(drawpixel)(x+dx, y, color); /* -> Spitze der Ellipse vollenden */ - GDISP_LLD(drawpixel)(x-dx, y, color); - } - } -#endif - -#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCS - - #include - - /* - * @brief Internal helper function for gdispDrawArc() - * - * @note DO NOT USE DIRECTLY! - * - * @param[in] x, y The middle point of the arc - * @param[in] start The start angle of the arc - * @param[in] end The end angle of the arc - * @param[in] radius The radius of the arc - * @param[in] color The color in which the arc will be drawn - * - * @notapi - */ - static void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) { - if (/*start >= 0 && */start <= 180) { - float x_maxI = x + radius*cos(start*M_PI/180); - float x_minI; - - if (end > 180) - x_minI = x - radius; - else - x_minI = x + radius*cos(end*M_PI/180); - - int a = 0; - int b = radius; - int P = 1 - radius; - - do { - if(x-a <= x_maxI && x-a >= x_minI) - GDISP_LLD(drawpixel)(x-a, y-b, color); - if(x+a <= x_maxI && x+a >= x_minI) - GDISP_LLD(drawpixel)(x+a, y-b, color); - if(x-b <= x_maxI && x-b >= x_minI) - GDISP_LLD(drawpixel)(x-b, y-a, color); - if(x+b <= x_maxI && x+b >= x_minI) - GDISP_LLD(drawpixel)(x+b, y-a, color); - - if (P < 0) { - P = P + 3 + 2*a; - a = a + 1; - } else { - P = P + 5 + 2*(a - b); - a = a + 1; - b = b - 1; - } - } while(a <= b); - } - - if (end > 180 && end <= 360) { - float x_maxII = x+radius*cos(end*M_PI/180); - float x_minII; - - if(start <= 180) - x_minII = x - radius; - else - x_minII = x+radius*cos(start*M_PI/180); - - int a = 0; - int b = radius; - int P = 1 - radius; - - do { - if(x-a <= x_maxII && x-a >= x_minII) - GDISP_LLD(drawpixel)(x-a, y+b, color); - if(x+a <= x_maxII && x+a >= x_minII) - GDISP_LLD(drawpixel)(x+a, y+b, color); - if(x-b <= x_maxII && x-b >= x_minII) - GDISP_LLD(drawpixel)(x-b, y+a, color); - if(x+b <= x_maxII && x+b >= x_minII) - GDISP_LLD(drawpixel)(x+b, y+a, color); - - if (P < 0) { - P = P + 3 + 2*a; - a = a + 1; - } else { - P = P + 5 + 2*(a - b); - a = a + 1; - b = b - 1; - } - } while (a <= b); - } - } - - void GDISP_LLD(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { - if(endangle < startangle) { - _draw_arc(x, y, startangle, 360, radius, color); - _draw_arc(x, y, 0, endangle, radius, color); - } else { - _draw_arc(x, y, startangle, endangle, radius, color); - } - } -#endif - -#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCFILLS - /* - * @brief Internal helper function for gdispDrawArc() - * - * @note DO NOT USE DIRECTLY! - * - * @param[in] x, y The middle point of the arc - * @param[in] start The start angle of the arc - * @param[in] end The end angle of the arc - * @param[in] radius The radius of the arc - * @param[in] color The color in which the arc will be drawn - * - * @notapi - */ - static void _fill_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) { - if (/*start >= 0 && */start <= 180) { - float x_maxI = x + radius*cos(start*M_PI/180); - float x_minI; - - if (end > 180) - x_minI = x - radius; - else - x_minI = x + radius*cos(end*M_PI/180); - - int a = 0; - int b = radius; - int P = 1 - radius; - - do { - if(x-a <= x_maxI && x-a >= x_minI) - GDISP_LLD(drawline)(x, y, x-a, y-b, color); - if(x+a <= x_maxI && x+a >= x_minI) - GDISP_LLD(drawline)(x, y, x+a, y-b, color); - if(x-b <= x_maxI && x-b >= x_minI) - GDISP_LLD(drawline)(x, y, x-b, y-a, color); - if(x+b <= x_maxI && x+b >= x_minI) - GDISP_LLD(drawline)(x, y, x+b, y-a, color); - - if (P < 0) { - P = P + 3 + 2*a; - a = a + 1; - } else { - P = P + 5 + 2*(a - b); - a = a + 1; - b = b - 1; - } - } while(a <= b); - } - - if (end > 180 && end <= 360) { - float x_maxII = x+radius*cos(end*M_PI/180); - float x_minII; - - if(start <= 180) - x_minII = x - radius; - else - x_minII = x+radius*cos(start*M_PI/180); - - int a = 0; - int b = radius; - int P = 1 - radius; - - do { - if(x-a <= x_maxII && x-a >= x_minII) - GDISP_LLD(drawline)(x, y, x-a, y+b, color); - if(x+a <= x_maxII && x+a >= x_minII) - GDISP_LLD(drawline)(x, y, x+a, y+b, color); - if(x-b <= x_maxII && x-b >= x_minII) - GDISP_LLD(drawline)(x, y, x-b, y+a, color); - if(x+b <= x_maxII && x+b >= x_minII) - GDISP_LLD(drawline)(x, y, x+b, y+a, color); - - if (P < 0) { - P = P + 3 + 2*a; - a = a + 1; - } else { - P = P + 5 + 2*(a - b); - a = a + 1; - b = b - 1; - } - } while (a <= b); - } - } - - void GDISP_LLD(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { - if(endangle < startangle) { - _fill_arc(x, y, startangle, 360, radius, color); - _fill_arc(x, y, 0, endangle, radius, color); - } else { - _fill_arc(x, y, startangle, endangle, radius, color); - } - } -#endif - -#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT - #include "gdisp_fonts.h" -#endif - -#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT - void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { - const fontcolumn_t *ptr; - fontcolumn_t column; - coord_t width, height, xscale, yscale; - coord_t i, j, xs, ys; - - /* Check we actually have something to print */ - width = _getCharWidth(font, c); - if (!width) return; - - xscale = font->xscale; - yscale = font->yscale; - height = font->height * yscale; - width *= xscale; - - ptr = _getCharData(font, c); - - /* Loop through the data and display. The font data is LSBit first, down the column */ - for(i=0; i < width; i+=xscale) { - /* Get the font bitmap data for the column */ - column = *ptr++; - - /* Draw each pixel */ - for(j=0; j < height; j+=yscale, column >>= 1) { - if (column & 0x01) { - for(xs=0; xs < xscale; xs++) - for(ys=0; ys < yscale; ys++) - GDISP_LLD(drawpixel)(x+i+xs, y+j+ys, color); - } - } - } - } -#endif - -#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXTFILLS - void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { - coord_t width, height; - coord_t xscale, yscale; - - /* Check we actually have something to print */ - width = _getCharWidth(font, c); - if (!width) return; - - xscale = font->xscale; - yscale = font->yscale; - height = font->height * yscale; - width *= xscale; - - /* Method 1: Use background fill and then draw the text */ - #if GDISP_HARDWARE_TEXT || GDISP_SOFTWARE_TEXTFILLDRAW - - /* Fill the area */ - GDISP_LLD(fillarea)(x, y, width, height, bgcolor); - - /* Draw the text */ - GDISP_LLD(drawchar)(x, y, c, font, color); - - /* Method 2: Create a single column bitmap and then blit it */ - #elif GDISP_HARDWARE_BITFILLS && GDISP_SOFTWARE_TEXTBLITCOLUMN - { - const fontcolumn_t *ptr; - fontcolumn_t column; - coord_t i, j, xs, ys; - - /* Working buffer for fast non-transparent text rendering [patch by Badger] - This needs to be larger than the largest character we can print. - Assume the max is double sized by one column. - */ - static pixel_t buf[sizeof(fontcolumn_t)*8*2]; - - #if GDISP_NEED_VALIDATION - /* Check our buffer is big enough */ - if ((unsigned)height > sizeof(buf)/sizeof(buf[0])) return; - #endif - - ptr = _getCharData(font, c); - - /* Loop through the data and display. The font data is LSBit first, down the column */ - for(i = 0; i < width; i+=xscale) { - /* Get the font bitmap data for the column */ - column = *ptr++; - - /* Draw each pixel */ - for(j = 0; j < height; j+=yscale, column >>= 1) { - if (column & 0x01) { - for(ys=0; ys < yscale; ys++) - gdispPackPixels(buf, 1, j+ys, 0, color); - } else { - for(ys=0; ys < yscale; ys++) - gdispPackPixels(buf, 1, j+ys, 0, bgcolor); - } - } - - for(xs=0; xs < xscale; xs++) - GDISP_LLD(blitareaex)(x+i+xs, y, 1, height, 0, 0, 1, buf); - } - } - - /* Method 3: Create a character bitmap and then blit it */ - #elif GDISP_HARDWARE_BITFILLS - { - const fontcolumn_t *ptr; - fontcolumn_t column; - coord_t i, j, xs, ys; - - /* Working buffer for fast non-transparent text rendering [patch by Badger] - This needs to be larger than the largest character we can print. - Assume the max is double sized. - */ - static pixel_t buf[20*(sizeof(fontcolumn_t)*8)*2]; - - #if GDISP_NEED_VALIDATION - /* Check our buffer is big enough */ - if ((unsigned)(width * height) > sizeof(buf)/sizeof(buf[0])) return; - #endif - - ptr = _getCharData(font, c); - - /* Loop through the data and display. The font data is LSBit first, down the column */ - for(i = 0; i < width; i+=xscale) { - /* Get the font bitmap data for the column */ - column = *ptr++; - - /* Draw each pixel */ - for(j = 0; j < height; j+=yscale, column >>= 1) { - if (column & 0x01) { - for(xs=0; xs < xscale; xs++) - for(ys=0; ys < yscale; ys++) - gdispPackPixels(buf, width, i+xs, j+ys, color); - } else { - for(xs=0; xs < xscale; xs++) - for(ys=0; ys < yscale; ys++) - gdispPackPixels(buf, width, i+xs, j+ys, bgcolor); - } - } - } - - /* [Patch by Badger] Write all in one stroke */ - GDISP_LLD(blitareaex)(x, y, width, height, 0, 0, width, buf); - } - - /* Method 4: Draw pixel by pixel */ - #else - { - const fontcolumn_t *ptr; - fontcolumn_t column; - coord_t i, j, xs, ys; - - ptr = _getCharData(font, c); - - /* Loop through the data and display. The font data is LSBit first, down the column */ - for(i = 0; i < width; i+=xscale) { - /* Get the font bitmap data for the column */ - column = *ptr++; - - /* Draw each pixel */ - for(j = 0; j < height; j+=yscale, column >>= 1) { - if (column & 0x01) { - for(xs=0; xs < xscale; xs++) - for(ys=0; ys < yscale; ys++) - GDISP_LLD(drawpixel)(x+i+xs, y+j+ys, color); - } else { - for(xs=0; xs < xscale; xs++) - for(ys=0; ys < yscale; ys++) - GDISP_LLD(drawpixel)(x+i+xs, y+j+ys, bgcolor); - } - } - } - } - #endif - } -#endif - - -#if GDISP_NEED_CONTROL && !GDISP_HARDWARE_CONTROL - void GDISP_LLD(control)(unsigned what, void *value) { - (void)what; - (void)value; - /* Ignore everything */ - } -#endif - -#if GDISP_NEED_QUERY && !GDISP_HARDWARE_QUERY -void *GDISP_LLD(query)(unsigned what) { - switch(what) { - case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; - case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; - case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; - case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; - case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; - case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; - default: return (void *)-1; - } -} -#endif - -#if GDISP_NEED_MSGAPI - void GDISP_LLD(msgdispatch)(gdisp_lld_msg_t *msg) { - switch(msg->action) { - case GDISP_LLD_MSG_NOP: - break; - case GDISP_LLD_MSG_INIT: - GDISP_LLD(init)(); - break; - case GDISP_LLD_MSG_CLEAR: - GDISP_LLD(clear)(msg->clear.color); - break; - case GDISP_LLD_MSG_DRAWPIXEL: - GDISP_LLD(drawpixel)(msg->drawpixel.x, msg->drawpixel.y, msg->drawpixel.color); - break; - case GDISP_LLD_MSG_FILLAREA: - GDISP_LLD(fillarea)(msg->fillarea.x, msg->fillarea.y, msg->fillarea.cx, msg->fillarea.cy, msg->fillarea.color); - break; - case GDISP_LLD_MSG_BLITAREA: - GDISP_LLD(blitareaex)(msg->blitarea.x, msg->blitarea.y, msg->blitarea.cx, msg->blitarea.cy, msg->blitarea.srcx, msg->blitarea.srcy, msg->blitarea.srccx, msg->blitarea.buffer); - break; - case GDISP_LLD_MSG_DRAWLINE: - GDISP_LLD(drawline)(msg->drawline.x0, msg->drawline.y0, msg->drawline.x1, msg->drawline.y1, msg->drawline.color); - break; - #if GDISP_NEED_CLIP - case GDISP_LLD_MSG_SETCLIP: - GDISP_LLD(setclip)(msg->setclip.x, msg->setclip.y, msg->setclip.cx, msg->setclip.cy); - break; - #endif - #if GDISP_NEED_CIRCLE - case GDISP_LLD_MSG_DRAWCIRCLE: - GDISP_LLD(drawcircle)(msg->drawcircle.x, msg->drawcircle.y, msg->drawcircle.radius, msg->drawcircle.color); - break; - case GDISP_LLD_MSG_FILLCIRCLE: - GDISP_LLD(fillcircle)(msg->fillcircle.x, msg->fillcircle.y, msg->fillcircle.radius, msg->fillcircle.color); - break; - #endif - #if GDISP_NEED_ELLIPSE - case GDISP_LLD_MSG_DRAWELLIPSE: - GDISP_LLD(drawellipse)(msg->drawellipse.x, msg->drawellipse.y, msg->drawellipse.a, msg->drawellipse.b, msg->drawellipse.color); - break; - case GDISP_LLD_MSG_FILLELLIPSE: - GDISP_LLD(fillellipse)(msg->fillellipse.x, msg->fillellipse.y, msg->fillellipse.a, msg->fillellipse.b, msg->fillellipse.color); - break; - #endif - #if GDISP_NEED_ARC - case GDISP_LLD_MSG_DRAWARC: - GDISP_LLD(drawcircle)(msg->drawarc.x, msg->drawarc.y, msg->drawarc.radius, msg->drawarc.startangle, msg->drawarc.endangle, msg->drawarc.color); - break; - case GDISP_LLD_MSG_FILLARC: - GDISP_LLD(fillcircle)(msg->fillarc.x, msg->fillarc.y, msg->fillarc.radius, msg->fillarc.startangle, msg->fillarc.endangle, msg->fillarc.color); - break; - #endif - #if GDISP_NEED_TEXT - case GDISP_LLD_MSG_DRAWCHAR: - GDISP_LLD(drawchar)(msg->drawchar.x, msg->drawchar.y, msg->drawchar.c, msg->drawchar.font, msg->drawchar.color); - break; - case GDISP_LLD_MSG_FILLCHAR: - GDISP_LLD(fillchar)(msg->fillchar.x, msg->fillchar.y, msg->fillchar.c, msg->fillchar.font, msg->fillchar.color, msg->fillchar.bgcolor); - break; - #endif - #if GDISP_NEED_PIXELREAD - case GDISP_LLD_MSG_GETPIXELCOLOR: - msg->getpixelcolor.result = GDISP_LLD(getpixelcolor)(msg->getpixelcolor.x, msg->getpixelcolor.y); - break; - #endif - #if GDISP_NEED_SCROLL - case GDISP_LLD_MSG_VERTICALSCROLL: - GDISP_LLD(verticalscroll)(msg->verticalscroll.x, msg->verticalscroll.y, msg->verticalscroll.cx, msg->verticalscroll.cy, msg->verticalscroll.lines, msg->verticalscroll.bgcolor); - break; - #endif - #if GDISP_NEED_CONTROL - case GDISP_LLD_MSG_CONTROL: - GDISP_LLD(control)(msg->control.what, msg->control.value); - break; - #endif - #if GDISP_NEED_QUERY - case GDISP_LLD_MSG_QUERY: - msg->query.result = GDISP_LLD(query)(msg->query.what); - break; - #endif - } - } -#endif - -#endif /* GFX_USE_GDISP */ -#endif /* GDISP_EMULATION_C */ - diff --git a/include/gdisp_fonts.h b/include/gdisp_fonts.h deleted file mode 100644 index e3b07e86..00000000 --- a/include/gdisp_fonts.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @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 maximum height of a font. - * @details Either 16 or 32. Defaults to 16 - * @note Setting this to 32 causes the font tables to take - * twice the internal program memory. - */ -#ifndef GDISP_MAX_FONT_HEIGHT - #define GDISP_MAX_FONT_HEIGHT 16 -#endif - -/** - * @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 { - 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; -}; - -/** - * @brief Macros to get to the complex parts of the font structure. - */ -#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_lld.h b/include/gdisp_lld.h deleted file mode 100644 index fecd710a..00000000 --- a/include/gdisp_lld.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file include/gdisp_lld.h - * @brief GDISP Graphic Driver subsystem low level driver header. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_H -#define _GDISP_LLD_H - -#if GFX_USE_GDISP || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Low level driver configuration needs */ -/*===========================================================================*/ - -/** - * @name GDISP low level driver more complex functionality to be compiled - * @{ - */ - /** - * @brief Should all operations be clipped to the screen and colors validated. - * @details Defaults to TRUE. - * @note If this is FALSE, any operations that extend beyond the - * edge of the screen will have undefined results. Any - * out-of-range colors will produce undefined results. - * @note If defined then all low level and high level driver routines - * must check the validity of inputs and do something sensible - * if they are out of range. It doesn't have to be efficient, - * just valid. - */ - #ifndef GDISP_NEED_VALIDATION - #define GDISP_NEED_VALIDATION TRUE - #endif - - /** - * @brief Are circle functions needed. - * @details Defaults to TRUE - */ - #ifndef GDISP_NEED_CIRCLE - #define GDISP_NEED_CIRCLE TRUE - #endif - - /** - * @brief Are ellipse functions needed. - * @details Defaults to TRUE - */ - #ifndef GDISP_NEED_ELLIPSE - #define GDISP_NEED_ELLIPSE TRUE - #endif - - /** - * @brief Are arc functions needed. - * @details Defaults to FALSE - */ - #ifndef GDISP_NEED_ARC - #define GDISP_NEED_ARC FALSE - #endif - - /** - * @brief Are text functions needed. - * @details Defaults to TRUE - */ - #ifndef GDISP_NEED_TEXT - #define GDISP_NEED_TEXT TRUE - #endif - - /** - * @brief Is scrolling needed. - * @details Defaults to FALSE - */ - #ifndef GDISP_NEED_SCROLL - #define GDISP_NEED_SCROLL FALSE - #endif - - /** - * @brief Is the capability to read pixels back needed. - * @details Defaults to FALSE - */ - #ifndef GDISP_NEED_PIXELREAD - #define GDISP_NEED_PIXELREAD FALSE - #endif - - /** - * @brief Are clipping functions needed. - * @details Defaults to TRUE - */ - #ifndef GDISP_NEED_CLIP - #define GDISP_NEED_CLIP FALSE - #endif - - /** - * @brief Control some aspect of the drivers operation. - * @details Defaults to FALSE - */ - #ifndef GDISP_NEED_CONTROL - #define GDISP_NEED_CONTROL FALSE - #endif - - /** - * @brief Query some aspect of the drivers operation. - * @details Defaults to TRUE - */ - #ifndef GDISP_NEED_QUERY - #define GDISP_NEED_QUERY TRUE - #endif - - /** - * @brief Is the messaging api interface required. - * @details Defaults to FALSE - */ - #ifndef GDISP_NEED_MSGAPI - #define GDISP_NEED_MSGAPI FALSE - #endif -/** @} */ - -/*===========================================================================*/ -/* Include the low level driver configuration information */ -/*===========================================================================*/ - -#include "gdisp_lld_config.h" - -/*===========================================================================*/ -/* Constants. */ -/*===========================================================================*/ - -/** - * @brief Driver Control Constants - * @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. - * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. - * GDISP_CONTROL_LLD - Low level driver control constants start at - * this value. - */ -#define GDISP_CONTROL_POWER 0 -#define GDISP_CONTROL_ORIENTATION 1 -#define GDISP_CONTROL_BACKLIGHT 2 -#define GDISP_CONTROL_CONTRAST 3 -#define GDISP_CONTROL_LLD 1000 - -/** - * @brief Driver Query Constants - * @details Unsupported query codes return (void *)-1. - * @note There are some predefined and some specific to the low level driver. - * @note The result should be typecast the required type. - * @note GDISP_QUERY_WIDTH - Gets the width of the screen - * GDISP_QUERY_HEIGHT - Gets the height of the screen - * GDISP_QUERY_POWER - Get the current powermode - * GDISP_QUERY_ORIENTATION - Get the current orientation - * GDISP_QUERY_BACKLIGHT - Get the backlight state (0 to 100) - * GDISP_QUERY_CONTRAST - Get the contrast. - * GDISP_QUERY_LLD - Low level driver control constants start at - * this value. - */ -#define GDISP_QUERY_WIDTH 0 -#define GDISP_QUERY_HEIGHT 1 -#define GDISP_QUERY_POWER 2 -#define GDISP_QUERY_ORIENTATION 3 -#define GDISP_QUERY_BACKLIGHT 4 -#define GDISP_QUERY_CONTRAST 5 -#define GDISP_QUERY_LLD 1000 - -/** - * @brief Driver Pixel Format Constants - */ -#define GDISP_PIXELFORMAT_RGB565 565 -#define GDISP_PIXELFORMAT_RGB888 888 -#define GDISP_PIXELFORMAT_RGB444 444 -#define GDISP_PIXELFORMAT_RGB332 332 -#define GDISP_PIXELFORMAT_RGB666 666 -#define GDISP_PIXELFORMAT_CUSTOM 99999 -#define GDISP_PIXELFORMAT_ERROR 88888 - -/*===========================================================================*/ -/* Error checks. */ -/*===========================================================================*/ - -/** - * @name GDISP hardware accelerated support - * @{ - */ - /** - * @brief Hardware accelerated line drawing. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_LINES - #define GDISP_HARDWARE_LINES FALSE - #endif - - /** - * @brief Hardware accelerated screen clears. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_CLEARS - #define GDISP_HARDWARE_CLEARS FALSE - #endif - - /** - * @brief Hardware accelerated rectangular fills. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_FILLS - #define GDISP_HARDWARE_FILLS FALSE - #endif - - /** - * @brief Hardware accelerated fills from an image. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_BITFILLS - #define GDISP_HARDWARE_BITFILLS FALSE - #endif - - /** - * @brief Hardware accelerated circles. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_CIRCLES - #define GDISP_HARDWARE_CIRCLES FALSE - #endif - - /** - * @brief Hardware accelerated filled circles. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_CIRCLEFILLS - #define GDISP_HARDWARE_CIRCLEFILLS FALSE - #endif - - /** - * @brief Hardware accelerated ellipses. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_ELLIPSES - #define GDISP_HARDWARE_ELLIPSES FALSE - #endif - - /** - * @brief Hardware accelerated filled ellipses. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_ELLIPSEFILLS - #define GDISP_HARDWARE_ELLIPSEFILLS FALSE - #endif - - /** - * @brief Hardware accelerated arc's. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_ARCS - #define GDISP_HARDWARE_ARCS FALSE - #endif - - /** - * @brief Hardware accelerated filled arcs. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_ARCFILLS - #define GDISP_HARDWARE_ARCFILLS FALSE - #endif - - /** - * @brief Hardware accelerated text drawing. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_TEXT - #define GDISP_HARDWARE_TEXT FALSE - #endif - - /** - * @brief Hardware accelerated text drawing with a filled background. - * @details If set to @p FALSE software emulation is used. - */ - #ifndef GDISP_HARDWARE_TEXTFILLS - #define GDISP_HARDWARE_TEXTFILLS FALSE - #endif - - /** - * @brief Hardware accelerated scrolling. - * @details If set to @p FALSE there is no support for scrolling. - */ - #ifndef GDISP_HARDWARE_SCROLL - #define GDISP_HARDWARE_SCROLL FALSE - #endif - - /** - * @brief Reading back of pixel values. - * @details If set to @p FALSE there is no support for pixel read-back. - */ - #ifndef GDISP_HARDWARE_PIXELREAD - #define GDISP_HARDWARE_PIXELREAD FALSE - #endif - - /** - * @brief The driver supports one or more control commands. - * @details If set to @p FALSE there is no support for control commands. - */ - #ifndef GDISP_HARDWARE_CONTROL - #define GDISP_HARDWARE_CONTROL FALSE - #endif - - /** - * @brief The driver supports a non-standard query. - * @details If set to @p FALSE there is no support for non-standard queries. - */ - #ifndef GDISP_HARDWARE_QUERY - #define GDISP_HARDWARE_QUERY FALSE - #endif - - /** - * @brief The driver supports a clipping in hardware. - * @details If set to @p FALSE there is no support for non-standard queries. - */ - #ifndef GDISP_HARDWARE_CLIP - #define GDISP_HARDWARE_CLIP FALSE - #endif -/** @} */ - -/** - * @name GDISP software algorithm choices - * @{ - */ - /** - * @brief For filled text drawing, use a background fill and then draw - * the text instead of using a blit or direct pixel drawing. - * @details If set to @p TRUE background fill and then text draw is used. - * @note This is ignored if hardware accelerated text is supported. - */ - #ifndef GDISP_SOFTWARE_TEXTFILLDRAW - #define GDISP_SOFTWARE_TEXTFILLDRAW FALSE - #endif - - /** - * @brief For filled text drawing, when using a bitmap blit - * use a column by column buffer rather than a full character - * buffer to save memory at a small performance cost. - * @details If set to @p TRUE background fill one character column at a time. - * @note This is ignored if software text using blit is not being used. - */ - #ifndef GDISP_SOFTWARE_TEXTBLITCOLUMN - #define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE - #endif -/** @} */ - -/** - * @name GDISP pixel format choices - * @{ - */ - /** - * @brief The native pixel format for this device - * @note Should be set to one of the following: - * GDISP_PIXELFORMAT_RGB565 - * GDISP_PIXELFORMAT_RGB888 - * GDISP_PIXELFORMAT_RGB444 - * GDISP_PIXELFORMAT_RGB332 - * GDISP_PIXELFORMAT_RGB666 - * GDISP_PIXELFORMAT_CUSTOM - * @note If you set GDISP_PIXELFORMAT_CUSTOM you need to also define - * color_t, RGB2COLOR(r,g,b), HTML2COLOR(h), - * RED_OF(c), GREEN_OF(c), BLUE_OF(c), - * COLOR(c) and MASKCOLOR. - */ - #ifndef GDISP_PIXELFORMAT - #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_ERROR - #endif - - /** - * @brief Do pixels require packing for a blit - * @note Is only valid for a pixel format that doesn't fill it's datatype. ie formats: - * GDISP_PIXELFORMAT_RGB888 - * GDISP_PIXELFORMAT_RGB444 - * GDISP_PIXELFORMAT_RGB666 - * GDISP_PIXELFORMAT_CUSTOM - * @note If you use GDISP_PIXELFORMAT_CUSTOM and packed bit fills - * you need to also define @p gdispPackPixels(buf,cx,x,y,c) - * @note If you are using GDISP_HARDWARE_BITFILLS = FALSE then the pixel - * format must not be a packed format as the software blit does - * not support packed pixels - * @note Very few cases should actually require packed pixels as the low - * level driver can also pack on the fly as it is sending it - * to the graphics device. - */ - #ifndef GDISP_PACKED_PIXELS - #define GDISP_PACKED_PIXELS FALSE - #endif - - /** - * @brief Do lines of pixels require packing for a blit - * @note Ignored if GDISP_PACKED_PIXELS is FALSE - */ - #ifndef GDISP_PACKED_LINES - #define GDISP_PACKED_LINES FALSE - #endif -/** @} */ - -/*===========================================================================*/ -/* Define the macro's for the various pixel formats */ -/*===========================================================================*/ - -#if defined(__DOXYGEN__) - /** - * @brief The color of a pixel. - */ - typedef uint16_t color_t; - /** - * @brief Convert a number (of any type) to a color_t. - * @details Masks any invalid bits in the color - */ - #define COLOR(c) ((color_t)(c)) - /** - * @brief Does the color_t type contain invalid bits that need masking. - */ - #define MASKCOLOR FALSE - /** - * @brief Convert red, green, blue (each 0 to 255) into a color value. - */ - #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF8)<<8) | (((g) & 0xFC)<<3) | (((b) & 0xF8)>>3))) - /** - * @brief Convert a 6 digit HTML code (hex) into a color value. - */ - #define HTML2COLOR(h) ((color_t)((((h) & 0xF80000)>>8) | (((h) & 0x00FC00)>>5) | (((h) & 0x0000F8)>>3))) - /** - * @brief Extract the red component (0 to 255) of a color value. - */ - #define RED_OF(c) (((c) & 0xF800)>>8) - /** - * @brief Extract the green component (0 to 255) of a color value. - */ - #define GREEN_OF(c) (((c)&0x007E)>>3) - /** - * @brief Extract the blue component (0 to 255) of a color value. - */ - #define BLUE_OF(c) (((c)&0x001F)<<3) - -#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 - typedef uint16_t color_t; - #define COLOR(c) ((color_t)(c)) - #define MASKCOLOR FALSE - #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF8)<<8) | (((g) & 0xFC)<<3) | (((b) & 0xF8)>>3))) - #define HTML2COLOR(h) ((color_t)((((h) & 0xF80000)>>8) | (((h) & 0x00FC00)>>5) | (((h) & 0x0000F8)>>3))) - #define RED_OF(c) (((c) & 0xF800)>>8) - #define GREEN_OF(c) (((c)&0x007E)>>3) - #define BLUE_OF(c) (((c)&0x001F)<<3) - -#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 - typedef uint32_t color_t; - #define COLOR(c) ((color_t)(((c) & 0xFFFFFF))) - #define MASKCOLOR TRUE - #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xFF)<<16) | (((g) & 0xFF) << 8) | ((b) & 0xFF))) - #define HTML2COLOR(h) ((color_t)(h)) - #define RED_OF(c) (((c) & 0xFF0000)>>16) - #define GREEN_OF(c) (((c)&0x00FF00)>>8) - #define BLUE_OF(c) ((c)&0x0000FF) - -#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB444 - typedef uint16_t color_t; - #define COLOR(c) ((color_t)(((c) & 0x0FFF))) - #define MASKCOLOR TRUE - #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF0)<<4) | ((g) & 0xF0) | (((b) & 0xF0)>>4))) - #define HTML2COLOR(h) ((color_t)((((h) & 0xF00000)>>12) | (((h) & 0x00F000)>>8) | (((h) & 0x0000F0)>>4))) - #define RED_OF(c) (((c) & 0x0F00)>>4) - #define GREEN_OF(c) ((c)&0x00F0) - #define BLUE_OF(c) (((c)&0x000F)<<4) - -#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB332 - typedef uint8_t color_t; - #define COLOR(c) ((color_t)(c)) - #define MASKCOLOR FALSE - #define RGB2COLOR(r,g,b) ((color_t)(((r) & 0xE0) | (((g) & 0xE0)>>3) | (((b) & 0xC0)>>6))) - #define HTML2COLOR(h) ((color_t)((((h) & 0xE00000)>>16) | (((h) & 0x00E000)>>11) | (((h) & 0x0000C0)>>6))) - #define RED_OF(c) ((c) & 0xE0) - #define GREEN_OF(c) (((c)&0x1C)<<3) - #define BLUE_OF(c) (((c)&0x03)<<6) - -#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB666 - typedef uint32_t color_t; - #define COLOR(c) ((color_t)(((c) & 0x03FFFF))) - #define MASKCOLOR TRUE - #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xFC)<<10) | (((g) & 0xFC)<<4) | (((b) & 0xFC)>>2))) - #define HTML2COLOR(h) ((color_t)((((h) & 0xFC0000)>>6) | (((h) & 0x00FC00)>>4) | (((h) & 0x0000FC)>>2))) - #define RED_OF(c) (((c) & 0x03F000)>>12) - #define GREEN_OF(c) (((c)&0x00FC00)>>8) - #define BLUE_OF(c) (((c)&0x00003F)<<2) - -#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM - #error "GDISP: No supported pixel format has been specified." -#endif - -/* Verify information for packed pixels and define a non-packed pixel macro */ -#if !GDISP_PACKED_PIXELS - #define gdispPackPixels(buf,cx,x,y,c) { ((color_t *)(buf))[(y)*(cx)+(x)] = (c); } -#elif !GDISP_HARDWARE_BITFILLS - #error "GDISP: packed pixel formats are only supported for hardware accelerated drivers." -#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888 \ - && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB444 \ - && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB666 \ - && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM - #error "GDISP: A packed pixel format has been specified for an unsupported pixel format." -#endif - -#if GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL - #error "GDISP: Hardware scrolling is wanted but not supported." -#endif - -#if GDISP_NEED_PIXELREAD && !GDISP_HARDWARE_PIXELREAD - #error "GDISP: Pixel read-back is wanted but not supported." -#endif - -/*===========================================================================*/ -/* Driver types. */ -/*===========================================================================*/ - -/** - * @brief The type for a coordinate or length on the screen. - */ -typedef int16_t coord_t; -/** - * @brief The type of a pixel. - */ -typedef color_t pixel_t; -/** - * @brief The type of a font. - */ -typedef const struct font *font_t; -/** - * @brief Type for the screen orientation. - */ -typedef enum orientation {GDISP_ROTATE_0, GDISP_ROTATE_90, GDISP_ROTATE_180, GDISP_ROTATE_270} gdisp_orientation_t; -/** - * @brief Type for the available power modes for the screen. - */ -typedef enum powermode {powerOff, powerSleep, powerDeepSleep, powerOn} gdisp_powermode_t; - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifndef GDISP_LLD_VMT - /* Special magic stuff for the VMT driver */ - #define GDISP_LLD_VMT(x) GDISP_LLD(x) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - /* Core functions */ - extern bool_t GDISP_LLD(init)(void); - - /* Some of these functions will be implemented in software by the high level driver - depending on the GDISP_HARDWARE_XXX macros defined in gdisp_lld_config.h. - */ - - /* Drawing functions */ - extern void GDISP_LLD_VMT(clear)(color_t color); - extern void GDISP_LLD_VMT(drawpixel)(coord_t x, coord_t y, color_t color); - extern void GDISP_LLD_VMT(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); - extern void GDISP_LLD_VMT(blitareaex)(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); - extern void GDISP_LLD_VMT(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); - - /* Circular Drawing Functions */ - #if GDISP_NEED_CIRCLE - extern void GDISP_LLD_VMT(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color); - extern void GDISP_LLD_VMT(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color); - #endif - - #if GDISP_NEED_ELLIPSE - extern void GDISP_LLD_VMT(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); - extern void GDISP_LLD_VMT(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); - #endif - - /* Arc Drawing Functions */ - #if GDISP_NEED_ARC - extern void GDISP_LLD_VMT(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); - extern void GDISP_LLD_VMT(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); - #endif - - /* Text Rendering Functions */ - #if GDISP_NEED_TEXT - extern void GDISP_LLD_VMT(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color); - extern void GDISP_LLD_VMT(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor); - #endif - - /* Pixel readback */ - #if GDISP_NEED_PIXELREAD - extern color_t GDISP_LLD_VMT(getpixelcolor)(coord_t x, coord_t y); - #endif - - /* Scrolling Function - clears the area scrolled out */ - #if GDISP_NEED_SCROLL - extern void GDISP_LLD_VMT(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor); - #endif - - /* Set driver specific control */ - #if GDISP_NEED_CONTROL - extern void GDISP_LLD_VMT(control)(unsigned what, void *value); - #endif - - /* Query driver specific data */ - #if GDISP_NEED_QUERY - extern void *GDISP_LLD_VMT(query)(unsigned what); - #endif - - /* Clipping Functions */ - #if GDISP_NEED_CLIP - extern void GDISP_LLD_VMT(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy); - #endif - - /* Messaging API */ - #if GDISP_NEED_MSGAPI - #include "gdisp_lld_msgs.h" - extern void GDISP_LLD(msgdispatch)(gdisp_lld_msg_t *msg); - #endif - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_GDISP */ - -#endif /* _GDISP_LLD_H */ -/** @} */ - diff --git a/include/gdisp_lld_msgs.h b/include/gdisp_lld_msgs.h deleted file mode 100644 index 5885a70c..00000000 --- a/include/gdisp_lld_msgs.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file include/gdisp_lld_msgs.h - * @brief GDISP Graphic Driver subsystem low level driver message structures. - * - * @addtogroup GDISP - * @{ - */ - -#ifndef _GDISP_LLD_MSGS_H -#define _GDISP_LLD_MSGS_H - -/* This file describes the message API for gdisp_lld */ -#if GFX_USE_GDISP && GDISP_NEED_MSGAPI - -typedef enum gdisp_msgaction { - GDISP_LLD_MSG_NOP, - GDISP_LLD_MSG_INIT, - GDISP_LLD_MSG_CLEAR, - GDISP_LLD_MSG_DRAWPIXEL, - GDISP_LLD_MSG_FILLAREA, - GDISP_LLD_MSG_BLITAREA, - GDISP_LLD_MSG_DRAWLINE, - #if GDISP_NEED_CLIP - GDISP_LLD_MSG_SETCLIP, - #endif - #if GDISP_NEED_CIRCLE - GDISP_LLD_MSG_DRAWCIRCLE, - GDISP_LLD_MSG_FILLCIRCLE, - #endif - #if GDISP_NEED_ELLIPSE - GDISP_LLD_MSG_DRAWELLIPSE, - GDISP_LLD_MSG_FILLELLIPSE, - #endif - #if GDISP_NEED_ARC - GDISP_LLD_MSG_DRAWARC, - GDISP_LLD_MSG_FILLARC, - #endif - #if GDISP_NEED_TEXT - GDISP_LLD_MSG_DRAWCHAR, - GDISP_LLD_MSG_FILLCHAR, - #endif - #if GDISP_NEED_PIXELREAD - GDISP_LLD_MSG_GETPIXELCOLOR, - #endif - #if GDISP_NEED_SCROLL - GDISP_LLD_MSG_VERTICALSCROLL, - #endif - #if GDISP_NEED_CONTROL - GDISP_LLD_MSG_CONTROL, - #endif - #if GDISP_NEED_QUERY - GDISP_LLD_MSG_QUERY, - #endif -} gdisp_msgaction_t; - -typedef union gdisp_lld_msg { - gdisp_msgaction_t action; - struct gdisp_lld_msg_init { - gdisp_msgaction_t action; // GDISP_LLD_MSG_INIT - } init; - struct gdisp_lld_msg_clear { - gdisp_msgaction_t action; // GDISP_LLD_MSG_CLEAR - color_t color; - } clear; - struct gdisp_lld_msg_drawpixel { - gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWPIXEL - coord_t x, y; - color_t color; - } drawpixel; - struct gdisp_lld_msg_fillarea { - gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLAREA - coord_t x, y; - coord_t cx, cy; - color_t color; - } fillarea; - struct gdisp_lld_msg_blitarea { - gdisp_msgaction_t action; // GDISP_LLD_MSG_BLITAREA - coord_t x, y; - coord_t cx, cy; - coord_t srcx, srcy; - coord_t srccx; - const pixel_t *buffer; - } blitarea; - struct gdisp_lld_msg_setclip { - gdisp_msgaction_t action; // GDISP_LLD_MSG_SETCLIP - coord_t x, y; - coord_t cx, cy; - } setclip; - struct gdisp_lld_msg_drawline { - gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWLINE - coord_t x0, y0; - coord_t x1, y1; - color_t color; - } drawline; - struct gdisp_lld_msg_drawcircle { - gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCIRCLE - coord_t x, y; - coord_t radius; - color_t color; - } drawcircle; - struct gdisp_lld_msg_fillcircle { - gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCIRCLE - coord_t x, y; - coord_t radius; - color_t color; - } fillcircle; - struct gdisp_lld_msg_drawellipse { - gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWELLIPSE - coord_t x, y; - coord_t a, b; - color_t color; - } drawellipse; - struct gdisp_lld_msg_fillellipse { - gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLELLIPSE - coord_t x, y; - coord_t a, b; - color_t color; - } fillellipse; - struct gdisp_lld_msg_drawarc { - gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWARC - coord_t x, y; - coord_t radius; - coord_t startangle, endangle; - color_t color; - } drawcircle; - struct gdisp_lld_msg_fillarc { - gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLARC - coord_t x, y; - coord_t radius; - coord_t startangle, endangle; - color_t color; - } fillcircle; - struct gdisp_lld_msg_drawchar { - gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCHAR - coord_t x, y; - char c; - font_t font; - color_t color; - } drawchar; - struct gdisp_lld_msg_fillchar { - gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCHAR - coord_t x, y; - char c; - font_t font; - color_t color; - color_t bgcolor; - } fillchar; - struct gdisp_lld_msg_getpixelcolor { - gdisp_msgaction_t action; // GDISP_LLD_MSG_GETPIXELCOLOR - coord_t x, y; - color_t result; - } getpixelcolor; - struct gdisp_lld_msg_verticalscroll { - gdisp_msgaction_t action; // GDISP_LLD_MSG_VERTICALSCROLL - coord_t x, y; - coord_t cx, cy; - int lines; - color_t bgcolor; - } verticalscroll; - struct gdisp_lld_msg_control { - gdisp_msgaction_t action; // GDISP_LLD_MSG_CONTROL - int what; - void * value; - } control; - struct gdisp_lld_msg_query { - gdisp_msgaction_t action; // GDISP_LLD_MSG_QUERY - int what; - void * result; - } query; -} gdisp_lld_msg_t; - -#endif /* GFX_USE_GDISP */ -#endif /* _GDISP_LLD_MSGS_H */ -/** @} */ - diff --git a/include/gevent.h b/include/gevent.h index e7c5dcbf..fa735452 100644 --- a/include/gevent.h +++ b/include/gevent.h @@ -100,11 +100,16 @@ typedef union GEvent_u { char pad[GEVENT_MAXIMUM_STATUS_SIZE]; // This is here to allow static initialisation of GEventObject's in the application. } GEvent; +// A special callback function +typedef void (*GEventCallbackFn)(void *param, GEvent *pe); + // The Listener Object typedef struct GListener { - Semaphore waitqueue; // Private: Semaphore for the listener to wait on. - BinarySemaphore eventlock; // Private: Protect against more than one sources trying to use this event lock at the same time - GEvent event; // Public: The event object into which the event information is stored. + Semaphore waitqueue; // Private: Semaphore for the listener to wait on. + BinarySemaphore eventlock; // Private: Protect against more than one sources trying to use this event lock at the same time + GEventCallbackFn callback; // Private: Call back Function + void *param; // Private: Parameter for the callback function. + GEvent event; // Public: The event object into which the event information is stored. } GListener; // The Source Object @@ -177,13 +182,29 @@ void geventDetachSource(GListener *pl, GSourceHandle gsh); * timeout specifies the time to wait in system ticks. * TIME_INFINITE means no timeout - wait forever for an event. * TIME_IMMEDIATE means return immediately - * Returns NULL on timeout. + * Returns NULL on timeout or if a callback function is already registered. * Note: The GEvent buffer is staticly allocated within the GListener so the event does not * need to be dynamicly freed however it will get overwritten by the next call to * this routine. */ GEvent *geventEventWait(GListener *pl, systime_t timeout); +/* Register a callback for an event on a listener from an assigned source. + * The type of the event should be checked (pevent->type) and then pevent should be typecast to the + * actual event type if it needs to be processed. + * Note: The GEvent buffer is valid only during the time of the callback. The callback MUST NOT save + * a pointer to the buffer for use outside the callback. + * Note: An existing callback function is de-registered by passing a NULL for 'fn'. Any existing + * callback function is replaced. Any thread currently waiting using geventEventWait will be sent the exit event. + * Note: Callbacks occur in a thread context but stack space must be kept to a minumum and + * the callback must process quickly as all other events are performed on a single thread. + * Note: In the callback function you should never call ANY event functions using your own GListener handle + * as it WILL create a deadlock and lock the system up. + * Note: Applications should not use this call - geventEventWait() is the preferred mechanism for an + * application. This call is provided for GUI objects that may not have their own thread. + */ +void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param); + /*---------- Source Functions --------------------------------------------*/ /* Sources create their own GSourceHandles which are pointers to any arbitrary structure diff --git a/include/ginput.h b/include/ginput.h index de2c617b..dc472e8e 100644 --- a/include/ginput.h +++ b/include/ginput.h @@ -37,41 +37,6 @@ * @name GINPUT more complex functionality to be compiled * @{ */ - /** - * @brief Should mouse functions be included. - * @details Defaults to FALSE - */ - #ifndef GINPUT_NEED_MOUSE - #define GINPUT_NEED_MOUSE FALSE - #endif - /** - * @brief Should touch functions be included. - * @details Defaults to FALSE - */ - #ifndef GINPUT_NEED_TOUCH - #define GINPUT_NEED_TOUCH FALSE - #endif - /** - * @brief Should keyboard functions be included. - * @details Defaults to FALSE - */ - #ifndef GINPUT_NEED_KEYBOARD - #define GINPUT_NEED_KEYBOARD FALSE - #endif - /** - * @brief Should hardware toggle/switch/button (pio) functions be included. - * @details Defaults to FALSE - */ - #ifndef GINPUT_NEED_TOGGLE - #define GINPUT_NEED_TOGGLE FALSE - #endif - /** - * @brief Should analog dial functions be included. - * @details Defaults to FALSE - */ - #ifndef GINPUT_NEED_DIAL - #define GINPUT_NEED_DIAL FALSE - #endif /** @} */ /*===========================================================================*/ @@ -81,10 +46,6 @@ #ifndef GFX_USE_GDISP #define GFX_USE_GDISP FALSE #endif -#if GINPUT_NEED_TOUCH || !GFX_USE_GDISP - #error "GINPUT: GFX_USE_GDISP must be defined for touch functions" -#endif - #if GFX_USE_GDISP #include "gdisp.h" #else @@ -94,14 +55,13 @@ #ifndef GFX_USE_GEVENT #define GFX_USE_GEVENT TRUE - #include "gevent.h" #elif !GFX_USE_GEVENT #error "GINPUT: GFX_USE_GEVENT must be defined" #endif +#include "gevent.h" #ifndef GFX_USE_GTIMER #define GFX_USE_GTIMER TRUE - #include "gtimer.h" #elif !GFX_USE_GTIMER #error "GINPUT: GFX_USE_GTIMER must be defined" #endif @@ -110,138 +70,10 @@ /* Type definitions */ /*===========================================================================*/ -// Event types for various ginput sources -#define GEVENT_MOUSE (GEVENT_GINPUT_FIRST+0) -#define GEVENT_TOUCH (GEVENT_GINPUT_FIRST+1) -#define GEVENT_KEYBOARD (GEVENT_GINPUT_FIRST+2) -#define GEVENT_TOGGLE (GEVENT_GINPUT_FIRST+3) -#define GEVENT_DIAL (GEVENT_GINPUT_FIRST+4) - -#if GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH - typedef struct GEventMouse_t { - GEventType type; // The type of this event (GEVENT_MOUSE or GEVENT_TOUCH) - uint16_t instance; // The mouse/touch instance - coord_t x, y, z; // The position of the mouse. - // - For touch devices, Z is the current pressure if supported (otherwise 0) - // - For mice, Z is the 3rd dimension if supported (otherwise 0) - uint16_t current_buttons; // A bit is set if the button is down. - // - For touch only bit 0 is relevant - // - For mice the order of the buttons is (from 0 to n) left, right, middle, any other buttons - // - Bit 15 being set indicates that an important mouse event has been missed. - #define GINPUT_TOUCH_PRESSED 0x0001 - #define GINPUT_MOUSE_BTN_LEFT 0x0001 - #define GINPUT_MOUSE_BTN_RIGHT 0x0002 - #define GINPUT_MOUSE_BTN_MIDDLE 0x0004 - #define GINPUT_MOUSE_BTN_4 0x0008 - #define GINPUT_MISSED_MOUSE_EVENT 0x8000 - uint16_t last_buttons; // The value of current_buttons on the last event - enum GMouseMeta_e { - GMETA_NONE, // There is no meta event currently happenning - GMETA_DOWN, GMETA_UP, // Button 0 has just gone up or down - GMETA_CLICK, // Button 0 has just gone through a short down - up cycle - GMETA_CXTCLICK // For mice - The right button has just been depressed - // For touch - a long press has just occurred - } meta; - } GEventMouse, GEventTouch; - - // Mouse/Touch Listen Flags - passed to geventAddSourceToListener() - #define GLISTEN_MOUSEMETA 0x0001 // Create events for meta events such as CLICK and CXTCLICK - #define GLISTEN_MOUSEDOWNMOVES 0x0002 // Creates mouse move events when the primary mouse button is down (touch is on the surface) - #define GLISTEN_MOUSEUPMOVES 0x0004 // Creates mouse move events when the primary mouse button is up (touch is off the surface - if the hardware allows). - #define GLISTEN_TOUCHMETA 0x0001 // Ditto for touch - #define GLISTEN_TOUCHDOWNMOVES 0x0002 - #define GLISTEN_TOUCHUPMOVES 0x0004 -#endif - -#if GINPUT_NEED_KEYBOARD - typedef struct GEventKeyboard_t { - GEventType type; // The type of this event (GEVENT_KEYBOARD) - uint16_t instance; // The keyboard instance - char c; // The Ascii code for the current key press. - // The only possible values are 0(NUL), 8(BS), 9(TAB), 13(CR), 27(ESC), 32(SPACE) to 126(~), 127(DEL) - // 0 indicates an extended only key. - uint16_t code; // An extended keyboard code. Codes less than 128 match their ascii equivelent. - #define GKEY_NULL 0 - #define GKEY_BACKSPACE 8 - #define GKEY_TAB 9 - #define GKEY_CR 13 - #define GKEY_ESC 27 - #define GKEY_SPACE 32 - #define GKEY_DEL 127 - #define GKEY_UP 0x0101 - #define GKEY_DOWN 0x0102 - #define GKEY_LEFT 0x0103 - #define GKEY_RIGHT 0x0104 - #define GKEY_HOME 0x0105 - #define GKEY_END 0x0106 - #define GKEY_PAGEUP 0x0107 - #define GKEY_PAGEDOWN 0x0108 - #define GKEY_INSERT 0x0109 - #define GKEY_DELETE 0x010A - #define GKEY_SHIFT 0x0201 - #define GKEY_CNTRL 0x0202 - #define GKEY_ALT 0x0203 - #define GKEY_WINKEY 0x0204 - #define GKEY_RCLKEY 0x0205 - #define GKEY_FNKEY 0x0206 - #define GKEY_FN1 0x0301 - #define GKEY_FN2 0x0302 - #define GKEY_FN3 0x0303 - #define GKEY_FN4 0x0304 - #define GKEY_FN5 0x0305 - #define GKEY_FN6 0x0306 - #define GKEY_FN7 0x0307 - #define GKEY_FN8 0x0308 - #define GKEY_FN9 0x0309 - #define GKEY_FN10 0x030A - #define GKEY_FN11 0x030B - #define GKEY_FN12 0x030C - uint16_t current_buttons; // A bit is set to indicate various meta status. - #define GMETA_KEYDN 0x0001 - #define GMETA_SHIFT 0x0002 - #define GMETA_CNTRL 0x0004 - #define GMETA_ALT 0x0008 - #define GMETA_WINKEY 0x0010 - #define GMETA_RCLKKEY 0x0020 - #define GMETA_FNKEY 0x0040 - #define GMETA_MISSED_EVENT 0x8000 - uint16_t last_buttons; // The value of current_buttons on the last event - } GEventKeyboard; - - // Keyboard Listen Flags - passed to geventAddSourceToListener() - #define GLISTEN_KEYREPEATS 0x0001 // Return key repeats (where the key is held down to get a repeat character) - #define GLISTEN_KEYCODES 0x0002 // Return all key presses including extended code key presses (not just ascii codes) - #define GLISTEN_KEYALL 0x0004 // Return keyup's, keydown's and everything in between (but not repeats unless GLISTEN_KEYREPEATS is set). - #define GLISTEN_KEYSINGLE 0x8000 // Return only when one particular extended code key is pressed or released. The particular extended code is OR'd into this value - // eg. (GLISTEN_KEYSINGLE | GKEY_CR) - // No other flags may be set with this flag. -#endif - -#if GINPUT_NEED_TOGGLE - typedef struct GEventToggle_t { - GEventType type; // The type of this event (GEVENT_TOGGLE) - uint16_t instance; // The toggle instance - BOOL on; // True if the toggle/button is on - } GEventToggle; -#endif - -#if GINPUT_NEED_DIAL - typedef struct GEventDial_t { - GEventType type; // The type of this event (GEVENT_DIAL) - uint16_t instance; // The dial instance - uint16_t value; // The dial value - } GEventDial; -#endif - - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ -#ifdef __cplusplus -extern "C" { -#endif - /* How to use... 1. Get source handles for all the inputs you are interested in. @@ -254,84 +86,11 @@ extern "C" { 5. When complete destroy the listener */ -#if GINPUT_NEED_MOUSE - /* Mouse Functions */ - GSourceHandle ginputGetMouse(uint16_t instance); // Instance = 0 to n-1 - - /* Get the current mouse position and button status. - * Unlike a listener event, this status cannot record meta events such as "CLICK" - * Returns FALSE on error (eg invalid instance) - */ - BOOL ginputGetMouseStatus(uint16_t instance, GEventMouse *pmouse); -#endif - -#if GINPUT_NEED_TOUCH - /* Touch Functions */ - GSourceHandle ginputGetTouch(uint16_t instance); // Instance = 0 to n-1 - - /* Get the current touch position and button status. - * Unlike a listener event, this status cannot record meta events such as "CLICK" - * Returns FALSE on error (eg invalid instance) - */ - BOOL ginputGetTouchStatus(uint16_t instance, GEventTouch *ptouch); - - /* Run a touch calibration. - * Returns FALSE if the driver doesn't support it or if the handle is invalid. - */ - BOOL ginputCalibrateTouch(uint16_t instance); - - /* Set the routines to save and fetch calibration data. - * This function should be called before first calling ginputGetTouch() for a particular instance - * as the gdispGetTouch() 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 gdispGetTouch() 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. - */ - typedef void (*)(uint16_t instance, const uint8_t *calbuf, size_t sz) GTouchCalibrationSaveRoutine; // Save calibration data - typedef const char * (*)(uint16_t instance) GTouchCalibrationFetchRoutine; // Fetch calibration data (returns NULL if not data saved) - void ginputSetTouchCalibrationRoutines(uint16_t instance, GTouchCalibrationSaveRoutine fnsave, GTouchCalibrationFetchRoutine fnfetch, BOOL requireFree); - - /* Test if a particular touch instance requires routines to save its calibration data. */ - BOOL ginputRequireTouchCalibrationStorage(uint16_t instance); -#endif - -#if GINPUT_NEED_KEYBOARD - /* Keyboard Functions */ - GSourceHandle ginputGetKeyboard(uint16_t instance); // Instance = 0 to n-1 - - /* Get the current keyboard button status. - * Returns FALSE on error (eg invalid instance) - */ - BOOL ginputGetKeyboardStatus(uint16_t instance, GEventKeyboard *pkeyboard); -#endif - -#if GINPUT_NEED_TOGGLE - /* Hardware Toggle/Switch/Button Functions */ - GSourceHandle ginputGetToggle(uint16_t instance); // Instance = 0 to n-1 - void ginputInvertToggle(uint16_t instance, BOOL invert); // If invert is true, invert the on/off sense for the toggle - - /* Get the current toggle status. - * Returns FALSE on error (eg invalid instance) - */ - BOOL ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle); -#endif - -#if GINPUT_NEED_DIAL - /* Dial Functions */ - GSourceHandle ginputGetDial(uint16_t instance); // Instance = 0 to n-1 - void ginputResetDialRange(uint16_t instance); // Reset the maximum value back to the hardware default. - uint16_t ginputGetDialRange(uint16_t instance); // Get the maximum value. The readings are scaled to be 0...max-1. 0 means over the full uint16_t range. - void ginputSetDialRange(uint16_t instance, uint16_t max); // Set the maximum value. - void ginputSetDialSensitivity(uint16_t instance, uint16_t diff); // Set the level change required before a dial event is generated. - // - This is done after range scaling - /* Get the current keyboard button status. - * Returns FALSE on error (eg invalid instance) - */ - BOOL ginputGetDialStatus(uint16_t instance, GEventDial *pdial); -#endif - -#ifdef __cplusplus -} -#endif +// Include various ginput types +#include "ginput/ginput_mouse.h" +#include "ginput/ginput_keyboard.h" +#include "ginput/ginput_toggle.h" +#include "ginput/ginput_dial.h" #endif /* GFX_USE_GINPUT */ diff --git a/include/ginput/ginput_dial.h b/include/ginput/ginput_dial.h new file mode 100644 index 00000000..71448c0b --- /dev/null +++ b/include/ginput/ginput_dial.h @@ -0,0 +1,89 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file ginput/ginput_dial.h + * @brief GINPUT GFX User Input subsystem header file. + * + * @addtogroup GINPUT + * @{ + */ +#ifndef _GINPUT_DIAL_H +#define _GINPUT_DIAL_H + +/** + * @name GINPUT more complex functionality to be compiled + * @{ + */ + /** + * @brief Should analog dial functions be included. + * @details Defaults to FALSE + */ + #ifndef GINPUT_NEED_DIAL + #define GINPUT_NEED_DIAL FALSE + #endif +/** @} */ + +#if GINPUT_NEED_DIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Low Level Driver details and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +// Event types for various ginput sources +#define GEVENT_DIAL (GEVENT_GINPUT_FIRST+4) + +typedef struct GEventDial_t { + GEventType type; // The type of this event (GEVENT_DIAL) + uint16_t instance; // The dial instance + uint16_t value; // The dial value + } GEventDial; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + /* Dial Functions */ + GSourceHandle ginputGetDial(uint16_t instance); // Instance = 0 to n-1 + void ginputResetDialRange(uint16_t instance); // Reset the maximum value back to the hardware default. + uint16_t ginputGetDialRange(uint16_t instance); // Get the maximum value. The readings are scaled to be 0...max-1. 0 means over the full uint16_t range. + void ginputSetDialRange(uint16_t instance, uint16_t max); // Set the maximum value. + void ginputSetDialSensitivity(uint16_t instance, uint16_t diff); // Set the level change required before a dial event is generated. + // - This is done after range scaling + /* Get the current keyboard button status. + * Returns FALSE on error (eg invalid instance) + */ + bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial); + +#ifdef __cplusplus +} +#endif + +#endif /* GINPUT_NEED_DIAL */ + +#endif /* _GINPUT_DIAL_H */ +/** @} */ diff --git a/include/ginput/ginput_keyboard.h b/include/ginput/ginput_keyboard.h new file mode 100644 index 00000000..850adf38 --- /dev/null +++ b/include/ginput/ginput_keyboard.h @@ -0,0 +1,143 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file ginput/ginput_keyboard.h + * @brief GINPUT GFX User Input subsystem header file. + * + * @addtogroup GINPUT + * @{ + */ +#ifndef _GINPUT_KEYBOARD_H +#define _GINPUT_KEYBOARD_H + +/** + * @name GINPUT more complex functionality to be compiled + * @{ + */ + /** + * @brief Should keyboard functions be included. + * @details Defaults to FALSE + */ + #ifndef GINPUT_NEED_KEYBOARD + #define GINPUT_NEED_KEYBOARD FALSE + #endif +/** @} */ + +#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Low Level Driver details and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +#define GINPUT_KEYBOARD_NUM_PORTS 1 // The total number of keyboard inputs + +// Event types for various ginput sources +#define GEVENT_KEYBOARD (GEVENT_GINPUT_FIRST+2) + +typedef struct GEventKeyboard_t { + GEventType type; // The type of this event (GEVENT_KEYBOARD) + uint16_t instance; // The keyboard instance + char c; // The Ascii code for the current key press. + // The only possible values are 0(NUL), 8(BS), 9(TAB), 13(CR), 27(ESC), 32(SPACE) to 126(~), 127(DEL) + // 0 indicates an extended only key. + uint16_t code; // An extended keyboard code. Codes less than 128 match their ascii equivelent. + #define GKEY_NULL 0 + #define GKEY_BACKSPACE 8 + #define GKEY_TAB 9 + #define GKEY_CR 13 + #define GKEY_ESC 27 + #define GKEY_SPACE 32 + #define GKEY_DEL 127 + #define GKEY_UP 0x0101 + #define GKEY_DOWN 0x0102 + #define GKEY_LEFT 0x0103 + #define GKEY_RIGHT 0x0104 + #define GKEY_HOME 0x0105 + #define GKEY_END 0x0106 + #define GKEY_PAGEUP 0x0107 + #define GKEY_PAGEDOWN 0x0108 + #define GKEY_INSERT 0x0109 + #define GKEY_DELETE 0x010A + #define GKEY_SHIFT 0x0201 + #define GKEY_CNTRL 0x0202 + #define GKEY_ALT 0x0203 + #define GKEY_WINKEY 0x0204 + #define GKEY_RCLKEY 0x0205 + #define GKEY_FNKEY 0x0206 + #define GKEY_FN1 0x0301 + #define GKEY_FN2 0x0302 + #define GKEY_FN3 0x0303 + #define GKEY_FN4 0x0304 + #define GKEY_FN5 0x0305 + #define GKEY_FN6 0x0306 + #define GKEY_FN7 0x0307 + #define GKEY_FN8 0x0308 + #define GKEY_FN9 0x0309 + #define GKEY_FN10 0x030A + #define GKEY_FN11 0x030B + #define GKEY_FN12 0x030C + uint16_t current_buttons; // A bit is set to indicate various meta status. + #define GMETA_KEY_DOWN 0x0001 + #define GMETA_KEY_SHIFT 0x0002 + #define GMETA_KEY_CNTRL 0x0004 + #define GMETA_KEY_ALT 0x0008 + #define GMETA_KEY_WINKEY 0x0010 + #define GMETA_KEY_RCLKKEY 0x0020 + #define GMETA_KEY_FN 0x0040 + #define GMETA_KEY_MISSED_EVENT 0x8000 + uint16_t last_buttons; // The value of current_buttons on the last event +} GEventKeyboard; + +// Keyboard Listen Flags - passed to geventAddSourceToListener() +#define GLISTEN_KEYREPEATS 0x0001 // Return key repeats (where the key is held down to get a repeat character) +#define GLISTEN_KEYCODES 0x0002 // Return all key presses including extended code key presses (not just ascii codes) +#define GLISTEN_KEYALL 0x0004 // Return keyup's, keydown's and everything in between (but not repeats unless GLISTEN_KEYREPEATS is set). +#define GLISTEN_KEYSINGLE 0x8000 // Return only when one particular extended code key is pressed or released. The particular extended code is OR'd into this value + // eg. (GLISTEN_KEYSINGLE | GKEY_CR) + // No other flags may be set with this flag. + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + /* Keyboard Functions */ + GSourceHandle ginputGetKeyboard(uint16_t instance); // Instance = 0 to n-1 + + /* Get the current keyboard button status. + * Returns FALSE on error (eg invalid instance) + */ + bool_t ginputGetKeyboardStatus(uint16_t instance, GEventKeyboard *pkeyboard); + +#ifdef __cplusplus +} +#endif + +#endif /* GINPUT_NEED_KEYBOARD */ + +#endif /* _GINPUT_KEYBOARD_H */ +/** @} */ diff --git a/include/ginput/ginput_mouse.h b/include/ginput/ginput_mouse.h new file mode 100644 index 00000000..1b596ac9 --- /dev/null +++ b/include/ginput/ginput_mouse.h @@ -0,0 +1,135 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file ginput/ginput_mouse.h + * @brief GINPUT GFX User Input subsystem header file for mouse and touch. + * + * @addtogroup GINPUT + * @{ + */ +#ifndef _GINPUT_MOUSE_H +#define _GINPUT_MOUSE_H + +/** + * @name GINPUT more complex functionality to be compiled + * @{ + */ + /** + * @brief Should mouse/touch functions be included. + * @details Defaults to FALSE + */ + #ifndef GINPUT_NEED_MOUSE + #define GINPUT_NEED_MOUSE FALSE + #endif +/** @} */ + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__) + +/* This type definition is also used by touch */ +typedef struct GEventMouse_t { + GEventType type; // The type of this event (GEVENT_MOUSE or GEVENT_TOUCH) + uint16_t instance; // The mouse/touch instance + coord_t x, y, z; // The position of the mouse. + // - For touch devices, Z is the current pressure if supported (otherwise 0) + // - For mice, Z is the 3rd dimension if supported (otherwise 0) + uint16_t current_buttons; // A bit is set if the button is down. + // - For touch only bit 0 is relevant + // - For mice the order of the buttons is (from 0 to n) left, right, middle, any other buttons + // - Bit 15 being set indicates that an important mouse event has been missed. + #define GINPUT_MOUSE_BTN_LEFT 0x0001 + #define GINPUT_MOUSE_BTN_RIGHT 0x0002 + #define GINPUT_MOUSE_BTN_MIDDLE 0x0004 + #define GINPUT_MOUSE_BTN_4 0x0008 + #define GINPUT_MISSED_MOUSE_EVENT 0x8000 + #define GINPUT_TOUCH_PRESSED GINPUT_MOUSE_BTN_LEFT + uint16_t last_buttons; // The value of current_buttons on the last event + enum GMouseMeta_e { + GMETA_NONE = 0, // There is no meta event currently happening + GMETA_MOUSE_DOWN = 1, // Button 0 has just gone down + GMETA_MOUSE_UP = 2, // Button 0 has just gone up + GMETA_MOUSE_CLICK = 4, // Button 0 has just gone through a short down - up cycle + GMETA_MOUSE_CXTCLICK = 8 // For mice - The right button has just been depressed + // For touch - a long press has just occurred + } meta; + } GEventMouse; + +// Mouse/Touch Listen Flags - passed to geventAddSourceToListener() +#define GLISTEN_MOUSEMETA 0x0001 // Create events for meta events such as CLICK and CXTCLICK +#define GLISTEN_MOUSEDOWNMOVES 0x0002 // Creates mouse move events when the primary mouse button is down (touch is on the surface) +#define GLISTEN_MOUSEUPMOVES 0x0004 // Creates mouse move events when the primary mouse button is up (touch is off the surface - if the hardware allows). +#define GLISTEN_MOUSENOFILTER 0x0008 // Don't filter out mouse moves where the position hasn't changed. +#define GLISTEN_TOUCHMETA GLISTEN_MOUSEMETA +#define GLISTEN_TOUCHDOWNMOVES GLISTEN_MOUSEDOWNMOVES +#define GLISTEN_TOUCHUPMOVES GLISTEN_MOUSEUPMOVES +#define GLISTEN_TOUCHNOFILTER GLISTEN_MOUSENOFILTER + +#define GINPUT_MOUSE_NUM_PORTS 1 // The total number of mouse/touch inputs supported + +// Event types for the mouse ginput source +#define GEVENT_MOUSE (GEVENT_GINPUT_FIRST+0) +#define GEVENT_TOUCH (GEVENT_GINPUT_FIRST+1) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + /* Mouse Functions */ + GSourceHandle ginputGetMouse(uint16_t instance); // Instance = 0 to n-1 + + /* Get the current mouse position and button status. + * Unlike a listener event, this status cannot record meta events such as "CLICK" + * Returns FALSE on error (eg invalid instance) + */ + bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pmouse); + + /* Run a calibration. + * Returns FALSE if the driver doesn't support it or if the handle is invalid. + */ + bool_t ginputCalibrateMouse(uint16_t instance); + + /* 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. + */ + typedef void (*GMouseCalibrationSaveRoutine)(uint16_t instance, const uint8_t *calbuf, size_t sz); // Save calibration data + typedef const char * (*GMouseCalibrationLoadRoutine)(uint16_t instance); // Load calibration data (returns NULL if not data saved) + void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree); + + /* Test if a particular mouse/touch instance requires routines to save its calibration data. */ + bool_t ginputRequireMouseCalibrationStorage(uint16_t instance); + +#ifdef __cplusplus +} +#endif + +#endif /* GINPUT_NEED_MOUSE */ + +#endif /* _GINPUT_MOUSE_H */ +/** @} */ diff --git a/include/ginput/ginput_toggle.h b/include/ginput/ginput_toggle.h new file mode 100644 index 00000000..10be1da9 --- /dev/null +++ b/include/ginput/ginput_toggle.h @@ -0,0 +1,93 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file ginput/ginput_toggle.h + * @brief GINPUT GFX User Input subsystem header file. + * + * @addtogroup GINPUT + * @{ + */ +#ifndef _GINPUT_TOGGLE_H +#define _GINPUT_TOGGLE_H + +/** + * @name GINPUT more complex functionality to be compiled + * @{ + */ + /** + * @brief Should hardware toggle/switch/button (pio) functions be included. + * @details Defaults to FALSE + */ + #ifndef GINPUT_NEED_TOGGLE + #define GINPUT_NEED_TOGGLE FALSE + #endif +/** @} */ + +#if GINPUT_NEED_TOGGLE || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Low Level Driver details and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +// Event types for various ginput sources +#define GEVENT_TOGGLE (GEVENT_GINPUT_FIRST+3) + +// Get the hardware definitions - Number of instances etc. +#include "ginput_lld_toggle_config.h" + +typedef struct GEventToggle_t { + GEventType type; // The type of this event (GEVENT_TOGGLE) + uint16_t instance; // The toggle instance + bool_t on; // True if the toggle/button is on + } GEventToggle; + +// Toggle Listen Flags - passed to geventAddSourceToListener() +#define GLISTEN_TOGGLE_ON 0x0001 // Return an event when the toggle turns on +#define GLISTEN_TOGGLE_OFF 0x0002 // Return an event when the toggle turns off + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + /* Hardware Toggle/Switch/Button Functions */ + GSourceHandle ginputGetToggle(uint16_t instance); // Instance = 0 to n-1 + void ginputInvertToggle(uint16_t instance, bool_t invert); // If invert is true, invert the on/off sense for the toggle + + /* Get the current toggle status. + * Returns FALSE on error (eg invalid instance) + */ + bool_t ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle); + +#ifdef __cplusplus +} +#endif + +#endif /* GINPUT_NEED_TOGGLE */ + +#endif /* _GINPUT_TOGGLE_H */ +/** @} */ diff --git a/include/gtimer.h b/include/gtimer.h index 76c52583..cf25ac8a 100644 --- a/include/gtimer.h +++ b/include/gtimer.h @@ -40,7 +40,7 @@ /** * @brief Data part of a static GTimer initializer. */ - #define _GTIMER_DATA() {0} + #define _GTIMER_DATA() {0,0,0,0,0,0,0} /** * @brief Static GTimer initializer. */ @@ -80,7 +80,7 @@ typedef struct GTimer_t { uint16_t flags; struct GTimer_t *next; struct GTimer_t *prev; -} GTimer; + } GTimer; /*===========================================================================*/ /* External declarations. */ @@ -93,6 +93,7 @@ extern "C" { void gtimerInit(GTimer *pt); void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, systime_t millisec); void gtimerStop(GTimer *pt); +bool_t gtimerIsActive(GTimer *pt); void gtimerJab(GTimer *pt); void gtimerJabI(GTimer *pt); diff --git a/include/gwin.h b/include/gwin.h index 24eba20c..f54c8d37 100644 --- a/include/gwin.h +++ b/include/gwin.h @@ -45,21 +45,6 @@ * @name GWIN more complex functionality to be compiled * @{ */ - /** - * @brief Should console functions be included. - * @details Defaults to FALSE - */ - #ifndef GWIN_NEED_CONSOLE - #define GWIN_NEED_CONSOLE FALSE - #endif - /** - * @brief Should button functions be included. - * @details Defaults to FALSE - */ - #ifndef GWIN_NEED_BUTTON - #define GWIN_NEED_BUTTON FALSE - #endif - /** @} */ /*===========================================================================*/ @@ -75,25 +60,13 @@ #warning "GWIN: Drawing can occur outside the defined window as GDISP_NEED_CLIP is FALSE" #endif -#if GWIN_NEED_CONSOLE && !GDISP_NEED_TEXT - #error "GWIN: Text support (GDISP_NEED_TEXT) is required if GWIN_NEED_CONSOLE is defined." -#endif - -#if GWIN_NEED_BUTTON && !GDISP_NEED_TEXT - #error "GWIN: Text support (GDISP_NEED_TEXT) is required if GWIN_NEED_BUTTON is defined." -#endif - -#if GWIN_NEED_BUTTON - #warning "GWIN: Button support is not complete yet" -#endif - /*===========================================================================*/ /* Type definitions */ /*===========================================================================*/ -typedef enum GWindowType_e { - GW_WINDOW, GW_CONSOLE, GW_BUTTON - } GWindowType; +typedef uint16_t GWindowType; +#define GW_WINDOW 0x0000 +#define GW_FIRST_USER_WINDOW 0x8000 // A basic window typedef struct GWindowObject_t { @@ -107,58 +80,6 @@ typedef struct GWindowObject_t { #endif } GWindowObject, * GHandle; -#if GWIN_NEED_CONSOLE - // A console window. Supports wrapped text writing and a cursor. - typedef struct GConsoleObject_t { - GWindowObject gwin; - - struct GConsoleWindowStream_t { - const struct GConsoleWindowVMT_t *vmt; - _base_asynchronous_channel_data - } stream; - - coord_t cx,cy; // Cursor position - uint8_t fy; // Current font height - uint8_t fp; // Current font inter-character spacing - } GConsoleObject; -#endif - -#if GWIN_NEED_BUTTON - typedef enum GButtonShape_e { - GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE - } GButtonShape; - - typedef struct GButtonStyle_t { - GButtonShape shape; - color_t color_up_edge; - color_t color_up_fill; - color_t color_up_txt; - color_t color_dn_edge; - color_t color_dn_fill; - color_t color_dn_txt; - } GButtonStyle; - - typedef enum GButtonType_e { - GBTN_NORMAL, GBTN_TOGGLE - } GButtonType; - - typedef enum GButtonState_e { - GBTN_UP, GBTN_DOWN - } GButtonState; - - // A button window - typedef struct GButtonObject_t { - GWindowObject gwin; - - GButtonStyle style; - GButtonState state; - GButtonType type; - const char * txt; - void * callback; // To be fixed - void * inputsrc; // To be fixed - } GButtonObject; -#endif - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -237,59 +158,45 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor /* Circle Functions */ #if GDISP_NEED_CIRCLE -void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius); -void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius); + void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius); + void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius); #endif /* Ellipse Functions */ #if GDISP_NEED_ELLIPSE -void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b); -void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b); + void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b); + void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b); #endif /* Arc Functions */ #if GDISP_NEED_ARC -void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle); -void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle); + void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle); + void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle); #endif /* Read a pixel Function */ #if GDISP_NEED_PIXELREAD -color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y); + color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y); #endif /* Extra Text Functions */ #if GDISP_NEED_TEXT -void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c); -void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c); -void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str); -void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str); -void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify); -void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify); -#endif - -#if GWIN_NEED_CONSOLE -GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font); -BaseSequentialStream *gwinGetConsoleStream(GHandle gh); -void gwinPutChar(GHandle gh, char c); -void gwinPutString(GHandle gh, const char *str); -void gwinPutCharArray(GHandle gh, const char *str, size_t n); -#endif - -#if GWIN_NEED_BUTTON -GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type); -void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style); -void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc); -void gwinButtonDraw(GHandle gh); -#define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state) -//void gwinSetButtonCallback(GHandle gh, ????); -//void gwinSetButtonInput(GHandle gh, ????); + void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c); + void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c); + void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str); + void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str); + void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify); + void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify); #endif #ifdef __cplusplus } #endif +/* Include extra window types */ +#include "gwin/gwin_console.h" +#include "gwin/gwin_button.h" + #endif /* GFX_USE_GWIN */ #endif /* _GWIN_H */ diff --git a/include/gwin/gwin_button.h b/include/gwin/gwin_button.h new file mode 100644 index 00000000..69a2474c --- /dev/null +++ b/include/gwin/gwin_button.h @@ -0,0 +1,142 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file gwin/gwin_button.h + * @brief GWIN Graphic window subsystem header file. + * + * @addtogroup GWIN + * @{ + */ +#ifndef _GWIN_BUTTON_H +#define _GWIN_BUTTON_H + +/** + * @name GWIN more complex functionality to be compiled + * @{ + */ + /** + * @brief Should button functions be included. + * @details Defaults to FALSE + */ + #ifndef GWIN_NEED_BUTTON + #define GWIN_NEED_BUTTON FALSE + #endif + +/** @} */ + +#if GWIN_NEED_BUTTON || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define GW_BUTTON 0x0002 +#define GEVENT_GWIN_BUTTON (GEVENT_GWIN_FIRST+0) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Low Level Driver details and error checks. */ +/*===========================================================================*/ + +#if !GDISP_NEED_TEXT + #error "GWIN: Text support (GDISP_NEED_TEXT) is required if GWIN_NEED_BUTTON is defined." +#endif + +#if !defined(GFX_USE_GEVENT) || !GFX_USE_GEVENT + #error "GWIN Buttons require GFX_USE_GEVENT" +#endif +#include "gevent.h" + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +typedef struct GEventGWinButton_t { + GEventType type; // The type of this event (GEVENT_GWIN_BUTTON) + GHandle button; // The button that has been depressed (actually triggered on release) +} GEventGWinButton; + +// There are currently no GEventGWinButton listening flags - use 0 + +typedef enum GButtonShape_e { + GBTN_3D, GBTN_SQUARE, GBTN_ROUNDED, GBTN_ELLIPSE +} GButtonShape; + +typedef struct GButtonStyle_t { + GButtonShape shape; + color_t color_up_edge; + color_t color_up_fill; + color_t color_up_txt; + color_t color_dn_edge; + color_t color_dn_fill; + color_t color_dn_txt; +} GButtonStyle; + +typedef enum GButtonType_e { + GBTN_NORMAL, GBTN_TOGGLE +} GButtonType; + +typedef enum GButtonState_e { + GBTN_UP, GBTN_DOWN +} GButtonState; + +// A button window +typedef struct GButtonObject_t { + GWindowObject gwin; + + GButtonStyle style; + GButtonState state; + GButtonType type; + const char * txt; + GListener listener; +} GButtonObject; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, coord_t height, font_t font, GButtonType type); + void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style); + void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc); + void gwinButtonDraw(GHandle gh); + #define gwinGetButtonState(gh) (((GButtonObject *)(gh))->state) + + // Get the source handle so the application can listen for events + #define gwinGetButtonSource(gh) ((GSourceHandle)(gh)) + + // Attach a source to this button. Sources recognised: Mouse, Touch and Toggle - others are ignored (returns false). + bool_t gwinAttachButtonSource(GHandle gh, GSourceHandle gsh, GEventType type); + +#ifdef __cplusplus +} +#endif + +#endif /* GWIN_NEED_BUTTON */ + +#endif /* _GWIN_BUTTON_H */ +/** @} */ diff --git a/include/gwin/gwin_console.h b/include/gwin/gwin_console.h new file mode 100644 index 00000000..5462ec2b --- /dev/null +++ b/include/gwin/gwin_console.h @@ -0,0 +1,102 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file gwin/gwin_console.h + * @brief GWIN Graphic window subsystem header file. + * + * @addtogroup GWIN + * @{ + */ +#ifndef _GWIN_CONSOLE_H +#define _GWIN_CONSOLE_H + +/** + * @name GWIN more complex functionality to be compiled + * @{ + */ + /** + * @brief Should console functions be included. + * @details Defaults to FALSE + */ + #ifndef GWIN_NEED_CONSOLE + #define GWIN_NEED_CONSOLE FALSE + #endif +/** @} */ + +#if GWIN_NEED_CONSOLE || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define GW_CONSOLE 0x0001 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Low Level Driver details and error checks. */ +/*===========================================================================*/ + +#if GWIN_NEED_CONSOLE && !GDISP_NEED_TEXT + #error "GWIN: Text support (GDISP_NEED_TEXT) is required if GWIN_NEED_CONSOLE is defined." +#endif + +/*===========================================================================*/ +/* Type definitions */ +/*===========================================================================*/ + +// A console window. Supports wrapped text writing and a cursor. +typedef struct GConsoleObject_t { + GWindowObject gwin; + + struct GConsoleWindowStream_t { + const struct GConsoleWindowVMT_t *vmt; + _base_asynchronous_channel_data + } stream; + + coord_t cx,cy; // Cursor position + uint8_t fy; // Current font height + uint8_t fp; // Current font inter-character spacing + } GConsoleObject; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font); + BaseSequentialStream *gwinGetConsoleStream(GHandle gh); + void gwinPutChar(GHandle gh, char c); + void gwinPutString(GHandle gh, const char *str); + void gwinPutCharArray(GHandle gh, const char *str, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* GWIN_NEED_CONSOLE */ + +#endif /* _GWIN_CONSOLE_H */ +/** @} */ diff --git a/include/lld/gdisp/emulation.c b/include/lld/gdisp/emulation.c new file mode 100644 index 00000000..88a8c42f --- /dev/null +++ b/include/lld/gdisp/emulation.c @@ -0,0 +1,770 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + Emulation routines included into gdisp_lld.c +*/ + +/* + Even though this is a software emulation of a low level driver + most validation doesn't need to happen here as eventually + we call a real low level driver routine and if validation is + required - it will do it. +*/ +#ifndef GDISP_EMULATION_C +#define GDISP_EMULATION_C + +#if GFX_USE_GDISP || defined(__DOXYGEN__) + +#ifndef GDISP_LLD_NO_STRUCT + static struct GDISPDriver { + coord_t Width; + coord_t Height; + gdisp_orientation_t Orientation; + gdisp_powermode_t Powermode; + uint8_t Backlight; + uint8_t Contrast; + #if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION + coord_t clipx0, clipy0; + coord_t clipx1, clipy1; /* not inclusive */ + #endif + } GDISP; +#endif + +#if !GDISP_HARDWARE_CLEARS + void GDISP_LLD(clear)(color_t color) { + GDISP_LLD(fillarea)(0, 0, GDISP.Width, GDISP.Height, color); + } +#endif + +#if !GDISP_HARDWARE_LINES + void GDISP_LLD(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { + int16_t dy, dx; + int16_t addx, addy; + int16_t P, diff, i; + + #if GDISP_HARDWARE_FILLS || GDISP_HARDWARE_SCROLL + // speed improvement if vertical or horizontal + if (x0 == x1) { + if (y1 > y0) + GDISP_LLD(fillarea)(x0, y0, 1, y1-y0+1, color); + else + GDISP_LLD(fillarea)(x0, y1, 1, y0-y1+1, color); + return; + } + if (y0 == y1) { + if (x1 > x0) + GDISP_LLD(fillarea)(x0, y0, x1-x0+1, 1, color); + else + GDISP_LLD(fillarea)(x0, y1, x0-x1+1, 1, color); + return; + } + #endif + + 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) { + GDISP_LLD(drawpixel)(x0, y0, color); + 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) { + GDISP_LLD(drawpixel)(x0, y0, color); + if (P < 0) { + P += dx; + y0 += addy; + } else { + P += diff; + x0 += addx; + y0 += addy; + } + } + } + } +#endif + +#if !GDISP_HARDWARE_FILLS + void GDISP_LLD(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { + #if GDISP_HARDWARE_SCROLL + GDISP_LLD(verticalscroll)(x, y, cx, cy, cy, color); + #elif GDISP_HARDWARE_LINES + coord_t x1, y1; + + x1 = x + cx - 1; + y1 = y + cy; + for(; y < y1; y++) + GDISP_LLD(drawline)(x, y, x1, y, color); + #else + coord_t x0, x1, y1; + + x0 = x; + x1 = x + cx; + y1 = y + cy; + for(; y < y1; y++) + for(x = x0; x < x1; x++) + GDISP_LLD(drawpixel)(x, y, color); + #endif + } +#endif + +#if !GDISP_HARDWARE_BITFILLS + void GDISP_LLD(blitareaex)(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 x0, x1, y1; + + x0 = x; + x1 = x + cx; + y1 = y + cy; + buffer += srcy*srccx+srcx; + srccx -= cx; + for(; y < y1; y++, buffer += srccx) + for(x=x0; x < x1; x++) + GDISP_LLD(drawpixel)(x, y, *buffer++); + } +#endif + +#if GDISP_NEED_CLIP && !GDISP_HARDWARE_CLIP + void GDISP_LLD(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy) { + #if GDISP_NEED_VALIDATION + if (x >= GDISP.Width || y >= GDISP.Height || cx < 0 || cy < 0) + return; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x+cx > GDISP.Width) cx = GDISP.Width - x; + if (y+cy > GDISP.Height) cy = GDISP.Height - y; + #endif + GDISP.clipx0 = x; + GDISP.clipy0 = y; + GDISP.clipx1 = x+cx; + GDISP.clipy1 = y+cy; + } +#endif + +#if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLES + void GDISP_LLD(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { + coord_t a, b, P; + + a = 0; + b = radius; + P = 1 - radius; + + do { + GDISP_LLD(drawpixel)(x+a, y+b, color); + GDISP_LLD(drawpixel)(x+b, y+a, color); + GDISP_LLD(drawpixel)(x-a, y+b, color); + GDISP_LLD(drawpixel)(x-b, y+a, color); + GDISP_LLD(drawpixel)(x+b, y-a, color); + GDISP_LLD(drawpixel)(x+a, y-b, color); + GDISP_LLD(drawpixel)(x-a, y-b, color); + GDISP_LLD(drawpixel)(x-b, y-a, color); + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a <= b); + } +#endif + +#if GDISP_NEED_CIRCLE && !GDISP_HARDWARE_CIRCLEFILLS + void GDISP_LLD(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color) { + coord_t a, b, P; + + a = 0; + b = radius; + P = 1 - radius; + + do { + GDISP_LLD(drawline)(x-a, y+b, x+a, y+b, color); + GDISP_LLD(drawline)(x-a, y-b, x+a, y-b, color); + GDISP_LLD(drawline)(x-b, y+a, x+b, y+a, color); + GDISP_LLD(drawline)(x-b, y-a, x+b, y-a, color); + if (P < 0) + P += 3 + 2*a++; + else + P += 5 + 2*(a++ - b--); + } while(a <= b); + } +#endif + +#if GDISP_NEED_ELLIPSE && !GDISP_HARDWARE_ELLIPSES + void GDISP_LLD(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { + int dx = 0, dy = b; /* im I. Quadranten von links oben nach rechts unten */ + long a2 = a*a, b2 = b*b; + long err = b2-(2*b-1)*a2, e2; /* Fehler im 1. Schritt */ + + do { + GDISP_LLD(drawpixel)(x+dx, y+dy, color); /* I. Quadrant */ + GDISP_LLD(drawpixel)(x-dx, y+dy, color); /* II. Quadrant */ + GDISP_LLD(drawpixel)(x-dx, y-dy, color); /* III. Quadrant */ + GDISP_LLD(drawpixel)(x+dx, y-dy, color); /* IV. Quadrant */ + + e2 = 2*err; + if(e2 < (2*dx+1)*b2) { + dx++; + err += (2*dx+1)*b2; + } + if(e2 > -(2*dy-1)*a2) { + dy--; + err -= (2*dy-1)*a2; + } + } while(dy >= 0); + + while(dx++ < a) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */ + GDISP_LLD(drawpixel)(x+dx, y, color); /* -> Spitze der Ellipse vollenden */ + GDISP_LLD(drawpixel)(x-dx, y, color); + } + } +#endif + +#if GDISP_NEED_ELLIPSE && !GDISP_HARDWARE_ELLIPSEFILLS + void GDISP_LLD(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { + int dx = 0, dy = b; /* im I. Quadranten von links oben nach rechts unten */ + long a2 = a*a, b2 = b*b; + long err = b2-(2*b-1)*a2, e2; /* Fehler im 1. Schritt */ + + do { + GDISP_LLD(drawline)(x-dx,y+dy,x+dx,y+dy, color); + GDISP_LLD(drawline)(x-dx,y-dy,x+dx,y-dy, color); + + e2 = 2*err; + if(e2 < (2*dx+1)*b2) { + dx++; + err += (2*dx+1)*b2; + } + if(e2 > -(2*dy-1)*a2) { + dy--; + err -= (2*dy-1)*a2; + } + } while(dy >= 0); + + while(dx++ < a) { /* fehlerhafter Abbruch bei flachen Ellipsen (b=1) */ + GDISP_LLD(drawpixel)(x+dx, y, color); /* -> Spitze der Ellipse vollenden */ + GDISP_LLD(drawpixel)(x-dx, y, color); + } + } +#endif + +#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCS + + #include + + /* + * @brief Internal helper function for gdispDrawArc() + * + * @note DO NOT USE DIRECTLY! + * + * @param[in] x, y The middle point of the arc + * @param[in] start The start angle of the arc + * @param[in] end The end angle of the arc + * @param[in] radius The radius of the arc + * @param[in] color The color in which the arc will be drawn + * + * @notapi + */ + static void _draw_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) { + if (/*start >= 0 && */start <= 180) { + float x_maxI = x + radius*cos(start*M_PI/180); + float x_minI; + + if (end > 180) + x_minI = x - radius; + else + x_minI = x + radius*cos(end*M_PI/180); + + int a = 0; + int b = radius; + int P = 1 - radius; + + do { + if(x-a <= x_maxI && x-a >= x_minI) + GDISP_LLD(drawpixel)(x-a, y-b, color); + if(x+a <= x_maxI && x+a >= x_minI) + GDISP_LLD(drawpixel)(x+a, y-b, color); + if(x-b <= x_maxI && x-b >= x_minI) + GDISP_LLD(drawpixel)(x-b, y-a, color); + if(x+b <= x_maxI && x+b >= x_minI) + GDISP_LLD(drawpixel)(x+b, y-a, color); + + if (P < 0) { + P = P + 3 + 2*a; + a = a + 1; + } else { + P = P + 5 + 2*(a - b); + a = a + 1; + b = b - 1; + } + } while(a <= b); + } + + if (end > 180 && end <= 360) { + float x_maxII = x+radius*cos(end*M_PI/180); + float x_minII; + + if(start <= 180) + x_minII = x - radius; + else + x_minII = x+radius*cos(start*M_PI/180); + + int a = 0; + int b = radius; + int P = 1 - radius; + + do { + if(x-a <= x_maxII && x-a >= x_minII) + GDISP_LLD(drawpixel)(x-a, y+b, color); + if(x+a <= x_maxII && x+a >= x_minII) + GDISP_LLD(drawpixel)(x+a, y+b, color); + if(x-b <= x_maxII && x-b >= x_minII) + GDISP_LLD(drawpixel)(x-b, y+a, color); + if(x+b <= x_maxII && x+b >= x_minII) + GDISP_LLD(drawpixel)(x+b, y+a, color); + + if (P < 0) { + P = P + 3 + 2*a; + a = a + 1; + } else { + P = P + 5 + 2*(a - b); + a = a + 1; + b = b - 1; + } + } while (a <= b); + } + } + + void GDISP_LLD(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + if(endangle < startangle) { + _draw_arc(x, y, startangle, 360, radius, color); + _draw_arc(x, y, 0, endangle, radius, color); + } else { + _draw_arc(x, y, startangle, endangle, radius, color); + } + } +#endif + +#if GDISP_NEED_ARC && !GDISP_HARDWARE_ARCFILLS + /* + * @brief Internal helper function for gdispDrawArc() + * + * @note DO NOT USE DIRECTLY! + * + * @param[in] x, y The middle point of the arc + * @param[in] start The start angle of the arc + * @param[in] end The end angle of the arc + * @param[in] radius The radius of the arc + * @param[in] color The color in which the arc will be drawn + * + * @notapi + */ + static void _fill_arc(coord_t x, coord_t y, uint16_t start, uint16_t end, uint16_t radius, color_t color) { + if (/*start >= 0 && */start <= 180) { + float x_maxI = x + radius*cos(start*M_PI/180); + float x_minI; + + if (end > 180) + x_minI = x - radius; + else + x_minI = x + radius*cos(end*M_PI/180); + + int a = 0; + int b = radius; + int P = 1 - radius; + + do { + if(x-a <= x_maxI && x-a >= x_minI) + GDISP_LLD(drawline)(x, y, x-a, y-b, color); + if(x+a <= x_maxI && x+a >= x_minI) + GDISP_LLD(drawline)(x, y, x+a, y-b, color); + if(x-b <= x_maxI && x-b >= x_minI) + GDISP_LLD(drawline)(x, y, x-b, y-a, color); + if(x+b <= x_maxI && x+b >= x_minI) + GDISP_LLD(drawline)(x, y, x+b, y-a, color); + + if (P < 0) { + P = P + 3 + 2*a; + a = a + 1; + } else { + P = P + 5 + 2*(a - b); + a = a + 1; + b = b - 1; + } + } while(a <= b); + } + + if (end > 180 && end <= 360) { + float x_maxII = x+radius*cos(end*M_PI/180); + float x_minII; + + if(start <= 180) + x_minII = x - radius; + else + x_minII = x+radius*cos(start*M_PI/180); + + int a = 0; + int b = radius; + int P = 1 - radius; + + do { + if(x-a <= x_maxII && x-a >= x_minII) + GDISP_LLD(drawline)(x, y, x-a, y+b, color); + if(x+a <= x_maxII && x+a >= x_minII) + GDISP_LLD(drawline)(x, y, x+a, y+b, color); + if(x-b <= x_maxII && x-b >= x_minII) + GDISP_LLD(drawline)(x, y, x-b, y+a, color); + if(x+b <= x_maxII && x+b >= x_minII) + GDISP_LLD(drawline)(x, y, x+b, y+a, color); + + if (P < 0) { + P = P + 3 + 2*a; + a = a + 1; + } else { + P = P + 5 + 2*(a - b); + a = a + 1; + b = b - 1; + } + } while (a <= b); + } + } + + void GDISP_LLD(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color) { + if(endangle < startangle) { + _fill_arc(x, y, startangle, 360, radius, color); + _fill_arc(x, y, 0, endangle, radius, color); + } else { + _fill_arc(x, y, startangle, endangle, radius, color); + } + } +#endif + +#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT + #include "gdisp/fonts.h" +#endif + +#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT + void GDISP_LLD(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color) { + const fontcolumn_t *ptr; + fontcolumn_t column; + coord_t width, height, xscale, yscale; + coord_t i, j, xs, ys; + + /* Check we actually have something to print */ + width = _getCharWidth(font, c); + if (!width) return; + + xscale = font->xscale; + yscale = font->yscale; + height = font->height * yscale; + width *= xscale; + + ptr = _getCharData(font, c); + + /* Loop through the data and display. The font data is LSBit first, down the column */ + for(i=0; i < width; i+=xscale) { + /* Get the font bitmap data for the column */ + column = *ptr++; + + /* Draw each pixel */ + for(j=0; j < height; j+=yscale, column >>= 1) { + if (column & 0x01) { + for(xs=0; xs < xscale; xs++) + for(ys=0; ys < yscale; ys++) + GDISP_LLD(drawpixel)(x+i+xs, y+j+ys, color); + } + } + } + } +#endif + +#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXTFILLS + void GDISP_LLD(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor) { + coord_t width, height; + coord_t xscale, yscale; + + /* Check we actually have something to print */ + width = _getCharWidth(font, c); + if (!width) return; + + xscale = font->xscale; + yscale = font->yscale; + height = font->height * yscale; + width *= xscale; + + /* Method 1: Use background fill and then draw the text */ + #if GDISP_HARDWARE_TEXT || GDISP_SOFTWARE_TEXTFILLDRAW + + /* Fill the area */ + GDISP_LLD(fillarea)(x, y, width, height, bgcolor); + + /* Draw the text */ + GDISP_LLD(drawchar)(x, y, c, font, color); + + /* Method 2: Create a single column bitmap and then blit it */ + #elif GDISP_HARDWARE_BITFILLS && GDISP_SOFTWARE_TEXTBLITCOLUMN + { + const fontcolumn_t *ptr; + fontcolumn_t column; + coord_t i, j, xs, ys; + + /* Working buffer for fast non-transparent text rendering [patch by Badger] + This needs to be larger than the largest character we can print. + Assume the max is double sized by one column. + */ + static pixel_t buf[sizeof(fontcolumn_t)*8*2]; + + #if GDISP_NEED_VALIDATION + /* Check our buffer is big enough */ + if ((unsigned)height > sizeof(buf)/sizeof(buf[0])) return; + #endif + + ptr = _getCharData(font, c); + + /* Loop through the data and display. The font data is LSBit first, down the column */ + for(i = 0; i < width; i+=xscale) { + /* Get the font bitmap data for the column */ + column = *ptr++; + + /* Draw each pixel */ + for(j = 0; j < height; j+=yscale, column >>= 1) { + if (column & 0x01) { + for(ys=0; ys < yscale; ys++) + gdispPackPixels(buf, 1, j+ys, 0, color); + } else { + for(ys=0; ys < yscale; ys++) + gdispPackPixels(buf, 1, j+ys, 0, bgcolor); + } + } + + for(xs=0; xs < xscale; xs++) + GDISP_LLD(blitareaex)(x+i+xs, y, 1, height, 0, 0, 1, buf); + } + } + + /* Method 3: Create a character bitmap and then blit it */ + #elif GDISP_HARDWARE_BITFILLS + { + const fontcolumn_t *ptr; + fontcolumn_t column; + coord_t i, j, xs, ys; + + /* Working buffer for fast non-transparent text rendering [patch by Badger] + This needs to be larger than the largest character we can print. + Assume the max is double sized. + */ + static pixel_t buf[20*(sizeof(fontcolumn_t)*8)*2]; + + #if GDISP_NEED_VALIDATION + /* Check our buffer is big enough */ + if ((unsigned)(width * height) > sizeof(buf)/sizeof(buf[0])) return; + #endif + + ptr = _getCharData(font, c); + + /* Loop through the data and display. The font data is LSBit first, down the column */ + for(i = 0; i < width; i+=xscale) { + /* Get the font bitmap data for the column */ + column = *ptr++; + + /* Draw each pixel */ + for(j = 0; j < height; j+=yscale, column >>= 1) { + if (column & 0x01) { + for(xs=0; xs < xscale; xs++) + for(ys=0; ys < yscale; ys++) + gdispPackPixels(buf, width, i+xs, j+ys, color); + } else { + for(xs=0; xs < xscale; xs++) + for(ys=0; ys < yscale; ys++) + gdispPackPixels(buf, width, i+xs, j+ys, bgcolor); + } + } + } + + /* [Patch by Badger] Write all in one stroke */ + GDISP_LLD(blitareaex)(x, y, width, height, 0, 0, width, buf); + } + + /* Method 4: Draw pixel by pixel */ + #else + { + const fontcolumn_t *ptr; + fontcolumn_t column; + coord_t i, j, xs, ys; + + ptr = _getCharData(font, c); + + /* Loop through the data and display. The font data is LSBit first, down the column */ + for(i = 0; i < width; i+=xscale) { + /* Get the font bitmap data for the column */ + column = *ptr++; + + /* Draw each pixel */ + for(j = 0; j < height; j+=yscale, column >>= 1) { + if (column & 0x01) { + for(xs=0; xs < xscale; xs++) + for(ys=0; ys < yscale; ys++) + GDISP_LLD(drawpixel)(x+i+xs, y+j+ys, color); + } else { + for(xs=0; xs < xscale; xs++) + for(ys=0; ys < yscale; ys++) + GDISP_LLD(drawpixel)(x+i+xs, y+j+ys, bgcolor); + } + } + } + } + #endif + } +#endif + + +#if GDISP_NEED_CONTROL && !GDISP_HARDWARE_CONTROL + void GDISP_LLD(control)(unsigned what, void *value) { + (void)what; + (void)value; + /* Ignore everything */ + } +#endif + +#if GDISP_NEED_QUERY && !GDISP_HARDWARE_QUERY +void *GDISP_LLD(query)(unsigned what) { + switch(what) { + case GDISP_QUERY_WIDTH: return (void *)(unsigned)GDISP.Width; + case GDISP_QUERY_HEIGHT: return (void *)(unsigned)GDISP.Height; + case GDISP_QUERY_POWER: return (void *)(unsigned)GDISP.Powermode; + case GDISP_QUERY_ORIENTATION: return (void *)(unsigned)GDISP.Orientation; + case GDISP_QUERY_BACKLIGHT: return (void *)(unsigned)GDISP.Backlight; + case GDISP_QUERY_CONTRAST: return (void *)(unsigned)GDISP.Contrast; + default: return (void *)-1; + } +} +#endif + +#if GDISP_NEED_MSGAPI + void GDISP_LLD(msgdispatch)(gdisp_lld_msg_t *msg) { + switch(msg->action) { + case GDISP_LLD_MSG_NOP: + break; + case GDISP_LLD_MSG_INIT: + GDISP_LLD(init)(); + break; + case GDISP_LLD_MSG_CLEAR: + GDISP_LLD(clear)(msg->clear.color); + break; + case GDISP_LLD_MSG_DRAWPIXEL: + GDISP_LLD(drawpixel)(msg->drawpixel.x, msg->drawpixel.y, msg->drawpixel.color); + break; + case GDISP_LLD_MSG_FILLAREA: + GDISP_LLD(fillarea)(msg->fillarea.x, msg->fillarea.y, msg->fillarea.cx, msg->fillarea.cy, msg->fillarea.color); + break; + case GDISP_LLD_MSG_BLITAREA: + GDISP_LLD(blitareaex)(msg->blitarea.x, msg->blitarea.y, msg->blitarea.cx, msg->blitarea.cy, msg->blitarea.srcx, msg->blitarea.srcy, msg->blitarea.srccx, msg->blitarea.buffer); + break; + case GDISP_LLD_MSG_DRAWLINE: + GDISP_LLD(drawline)(msg->drawline.x0, msg->drawline.y0, msg->drawline.x1, msg->drawline.y1, msg->drawline.color); + break; + #if GDISP_NEED_CLIP + case GDISP_LLD_MSG_SETCLIP: + GDISP_LLD(setclip)(msg->setclip.x, msg->setclip.y, msg->setclip.cx, msg->setclip.cy); + break; + #endif + #if GDISP_NEED_CIRCLE + case GDISP_LLD_MSG_DRAWCIRCLE: + GDISP_LLD(drawcircle)(msg->drawcircle.x, msg->drawcircle.y, msg->drawcircle.radius, msg->drawcircle.color); + break; + case GDISP_LLD_MSG_FILLCIRCLE: + GDISP_LLD(fillcircle)(msg->fillcircle.x, msg->fillcircle.y, msg->fillcircle.radius, msg->fillcircle.color); + break; + #endif + #if GDISP_NEED_ELLIPSE + case GDISP_LLD_MSG_DRAWELLIPSE: + GDISP_LLD(drawellipse)(msg->drawellipse.x, msg->drawellipse.y, msg->drawellipse.a, msg->drawellipse.b, msg->drawellipse.color); + break; + case GDISP_LLD_MSG_FILLELLIPSE: + GDISP_LLD(fillellipse)(msg->fillellipse.x, msg->fillellipse.y, msg->fillellipse.a, msg->fillellipse.b, msg->fillellipse.color); + break; + #endif + #if GDISP_NEED_ARC + case GDISP_LLD_MSG_DRAWARC: + GDISP_LLD(drawcircle)(msg->drawarc.x, msg->drawarc.y, msg->drawarc.radius, msg->drawarc.startangle, msg->drawarc.endangle, msg->drawarc.color); + break; + case GDISP_LLD_MSG_FILLARC: + GDISP_LLD(fillcircle)(msg->fillarc.x, msg->fillarc.y, msg->fillarc.radius, msg->fillarc.startangle, msg->fillarc.endangle, msg->fillarc.color); + break; + #endif + #if GDISP_NEED_TEXT + case GDISP_LLD_MSG_DRAWCHAR: + GDISP_LLD(drawchar)(msg->drawchar.x, msg->drawchar.y, msg->drawchar.c, msg->drawchar.font, msg->drawchar.color); + break; + case GDISP_LLD_MSG_FILLCHAR: + GDISP_LLD(fillchar)(msg->fillchar.x, msg->fillchar.y, msg->fillchar.c, msg->fillchar.font, msg->fillchar.color, msg->fillchar.bgcolor); + break; + #endif + #if GDISP_NEED_PIXELREAD + case GDISP_LLD_MSG_GETPIXELCOLOR: + msg->getpixelcolor.result = GDISP_LLD(getpixelcolor)(msg->getpixelcolor.x, msg->getpixelcolor.y); + break; + #endif + #if GDISP_NEED_SCROLL + case GDISP_LLD_MSG_VERTICALSCROLL: + GDISP_LLD(verticalscroll)(msg->verticalscroll.x, msg->verticalscroll.y, msg->verticalscroll.cx, msg->verticalscroll.cy, msg->verticalscroll.lines, msg->verticalscroll.bgcolor); + break; + #endif + #if GDISP_NEED_CONTROL + case GDISP_LLD_MSG_CONTROL: + GDISP_LLD(control)(msg->control.what, msg->control.value); + break; + #endif + #if GDISP_NEED_QUERY + case GDISP_LLD_MSG_QUERY: + msg->query.result = GDISP_LLD(query)(msg->query.what); + break; + #endif + } + } +#endif + +#endif /* GFX_USE_GDISP */ +#endif /* GDISP_EMULATION_C */ + diff --git a/include/lld/gdisp/gdisp_lld.h b/include/lld/gdisp/gdisp_lld.h new file mode 100644 index 00000000..fecd710a --- /dev/null +++ b/include/lld/gdisp/gdisp_lld.h @@ -0,0 +1,650 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file include/gdisp_lld.h + * @brief GDISP Graphic Driver subsystem low level driver header. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_H +#define _GDISP_LLD_H + +#if GFX_USE_GDISP || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Low level driver configuration needs */ +/*===========================================================================*/ + +/** + * @name GDISP low level driver more complex functionality to be compiled + * @{ + */ + /** + * @brief Should all operations be clipped to the screen and colors validated. + * @details Defaults to TRUE. + * @note If this is FALSE, any operations that extend beyond the + * edge of the screen will have undefined results. Any + * out-of-range colors will produce undefined results. + * @note If defined then all low level and high level driver routines + * must check the validity of inputs and do something sensible + * if they are out of range. It doesn't have to be efficient, + * just valid. + */ + #ifndef GDISP_NEED_VALIDATION + #define GDISP_NEED_VALIDATION TRUE + #endif + + /** + * @brief Are circle functions needed. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_CIRCLE + #define GDISP_NEED_CIRCLE TRUE + #endif + + /** + * @brief Are ellipse functions needed. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_ELLIPSE + #define GDISP_NEED_ELLIPSE TRUE + #endif + + /** + * @brief Are arc functions needed. + * @details Defaults to FALSE + */ + #ifndef GDISP_NEED_ARC + #define GDISP_NEED_ARC FALSE + #endif + + /** + * @brief Are text functions needed. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_TEXT + #define GDISP_NEED_TEXT TRUE + #endif + + /** + * @brief Is scrolling needed. + * @details Defaults to FALSE + */ + #ifndef GDISP_NEED_SCROLL + #define GDISP_NEED_SCROLL FALSE + #endif + + /** + * @brief Is the capability to read pixels back needed. + * @details Defaults to FALSE + */ + #ifndef GDISP_NEED_PIXELREAD + #define GDISP_NEED_PIXELREAD FALSE + #endif + + /** + * @brief Are clipping functions needed. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_CLIP + #define GDISP_NEED_CLIP FALSE + #endif + + /** + * @brief Control some aspect of the drivers operation. + * @details Defaults to FALSE + */ + #ifndef GDISP_NEED_CONTROL + #define GDISP_NEED_CONTROL FALSE + #endif + + /** + * @brief Query some aspect of the drivers operation. + * @details Defaults to TRUE + */ + #ifndef GDISP_NEED_QUERY + #define GDISP_NEED_QUERY TRUE + #endif + + /** + * @brief Is the messaging api interface required. + * @details Defaults to FALSE + */ + #ifndef GDISP_NEED_MSGAPI + #define GDISP_NEED_MSGAPI FALSE + #endif +/** @} */ + +/*===========================================================================*/ +/* Include the low level driver configuration information */ +/*===========================================================================*/ + +#include "gdisp_lld_config.h" + +/*===========================================================================*/ +/* Constants. */ +/*===========================================================================*/ + +/** + * @brief Driver Control Constants + * @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. + * GDISP_CONTROL_CONTRAST - Takes an int from 0 to 100. + * GDISP_CONTROL_LLD - Low level driver control constants start at + * this value. + */ +#define GDISP_CONTROL_POWER 0 +#define GDISP_CONTROL_ORIENTATION 1 +#define GDISP_CONTROL_BACKLIGHT 2 +#define GDISP_CONTROL_CONTRAST 3 +#define GDISP_CONTROL_LLD 1000 + +/** + * @brief Driver Query Constants + * @details Unsupported query codes return (void *)-1. + * @note There are some predefined and some specific to the low level driver. + * @note The result should be typecast the required type. + * @note GDISP_QUERY_WIDTH - Gets the width of the screen + * GDISP_QUERY_HEIGHT - Gets the height of the screen + * GDISP_QUERY_POWER - Get the current powermode + * GDISP_QUERY_ORIENTATION - Get the current orientation + * GDISP_QUERY_BACKLIGHT - Get the backlight state (0 to 100) + * GDISP_QUERY_CONTRAST - Get the contrast. + * GDISP_QUERY_LLD - Low level driver control constants start at + * this value. + */ +#define GDISP_QUERY_WIDTH 0 +#define GDISP_QUERY_HEIGHT 1 +#define GDISP_QUERY_POWER 2 +#define GDISP_QUERY_ORIENTATION 3 +#define GDISP_QUERY_BACKLIGHT 4 +#define GDISP_QUERY_CONTRAST 5 +#define GDISP_QUERY_LLD 1000 + +/** + * @brief Driver Pixel Format Constants + */ +#define GDISP_PIXELFORMAT_RGB565 565 +#define GDISP_PIXELFORMAT_RGB888 888 +#define GDISP_PIXELFORMAT_RGB444 444 +#define GDISP_PIXELFORMAT_RGB332 332 +#define GDISP_PIXELFORMAT_RGB666 666 +#define GDISP_PIXELFORMAT_CUSTOM 99999 +#define GDISP_PIXELFORMAT_ERROR 88888 + +/*===========================================================================*/ +/* Error checks. */ +/*===========================================================================*/ + +/** + * @name GDISP hardware accelerated support + * @{ + */ + /** + * @brief Hardware accelerated line drawing. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_LINES + #define GDISP_HARDWARE_LINES FALSE + #endif + + /** + * @brief Hardware accelerated screen clears. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_CLEARS + #define GDISP_HARDWARE_CLEARS FALSE + #endif + + /** + * @brief Hardware accelerated rectangular fills. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_FILLS + #define GDISP_HARDWARE_FILLS FALSE + #endif + + /** + * @brief Hardware accelerated fills from an image. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_BITFILLS + #define GDISP_HARDWARE_BITFILLS FALSE + #endif + + /** + * @brief Hardware accelerated circles. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_CIRCLES + #define GDISP_HARDWARE_CIRCLES FALSE + #endif + + /** + * @brief Hardware accelerated filled circles. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_CIRCLEFILLS + #define GDISP_HARDWARE_CIRCLEFILLS FALSE + #endif + + /** + * @brief Hardware accelerated ellipses. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_ELLIPSES + #define GDISP_HARDWARE_ELLIPSES FALSE + #endif + + /** + * @brief Hardware accelerated filled ellipses. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_ELLIPSEFILLS + #define GDISP_HARDWARE_ELLIPSEFILLS FALSE + #endif + + /** + * @brief Hardware accelerated arc's. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_ARCS + #define GDISP_HARDWARE_ARCS FALSE + #endif + + /** + * @brief Hardware accelerated filled arcs. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_ARCFILLS + #define GDISP_HARDWARE_ARCFILLS FALSE + #endif + + /** + * @brief Hardware accelerated text drawing. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_TEXT + #define GDISP_HARDWARE_TEXT FALSE + #endif + + /** + * @brief Hardware accelerated text drawing with a filled background. + * @details If set to @p FALSE software emulation is used. + */ + #ifndef GDISP_HARDWARE_TEXTFILLS + #define GDISP_HARDWARE_TEXTFILLS FALSE + #endif + + /** + * @brief Hardware accelerated scrolling. + * @details If set to @p FALSE there is no support for scrolling. + */ + #ifndef GDISP_HARDWARE_SCROLL + #define GDISP_HARDWARE_SCROLL FALSE + #endif + + /** + * @brief Reading back of pixel values. + * @details If set to @p FALSE there is no support for pixel read-back. + */ + #ifndef GDISP_HARDWARE_PIXELREAD + #define GDISP_HARDWARE_PIXELREAD FALSE + #endif + + /** + * @brief The driver supports one or more control commands. + * @details If set to @p FALSE there is no support for control commands. + */ + #ifndef GDISP_HARDWARE_CONTROL + #define GDISP_HARDWARE_CONTROL FALSE + #endif + + /** + * @brief The driver supports a non-standard query. + * @details If set to @p FALSE there is no support for non-standard queries. + */ + #ifndef GDISP_HARDWARE_QUERY + #define GDISP_HARDWARE_QUERY FALSE + #endif + + /** + * @brief The driver supports a clipping in hardware. + * @details If set to @p FALSE there is no support for non-standard queries. + */ + #ifndef GDISP_HARDWARE_CLIP + #define GDISP_HARDWARE_CLIP FALSE + #endif +/** @} */ + +/** + * @name GDISP software algorithm choices + * @{ + */ + /** + * @brief For filled text drawing, use a background fill and then draw + * the text instead of using a blit or direct pixel drawing. + * @details If set to @p TRUE background fill and then text draw is used. + * @note This is ignored if hardware accelerated text is supported. + */ + #ifndef GDISP_SOFTWARE_TEXTFILLDRAW + #define GDISP_SOFTWARE_TEXTFILLDRAW FALSE + #endif + + /** + * @brief For filled text drawing, when using a bitmap blit + * use a column by column buffer rather than a full character + * buffer to save memory at a small performance cost. + * @details If set to @p TRUE background fill one character column at a time. + * @note This is ignored if software text using blit is not being used. + */ + #ifndef GDISP_SOFTWARE_TEXTBLITCOLUMN + #define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE + #endif +/** @} */ + +/** + * @name GDISP pixel format choices + * @{ + */ + /** + * @brief The native pixel format for this device + * @note Should be set to one of the following: + * GDISP_PIXELFORMAT_RGB565 + * GDISP_PIXELFORMAT_RGB888 + * GDISP_PIXELFORMAT_RGB444 + * GDISP_PIXELFORMAT_RGB332 + * GDISP_PIXELFORMAT_RGB666 + * GDISP_PIXELFORMAT_CUSTOM + * @note If you set GDISP_PIXELFORMAT_CUSTOM you need to also define + * color_t, RGB2COLOR(r,g,b), HTML2COLOR(h), + * RED_OF(c), GREEN_OF(c), BLUE_OF(c), + * COLOR(c) and MASKCOLOR. + */ + #ifndef GDISP_PIXELFORMAT + #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_ERROR + #endif + + /** + * @brief Do pixels require packing for a blit + * @note Is only valid for a pixel format that doesn't fill it's datatype. ie formats: + * GDISP_PIXELFORMAT_RGB888 + * GDISP_PIXELFORMAT_RGB444 + * GDISP_PIXELFORMAT_RGB666 + * GDISP_PIXELFORMAT_CUSTOM + * @note If you use GDISP_PIXELFORMAT_CUSTOM and packed bit fills + * you need to also define @p gdispPackPixels(buf,cx,x,y,c) + * @note If you are using GDISP_HARDWARE_BITFILLS = FALSE then the pixel + * format must not be a packed format as the software blit does + * not support packed pixels + * @note Very few cases should actually require packed pixels as the low + * level driver can also pack on the fly as it is sending it + * to the graphics device. + */ + #ifndef GDISP_PACKED_PIXELS + #define GDISP_PACKED_PIXELS FALSE + #endif + + /** + * @brief Do lines of pixels require packing for a blit + * @note Ignored if GDISP_PACKED_PIXELS is FALSE + */ + #ifndef GDISP_PACKED_LINES + #define GDISP_PACKED_LINES FALSE + #endif +/** @} */ + +/*===========================================================================*/ +/* Define the macro's for the various pixel formats */ +/*===========================================================================*/ + +#if defined(__DOXYGEN__) + /** + * @brief The color of a pixel. + */ + typedef uint16_t color_t; + /** + * @brief Convert a number (of any type) to a color_t. + * @details Masks any invalid bits in the color + */ + #define COLOR(c) ((color_t)(c)) + /** + * @brief Does the color_t type contain invalid bits that need masking. + */ + #define MASKCOLOR FALSE + /** + * @brief Convert red, green, blue (each 0 to 255) into a color value. + */ + #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF8)<<8) | (((g) & 0xFC)<<3) | (((b) & 0xF8)>>3))) + /** + * @brief Convert a 6 digit HTML code (hex) into a color value. + */ + #define HTML2COLOR(h) ((color_t)((((h) & 0xF80000)>>8) | (((h) & 0x00FC00)>>5) | (((h) & 0x0000F8)>>3))) + /** + * @brief Extract the red component (0 to 255) of a color value. + */ + #define RED_OF(c) (((c) & 0xF800)>>8) + /** + * @brief Extract the green component (0 to 255) of a color value. + */ + #define GREEN_OF(c) (((c)&0x007E)>>3) + /** + * @brief Extract the blue component (0 to 255) of a color value. + */ + #define BLUE_OF(c) (((c)&0x001F)<<3) + +#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 + typedef uint16_t color_t; + #define COLOR(c) ((color_t)(c)) + #define MASKCOLOR FALSE + #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF8)<<8) | (((g) & 0xFC)<<3) | (((b) & 0xF8)>>3))) + #define HTML2COLOR(h) ((color_t)((((h) & 0xF80000)>>8) | (((h) & 0x00FC00)>>5) | (((h) & 0x0000F8)>>3))) + #define RED_OF(c) (((c) & 0xF800)>>8) + #define GREEN_OF(c) (((c)&0x007E)>>3) + #define BLUE_OF(c) (((c)&0x001F)<<3) + +#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 + typedef uint32_t color_t; + #define COLOR(c) ((color_t)(((c) & 0xFFFFFF))) + #define MASKCOLOR TRUE + #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xFF)<<16) | (((g) & 0xFF) << 8) | ((b) & 0xFF))) + #define HTML2COLOR(h) ((color_t)(h)) + #define RED_OF(c) (((c) & 0xFF0000)>>16) + #define GREEN_OF(c) (((c)&0x00FF00)>>8) + #define BLUE_OF(c) ((c)&0x0000FF) + +#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB444 + typedef uint16_t color_t; + #define COLOR(c) ((color_t)(((c) & 0x0FFF))) + #define MASKCOLOR TRUE + #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xF0)<<4) | ((g) & 0xF0) | (((b) & 0xF0)>>4))) + #define HTML2COLOR(h) ((color_t)((((h) & 0xF00000)>>12) | (((h) & 0x00F000)>>8) | (((h) & 0x0000F0)>>4))) + #define RED_OF(c) (((c) & 0x0F00)>>4) + #define GREEN_OF(c) ((c)&0x00F0) + #define BLUE_OF(c) (((c)&0x000F)<<4) + +#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB332 + typedef uint8_t color_t; + #define COLOR(c) ((color_t)(c)) + #define MASKCOLOR FALSE + #define RGB2COLOR(r,g,b) ((color_t)(((r) & 0xE0) | (((g) & 0xE0)>>3) | (((b) & 0xC0)>>6))) + #define HTML2COLOR(h) ((color_t)((((h) & 0xE00000)>>16) | (((h) & 0x00E000)>>11) | (((h) & 0x0000C0)>>6))) + #define RED_OF(c) ((c) & 0xE0) + #define GREEN_OF(c) (((c)&0x1C)<<3) + #define BLUE_OF(c) (((c)&0x03)<<6) + +#elif GDISP_PIXELFORMAT == GDISP_PIXELFORMAT_RGB666 + typedef uint32_t color_t; + #define COLOR(c) ((color_t)(((c) & 0x03FFFF))) + #define MASKCOLOR TRUE + #define RGB2COLOR(r,g,b) ((color_t)((((r) & 0xFC)<<10) | (((g) & 0xFC)<<4) | (((b) & 0xFC)>>2))) + #define HTML2COLOR(h) ((color_t)((((h) & 0xFC0000)>>6) | (((h) & 0x00FC00)>>4) | (((h) & 0x0000FC)>>2))) + #define RED_OF(c) (((c) & 0x03F000)>>12) + #define GREEN_OF(c) (((c)&0x00FC00)>>8) + #define BLUE_OF(c) (((c)&0x00003F)<<2) + +#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM + #error "GDISP: No supported pixel format has been specified." +#endif + +/* Verify information for packed pixels and define a non-packed pixel macro */ +#if !GDISP_PACKED_PIXELS + #define gdispPackPixels(buf,cx,x,y,c) { ((color_t *)(buf))[(y)*(cx)+(x)] = (c); } +#elif !GDISP_HARDWARE_BITFILLS + #error "GDISP: packed pixel formats are only supported for hardware accelerated drivers." +#elif GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888 \ + && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB444 \ + && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB666 \ + && GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_CUSTOM + #error "GDISP: A packed pixel format has been specified for an unsupported pixel format." +#endif + +#if GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL + #error "GDISP: Hardware scrolling is wanted but not supported." +#endif + +#if GDISP_NEED_PIXELREAD && !GDISP_HARDWARE_PIXELREAD + #error "GDISP: Pixel read-back is wanted but not supported." +#endif + +/*===========================================================================*/ +/* Driver types. */ +/*===========================================================================*/ + +/** + * @brief The type for a coordinate or length on the screen. + */ +typedef int16_t coord_t; +/** + * @brief The type of a pixel. + */ +typedef color_t pixel_t; +/** + * @brief The type of a font. + */ +typedef const struct font *font_t; +/** + * @brief Type for the screen orientation. + */ +typedef enum orientation {GDISP_ROTATE_0, GDISP_ROTATE_90, GDISP_ROTATE_180, GDISP_ROTATE_270} gdisp_orientation_t; +/** + * @brief Type for the available power modes for the screen. + */ +typedef enum powermode {powerOff, powerSleep, powerDeepSleep, powerOn} gdisp_powermode_t; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifndef GDISP_LLD_VMT + /* Special magic stuff for the VMT driver */ + #define GDISP_LLD_VMT(x) GDISP_LLD(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + /* Core functions */ + extern bool_t GDISP_LLD(init)(void); + + /* Some of these functions will be implemented in software by the high level driver + depending on the GDISP_HARDWARE_XXX macros defined in gdisp_lld_config.h. + */ + + /* Drawing functions */ + extern void GDISP_LLD_VMT(clear)(color_t color); + extern void GDISP_LLD_VMT(drawpixel)(coord_t x, coord_t y, color_t color); + extern void GDISP_LLD_VMT(fillarea)(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color); + extern void GDISP_LLD_VMT(blitareaex)(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); + extern void GDISP_LLD_VMT(drawline)(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); + + /* Circular Drawing Functions */ + #if GDISP_NEED_CIRCLE + extern void GDISP_LLD_VMT(drawcircle)(coord_t x, coord_t y, coord_t radius, color_t color); + extern void GDISP_LLD_VMT(fillcircle)(coord_t x, coord_t y, coord_t radius, color_t color); + #endif + + #if GDISP_NEED_ELLIPSE + extern void GDISP_LLD_VMT(drawellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); + extern void GDISP_LLD_VMT(fillellipse)(coord_t x, coord_t y, coord_t a, coord_t b, color_t color); + #endif + + /* Arc Drawing Functions */ + #if GDISP_NEED_ARC + extern void GDISP_LLD_VMT(drawarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + extern void GDISP_LLD_VMT(fillarc)(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); + #endif + + /* Text Rendering Functions */ + #if GDISP_NEED_TEXT + extern void GDISP_LLD_VMT(drawchar)(coord_t x, coord_t y, char c, font_t font, color_t color); + extern void GDISP_LLD_VMT(fillchar)(coord_t x, coord_t y, char c, font_t font, color_t color, color_t bgcolor); + #endif + + /* Pixel readback */ + #if GDISP_NEED_PIXELREAD + extern color_t GDISP_LLD_VMT(getpixelcolor)(coord_t x, coord_t y); + #endif + + /* Scrolling Function - clears the area scrolled out */ + #if GDISP_NEED_SCROLL + extern void GDISP_LLD_VMT(verticalscroll)(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor); + #endif + + /* Set driver specific control */ + #if GDISP_NEED_CONTROL + extern void GDISP_LLD_VMT(control)(unsigned what, void *value); + #endif + + /* Query driver specific data */ + #if GDISP_NEED_QUERY + extern void *GDISP_LLD_VMT(query)(unsigned what); + #endif + + /* Clipping Functions */ + #if GDISP_NEED_CLIP + extern void GDISP_LLD_VMT(setclip)(coord_t x, coord_t y, coord_t cx, coord_t cy); + #endif + + /* Messaging API */ + #if GDISP_NEED_MSGAPI + #include "gdisp_lld_msgs.h" + extern void GDISP_LLD(msgdispatch)(gdisp_lld_msg_t *msg); + #endif + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GDISP */ + +#endif /* _GDISP_LLD_H */ +/** @} */ + diff --git a/include/lld/gdisp/gdisp_lld_msgs.h b/include/lld/gdisp/gdisp_lld_msgs.h new file mode 100644 index 00000000..5885a70c --- /dev/null +++ b/include/lld/gdisp/gdisp_lld_msgs.h @@ -0,0 +1,195 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file include/gdisp_lld_msgs.h + * @brief GDISP Graphic Driver subsystem low level driver message structures. + * + * @addtogroup GDISP + * @{ + */ + +#ifndef _GDISP_LLD_MSGS_H +#define _GDISP_LLD_MSGS_H + +/* This file describes the message API for gdisp_lld */ +#if GFX_USE_GDISP && GDISP_NEED_MSGAPI + +typedef enum gdisp_msgaction { + GDISP_LLD_MSG_NOP, + GDISP_LLD_MSG_INIT, + GDISP_LLD_MSG_CLEAR, + GDISP_LLD_MSG_DRAWPIXEL, + GDISP_LLD_MSG_FILLAREA, + GDISP_LLD_MSG_BLITAREA, + GDISP_LLD_MSG_DRAWLINE, + #if GDISP_NEED_CLIP + GDISP_LLD_MSG_SETCLIP, + #endif + #if GDISP_NEED_CIRCLE + GDISP_LLD_MSG_DRAWCIRCLE, + GDISP_LLD_MSG_FILLCIRCLE, + #endif + #if GDISP_NEED_ELLIPSE + GDISP_LLD_MSG_DRAWELLIPSE, + GDISP_LLD_MSG_FILLELLIPSE, + #endif + #if GDISP_NEED_ARC + GDISP_LLD_MSG_DRAWARC, + GDISP_LLD_MSG_FILLARC, + #endif + #if GDISP_NEED_TEXT + GDISP_LLD_MSG_DRAWCHAR, + GDISP_LLD_MSG_FILLCHAR, + #endif + #if GDISP_NEED_PIXELREAD + GDISP_LLD_MSG_GETPIXELCOLOR, + #endif + #if GDISP_NEED_SCROLL + GDISP_LLD_MSG_VERTICALSCROLL, + #endif + #if GDISP_NEED_CONTROL + GDISP_LLD_MSG_CONTROL, + #endif + #if GDISP_NEED_QUERY + GDISP_LLD_MSG_QUERY, + #endif +} gdisp_msgaction_t; + +typedef union gdisp_lld_msg { + gdisp_msgaction_t action; + struct gdisp_lld_msg_init { + gdisp_msgaction_t action; // GDISP_LLD_MSG_INIT + } init; + struct gdisp_lld_msg_clear { + gdisp_msgaction_t action; // GDISP_LLD_MSG_CLEAR + color_t color; + } clear; + struct gdisp_lld_msg_drawpixel { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWPIXEL + coord_t x, y; + color_t color; + } drawpixel; + struct gdisp_lld_msg_fillarea { + gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLAREA + coord_t x, y; + coord_t cx, cy; + color_t color; + } fillarea; + struct gdisp_lld_msg_blitarea { + gdisp_msgaction_t action; // GDISP_LLD_MSG_BLITAREA + coord_t x, y; + coord_t cx, cy; + coord_t srcx, srcy; + coord_t srccx; + const pixel_t *buffer; + } blitarea; + struct gdisp_lld_msg_setclip { + gdisp_msgaction_t action; // GDISP_LLD_MSG_SETCLIP + coord_t x, y; + coord_t cx, cy; + } setclip; + struct gdisp_lld_msg_drawline { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWLINE + coord_t x0, y0; + coord_t x1, y1; + color_t color; + } drawline; + struct gdisp_lld_msg_drawcircle { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCIRCLE + coord_t x, y; + coord_t radius; + color_t color; + } drawcircle; + struct gdisp_lld_msg_fillcircle { + gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCIRCLE + coord_t x, y; + coord_t radius; + color_t color; + } fillcircle; + struct gdisp_lld_msg_drawellipse { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWELLIPSE + coord_t x, y; + coord_t a, b; + color_t color; + } drawellipse; + struct gdisp_lld_msg_fillellipse { + gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLELLIPSE + coord_t x, y; + coord_t a, b; + color_t color; + } fillellipse; + struct gdisp_lld_msg_drawarc { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWARC + coord_t x, y; + coord_t radius; + coord_t startangle, endangle; + color_t color; + } drawcircle; + struct gdisp_lld_msg_fillarc { + gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLARC + coord_t x, y; + coord_t radius; + coord_t startangle, endangle; + color_t color; + } fillcircle; + struct gdisp_lld_msg_drawchar { + gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCHAR + coord_t x, y; + char c; + font_t font; + color_t color; + } drawchar; + struct gdisp_lld_msg_fillchar { + gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCHAR + coord_t x, y; + char c; + font_t font; + color_t color; + color_t bgcolor; + } fillchar; + struct gdisp_lld_msg_getpixelcolor { + gdisp_msgaction_t action; // GDISP_LLD_MSG_GETPIXELCOLOR + coord_t x, y; + color_t result; + } getpixelcolor; + struct gdisp_lld_msg_verticalscroll { + gdisp_msgaction_t action; // GDISP_LLD_MSG_VERTICALSCROLL + coord_t x, y; + coord_t cx, cy; + int lines; + color_t bgcolor; + } verticalscroll; + struct gdisp_lld_msg_control { + gdisp_msgaction_t action; // GDISP_LLD_MSG_CONTROL + int what; + void * value; + } control; + struct gdisp_lld_msg_query { + gdisp_msgaction_t action; // GDISP_LLD_MSG_QUERY + int what; + void * result; + } query; +} gdisp_lld_msg_t; + +#endif /* GFX_USE_GDISP */ +#endif /* _GDISP_LLD_MSGS_H */ +/** @} */ + diff --git a/include/lld/ginput/mouse.h b/include/lld/ginput/mouse.h new file mode 100644 index 00000000..64c7c5ec --- /dev/null +++ b/include/lld/ginput/mouse.h @@ -0,0 +1,125 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file lld/ginput/mouse.h + * @brief GINPUT LLD header file for mouse/touch drivers. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ +#ifndef _LLD_GINPUT_MOUSE_H +#define _LLD_GINPUT_MOUSE_H + +#ifndef GINPUT_NEED_MOUSE + #define GINPUT_NEED_MOUSE FALSE +#endif +#ifndef GINPUT_NEED_TOUCH + #define GINPUT_NEED_TOUCH FALSE +#endif + +#if GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH + +#include "ginput_lld_mouse_config.h" + +// GEVENT_MOUSE or GEVENT_TOUCH - What type of device is this. +#ifndef GINPUT_MOUSE_EVENT_TYPE + #define GINPUT_MOUSE_EVENT_TYPE GEVENT_MOUSE +#endif + +// TRUE/FALSE - Does the mouse/touch driver require calibration? +#ifndef GINPUT_MOUSE_NEED_CALIBRATION + #define GINPUT_MOUSE_NEED_CALIBRATION FALSE +#endif + +// TRUE/FALSE - Can the mouse/touch driver itself save calibration data? +#ifndef GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE + #define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE FALSE +#endif + +// n or -1 - n means to test calibration result (+/- pixels), -1 means not to. +#ifndef GINPUT_MOUSE_MAX_CALIBRATION_ERROR + #define GINPUT_MOUSE_MAX_CALIBRATION_ERROR -1 +#endif + +// n - How many times to read (and average) per poll +#ifndef GINPUT_MOUSE_READ_CYCLES + #define GINPUT_MOUSE_READ_CYCLES 1 +#endif + +// n - Millisecs between poll's +#ifndef GINPUT_MOUSE_POLL_PERIOD + #define GINPUT_MOUSE_POLL_PERIOD 100 +#endif + +// n - Movement allowed without discarding the CLICK or CLICKCXT event (+/- pixels) +#ifndef GINPUT_MOUSE_MAX_CLICK_JITTER + #define GINPUT_MOUSE_MAX_CLICK_JITTER 1 +#endif + +// n - Movement allowed without discarding the MOVE event (+/- pixels) +#ifndef GINPUT_MOUSE_MAX_MOVE_JITTER + #define GINPUT_MOUSE_MAX_MOVE_JITTER 0 +#endif + +// ms - Millisecs seperating a CLICK from a CXTCLICK +#ifndef GINPUT_MOUSE_CLICK_TIME + #define GINPUT_MOUSE_CLICK_TIME 700 +#endif + + +typedef struct MouseReading_t { + coord_t x, y, z; + uint16_t buttons; + } MouseReading; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + + void ginput_lld_mouse_init(void); + void ginput_lld_mouse_get_reading(MouseReading *pt); + + #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE + const char *ginput_lld_mouse_calibration_load(uint16_t instance); + void ginput_lld_mouse_calibration_save(uint16_t instance, const uint8_t *calbuf, size_t sz); + #endif + + /* This routine is provided to low level drivers to wakeup a value read from a thread context. + * Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE + */ + void ginputMouseWakeup(void); + + /* This routine is provided to low level drivers to wakeup a value read from an ISR + * Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE + */ + void ginputMouseWakeupI(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH */ + +#endif /* _LLD_GINPUT_MOUSE_H */ +/** @} */ diff --git a/include/lld/ginput/toggle.h b/include/lld/ginput/toggle.h new file mode 100644 index 00000000..826ace83 --- /dev/null +++ b/include/lld/ginput/toggle.h @@ -0,0 +1,71 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file lld/ginput/toggle.h + * @brief GINPUT header file for toggle drivers. + * + * @addtogroup GINPUT_TOGGLE + * @{ + */ +#ifndef _LLD_GINPUT_TOGGLE_H +#define _LLD_GINPUT_TOGGLE_H + +#ifndef GFX_USE_GINPUT + #define GFX_USE_GINPUT FALSE +#endif + +#if GFX_USE_GINPUT || defined(__DOXYGEN__) + +#if GINPUT_NEED_TOGGLE + // Describes how the toggle bits are obtained + typedef struct GToggleConfig_t { + void *id; + unsigned mask; + unsigned invert; + iomode_t mode; + } GToggleConfig; +#endif + +// This must be included after the above type definition +#include "ginput.h" + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if GINPUT_NEED_TOGGLE + extern const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES]; + + void ginput_lld_toggle_init(const GToggleConfig *ptc); + unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GINPUT */ + +#endif /* _LLD_GINPUT_TOGGLE_H */ +/** @} */ diff --git a/include/lld/touchscreen/touchscreen_lld.h b/include/lld/touchscreen/touchscreen_lld.h new file mode 100644 index 00000000..9dd29629 --- /dev/null +++ b/include/lld/touchscreen/touchscreen_lld.h @@ -0,0 +1,130 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file include/touchscreen_lld.h + * @brief TOUCHSCREEN Driver subsystem low level driver header. + * + * @addtogroup TOUCHSCREEN + * @{ + */ + +#ifndef TOUCHSCREEN_LLD_H +#define TOUCHSCREEN_LLD_H + +#if GFX_USE_TOUCHSCREEN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Include the low level driver configuration information */ +/*===========================================================================*/ + +#include "touchscreen_lld_config.h" + +/*===========================================================================*/ +/* Error checks. */ +/*===========================================================================*/ + +#ifndef TOUCHSCREEN_NEED_MULTITHREAD + #define TOUCHSCREEN_NEED_MULTITHREAD FALSE +#endif + +#ifndef TOUCHSCREEN_XY_INVERTED + #define TOUCHSCREEN_XY_INVERTED FALSE +#endif + +#ifndef TOUCHSCREEN_HAS_PRESSED + #define TOUCHSCREEN_HAS_PRESSED FALSE +#endif + +#ifndef TOUCHSCREEN_HAS_PRESSURE + #define TOUCHSCREEN_HAS_PRESSURE FALSE +#endif + +#ifndef TOUCHSCREEN_SPI_PROLOGUE + #define TOUCHSCREEN_SPI_PROLOGUE() +#endif + +#ifndef TOUCHSCREEN_SPI_EPILOGUE + #define TOUCHSCREEN_SPI_EPILOGUE() +#endif + +#ifndef TOUCHSCREEN_STORE_CALIBRATION + #define TOUCHSCREEN_STORE_CALIBRATION FALSE +#endif + +#ifndef TOUCHSCREEN_VERIFY_CALIBRATION + #define TOUCHSCREEN_VERIFY_CALIBRATION FALSE +#endif + +#ifndef TOUCHSCREEN_CONVERSIONS + #define TOUCHSCREEN_CONVERSIONS 3 +#endif + +/*===========================================================================*/ +/* Driver types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing a touchscreen driver. Hardware dependant. + */ +typedef struct TouchscreenDriver TouchscreenDriver; + +// Forward declaration +struct cal_t; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + /* Core functions */ + void ts_lld_init(const TouchscreenDriver *ts); + + uint16_t ts_lld_read_value(uint8_t cmd); + uint16_t ts_lld_read_x(void); + uint16_t ts_lld_read_y(void); + + #if TOUCHSCREEN_HAS_PRESSED + uint8_t ts_lld_pressed(void); + #endif + + #if TOUCHSCREEN_HAS_PRESSURE + uint16_t ts_lld_read_z(void); + #endif + + #if TOUCHSCREEN_STORE_CALIBRATION + // These may be defined by the low level driver or by the application + void ts_store_calibration_lld(struct cal_t *cal); + struct cal_t *ts_restore_calibration_lld(void); + #endif + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_TOUCHSCREEN */ + +#endif /* _TOUCHSCREEN_LLD_H */ +/** @} */ + diff --git a/include/touchscreen.h b/include/touchscreen.h index 253855ca..5a84afdf 100644 --- a/include/touchscreen.h +++ b/include/touchscreen.h @@ -40,7 +40,7 @@ /*===========================================================================*/ /* Include the low level driver information */ -#include "touchscreen_lld.h" +#include "lld/touchscreen/touchscreen_lld.h" /* For definitions of coord_t, we require gdisp.h */ #include "gdisp.h" diff --git a/include/touchscreen_lld.h b/include/touchscreen_lld.h deleted file mode 100644 index 9dd29629..00000000 --- a/include/touchscreen_lld.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file include/touchscreen_lld.h - * @brief TOUCHSCREEN Driver subsystem low level driver header. - * - * @addtogroup TOUCHSCREEN - * @{ - */ - -#ifndef TOUCHSCREEN_LLD_H -#define TOUCHSCREEN_LLD_H - -#if GFX_USE_TOUCHSCREEN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Include the low level driver configuration information */ -/*===========================================================================*/ - -#include "touchscreen_lld_config.h" - -/*===========================================================================*/ -/* Error checks. */ -/*===========================================================================*/ - -#ifndef TOUCHSCREEN_NEED_MULTITHREAD - #define TOUCHSCREEN_NEED_MULTITHREAD FALSE -#endif - -#ifndef TOUCHSCREEN_XY_INVERTED - #define TOUCHSCREEN_XY_INVERTED FALSE -#endif - -#ifndef TOUCHSCREEN_HAS_PRESSED - #define TOUCHSCREEN_HAS_PRESSED FALSE -#endif - -#ifndef TOUCHSCREEN_HAS_PRESSURE - #define TOUCHSCREEN_HAS_PRESSURE FALSE -#endif - -#ifndef TOUCHSCREEN_SPI_PROLOGUE - #define TOUCHSCREEN_SPI_PROLOGUE() -#endif - -#ifndef TOUCHSCREEN_SPI_EPILOGUE - #define TOUCHSCREEN_SPI_EPILOGUE() -#endif - -#ifndef TOUCHSCREEN_STORE_CALIBRATION - #define TOUCHSCREEN_STORE_CALIBRATION FALSE -#endif - -#ifndef TOUCHSCREEN_VERIFY_CALIBRATION - #define TOUCHSCREEN_VERIFY_CALIBRATION FALSE -#endif - -#ifndef TOUCHSCREEN_CONVERSIONS - #define TOUCHSCREEN_CONVERSIONS 3 -#endif - -/*===========================================================================*/ -/* Driver types. */ -/*===========================================================================*/ - -/** - * @brief Structure representing a touchscreen driver. Hardware dependant. - */ -typedef struct TouchscreenDriver TouchscreenDriver; - -// Forward declaration -struct cal_t; - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Core functions */ - void ts_lld_init(const TouchscreenDriver *ts); - - uint16_t ts_lld_read_value(uint8_t cmd); - uint16_t ts_lld_read_x(void); - uint16_t ts_lld_read_y(void); - - #if TOUCHSCREEN_HAS_PRESSED - uint8_t ts_lld_pressed(void); - #endif - - #if TOUCHSCREEN_HAS_PRESSURE - uint16_t ts_lld_read_z(void); - #endif - - #if TOUCHSCREEN_STORE_CALIBRATION - // These may be defined by the low level driver or by the application - void ts_store_calibration_lld(struct cal_t *cal); - struct cal_t *ts_restore_calibration_lld(void); - #endif - -#ifdef __cplusplus -} -#endif - -#endif /* GFX_USE_TOUCHSCREEN */ - -#endif /* _TOUCHSCREEN_LLD_H */ -/** @} */ - diff --git a/src/gdisp.c b/src/gdisp.c index 92bb060d..51a43b49 100644 --- a/src/gdisp.c +++ b/src/gdisp.c @@ -32,7 +32,7 @@ #if GFX_USE_GDISP || defined(__DOXYGEN__) #ifdef GDISP_NEED_TEXT - #include "gdisp_fonts.h" + #include "gdisp/fonts.h" #endif /*===========================================================================*/ @@ -487,13 +487,13 @@ * * @api */ - void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) { + void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { chMtxLock(&gdispMutex); GDISP_LLD(drawarc)(x, y, radius, start, end, color); chMtxUnlock(); } #elif GDISP_NEED_ARC && GDISP_NEED_ASYNC - void gdispDrawArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) { + void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWARC); p->drawarc.x = x; p->drawarc.y = y; @@ -518,13 +518,13 @@ * * @api */ - void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) { + void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { chMtxLock(&gdispMutex); GDISP_LLD(fillarc)(x, y, radius, start, end, color); chMtxUnlock(); } #elif GDISP_NEED_ARC && GDISP_NEED_ASYNC - void gdispFillArc(coord_t x, coord_t y, coord_t radius, uint16_t start, uint16_t end, color_t color) { + void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLARC); p->fillarc.x = x; p->fillarc.y = y; diff --git a/src/gdisp_fonts.c b/src/gdisp_fonts.c index 4384a72e..6a6cd910 100644 --- a/src/gdisp_fonts.c +++ b/src/gdisp_fonts.c @@ -29,7 +29,8 @@ #if GDISP_NEED_TEXT -#include "gdisp_fonts.h" +#include "gdisp/fonts.h" + /* fontSmall - for side buttons */ #if 1 diff --git a/src/gevent.c b/src/gevent.c index d9c7e4f1..0a18eca2 100644 --- a/src/gevent.c +++ b/src/gevent.c @@ -71,6 +71,7 @@ static void deleteAssignments(GListener *pl, GSourceHandle gsh) { void geventListenerInit(GListener *pl) { chSemInit(&pl->waitqueue, 0); // Next wait'er will block chBSemInit(&pl->eventlock, FALSE); // Only one thread at a time looking at the event buffer + pl->callback = 0; // No callback active pl->event.type = GEVENT_NULL; // Always safety } @@ -165,9 +166,45 @@ void geventDetachSource(GListener *pl, GSourceHandle gsh) { * @return NULL on timeout */ GEvent *geventEventWait(GListener *pl, systime_t timeout) { + if (pl->callback || chSemGetCounterI(&pl->waitqueue) < 0) + return 0; return chSemWaitTimeout(&pl->waitqueue, timeout) == RDY_OK ? &pl->event : 0; } +/* @brief Register a callback for an event on a listener from an assigned source. + * @details The type of the event should be checked (pevent->type) and then pevent should be typecast to the + * actual event type if it needs to be processed. + * + * @params[in] pl The Listener + * @params[in] fn The function to call back + * @params[in] param A parameter to pass the callback function + * + * @note The GEvent buffer is valid only during the time of the callback. The callback MUST NOT save + * a pointer to the buffer for use outside the callback. + * @note An existing callback function is de-registered by passing a NULL for 'fn'. Any existing + * callback function is replaced. Any thread currently waiting using geventEventWait will be sent the exit event. + * @note Callbacks occur in a thread context but stack space must be kept to a minumum and + * the callback must process quickly as all other events are performed on a single thread. + * @note In the callback function you should never call ANY event functions using your own GListener handle + * as it WILL create a deadlock and lock the system up. + * @note Applications should not use this call - geventEventWait() is the preferred mechanism for an + * application. This call is provided for GUI objects that may not have their own thread. + */ +void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) { + if (pl) { + chMtxLock(&geventMutex); + chBSemWait(&pl->eventlock); // Obtain the buffer lock + pl->param = param; // Set the param + pl->callback = fn; // Set the callback function + if (chSemGetCounterI(&pl->waitqueue) < 0) { + pl->event.type = GEVENT_EXIT; // Set up the EXIT event + chSemSignal(&pl->waitqueue); // Wake up the listener + } + chBSemSignal(&pl->eventlock); // Release the buffer lock + chMtxUnlock(); + } +} + /** * @brief Called by a source with a possible event to get a listener record. * @details @p lastlr should be NULL on the first call and thereafter the result of the previous call. @@ -215,7 +252,7 @@ GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *las */ GEvent *geventGetEventBuffer(GSourceListener *psl) { // We already know we have the event lock - return chSemGetCounterI(&psl->pListener->waitqueue) < 0 ? &psl->pListener->event : 0; + return &psl->pListener->callback || chSemGetCounterI(&psl->pListener->waitqueue) < 0 ? &psl->pListener->event : 0; } /** @@ -226,10 +263,17 @@ GEvent *geventGetEventBuffer(GSourceListener *psl) { */ void geventSendEvent(GSourceListener *psl) { chMtxLock(&geventMutex); - // Wake up the listener - if (chSemGetCounterI(&psl->pListener->waitqueue) < 0) - chSemSignal(&psl->pListener->waitqueue); - chMtxUnlock(); + if (psl->pListener->callback) { // This test needs to be taken inside the mutex + chMtxUnlock(); + // We already know we have the event lock + psl->pListener->callback(psl->pListener->param, &psl->pListener->event); + + } else { + // Wake up the listener + if (chSemGetCounterI(&psl->pListener->waitqueue) < 0) + chSemSignal(&psl->pListener->waitqueue); + chMtxUnlock(); + } } /** diff --git a/src/ginput.c b/src/ginput.c deleted file mode 100644 index 9b6b180a..00000000 --- a/src/ginput.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - ChibiOS/GFX - Copyright (C) 2012 - Joel Bodenmann aka Tectu - - This file is part of ChibiOS/GFX. - - ChibiOS/GFX is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/GFX is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file src/ginput.c - * @brief GINPUT Driver code. - * - * @addtogroup GINPUT - * @{ - */ -#include "ch.h" -#include "hal.h" -#include "ginput.h" - -#if GFX_USE_GINPUT || defined(__DOXYGEN__) - -#error "GINPUT: Not Implemented Yet" - -#endif /* GFX_USE_GINPUT */ -/** @} */ diff --git a/src/ginput/dial.c b/src/ginput/dial.c new file mode 100644 index 00000000..cb6799a9 --- /dev/null +++ b/src/ginput/dial.c @@ -0,0 +1,35 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file src/ginput/dial.c + * @brief GINPUT dial code. + * + * @addtogroup GINPUT + * @{ + */ +#include "ch.h" +#include "hal.h" +#include "ginput.h" + +#if GINPUT_NEED_DIAL || defined(__DOXYGEN__) + #error "GINPUT: GINPUT_NEED_DIAL - Not Implemented Yet" +#endif /* GINPUT_NEED_DIAL */ +/** @} */ diff --git a/src/ginput/ginput.mk b/src/ginput/ginput.mk new file mode 100644 index 00000000..06bcfc07 --- /dev/null +++ b/src/ginput/ginput.mk @@ -0,0 +1,4 @@ +GFXSRC += $(GFXLIB)/src/ginput/mouse.c \ + $(GFXLIB)/src/ginput/keyboard.c \ + $(GFXLIB)/src/ginput/toggle.c \ + $(GFXLIB)/src/ginput/dial.c diff --git a/src/ginput/keyboard.c b/src/ginput/keyboard.c new file mode 100644 index 00000000..1c38a408 --- /dev/null +++ b/src/ginput/keyboard.c @@ -0,0 +1,35 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file src/ginput/keyboard.c + * @brief GINPUT keyboard code. + * + * @addtogroup GINPUT + * @{ + */ +#include "ch.h" +#include "hal.h" +#include "ginput.h" + +#if GINPUT_NEED_KEYBOARD || defined(__DOXYGEN__) + #error "GINPUT: GINPUT_NEED_KEYBOARD - Not Implemented Yet" +#endif /* GINPUT_NEED_KEYBOARD */ +/** @} */ diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c new file mode 100644 index 00000000..35872a6c --- /dev/null +++ b/src/ginput/mouse.c @@ -0,0 +1,554 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file src/ginput/mouse.c + * @brief GINPUT mouse/touch code. + * + * @addtogroup GINPUT_MOUSE + * @{ + */ +#include "ch.h" +#include "hal.h" +#include "gtimer.h" +#include "ginput.h" + +#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__) + +#include "lld/ginput/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 &fontUI2Double + #define GINPUT_MOUSE_CALIBRATION_TEXT "Calibration" + + #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); + } + } +} + +/* Mouse Functions */ +GSourceHandle ginputGetMouse(uint16_t instance) { + #if GINPUT_MOUSE_NEED_CALIBRATION + Calibration *pc; + #endif + + // We only support a single mouse instance currently + if (instance) + 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 + 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; +} + +/* Get the current mouse position and button status. + * Unlike a listener event, this status cannot record meta events such as "CLICK" + * Returns FALSE on error (eg invalid instance) + */ +bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) { + 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; +} + +/* Run a mouse calibration. + * Returns FALSE if the driver doesn't support it or if the handle is invalid. + */ +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; + + if (instance || (MouseConfig.flags & FLG_IN_CAL)) + return FALSE; + + MouseConfig.flags |= FLG_IN_CAL; + gtimerStop(&MouseTimer); + MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED); + + #if GDISP_NEED_CONTROL + gdispSetOrientation(GDISP_ROTATE_0); + #endif + + gdispClear(Blue); + + gdispFillStringBox(0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, GINPUT_MOUSE_CALIBRATION_FONT, White, Blue, justifyCenter); + + #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0 + do { + #endif + 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); + } + + /* 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 */ + px = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) + + (MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y); + + } while (px > GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR); + #endif + + // Restart everything + 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 /* GINPUT_NEED_MOUSE */ +/** @} */ diff --git a/src/ginput/toggle.c b/src/ginput/toggle.c new file mode 100644 index 00000000..a49ebfd3 --- /dev/null +++ b/src/ginput/toggle.c @@ -0,0 +1,161 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file src/ginput/toggle.c + * @brief GINPUT toggle code. + * + * @addtogroup GINPUT_TOGGLE + * @{ + */ +#include "ch.h" +#include "hal.h" +#include "gtimer.h" +#include "ginput.h" + +#if GINPUT_NEED_TOGGLE || defined(__DOXYGEN__) + +#include "lld/ginput/toggle.h" + +#ifndef GINPUT_TOGGLE_POLL_PERIOD + #define GINPUT_TOGGLE_POLL_PERIOD 250 +#endif + +#define GINPUT_TOGGLE_ISON 0x01 +#define GINPUT_TOGGLE_INVERT 0x02 + +static GTIMER_DECL(ToggleTimer); +static struct GEventToggleStatus_t { + uint8_t status; +} ToggleStatus[GINPUT_TOGGLE_NUM_PORTS]; + +// Our polling function +static void TogglePoll(void *param) { + (void) param; + + const GToggleConfig *ptc; + GSourceListener *psl; + GEventToggle *pe; + unsigned i, bits, mask; + uint8_t state; + + // Loop while there are bits to get + for(ptc = GInputToggleConfigTable, i=0; i < GINPUT_TOGGLE_NUM_PORTS; ptc++) { + + // Get the next block of bits + bits = ginput_lld_toggle_getbits(ptc) ^ ptc->invert; + + // Extract the bits of use + for(mask = ptc->mask; i < GINPUT_TOGGLE_NUM_PORTS && mask; mask >>= 1, bits >>= 1) { + // Ignore bits not in our mask + if (!(mask & 1)) + continue; + + // Calculate our new state + state = ToggleStatus[i].status & ~GINPUT_TOGGLE_ISON; + if (state & GINPUT_TOGGLE_INVERT) + bits ^= 1; + if (bits & 1) + state |= GINPUT_TOGGLE_ISON; + + // Has it changed? + if ((state ^ ToggleStatus[i].status) & GINPUT_TOGGLE_ISON) { + + // Save the new state + ToggleStatus[i].status = state; + + // Send the event to the listeners that are interested. + psl = 0; + while ((psl = geventGetSourceListener((GSourceHandle)(ToggleStatus+i), psl))) { + if (!(pe = (GEventToggle *)geventGetEventBuffer(psl))) + continue; + if ((state & GINPUT_TOGGLE_ISON)) { + if ((psl->listenflags & GLISTEN_TOGGLE_ON)) { + pe->type = GEVENT_TOGGLE; + pe->instance = i; + pe->on = TRUE; + geventSendEvent(psl); + } + } else { + if ((psl->listenflags & GLISTEN_TOGGLE_OFF)) { + pe->type = GEVENT_TOGGLE; + pe->instance = i; + pe->on = FALSE; + geventSendEvent(psl); + } + } + } + } + + // Next toggle switch + i++; + } + } +} + +/* Hardware Toggle/Switch/Button Functions */ +GSourceHandle ginputGetToggle(uint16_t instance) { + const GToggleConfig *ptc; + + if (instance >= GINPUT_TOGGLE_NUM_PORTS) + return 0; + + // Do we need to initialise the toggle subsystem? + if (!gtimerIsActive(&ToggleTimer)) { + for(ptc = GInputToggleConfigTable; ptc < GInputToggleConfigTable+sizeof(GInputToggleConfigTable)/sizeof(GInputToggleConfigTable[0]); ptc++) + ginput_lld_toggle_init(ptc); + gtimerStart(&ToggleTimer, TogglePoll, 0, TRUE, GINPUT_TOGGLE_POLL_PERIOD); + } + + // OK - return this input + return (GSourceHandle)(ToggleStatus+instance); +} + +// If invert is true, invert the on/off sense for the toggle +void ginputInvertToggle(uint16_t instance, bool_t invert) { + if (instance >= GINPUT_TOGGLE_NUM_PORTS) + return; + if (invert) { + if (!(ToggleStatus[instance].status & GINPUT_TOGGLE_INVERT)) { + ToggleStatus[instance].status |= GINPUT_TOGGLE_INVERT; + ToggleStatus[instance].status ^= GINPUT_TOGGLE_ISON; + } + } else { + if ((ToggleStatus[instance].status & GINPUT_TOGGLE_INVERT)) { + ToggleStatus[instance].status &= ~GINPUT_TOGGLE_INVERT; + ToggleStatus[instance].status ^= GINPUT_TOGGLE_ISON; + } + } +} + +/* Get the current toggle status. + * Returns FALSE on error (eg invalid instance) + */ +bool_t ginputGetToggleStatus(uint16_t instance, GEventToggle *ptoggle) { + if (instance >= GINPUT_TOGGLE_NUM_PORTS) + return FALSE; + ptoggle->type = GEVENT_TOGGLE; + ptoggle->instance = instance; + ptoggle->on = (ToggleStatus[instance].status & GINPUT_TOGGLE_ISON) ? TRUE : FALSE; + return TRUE; +} + +#endif /* GINPUT_NEED_TOGGLE */ +/** @} */ diff --git a/src/gtimer.c b/src/gtimer.c index 98556607..8956a190 100644 --- a/src/gtimer.c +++ b/src/gtimer.c @@ -36,14 +36,14 @@ #define GTIMER_FLG_JABBED 0x0004 #define GTIMER_FLG_SCHEDULED 0x0008 -#define TimeIsWithin(time, start, end) (end > start ? (time >= start && time <= end) : (time >= start || time <= end)) +/* Don't rework this macro to use a ternary operator - the gcc compiler stuffs it up */ +#define TimeIsWithin(x, start, end) ((end >= start && x >= start && x <= end) || (end < start && (x >= start || x <= end))) // This mutex protects access to our tables static MUTEX_DECL(mutex); static Thread *pThread = 0; static GTimer *pTimerHead = 0; -static systime_t lastTime = 0; -static SEMAPHORE_DECL(waitsem, 0); +static BSEMAPHORE_DECL(waitsem, TRUE); static WORKING_AREA(waTimerThread, GTIMER_THREAD_STACK_SIZE); /*===========================================================================*/ @@ -55,7 +55,7 @@ static msg_t GTimerThreadHandler(void *arg) { GTimer *pt; systime_t tm; systime_t nxtTimeout; - systime_t tmptime; + systime_t lastTime; GTimerFunction fn; void *param; @@ -64,9 +64,11 @@ static msg_t GTimerThreadHandler(void *arg) { #endif nxtTimeout = TIME_INFINITE; + lastTime = 0; while(1) { /* Wait for work to do. */ - chSemWaitTimeout(&waitsem, nxtTimeout); + chThdYield(); // Give someone else a go no matter how busy we are + chBSemWaitTimeout(&waitsem, nxtTimeout); restartTimerChecks: @@ -87,11 +89,13 @@ static msg_t GTimerThreadHandler(void *arg) { if ((pt->flags & GTIMER_FLG_PERIODIC) && pt->period != TIME_IMMEDIATE) { // Yes - Update ready for the next period if (!(pt->flags & GTIMER_FLG_INFINITE)) { - do { - pt->when += pt->period; // We may have skipped a period - } while (TimeIsWithin(pt->when, lastTime, tm)); + // We may have skipped a period. + // We use this complicated formulae rather than a loop + // because the gcc compiler stuffs up the loop so that it + // either loops forever or doesn't get executed at all. + pt->when += ((tm + pt->period - pt->when) / pt->period) * pt->period; } - + // We are definitely no longer jabbed pt->flags &= ~GTIMER_FLG_JABBED; @@ -120,10 +124,8 @@ static msg_t GTimerThreadHandler(void *arg) { } // Find when we next need to wake up - if (!(pt->flags & GTIMER_FLG_INFINITE)) { - tmptime = pt->when - tm; - if (tmptime < nxtTimeout) nxtTimeout = tmptime; - } + if (!(pt->flags & GTIMER_FLG_INFINITE) && pt->when - tm < nxtTimeout) + nxtTimeout = pt->when - tm; pt = pt->next; } while(pt != pTimerHead); } @@ -201,11 +203,13 @@ void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, sy pt->flags = GTIMER_FLG_SCHEDULED; if (periodic) pt->flags |= GTIMER_FLG_PERIODIC; - if (millisec != TIME_INFINITE) { + if (millisec == TIME_INFINITE) { + pt->flags |= GTIMER_FLG_INFINITE; + pt->period = TIME_INFINITE; + } else { pt->period = MS2ST(millisec); pt->when = chTimeNow() + pt->period; - } else - pt->flags |= GTIMER_FLG_INFINITE; + } // Just pop it on the end of the queue if (pTimerHead) { @@ -217,7 +221,8 @@ void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, sy pt->next = pt->prev = pTimerHead = pt; // Bump the thread - chSemSignal(&waitsem); + if (!(pt->flags & GTIMER_FLG_INFINITE)) + chBSemSignal(&waitsem); chMtxUnlock(); } @@ -248,6 +253,17 @@ void gtimerStop(GTimer *pt) { chMtxUnlock(); } +/** + * @brief Test if a timer is currently active + * + * @param[in] pt Pointer to a GTimer structure + * + * @api + */ +bool_t gtimerIsActive(GTimer *pt) { + return (pt->flags & GTIMER_FLG_SCHEDULED) ? TRUE : FALSE; +} + /** * @brief Jab a timer causing the current period to immediate expire * @details The callback function will be called as soon as possible. @@ -268,7 +284,7 @@ void gtimerJab(GTimer *pt) { pt->flags |= GTIMER_FLG_JABBED; // Bump the thread - chSemSignal(&waitsem); + chBSemSignal(&waitsem); chMtxUnlock(); } @@ -291,7 +307,7 @@ void gtimerJabI(GTimer *pt) { pt->flags |= GTIMER_FLG_JABBED; // Bump the thread - chSemSignalI(&waitsem); + chBSemSignalI(&waitsem); } #endif /* GFX_USE_GTIMER */ diff --git a/src/gwin.c b/src/gwin.c index 86765935..87288aa9 100644 --- a/src/gwin.c +++ b/src/gwin.c @@ -31,17 +31,11 @@ #if GFX_USE_GWIN || defined(__DOXYGEN__) -#include - -#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE -#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE - -#define GWIN_FLG_DYNAMIC 0x0001 -#define GWIN_FIRST_CONTROL_FLAG 0x0002 -#define GBTN_FLG_ALLOCTXT (GWIN_FIRST_CONTROL_FLAG<<0) +#include "gwin/gwin_internal.h" +// Internal routine for use by GWIN components only // Initialise a window creating it dynamicly if required. -static GHandle gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) { +GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) { coord_t w, h; // Check the window size against the screen size @@ -90,7 +84,7 @@ static GHandle gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, * @api */ GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gw = (GWindowObject *)gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject)))) + if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject)))) return 0; gw->type = GW_WINDOW; return (GHandle)gw; @@ -536,360 +530,6 @@ void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, } #endif -/*------------------------------------------------------------------------------------------------------------------------*/ - -#if GWIN_NEED_CONSOLE || defined(__DOXYGEN__) - -/* - * Stream interface implementation. The interface is write only - */ - -#define Stream2GWindow(ip) ((GHandle)(((char *)(ip)) - (size_t)(&(((GConsoleObject *)0)->stream)))) - -static size_t GWinStreamWrite(void *ip, const uint8_t *bp, size_t n) { gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } -static size_t GWinStreamRead(void *ip, uint8_t *bp, size_t n) { (void)ip; (void)bp; (void)n; return 0; } -static msg_t GWinStreamPut(void *ip, uint8_t b) { gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } -static msg_t GWinStreamGet(void *ip) {(void)ip; return RDY_OK; } -static msg_t GWinStreamPutTimed(void *ip, uint8_t b, systime_t time) { (void)time; gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } -static msg_t GWinStreamGetTimed(void *ip, systime_t timeout) { (void)ip; (void)timeout; return RDY_OK; } -static size_t GWinStreamWriteTimed(void *ip, const uint8_t *bp, size_t n, systime_t time) { (void)time; gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } -static size_t GWinStreamReadTimed(void *ip, uint8_t *bp, size_t n, systime_t time) { (void)ip; (void)bp; (void)n; (void)time; return 0; } - -struct GConsoleWindowVMT_t { - _base_asynchronous_channel_methods -}; - -static const struct GConsoleWindowVMT_t GWindowConsoleVMT = { - GWinStreamWrite, - GWinStreamRead, - GWinStreamPut, - GWinStreamGet, - GWinStreamPutTimed, - GWinStreamGetTimed, - GWinStreamWriteTimed, - GWinStreamReadTimed -}; - -/** - * @brief Create a console window. - * @details A console window allows text to be written using chprintf() (and the console functions defined here). - * @brief Text in a console window supports newlines and will wrap text as required. - * @return NULL if there is no resultant drawing area, otherwise a window handle. - * - * @param[in] gc The GConsoleObject structure to initialise. If this is NULL the structure is dynamically allocated. - * @param[in] x,y The screen co-ordinates for the bottom left corner of the window - * @param[in] width The width of the window - * @param[in] height The height of the window - * @param[in] font The font to use - * @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color) - * @note If the dispay does not support scrolling, the window will be cleared when the bottom line is reached. - * @note The default drawing color gets set to White and the background drawing color to Black. - * @note The dimensions and position may be changed to fit on the real screen. - * - * @api - */ -GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) { - if (!(gc = (GConsoleObject *)gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject)))) - return 0; - gc->gwin.type = GW_CONSOLE; - gwinSetFont(&gc->gwin, font); - gc->stream.vmt = &GWindowConsoleVMT; - gc->cx = 0; - gc->cy = 0; - return (GHandle)gc; -} - -/** - * @brief Get a stream from a console window suitable for use with chprintf(). - * @return The stream handle or NULL if this is not a console window. - * - * @param[in] gh The window handle (must be a console window) - * - * @api - */ -BaseSequentialStream *gwinGetConsoleStream(GHandle gh) { - if (gh->type != GW_CONSOLE) - return 0; - return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream); -} - -/** - * @brief Put a character at the cursor position in the window. - * @note Uses the current foreground color to draw the character and fills the background using the background drawing color - * - * @param[in] gh The window handle (must be a console window) - * @param[in] c The character to draw - * - * @api - */ -void gwinPutChar(GHandle gh, char c) { - uint8_t width; - #define gcw ((GConsoleObject *)gh) - - if (gh->type != GW_CONSOLE || !gh->font) return; - - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - - if (c == '\n') { - gcw->cx = 0; - gcw->cy += gcw->fy; - // We use lazy scrolling here and only scroll when the next char arrives - } else if (c == '\r') { - // gcw->cx = 0; - } else { - width = gdispGetCharWidth(c, gh->font) + gcw->fp; - if (gcw->cx + width >= gh->width) { - gcw->cx = 0; - gcw->cy += gcw->fy; - } - - if (gcw->cy + gcw->fy > gh->height) { -#if GDISP_NEED_SCROLL - /* scroll the console */ - gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor); - /* reset the cursor to the start of the last line */ - gcw->cx = 0; - gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy; -#else - /* clear the console */ - gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); - /* reset the cursor to the top of the window */ - gcw->cx = 0; - gcw->cy = 0; -#endif - } - -#if GWIN_CONSOLE_USE_CLEAR_LINES - /* clear to the end of the line */ - if (gcw->cx == 0) - gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor); -#endif -#if GWIN_CONSOLE_USE_FILLED_CHARS - gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor); -#else - gdispDrawChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color); -#endif - - /* update cursor */ - gcw->cx += width; - } - #undef gcw -} - -/** - * @brief Put a string at the cursor position in the window. It will wrap lines as required. - * @note Uses the current foreground color to draw the string and fills the background using the background drawing color - * - * @param[in] gh The window handle (must be a console window) - * @param[in] str The string to draw - * - * @api - */ -void gwinPutString(GHandle gh, const char *str) { - while(*str) - gwinPutChar(gh, *str++); -} - -/** - * @brief Put the character array at the cursor position in the window. It will wrap lines as required. - * @note Uses the current foreground color to draw the string and fills the background using the background drawing color - * - * @param[in] gh The window handle (must be a console window) - * @param[in] str The string to draw - * @param[in] n The number of characters to draw - * - * @api - */ -void gwinPutCharArray(GHandle gh, const char *str, size_t n) { - while(n--) - gwinPutChar(gh, *str++); -} -#endif - -/*------------------------------------------------------------------------------------------------------------------------*/ - -#if GWIN_NEED_BUTTON || defined(__DOXYGEN__) - -static const GButtonStyle GButtonDefaultStyle = { - GBTN_3D, - HTML2COLOR(0x404040), // color_up_edge; - HTML2COLOR(0xE0E0E0), // color_up_fill; - HTML2COLOR(0x000000), // color_up_txt; - HTML2COLOR(0x404040), // color_dn_edge; - HTML2COLOR(0x808080), // color_dn_fill; - HTML2COLOR(0x404040), // color_dn_txt; - }; - -/** - * @brief Create a button window. - * @return NULL if there is no resultant drawing area, otherwise a window handle. - * - * @param[in] gb The GConsoleWindow structure to initialise. If this is NULL the structure is dynamically allocated. - * @param[in] x,y The screen co-ordinates for the bottom left corner of the window - * @param[in] width The width of the window - * @param[in] height The height of the window - * @param[in] font The font to use - * @param[in] type The type of button - * @note The drawing color gets set to White and the background drawing color to Black. - * @note The dimensions and position may be changed to fit on the real screen. - * @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text. - * - * @api - */ -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; - gwinSetFont(&gb->gwin, font); - gwinSetButtonStyle(&gb->gwin, &GButtonDefaultStyle); - gb->type = type; - gb->state = GBTN_UP; - gb->txt = ""; - gb->callback = 0; - gb->inputsrc = 0; - return (GHandle)gb; -} - -/** - * @brief Set the style of a button. - * @details The button style is defined by its shape and colours. - * - * @param[in] gh The window handle (must be a button window) - * @param[in] style The button style to set. - * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style - * - * @api - */ -void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style) { - #define gbw ((GButtonObject *)gh) - if (gh->type != GW_BUTTON) - return; - - gbw->style.shape = style->shape; - gbw->style.color_up_edge = style->color_up_edge; - gbw->style.color_up_fill = style->color_up_fill; - gbw->style.color_dn_edge = style->color_dn_edge; - gbw->style.color_dn_fill = style->color_dn_fill; - gbw->style.color_up_txt = style->color_up_txt; - gbw->style.color_dn_txt = style->color_dn_txt; - #undef gbw -} - -/** - * @brief Set the text of a button. - * - * @param[in] gh The window handle (must be a button window) - * @param[in] txt The button text to set. This must be a constant string unless useAlloc is set. - * @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory. - * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text. - * - * @api - */ -void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) { - #define gbw ((GButtonObject *)gh) - if (gh->type != GW_BUTTON) - return; - - // Dispose of the old string - if ((gh->flags & GBTN_FLG_ALLOCTXT)) { - gh->flags &= ~GBTN_FLG_ALLOCTXT; - if (gbw->txt) { - chHeapFree((void *)gbw->txt); - gbw->txt = ""; - } - } - // Alloc the new text if required - if (txt && useAlloc) { - char *str; - - if ((str = (char *)chHeapAlloc(NULL, strlen(txt)+1))) { - gh->flags |= GBTN_FLG_ALLOCTXT; - strcpy(str, txt); - } - txt = (const char *)str; - } - - gbw->txt = txt ? txt : ""; - #undef gbw -} - -/** - * @brief Redraw the button. - * - * @param[in] gh The window handle (must be a button window) - * - * @api - */ -void gwinButtonDraw(GHandle gh) { - color_t cedge; - color_t cfill; - color_t ctxt; - const char * txt; - #define gbw ((GButtonObject *)gh) - #define RND_CNR_SIZE 5 - - if (gh->type != GW_BUTTON) - return; - - #if GDISP_NEED_CLIP - gdispSetClip(gh->x, gh->y, gh->width, gh->height); - #endif - - // Get the text (safely) - txt = gh->font && gbw->txt ? gbw->txt : ""; - - // Determine the colors to use - switch(gbw->state) { - case GBTN_DOWN: - cedge = gbw->style.color_dn_edge; - cfill = gbw->style.color_dn_fill; - ctxt = gbw->style.color_dn_txt; - break; - case GBTN_UP: default: - cedge = gbw->style.color_up_edge; - cfill = gbw->style.color_up_fill; - ctxt = gbw->style.color_up_txt; - break; - } - - // Draw according to the shape specified. - switch(gbw->style.shape) { -#if GDISP_NEED_ARC - case GBTN_ROUNDED: - if (gh->width >= 2*RND_CNR_SIZE+10) { - gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, cfill); - gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, ctxt, justifyCenter); - gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, cedge); - break; - } - /* Fall Through */ -#endif - case GBTN_SQUARE: - gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, cfill, justifyCenter); - gdispDrawBox(gh->x, gh->y, gh->width, gh->height, cedge); - break; -#if GDISP_NEED_ELLIPSE - case GBTN_ELLIPSE: - gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, cfill); - gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, justifyCenter); - gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, cedge); - break; -#endif - case GBTN_3D: default: - gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, ctxt, cfill, justifyCenter); - gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, cedge); - gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, cedge); - break; - } - #undef gbw -} - -//void gwinSetButtonCallback(GHandle gh, ????); -//void gwinSetButtonInput(GHandle gh, ????); -#endif - #endif /* GFX_USE_GWIN */ /** @} */ diff --git a/src/gwin/button.c b/src/gwin/button.c new file mode 100644 index 00000000..f62a86a4 --- /dev/null +++ b/src/gwin/button.c @@ -0,0 +1,331 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file src/gwin/button.c + * @brief GWIN Driver code. + * + * @addtogroup GWIN_BUTTON + * @{ + */ +#include "ch.h" +#include "hal.h" +#include "gwin.h" +#include "ginput.h" + +#if !defined(GFX_USE_GINPUT) || !GFX_USE_GINPUT + #error "GWIN Buttons require GFX_USE_GINPUT" +#endif + +#if (GFX_USE_GWIN && GWIN_NEED_BUTTON) || defined(__DOXYGEN__) + +#include +#include "gwin_internal.h" + +static const GButtonStyle GButtonDefaultStyle = { + GBTN_3D, + HTML2COLOR(0x404040), // color_up_edge; + HTML2COLOR(0xE0E0E0), // color_up_fill; + HTML2COLOR(0x000000), // color_up_txt; + HTML2COLOR(0x404040), // color_dn_edge; + HTML2COLOR(0x808080), // color_dn_fill; + HTML2COLOR(0x404040), // color_dn_txt; + }; + +// Process an event callback +static void gwinButtonCallback(void *param, GEvent *pe) { + GSourceListener *psl; + #define gh ((GHandle)param) + #define gbw ((GButtonObject *)param) + #define gsh ((GSourceHandle)param) + #define pme ((GEventMouse *)pe) + #define pte ((GEventTouch *)pe) + #define pxe ((GEventToggle *)pe) + #define pbe ((GEventGWinButton *)pe) + + switch (pe->type) { + #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE + case GEVENT_MOUSE: + case GEVENT_TOUCH: + // Ignore anything other than the primary mouse button going up or down + if (!((pme->current_buttons ^ pme->last_buttons) & GINPUT_MOUSE_BTN_LEFT)) + return; + + if (gbw->state == GBTN_UP) { + // Our button is UP: Test for button down over the button + if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT) + && pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width + && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) { + gbw->state = GBTN_DOWN; + gwinButtonDraw((GHandle)param); + } + return; + } + + // Our button is DOWN + + // Skip more mouse downs + if ((pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) + return; + + // This must be a mouse up - set the button as UP + gbw->state = GBTN_UP; + gwinButtonDraw((GHandle)param); + + // If the mouse up was over the button then create the event + if (pme->x >= gbw->gwin.x && pme->x < gbw->gwin.x + gbw->gwin.width + && pme->y >= gbw->gwin.y && pme->y < gbw->gwin.y + gbw->gwin.height) + break; + + return; + #endif + + #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE + case GEVENT_TOGGLE: + // State has changed - update the button + gbw->state = pxe->on ? GBTN_DOWN : GBTN_UP; + gwinButtonDraw((GHandle)param); + + // Trigger the event on button down (different than for mouse/touch) + if (gbw->state == GBTN_DOWN) + break; + + return; + #endif + + default: + return; + } + + // Trigger a GWIN Button Event + psl = 0; + while ((psl = geventGetSourceListener(gsh, psl))) { + if (!(pe = geventGetEventBuffer(psl))) + continue; + pbe->type = GEVENT_GWIN_BUTTON; + pbe->button = gh; + geventSendEvent(psl); + } + + #undef pbe + #undef pme + #undef pte + #undef pxe + #undef gsh + #undef gbw + #undef gh +} + +/** + * @brief Create a button window. + * @return NULL if there is no resultant drawing area, otherwise a window handle. + * + * @param[in] gb The GConsoleWindow structure to initialise. If this is NULL the structure is dynamically allocated. + * @param[in] x,y The screen co-ordinates for the bottom left corner of the window + * @param[in] width The width of the window + * @param[in] height The height of the window + * @param[in] font The font to use + * @param[in] type The type of button + * @note The drawing color gets set to White and the background drawing color to Black. + * @note The dimensions and position may be changed to fit on the real screen. + * @note The button is not automatically drawn. Call gwinButtonDraw() after changing the button style or setting the text. + * + * @api + */ +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; + gwinSetFont(&gb->gwin, font); + gwinSetButtonStyle(&gb->gwin, &GButtonDefaultStyle); + gb->type = type; + gb->state = GBTN_UP; + gb->txt = ""; + geventListenerInit(&gb->listener); + geventRegisterCallback(&gb->listener, gwinButtonCallback, gb); + return (GHandle)gb; +} + +/** + * @brief Set the style of a button. + * @details The button style is defined by its shape and colours. + * + * @param[in] gh The window handle (must be a button window) + * @param[in] style The button style to set. + * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button style + * + * @api + */ +void gwinSetButtonStyle(GHandle gh, const GButtonStyle *style) { + #define gbw ((GButtonObject *)gh) + if (gh->type != GW_BUTTON) + return; + + gbw->style.shape = style->shape; + gbw->style.color_up_edge = style->color_up_edge; + gbw->style.color_up_fill = style->color_up_fill; + gbw->style.color_dn_edge = style->color_dn_edge; + gbw->style.color_dn_fill = style->color_dn_fill; + gbw->style.color_up_txt = style->color_up_txt; + gbw->style.color_dn_txt = style->color_dn_txt; + #undef gbw +} + +/** + * @brief Set the text of a button. + * + * @param[in] gh The window handle (must be a button window) + * @param[in] txt The button text to set. This must be a constant string unless useAlloc is set. + * @param[in] useAlloc If TRUE the string specified will be copied into dynamically allocated memory. + * @note The button is not automatically redrawn. Call gwinButtonDraw() after changing the button text. + * + * @api + */ +void gwinSetButtonText(GHandle gh, const char *txt, bool_t useAlloc) { + #define gbw ((GButtonObject *)gh) + if (gh->type != GW_BUTTON) + return; + + // Dispose of the old string + if ((gh->flags & GBTN_FLG_ALLOCTXT)) { + gh->flags &= ~GBTN_FLG_ALLOCTXT; + if (gbw->txt) { + chHeapFree((void *)gbw->txt); + gbw->txt = ""; + } + } + // Alloc the new text if required + if (txt && useAlloc) { + char *str; + + if ((str = (char *)chHeapAlloc(NULL, strlen(txt)+1))) { + gh->flags |= GBTN_FLG_ALLOCTXT; + strcpy(str, txt); + } + txt = (const char *)str; + } + + gbw->txt = txt ? txt : ""; + #undef gbw +} + +/** + * @brief Redraw the button. + * + * @param[in] gh The window handle (must be a button window) + * + * @api + */ +void gwinButtonDraw(GHandle gh) { + color_t cedge; + color_t cfill; + color_t ctxt; + const char * txt; + #define gbw ((GButtonObject *)gh) + #define RND_CNR_SIZE 5 + + if (gh->type != GW_BUTTON) + return; + + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + + // Get the text (safely) + txt = gh->font && gbw->txt ? gbw->txt : ""; + + // Determine the colors to use + switch(gbw->state) { + case GBTN_DOWN: + cedge = gbw->style.color_dn_edge; + cfill = gbw->style.color_dn_fill; + ctxt = gbw->style.color_dn_txt; + break; + case GBTN_UP: default: + cedge = gbw->style.color_up_edge; + cfill = gbw->style.color_up_fill; + ctxt = gbw->style.color_up_txt; + break; + } + + // Draw according to the shape specified. + switch(gbw->style.shape) { +#if GDISP_NEED_ARC + case GBTN_ROUNDED: + if (gh->width >= 2*RND_CNR_SIZE+10) { + gdispFillRoundedBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, RND_CNR_SIZE-1, cfill); + gdispDrawStringBox(gh->x+1, gh->y+RND_CNR_SIZE, gh->width-2, gh->height-(2*RND_CNR_SIZE), txt, gh->font, ctxt, justifyCenter); + gdispDrawRoundedBox(gh->x, gh->y, gh->width, gh->height, RND_CNR_SIZE, cedge); + break; + } + /* Fall Through */ +#endif + case GBTN_SQUARE: + gdispFillStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, cfill, justifyCenter); + gdispDrawBox(gh->x, gh->y, gh->width, gh->height, cedge); + break; +#if GDISP_NEED_ELLIPSE + case GBTN_ELLIPSE: + gdispFillEllipse(gh->x+1, gh->y+1, gh->width/2-1, gh->height/2-1, cfill); + gdispDrawStringBox(gh->x+1, gh->y+1, gh->width-2, gh->height-2, txt, gh->font, ctxt, justifyCenter); + gdispDrawEllipse(gh->x, gh->y, gh->width/2, gh->height/2, cedge); + break; +#endif + case GBTN_3D: default: + gdispFillStringBox(gh->x, gh->y, gh->width-1, gh->height-1, txt, gh->font, ctxt, cfill, justifyCenter); + gdispDrawLine(gh->x+gh->width-1, gh->y, gh->x+gh->width-1, gh->y+gh->height-1, cedge); + gdispDrawLine(gh->x, gh->y+gh->height-1, gh->x+gh->width-2, gh->y+gh->height-1, cedge); + break; + } + #undef gbw +} + +// Attach a source to this button. Sources recognised: Mouse, Touch and Toggle - others are ignored (returns false). +bool_t gwinAttachButtonSource(GHandle gh, GSourceHandle gsh, GEventType type) { + #define gbw ((GButtonObject *)gh) + unsigned flags; + + switch (type) { + #if defined(GINPUT_NEED_MOUSE) && GINPUT_NEED_MOUSE + case GEVENT_MOUSE: + flags = 0; + break; + #endif + #if defined(GINPUT_NEED_TOUCH) && GINPUT_NEED_TOUCH + case GEVENT_TOUCH: + flags = 0; + break; + #endif + #if defined(GINPUT_NEED_TOGGLE) && GINPUT_NEED_TOGGLE + case GEVENT_TOGGLE: + flags = GLISTEN_TOGGLE_OFF|GLISTEN_TOGGLE_ON; + break; + #endif + default: + return FALSE; + } + return geventAttachSource(&gbw->listener, gsh, flags); + + #undef gbw +} + +#endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */ +/** @} */ + diff --git a/src/gwin/console.c b/src/gwin/console.c new file mode 100644 index 00000000..63960c23 --- /dev/null +++ b/src/gwin/console.c @@ -0,0 +1,210 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file src/gwin/console.c + * @brief GWIN Driver code. + * + * @addtogroup GWIN_CONSOLE + * @{ + */ +#include "ch.h" +#include "hal.h" +#include "gwin.h" + +#if (GFX_USE_GWIN && GWIN_NEED_CONSOLE) || defined(__DOXYGEN__) + +#include +#include "gwin_internal.h" + + +#define GWIN_CONSOLE_USE_CLEAR_LINES TRUE +#define GWIN_CONSOLE_USE_FILLED_CHARS FALSE + +/* + * Stream interface implementation. The interface is write only + */ + +#define Stream2GWindow(ip) ((GHandle)(((char *)(ip)) - (size_t)(&(((GConsoleObject *)0)->stream)))) + +static size_t GWinStreamWrite(void *ip, const uint8_t *bp, size_t n) { gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } +static size_t GWinStreamRead(void *ip, uint8_t *bp, size_t n) { (void)ip; (void)bp; (void)n; return 0; } +static msg_t GWinStreamPut(void *ip, uint8_t b) { gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } +static msg_t GWinStreamGet(void *ip) {(void)ip; return RDY_OK; } +static msg_t GWinStreamPutTimed(void *ip, uint8_t b, systime_t time) { (void)time; gwinPutChar(Stream2GWindow(ip), (char)b); return RDY_OK; } +static msg_t GWinStreamGetTimed(void *ip, systime_t timeout) { (void)ip; (void)timeout; return RDY_OK; } +static size_t GWinStreamWriteTimed(void *ip, const uint8_t *bp, size_t n, systime_t time) { (void)time; gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } +static size_t GWinStreamReadTimed(void *ip, uint8_t *bp, size_t n, systime_t time) { (void)ip; (void)bp; (void)n; (void)time; return 0; } + +struct GConsoleWindowVMT_t { + _base_asynchronous_channel_methods +}; + +static const struct GConsoleWindowVMT_t GWindowConsoleVMT = { + GWinStreamWrite, + GWinStreamRead, + GWinStreamPut, + GWinStreamGet, + GWinStreamPutTimed, + GWinStreamGetTimed, + GWinStreamWriteTimed, + GWinStreamReadTimed +}; + +/** + * @brief Create a console window. + * @details A console window allows text to be written using chprintf() (and the console functions defined here). + * @brief Text in a console window supports newlines and will wrap text as required. + * @return NULL if there is no resultant drawing area, otherwise a window handle. + * + * @param[in] gc The GConsoleObject structure to initialise. If this is NULL the structure is dynamically allocated. + * @param[in] x,y The screen co-ordinates for the bottom left corner of the window + * @param[in] width The width of the window + * @param[in] height The height of the window + * @param[in] font The font to use + * @note The console is not automatically cleared on creation. You must do that by calling gwinClear() (possibly after changing your background color) + * @note If the dispay does not support scrolling, the window will be cleared when the bottom line is reached. + * @note The default drawing color gets set to White and the background drawing color to Black. + * @note The dimensions and position may be changed to fit on the real screen. + * + * @api + */ +GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height, font_t font) { + if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject)))) + return 0; + gc->gwin.type = GW_CONSOLE; + gwinSetFont(&gc->gwin, font); + gc->stream.vmt = &GWindowConsoleVMT; + gc->cx = 0; + gc->cy = 0; + return (GHandle)gc; +} + +/** + * @brief Get a stream from a console window suitable for use with chprintf(). + * @return The stream handle or NULL if this is not a console window. + * + * @param[in] gh The window handle (must be a console window) + * + * @api + */ +BaseSequentialStream *gwinGetConsoleStream(GHandle gh) { + if (gh->type != GW_CONSOLE) + return 0; + return (BaseSequentialStream *)&(((GConsoleObject *)(gh))->stream); +} + +/** + * @brief Put a character at the cursor position in the window. + * @note Uses the current foreground color to draw the character and fills the background using the background drawing color + * + * @param[in] gh The window handle (must be a console window) + * @param[in] c The character to draw + * + * @api + */ +void gwinPutChar(GHandle gh, char c) { + uint8_t width; + #define gcw ((GConsoleObject *)gh) + + if (gh->type != GW_CONSOLE || !gh->font) return; + + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + + if (c == '\n') { + gcw->cx = 0; + gcw->cy += gcw->fy; + // We use lazy scrolling here and only scroll when the next char arrives + } else if (c == '\r') { + // gcw->cx = 0; + } else { + width = gdispGetCharWidth(c, gh->font) + gcw->fp; + if (gcw->cx + width >= gh->width) { + gcw->cx = 0; + gcw->cy += gcw->fy; + } + + if (gcw->cy + gcw->fy > gh->height) { +#if GDISP_NEED_SCROLL + /* scroll the console */ + gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, gcw->fy, gh->bgcolor); + /* reset the cursor to the start of the last line */ + gcw->cx = 0; + gcw->cy = (((coord_t)(gh->height/gcw->fy))-1)*gcw->fy; +#else + /* clear the console */ + gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); + /* reset the cursor to the top of the window */ + gcw->cx = 0; + gcw->cy = 0; +#endif + } + +#if GWIN_CONSOLE_USE_CLEAR_LINES + /* clear to the end of the line */ + if (gcw->cx == 0) + gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, gcw->fy, gh->bgcolor); +#endif +#if GWIN_CONSOLE_USE_FILLED_CHARS + gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor); +#else + gdispDrawChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color); +#endif + + /* update cursor */ + gcw->cx += width; + } + #undef gcw +} + +/** + * @brief Put a string at the cursor position in the window. It will wrap lines as required. + * @note Uses the current foreground color to draw the string and fills the background using the background drawing color + * + * @param[in] gh The window handle (must be a console window) + * @param[in] str The string to draw + * + * @api + */ +void gwinPutString(GHandle gh, const char *str) { + while(*str) + gwinPutChar(gh, *str++); +} + +/** + * @brief Put the character array at the cursor position in the window. It will wrap lines as required. + * @note Uses the current foreground color to draw the string and fills the background using the background drawing color + * + * @param[in] gh The window handle (must be a console window) + * @param[in] str The string to draw + * @param[in] n The number of characters to draw + * + * @api + */ +void gwinPutCharArray(GHandle gh, const char *str, size_t n) { + while(n--) + gwinPutChar(gh, *str++); +} + +#endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */ +/** @} */ + diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk new file mode 100644 index 00000000..cf952580 --- /dev/null +++ b/src/gwin/gwin.mk @@ -0,0 +1,2 @@ +GFXSRC += $(GFXLIB)/src/gwin/console.c \ + $(GFXLIB)/src/gwin/button.c diff --git a/src/gwin/gwin_internal.h b/src/gwin/gwin_internal.h new file mode 100644 index 00000000..13401a6f --- /dev/null +++ b/src/gwin/gwin_internal.h @@ -0,0 +1,53 @@ +/* + ChibiOS/GFX - Copyright (C) 2012 + Joel Bodenmann aka Tectu + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/** + * @file gwin_internal.h + * @brief GWIN Graphic window subsystem header file. + * + * @addtogroup GWIN + * @{ + */ +#ifndef _GWIN_INTERNAL_H +#define _GWIN_INTERNAL_H + +#if GFX_USE_GWIN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Sub-system constants. */ +/*===========================================================================*/ + +#define GWIN_FLG_DYNAMIC 0x0001 +#define GWIN_FIRST_CONTROL_FLAG 0x0002 +#define GBTN_FLG_ALLOCTXT (GWIN_FIRST_CONTROL_FLAG<<0) + +#ifdef __cplusplus +extern "C" { +#endif + +GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GWIN */ + +#endif /* _GWIN_INTERNAL_H */ +/** @} */ -- cgit v1.2.3