Ginput and structure changes

GINPUT Touch including drivers
GTIMER fixes
GEVENT fixes
GWIN button completion
Structure changes to better seperate sections of a sub-system
ugfx_release_2.6
Andrew Hannam 2012-11-26 18:45:26 +10:00
parent 6cc2bc280c
commit 8275c8820f
65 changed files with 3593 additions and 887 deletions

View File

@ -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
/*===========================================================================*/

View File

@ -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 */

View File

@ -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"

View File

@ -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 */

View File

@ -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.

View File

@ -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 ---- */
/*

View File

@ -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. */

View File

@ -1,5 +0,0 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/gdisp/Win32/gdisp_lld.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/gdisp/Win32

View File

@ -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

View File

@ -0,0 +1,62 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,65 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,60 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,44 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,139 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,87 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,97 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,41 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,136 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,96 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,174 @@
/*
ChibiOS/RT - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,41 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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

View File

@ -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 <stdio.h>
#include <string.h>
@ -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 */
/** @} */

View File

@ -0,0 +1,5 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/multiple/Win32

View File

@ -0,0 +1,58 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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

4
gfx.mk
View File

@ -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

View File

@ -114,7 +114,7 @@
/*===========================================================================*/
/* Include the low level driver information */
#include "gdisp_lld.h"
#include "lld/gdisp/gdisp_lld.h"
/*===========================================================================*/
/* Type definitions */

View File

@ -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

View File

@ -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 */

View File

@ -0,0 +1,89 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,143 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,135 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,93 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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);

View File

@ -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 */

View File

@ -0,0 +1,142 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,102 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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

View File

@ -0,0 +1,125 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -0,0 +1,71 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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"

View File

@ -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;

View File

@ -29,7 +29,8 @@
#if GDISP_NEED_TEXT
#include "gdisp_fonts.h"
#include "gdisp/fonts.h"
/* fontSmall - for side buttons */
#if 1

View File

@ -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();
}
}
/**

View File

@ -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 */
/** @} */

View File

@ -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

View File

@ -0,0 +1,35 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

554
src/ginput/mouse.c 100644
View File

@ -0,0 +1,554 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

161
src/ginput/toggle.c 100644
View File

@ -0,0 +1,161 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */

View File

@ -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 */

View File

@ -31,17 +31,11 @@
#if GFX_USE_GWIN || defined(__DOXYGEN__)
#include <string.h>
#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 */
/** @} */

331
src/gwin/button.c 100644
View File

@ -0,0 +1,331 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 <string.h>
#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 */
/** @} */

210
src/gwin/console.c 100644
View File

@ -0,0 +1,210 @@
/*
ChibiOS/GFX - Copyright (C) 2012
Joel Bodenmann aka Tectu <joel@unormal.org>
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 <http://www.gnu.org/licenses/>.
*/
/**
* @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 <string.h>
#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 */
/** @} */

2
src/gwin/gwin.mk 100644
View File

@ -0,0 +1,2 @@
GFXSRC += $(GFXLIB)/src/gwin/console.c \
$(GFXLIB)/src/gwin/button.c

View File

@ -17,34 +17,37 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @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 */
/** @} */