Merge branch 'newmouse'

ugfx_release_2.6
Joel Bodenmann 2014-11-12 08:50:05 +01:00
commit d3a0606c65
81 changed files with 3668 additions and 2742 deletions

View File

@ -16,6 +16,14 @@
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_ADS7843_PEN_CALIBRATE_ERROR 8
#define GMOUSE_ADS7843_PEN_CLICK_ERROR 6
#define GMOUSE_ADS7843_PEN_MOVE_ERROR 4
#define GMOUSE_ADS7843_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_ADS7843_FINGER_CLICK_ERROR 18
#define GMOUSE_ADS7843_FINGER_MOVE_ERROR 14
static const SPIConfig spicfg = {
0,
GPIOG,
@ -23,67 +31,49 @@ static const SPIConfig spicfg = {
/* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
};
/**
* @brief Initialise the board for the touch.
*
* @notapi
*/
static inline void init_board(void) {
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_ADS7843_BOARD_DATA_SIZE 0
static bool_t init_board(GMouse* m, unsigned driverinstance) {
(void) m;
if (driverinstance)
return FALSE;
spiStart(&SPID2, &spicfg);
return TRUE;
}
/**
* @brief Check whether the surface is currently touched
* @return TRUE if the surface is currently touched
*
* @notapi
*/
static inline bool_t getpin_pressed(void) {
static inline bool_t getpin_pressed(GMouse* m) {
(void) m;
return (!palReadPad(GPIOG, 0));
}
/**
* @brief Aquire the bus ready for readings
*
* @notapi
*/
static inline void aquire_bus(void) {
static inline void aquire_bus(GMouse* m) {
(void) m;
spiAcquireBus(&SPID2);
//TOUCHSCREEN_SPI_PROLOGUE();
palClearPad(GPIOG, 10);
}
/**
* @brief Release the bus after readings
*
* @notapi
*/
static inline void release_bus(void) {
static inline void release_bus(GMouse* m) {
(void) m;
palSetPad(GPIOG, 10);
spiReleaseBus(&SPID2);
//TOUCHSCREEN_SPI_EPILOGUE();
}
/**
* @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 inline uint16_t read_value(GMouse* m, uint16_t port) {
static uint8_t txbuf[3] = {0};
static uint8_t rxbuf[3] = {0};
uint16_t ret;
(void) m;
txbuf[0] = port;
spiExchange(&SPID2, 3, txbuf, rxbuf);
ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
return ret;
return ((uint16_t)rxbuf[1] << 5) | (rxbuf[2] >> 3);
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -34,41 +34,61 @@ static const SPIConfig spicfg = {
/* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
};
static inline void init_board(void) {
// Resolution and Accuracy Settings
#define GMOUSE_ADS7843_PEN_CALIBRATE_ERROR 8
#define GMOUSE_ADS7843_PEN_CLICK_ERROR 6
#define GMOUSE_ADS7843_PEN_MOVE_ERROR 4
#define GMOUSE_ADS7843_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_ADS7843_FINGER_CLICK_ERROR 18
#define GMOUSE_ADS7843_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_ADS7843_BOARD_DATA_SIZE 0
static bool_t init_board(GMouse* m, unsigned driverinstance) {
(void) m;
if (driverinstance)
return FALSE;
palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) ); /* SCK */
palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5) ); /* MISO */
palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) ); /* MOSI */
palSetPadMode(GPIOC, 4, PAL_MODE_OUTPUT_PUSHPULL); /* CS */
spiStart(&SPID2, &spicfg);
return TRUE;
}
static inline bool_t getpin_pressed(void) {
static inline bool_t getpin_pressed(GMouse* m) {
(void) m;
return (!palReadPad(GPIOC, 5));
}
static inline void aquire_bus(void) {
static inline void aquire_bus(GMouse* m) {
(void) m;
spiAcquireBus(&SPID2);
palClearPad(GPIOC, 4);
}
static inline void release_bus(void) {
static inline void release_bus(GMouse* m) {
(void) m;
palSetPad(GPIOC, 4);
spiReleaseBus(&SPID2);
}
static inline uint16_t read_value(uint16_t port) {
static inline uint16_t read_value(GMouse* m, uint16_t port) {
static uint8_t txbuf[3] = {0};
static uint8_t rxbuf[3] = {0};
uint16_t ret;
(void) m;
txbuf[0] = port;
spiExchange(&SPID2, 3, txbuf, rxbuf);
ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
return ret;
return ((uint16_t)rxbuf[1] << 5) | (rxbuf[2] >> 3);
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -16,6 +16,24 @@
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
#define ADC_MAX 1023
// Resolution and Accuracy Settings
#define GMOUSE_MCU_PEN_CALIBRATE_ERROR 8
#define GMOUSE_MCU_PEN_CLICK_ERROR 6
#define GMOUSE_MCU_PEN_MOVE_ERROR 4
#define GMOUSE_MCU_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_MCU_FINGER_CLICK_ERROR 18
#define GMOUSE_MCU_FINGER_MOVE_ERROR 14
#define GMOUSE_MCU_Z_MIN 0 // The minimum Z reading
#define GMOUSE_MCU_Z_MAX ADC_MAX // The maximum Z reading
#define GMOUSE_MCU_Z_TOUCHON 60 // Values between this and Z_MAX are definitely pressed
#define GMOUSE_MCU_Z_TOUCHOFF 30 // Values between this and Z_MIN are definitely not pressed
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_MCU_BOARD_DATA_SIZE 0
static const ADCConfig ADCC = {
.vref = ADC_VREF_CFG_AVDD_AVSS,
.stime = 15,
@ -29,10 +47,6 @@ static struct ADCDriver ADCD;
#define XPOS 12 // L
#define YPOS 11 // D
#define ADC_MAX 1023
#define TOUCH_THRESHOULD 50
static const ADCConversionGroup ADC_X_CG = {
.circular = FALSE,
.num_channels = 1,
@ -45,104 +59,59 @@ static const ADCConversionGroup ADC_Y_CG = {
.channels = 1 << YPOS,
};
/**
* @brief Initialise the board for the touch.
*
* @notapi
*/
static inline void init_board(void) {
adcObjectInit(&ADCD);
adcStart(&ADCD, &ADCC);
static bool_t init_board(GMouse *m, unsigned driverinstance) {
(void) m;
if (driverinstance)
return FALSE;
adcObjectInit(&ADCD);
adcStart(&ADCD, &ADCC);
return TRUE;
}
/**
* @brief Check whether the surface is currently touched
* @return TRUE if the surface is currently touched
*
* @notapi
*/
static inline bool_t getpin_pressed(void) {
adcsample_t samples[2] = {0, };
static bool_t read_xyz(GMouse *m, GMouseReading *prd) {
adcsample_t samples[2];
// Set X+ to ground
palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
palClearPad(IOPORTB, XPOS);
prd->buttons = 0;
// Set Y- to VCC
palSetPadMode(IOPORTB, YNEG, PAL_MODE_OUTPUT);
palSetPad(IOPORTB, YNEG);
// Read the z value first.
// Set X+ to ground and Y- to VCC
palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
palClearPad(IOPORTB, XPOS);
palSetPadMode(IOPORTB, YNEG, PAL_MODE_OUTPUT);
palSetPad(IOPORTB, YNEG);
palSetPadMode(IOPORTB, XNEG, PAL_MODE_INPUT_ANALOG);
palSetPadMode(IOPORTB, YPOS, PAL_MODE_INPUT_ANALOG);
adcConvert(&ADCD, &ADC_X_CG, &samples[0], 1);
adcConvert(&ADCD, &ADC_Y_CG, &samples[1], 1);
pdr->z = ADC_MAX - (samples[1] - samples[0]);
palSetPadMode(IOPORTB, XNEG, PAL_MODE_INPUT_ANALOG);
palSetPadMode(IOPORTB, YPOS, PAL_MODE_INPUT_ANALOG);
// Shortcut - no need to read X or Y if the touch is off.
if (pdr->z < GMOUSE_MCU_Z_TOUCHON)
return TRUE;
adcConvert(&ADCD, &ADC_X_CG, &samples[0], 1);
adcConvert(&ADCD, &ADC_Y_CG, &samples[1], 1);
// Read X
palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
palSetPad(IOPORTB, XPOS);
palSetPadMode(IOPORTB, XNEG, PAL_MODE_OUTPUT);
palClearPad(IOPORTB, XNEG);
palSetPadMode(IOPORTB, YNEG, PAL_MODE_INPUT);
palSetPadMode(IOPORTB, YPOS, PAL_MODE_INPUT_ANALOG);
adcConvert(&ADCD, &ADC_Y_CG, &samples[0], 1);
pdr->x = ADC_MAX - samples[0];
return (ADC_MAX - (samples[1] - samples[0])) > TOUCH_THRESHOULD;
}
// Read Y
palSetPadMode(IOPORTB, YNEG, PAL_MODE_OUTPUT);
palClearPad(IOPORTB, YNEG);
palSetPadMode(IOPORTB, YPOS, PAL_MODE_OUTPUT);
palSetPad(IOPORTB, YPOS);
palSetPadMode(IOPORTB, XPOS, PAL_MODE_INPUT);
palSetPadMode(IOPORTB, XNEG, PAL_MODE_INPUT_ANALOG);
adcConvert(&ADCD, &ADC_X_CG, &samples[0], 1);
pdr->y = ADC_MAX - samples[0];
/**
* @brief Aquire the bus ready for readings
*
* @notapi
*/
static inline void aquire_bus(void) {
}
/**
* @brief Release the bus after readings
*
* @notapi
*/
static inline void release_bus(void) {
}
/**
* @brief Read an x value from touch controller
* @return The value read from the controller
*
* @notapi
*/
static inline uint16_t read_x_value(void) {
adcsample_t sample;
palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
palSetPad(IOPORTB, XPOS);
palSetPadMode(IOPORTB, XNEG, PAL_MODE_OUTPUT);
palClearPad(IOPORTB, XNEG);
palSetPadMode(IOPORTB, YNEG, PAL_MODE_INPUT);
palSetPadMode(IOPORTB, YPOS, PAL_MODE_INPUT_ANALOG);
adcConvert(&ADCD, &ADC_Y_CG, &sample, 1);
return ADC_MAX - sample;
}
/**
* @brief Read an y value from touch controller
* @return The value read from the controller
*
* @notapi
*/
static inline uint16_t read_y_value(void) {
adcsample_t sample;
palSetPadMode(IOPORTB, YNEG, PAL_MODE_OUTPUT);
palClearPad(IOPORTB, YNEG);
palSetPadMode(IOPORTB, YPOS, PAL_MODE_OUTPUT);
palSetPad(IOPORTB, YPOS);
palSetPadMode(IOPORTB, XPOS, PAL_MODE_INPUT);
palSetPadMode(IOPORTB, XNEG, PAL_MODE_INPUT_ANALOG);
adcConvert(&ADCD, &ADC_X_CG, &sample, 1);
return ADC_MAX - sample;
return TRUE;
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,88 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
static const I2CConfig i2ccfg = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};
static void init_board(void)
{
palSetPadMode(GPIOC, 13, PAL_MODE_INPUT | PAL_STM32_PUDR_FLOATING); /* TP IRQ */
palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); /* SCL */
palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); /* SDA */
i2cStart(&I2CD1, &i2ccfg);
}
static inline bool_t getpin_irq(void)
{
return (!(palReadPad(GPIOC, 13)));
}
static void write_reg(uint8_t reg, uint8_t n, uint16_t val)
{
uint8_t txbuf[3];
i2cAcquireBus(&I2CD1);
txbuf[0] = reg;
if (n == 1) {
txbuf[1] = val;
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 2, 0, 0, MS2ST(STMPE811_TIMEOUT));
} else if (n == 2) {
txbuf[1] = ((val & 0xFF00) >> 8);
txbuf[2] = (val & 0x00FF);
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 3, 0, 0, MS2ST(STMPE811_TIMEOUT));
}
i2cReleaseBus(&I2CD1);
}
static uint16_t read_reg(uint8_t reg, uint8_t n)
{
uint8_t txbuf[1], rxbuf[2];
uint16_t ret;
rxbuf[0] = 0;
rxbuf[1] = 0;
i2cAcquireBus(&I2CD1);
txbuf[0] = reg;
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 1, rxbuf, n, MS2ST(STMPE811_TIMEOUT));
if (n == 1) {
ret = rxbuf[0];
} else if (n == 2) {
ret = ((rxbuf[0] << 8) | (rxbuf[1] & 0xFF));
}
i2cReleaseBus(&I2CD1);
return ret;
}
static void read_reg_n(uint8_t reg, uint8_t n, uint8_t *rxbuf)
{
uint8_t txbuf[1];
i2cAcquireBus(&I2CD1);
txbuf[0] = reg;
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 1, rxbuf, n, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD1);
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,22 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 12
#define GINPUT_MOUSE_READ_CYCLES 4
#define GINPUT_MOUSE_POLL_PERIOD 3
#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
#define GINPUT_MOUSE_CLICK_TIME 500
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,119 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_STMPE811_PEN_CALIBRATE_ERROR 8
#define GMOUSE_STMPE811_PEN_CLICK_ERROR 6
#define GMOUSE_STMPE811_PEN_MOVE_ERROR 4
#define GMOUSE_STMPE811_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_STMPE811_FINGER_CLICK_ERROR 18
#define GMOUSE_STMPE811_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_STMPE811_BOARD_DATA_SIZE 0
// Options - Leave these commented to make it user configurable in the gfxconf.h
//#define GMOUSE_STMPE811_READ_PRESSURE FALSE
//#define GMOUSE_STMPE811_SELF_CALIBRATE FALSE
//#define GMOUSE_STMPE811_TEST_MODE FALSE
// If TRUE this board has the STMPE811 IRQ pin connected to a GPIO.
// Note: Although this board has such a pin its reliability has not been tested on this board!!!!!
#define GMOUSE_STMPE811_GPIO_IRQPIN FALSE
// If TRUE this is a really slow CPU and we should always clear the FIFO between reads.
#define GMOUSE_STMPE811_SLOW_CPU FALSE
// Slave address
#define STMPE811_ADDR (0x82 >> 1)
// Maximum timeout
#define STMPE811_TIMEOUT 0x3000
static const I2CConfig i2ccfg = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};
static bool_t init_board(GMouse* m, unsigned driverinstance) {
(void) m;
// This board only supports one touch panel
if (driverinstance)
return FALSE;
palSetPadMode(GPIOC, 13, PAL_MODE_INPUT | PAL_STM32_PUDR_FLOATING); /* TP IRQ */
palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); /* SCL */
palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); /* SDA */
i2cStart(&I2CD1, &i2ccfg);
return TRUE;
}
#if GMOUSE_STMPE811_GPIO_IRQPIN
static bool_t getpin_irq(GMouse* m) {
(void) m;
return !palReadPad(GPIOC, 13);
}
#endif
static inline void aquire_bus(GMouse* m) {
(void) m;
}
static inline void release_bus(GMouse* m) {
(void) m;
}
static void write_reg(GMouse* m, uint8_t reg, uint8_t val) {
uint8_t txbuf[2];
(void) m;
txbuf[0] = reg;
txbuf[1] = val;
i2cAcquireBus(&I2CD1);
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 2, 0, 0, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD1);
}
static uint8_t read_byte(GMouse* m, uint8_t reg) {
uint8_t rxbuf[1];
(void) m;
rxbuf[0] = 0;
i2cAcquireBus(&I2CD1);
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, &reg, 1, rxbuf, 1, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD1);
return rxbuf[0];
}
static uint16_t read_word(GMouse* m, uint8_t reg) {
uint8_t rxbuf[2];
(void) m;
rxbuf[0] = 0;
rxbuf[1] = 0;
i2cAcquireBus(&I2CD1);
i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, &reg, 1, rxbuf, 2, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD1);
return (((uint16_t)rxbuf[0]) << 8) | rxbuf[1];
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,56 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
static const SPIConfig spicfg = {
0,
GPIOC,
6,
/* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
};
static inline void init_board(void)
{
spiStart(&SPID1, &spicfg);
}
static inline bool_t getpin_pressed(void)
{
return (!palReadPad(GPIOC, 4));
}
static inline void aquire_bus(void)
{
spiAcquireBus(&SPID1);
palClearPad(GPIOC, 6);
}
static inline void release_bus(void)
{
palSetPad(GPIOC, 6);
spiReleaseBus(&SPID1);
}
static inline uint16_t read_value(uint16_t port)
{
static uint8_t txbuf[3] = {0};
static uint8_t rxbuf[3] = {0};
uint16_t ret;
txbuf[0] = port;
spiExchange(&SPID1, 3, txbuf, rxbuf);
ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
return ret;
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,22 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 12
#define GINPUT_MOUSE_READ_CYCLES 4
#define GINPUT_MOUSE_POLL_PERIOD 3
#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
#define GINPUT_MOUSE_CLICK_TIME 500
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,86 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_ADS7843_PEN_CALIBRATE_ERROR 2
#define GMOUSE_ADS7843_PEN_CLICK_ERROR 2
#define GMOUSE_ADS7843_PEN_MOVE_ERROR 2
#define GMOUSE_ADS7843_FINGER_CALIBRATE_ERROR 20
#define GMOUSE_ADS7843_FINGER_CLICK_ERROR 4
#define GMOUSE_ADS7843_FINGER_MOVE_ERROR 4
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_ADS7843_BOARD_DATA_SIZE 0
static const SPIConfig spicfg = {
0,
GPIOC,
6,
/* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
};
static bool_t init_board(GMouse* m, unsigned driverinstance)
{
(void)m;
// Only one touch interface on this board
if (driverinstance)
return FALSE;
// Set the GPIO modes
palSetPadMode(GPIOC, 4, PAL_MODE_INPUT_PULLUP);
// Start the SPI peripheral
spiStart(&SPID1, &spicfg);
return TRUE;
}
static inline bool_t getpin_pressed(GMouse* m)
{
(void) m;
return (!palReadPad(GPIOC, 4));
}
static inline void aquire_bus(GMouse* m)
{
(void) m;
spiAcquireBus(&SPID1);
palClearPad(GPIOC, 6);
}
static inline void release_bus(GMouse* m)
{
(void) m;
palSetPad(GPIOC, 6);
spiReleaseBus(&SPID1);
}
static inline uint16_t read_value(GMouse* m, uint16_t port)
{
static uint8_t txbuf[3] = {0};
static uint8_t rxbuf[3] = {0};
uint16_t ret;
(void) m;
txbuf[0] = port;
spiExchange(&SPID1, 3, txbuf, rxbuf);
ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3);
return ret;
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,111 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* @file drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_marlin.h
* @brief GINPUT Touch low level driver source for the FT5x06.
*
* @defgroup Mouse Mouse
* @ingroup GINPUT
* @{
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
/* I2C interface #2 - Touchscreen controller */
static const I2CConfig i2ccfg2 = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};
/**
* @brief Initialise the board for the touch.
*
* @notapi
*/
static void init_board(void) {
}
/**
* @brief Write a value into a certain register
*
* @param[in] reg The register address
* @param[in] n The amount of bytes (one or two)
* @param[in] val The value
*
* @notapi
*/
static void write_reg(uint8_t reg, uint8_t n, uint16_t val) {
uint8_t txbuf[3];
i2cAcquireBus(&I2CD2);
txbuf[0] = reg;
if (n == 1) {
txbuf[1] = val;
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 2, 0, 0, MS2ST(FT5x06_TIMEOUT));
} else if (n == 2) {
txbuf[1] = ((val & 0xFF00) >> 8);
txbuf[2] = (val & 0x00FF);
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 3, 0, 0, MS2ST(FT5x06_TIMEOUT));
}
i2cReleaseBus(&I2CD2);
}
/**
* @brief Read the value of a certain register
*
* @param[in] reg The register address
* @param[in] n The amount of bytes (one or two)
*
* @return Data read from device (one byte or two depending on n param)
*
* @notapi
*/
static uint16_t read_reg(uint8_t reg, uint8_t n) {
uint8_t txbuf[1], rxbuf[2];
uint16_t ret;
rxbuf[0] = 0;
rxbuf[1] = 0;
i2cAcquireBus(&I2CD2);
txbuf[0] = reg;
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 1, rxbuf, n, MS2ST(FT5x06_TIMEOUT));
if (n == 1) {
ret = rxbuf[0];
} else if (n == 2) {
ret = ((rxbuf[0] << 8) | (rxbuf[1] & 0xFF));
}
i2cReleaseBus(&I2CD2);
return ret;
}
static void read_reg_n(uint8_t reg, uint8_t n, uint8_t *rxbuf) {
uint8_t txbuf[1];
i2cAcquireBus(&I2CD2);
txbuf[0] = reg;
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 1, rxbuf, n, MS2ST(FT5x06_TIMEOUT));
i2cReleaseBus(&I2CD2);
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
/** @} */

View File

@ -1,32 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
/**
* @file drivers/ginput/touch/STMPE811/ginput_lld_mouse_config.h
* @brief GINPUT LLD header file for mouse/touch driver.
*
* @defgroup Mouse Mouse
* @ingroup GINPUT
*
* @{
*/
#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 15
#define GINPUT_MOUSE_READ_CYCLES 1
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 10
#define GINPUT_MOUSE_MAX_MOVE_JITTER 5
#define GINPUT_MOUSE_CLICK_TIME 450
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */
/** @} */

View File

@ -0,0 +1,93 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_FT5x06_PEN_CALIBRATE_ERROR 8
#define GMOUSE_FT5x06_PEN_CLICK_ERROR 6
#define GMOUSE_FT5x06_PEN_MOVE_ERROR 4
#define GMOUSE_FT5x06_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_FT5x06_FINGER_CLICK_ERROR 18
#define GMOUSE_FT5x06_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_FT5x06_BOARD_DATA_SIZE 0
// Set this to TRUE if you want self-calibration.
// NOTE: This is not as accurate as real calibration.
// It requires the orientation of the touch panel to match the display.
// It requires the active area of the touch panel to exactly match the display size.
#define GMOUSE_FT5x06_SELF_CALIBRATE FALSE
/* I2C interface #2 - Touchscreen controller */
static const I2CConfig i2ccfg2 = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};
static bool_t init_board(GMouse* m, unsigned driverinstance) {
(void) m;
// We only support one of these on this board
if (driverinstance)
return FALSE;
return TRUE;
}
static inline void aquire_bus(GMouse* m) {
(void) m;
}
static inline void release_bus(GMouse* m) {
(void) m;
}
static void write_reg(GMouse* m, uint8_t reg, uint8_t val) {
uint8_t txbuf[2];
(void) m;
txbuf[0] = reg;
txbuf[1] = val;
i2cAcquireBus(&I2CD2);
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 2, 0, 0, MS2ST(FT5x06_TIMEOUT));
i2cReleaseBus(&I2CD2);
}
static uint8_t read_byte(GMouse* m, uint8_t reg) {
uint8_t rxbuf[1];
(void) m;
rxbuf[0] = 0;
i2cAcquireBus(&I2CD2);
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, &reg, 1, rxbuf, 1, MS2ST(FT5x06_TIMEOUT));
i2cReleaseBus(&I2CD2);
return rxbuf[0];
}
static uint16_t read_word(GMouse* m, uint8_t reg) {
uint8_t rxbuf[2];
(void) m;
rxbuf[0] = 0;
rxbuf[1] = 0;
i2cAcquireBus(&I2CD2);
i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, &reg, 1, rxbuf, 2, MS2ST(FT5x06_TIMEOUT));
i2cReleaseBus(&I2CD2);
return (((uint16_t)rxbuf[0]) << 8) | rxbuf[1];
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,85 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 adcgrpcfg = {
FALSE,
ADC_NUM_CHANNELS,
0,
0,
/* HW dependent part.*/
0,
ADC_CR2_SWSTART,
0,
0,
ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
0,
ADC_SQR3_SQ2_N(ADC_CHANNEL_IN8) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN9)
};
static inline void init_board(void) {
adcStart(&ADCD1, 0);
}
static inline void aquire_bus(void) {
}
static inline void release_bus(void) {
}
static inline void setup_x(void) {
palSetPad(GPIOB, GPIOB_DRIVEA);
palClearPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(2);
}
static inline void setup_y(void) {
palClearPad(GPIOB, GPIOB_DRIVEA);
palSetPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(2);
}
static inline void setup_z(void) {
palClearPad(GPIOB, GPIOB_DRIVEA);
palClearPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(2);
}
static inline uint16_t read_x(void) {
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
adcConvert(&ADCD1, &adcgrpcfg, samples, ADC_BUF_DEPTH);
return samples[1];
}
static inline uint16_t read_y(void) {
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
adcConvert(&ADCD1, &adcgrpcfg, samples, ADC_BUF_DEPTH);
return samples[0];
}
static inline uint16_t read_z(void) {
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
adcConvert(&ADCD1, &adcgrpcfg, samples, ADC_BUF_DEPTH);
// z will go from ~200 to ~4000 when pressed
// auto range this back to 0 to 100
if (samples[0] > 4000)
return 100;
if (samples[0] < 400)
return 0;
return (samples[0] - 400) / ((4000-400)/100);
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,21 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 12
#define GINPUT_MOUSE_READ_CYCLES 1
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
#define GINPUT_MOUSE_CLICK_TIME 500
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,95 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _LLD_GMOUSE_MCU_BOARD_H
#define _LLD_GMOUSE_MCU_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_MCU_PEN_CALIBRATE_ERROR 8
#define GMOUSE_MCU_PEN_CLICK_ERROR 6
#define GMOUSE_MCU_PEN_MOVE_ERROR 4
#define GMOUSE_MCU_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_MCU_FINGER_CLICK_ERROR 18
#define GMOUSE_MCU_FINGER_MOVE_ERROR 14
#define GMOUSE_MCU_Z_MIN 0
#define GMOUSE_MCU_Z_MAX 4095
#define GMOUSE_MCU_Z_TOUCHON 3090
#define GMOUSE_MCU_Z_TOUCHOFF 400
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_MCU_BOARD_DATA_SIZE 0
#define ADC_NUM_CHANNELS 2
#define ADC_BUF_DEPTH 1
static const ADCConversionGroup adcgrpcfg = {
FALSE,
ADC_NUM_CHANNELS,
0,
0,
/* HW dependent part.*/
0,
ADC_CR2_SWSTART,
0,
0,
ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
0,
ADC_SQR3_SQ2_N(ADC_CHANNEL_IN8) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN9)
};
static bool_t init_board(GMouse *m, unsigned driverinstance) {
(void) m;
// Only one touch interface on this board
if (driverinstance)
return FALSE;
adcStart(&ADCD1, 0);
// Set up for reading Z
palClearPad(GPIOB, GPIOB_DRIVEA);
palClearPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(1); // Settling time
return TRUE;
}
static bool_t read_xyz(GMouse *m, GMouseReading *prd) {
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
(void) m;
// No buttons
prd->buttons = 0;
// Get the z reading (assumes we are ready to read z)
adcConvert(&ADCD1, &adcgrpcfg, samples, ADC_BUF_DEPTH);
prd->z = samples[0];
// Take a shortcut and don't read x, y if we know we are definitely not touched.
if (prd->z >= GMOUSE_MCU_Z_TOUCHOFF) {
// Get the x reading
palSetPad(GPIOB, GPIOB_DRIVEA);
palClearPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(2);
adcConvert(&ADCD1, &adcgrpcfg, samples, ADC_BUF_DEPTH);
prd->x = samples[1];
// Get the y reading
palClearPad(GPIOB, GPIOB_DRIVEA);
palSetPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(2);
adcConvert(&ADCD1, &adcgrpcfg, samples, ADC_BUF_DEPTH);
prd->y = samples[0];
// Set up for reading z again. We know it will be 20ms before we get called again so don't worry about settling time
palClearPad(GPIOB, GPIOB_DRIVEA);
palClearPad(GPIOB, GPIOB_DRIVEB);
}
return TRUE;
}
#endif /* _LLD_GMOUSE_MCU_BOARD_H */

View File

@ -1,126 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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,
0,
0,
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,
0,
0,
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)
};
static inline void init_board(void) {
adcStart(&ADCD1, 0);
}
static inline void aquire_bus(void) {
}
static inline void release_bus(void) {
}
static inline void setup_x(void) {
palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 2, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOC, 2);
palClearPad(GPIOC, 3);
gfxSleepMilliseconds(1);
}
static inline void setup_y(void) {
palSetPadMode(GPIOC, 2, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 0, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOC, 1, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOC, 1);
palClearPad(GPIOC, 0);
gfxSleepMilliseconds(1);
}
static inline void setup_z(void) {
palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_PULLDOWN);
palSetPadMode(GPIOC, 1, PAL_MODE_INPUT);
palSetPadMode(GPIOC, 2, PAL_MODE_INPUT);
palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOC, 3);
}
static inline uint16_t read_x(void) {
uint16_t val1, val2;
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
palSetPad(GPIOC, 2);
palClearPad(GPIOC, 3);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
val1 = ((samples[0] + samples[1])/2);
palClearPad(GPIOC, 2);
palSetPad(GPIOC, 3);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
val2 = ((samples[0] + samples[1])/2);
return ((val1+((1<<12)-val2))/4);
}
static inline uint16_t read_y(void) {
uint16_t val1, val2;
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
palSetPad(GPIOC, 1);
palClearPad(GPIOC, 0);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
val1 = ((samples[0] + samples[1])/2);
palClearPad(GPIOC, 1);
palSetPad(GPIOC, 0);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
val2 = ((samples[0] + samples[1])/2);
return ((val1+((1<<12)-val2))/4);
}
static inline uint16_t read_z(void) {
if (palReadPad(GPIOC, 0))
return 100;
else
return 0;
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,22 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 12
#define GINPUT_MOUSE_READ_CYCLES 1
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
#define GINPUT_MOUSE_CLICK_TIME 500
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,136 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _LLD_GMOUSE_MCU_BOARD_H
#define _LLD_GMOUSE_MCU_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_MCU_PEN_CALIBRATE_ERROR 8
#define GMOUSE_MCU_PEN_CLICK_ERROR 6
#define GMOUSE_MCU_PEN_MOVE_ERROR 4
#define GMOUSE_MCU_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_MCU_FINGER_CLICK_ERROR 18
#define GMOUSE_MCU_FINGER_MOVE_ERROR 14
#define GMOUSE_MCU_Z_MIN 0
#define GMOUSE_MCU_Z_MAX 1
#define GMOUSE_MCU_Z_TOUCHON 1
#define GMOUSE_MCU_Z_TOUCHOFF 0
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_MCU_BOARD_DATA_SIZE 0
#define ADC_NUM_CHANNELS 2
#define ADC_BUF_DEPTH 1
static const ADCConversionGroup adc_y_config = {
FALSE,
ADC_NUM_CHANNELS,
0,
0,
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,
0,
0,
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)
};
static inline void setup_z(void) {
palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_PULLDOWN);
palSetPadMode(GPIOC, 1, PAL_MODE_INPUT);
palSetPadMode(GPIOC, 2, PAL_MODE_INPUT);
palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOC, 3);
}
static bool_t init_board(GMouse *m, unsigned driverinstance) {
(void) m;
// Only one touch interface on this board
if (driverinstance)
return FALSE;
adcStart(&ADCD1, 0);
// Set up for reading Z
setup_z();
chThdSleepMilliseconds(1); // Settling time
return TRUE;
}
static bool_t read_xyz(GMouse *m, GMouseReading *prd) {
adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
uint16_t val1, val2;
(void) m;
// No buttons and assume touch off
prd->buttons = 0;
prd->z = 0;
// Get the z reading (assumes we are ready to read z)
// Take a shortcut and don't read x, y if we know we are definitely not touched.
if (palReadPad(GPIOC, 0)) {
prd->z = 1;
// Get the x reading - Weird but it works. Optimize later.
palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 2, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOC, 2);
palClearPad(GPIOC, 3);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
val1 = ((samples[0] + samples[1])/2);
palClearPad(GPIOC, 2);
palSetPad(GPIOC, 3);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
val2 = ((samples[0] + samples[1])/2);
prd->x = ((val1+((1<<12)-val2))/4);
// Get the y reading - Weird but it works. Optimize later.
palSetPadMode(GPIOC, 2, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG);
palSetPadMode(GPIOC, 0, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOC, 1, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOC, 1);
palClearPad(GPIOC, 0);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
val1 = ((samples[0] + samples[1])/2);
palClearPad(GPIOC, 1);
palSetPad(GPIOC, 0);
gfxSleepMilliseconds(1);
adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
val2 = ((samples[0] + samples[1])/2);
prd->y = ((val1+((1<<12)-val2))/4);
// Set up for reading z again. We know it will be 20ms before we get called again so don't worry about settling time
setup_z();
}
return TRUE;
}
#endif /* _LLD_GMOUSE_MCU_BOARD_H */

View File

@ -4,5 +4,4 @@ GFXSRC += $(GFXLIB)/boards/base/STM32F429i-Discovery/stm32f429i_discovery_sdram
GFXDEFS += -DGFX_USE_OS_CHIBIOS=TRUE
include $(GFXLIB)/drivers/gdisp/STM32F429iDiscovery/driver.mk
#include $(GFXLIB)/drivers/ginput/touch/MCU/driver.mk
#include $(GFXLIB)/drivers/gaudio/vs1053/driver.mk
include $(GFXLIB)/drivers/ginput/touch/STMPE811/driver.mk

View File

@ -76,7 +76,7 @@
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#define HAL_USE_I2C TRUE
#endif
/**

View File

@ -138,7 +138,7 @@
*/
#define STM32_I2C_USE_I2C1 FALSE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_USE_I2C3 FALSE
#define STM32_I2C_USE_I2C3 TRUE
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)

View File

@ -0,0 +1,120 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_STMPE811_PEN_CALIBRATE_ERROR 8
#define GMOUSE_STMPE811_PEN_CLICK_ERROR 6
#define GMOUSE_STMPE811_PEN_MOVE_ERROR 4
#define GMOUSE_STMPE811_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_STMPE811_FINGER_CLICK_ERROR 18
#define GMOUSE_STMPE811_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_STMPE811_BOARD_DATA_SIZE 0
// Options - Leave these commented to make it user configurable in the gfxconf.h
//#define GMOUSE_STMPE811_READ_PRESSURE FALSE
//#define GMOUSE_STMPE811_SELF_CALIBRATE FALSE
//#define GMOUSE_STMPE811_TEST_MODE FALSE
// Set to FALSE because it does not work properly on this board even though the pin exists.
#define GMOUSE_STMPE811_GPIO_IRQPIN FALSE
// If TRUE this is a really slow CPU and we should always clear the FIFO between reads.
#define GMOUSE_STMPE811_SLOW_CPU FALSE
// Slave address
#define STMPE811_ADDR 0x41
// Maximum timeout
#define STMPE811_TIMEOUT 0x3000
static const I2CConfig i2ccfg = {
OPMODE_I2C,
400000,
FAST_DUTY_CYCLE_2,
};
static bool_t init_board(GMouse* m, unsigned driverinstance) {
(void) m;
// This board only supports one touch panel
if (driverinstance)
return FALSE;
// Set pin modes
palSetPadMode(GPIOA, 15, PAL_MODE_INPUT | PAL_STM32_PUDR_FLOATING); /* TP IRQ */
palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); /* SCL */
palSetPadMode(GPIOC, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN); /* SDA */
// Start the I2C
i2cStart(&I2CD3, &i2ccfg);
return TRUE;
}
#if GMOUSE_STMPE811_GPIO_IRQPIN
static bool_t getpin_irq(GMouse* m) {
(void) m;
return !palReadPad(GPIOA, 15);
}
#endif
static inline void aquire_bus(GMouse* m) {
(void) m;
}
static inline void release_bus(GMouse* m) {
(void) m;
}
static void write_reg(GMouse* m, uint8_t reg, uint8_t val) {
uint8_t txbuf[2];
(void) m;
txbuf[0] = reg;
txbuf[1] = val;
i2cAcquireBus(&I2CD3);
i2cMasterTransmitTimeout(&I2CD3, STMPE811_ADDR, txbuf, 2, 0, 0, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD3);
}
static uint8_t read_byte(GMouse* m, uint8_t reg) {
uint8_t rxbuf[1];
(void) m;
rxbuf[0] = 0;
i2cAcquireBus(&I2CD3);
i2cMasterTransmitTimeout(&I2CD3, STMPE811_ADDR, &reg, 1, rxbuf, 1, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD3);
return rxbuf[0];
}
static uint16_t read_word(GMouse* m, uint8_t reg) {
uint8_t rxbuf[2];
(void) m;
rxbuf[0] = 0;
rxbuf[1] = 0;
i2cAcquireBus(&I2CD3);
i2cMasterTransmitTimeout(&I2CD3, STMPE811_ADDR, &reg, 1, rxbuf, 2, MS2ST(STMPE811_TIMEOUT));
i2cReleaseBus(&I2CD3);
return (((uint16_t)rxbuf[0]) << 8) | rxbuf[1];
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -39,7 +39,7 @@ static void createWidgets(void) {
gwinWidgetClearInit(&wi);
wi.g.show = TRUE;
// Apply the button parameters
// Apply the button parameters
wi.g.width = 100;
wi.g.height = 30;
wi.g.y = 10;
@ -67,9 +67,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Attach the mouse input
gwinAttachMouse(0);
// create the widget
createWidgets();

View File

@ -39,14 +39,14 @@ static void createWidgets(void) {
gwinWidgetClearInit(&wi);
wi.g.show = TRUE;
// Apply the checkbox parameters
// Apply the checkbox parameters
wi.g.width = 100; // includes text
wi.g.height = 20;
wi.g.y = 10;
wi.g.x = 10;
wi.text = "Checkbox";
// Create the actual checkbox
// Create the actual checkbox
ghCheckbox1 = gwinCheckboxCreate(0, &wi);
}
@ -61,9 +61,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Attach the mouse input
gwinAttachMouse(0);
// create the widget
createWidgets();

View File

@ -19,7 +19,7 @@ static void createWidgets(void) {
ghContainer = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
wi.g.show = TRUE;
// Apply the button parameters
// Apply the button parameters
wi.g.width = 120;
wi.g.height = 30;
wi.g.y = 10;
@ -37,9 +37,6 @@ int main(void) {
// Initialize the display
gfxInit();
// Attach the mouse input
gwinAttachMouse(0);
// Set the widget defaults
gwinSetDefaultFont(gdispOpenFont("*"));
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);

View File

@ -40,7 +40,7 @@ static void createWidgets(void) {
wi.text = "Container 3";
ghContainer3 = gwinContainerCreate(0, &wi, GWIN_CONTAINER_BORDER);
// Button 1
// Button 1
wi.g.width = 80;
wi.g.height = 20;
wi.g.y = 10;
@ -49,7 +49,7 @@ static void createWidgets(void) {
wi.g.parent = ghContainer2;
ghButton1 = gwinButtonCreate(0, &wi);
// Button 2
// Button 2
wi.g.width = 80;
wi.g.height = 20;
wi.g.y = 40;
@ -58,7 +58,7 @@ static void createWidgets(void) {
wi.g.parent = ghContainer2;
ghButton2 = gwinButtonCreate(0, &wi);
// Button 3
// Button 3
wi.g.width = 80;
wi.g.height = 20;
wi.g.y = 10;
@ -67,7 +67,7 @@ static void createWidgets(void) {
wi.g.parent = ghContainer3;
ghButton3 = gwinButtonCreate(0, &wi);
// Button 4
// Button 4
wi.g.width = 80;
wi.g.height = 20;
wi.g.y = 40;
@ -115,9 +115,6 @@ int main(void) {
// Initialize the display
gfxInit();
// Attach the mouse input
gwinAttachMouse(0);
// Set the widget defaults
gwinSetDefaultFont(gdispOpenFont("*"));
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);

View File

@ -33,7 +33,7 @@ static void _createWidgets(void) {
wi.text = "Surprise!";
gwinLabelCreate(0, &wi);
// Apply the frame parameters
// Apply the frame parameters
wi.g.width = 300;
wi.g.height = 200;
wi.g.y = 10;
@ -107,7 +107,7 @@ static void _createWidgets(void) {
wi.g.x = 10;
wi.g.y = 90;
ghWindow1 = gwinWindowCreate(0, &wi.g);
_updateColor();
}
@ -117,9 +117,6 @@ int main(void) {
// Initialize the display
gfxInit();
// Attach the mouse input
gwinAttachMouse(0);
// Set the widget defaults
gwinSetDefaultFont(gdispOpenFont("*"));
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);

View File

@ -63,9 +63,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Attach the mouse input
gwinAttachMouse(0);
// create the widget
createWidgets();

View File

@ -79,9 +79,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Attach the mouse input
gwinAttachMouse(0);
// create the widget
createWidgets();

View File

@ -83,9 +83,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Attach the mouse input
gwinAttachMouse(0);
// create the widget
createWidgets();

View File

@ -59,9 +59,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
// Attach the mouse input
gwinAttachMouse(0);
// create the widget
createWidgets();

View File

@ -418,11 +418,6 @@ int main(void) {
// Initialize the display
gfxInit();
// Connect the mouse
#if GINPUT_NEED_MOUSE
gwinAttachMouse(0);
#endif
// Set the widget defaults
font = gdispOpenFont("*"); // Get the first defined font.
gwinSetDefaultFont(font);

View File

@ -32,6 +32,10 @@ FEATURE: Added transparent custom draws for GWIN containers and frame widgets
FEATURE: Added image custom draws for GWIN containers and frame widgets
FEATURE: Added GDRIVER infrastructure. Ported GDISP to use it.
FEATURE: Added gdispDrawArcSectors() and gdispFillArcSectors().
FEATURE: Ported GINPUT MOUSE to GDRIVER infrastructure.
FEATURE: Mouse/Touch now support both pen and finger mode.
DEPRECATE: gwinAttachMouse() is now handled automaticly.
FEATURE: Added MAX11802 touch driver by user steved
*** Release 2.1 ***

View File

@ -1,5 +1,2 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/ginput/touch/ADS7843
GFXSRC += $(GFXLIB)/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843.c

View File

@ -1,94 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/
#include "src/ginput/driver_mouse.h"
#include "ginput_lld_mouse_board.h"
#if defined(GINPUT_MOUSE_YX_INVERTED) && GINPUT_MOUSE_YX_INVERTED
#define CMD_X 0x91
#define CMD_Y 0xD1
#else
#define CMD_X 0xD1
#define CMD_Y 0x91
#endif
static uint16_t sampleBuf[7];
static coord_t lastx, lasty;
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;
}
}
}
}
void ginput_lld_mouse_init(void) {
init_board();
}
void ginput_lld_mouse_get_reading(MouseReading *pt) {
uint16_t i;
// 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(CMD_X);
for(i = 0; i < 7; i++)
sampleBuf[i] = read_value(CMD_X);
read_value(CMD_X-1);
filter();
lastx = (coord_t)sampleBuf[3];
/* Get the Y value using the same process as above */
read_value(CMD_Y);
for(i = 0; i < 7; i++)
sampleBuf[i] = read_value(CMD_Y);
read_value(CMD_Y-1);
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

@ -1,31 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
static inline void init_board(void) {
}
static inline bool_t getpin_pressed(void) {
}
static inline void aquire_bus(void) {
}
static inline void release_bus(void) {
}
static inline uint16_t read_value(uint16_t port) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,21 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 5
#define GINPUT_MOUSE_READ_CYCLES 4
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 10
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
#define GINPUT_MOUSE_CLICK_TIME 500
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,80 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE)
#define GMOUSE_DRIVER_VMT GMOUSEVMT_ADS7843
#include "src/ginput/driver_mouse.h"
// Get the hardware interface
#include "gmouse_lld_ADS7843_board.h"
#define CMD_X 0xD1
#define CMD_Y 0x91
#define CMD_ENABLE_IRQ 0x80
static bool_t MouseXYZ(GMouse* m, GMouseReading* pdr)
{
(void)m;
// No buttons
pdr->buttons = 0;
pdr->z = 0;
if (getpin_pressed(m)) {
pdr->z = 1; // Set to Z_MAX as we are pressed
aquire_bus(m);
read_value(m, CMD_X); // Dummy read - disable PenIRQ
pdr->x = read_value(m, CMD_X); // Read X-Value
read_value(m, CMD_Y); // Dummy read - disable PenIRQ
pdr->y = read_value(m, CMD_Y); // Read Y-Value
read_value(m, CMD_ENABLE_IRQ); // Enable IRQ
release_bus(m);
}
return TRUE;
}
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_TOUCH,
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_CALIBRATE | GMOUSE_VFLG_CAL_TEST |
GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN,
sizeof(GMouse)+BOARD_DATA_SIZE,
_gmouseInitDriver,
_gmousePostInitDriver,
_gmouseDeInitDriver
},
1, // z_max - (currently?) not supported
0, // z_min - (currently?) not supported
1, // z_touchon
0, // z_touchoff
{ // pen_jitter
GMOUSE_ADS7843_PEN_CALIBRATE_ERROR, // calibrate
GMOUSE_ADS7843_PEN_CLICK_ERROR, // click
GMOUSE_ADS7843_PEN_MOVE_ERROR // move
},
{ // finger_jitter
GMOUSE_ADS7843_FINGER_CALIBRATE_ERROR, // calibrate
GMOUSE_ADS7843_FINGER_CLICK_ERROR, // click
GMOUSE_ADS7843_FINGER_MOVE_ERROR // move
},
init_board, // init
0, // deinit
MouseXYZ, // get
0, // calsave
0 // calload
}};
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -0,0 +1,42 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_ADS7843_PEN_CALIBRATE_ERROR 8
#define GMOUSE_ADS7843_PEN_CLICK_ERROR 6
#define GMOUSE_ADS7843_PEN_MOVE_ERROR 4
#define GMOUSE_ADS7843_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_ADS7843_FINGER_CLICK_ERROR 18
#define GMOUSE_ADS7843_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_ADS7843_BOARD_DATA_SIZE 0
static bool_t init_board(GMouse* m, unsigned driverinstance) {
}
static inline bool_t getpin_pressed(GMouse* m) {
}
static inline void aquire_bus(GMouse* m) {
}
static inline void release_bus(GMouse* m) {
}
static inline uint16_t read_value(GMouse* m, uint16_t port) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,5 +1,2 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/ginput/touch/FT5x06/ginput_lld_mouse.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/ginput/touch/FT5x06
GFXSRC += $(GFXLIB)/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06.c

View File

@ -1,88 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/
#include "src/ginput/driver_mouse.h"
#include "drivers/ginput/touch/FT5x06/ft5x06.h"
// include board abstraction
#include "ginput_lld_mouse_board.h"
static coord_t x, y, z;
static uint8_t touched;
void ginput_lld_mouse_init(void) {
init_board();
// Init default values. (From NHD-3.5-320240MF-ATXL-CTP-1 datasheet)
// Valid touching detect threshold
write_reg(FT5x06_ID_G_THGROUP, 1, 0x16);
// valid touching peak detect threshold
write_reg(FT5x06_ID_G_THPEAK, 1, 0x3C);
// Touch focus threshold
write_reg(FT5x06_ID_G_THCAL, 1, 0xE9);
// threshold when there is surface water
write_reg(FT5x06_ID_G_THWATER, 1, 0x01);
// threshold of temperature compensation
write_reg(FT5x06_ID_G_THTEMP, 1, 0x01);
// Touch difference threshold
write_reg(FT5x06_ID_G_THDIFF, 1, 0xA0);
// Delay to enter 'Monitor' status (s)
write_reg(FT5x06_ID_G_TIME_ENTER_MONITOR, 1, 0x0A);
// Period of 'Active' status (ms)
write_reg(FT5x06_ID_G_PERIODACTIVE, 1, 0x06);
// Timer to enter ÔidleÕ when in 'Monitor' (ms)
write_reg(FT5x06_ID_G_PERIODMONITOR, 1, 0x28);
}
void ginput_lld_mouse_get_reading(MouseReading *pt) {
// Poll to get the touched status
uint8_t last_touched;
last_touched = touched;
touched = (uint8_t)read_reg(FT5x06_TOUCH_POINTS, 1) & 0x07;
// If not touched, return the previous results
if (touched == 0) {
pt->x = x;
pt->y = y;
pt->z = 0;
pt->buttons = 0;
return;
}
/* Get the X, Y, Z values */
x = (coord_t)(read_reg(FT5x06_TOUCH1_XH, 2) & 0x0fff);
y = (coord_t)read_reg(FT5x06_TOUCH1_YH, 2);
z = 100;
// Rescale X,Y,Z - X & Y don't need scaling when you are using calibration!
#if !GINPUT_MOUSE_NEED_CALIBRATION
x = gdispGetWidth() - x / (4096/gdispGetWidth());
y = y / (4096/gdispGetHeight());
#endif
// Return the results. ADC gives values from 0 to 2^12 (4096)
pt->x = x;
pt->y = y;
pt->z = z;
pt->buttons = GINPUT_TOUCH_PRESSED;
}
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -1,27 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
static void init_board(void) {
}
static inline bool_t getpin_irq(void) {
}
static void write_reg(uint8_t reg, uint8_t n, uint16_t val) {
}
static uint16_t read_reg(uint8_t reg, uint8_t n) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,21 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 15
#define GINPUT_MOUSE_READ_CYCLES 1
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 10
#define GINPUT_MOUSE_MAX_MOVE_JITTER 5
#define GINPUT_MOUSE_CLICK_TIME 450
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,121 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
#define GMOUSE_DRIVER_VMT GMOUSEVMT_FT5x06
#include "src/ginput/driver_mouse.h"
// Get the hardware interface
#include "gmouse_lld_FT5x06_board.h"
// Hardware definitions
#include "drivers/ginput/touch/FT5x06/ft5x06.h"
static bool_t MouseInit(GMouse* m, unsigned driverinstance) {
if (!init_board(m, driverinstance))
return FALSE;
aquire_bus(m);
// Init default values. (From NHD-3.5-320240MF-ATXL-CTP-1 datasheet)
// Valid touching detect threshold
write_reg(m, FT5x06_ID_G_THGROUP, 0x16);
// valid touching peak detect threshold
write_reg(m, FT5x06_ID_G_THPEAK, 0x3C);
// Touch focus threshold
write_reg(m, FT5x06_ID_G_THCAL, 0xE9);
// threshold when there is surface water
write_reg(m, FT5x06_ID_G_THWATER, 0x01);
// threshold of temperature compensation
write_reg(m, FT5x06_ID_G_THTEMP, 0x01);
// Touch difference threshold
write_reg(m, FT5x06_ID_G_THDIFF, 0xA0);
// Delay to enter 'Monitor' status (s)
write_reg(m, FT5x06_ID_G_TIME_ENTER_MONITOR, 0x0A);
// Period of 'Active' status (ms)
write_reg(m, FT5x06_ID_G_PERIODACTIVE, 0x06);
// Timer to enter 'idle' when in 'Monitor' (ms)
write_reg(m, FT5x06_ID_G_PERIODMONITOR, 0x28);
release_bus(m);
return TRUE;
}
static bool_t MouseXYZ(GMouse* m, GMouseReading* pdr)
{
// Assume not touched.
pdr->buttons = 0;
pdr->z = 0;
aquire_bus(m);
// Only take a reading if we are touched.
if ((read_byte(m, FT5x06_TOUCH_POINTS) & 0x07)) {
/* Get the X, Y, Z values */
pdr->x = (coord_t)(read_word(m, FT5x06_TOUCH1_XH) & 0x0fff);
pdr->y = (coord_t)read_word(m, FT5x06_TOUCH1_YH);
pdr->z = 1;
#if GMOUSE_FT5x06_SELF_CALIBRATE
// Rescale X,Y,Z - If we are using self-calibration
pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
#endif
}
release_bus(m);
return TRUE;
}
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_TOUCH,
#if GMOUSE_FT5x06_SELF_CALIBRATE
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN,
#else
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN | GMOUSE_VFLG_CALIBRATE | GMOUSE_VFLG_CAL_TEST,
#endif
sizeof(GMouse) + GMOUSE_FT5x06_BOARD_DATA_SIZE,
_gmouseInitDriver,
_gmousePostInitDriver,
_gmouseDeInitDriver
},
1, // z_max - (currently?) not supported
0, // z_min - (currently?) not supported
1, // z_touchon
0, // z_touchoff
{ // pen_jitter
GMOUSE_FT5x06_PEN_CALIBRATE_ERROR, // calibrate
GMOUSE_FT5x06_PEN_CLICK_ERROR, // click
GMOUSE_FT5x06_PEN_MOVE_ERROR // move
},
{ // finger_jitter
GMOUSE_FT5x06_FINGER_CALIBRATE_ERROR, // calibrate
GMOUSE_FT5x06_FINGER_CLICK_ERROR, // click
GMOUSE_FT5x06_FINGER_MOVE_ERROR // move
},
MouseInit, // init
0, // deinit
read_xyz, // get
0, // calsave
0 // calload
}};
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -0,0 +1,46 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_FT5x06_PEN_CALIBRATE_ERROR 8
#define GMOUSE_FT5x06_PEN_CLICK_ERROR 6
#define GMOUSE_FT5x06_PEN_MOVE_ERROR 4
#define GMOUSE_FT5x06_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_FT5x06_FINGER_CLICK_ERROR 18
#define GMOUSE_FT5x06_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_FT5x06_BOARD_DATA_SIZE 0
// Set this to TRUE if you want self-calibration.
// NOTE: This is not as accurate as real calibration.
// It requires the orientation of the touch panel to match the display.
// It requires the active area of the touch panel to exactly match the display size.
#define GMOUSE_FT5x06_SELF_CALIBRATE FALSE
static bool_t init_board(GMouse* m, unsigned driverinstance) {
}
static inline void aquire_bus(GMouse* m) {
}
static inline void release_bus(GMouse* m) {
}
static void write_reg(GMouse* m, uint8_t reg, uint8_t val) {
}
static uint8_t read_byte(GMouse* m, uint8_t reg) {
}
static uint16_t read_word(GMouse* m, uint8_t reg) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -0,0 +1,2 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c

View File

@ -0,0 +1,189 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
#define GMOUSE_DRIVER_VMT GMOUSEVMT_MAX11802
#include "src/ginput/driver_mouse.h"
// Hardware definitions
#include "drivers/ginput/touch/MAX11802/max11802.h"
// Get the hardware interface
#include "gmouse_lld_MAX11802_board.h"
// Register values to set
#define MAX11802_MODE 0x0E // Direct conversion with averaging
#define MAX11802_AVG 0x55
#define MAX11802_TIMING 0x77
#define MAX11802_DELAY 0x55
#define Z_MIN 0
#define Z_MAX 1
static bool_t MouseInit(GMouse* m, unsigned driverinstance)
{
uint8_t *p;
static const uint8_t commandList[] = {
MAX11802_CMD_GEN_WR, 0xf0, // General config - leave TIRQ enabled, even though we ignore it ATM
MAX11802_CMD_RES_WR, 0x00, // A-D resolution, hardware config - rewriting default; all 12-bit resolution
MAX11802_CMD_AVG_WR, MAX11802_AVG, // A-D averaging - 8 samples, average four median samples
MAX11802_CMD_SAMPLE_WR, 0x00, // A-D sample time - use default
MAX11802_CMD_TIMING_WR, MAX11802_TIMING, // Setup timing
MAX11802_CMD_DELAY_WR, MAX11802_DELAY, // Conversion delays
MAX11802_CMD_TDPULL_WR, 0x00, // A-D resolution, hardware config - rewrite default
// MAX11802_CMD_MDTIM_WR, 0x00, // Autonomous mode timing - write default - only for MAX11800, MAX11801
// MAX11802_CMD_APCONF_WR, 0x00, // Aperture config register - rewrite default - only for MAX11800, MAX11801
// Ignore aux config register - not used
MAX11802_CMD_MODE_WR, MAX11802_MODE // Set mode last
};
if (!init_board(m, driverinstance))
return FALSE;
aquire_bus(m);
for (p = commandList; p < commandList+sizeof(commandList); p += 2)
write_command(m, p[0], p[1]);
// Read something as a test
if (write_command(m, MAX11802_CMD_MODE_RD, 0) != MAX11802_MODE) {
release_bus(m);
return FALSE;
}
release_bus(m);
return TRUE;
}
static bool_t read_xyz(GMouse* m, GMouseReading* pdr)
{
uint8_t readyCount;
uint8_t notReadyCount;
// Assume not touched.
pdr->buttons = 0;
pdr->z = 0;
aquire_bus(m);
// Start the conversion
gfintWriteCommand(m, MAX11802_CMD_MEASUREXY); // just write command
/**
* put a delay in here, since conversion will take a finite time - longer if reading Z as well
* Potentially 1msec for 3 axes with 8us conversion time per sample, 8 samples per average
* Note Maxim AN5435-software to do calculation (www.maximintegrated.com/design/tools/appnotes/5435/AN5435-software.zip)
*
* We'll just use a fixed delay to avoid too much polling/bus activity
*/
gfxSleepMilliseconds(2); // Was 1 - try 2
/* Wait for data ready
* Note: MAX11802 signals the readiness of the results using the lowest 4 bits of the result. However, these are the
* last bits to be read out of the device. It is possible for the hardware value to change in the middle of the read,
* causing the analog value to still be invalid even though the tags indicate a valid result.
*
* We work around this by reading the registers once more after the tags indicate they are ready.
* There's also a separate counter to guard against never getting valid readings.
*
* Read the two or three readings required in a single burst, swapping x and y order if necessary
*
* Reading Z is possible but complicated requiring two z readings, multiplication and division, various constant ratio's,
* and interpolation in relation to the X and Y readings. It is not a simple pressure reading.
* In other words, don't bother trying.
*/
readyCount = notReadyCount = 0;
do {
// Get a set of readings
gfintWriteCommand(m, MAX11802_CMD_XPOSITION);
#if defined(GINPUT_MOUSE_YX_INVERTED) && GINPUT_MOUSE_YX_INVERTED
pdr->y = read_value(m);
pdr->x = read_value(m);
#else
pdr->x = read_value(m);
pdr->y = read_value(m);
#endif
// Test the result validity
if (((pdr->x | pdr->y) & 0x03) == 0x03) {
// Has it been too long? If so give up
if (++notReadyCount >= 5) {
release_bus(m);
return FALSE;
}
// Give up the time slice to someone else and then try again
gfxYield();
continue;
}
// We have a result but we need two valid results to believe it
readyCount++;
} while (readyCount < 2);
release_bus(m);
/**
* format of each value returned by MAX11802:
* Bits 15..4 - analog value
* Bits 3..2 - tag value - measurement type (X, Y, Z1, Z2)
* Bits 1..0 - tag value - event type (00 = valid touch, 10 - no touch, 11 - measurement in progress)
*/
// Was there a valid touch?
if ((pt->x & 0x03) == 0x02) {
pdr->z = Z_MIN;
return TRUE;
}
// Strip the tags
pt->x >>= 4;
pt->y >>= 4;
pdr->z = Z_MAX;
return TRUE;
}
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_TOUCH,
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN | GMOUSE_VFLG_CALIBRATE | GMOUSE_VFLG_CAL_TEST,
sizeof(GMouse) + GMOUSE_MAX11802_BOARD_DATA_SIZE,
_gmouseInitDriver,
_gmousePostInitDriver,
_gmouseDeInitDriver
},
Z_MAX, // z_max
Z_MIN, // z_min
Z_MIN, // z_touchoff
Z_MAX, // z_touchon
{ // pen_jitter
GMOUSE_MAX11802_PEN_CALIBRATE_ERROR, // calibrate
GMOUSE_MAX11802_PEN_CLICK_ERROR, // click
GMOUSE_MAX11802_PEN_MOVE_ERROR // move
},
{ // finger_jitter
GMOUSE_MAX11802_FINGER_CALIBRATE_ERROR, // calibrate
GMOUSE_MAX11802_FINGER_CLICK_ERROR, // click
GMOUSE_MAX11802_FINGER_MOVE_ERROR // move
},
MouseInit, // init
0, // deinit
read_xyz, // get
0, // calsave
0 // calload
}};
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -0,0 +1,69 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_MAX11802_PEN_CALIBRATE_ERROR 8
#define GMOUSE_MAX11802_PEN_CLICK_ERROR 6
#define GMOUSE_MAX11802_PEN_MOVE_ERROR 4
#define GMOUSE_MAX11802_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_MAX11802_FINGER_CLICK_ERROR 18
#define GMOUSE_MAX11802_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_MAX11802_BOARD_DATA_SIZE 0
/**
* Init the board
*
* Returns TRUE on success, FALSE on failure
*/
static inline bool_t init_board(GMouse* m, unsigned driverinstance) {
}
/**
* Acquire the bus
*/
static inline void aquire_bus(GMouse* m) {
}
/**
* Release the bus
*/
static inline void release_bus(GMouse* m) {
}
/**
* Send command (with parameter) to the MAX11802
*
* Return the second byte read in case of interest
*/
static inline uint8_t write_command(GMouse* m, uint8_t command, uint8_t value) {
}
/**
* Send command (no parameter) to the MAX11802
*
* Return the byte read in case of interest
*/
static inline uint8_t gfintWriteCommand(GMouse* m, uint8_t command) {
}
/*
* Read 2 bytes as 16-bit value (command to read must have been sent previously)
* Note: Analog value is in bits 15..4, tags (reading status) in bits 3..0
*/
static inline uint16_t read_value(GMouse* m) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -0,0 +1,31 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _MAX11802_H
#define _MAX11802_H
#define MAX11802_CMD_XPOSITION ((0x52 << 1) | 1)
#define MAX11802_CMD_YPOSITION ((0x54 << 1) | 1)
#define MAX11802_CMD_ZPOSITION ((0x56 << 1) | 1)
// LSB of register addresses specifies read (1) or write (0)
#define MAX11802_CMD_MEASUREXY (0x70 << 1)
#define MAX11802_CMD_MEASUREXYZ (0x72 << 1)
#define MAX11802_CMD_GEN_WR (0x01 << 1) // General config register
#define MAX11802_CMD_RES_WR (0x02 << 1)
#define MAX11802_CMD_AVG_WR (0x03 << 1)
#define MAX11802_CMD_SAMPLE_WR (0x04 << 1)
#define MAX11802_CMD_TIMING_WR (0x05 << 1)
#define MAX11802_CMD_DELAY_WR (0x06 << 1)
#define MAX11802_CMD_TDPULL_WR (0x07 << 1)
#define MAX11802_CMD_MDTIM_WR (0x08 << 1)
#define MAX11802_CMD_APCONF_WR (0x09 << 1)
#define MAX11802_CMD_MODE_WR (0x0B << 1)
#define MAX11802_CMD_MODE_RD ((0x0B << 1) | 1)
#define MAX11802_CMD_GSR_RD ((0x00 << 1) | 1) // General status register - read-only
#endif /* _MAX11802_H */

View File

@ -1,5 +1,2 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/ginput/touch/MCU/ginput_lld_mouse.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/ginput/touch/MCU
GFXSRC += $(GFXLIB)/drivers/ginput/touch/MCU/gmouse_lld_MCU.c

View File

@ -1,80 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/
#include "src/ginput/driver_mouse.h"
#include "ginput_lld_mouse_board.h"
static uint16_t sampleBuf[7];
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;
}
}
}
}
void ginput_lld_mouse_init(void) {
init_board();
}
void ginput_lld_mouse_get_reading(MouseReading *pt) {
uint16_t i;
// Obtain access to the bus
aquire_bus();
// Read the ADC for z, x, y and then z again
while(1) {
setup_z();
for(i = 0; i < 7; i++)
sampleBuf[i] = read_z();
filter();
pt->z = (coord_t)sampleBuf[3];
setup_x();
for(i = 0; i < 7; i++)
sampleBuf[i] = read_x();
filter();
pt->x = (coord_t)sampleBuf[3];
setup_y();
for(i = 0; i < 7; i++)
sampleBuf[i] = read_y();
filter();
pt->y = (coord_t)sampleBuf[3];
pt->buttons = pt->z >= 80 ? GINPUT_TOUCH_PRESSED : 0;
setup_z();
for(i = 0; i < 7; i++)
sampleBuf[i] = read_z();
filter();
i = (coord_t)sampleBuf[3] >= 80 ? GINPUT_TOUCH_PRESSED : 0;
if (pt->buttons == i)
break;
}
// Release the bus
release_bus();
}
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -1,41 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
static inline void init_board(void) {
}
static inline void aquire_bus(void) {
}
static inline void release_bus(void) {
}
static inline void setup_x(void) {
}
static inline void setup_y(void) {
}
static inline void setup_z(void) {
palClearPad(GPIOB, GPIOB_DRIVEA);
palClearPad(GPIOB, GPIOB_DRIVEB);
chThdSleepMilliseconds(2);
}
static inline uint16_t read_x(void) {
}
static inline uint16_t read_y(void) {
}
static inline uint16_t read_z(void) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,21 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 12
#define GINPUT_MOUSE_READ_CYCLES 1
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 2
#define GINPUT_MOUSE_MAX_MOVE_JITTER 2
#define GINPUT_MOUSE_CLICK_TIME 500
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,50 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
#define GMOUSE_DRIVER_VMT GMOUSEVMT_MCU
#include "src/ginput/driver_mouse.h"
// Get the hardware interface
#include "gmouse_lld_MCU_board.h"
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_TOUCH,
GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_TEST
|GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN,
// Extra flags for testing only
//GMOUSE_VFLG_DEFAULTFINGER|GMOUSE_VFLG_CAL_EXTREMES - Possible
//GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_CAL_LOADFREE - unlikely
sizeof(GMouse) + GMOUSE_MCU_BOARD_DATA_SIZE,
_gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
},
GMOUSE_MCU_Z_MAX, // z_max
GMOUSE_MCU_Z_MIN, // z_min
GMOUSE_MCU_Z_TOUCHON, // z_touchon
GMOUSE_MCU_Z_TOUCHOFF, // z_touchoff
{ // pen_jitter
GMOUSE_MCU_PEN_CALIBRATE_ERROR, // calibrate
GMOUSE_MCU_PEN_CLICK_ERROR, // click
GMOUSE_MCU_PEN_MOVE_ERROR // move
},
{ // finger_jitter
GMOUSE_MCU_FINGER_CALIBRATE_ERROR, // calibrate
GMOUSE_MCU_FINGER_CLICK_ERROR, // click
GMOUSE_MCU_FINGER_MOVE_ERROR // move
},
init_board, // init
0, // deinit
read_xyz, // get
0, // calsave
0 // calload
}};
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -0,0 +1,32 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _LLD_GMOUSE_MCU_BOARD_H
#define _LLD_GMOUSE_MCU_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_MCU_PEN_CALIBRATE_ERROR 8
#define GMOUSE_MCU_PEN_CLICK_ERROR 6
#define GMOUSE_MCU_PEN_MOVE_ERROR 4
#define GMOUSE_MCU_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_MCU_FINGER_CLICK_ERROR 18
#define GMOUSE_MCU_FINGER_MOVE_ERROR 14
#define GMOUSE_MCU_Z_MIN 0 // The minimum Z reading
#define GMOUSE_MCU_Z_MAX 100 // The maximum Z reading
#define GMOUSE_MCU_Z_TOUCHON 80 // Values between this and Z_MAX are definitely pressed
#define GMOUSE_MCU_Z_TOUCHOFF 70 // Values between this and Z_MIN are definitely not pressed
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_MCU_BOARD_DATA_SIZE 0
static bool_t init_board(GMouse *m, unsigned driverinstance) {
}
static bool_t read_xyz(GMouse *m, GMouseReading *prd) {
}
#endif /* _LLD_GMOUSE_MCU_BOARD_H */

View File

@ -1,5 +1,2 @@
# List the required driver.
GFXSRC += $(GFXLIB)/drivers/ginput/touch/STMPE811/ginput_lld_mouse.c
# Required include directories
GFXINC += $(GFXLIB)/drivers/ginput/touch/STMPE811
GFXSRC += $(GFXLIB)/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811.c

View File

@ -1,132 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) /*|| defined(__DOXYGEN__)*/
#include "src/ginput/driver_mouse.h"
#include "drivers/ginput/touch/STMPE811/stmpe811.h"
#include "ginput_lld_mouse_board.h"
#ifndef STMP811_NO_GPIO_IRQPIN
#define STMP811_NO_GPIO_IRQPIN FALSE
#endif
#ifndef STMP811_SLOW_CPU
#define STMP811_SLOW_CPU FALSE
#endif
static coord_t x, y, z;
static uint8_t touched;
/* set the active window of the stmpe811. bl is bottom left, tr is top right */
static void setActiveWindow(uint16_t bl_x, uint16_t bl_y, uint16_t tr_x, uint16_t tr_y)
{
write_reg(STMPE811_REG_WDW_TR_X, 2, tr_x);
write_reg(STMPE811_REG_WDW_TR_Y, 2, tr_y);
write_reg(STMPE811_REG_WDW_BL_X, 2, bl_x);
write_reg(STMPE811_REG_WDW_BL_Y, 2, bl_y);
}
void ginput_lld_mouse_init(void)
{
init_board();
write_reg(STMPE811_REG_SYS_CTRL1, 1, 0x02); // Software chip reset
gfxSleepMilliseconds(10);
write_reg(STMPE811_REG_SYS_CTRL2, 1, 0x0C); // Temperature sensor clock off, GPIO clock off, touch clock on, ADC clock on
#if STMP811_NO_GPIO_IRQPIN
write_reg(STMPE811_REG_INT_EN, 1, 0x00); // Interrupt on INT pin when touch is detected
#else
write_reg(STMPE811_REG_INT_EN, 1, 0x01); // Interrupt on INT pin when touch is detected
#endif
write_reg(STMPE811_REG_ADC_CTRL1, 1, 0x48); // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage refernce
gfxSleepMilliseconds(2);
write_reg(STMPE811_REG_ADC_CTRL2, 1, 0x01); // ADC speed 3.25MHz
write_reg(STMPE811_REG_GPIO_AF, 1, 0x00); // GPIO alternate function - OFF
write_reg(STMPE811_REG_TSC_CFG, 1, 0x9A); // Averaging 4, touch detect delay 500 us, panel driver settling time 500 us
write_reg(STMPE811_REG_FIFO_TH, 1, 0x40); // FIFO threshold = 64
write_reg(STMPE811_REG_FIFO_STA, 1, 0x01); // FIFO reset enable
write_reg(STMPE811_REG_FIFO_STA, 1, 0x00); // FIFO reset disable
write_reg(STMPE811_REG_TSC_FRACT_XYZ, 1, 0x07); // Z axis data format
write_reg(STMPE811_REG_TSC_I_DRIVE, 1, 0x01); // 50mA touchscreen line current
write_reg(STMPE811_REG_TSC_CTRL, 1, 0x00); // X&Y&Z
write_reg(STMPE811_REG_TSC_CTRL, 1, 0x01); // X&Y&Z, TSC enable
write_reg(STMPE811_REG_INT_STA, 1, 0xFF); // Clear all interrupts
#if !STMP811_NO_GPIO_IRQPIN
touched = (uint8_t)read_reg(STMPE811_REG_TSC_CTRL, 1) & 0x80;
#endif
write_reg(STMPE811_REG_INT_CTRL, 1, 0x01); // Level interrupt, enable intrrupts
}
void ginput_lld_mouse_get_reading(MouseReading *pt)
{
bool_t clearfifo; // Do we need to clear the FIFO
#if STMP811_NO_GPIO_IRQPIN
// Poll to get the touched status
uint8_t last_touched;
last_touched = touched;
touched = (uint8_t)read_reg(STMPE811_REG_TSC_CTRL, 1) & 0x80;
clearfifo = (touched != last_touched);
#else
// Check if the touch controller IRQ pin has gone off
clearfifo = false;
if(getpin_irq()) { // please rename this to getpin_irq
write_reg(STMPE811_REG_INT_STA, 1, 0xFF); // clear all interrupts
touched = (uint8_t)read_reg(STMPE811_REG_TSC_CTRL, 1) & 0x80; // set the new touched status
clearfifo = true; // only take the last FIFO reading
}
#endif
// If not touched, return the previous results
if (!touched) {
pt->x = x;
pt->y = y;
pt->z = 0;
pt->buttons = 0;
return;
}
#if !STMP811_SLOW_CPU
if (!clearfifo && (read_reg(STMPE811_REG_FIFO_STA, 1) & 0xD0))
#endif
clearfifo = true;
do {
/* Get the X, Y, Z values */
/* This could be done in a single 4 byte read to STMPE811_REG_TSC_DATA_XYZ (incr or non-incr) */
x = (coord_t)read_reg(STMPE811_REG_TSC_DATA_X, 2);
y = (coord_t)read_reg(STMPE811_REG_TSC_DATA_Y, 2);
z = (coord_t)read_reg(STMPE811_REG_TSC_DATA_Z, 1);
} while(clearfifo && !(read_reg(STMPE811_REG_FIFO_STA, 1) & 0x20));
// Rescale X,Y,Z - X & Y don't need scaling when you are using calibration!
#if !GINPUT_MOUSE_NEED_CALIBRATION
x = gdispGetWidth() - x / (4096/gdispGetWidth());
y = y / (4096/gdispGetHeight());
#endif
z = (((z&0xFF) * 100)>>8) + 1;
// Return the results. ADC gives values from 0 to 2^12 (4096)
pt->x = x;
pt->y = y;
pt->z = z;
pt->buttons = GINPUT_TOUCH_PRESSED;
/* Force another read if we have more results */
if (!clearfifo && !(read_reg(STMPE811_REG_FIFO_STA, 1) & 0x20))
ginputMouseWakeup();
}
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -1,27 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
static void init_board(void) {
}
static inline bool_t getpin_irq(void) {
}
static void write_reg(uint8_t reg, uint8_t n, uint16_t val) {
}
static uint16_t read_reg(uint8_t reg, uint8_t n) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -1,25 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 5
#define GINPUT_MOUSE_READ_CYCLES 1
#define GINPUT_MOUSE_POLL_PERIOD 25
#define GINPUT_MOUSE_MAX_CLICK_JITTER 10
#define GINPUT_MOUSE_MAX_MOVE_JITTER 5
#define GINPUT_MOUSE_CLICK_TIME 450
/* default values - over write these in your boad files */
#define STMP811_SLOWER_RESPONSE FALSE
#define STMP811_NO_GPIO_IRQPIN FALSE
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -0,0 +1,253 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
#define GMOUSE_DRIVER_VMT GMOUSEVMT_STMPE811
#include "src/ginput/driver_mouse.h"
// Hardware definitions
#include "drivers/ginput/touch/STMPE811/stmpe811.h"
// Get the hardware interface
#include "gmouse_lld_STMPE811_board.h"
// Extra settings for the users gfxconf.h file. See readme.txt
#ifndef GMOUSE_STMPE811_SELF_CALIBRATE
#define GMOUSE_STMPE811_SELF_CALIBRATE FALSE
#endif
#ifndef GMOUSE_STMPE811_READ_PRESSURE
#define GMOUSE_STMPE811_READ_PRESSURE FALSE
#endif
#ifndef GMOUSE_STMPE811_TEST_MODE
#define GMOUSE_STMPE811_TEST_MODE FALSE
#endif
/**
* Notes:
*
* This chip has some problems which required careful coding to overcome.
*
* The interrupt pin seems to be unreliable, at least on some boards, so we at most
* use the pin for filtering results to reduce cpu load.
* The symptoms are that readings will just stop due to the irq not being asserted
* even though there are items in the fifo. Another interrupt source such as a
* touch transition will restart the irq.
*
* There is no fifo entry created when a touch up event occurs. We must therefore
* generate a pseudo result on touch up. Fortunately the touch detection appears
* reliable and so we turn off the driver GMOUSE_VFLG_POORUPDOWN setting. In practice
* if touch is up we always return a pseudo event as this saves having to remember the
* previous touch state.
*
* Z readings range from around 90 (fully touched) to around 150 (on the verge of non-touched).
* Note the above is on the STM32F429i-Discovery board. Other boards may be different.
* To be conservative we use 255 as touch off, anything else is a touch on.
*
* GMOUSE_STMPE811_TEST_MODE is designed to be used with the "touch_raw_readings" tool which shows
* a steady stream of raw readings.
*
* Settings that may need tweaking on other hardware:
* The settling times. We have set these conservatively at 1ms.
* The reading window. We set this to 16 just to reduce noise. High-res panels may need a lower value.
*/
static bool_t MouseInit(GMouse* m, unsigned driverinstance) {
if (!init_board(m, driverinstance))
return FALSE;
aquire_bus(m);
write_reg(m, STMPE811_REG_SYS_CTRL1, 0x02); // Software chip reset
gfxSleepMilliseconds(10);
write_reg(m, STMPE811_REG_SYS_CTRL2, 0x0C); // Temperature sensor clock off, GPIO clock off, touch clock on, ADC clock on
#if GMOUSE_STMPE811_GPIO_IRQPIN
write_reg(m, STMPE811_REG_INT_EN, 0x03); // Interrupt on INT pin when there is a sample or a touch transition.
#else
write_reg(m, STMPE811_REG_INT_EN, 0x00); // Don't Interrupt on INT pin
#endif
write_reg(m, STMPE811_REG_ADC_CTRL1, 0x48); // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage refernce
gfxSleepMilliseconds(2);
write_reg(m, STMPE811_REG_ADC_CTRL2, 0x01); // ADC speed 3.25MHz
write_reg(m, STMPE811_REG_GPIO_AF, 0x00); // GPIO alternate function - OFF
write_reg(m, STMPE811_REG_TSC_CFG, 0xA3); // Averaging 4, touch detect delay 1ms, panel driver settling time 1ms
write_reg(m, STMPE811_REG_FIFO_TH, 0x01); // FIFO threshold = 1
write_reg(m, STMPE811_REG_FIFO_STA, 0x01); // FIFO reset enable
write_reg(m, STMPE811_REG_FIFO_STA, 0x00); // FIFO reset disable
write_reg(m, STMPE811_REG_TSC_FRACT_XYZ, 0x07); // Z axis data format
write_reg(m, STMPE811_REG_TSC_I_DRIVE, 0x01); // max 50mA touchscreen line current
#if GMOUSE_STMPE811_READ_PRESSURE
write_reg(m, STMPE811_REG_TSC_CTRL, 0x30); // X&Y&Z, 16 reading window
write_reg(m, STMPE811_REG_TSC_CTRL, 0x31); // X&Y&Z, 16 reading window, TSC enable
#else
write_reg(m, STMPE811_REG_TSC_CTRL, 0x32); // X&Y, 16 reading window
write_reg(m, STMPE811_REG_TSC_CTRL, 0x33); // X&Y, 16 reading window, TSC enable
#endif
write_reg(m, STMPE811_REG_INT_STA, 0xFF); // Clear all interrupts
write_reg(m, STMPE811_REG_INT_CTRL, 0x01); // Level interrupt, enable interrupts
release_bus(m);
return TRUE;
}
static bool_t read_xyz(GMouse* m, GMouseReading* pdr)
{
#if GMOUSE_STMPE811_TEST_MODE
static GMouseReading n;
#endif
uint8_t status;
// Button information will be regenerated
pdr->buttons = 0;
#if GMOUSE_STMPE811_TEST_MODE
aquire_bus(m);
// Set the buttons to match various touch signals
if ((read_byte(m, STMPE811_REG_TSC_CTRL) & 0x80))
pdr->buttons |= 0x02;
status = read_byte(m, STMPE811_REG_FIFO_STA);
if (!(status & 0x20))
pdr->buttons |= 0x04;
#if GMOUSE_STMPE811_GPIO_IRQPIN
if (getpin_irq(m))
pdr->buttons |= 0x08;
#endif
if ((status & 0x20)) {
// Nothing in the fifo - just return the last position and pressure
pdr->x = n.x;
pdr->y = n.y;
pdr->z = n.z;
#if GMOUSE_STMPE811_GPIO_IRQPIN
write_reg(m, STMPE811_REG_INT_STA, 0xFF);
#endif
release_bus(m);
return TRUE;
}
#else
// Is there a new sample or a touch transition
#if GMOUSE_STMPE811_GPIO_IRQPIN
if(!getpin_irq(m))
return FALSE;
#endif
// Is there something in the fifo
status = read_byte(m, STMPE811_REG_FIFO_STA);
if ((status & 0x20)) {
// Nothing in the fifo.
// If not touched return the pseudo result
if (!(read_byte(m, STMPE811_REG_TSC_CTRL) & 0x80)) {
pdr->z = gmvmt(m)->z_min;
#if GMOUSE_STMPE811_GPIO_IRQPIN
write_reg(m, STMPE811_REG_INT_STA, 0xFF);
#endif
release_bus(m);
return TRUE;
}
// No new result
#if GMOUSE_STMPE811_GPIO_IRQPIN
write_reg(m, STMPE811_REG_INT_STA, 0xFF);
#endif
release_bus(m);
return FALSE;
}
#endif
// Time to get some readings
pdr->x = (coord_t)read_word(m, STMPE811_REG_TSC_DATA_X);
pdr->y = (coord_t)read_word(m, STMPE811_REG_TSC_DATA_Y);
#if GMOUSE_STMPE811_READ_PRESSURE
pdr->z = (coord_t)read_byte(m, STMPE811_REG_TSC_DATA_Z);
#else
pdr->z = gmvmt(m)->z_max;
#endif
#if !GMOUSE_STMPE811_SLOW_CPU
if (!(status & 0xC0)) {
// Is there more data to come
if (!(read_byte(m, STMPE811_REG_FIFO_STA) & 0x20))
_gmouseWakeup(m);
} else
#endif
// Clear the rest of the fifo
{
write_reg(m, STMPE811_REG_FIFO_STA, 0x01); // FIFO reset enable
write_reg(m, STMPE811_REG_FIFO_STA, 0x00); // FIFO reset disable
}
// All done
#if GMOUSE_STMPE811_GPIO_IRQPIN
write_reg(m, STMPE811_REG_INT_STA, 0xFF);
#endif
release_bus(m);
#if GMOUSE_STMPE811_TEST_MODE
// Save the result for later
n.x = pdr->x;
n.y = pdr->y;
n.z = pdr->z;
#endif
// Rescale X,Y if we are using self-calibration
#if GMOUSE_STMPE811_SELF_CALIBRATE
pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
#endif
return TRUE;
}
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_TOUCH,
#if GMOUSE_STMPE811_SELF_CALIBRATE
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN,
#else
GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_CALIBRATE | GMOUSE_VFLG_CAL_TEST,
#endif
sizeof(GMouse) + GMOUSE_STMPE811_BOARD_DATA_SIZE,
_gmouseInitDriver,
_gmousePostInitDriver,
_gmouseDeInitDriver
},
0, // z_max - 0 indicates full touch
255, // z_min
150, // z_touchon
255, // z_touchoff
{ // pen_jitter
GMOUSE_STMPE811_PEN_CALIBRATE_ERROR, // calibrate
GMOUSE_STMPE811_PEN_CLICK_ERROR, // click
GMOUSE_STMPE811_PEN_MOVE_ERROR // move
},
{ // finger_jitter
GMOUSE_STMPE811_FINGER_CALIBRATE_ERROR, // calibrate
GMOUSE_STMPE811_FINGER_CLICK_ERROR, // click
GMOUSE_STMPE811_FINGER_MOVE_ERROR // move
},
MouseInit, // init
0, // deinit
read_xyz, // get
0, // calsave
0 // calload
}};
#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

View File

@ -0,0 +1,60 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H
// Resolution and Accuracy Settings
#define GMOUSE_STMPE811_PEN_CALIBRATE_ERROR 8
#define GMOUSE_STMPE811_PEN_CLICK_ERROR 6
#define GMOUSE_STMPE811_PEN_MOVE_ERROR 4
#define GMOUSE_STMPE811_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_STMPE811_FINGER_CLICK_ERROR 18
#define GMOUSE_STMPE811_FINGER_MOVE_ERROR 14
// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_STMPE811_BOARD_DATA_SIZE 0
// Options - Leave these commented to make it user configurable in the gfxconf.h
//#define GMOUSE_STMPE811_READ_PRESSURE FALSE
//#define GMOUSE_STMPE811_SELF_CALIBRATE FALSE
//#define GMOUSE_STMPE811_TEST_MODE FALSE
// If TRUE this board has the STMPE811 IRQ pin connected to a GPIO.
// Note: For tested hardware this is unreliable and should be set to FALSE until tested.
// Symptoms are that mouse readings just appear to stop for a bit. Lifting the touch
// and re-applying the touch cause readings to start again.
#define GMOUSE_STMPE811_GPIO_IRQPIN FALSE
// If TRUE this is a really slow CPU and we should always clear the FIFO between reads.
#define GMOUSE_STMPE811_SLOW_CPU FALSE
static bool_t init_board(GMouse* m, unsigned driverinstance) {
}
#if GMOUSE_STMPE811_GPIO_IRQPIN
static bool_t getpin_irq(GMouse* m) {
}
#endif
static inline void aquire_bus(GMouse* m) {
}
static inline void release_bus(GMouse* m) {
}
static void write_reg(GMouse* m, uint8_t reg, uint8_t val) {
}
static uint8_t read_byte(GMouse* m, uint8_t reg) {
}
static uint16_t read_word(GMouse* m, uint8_t reg) {
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */

View File

@ -0,0 +1,11 @@
This driver has a number of optional settings which can be specified in gfxconf.h:
#define GMOUSE_STMPE811_READ_PRESSURE TRUE
Returns pressure values when the touch is down. On tested boards this ranges from 90 to 150. 255 is touch off.
#define GMOUSE_STMPE811_SELF_CALIBRATE TRUE
Scale the touch readings to avoid calibration. This is not as accurate as real calibration.
#define GMOUSE_STMPE811_TEST_MODE TRUE
Return raw readings for diagnostic use with the "touch_raw_readings" tool.

View File

@ -8,12 +8,6 @@
#ifndef _STMPE811_H
#define _STMPE811_H
// Slave address
#define STMPE811_ADDR (0x82 >> 1)
// Maximum timeout
#define STMPE811_TIMEOUT 0x3000
// Identification registers
#define STMPE811_REG_CHP_ID 0x00 // 16-bit
#define STMPE811_REG_ID_VER 0x02

View File

@ -10,7 +10,7 @@
#if GFX_USE_GDISP
#define GDISP_DRIVER_VMT GDISPVMT_Win32
#include "drivers/multiple/Win32/gdisp_lld_config.h"
#include "gdisp_lld_config.h"
#include "src/gdisp/driver.h"
#ifndef GDISP_SCREEN_WIDTH
@ -52,7 +52,6 @@
#define GDISP_FLG_READY (GDISP_FLG_DRIVER<<0)
#define GDISP_FLG_HASTOGGLE (GDISP_FLG_DRIVER<<1)
#define GDISP_FLG_HASMOUSE (GDISP_FLG_DRIVER<<2)
#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
#define GDISP_FLG_WSTREAM (GDISP_FLG_DRIVER<<3)
#define GDISP_FLG_WRAPPED (GDISP_FLG_DRIVER<<4)
@ -64,16 +63,50 @@
#endif
#if GINPUT_NEED_MOUSE
/* Include mouse support code */
// Include mouse support code
#define GMOUSE_DRIVER_VMT GMOUSEVMT_Win32
#include "src/ginput/driver_mouse.h"
// Forward definitions
static bool_t Win32MouseInit(GMouse *m, unsigned driverinstance);
static bool_t Win32MouseRead(GMouse *m, GMouseReading *prd);
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_MOUSE,
GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY,
// Extra flags for testing only
//GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_DEFAULTFINGER
//GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_EXTREMES|GMOUSE_VFLG_CAL_TEST|GMOUSE_VFLG_CAL_LOADFREE
//GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN
sizeof(GMouse),
_gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
},
1, // z_max
0, // z_min
1, // z_touchon
0, // z_touchoff
{ // pen_jitter
0, // calibrate
0, // click
0 // move
},
{ // finger_jitter
0, // calibrate
2, // click
2 // move
},
Win32MouseInit, // init
0, // deinit
Win32MouseRead, // get
0, // calsave
0 // calload
}};
#endif
static DWORD winThreadId;
static volatile bool_t QReady;
static HANDLE drawMutex;
#if GINPUT_NEED_MOUSE
static GDisplay * mouseDisplay;
#endif
/*===========================================================================*/
/* Driver local routines . */
@ -95,6 +128,7 @@ typedef struct winPriv {
#if GINPUT_NEED_MOUSE
coord_t mousex, mousey;
uint16_t mousebuttons;
GMouse *mouse;
#endif
#if GINPUT_NEED_TOGGLE
uint8_t toggles;
@ -149,7 +183,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
// Handle mouse down on the window
#if GINPUT_NEED_MOUSE
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
goto mousemove;
}
@ -198,7 +232,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
// Handle mouse up on the window
#if GINPUT_NEED_MOUSE
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
priv->mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
goto mousemove;
}
@ -210,7 +244,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
case WM_MBUTTONDOWN:
g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
priv = (winPriv *)g->priv;
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
goto mousemove;
}
@ -218,7 +252,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
case WM_MBUTTONUP:
g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
priv = (winPriv *)g->priv;
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
priv->mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
goto mousemove;
}
@ -226,7 +260,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
case WM_RBUTTONDOWN:
g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
priv = (winPriv *)g->priv;
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
priv->mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
goto mousemove;
}
@ -234,7 +268,7 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
case WM_RBUTTONUP:
g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
priv = (winPriv *)g->priv;
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT) {
priv->mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
goto mousemove;
}
@ -242,14 +276,13 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
case WM_MOUSEMOVE:
g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
priv = (winPriv *)g->priv;
if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT || !(g->flags & GDISP_FLG_HASMOUSE))
if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT)
break;
mousemove:
priv->mousex = (coord_t)LOWORD(lParam);
priv->mousey = (coord_t)HIWORD(lParam);
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
ginputMouseWakeup();
#endif
if ((gmvmt(priv->mouse)->d.flags & GMOUSE_VFLG_NOPOLL)) // For normal setup this is always TRUE
_gmouseWakeup(priv->mouse);
break;
#endif
@ -445,14 +478,6 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
g->flags |= GDISP_FLG_HASTOGGLE;
#endif
// Only turn on mouse on the first window for now
#if GINPUT_NEED_MOUSE
if (!g->controllerdisplay) {
mouseDisplay = g;
g->flags |= GDISP_FLG_HASMOUSE;
}
#endif
// Create a private area for this window
priv = gfxAlloc(sizeof(winPriv));
assert(priv != 0);
@ -471,6 +496,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
Sleep(1);
// Create the associated mouse
#if GINPUT_NEED_MOUSE
priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g);
#endif
sprintf(buf, APP_NAME " - %u", g->systemdisplay+1);
SetWindowText(priv->hwnd, buf);
ShowWindow(priv->hwnd, SW_SHOW);
@ -686,10 +716,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
winPriv * priv;
int x, y;
COLORREF color;
priv = g->priv;
color = gdispColor2Native(g->p.color);
#if GDISP_NEED_CONTROL
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
@ -818,7 +848,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
sz = (size_t)g->p.cx * (size_t)g->p.cy;
if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
return 0;
// Copy the bits we need
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
@ -847,7 +877,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
return dstbuf;
}
#endif
#if GDISP_HARDWARE_BITFILLS
#if COLOR_SYSTEM != GDISP_COLORSYSTEM_TRUECOLOR || COLOR_TYPE_BITS <= 8
#error "GDISP Win32: This driver's bitblit currently only supports true-color with bit depths > 8 bits."
@ -863,7 +893,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
priv = g->priv;
buffer = g->p.ptr;
buffer += g->p.x2*g->p.y1;
memset(&bmpInfo, 0, sizeof(bmpInfo));
bmpInfo.bV4Size = sizeof(bmpInfo);
bmpInfo.bV4Planes = 1;
@ -982,7 +1012,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
#endif
ReleaseMutex(drawMutex);
return gdispNative2Color(color);
}
#endif
@ -992,7 +1022,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
winPriv * priv;
RECT rect;
coord_t lines;
priv = g->priv;
#if GDISP_NEED_CONTROL
@ -1134,18 +1164,51 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
#endif
#if GINPUT_NEED_MOUSE
void ginput_lld_mouse_init(void) {}
void ginput_lld_mouse_get_reading(MouseReading *pt) {
static bool_t Win32MouseInit(GMouse *m, unsigned driverinstance) {
(void) m;
(void) driverinstance;
return TRUE;
}
static bool_t Win32MouseRead(GMouse *m, GMouseReading *pt) {
GDisplay * g;
winPriv * priv;
g = mouseDisplay;
g = m->display;
priv = g->priv;
pt->x = priv->mousex;
pt->y = priv->mousey > g->g.Height ? g->g.Height : priv->mousey;
pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
pt->y = priv->mousey;
pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 1 : 0;
pt->buttons = priv->mousebuttons;
#if GDISP_NEED_CONTROL
// If the self-rotation has been set in the VMT then do that here (TESTING ONLY)
if ((gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) { // For normal setup this is always False
coord_t t;
switch(gdispGGetOrientation(m->display)) {
case GDISP_ROTATE_0:
default:
break;
case GDISP_ROTATE_90:
t = pt->x;
pt->x = g->g.Width - 1 - pt->y;
pt->y = t;
break;
case GDISP_ROTATE_180:
pt->x = g->g.Width - 1 - pt->x;
pt->y = g->g.Height - 1 - pt->y;
break;
case GDISP_ROTATE_270:
t = pt->y;
pt->y = g->g.Height - 1 - pt->x;
pt->x = t;
break;
}
}
#endif
return TRUE;
}
#endif /* GINPUT_NEED_MOUSE */

View File

@ -1,38 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 1
#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 25 // Poll driven
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -10,7 +10,7 @@
#if GFX_USE_GDISP
#define GDISP_DRIVER_VMT GDISPVMT_X11
#include "drivers/multiple/X/gdisp_lld_config.h"
#include "gdisp_lld_config.h"
#include "src/gdisp/driver.h"
#ifndef GDISP_FORCE_24BIT
@ -27,8 +27,45 @@
#define GDISP_FLG_READY (GDISP_FLG_DRIVER<<0)
#if GINPUT_NEED_MOUSE
/* Include mouse support code */
// Include mouse support code
#define GMOUSE_DRIVER_VMT GMOUSEVMT_X11
#include "src/ginput/driver_mouse.h"
// Forward definitions
static bool_t XMouseInit(GMouse *m, unsigned driverinstance);
static bool_t XMouseRead(GMouse *m, GMouseReading *prd);
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_MOUSE,
GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY,
// Extra flags for testing only
//GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_DEFAULTFINGER
//GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_EXTREMES|GMOUSE_VFLG_CAL_TEST|GMOUSE_VFLG_CAL_LOADFREE
//GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN
sizeof(GMouse),
_gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
},
1, // z_max
0, // z_min
1, // z_touchon
0, // z_touchoff
{ // pen_jitter
0, // calibrate
0, // click
0 // move
},
{ // finger_jitter
0, // calibrate
2, // click
2 // move
},
XMouseInit, // init
0, // deinit
XMouseRead, // get
0, // calsave
0 // calload
}};
#endif
#include <X11/Xlib.h>
@ -45,15 +82,16 @@ static Colormap cmap;
static XVisualInfo vis;
static XContext cxt;
static Atom wmDelete;
#if GINPUT_NEED_MOUSE
static coord_t mousex, mousey;
static uint16_t mousebuttons;
#endif
typedef struct xPriv {
Pixmap pix;
GC gc;
Window win;
#if GINPUT_NEED_MOUSE
coord_t mousex, mousey;
uint16_t buttons;
GMouse * mouse;
#endif
} xPriv;
static void ProcessEvent(GDisplay *g, xPriv *priv) {
@ -80,37 +118,31 @@ static void ProcessEvent(GDisplay *g, xPriv *priv) {
break;
#if GINPUT_NEED_MOUSE
case ButtonPress:
mousex = evt.xbutton.x;
mousey = evt.xbutton.y;
priv->mousex = evt.xbutton.x;
priv->mousey = evt.xbutton.y;
switch(evt.xbutton.button){
case 1: mousebuttons |= GINPUT_MOUSE_BTN_LEFT; break;
case 2: mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; break;
case 3: mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; break;
case 4: mousebuttons |= GINPUT_MOUSE_BTN_4; break;
case 1: priv->buttons |= GINPUT_MOUSE_BTN_LEFT; break;
case 2: priv->buttons |= GINPUT_MOUSE_BTN_MIDDLE; break;
case 3: priv->buttons |= GINPUT_MOUSE_BTN_RIGHT; break;
case 4: priv->buttons |= GINPUT_MOUSE_BTN_4; break;
}
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
ginputMouseWakeup();
#endif
_gmouseWakeup(priv->mouse);
break;
case ButtonRelease:
mousex = evt.xbutton.x;
mousey = evt.xbutton.y;
priv->mousex = evt.xbutton.x;
priv->mousey = evt.xbutton.y;
switch(evt.xbutton.button){
case 1: mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; break;
case 2: mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; break;
case 3: mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; break;
case 4: mousebuttons &= ~GINPUT_MOUSE_BTN_4; break;
case 1: priv->buttons &= ~GINPUT_MOUSE_BTN_LEFT; break;
case 2: priv->buttons &= ~GINPUT_MOUSE_BTN_MIDDLE; break;
case 3: priv->buttons &= ~GINPUT_MOUSE_BTN_RIGHT; break;
case 4: priv->buttons &= ~GINPUT_MOUSE_BTN_4; break;
}
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
ginputMouseWakeup();
#endif
_gmouseWakeup(priv->mouse);
break;
case MotionNotify:
mousex = evt.xmotion.x;
mousey = evt.xmotion.y;
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
ginputMouseWakeup();
#endif
priv->mousex = evt.xmotion.x;
priv->mousey = evt.xmotion.y;
_gmouseWakeup(priv->mouse);
break;
#endif
}
@ -231,6 +263,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
XSetBackground(dis, priv->gc, BlackPixel(dis, scr));
XSync(dis, TRUE);
// Create the associated mouse before the map
#if GINPUT_NEED_MOUSE
priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g);
#endif
XSelectInput(dis, priv->win, StructureNotifyMask);
XMapWindow(dis, priv->win);
@ -322,16 +359,21 @@ LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g)
#endif
#if GINPUT_NEED_MOUSE
void ginput_lld_mouse_init(void) {}
void ginput_lld_mouse_get_reading(MouseReading *pt) {
pt->x = mousex;
pt->y = mousey;
pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
pt->buttons = mousebuttons;
static bool_t XMouseInit(GMouse *m, unsigned driverinstance) {
(void) m;
(void) driverinstance;
return TRUE;
}
static bool_t XMouseRead(GMouse *m, GMouseReading *pt) {
xPriv * priv;
priv = m->display->priv;
pt->x = priv->mousex;
pt->y = priv->mousey;
pt->z = (priv->buttons & GINPUT_MOUSE_BTN_LEFT) ? 1 : 0;
pt->buttons = priv->buttons;
return TRUE;
}
#endif /* GINPUT_NEED_MOUSE */
#endif /* GFX_USE_GDISP */

View File

@ -1,38 +0,0 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#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 1
#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 25 // Poll driven
#endif /* _LLD_GINPUT_MOUSE_CONFIG_H */

View File

@ -10,7 +10,7 @@
#if GFX_USE_GDISP
#define GDISP_DRIVER_VMT GDISPVMT_uGFXnet
#include "drivers/multiple/uGFXnet/gdisp_lld_config.h"
#include "gdisp_lld_config.h"
#include "src/gdisp/driver.h"
#include "uGFXnetProtocol.h"
@ -33,6 +33,48 @@
#define GDISP_GFXNET_BROKEN_LWIP_ACCEPT FALSE
#endif
#if GINPUT_NEED_MOUSE
// Include mouse support code
#define GMOUSE_DRIVER_VMT GMOUSEVMT_uGFXnet
#include "src/ginput/driver_mouse.h"
// Forward definitions
static bool_t NMouseInit(GMouse *m, unsigned driverinstance);
static bool_t NMouseRead(GMouse *m, GMouseReading *prd);
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
{
GDRIVER_TYPE_MOUSE,
GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY,
// Extra flags for testing only
//GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_DEFAULTFINGER
//GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_EXTREMES|GMOUSE_VFLG_CAL_TEST|GMOUSE_VFLG_CAL_LOADFREE
//GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN
sizeof(GMouse),
_gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
},
1, // z_max
0, // z_min
1, // z_touchon
0, // z_touchoff
{ // pen_jitter
0, // calibrate
0, // click
0 // move
},
{ // finger_jitter
0, // calibrate
2, // click
2 // move
},
NMouseInit, // init
0, // deinit
NMouseRead, // get
0, // calsave
0 // calload
}};
#endif
#if GNETCODE_VERSION != GNETCODE_VERSION_1_0
#error "GDISP: uGFXnet - This driver only support protocol V1.0"
#endif
@ -98,14 +140,8 @@
#endif
#endif
#define GDISP_FLG_HASMOUSE (GDISP_FLG_DRIVER<<0)
#define GDISP_FLG_CONNECTED (GDISP_FLG_DRIVER<<1)
#define GDISP_FLG_HAVEDATA (GDISP_FLG_DRIVER<<2)
#if GINPUT_NEED_MOUSE
/* Include mouse support code */
#include "src/ginput/driver_mouse.h"
#endif
#define GDISP_FLG_CONNECTED (GDISP_FLG_DRIVER<<0)
#define GDISP_FLG_HAVEDATA (GDISP_FLG_DRIVER<<1)
/*===========================================================================*/
/* Driver local routines . */
@ -118,15 +154,12 @@ typedef struct netPriv {
#if GINPUT_NEED_MOUSE
coord_t mousex, mousey;
uint16_t mousebuttons;
GMouse * mouse;
#endif
} netPriv;
static gfxThreadHandle hThread;
#if GINPUT_NEED_MOUSE
static GDisplay * mouseDisplay;
#endif
#if GDISP_GFXNET_UNSAFE_SOCKETS
static gfxMutex uGFXnetMutex;
#define MUTEX_INIT gfxMutexInit(&uGFXnetMutex)
@ -156,15 +189,134 @@ static bool_t sendpkt(SOCKET_TYPE netfd, uint16_t *pkt, int len) {
return send(netfd, (const char *)pkt, len, 0) == len;
}
static bool_t newconnection(SOCKET_TYPE clientfd) {
GDisplay * g;
netPriv * priv;
// Look for a display that isn't connected
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
// Ignore displays for other controllers
#ifdef GDISP_DRIVER_LIST
if (gvmt(g) != &GDISPVMT_uGFXnet)
continue;
#endif
if (!(g->flags & GDISP_FLG_CONNECTED))
break;
}
// Was anything found?
if (!g)
return FALSE;
// Reset the priv area
priv = g->priv;
priv->netfd = clientfd;
priv->databytes = 0;
priv->mousebuttons = 0;
// Send the initialisation data (2 words at a time)
priv->data[0] = GNETCODE_INIT;
priv->data[1] = GNETCODE_VERSION;
sendpkt(priv->netfd, priv->data, 2);
priv->data[0] = GDISP_SCREEN_WIDTH;
priv->data[1] = GDISP_SCREEN_HEIGHT;
sendpkt(priv->netfd, priv->data, 2);
priv->data[0] = GDISP_LLD_PIXELFORMAT;
priv->data[1] = 1; // We have a mouse
MUTEX_ENTER;
sendpkt(priv->netfd, priv->data, 2);
MUTEX_EXIT;
// The display is now working
g->flags |= GDISP_FLG_CONNECTED;
// Send a redraw all
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
gdispGClear(g, gwinGetDefaultBgColor());
gwinRedrawDisplay(g, FALSE);
#endif
return TRUE;
}
static bool_t rxdata(SOCKET_TYPE fd) {
GDisplay * g;
netPriv * priv;
int len;
// Look for a display that is connected and the socket descriptor matches
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
// Ignore displays for other controllers
#ifdef GDISP_DRIVER_LIST
if (gvmt(g) != &GDISPVMT_uGFXnet)
continue;
#endif
priv = g->priv;
if ((g->flags & GDISP_FLG_CONNECTED) && priv->netfd == fd)
break;
}
if (!g)
gfxHalt("GDISP: uGFXnet - Got data from unrecognized connection");
if ((g->flags & GDISP_FLG_HAVEDATA)) {
// The higher level is still processing the previous data.
// Give it a chance to run by coming back to this data.
gfxSleepMilliseconds(1);
return TRUE;
}
/* handle data from a client */
MUTEX_ENTER;
if ((len = recv(fd, ((char *)priv->data)+priv->databytes, sizeof(priv->data)-priv->databytes, 0)) <= 0) {
// Socket closed or in error state
MUTEX_EXIT;
g->flags &= ~GDISP_FLG_CONNECTED;
return FALSE;
}
MUTEX_EXIT;
// Do we have a full reply yet
priv->databytes += len;
if (priv->databytes < sizeof(priv->data))
return TRUE;
priv->databytes = 0;
// Convert network byte or to host byte order
priv->data[0] = ntohs(priv->data[0]);
priv->data[1] = ntohs(priv->data[1]);
// Process the data received
switch(priv->data[0]) {
#if GINPUT_NEED_MOUSE
case GNETCODE_MOUSE_X: priv->mousex = priv->data[1]; break;
case GNETCODE_MOUSE_Y: priv->mousey = priv->data[1]; break;
case GNETCODE_MOUSE_B:
priv->mousebuttons = priv->data[1];
// Treat the button event as the sync signal
_gmouseWakeup(priv->mouse);
break;
#endif
case GNETCODE_CONTROL:
case GNETCODE_READ:
g->flags |= GDISP_FLG_HAVEDATA;
break;
case GNETCODE_KILL:
gfxHalt("GDISP: uGFXnet - Display sent KILL command");
break;
default:
// Just ignore unrecognised data
break;
}
return TRUE;
}
static DECLARE_THREAD_STACK(waNetThread, 512);
static DECLARE_THREAD_FUNCTION(NetThread, param) {
SOCKET_TYPE listenfd, fdmax, i, clientfd;
socklen_t len;
int leni;
fd_set master, read_fds;
struct sockaddr_in addr;
GDisplay * g;
netPriv * priv;
(void)param;
// Start the sockets layer
@ -197,25 +349,13 @@ static DECLARE_THREAD_FUNCTION(NetThread, param) {
fdmax = listenfd; /* so far, it's this one*/
#if GDISP_GFXNET_BROKEN_LWIP_ACCEPT
{
#warning "Using GDISP_GFXNET_BROKEN_LWIP_ACCEPT limits the number of displays and the use of GFXNET. Avoid if possible!"
len = sizeof(addr);
if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1)
gfxHalt("GDISP: uGFXnet - Accept failed");
//printf("New connection from %s on socket %d\n", inet_ntoa(addr.sin_addr), clientfd);
// Look for a display that isn't connected
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
// Ignore displays for other controllers
#ifdef GDISP_DRIVER_LIST
if (gvmt(g) != &GDISPVMT_uGFXnet)
continue;
#endif
if (!(g->flags & GDISP_FLG_CONNECTED))
break;
}
// Was anything found?
if (!g) {
if (!newconnection(clientfd)) {
// No Just close the connection
closesocket(clientfd);
gfxHalt("GDISP: uGFXnet - Can't find display for connection");
@ -225,33 +365,6 @@ static DECLARE_THREAD_FUNCTION(NetThread, param) {
// Save the descriptor
FD_SET(clientfd, &master);
if (clientfd > fdmax) fdmax = clientfd;
priv = g->priv;
memset(priv, 0, sizeof(netPriv));
priv->netfd = clientfd;
//printf(New connection from %s on socket %d allocated to display %u\n", inet_ntoa(addr.sin_addr), clientfd, disp+1);
// Send the initialisation data (2 words at a time)
priv->data[0] = GNETCODE_INIT;
priv->data[1] = GNETCODE_VERSION;
sendpkt(priv->netfd, priv->data, 2);
priv->data[0] = GDISP_SCREEN_WIDTH;
priv->data[1] = GDISP_SCREEN_HEIGHT;
sendpkt(priv->netfd, priv->data, 2);
priv->data[0] = GDISP_LLD_PIXELFORMAT;
priv->data[1] = (g->flags & GDISP_FLG_HASMOUSE) ? 1 : 0;
MUTEX_ENTER;
sendpkt(priv->netfd, priv->data, 2);
MUTEX_EXIT;
// The display is now working
g->flags |= GDISP_FLG_CONNECTED;
// Send a redraw all
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
gdispGClear(g, gwinGetDefaultBgColor());
gwinRedrawDisplay(g, FALSE);
#endif
}
#endif
/* loop */
@ -268,132 +381,33 @@ static DECLARE_THREAD_FUNCTION(NetThread, param) {
// Handle new connections
if(i == listenfd) {
// Accept the connection
len = sizeof(addr);
if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1)
gfxHalt("GDISP: uGFXnet - Accept failed");
//printf("New connection from %s on socket %d\n", inet_ntoa(addr.sin_addr), clientfd);
// Look for a display that isn't connected
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
// Ignore displays for other controllers
#ifdef GDISP_DRIVER_LIST
if (gvmt(g) != &GDISPVMT_uGFXnet)
continue;
#endif
if (!(g->flags & GDISP_FLG_CONNECTED))
break;
}
// Can we handle it?
if (!newconnection(clientfd)) {
// Was anything found?
if (!g) {
// No Just close the connection
// No - Just close the connection
closesocket(clientfd);
//printf(New connection from %s on socket %d rejected as all displays are already connected\n", inet_ntoa(addr.sin_addr), clientfd);
//printf("Rejected connection as all displays are already connected\n");
continue;
}
// Save the descriptor
FD_SET(clientfd, &master);
if (clientfd > fdmax) fdmax = clientfd;
priv = g->priv;
memset(priv, 0, sizeof(netPriv));
priv->netfd = clientfd;
//printf(New connection from %s on socket %d allocated to display %u\n", inet_ntoa(addr.sin_addr), clientfd, disp+1);
// Send the initialisation data (2 words at a time)
priv->data[0] = GNETCODE_INIT;
priv->data[1] = GNETCODE_VERSION;
sendpkt(priv->netfd, priv->data, 2);
priv->data[0] = GDISP_SCREEN_WIDTH;
priv->data[1] = GDISP_SCREEN_HEIGHT;
sendpkt(priv->netfd, priv->data, 2);
priv->data[0] = GDISP_LLD_PIXELFORMAT;
priv->data[1] = (g->flags & GDISP_FLG_HASMOUSE) ? 1 : 0;
MUTEX_ENTER;
sendpkt(priv->netfd, priv->data, 2);
MUTEX_EXIT;
// The display is now working
g->flags |= GDISP_FLG_CONNECTED;
// Send a redraw all
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
gdispGClear(g, gwinGetDefaultBgColor());
gwinRedrawDisplay(g, FALSE);
#endif
continue;
}
// Handle data from a client
// Look for a display that is connected and the socket descriptor matches
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
// Ignore displays for other controllers
#ifdef GDISP_DRIVER_LIST
if (gvmt(g) != &GDISPVMT_uGFXnet)
continue;
#endif
priv = g->priv;
if ((g->flags & GDISP_FLG_CONNECTED) && priv->netfd == i)
break;
}
if (!g)
gfxHalt("GDISP: uGFXnet - Got data from unrecognized connection");
if ((g->flags & GDISP_FLG_HAVEDATA)) {
// The higher level is still processing the previous data.
// Give it a chance to run by coming back to this data.
gfxSleepMilliseconds(1);
continue;
}
/* handle data from a client */
MUTEX_ENTER;
if ((leni = recv(i, ((char *)priv->data)+priv->databytes, sizeof(priv->data)-priv->databytes, 0)) <= 0) {
// Socket closed or in error state
MUTEX_EXIT;
g->flags &= ~GDISP_FLG_CONNECTED;
memset(priv, 0, sizeof(netPriv));
if (!rxdata(i)) {
closesocket(i);
FD_CLR(i, &master);
continue;
}
MUTEX_EXIT;
// Do we have a full reply yet
priv->databytes += leni;
if (priv->databytes < sizeof(priv->data))
continue;
priv->databytes = 0;
// Convert network byte or to host byte order
priv->data[0] = ntohs(priv->data[0]);
priv->data[1] = ntohs(priv->data[1]);
// Process the data received
switch(priv->data[0]) {
#if GINPUT_NEED_MOUSE
case GNETCODE_MOUSE_X: priv->mousex = priv->data[1]; break;
case GNETCODE_MOUSE_Y: priv->mousey = priv->data[1]; break;
case GNETCODE_MOUSE_B:
priv->mousebuttons = priv->data[1];
// Treat the button event as the sync signal
#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
ginputMouseWakeup();
#endif
break;
#endif
case GNETCODE_CONTROL:
case GNETCODE_READ:
g->flags |= GDISP_FLG_HAVEDATA;
break;
case GNETCODE_KILL:
gfxHalt("GDISP: uGFXnet - Display sent KILL command");
break;
default:
// Just ignore unrecognised data
break;
FD_CLR(clientfd, &master);
}
}
}
@ -414,14 +428,6 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
gfxThreadClose(hThread);
}
// Only turn on mouse on the first window for now
#if GINPUT_NEED_MOUSE
if (!g->controllerdisplay) {
mouseDisplay = g;
g->flags |= GDISP_FLG_HASMOUSE;
}
#endif
// Create a private area for this window
if (!(priv = gfxAlloc(sizeof(netPriv))))
gfxHalt("GDISP: uGFXnet - Memory allocation failed");
@ -429,6 +435,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
g->priv = priv;
g->board = 0; // no board interface for this controller
// Create the associated mouse
#if GINPUT_NEED_MOUSE
priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g);
#endif
// Initialise the GDISP structure
g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
@ -694,18 +705,23 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
#endif
#if GINPUT_NEED_MOUSE
void ginput_lld_mouse_init(void) {}
void ginput_lld_mouse_get_reading(MouseReading *pt) {
static bool_t NMouseInit(GMouse *m, unsigned driverinstance) {
(void) m;
(void) driverinstance;
return TRUE;
}
static bool_t NMouseRead(GMouse *m, GMouseReading *pt) {
GDisplay * g;
netPriv * priv;
g = mouseDisplay;
g = m->display;
priv = g->priv;
pt->x = priv->mousex;
pt->y = priv->mousey;
pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 1 : 0;
pt->buttons = priv->mousebuttons;
return TRUE;
}
#endif /* GINPUT_NEED_MOUSE */

View File

@ -211,6 +211,16 @@
//#define GFX_USE_GINPUT FALSE
//#define GINPUT_NEED_MOUSE FALSE
// #define GINPUT_TOUCH_STARTRAW FALSE
// #define GINPUT_TOUCH_NOTOUCH FALSE
// #define GINPUT_TOUCH_NOCALIBRATE FALSE
// #define GINPUT_TOUCH_NOCALIBRATE_GUI FALSE
// #define GINPUT_MOUSE_POLL_PERIOD 25
// #define GINPUT_MOUSE_CLICK_TIME 300
// #define GINPUT_TOUCH_CXTCLICK_TIME 700
// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD FALSE
// #define GINPUT_TOUCH_USER_CALIBRATION_FREE FALSE
// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE FALSE
//#define GINPUT_NEED_KEYBOARD FALSE
//#define GINPUT_NEED_TOGGLE FALSE
//#define GINPUT_NEED_DIAL FALSE

View File

@ -17,162 +17,159 @@
#ifndef _LLD_GINPUT_MOUSE_H
#define _LLD_GINPUT_MOUSE_H
#if GINPUT_NEED_MOUSE || defined(__DOXYGEN__)
#if GINPUT_NEED_MOUSE //|| defined(__DOXYGEN__)
#include "ginput_lld_mouse_config.h"
// Include the GDRIVER infrastructure
#include "src/gdriver/sys_defs.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 - Should the calibration happen at the extremes of the panel?
#ifndef GINPUT_MOUSE_CALIBRATE_EXTREMES
#define GINPUT_MOUSE_CALIBRATE_EXTREMES 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 25
#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
// true/false - Whether the mouse driver internally handles screen rotation
#ifndef GINPUT_MOUSE_NO_ROTATION
#define GINPUT_MOUSE_NO_ROTATION FALSE
#endif
typedef struct MouseReading_t {
typedef struct GMouseReading {
coord_t x, y, z;
uint16_t buttons;
} MouseReading;
} GMouseReading;
#if !GINPUT_TOUCH_NOCALIBRATE
typedef struct GMouseCalibration {
float ax;
float bx;
float cx;
float ay;
float by;
float cy;
} GMouseCalibration;
#endif
typedef struct GMouse {
GDriver d; // The driver overheads and vmt
GMouseReading r; // The current position and state
uint16_t flags; // Flags
#define GMOUSE_FLG_CLICK_TIMER 0x0001 // Currently timing a click
#define GMOUSE_FLG_INDELTA 0x0002 // Currently in a up/down transition test
#define GMOUSE_FLG_CLIP 0x0004 // Clip reading to the display
#define GMOUSE_FLG_CALIBRATE 0x0008 // Calibrate readings
#define GMOUSE_FLG_IN_CAL 0x0010 // Currently in calibration routine
#define GMOUSE_FLG_FINGERMODE 0x0020 // Mouse is currently in finger mode
#define GMOUSE_FLG_NEEDREAD 0x0040 // The mouse needs reading
#define GMOUSE_FLG_DRIVER_FIRST 0x0100 // The first flag available for the driver
point clickpos; // The position of the last click event
systemticks_t clicktime; // The time of the last click event
GDisplay * display; // The display the mouse is associated with
#if !GINPUT_TOUCH_NOCALIBRATE
GMouseCalibration caldata; // The calibration data
#endif
// Other driver specific fields may follow.
} GMouse;
typedef struct GMouseJitter {
coord_t calibrate; // Maximum error for a calibration to succeed
coord_t click; // Movement allowed without discarding the CLICK or CLICKCXT event
coord_t move; // Movement allowed without discarding the MOVE event
} GMouseJitter;
typedef struct GMouseVMT {
GDriverVMT d; // Device flags are part of the general vmt
#define GMOUSE_VFLG_TOUCH 0x0001 // This is a touch device (rather than a mouse). Button 1 is calculated from z value.
#define GMOUSE_VFLG_NOPOLL 0x0002 // Do not poll this device - it is purely interrupt driven
#define GMOUSE_VFLG_SELFROTATION 0x0004 // This device returns readings that are aligned with the display orientation
#define GMOUSE_VFLG_DEFAULTFINGER 0x0008 // Default to finger mode
#define GMOUSE_VFLG_CALIBRATE 0x0010 // This device requires calibration
#define GMOUSE_VFLG_CAL_EXTREMES 0x0020 // Use edge to edge calibration
#define GMOUSE_VFLG_CAL_TEST 0x0040 // Test the results of the calibration
#define GMOUSE_VFLG_CAL_LOADFREE 0x0080 // Call gfxFree on the buffer returned by the VMT calload() routine.
#define GMOUSE_VFLG_ONLY_DOWN 0x0100 // This device returns a valid position only when the mouse is down
#define GMOUSE_VFLG_POORUPDOWN 0x0200 // Position readings during up/down are unreliable
#define GMOUSE_VFLG_DYNAMICONLY 0x8000 // This mouse driver should not be statically initialized eg Win32
coord_t z_max; // TOUCH: Maximum possible z value (fully touched)
coord_t z_min; // TOUCH: Minimum possible z value (touch off screen). Note may also be > z_max
coord_t z_touchon; // TOUCH: z values between z_max and this are a solid touch on
coord_t z_touchoff; // TOUCH: z values between z_min and this are a solid touch off
GMouseJitter pen_jitter; // PEN MODE: Jitter settings
GMouseJitter finger_jitter; // FINGER MODE: Jitter settings
bool_t (*init)(GMouse *m, unsigned driverinstance); // Required
void (*deinit)(GMouse *m); // Optional
bool_t (*get)(GMouse *m, GMouseReading *prd); // Required
void (*calsave)(GMouse *m, void *buf, size_t sz); // Optional
const char *(*calload)(GMouse *m, size_t sz); // Optional: Can return NULL if no data is saved.
} GMouseVMT;
#define gmvmt(m) ((const GMouseVMT const *)((m)->d.vmt))
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
// If we are not using multiple mice then hard-code the VMT name
#if !defined(GINPUT_MOUSE_DRIVER_LIST)
#undef GMOUSE_DRIVER_VMT
#define GMOUSE_DRIVER_VMT GMOUSEVMT_OnlyOne
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialise the mouse/touch.
* @brief Initialize a mouse driver
*
* @param[in] g The mouse driver
* @param[in] display The display to which the mouse shall be assigned
* @param[in] driverinstance The driver instance ToDo: Add some more details
* @param[in] systeminstance The mouse instance ToDo: Add some more details
*
* @return TRUE on success, FALSE otherwise
* @note This routine is provided by the high level code for
* use in the driver VMT's GMouseVMT.d structure.
*
* @notapi
*/
void ginput_lld_mouse_init(void);
bool_t _gmouseInitDriver(GDriver *g, void *display, unsigned driverinstance, unsigned systeminstance);
/**
* @brief Read the mouse/touch position.
* @brief Routine that is called after initialization
*
* @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.
* @param[in] g The mouse driver
* @note This routine is provided by the high level code for
* use in the driver VMT's GMouseVMT.d structure.
*
* @notapi
*/
void ginput_lld_mouse_get_reading(MouseReading *pt);
void _gmousePostInitDriver(GDriver *g);
#if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
/**
* @brief Load calibration data from a storage area on the touch controller.
*
* @param[in] instance The mouse instance number
*
* @note The instance parameter is currently always 0 as we only support
* one mouse/touch device at a time.
* @note This routine should only be provided if the driver has its own
* storage area where calibration data can be stored. The drivers
* option.h file should define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE = TRUE
* if it supports this.
*
* @notapi
*/
const char *ginput_lld_mouse_calibration_load(uint16_t instance);
/**
* @brief Save calibration data to a storage area on the touch controller.
*
* @param[in] instance The mouse instance number
* @param[in] calbuf The calibration data to be saved
* @param[in] sz The size of the calibration data
*
* @note The instance parameter is currently always 0 as we only support
* one mouse/touch device at a time.
* @note This routine should only be provided if the driver has its own
* storage area where calibration data can be stored. The drivers
* option.h file should define GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE = TRUE
* if it supports this.
*
* @notapi
*/
void ginput_lld_mouse_calibration_save(uint16_t instance, const uint8_t *calbuf, size_t sz);
#endif
/**
* @brief Deinitialize a mouse driver
*
* @param[in] g The mouse driver
* @note This routine is provided by the high level code for
* use in the driver VMT's GMouseVMT.d structure.
*
* @notapi
*/
void _gmouseDeInitDriver(GDriver *g);
/**
* @brief Wakeup the high level code so that it attempts another read
*
* @note This routine is provided to low level drivers by the high level code
* @note Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
*
* @notapi
*/
void ginputMouseWakeup(void);
void _gmouseWakeup(GMouse *m);
/**
* @brief Wakeup the high level code so that it attempts another read
*
* @note This routine is provided to low level drivers by the high level code
* @note Particularly useful if GINPUT_MOUSE_POLL_PERIOD = TIME_INFINITE
*
* @iclass
* @notapi
*/
void ginputMouseWakeupI(void);
void _gmouseWakeupI(GMouse *m);
#ifdef __cplusplus
}
#endif
#endif /* GINPUT_NEED_MOUSE || GINPUT_NEED_TOUCH */
#endif /* GINPUT_NEED_MOUSE */
#endif /* _LLD_GINPUT_MOUSE_H */
/** @} */

View File

@ -16,10 +16,16 @@
#if GFX_USE_GINPUT
#if GINPUT_NEED_MOUSE
extern void _gmouseInit(void);
extern void _gmouseDeinit(void);
#endif
void _ginputInit(void)
{
/* ToDo */
#if GINPUT_NEED_MOUSE
_gmouseInit();
#endif
/**
* This should really call an init routine for each ginput sub-system.
* Maybe we'll do this later.
@ -28,7 +34,9 @@ void _ginputInit(void)
void _ginputDeinit(void)
{
#if GINPUT_NEED_MOUSE
_gmouseDeinit();
#endif
}
#endif /* GFX_USE_GINPUT */

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
*
* @pre GFX_USE_GINPUT must be set to TRUE in your gfxconf.h
* @pre GINPUT_NEED_MOUSE must be set to TRUE in your gfxconf.h
*
*
* @{
*/
@ -32,32 +32,29 @@
/* 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;
GEventType type; // The type of this event (GEVENT_MOUSE or GEVENT_TOUCH)
coord_t x, y, z; // The position of the mouse.
// - For touch devices, Z is the current pressure if supported (values are device specific)
// - For mice, Z is the 3rd dimension if supported (values are device specific)
uint16_t buttons; // A bit is set if the button is down or a meta event has occurred.
#define GINPUT_MOUSE_BTN_MASK 0x000F // The "button is down" mask
#define GINPUT_MOUSE_BTN_LEFT 0x0001 // The left mouse button is currently down
#define GINPUT_MOUSE_BTN_RIGHT 0x0002 // The right mouse button is currently down
#define GINPUT_MOUSE_BTN_MIDDLE 0x0004 // The middle mouse button is currently down
#define GINPUT_MOUSE_BTN_4 0x0008 // The 4th mouse button is currently down
#define GINPUT_TOUCH_PRESSED 0x0001 // The touch surface is currently touched
#define GMETA_MASK 0x00F0 // The "button transition" mask
#define GMETA_NONE 0x0000 // No "button transition" events
#define GMETA_MOUSE_DOWN 0x0010 // Left mouse/touch has just gone down
#define GMETA_MOUSE_UP 0x0020 // Left mouse/touch has just gone up
#define GMETA_MOUSE_CLICK 0x0040 // Left mouse/touch has just gone through a click (short down - up cycle)
#define GMETA_MOUSE_CXTCLICK 0x0080 // Right mouse has just been depressed or touch has gone through a long click
#define GINPUT_MISSED_MOUSE_EVENT 0x8000 // Oops - a mouse event has previously been missed
GDisplay * display; // The display this mouse is currently associated with.
} GEventMouse;
} GEventMouse;
// Mouse/Touch Listen Flags - passed to geventAddSourceToListener()
#define GLISTEN_MOUSEMETA 0x0001 // Create events for meta events such as CLICK and CXTCLICK
@ -69,12 +66,13 @@ typedef struct GEventMouse_t {
#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)
// All mice
#define GMOUSE_ALL_INSTANCES ((unsigned)-1)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
@ -84,16 +82,32 @@ extern "C" {
#endif
/**
* @brief Creates an instance of a mouse and returns the Source handler
* @note HACK: if the instance is 9999, it is treated as instance 0 except
* that no calibration will be performed!
* @brief Get the Source handler for a mouse using the instance number
*
* @param[in] instance The ID of the mouse input instance (from 0 to 9999)
* @param[in] instance The mouse instance number
*
* @return The source handle of the created instance
* @return The source handle of the mouse or NULL
* @note You can use the special value of GMOUSE_ALL_INSTANCES to
* get a source handle that returns events for all mice rather
* than a specific mouse. Using GMOUSE_ALL_INSTANCES will always
* return a valid spurce handle even if there are currently no mice
* in the system.
*/
GSourceHandle ginputGetMouse(uint16_t instance);
GSourceHandle ginputGetMouse(unsigned instance);
/**
* @brief Should this device be in Pen mode or Finger mode
* @note A touch device (and even theoritically a mouse) can operate
* in either pen or finger mode. In finger mode typically a
* touch device will be far more tolerant of movement and other
* inaccuracies. Each driver specifies its own tolerances for
* pen versus finger mode.
*
* @param[in] instance The ID of the mouse input instance
* @param[in] on If true then finger mode is turned on.
*/
void ginputSetFingerMode(unsigned instance, bool_t on);
/**
* @brief Assign the display associated with the mouse
* @note This only needs to be called if the mouse is associated with a display
@ -105,7 +119,7 @@ extern "C" {
* @param[in] instance The ID of the mouse input instance
* @param[in] g The GDisplay to which this mouse belongs
*/
void ginputSetMouseDisplay(uint16_t instance, GDisplay *g);
void ginputSetMouseDisplay(unsigned instance, GDisplay *g);
/**
* @brief Get the display currently associated with the mouse
@ -113,7 +127,7 @@ extern "C" {
*
* @param[in] instance The ID of the mouse input instance
*/
GDisplay *ginputGetMouseDisplay(uint16_t instance);
GDisplay *ginputGetMouseDisplay(unsigned instance);
/**
* @brief Get the current mouse position and button status
@ -125,51 +139,47 @@ extern "C" {
*
* @return FALSE on an error (eg. invalid instance)
*/
bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pmouse);
bool_t ginputGetMouseStatus(unsigned instance, GEventMouse *pmouse);
/**
* @brief Performs a calibration
*
* @param[in] instance The ID of the mouse input instance
*
* @return FALSE if the driver dosen't support a calibration of if the handle is invalid
* @return The calibration error squared if calibration fails, or 0 on success or if the driver dosen't need calibration.
* @note An invalid instance will also return 0.
*/
bool_t ginputCalibrateMouse(uint16_t instance);
uint32_t ginputCalibrateMouse(unsigned 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)
/**
* @brief Load a set of mouse calibration data
* @return A pointer to the data or NULL on failure
*
* @param[in] instance The mouse input instance number
* @param[in] sz The size in bytes of the data to retrieve.
*
* @note This routine is provided by the user application. It is only
* called if GINPUT_TOUCH_USER_CALIBRATION_LOAD has been set to TRUE in the
* users gfxconf.h file.
* @note If GINPUT_TOUCH_USER_CALIBRATION_FREE has been set to TRUE in the users
* gfxconf.h file then the buffer returned will be free'd using gfxFree().
*/
void *LoadMouseCalibration(unsigned instance, size_t sz);
/**
* @brief Set the routines to store and restore calibration data
/**
* @brief Save a set of mouse calibration data
* @return TRUE if the save operation was successful.
*
* @param[in] instance The mouse input instance number
* @param[in] data The data to save
* @param[in] sz The size in bytes of the data to retrieve.
*
* @details 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.
*
* @param[in] instance The ID of the mouse input instance
* @param[in] fnsave The routine to save the data
* @param[in] fnload The routine to restore the data
* @param[in] requireFree TRUE if the buffer returned by the load function must be freed by the mouse code.
*/
void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree);
* @note This routine is provided by the user application. It is only
* called if GINPUT_TOUCH_USER_CALIBRATION_SAVE has been set to TRUE in the
* users gfxconf.h file.
*/
bool_t SaveMouseCalibration(unsigned instance, const void *data, size_t sz);
/**
* @brief Test if a particular mouse/touch instance requires routines to save it's alibration data
* @note Not implemented yet
*
* @param[in] instance The ID of the mouse input instance
*
* @return TRUE if needed
*/
bool_t ginputRequireMouseCalibrationStorage(uint16_t instance);
#ifdef __cplusplus
}
#endif

View File

@ -73,40 +73,97 @@
* @{
*/
/**
* @brief Use a custom board definition for the mouse/touch driver even if a board definition exists.
* @brief Start touch devices without loading or running calibration.
* @details Defaults to FALSE
* @details If TRUE, add ginput_lld_mouse_board.h to your project directory and customise it.
* @note Not all GINPUT mouse/touch low level drivers use board definition files.
* @note This is used if you want to manually control the initial calibration
* process. In practice this is only useful for a touch driver test program.
*/
#ifndef GINPUT_MOUSE_USE_CUSTOM_BOARD
#define GINPUT_MOUSE_USE_CUSTOM_BOARD FALSE
#ifndef GINPUT_TOUCH_STARTRAW
#define GINPUT_TOUCH_STARTRAW FALSE
#endif
/**
* @brief Turn off the touch calibration GUI.
* @details Defaults to FALSE
* @note Turning off the calibration GUI just turns off the manual calibration
* process. Readings may still be calibrated if calibration data
* can be loaded.
* @note Calibration requires a lot of code. If your device doesn't require it
* using this option can save a lot of space.
*/
#ifndef GINPUT_TOUCH_NOCALIBRATE_GUI
#define GINPUT_TOUCH_NOCALIBRATE_GUI FALSE
#endif
/**
* @brief Use a custom board definition for the keyboard driver even if a board definition exists.
* @brief Turn off all touch calibration support.
* @details Defaults to FALSE
* @details If TRUE, add ginput_lld_keyboard_board.h to your project directory and customise it.
* @note Not all GINPUT keyboard low level drivers use board definition files.
* @note With this set to TRUE touch readings will not be calibrated.
* @note This automatically turns off the calibration GUI too!
* @note Calibration requires a lot of code. If your device doesn't require it
* using this option can save a lot of space.
*/
#ifndef GINPUT_KEYBOARD_USE_CUSTOM_BOARD
#define GINPUT_KEYBOARD_USE_CUSTOM_BOARD FALSE
#ifndef GINPUT_TOUCH_NOCALIBRATE
#define GINPUT_TOUCH_NOCALIBRATE FALSE
#endif
/**
* @brief Use a custom board definition for the toggle driver even if a board definition exists.
* @brief Turn off all touch support.
* @details Defaults to FALSE
* @details If TRUE, add ginput_lld_toggle_board.h to your project directory and customise it.
* @note Not all GINPUT toggle low level drivers use board definition files.
* @note This automatically turns off all calibration and the calibration GUI too!
* @note Touch device handling requires a lot of code. If your device doesn't require it
* using this option can save a lot of space.
*/
#ifndef GINPUT_TOGGLE_USE_CUSTOM_BOARD
#define GINPUT_TOGGLE_USE_CUSTOM_BOARD FALSE
#ifndef GINPUT_TOUCH_NOTOUCH
#define GINPUT_TOUCH_NOTOUCH FALSE
#endif
/**
* @brief Use a custom board definition for the dial driver even if a board definition exists.
* @details Defaults to FALSE
* @details If TRUE, add ginput_lld_dial_board.h to your project directory and customise it.
* @note Not all GINPUT dial low level drivers use board definition files.
* @brief Milliseconds between mouse polls.
* @details Defaults to 25 millseconds
* @note How often mice should be polled. More often leads to smoother mouse movement
* but increases CPU usage.
*/
#ifndef GINPUT_DIAL_USE_CUSTOM_BOARD
#define GINPUT_DIAL_USE_CUSTOM_BOARD FALSE
#ifndef GINPUT_MOUSE_POLL_PERIOD
#define GINPUT_MOUSE_POLL_PERIOD 25
#endif
/**
* @brief Maximum length of CLICK in milliseconds
* @details Defaults to 300 millseconds
* @note Mouse down to Mouse up times greater than this are not clicks.
*/
#ifndef GINPUT_MOUSE_CLICK_TIME
#define GINPUT_MOUSE_CLICK_TIME 300
#endif
/**
* @brief Milliseconds to generate a CXTCLICK on a touch device.
* @details Defaults to 700 millseconds
* @note If you hold the touch down for longer than this a CXTCLICK is generated
* but only on a touch device.
*/
#ifndef GINPUT_TOUCH_CXTCLICK_TIME
#define GINPUT_TOUCH_CXTCLICK_TIME 700
#endif
/**
* @brief There is a user supplied routine to load mouse calibration data
* @details Defaults to FALSE
* @note If TRUE the user must supply the @p LoadMouseCalibration() routine.
*/
#ifndef GINPUT_TOUCH_USER_CALIBRATION_LOAD
#define GINPUT_TOUCH_USER_CALIBRATION_LOAD FALSE
#endif
/**
* @brief The buffer returned by the users @p LoadMouseCalibration() routine must be gfxFree()'d
* by the mouse code.
* @details Defaults to FALSE
*/
#ifndef GINPUT_TOUCH_USER_CALIBRATION_FREE
#define GINPUT_TOUCH_USER_CALIBRATION_FREE FALSE
#endif
/**
* @brief There is a user supplied routine to save mouse calibration data
* @details Defaults to FALSE
* @note If TRUE the user must supply the @p SaveMouseCalibration() routine.
*/
#ifndef GINPUT_TOUCH_USER_CALIBRATION_SAVE
#define GINPUT_TOUCH_USER_CALIBRATION_SAVE FALSE
#endif
/** @} */

View File

@ -31,6 +31,21 @@
#undef GFX_USE_GTIMER
#define GFX_USE_GTIMER TRUE
#endif
#if GINPUT_NEED_MOUSE
#if GINPUT_TOUCH_NOTOUCH
// No warning needed for this
#undef GINPUT_TOUCH_NOCALIBRATE
#define GINPUT_TOUCH_NOCALIBRATE TRUE
#endif
#if GINPUT_TOUCH_NOCALIBRATE
// No warning needed for this
#undef GINPUT_TOUCH_NOCALIBRATE_GUI
#define GINPUT_TOUCH_NOCALIBRATE_GUI TRUE
#endif
#if !GINPUT_TOUCH_NOTOUCH && GINPUT_MOUSE_CLICK_TIME > GINPUT_TOUCH_CXTCLICK_TIME
#error "GINPUT MOUSE: The GINPUT_MOUSE_CLICK_TIME must be <= GINPUT_TOUCH_CXTCLICK_TIME"
#endif
#endif
#endif
#endif /* _GINPUT_RULES_H */

View File

@ -114,7 +114,7 @@ static void gwidgetEvent(void *param, GEvent *pe) {
// Is the mouse currently captured by this widget?
if ((h->flags & (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) == (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) {
gh = h;
if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
if ((pme->buttons & GMETA_MOUSE_UP)) {
gh->flags &= ~GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseUp)
wvmt->MouseUp(gw, pme->x - gh->x, pme->y - gh->y);
@ -133,7 +133,7 @@ static void gwidgetEvent(void *param, GEvent *pe) {
// Process any mouse down over the highest order window if it is an enabled widget
if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
if ((pme->buttons & GMETA_MOUSE_DOWN)) {
gh->flags |= GWIN_FLG_MOUSECAPTURE;
if (wvmt->MouseDown)
wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
@ -234,6 +234,7 @@ void _gwidgetInit(void)
{
geventListenerInit(&gl);
geventRegisterCallback(&gl, gwidgetEvent, 0);
geventAttachSource(&gl, ginputGetMouse(GMOUSE_ALL_INSTANCES), GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
}
void _gwidgetDeinit(void)
@ -427,13 +428,10 @@ bool_t gwinAttachListener(GListener *pl) {
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
bool_t gwinAttachMouse(uint16_t instance) {
GSourceHandle gsh;
if (!(gsh = ginputGetMouse(instance)))
return FALSE;
return geventAttachSource(&gl, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
bool_t DEPRECATED("This call can now be removed. Attaching the mouse to GWIN is now automatic.") gwinAttachMouse(uint16_t instance) {
// This is now a NULL event because we automatically attach to all mice in the system.
(void) instance;
return TRUE;
}
#endif

View File

@ -199,7 +199,7 @@ void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll);
* @brief Get the current default style.
*
* @return The current default style.
*
*
* @api
*/
const GWidgetStyle *gwinGetDefaultStyle(void);
@ -305,17 +305,7 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param);
bool_t gwinAttachListener(GListener *pl);
#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) || defined(__DOXYGEN__)
/**
* @brief Set the mouse to be used to control the widgets
* @return TRUE on success
*
* @param[in] instance The mouse instance
*
* @note Every widget uses the same mouse.
*
* @api
*/
bool_t gwinAttachMouse(uint16_t instance);
bool_t DEPRECATED("This call can now be removed. Attaching the mouse to GWIN is now automatic.") gwinAttachMouse(uint16_t instance);
#endif
#if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || defined(__DOXYGEN__)

View File

@ -57,5 +57,6 @@
/* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE
#define GINPUT_TOUCH_STARTRAW TRUE
#endif /* _GFXCONF_H */

View File

@ -29,9 +29,57 @@
#include "gfx.h"
// We get nasty and look at some internal structures - get the relevant information
#include "src/gdriver/sys_defs.h"
#include "src/ginput/driver_mouse.h"
#include <string.h>
static GConsoleObject gc;
static GListener gl;
static font_t font;
static coord_t bWidth, bWidth2, bHeight;
static GHandle ghc;
static coord_t swidth, sheight;
static void DrawHeader(const char *title, bool_t btnNext, bool_t btnPrev, bool_t btnPlusMinus) {
#if GDISP_NEED_CLIP
gdispSetClip(0, 0, swidth, sheight);
#endif
gdispFillStringBox(0, 0, swidth, bHeight, "Touch Calibration", font, Red, White, justifyLeft);
if (btnNext)
gdispFillStringBox(swidth-1*bWidth, 0, bWidth , bHeight, "Next", font, Black, Gray, justifyCenter);
if (btnPrev)
gdispFillStringBox(swidth-2*bWidth, 0, bWidth-1, bHeight, "Prev", font, Black, Gray, justifyCenter);
if (btnPlusMinus) {
gdispFillStringBox(swidth-2*bWidth-1*bWidth2, 0, bWidth2-1, bHeight, "+", font, Black, Gray, justifyCenter);
gdispFillStringBox(swidth-2*bWidth-2*bWidth2, 0, bWidth2-1, bHeight, "-", font, Black, Gray, justifyCenter);
}
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n%s\n\n", title);
gwinSetColor(ghc, White);
}
#define BTN_NONE 0
#define BTN_NEXT 1
#define BTN_PREV 2
#define BTN_PLUS 3
#define BTN_MINUS 4
static int CheckButtons(GEventMouse *pem) {
if (pem->y < bHeight && (pem->buttons & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-1*bWidth)
return BTN_NEXT;
if (pem->x >= swidth-2*bWidth)
return BTN_PREV;
if (pem->x >= swidth-2*bWidth-1*bWidth2)
return BTN_PLUS;
if (pem->x >= swidth-2*bWidth-2*bWidth2)
return BTN_MINUS;
}
return BTN_NONE;
}
/*------------------------------------------------------------------------*
* GINPUT Touch Driver Calibrator. *
@ -39,18 +87,22 @@ static font_t font;
int main(void) {
GSourceHandle gs;
GEventMouse *pem;
coord_t swidth, sheight;
GHandle ghc;
GEventType deviceType;
bool_t calibrated;
coord_t bWidth, bHeight;
bool_t isFirstTime;
bool_t isCalibrated;
bool_t isTouch;
bool_t isFinger;
const char * isFingerText;
const char * deviceText;
GMouse * m;
GMouseVMT * vmt;
GMouseJitter * pjit;
uint32_t calerr;
gfxInit(); // Initialize the display
// Get the display dimensions
swidth = gdispGetWidth();
sheight = gdispGetHeight();
calibrated = FALSE;
// Create our title
font = gdispOpenFont("UI2");
@ -59,8 +111,11 @@ int main(void) {
bHeight = gdispGetStringWidth("Prev", font);
if (bHeight > bWidth) bWidth = bHeight;
bWidth += 4;
bHeight = gdispGetFontMetric(font, fontHeight)+2;
gdispFillStringBox(0, 0, swidth, bHeight, "Touch Calibration", font, Red, White, justifyLeft);
bWidth2 = gdispGetStringWidth("+", font)*2;
bHeight = gdispGetStringWidth("-", font)*2;
if (bHeight > bWidth2) bWidth2 = bHeight;
bWidth2 += 4;
bHeight = gdispGetFontMetric(font, fontHeight)*2+2;
// Create our main display window
{
@ -70,75 +125,98 @@ int main(void) {
wi.show = TRUE; wi.x = 0; wi.y = bHeight; wi.width = swidth; wi.height = sheight-bHeight;
ghc = gwinConsoleCreate(&gc, &wi);
}
gwinClear(ghc);
// Initialize the mouse in our special no calibration mode.
// Initialize the listener
geventListenerInit(&gl);
gs = ginputGetMouse(9999);
// Copy the current mouse's VMT so we can play with it.
m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, 0);
if (!m) gfxHalt("No mouse instance 0");
vmt = gfxAlloc(sizeof(GMouseVMT));
if (!vmt) gfxHalt("Could not allocate memory for mouse VMT");
memcpy(vmt, m->d.vmt, sizeof(GMouseVMT));
// Swap VMT's on the current mouse to our RAM copy
m->d.vmt = (const GDriverVMT *)vmt;
// Listen for events
gs = ginputGetMouse(0);
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
// Get initial display settings for buttons
isFirstTime = TRUE;
isCalibrated = (vmt->d.flags & GMOUSE_VFLG_CALIBRATE) ? FALSE : TRUE;
calerr = 0;
/*
* Test: Device Type
*/
StepDeviceType:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n1. DEVICE TYPE\n\n");
DrawHeader("1. Device Type", isCalibrated, isCalibrated && !isFirstTime, isCalibrated);
pem = (GEventMouse *)&gl.event;
ginputGetMouseStatus(0, pem);
deviceType = pem->type;
// Get the type of device and the current mode
isTouch = (vmt->d.flags & GMOUSE_VFLG_TOUCH) ? TRUE : FALSE;
isFinger = (m->flags & GMOUSE_FLG_FINGERMODE) ? TRUE : FALSE;
pjit = isFinger ? &vmt->finger_jitter : &vmt->pen_jitter;
isFingerText = isFinger ? "finger" : "pen";
deviceText = isTouch ? isFingerText : "mouse";
gwinSetColor(ghc, White);
gwinPrintf(ghc, "This is detected as a %s device\n\n",
deviceType == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN"));
gwinPrintf(ghc, "This is detected as a %s device\n\n", isTouch ? "TOUCH" : "MOUSE");
gwinPrintf(ghc, "It is currently in %s mode\n\n", isFinger ? "FINGER" : "PEN");
if (calibrated)
gwinPrintf(ghc, "Press Next or Back to continue.\n");
else if (deviceType == GEVENT_MOUSE)
gwinPrintf(ghc, "Click the mouse button to move on to the next test.\n");
else
gwinPrintf(ghc, "Press and release your finger to move on to the next test.\n");
if (!isCalibrated)
gwinPrintf(ghc, "Press and release your %s to move on to the next test.\n", deviceText);
else {
gwinPrintf(ghc, "Press + for pen or - for finger.\n");
if (isFirstTime)
gwinPrintf(ghc, "Press Next to continue.\n");
else
gwinPrintf(ghc, "Press Next or Back to continue.\n");
}
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (calibrated) {
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepClickJitter;
}
if (isCalibrated) {
switch (CheckButtons(pem)) {
case BTN_NEXT:
break;
case BTN_PREV:
if (!isFirstTime)
goto StepDrawing;
continue;
case BTN_PLUS:
m->flags &= ~GMOUSE_FLG_FINGERMODE;
goto StepDeviceType;
case BTN_MINUS:
m->flags |= GMOUSE_FLG_FINGERMODE;
goto StepDeviceType;
default:
continue;
}
} else if ((pem->meta & GMETA_MOUSE_UP))
break;
}
if ((pem->buttons & GMETA_MOUSE_UP))
break;
}
/*
* Test: Mouse raw reading jitter
* Test: Mouse raw reading
*/
StepRawJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n2. GINPUT_MOUSE_READ_CYCLES\n\n");
gwinSetColor(ghc, White);
if (deviceType == GEVENT_MOUSE)
gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
else
StepRawReading:
DrawHeader("2. Raw Mouse Output", FALSE, FALSE, FALSE);
if (isTouch)
gwinPrintf(ghc, "Press and hold on the surface.\n\n");
gwinPrintf(ghc, "Numbers will display in this window.\n"
"Ensure that values don't jump around very much when your finger is stationary.\n\n"
"Increasing GINPUT_MOUSE_READ_CYCLES helps reduce jitter but increases CPU usage.\n\n");
if (calibrated)
gwinPrintf(ghc, "Press Next or Back to continue.\n");
else if (deviceType == GEVENT_MOUSE)
gwinPrintf(ghc, "Release the mouse button to move on to the next test.\n");
else
gwinPrintf(ghc, "Release your finger to move on to the next test.\n");
gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
gwinPrintf(ghc, "The raw values coming from your mouse driver will display.\n\n");
gwinPrintf(ghc, "Make sure the x and y values change as you move.\n\n");
gwinPrintf(ghc, "Release your %s to move on to the next test.\n", deviceText);
// Make sure we are in uncalibrated mode
m->flags &= ~(GMOUSE_FLG_CALIBRATE|GMOUSE_FLG_CLIP);
// For this test turn on ALL mouse movement events
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEUPMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
@ -148,17 +226,16 @@ StepRawJitter:
// mind missing events for this test.
gfxSleepMilliseconds(100);
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (calibrated) {
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepDeviceType;
}
}
} else if ((pem->meta & GMETA_MOUSE_UP))
gwinPrintf(ghc, "%u, %u z=%u b=0x%04x\n", pem->x, pem->y, pem->z, pem->buttons & ~GINPUT_MISSED_MOUSE_EVENT);
if ((pem->buttons & GMETA_MOUSE_UP))
break;
gwinPrintf(ghc, "%u:%u z=%u b=0x%04x m=%04x\n", pem->x, pem->y, pem->z, pem->current_buttons, pem->meta);
}
// Reset to calibrated condition
if (isCalibrated) {
m->flags |= GMOUSE_FLG_CLIP;
if ((vmt->d.flags & GMOUSE_VFLG_CALIBRATE))
m->flags |= GMOUSE_FLG_CALIBRATE;
}
// Reset to just changed movements.
@ -169,62 +246,68 @@ StepRawJitter:
*/
StepCalibrate:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n3. GINPUT_MOUSE_CALIBRATION_ERROR\n\n");
gwinSetColor(ghc, Gray);
gwinPrintf(ghc, "Ensure GINPUT_MOUSE_NEED_CALIBRATION = TRUE and GINPUT_MOUSE_CALIBRATION_ERROR is >= 0\n\n");
gwinSetColor(ghc, White);
gwinPrintf(ghc, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
"If the calibration repeatedly fails, increase GINPUT_MOUSE_CALIBRATION_ERROR and try again.\n\n");
if (calibrated)
gwinPrintf(ghc, "Press Next to start the calibration.\n");
else if (deviceType == GEVENT_MOUSE)
gwinPrintf(ghc, "Click the mouse button to start the calibration.\n");
DrawHeader("3. Calibration Jitter", isCalibrated, isCalibrated, isCalibrated);
if ((vmt->d.flags & GMOUSE_VFLG_CALIBRATE)) {
gwinPrintf(ghc, "You will be presented with a number of points to touch.\nPress them in turn.\n\n"
"If the calibration repeatedly fails, increase the jitter for %s calibration and try again.\n\n", isFingerText);
gwinPrintf(ghc, "Pressing the surface for longer gives more accurate results.\n\n");
if (calerr)
gwinPrintf(ghc, "Last calibration error ^ 2 = %u\n", calerr);
gwinPrintf(ghc, "Calibration jitter (%s) = %u\n", isFingerText, pjit->calibrate);
if (isCalibrated)
gwinPrintf(ghc, "Press + or - to adjust.\n");
} else {
gwinPrintf(ghc, "This device does not need calibration.\n\n");
}
if (isCalibrated)
gwinPrintf(ghc, "Press Next or Back to continue.\n");
else
gwinPrintf(ghc, "Press and release your finger to start the calibration.\n");
gwinPrintf(ghc, "Press and release your %s to move on to start calibration.\n", deviceText);
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (calibrated) {
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepRawJitter;
}
if (isCalibrated) {
switch (CheckButtons(pem)) {
case BTN_NEXT:
break;
case BTN_PREV:
goto StepRawReading;
case BTN_PLUS:
gwinPrintf(ghc, "Calibration jitter (%s) = %u", isFingerText, ++pjit->calibrate);
continue;
case BTN_MINUS:
gwinPrintf(ghc, "Calibration jitter (%s) = %u", isFingerText, --pjit->calibrate);
continue;
default:
continue;
}
} else if ((pem->meta & GMETA_MOUSE_UP))
break;
}
if ((pem->buttons & GMETA_MOUSE_UP))
break;
}
// Calibrate
ginputCalibrateMouse(0);
calibrated = TRUE;
// Calibration used the whole screen - re-establish our title and Next and Previous Buttons
gdispFillStringBox(0, 0, swidth, bHeight, "Touch Calibration", font, Green, White, justifyLeft);
gdispFillStringBox(swidth-2*bWidth, 0, bWidth-1, bHeight, "Prev", font, Black, Gray, justifyCenter);
gdispFillStringBox(swidth-1*bWidth, 0, bWidth , bHeight, "Next", font, Black, Gray, justifyCenter);
if ((vmt->d.flags & GMOUSE_VFLG_CALIBRATE)) {
calerr = ginputCalibrateMouse(0);
if (calerr)
goto StepCalibrate;
isCalibrated = TRUE;
}
/*
* Test: Mouse coords
*/
StepMouseCoords:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n4. Show Mouse Coordinates\n\n");
gwinSetColor(ghc, White);
if (deviceType == GEVENT_MOUSE)
gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
else
DrawHeader("4. Show Mouse Coordinates", TRUE, TRUE, TRUE);
if (isTouch)
gwinPrintf(ghc, "Press and hold on the surface.\n\n");
gwinPrintf(ghc, "Numbers will display in this window.\n"
"Check the coordinates against where it should be on the screen.\n\n");
else
gwinPrintf(ghc, "Press and hold the mouse button.\n\n");
gwinPrintf(ghc, "Check the coordinates against where it should be on the screen.\n\n");
gwinPrintf(ghc, "X should be 0 to %u\nY should be 0 to %u\n\n", swidth-1, sheight-1);
gwinPrintf(ghc, "Press + to retry using extremes or - for normal calibration.\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n");
// For this test normal mouse movement events
@ -235,15 +318,23 @@ StepMouseCoords:
// mind missing events for this test.
gfxSleepMilliseconds(100);
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepCalibrate;
}
switch (CheckButtons(pem)) {
case BTN_NEXT:
break;
case BTN_PREV:
goto StepCalibrate;
case BTN_PLUS:
vmt->d.flags |= GMOUSE_VFLG_CAL_EXTREMES;
goto StepCalibrate;
case BTN_MINUS:
vmt->d.flags &= ~GMOUSE_VFLG_CAL_EXTREMES;
goto StepCalibrate;
default:
gwinPrintf(ghc, "%u, %u\n", pem->x, pem->y);
continue;
}
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
gwinPrintf(ghc, "%u:%u z=%u\n", pem->x, pem->y, pem->z);
break;
}
// Reset to just changed movements.
@ -253,66 +344,41 @@ StepMouseCoords:
* Test: Mouse movement jitter
*/
StepJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n4. GINPUT_MOUSE_MOVE_JITTER\n\n");
gwinSetColor(ghc, White);
if (deviceType == GEVENT_MOUSE)
gwinPrintf(ghc, "Press and hold the mouse button and move around as if to draw.\n\n");
else
StepMovementJitter:
DrawHeader("5. Movement Jitter", TRUE, TRUE, TRUE);
if (isTouch)
gwinPrintf(ghc, "Press firmly on the surface and move around as if to draw.\n\n");
else
gwinPrintf(ghc, "Press and hold the mouse button and move around as if to draw.\n\n");
gwinPrintf(ghc, "Dots will display in this window. Ensure that when you stop moving your finger that "
"new dots stop displaying.\nNew dots should only display when your finger is moving.\n\n"
"Adjust GINPUT_MOUSE_MOVE_JITTER to the smallest value that this reliably works for.\n\n");
gwinPrintf(ghc, "Dots will display in this window. Ensure that when you stop moving your %s that "
"new dots stop displaying.\nNew dots should only display when your %s is moving.\n\n"
"Adjust %s movement jitter to the smallest value that this reliably works for.\n\n", deviceText, deviceText, isFingerText);
gwinPrintf(ghc, "Movement jitter (%s) = %u\n", isFingerText, pjit->move);
gwinPrintf(ghc, "Press + or - to adjust.\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepMouseCoords;
}
switch (CheckButtons(pem)) {
case BTN_NEXT:
break;
case BTN_PREV:
goto StepMouseCoords;
case BTN_PLUS:
gwinPrintf(ghc, "Movement jitter (%s) = %u", isFingerText, ++pjit->move);
continue;
case BTN_MINUS:
gwinPrintf(ghc, "Movement jitter (%s) = %u", isFingerText, --pjit->move);
continue;
default:
if ((pem->buttons & GINPUT_MOUSE_BTN_LEFT))
gwinPrintf(ghc, ".");
continue;
}
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
gwinPrintf(ghc, ".");
break;
}
/*
* Test: Polling frequency
*/
StepPolling:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n");
gwinSetColor(ghc, White);
gwinPrintf(ghc, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
gwinPrintf(ghc, "A green line will follow your finger.\n"
"Adjust GINPUT_MOUSE_POLL_PERIOD to the highest value that provides a line without "
"gaps that are too big.\nDecreasing the value increases CPU usage.\n"
"About 25 (millisecs) normally produces good results."
"This test can be ignored for interrupt driven drivers.\n\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepJitter;
}
}
if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
gdispDrawPixel(pem->x, pem->y, Green);
}
/*
* Test: Click Jitter
*/
@ -320,38 +386,76 @@ StepPolling:
StepClickJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n");
gwinPrintf(ghc, "\n6. Click Jitter\n\n");
gwinSetColor(ghc, White);
gwinPrintf(ghc, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
gwinPrintf(ghc, "For a mouse click with the left and right buttons.\n\n");
gwinPrintf(ghc, "Dots will display in this window. A yellow dash is a left (or short) click. "
if (isTouch)
gwinPrintf(ghc, "Press and release the touch surface to \"click\".\nTry both short and long presses.\n");
else
gwinPrintf(ghc, "Click the mouse with the left and right buttons.\n\n");
gwinPrintf(ghc, "A yellow dash is a left (or short) click.\n"
"A red x is a right (or long) click.\n\n"
"Adjust GINPUT_MOUSE_CLICK_JITTER to the smallest value that this reliably works for.\n"
"Adjust GINPUT_MOUSE_CLICK_TIME to adjust distinguishing short vs long presses.\n"
"TIME_INFINITE means there are no long presses (although a right mouse button will still work).\n\n"
"Note: moving your finger (mouse) during a click cancels it.\n\n");
gwinPrintf(ghc, "This is the last test but you can press Next or Back to continue.\n\n");
"Adjust %s click jitter to the smallest value that this reliably works for.\n"
"Note: moving your %s during a click cancels it.\n\n", isFingerText, deviceText);
gwinPrintf(ghc, "Click jitter (%s) = %u\n", isFingerText, pjit->click);
gwinPrintf(ghc, "Press + or - to adjust.\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
switch (CheckButtons(pem)) {
case BTN_NEXT:
break;
case BTN_PREV:
goto StepMovementJitter;
case BTN_PLUS:
gwinPrintf(ghc, "Click jitter (%s) = %u", isFingerText, ++pjit->click);
continue;
case BTN_MINUS:
gwinPrintf(ghc, "Click jitter (%s) = %u", isFingerText, --pjit->click);
continue;
default:
if ((pem->buttons & GMETA_MOUSE_CLICK)) {
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "-");
}
if ((pem->buttons & GMETA_MOUSE_CXTCLICK)) {
gwinSetColor(ghc, Red);
gwinPrintf(ghc, "x");
}
continue;
}
break;
}
/*
* Test: Polling frequency
*/
StepDrawing:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "\n7. Drawing\n\n");
gwinSetColor(ghc, White);
gwinPrintf(ghc, "Press firmly on the surface (or press and hold the mouse button) and move around as if to draw.\n\n");
gwinPrintf(ghc, "A green line will follow your %s.\n\n", deviceText);
gwinPrintf(ghc, "Pressing Next will start the tests again but with the option of changing pen/finger mode.\n\n");
gwinPrintf(ghc, "Press Next or Back to continue.\n\n");
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
if ((pem->meta & GMETA_MOUSE_UP)) {
if ((pem->buttons & GMETA_MOUSE_UP)) {
if (pem->x >= swidth-bWidth)
break;
goto StepPolling;
goto StepClickJitter;
}
}
if ((pem->meta & GMETA_MOUSE_CLICK)) {
gwinSetColor(ghc, Yellow);
gwinPrintf(ghc, "-");
}
if ((pem->meta & GMETA_MOUSE_CXTCLICK)) {
gwinSetColor(ghc, Red);
gwinPrintf(ghc, "x");
}
gdispDrawPixel(pem->x, pem->y, Green);
}
// Can't let this really exit
isFirstTime = FALSE;
goto StepDeviceType;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GFXCONF_H
#define _GFXCONF_H
/* The operating system to use. One of these must be defined - preferably in your Makefile */
//#define GFX_USE_OS_CHIBIOS FALSE
//#define GFX_USE_OS_WIN32 FALSE
//#define GFX_USE_OS_LINUX FALSE
//#define GFX_USE_OS_OSX FALSE
/* GFX sub-systems to turn on */
#define GFX_USE_GDISP TRUE
#define GFX_USE_GWIN TRUE
#define GFX_USE_GEVENT TRUE
#define GFX_USE_GTIMER TRUE
#define GFX_USE_GINPUT TRUE
/* Features for the GDISP sub-system. */
#define GDISP_NEED_VALIDATION TRUE
#define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_TEXT TRUE
#define GDISP_NEED_MULTITHREAD TRUE
/* Builtin Fonts */
#define GDISP_INCLUDE_FONT_UI2 TRUE
/* Features for the GWIN sub-system. */
#define GWIN_NEED_CONSOLE TRUE
/* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE
#define GINPUT_TOUCH_STARTRAW TRUE
#endif /* _GFXCONF_H */

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
* Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gfx.h"
// We get nasty and look at some internal structures - get the relevant information
#include "src/gdriver/sys_defs.h"
#include "src/ginput/driver_mouse.h"
#include <string.h>
static GConsoleObject gc;
static GListener gl;
static font_t font;
static coord_t bHeight;
static GHandle ghc;
static coord_t swidth, sheight;
/*------------------------------------------------------------------------*
* GINPUT Touch Driver Calibrator. *
*------------------------------------------------------------------------*/
int main(void) {
GSourceHandle gs;
GEventMouse *pem;
GMouse * m;
GMouseVMT * vmt;
gfxInit(); // Initialize the display
// Get the display dimensions
swidth = gdispGetWidth();
sheight = gdispGetHeight();
// Create our title
font = gdispOpenFont("UI2");
gwinSetDefaultFont(font);
bHeight = gdispGetFontMetric(font, fontHeight)+4;
gdispFillStringBox(0, 0, swidth, bHeight, "Raw Touch Readings", font, Red, White, justifyCenter);
// Create our main display writing window
{
GWindowInit wi;
gwinClearInit(&wi);
wi.show = TRUE; wi.x = 0; wi.y = bHeight; wi.width = swidth; wi.height = sheight-bHeight;
ghc = gwinConsoleCreate(&gc, &wi);
}
// Initialize the listener
geventListenerInit(&gl);
// Copy the current mouse's VMT so we can play with it.
m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, 0);
if (!m) gfxHalt("No mouse instance 0");
vmt = gfxAlloc(sizeof(GMouseVMT));
if (!vmt) gfxHalt("Could not allocate memory for mouse VMT");
memcpy(vmt, m->d.vmt, sizeof(GMouseVMT));
// Swap VMT's on the current mouse to our RAM copy
m->d.vmt = (const GDriverVMT *)vmt;
// Listen for events
gs = ginputGetMouse(0);
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEMETA);
// Make sure we are in uncalibrated pen mode
m->flags &= ~(GMOUSE_FLG_CALIBRATE|GMOUSE_FLG_CLIP|GMOUSE_FLG_FINGERMODE);
// Pretend we are a mouse, turn off all touch processing, turn off move and click filtering
vmt->d.flags &= ~(GMOUSE_VFLG_TOUCH | GMOUSE_VFLG_ONLY_DOWN | GMOUSE_VFLG_POORUPDOWN);
vmt->pen_jitter.move = 0;
vmt->pen_jitter.click = 0;
// For this test turn on ALL mouse movement events
geventAttachSource(&gl, gs, GLISTEN_MOUSEDOWNMOVES|GLISTEN_MOUSEUPMOVES|GLISTEN_MOUSEMETA|GLISTEN_MOUSENOFILTER);
while(1) {
pem = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
gwinPrintf(ghc, "%u, %u z=%u b=0x%04x\n", pem->x, pem->y, pem->z, pem->buttons & ~GINPUT_MISSED_MOUSE_EVENT);
// Always sleep a bit first to enable other events. We actually don't mind missing events.
gfxSleepMilliseconds(100);
}
}