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.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/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/gdisp/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c similarity index 91% rename from drivers/gdisp/Win32/gdisp_lld.c rename to drivers/multiple/Win32/gdisp_lld.c index 8aff8efc..72ad0554 100644 --- a/drivers/gdisp/Win32/gdisp_lld.c +++ b/drivers/multiple/Win32/gdisp_lld.c @@ -29,12 +29,14 @@ #include "ch.h" #include "hal.h" #include "gdisp.h" -#include "touchscreen.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 "gdisp_emulation.c" +#include "lld/gdisp/emulation.c" #include #include @@ -60,7 +62,7 @@ static HBITMAP dcBitmap = NULL; static HBITMAP dcOldBitmap; static volatile bool_t isReady = FALSE; static coord_t mousex, mousey; -static bool_t mousedn; +static uint16_t mousebuttons; static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { @@ -70,28 +72,34 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) switch (Msg) { case WM_CREATE: break; +#if GINPUT_NEED_MOUSE case WM_LBUTTONDOWN: - mousedn = TRUE; - mousex = (coord_t)LOWORD(lParam); - mousey = (coord_t)HIWORD(lParam); - break; + mousebuttons = 0x0001; + goto mousemove; 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: + mousebuttons &= ~0x0001; + goto mousemove; case WM_MBUTTONDOWN: + mousebuttons = 0x0004; + goto mousemove; case WM_MBUTTONUP: - case WM_MBUTTONDBLCLK: + mousebuttons &= ~0x0004; + goto mousemove; case WM_RBUTTONDOWN: + mousebuttons = 0x0002; + goto mousemove; case WM_RBUTTONUP: - case WM_RBUTTONDBLCLK: + 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: @@ -882,70 +890,20 @@ void GDISP_LLD(drawpixel)(coord_t x, coord_t y, color_t color) { } #endif -#if GFX_USE_TOUCHSCREEN /*|| defined(__DOXYGEN__)*/ +#if GINPUT_NEED_MOUSE -void ts_store_calibration_lld(struct cal_t *cal) { - (void) cal; - // Just ignore the calibration data - we implicitly know the calibration +#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. } -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 /* 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/gdisp/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h similarity index 100% rename from drivers/gdisp/Win32/gdisp_lld_config.h rename to drivers/multiple/Win32/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/gdisp/Win32/readme.txt b/drivers/multiple/Win32/readme.txt similarity index 79% rename from drivers/gdisp/Win32/readme.txt rename to drivers/multiple/Win32/readme.txt index a475118b..6151f2f2 100644 --- a/drivers/gdisp/Win32/readme.txt +++ b/drivers/multiple/Win32/readme.txt @@ -5,7 +5,8 @@ and a touchscreen driver. 1. Add in your halconf.h: a) #define GFX_USE_GDISP TRUE - b) #define GFX_USE_TOUCHSCREEN 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 @@ -14,7 +15,7 @@ and a touchscreen driver. 2. To your makefile add the following lines: include $(GFXLIB)/gfx.mk - include $(GFXLIB)/drivers/gdisp/Win32/gdisp_lld.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 similarity index 100% rename from include/gdisp_fonts.h rename to include/gdisp/fonts.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/gdisp_emulation.c b/include/lld/gdisp/emulation.c similarity index 96% rename from include/gdisp_emulation.c rename to include/lld/gdisp/emulation.c index 31ca1a03..88a8c42f 100644 --- a/include/gdisp_emulation.c +++ b/include/lld/gdisp/emulation.c @@ -481,7 +481,7 @@ #endif #if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT - #include "gdisp_fonts.h" + #include "gdisp/fonts.h" #endif #if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT diff --git a/include/gdisp_lld.h b/include/lld/gdisp/gdisp_lld.h similarity index 100% rename from include/gdisp_lld.h rename to include/lld/gdisp/gdisp_lld.h diff --git a/include/gdisp_lld_msgs.h b/include/lld/gdisp/gdisp_lld_msgs.h similarity index 100% rename from include/gdisp_lld_msgs.h rename to include/lld/gdisp/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/touchscreen_lld.h b/include/lld/touchscreen/touchscreen_lld.h similarity index 100% rename from include/touchscreen_lld.h rename to include/lld/touchscreen/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/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/dial.c similarity index 79% rename from src/ginput.c rename to src/ginput/dial.c index 9b6b180a..cb6799a9 100644 --- a/src/ginput.c +++ b/src/ginput/dial.c @@ -19,8 +19,8 @@ */ /** - * @file src/ginput.c - * @brief GINPUT Driver code. + * @file src/ginput/dial.c + * @brief GINPUT dial code. * * @addtogroup GINPUT * @{ @@ -29,9 +29,7 @@ #include "hal.h" #include "ginput.h" -#if GFX_USE_GINPUT || defined(__DOXYGEN__) - -#error "GINPUT: Not Implemented Yet" - -#endif /* GFX_USE_GINPUT */ +#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/drivers/gdisp/Win32/touchscreen_lld_config.h b/src/gwin/gwin_internal.h similarity index 59% rename from drivers/gdisp/Win32/touchscreen_lld_config.h rename to src/gwin/gwin_internal.h index ef5d5a27..13401a6f 100644 --- a/drivers/gdisp/Win32/touchscreen_lld_config.h +++ b/src/gwin/gwin_internal.h @@ -17,34 +17,37 @@ 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. + * @file gwin_internal.h + * @brief GWIN Graphic window subsystem header file. * - * @addtogroup TOUCHSCREEN + * @addtogroup GWIN * @{ */ +#ifndef _GWIN_INTERNAL_H +#define _GWIN_INTERNAL_H -#ifndef TOUCHSCREEN_LLD_CONFIG_H -#define TOUCHSCREEN_LLD_CONFIG_H - -#if GFX_USE_TOUCHSCREEN /*|| defined(__DOXYGEN__)*/ +#if GFX_USE_GWIN || defined(__DOXYGEN__) /*===========================================================================*/ -/* Driver hardware support. */ +/* Sub-system constants. */ /*===========================================================================*/ -#define TOUCHSCREEN_HAS_PRESSED TRUE -#define TOUCHSCREEN_HAS_PRESSURE FALSE -#define TOUCHSCREEN_XY_INVERTED FALSE -#define TOUCHSCREEN_STORE_CALIBRATION TRUE -#define TOUCHSCREEN_CONVERSIONS 1 +#define GWIN_FLG_DYNAMIC 0x0001 +#define GWIN_FIRST_CONTROL_FLAG 0x0002 +#define GBTN_FLG_ALLOCTXT (GWIN_FIRST_CONTROL_FLAG<<0) -struct TouchscreenDriver {}; +#ifdef __cplusplus +extern "C" { +#endif -#endif /* GFX_USE_TOUCHSCREEN */ +GHandle _gwinInit(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size); -#endif /* TOUCHSCREEN_LLD_CONFIG_H */ +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_GWIN */ + +#endif /* _GWIN_INTERNAL_H */ /** @} */ -