aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@unormal.org>2014-11-12 08:50:05 +0100
committerJoel Bodenmann <joel@unormal.org>2014-11-12 08:50:05 +0100
commitd3a0606c65535be34cb38e6cfb3ba8d92657ad82 (patch)
tree0baf7c7a132138efc5a5a223f986795521108187
parentf793194e43b130ae9e5133ac7d03bd819ce77e91 (diff)
parent04334f284c8c4236e2a07b6611ddb790ee05db72 (diff)
downloaduGFX-d3a0606c65535be34cb38e6cfb3ba8d92657ad82.tar.gz
uGFX-d3a0606c65535be34cb38e6cfb3ba8d92657ad82.tar.bz2
uGFX-d3a0606c65535be34cb38e6cfb3ba8d92657ad82.zip
Merge branch 'newmouse'
-rw-r--r--boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h72
-rw-r--r--boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h40
-rw-r--r--boards/addons/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h165
-rw-r--r--boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_board.h88
-rw-r--r--boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_config.h22
-rw-r--r--boards/base/Embest-STM32-DMSTF4BB/gmouse_lld_STMPE811_board.h119
-rw-r--r--boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_board.h56
-rw-r--r--boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_config.h22
-rw-r--r--boards/base/FireBull-STM32F103-FB/gmouse_lld_ADS7843_board.h86
-rw-r--r--boards/base/Marlin/ginput_lld_mouse_board.h111
-rw-r--r--boards/base/Marlin/ginput_lld_mouse_config.h32
-rw-r--r--boards/base/Marlin/gmouse_lld_FT5x06_board.h93
-rw-r--r--boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_board.h85
-rw-r--r--boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_config.h21
-rw-r--r--boards/base/Mikromedia-STM32-M4-ILI9341/gmouse_lld_MCU_board.h95
-rw-r--r--boards/base/Olimex-STM32-LCD/ginput_lld_mouse_board.h126
-rw-r--r--boards/base/Olimex-STM32-LCD/ginput_lld_mouse_config.h22
-rw-r--r--boards/base/Olimex-STM32-LCD/gmouse_lld_MCU_board.h136
-rw-r--r--boards/base/STM32F429i-Discovery/board.mk3
-rw-r--r--boards/base/STM32F429i-Discovery/example_chibios_2.x/halconf.h2
-rw-r--r--boards/base/STM32F429i-Discovery/example_chibios_2.x/mcuconf.h2
-rw-r--r--boards/base/STM32F429i-Discovery/gmouse_lld_STMPE811_board.h120
-rw-r--r--demos/modules/gwin/button/main.c5
-rw-r--r--demos/modules/gwin/checkbox/main.c7
-rw-r--r--demos/modules/gwin/container/main.c5
-rw-r--r--demos/modules/gwin/container_nested/main.c11
-rw-r--r--demos/modules/gwin/frame/main.c7
-rw-r--r--demos/modules/gwin/label/main.c3
-rw-r--r--demos/modules/gwin/list/main.c3
-rw-r--r--demos/modules/gwin/radio/main.c3
-rw-r--r--demos/modules/gwin/slider/main.c3
-rw-r--r--demos/modules/gwin/widgets/main.c5
-rw-r--r--docs/releases.txt4
-rw-r--r--drivers/ginput/touch/ADS7843/driver.mk5
-rw-r--r--drivers/ginput/touch/ADS7843/ginput_lld_mouse.c94
-rw-r--r--drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_template.h31
-rw-r--r--drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h21
-rw-r--r--drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843.c80
-rw-r--r--drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843_board_template.h42
-rw-r--r--drivers/ginput/touch/FT5x06/driver.mk5
-rw-r--r--drivers/ginput/touch/FT5x06/ginput_lld_mouse.c88
-rw-r--r--drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_template.h27
-rw-r--r--drivers/ginput/touch/FT5x06/ginput_lld_mouse_config.h21
-rw-r--r--drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06.c121
-rw-r--r--drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06_board_template.h46
-rw-r--r--drivers/ginput/touch/MAX11802/driver.mk2
-rw-r--r--drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c189
-rw-r--r--drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h69
-rw-r--r--drivers/ginput/touch/MAX11802/max11802.h31
-rw-r--r--drivers/ginput/touch/MCU/driver.mk5
-rw-r--r--drivers/ginput/touch/MCU/ginput_lld_mouse.c80
-rw-r--r--drivers/ginput/touch/MCU/ginput_lld_mouse_board_template.h41
-rw-r--r--drivers/ginput/touch/MCU/ginput_lld_mouse_config_template.h21
-rw-r--r--drivers/ginput/touch/MCU/gmouse_lld_MCU.c50
-rw-r--r--drivers/ginput/touch/MCU/gmouse_lld_MCU_board_template.h32
-rw-r--r--drivers/ginput/touch/STMPE811/driver.mk5
-rw-r--r--drivers/ginput/touch/STMPE811/ginput_lld_mouse.c132
-rw-r--r--drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_template.h27
-rw-r--r--drivers/ginput/touch/STMPE811/ginput_lld_mouse_config.h25
-rw-r--r--drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811.c253
-rw-r--r--drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811_board_template.h60
-rw-r--r--drivers/ginput/touch/STMPE811/readme.txt11
-rw-r--r--drivers/ginput/touch/STMPE811/stmpe811.h6
-rw-r--r--drivers/multiple/Win32/gdisp_lld_Win32.c135
-rw-r--r--drivers/multiple/Win32/ginput_lld_mouse_config.h38
-rw-r--r--drivers/multiple/X/gdisp_lld_X.c118
-rw-r--r--drivers/multiple/X/ginput_lld_mouse_config.h38
-rw-r--r--drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c374
-rw-r--r--gfxconf.example.h10
-rw-r--r--src/ginput/driver_mouse.h219
-rw-r--r--src/ginput/ginput_ginput.c14
-rw-r--r--src/ginput/ginput_mouse.c1245
-rw-r--r--src/ginput/ginput_mouse.h154
-rw-r--r--src/ginput/sys_options.h99
-rw-r--r--src/ginput/sys_rules.h15
-rw-r--r--src/gwin/gwin_widget.c16
-rw-r--r--src/gwin/gwin_widget.h14
-rw-r--r--tools/touch_driver_test/gfxconf.h1
-rw-r--r--tools/touch_driver_test/main.c450
-rw-r--r--tools/touch_raw_readings/gfxconf.h62
-rw-r--r--tools/touch_raw_readings/main.c110
81 files changed, 3616 insertions, 2690 deletions
diff --git a/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h b/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
index f17d6e8e..af5f1282 100644
--- a/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
+++ b/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
@@ -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 */
-
diff --git a/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h b/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h
index 6c3e2124..b4478d2b 100644
--- a/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h
+++ b/boards/addons/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h
@@ -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 */
diff --git a/boards/addons/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h b/boards/addons/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h
index 87e2a93c..391eba9c 100644
--- a/boards/addons/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h
+++ b/boards/addons/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h
@@ -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;
-/**
- * @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, };
-
- // Set X+ to ground
- palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
- palClearPad(IOPORTB, XPOS);
-
- // Set Y- to VCC
- 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);
+ if (driverinstance)
+ return FALSE;
- return (ADC_MAX - (samples[1] - samples[0])) > TOUCH_THRESHOULD;
+ adcObjectInit(&ADCD);
+ adcStart(&ADCD, &ADCC);
+ return TRUE;
}
-/**
- * @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;
+static bool_t read_xyz(GMouse *m, GMouseReading *prd) {
+ adcsample_t samples[2];
+
+ prd->buttons = 0;
+
+ // 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]);
+
+ // Shortcut - no need to read X or Y if the touch is off.
+ if (pdr->z < GMOUSE_MCU_Z_TOUCHON)
+ return TRUE;
+
+ // 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];
+
+ // 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];
+
+ return TRUE;
}
#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
diff --git a/boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_board.h b/boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_board.h
deleted file mode 100644
index d525e268..00000000
--- a/boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_board.h
+++ /dev/null
@@ -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 */
-
diff --git a/boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_config.h b/boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_config.h
deleted file mode 100644
index f3a89208..00000000
--- a/boards/base/Embest-STM32-DMSTF4BB/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
-
diff --git a/boards/base/Embest-STM32-DMSTF4BB/gmouse_lld_STMPE811_board.h b/boards/base/Embest-STM32-DMSTF4BB/gmouse_lld_STMPE811_board.h
new file mode 100644
index 00000000..bbb17010
--- /dev/null
+++ b/boards/base/Embest-STM32-DMSTF4BB/gmouse_lld_STMPE811_board.h
@@ -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 */
diff --git a/boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_board.h b/boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_board.h
deleted file mode 100644
index 6ca1a897..00000000
--- a/boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_board.h
+++ /dev/null
@@ -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 */
-
diff --git a/boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_config.h b/boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_config.h
deleted file mode 100644
index f3a89208..00000000
--- a/boards/base/FireBull-STM32F103-FB/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
-
diff --git a/boards/base/FireBull-STM32F103-FB/gmouse_lld_ADS7843_board.h b/boards/base/FireBull-STM32F103-FB/gmouse_lld_ADS7843_board.h
new file mode 100644
index 00000000..b202dd85
--- /dev/null
+++ b/boards/base/FireBull-STM32F103-FB/gmouse_lld_ADS7843_board.h
@@ -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 */
+
diff --git a/boards/base/Marlin/ginput_lld_mouse_board.h b/boards/base/Marlin/ginput_lld_mouse_board.h
deleted file mode 100644
index d787d224..00000000
--- a/boards/base/Marlin/ginput_lld_mouse_board.h
+++ /dev/null
@@ -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 */
-/** @} */
-
diff --git a/boards/base/Marlin/ginput_lld_mouse_config.h b/boards/base/Marlin/ginput_lld_mouse_config.h
deleted file mode 100644
index 57d3f135..00000000
--- a/boards/base/Marlin/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
-/** @} */
diff --git a/boards/base/Marlin/gmouse_lld_FT5x06_board.h b/boards/base/Marlin/gmouse_lld_FT5x06_board.h
new file mode 100644
index 00000000..ac961d0e
--- /dev/null
+++ b/boards/base/Marlin/gmouse_lld_FT5x06_board.h
@@ -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 */
diff --git a/boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_board.h b/boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_board.h
deleted file mode 100644
index 75db2c62..00000000
--- a/boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_board.h
+++ /dev/null
@@ -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 */
diff --git a/boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_config.h b/boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_config.h
deleted file mode 100644
index 328e6337..00000000
--- a/boards/base/Mikromedia-STM32-M4-ILI9341/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
diff --git a/boards/base/Mikromedia-STM32-M4-ILI9341/gmouse_lld_MCU_board.h b/boards/base/Mikromedia-STM32-M4-ILI9341/gmouse_lld_MCU_board.h
new file mode 100644
index 00000000..bad8b9ab
--- /dev/null
+++ b/boards/base/Mikromedia-STM32-M4-ILI9341/gmouse_lld_MCU_board.h
@@ -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 */
diff --git a/boards/base/Olimex-STM32-LCD/ginput_lld_mouse_board.h b/boards/base/Olimex-STM32-LCD/ginput_lld_mouse_board.h
deleted file mode 100644
index 91575527..00000000
--- a/boards/base/Olimex-STM32-LCD/ginput_lld_mouse_board.h
+++ /dev/null
@@ -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 */
-
diff --git a/boards/base/Olimex-STM32-LCD/ginput_lld_mouse_config.h b/boards/base/Olimex-STM32-LCD/ginput_lld_mouse_config.h
deleted file mode 100644
index e8362219..00000000
--- a/boards/base/Olimex-STM32-LCD/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
-
diff --git a/boards/base/Olimex-STM32-LCD/gmouse_lld_MCU_board.h b/boards/base/Olimex-STM32-LCD/gmouse_lld_MCU_board.h
new file mode 100644
index 00000000..414587cf
--- /dev/null
+++ b/boards/base/Olimex-STM32-LCD/gmouse_lld_MCU_board.h
@@ -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 */
diff --git a/boards/base/STM32F429i-Discovery/board.mk b/boards/base/STM32F429i-Discovery/board.mk
index c8dc7117..09116393 100644
--- a/boards/base/STM32F429i-Discovery/board.mk
+++ b/boards/base/STM32F429i-Discovery/board.mk
@@ -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
diff --git a/boards/base/STM32F429i-Discovery/example_chibios_2.x/halconf.h b/boards/base/STM32F429i-Discovery/example_chibios_2.x/halconf.h
index e0ef55fe..8c45a63b 100644
--- a/boards/base/STM32F429i-Discovery/example_chibios_2.x/halconf.h
+++ b/boards/base/STM32F429i-Discovery/example_chibios_2.x/halconf.h
@@ -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
/**
diff --git a/boards/base/STM32F429i-Discovery/example_chibios_2.x/mcuconf.h b/boards/base/STM32F429i-Discovery/example_chibios_2.x/mcuconf.h
index d0b1d6a4..222958fe 100644
--- a/boards/base/STM32F429i-Discovery/example_chibios_2.x/mcuconf.h
+++ b/boards/base/STM32F429i-Discovery/example_chibios_2.x/mcuconf.h
@@ -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)
diff --git a/boards/base/STM32F429i-Discovery/gmouse_lld_STMPE811_board.h b/boards/base/STM32F429i-Discovery/gmouse_lld_STMPE811_board.h
new file mode 100644
index 00000000..f5bab2b9
--- /dev/null
+++ b/boards/base/STM32F429i-Discovery/gmouse_lld_STMPE811_board.h
@@ -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 */
diff --git a/demos/modules/gwin/button/main.c b/demos/modules/gwin/button/main.c
index 15e8e5a7..1d8aa2e6 100644
--- a/demos/modules/gwin/button/main.c
+++ b/demos/modules/gwin/button/main.c
@@ -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();
diff --git a/demos/modules/gwin/checkbox/main.c b/demos/modules/gwin/checkbox/main.c
index 28122bee..22963e40 100644
--- a/demos/modules/gwin/checkbox/main.c
+++ b/demos/modules/gwin/checkbox/main.c
@@ -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();
diff --git a/demos/modules/gwin/container/main.c b/demos/modules/gwin/container/main.c
index 4e73b0c4..75e3f78b 100644
--- a/demos/modules/gwin/container/main.c
+++ b/demos/modules/gwin/container/main.c
@@ -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);
diff --git a/demos/modules/gwin/container_nested/main.c b/demos/modules/gwin/container_nested/main.c
index 2d90f76b..5cd5e793 100644
--- a/demos/modules/gwin/container_nested/main.c
+++ b/demos/modules/gwin/container_nested/main.c
@@ -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);
diff --git a/demos/modules/gwin/frame/main.c b/demos/modules/gwin/frame/main.c
index fe956925..a97525ab 100644
--- a/demos/modules/gwin/frame/main.c
+++ b/demos/modules/gwin/frame/main.c
@@ -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);
diff --git a/demos/modules/gwin/label/main.c b/demos/modules/gwin/label/main.c
index aab9cd76..425436ea 100644
--- a/demos/modules/gwin/label/main.c
+++ b/demos/modules/gwin/label/main.c
@@ -63,9 +63,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
- // Attach the mouse input
- gwinAttachMouse(0);
-
// create the widget
createWidgets();
diff --git a/demos/modules/gwin/list/main.c b/demos/modules/gwin/list/main.c
index ed5b6905..0102f276 100644
--- a/demos/modules/gwin/list/main.c
+++ b/demos/modules/gwin/list/main.c
@@ -79,9 +79,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
- // Attach the mouse input
- gwinAttachMouse(0);
-
// create the widget
createWidgets();
diff --git a/demos/modules/gwin/radio/main.c b/demos/modules/gwin/radio/main.c
index 7455c770..59b86983 100644
--- a/demos/modules/gwin/radio/main.c
+++ b/demos/modules/gwin/radio/main.c
@@ -83,9 +83,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
- // Attach the mouse input
- gwinAttachMouse(0);
-
// create the widget
createWidgets();
diff --git a/demos/modules/gwin/slider/main.c b/demos/modules/gwin/slider/main.c
index ddcd90df..bf0aacfc 100644
--- a/demos/modules/gwin/slider/main.c
+++ b/demos/modules/gwin/slider/main.c
@@ -59,9 +59,6 @@ int main(void) {
gwinSetDefaultStyle(&WhiteWidgetStyle, FALSE);
gdispClear(White);
- // Attach the mouse input
- gwinAttachMouse(0);
-
// create the widget
createWidgets();
diff --git a/demos/modules/gwin/widgets/main.c b/demos/modules/gwin/widgets/main.c
index 3239ab4c..d2f6882b 100644
--- a/demos/modules/gwin/widgets/main.c
+++ b/demos/modules/gwin/widgets/main.c
@@ -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);
diff --git a/docs/releases.txt b/docs/releases.txt
index cf401935..ef1e4547 100644
--- a/docs/releases.txt
+++ b/docs/releases.txt
@@ -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 ***
diff --git a/drivers/ginput/touch/ADS7843/driver.mk b/drivers/ginput/touch/ADS7843/driver.mk
index 31e9ab2c..1a0eaf8e 100644
--- a/drivers/ginput/touch/ADS7843/driver.mk
+++ b/drivers/ginput/touch/ADS7843/driver.mk
@@ -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
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c b/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
deleted file mode 100644
index cb9b6f4e..00000000
--- a/drivers/ginput/touch/ADS7843/ginput_lld_mouse.c
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_template.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_template.h
deleted file mode 100644
index 09783adf..00000000
--- a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_template.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h
deleted file mode 100644
index 31840a51..00000000
--- a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843.c b/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843.c
new file mode 100644
index 00000000..5f1eb226
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843.c
@@ -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 */
+
diff --git a/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843_board_template.h b/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843_board_template.h
new file mode 100644
index 00000000..0b9cc71b
--- /dev/null
+++ b/drivers/ginput/touch/ADS7843/gmouse_lld_ADS7843_board_template.h
@@ -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 */
diff --git a/drivers/ginput/touch/FT5x06/driver.mk b/drivers/ginput/touch/FT5x06/driver.mk
index 17d38c61..741464e8 100644
--- a/drivers/ginput/touch/FT5x06/driver.mk
+++ b/drivers/ginput/touch/FT5x06/driver.mk
@@ -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
diff --git a/drivers/ginput/touch/FT5x06/ginput_lld_mouse.c b/drivers/ginput/touch/FT5x06/ginput_lld_mouse.c
deleted file mode 100644
index 7a50c5f6..00000000
--- a/drivers/ginput/touch/FT5x06/ginput_lld_mouse.c
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_template.h b/drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_template.h
deleted file mode 100644
index b7744a49..00000000
--- a/drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_template.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/FT5x06/ginput_lld_mouse_config.h b/drivers/ginput/touch/FT5x06/ginput_lld_mouse_config.h
deleted file mode 100644
index 24335a0a..00000000
--- a/drivers/ginput/touch/FT5x06/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06.c b/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06.c
new file mode 100644
index 00000000..6b0bcdb2
--- /dev/null
+++ b/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06.c
@@ -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 */
+
diff --git a/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06_board_template.h b/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06_board_template.h
new file mode 100644
index 00000000..46680a16
--- /dev/null
+++ b/drivers/ginput/touch/FT5x06/gmouse_lld_FT5x06_board_template.h
@@ -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 */
diff --git a/drivers/ginput/touch/MAX11802/driver.mk b/drivers/ginput/touch/MAX11802/driver.mk
new file mode 100644
index 00000000..246e48b3
--- /dev/null
+++ b/drivers/ginput/touch/MAX11802/driver.mk
@@ -0,0 +1,2 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c
diff --git a/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c
new file mode 100644
index 00000000..d1435628
--- /dev/null
+++ b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802.c
@@ -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 */
diff --git a/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h
new file mode 100644
index 00000000..6171089f
--- /dev/null
+++ b/drivers/ginput/touch/MAX11802/gmouse_lld_MAX11802_board_template.h
@@ -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 */
diff --git a/drivers/ginput/touch/MAX11802/max11802.h b/drivers/ginput/touch/MAX11802/max11802.h
new file mode 100644
index 00000000..2266bfa1
--- /dev/null
+++ b/drivers/ginput/touch/MAX11802/max11802.h
@@ -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 */
diff --git a/drivers/ginput/touch/MCU/driver.mk b/drivers/ginput/touch/MCU/driver.mk
index e771236a..c8c792b2 100644
--- a/drivers/ginput/touch/MCU/driver.mk
+++ b/drivers/ginput/touch/MCU/driver.mk
@@ -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
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse.c b/drivers/ginput/touch/MCU/ginput_lld_mouse.c
deleted file mode 100644
index ad2519e4..00000000
--- a/drivers/ginput/touch/MCU/ginput_lld_mouse.c
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_template.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_template.h
deleted file mode 100644
index e213bcb9..00000000
--- a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_template.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_config_template.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_config_template.h
deleted file mode 100644
index 328e6337..00000000
--- a/drivers/ginput/touch/MCU/ginput_lld_mouse_config_template.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/MCU/gmouse_lld_MCU.c b/drivers/ginput/touch/MCU/gmouse_lld_MCU.c
new file mode 100644
index 00000000..babf8bc3
--- /dev/null
+++ b/drivers/ginput/touch/MCU/gmouse_lld_MCU.c
@@ -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 */
diff --git a/drivers/ginput/touch/MCU/gmouse_lld_MCU_board_template.h b/drivers/ginput/touch/MCU/gmouse_lld_MCU_board_template.h
new file mode 100644
index 00000000..440d81fe
--- /dev/null
+++ b/drivers/ginput/touch/MCU/gmouse_lld_MCU_board_template.h
@@ -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 */
diff --git a/drivers/ginput/touch/STMPE811/driver.mk b/drivers/ginput/touch/STMPE811/driver.mk
index 5147e989..cf12507b 100644
--- a/drivers/ginput/touch/STMPE811/driver.mk
+++ b/drivers/ginput/touch/STMPE811/driver.mk
@@ -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
diff --git a/drivers/ginput/touch/STMPE811/ginput_lld_mouse.c b/drivers/ginput/touch/STMPE811/ginput_lld_mouse.c
deleted file mode 100644
index e658fae2..00000000
--- a/drivers/ginput/touch/STMPE811/ginput_lld_mouse.c
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_template.h b/drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_template.h
deleted file mode 100644
index b7744a49..00000000
--- a/drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_template.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/STMPE811/ginput_lld_mouse_config.h b/drivers/ginput/touch/STMPE811/ginput_lld_mouse_config.h
deleted file mode 100644
index 5cd512eb..00000000
--- a/drivers/ginput/touch/STMPE811/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811.c b/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811.c
new file mode 100644
index 00000000..27bc280e
--- /dev/null
+++ b/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811.c
@@ -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 */
+
diff --git a/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811_board_template.h b/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811_board_template.h
new file mode 100644
index 00000000..4520cf67
--- /dev/null
+++ b/drivers/ginput/touch/STMPE811/gmouse_lld_STMPE811_board_template.h
@@ -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 */
diff --git a/drivers/ginput/touch/STMPE811/readme.txt b/drivers/ginput/touch/STMPE811/readme.txt
new file mode 100644
index 00000000..60d7f603
--- /dev/null
+++ b/drivers/ginput/touch/STMPE811/readme.txt
@@ -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.
+
diff --git a/drivers/ginput/touch/STMPE811/stmpe811.h b/drivers/ginput/touch/STMPE811/stmpe811.h
index 1ee9c211..df85889f 100644
--- a/drivers/ginput/touch/STMPE811/stmpe811.h
+++ b/drivers/ginput/touch/STMPE811/stmpe811.h
@@ -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
diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c
index 3643d727..13c5e544 100644
--- a/drivers/multiple/Win32/gdisp_lld_Win32.c
+++ b/drivers/multiple/Win32/gdisp_lld_Win32.c
@@ -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 */
diff --git a/drivers/multiple/Win32/ginput_lld_mouse_config.h b/drivers/multiple/Win32/ginput_lld_mouse_config.h
deleted file mode 100644
index 8263ebed..00000000
--- a/drivers/multiple/Win32/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/multiple/X/gdisp_lld_X.c b/drivers/multiple/X/gdisp_lld_X.c
index 35cf250d..d62f52e6 100644
--- a/drivers/multiple/X/gdisp_lld_X.c
+++ b/drivers/multiple/X/gdisp_lld_X.c
@@ -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 */
diff --git a/drivers/multiple/X/ginput_lld_mouse_config.h b/drivers/multiple/X/ginput_lld_mouse_config.h
deleted file mode 100644
index 8263ebed..00000000
--- a/drivers/multiple/X/ginput_lld_mouse_config.h
+++ /dev/null
@@ -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 */
diff --git a/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c b/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c
index 82c0e2ff..3b42bcda 100644
--- a/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c
+++ b/drivers/multiple/uGFXnet/gdisp_lld_uGFXnet.c
@@ -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);
+
+ // Can we handle it?
+ if (!newconnection(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) {
- // 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 */
diff --git a/gfxconf.example.h b/gfxconf.example.h
index 564c0c70..cea9bba7 100644
--- a/gfxconf.example.h
+++ b/gfxconf.example.h
@@ -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
diff --git a/src/ginput/driver_mouse.h b/src/ginput/driver_mouse.h
index 21d87dac..836ae1de 100644
--- a/src/ginput/driver_mouse.h
+++ b/src/ginput/driver_mouse.h
@@ -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
+ * @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.
*
- * @note For drivers that don't support returning a position
- * when the touch is up (most touch devices), it should
- * return the previous position with the new Z value.
- * The z value is the pressure for those touch devices
- * that support it (-100 to 100 where > 0 is touched)
- * or, 0 or 100 for those drivers that don't.
+ * @notapi
+ */
+ void _gmousePostInitDriver(GDriver *g);
+
+ /**
+ * @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 ginput_lld_mouse_get_reading(MouseReading *pt);
-
- #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
+ 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 */
/** @} */
diff --git a/src/ginput/ginput_ginput.c b/src/ginput/ginput_ginput.c
index 4197fa25..191ae025 100644
--- a/src/ginput/ginput_ginput.c
+++ b/src/ginput/ginput_ginput.c
@@ -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 */
diff --git a/src/ginput/ginput_mouse.c b/src/ginput/ginput_mouse.c
index a0daba98..570839a2 100644
--- a/src/ginput/ginput_mouse.c
+++ b/src/ginput/ginput_mouse.c
@@ -8,670 +8,815 @@
/**
* @file src/ginput/ginput_mouse.c
* @brief GINPUT mouse/touch code.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
*/
#include "gfx.h"
-#if (GFX_USE_GINPUT && GINPUT_NEED_MOUSE) || defined(__DOXYGEN__)
+#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+
+// Just to make code easier
+#if !GFX_USE_GDISP
+ #define GDISP 0
+#endif
+// Local Settings
+#define CALIBRATION_POLL_PERIOD 20 // milliseconds
+#define CALIBRATION_MINPRESS_PERIOD 300 // milliseconds
+#define CALIBRATION_MAXPRESS_PERIOD 5000 // milliseconds
+
+#define CALIBRATION_FONT "* Double"
+#define CALIBRATION_FONT2 "* Narrow"
+#define CALIBRATION_BACKGROUND Blue
+
+#define CALIBRATION_CROSS_COLOR1 White
+#define CALIBRATION_CROSS_COLOR2 RGB2COLOR(184,158,131)
+#define CALIBRATION_CROSS_INNERGAP 2
+#define CALIBRATION_CROSS_RADIUS 15
+
+#define CALIBRATION_TITLE "Calibration"
+#define CALIBRATION_TITLE_Y 5
+#define CALIBRATION_TITLE_HEIGHT 30
+#define CALIBRATION_TITLE_COLOR White
+#define CALIBRATION_TITLE_BACKGROUND Blue
+
+#define CALIBRATION_ERROR_TEXT "Calibration Failed!"
+#define CALIBRATION_ERROR_DELAY 3000
+#define CALIBRATION_ERROR_COLOR Red
+#define CALIBRATION_ERROR_BACKGROUND Yellow
+#define CALIBRATION_ERROR_Y 35
+#define CALIBRATION_ERROR_HEIGHT 40
+
+// Get the mouse driver interface
#include "driver_mouse.h"
-#if GINPUT_MOUSE_NEED_CALIBRATION
- #if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
- #error "GINPUT: GFX_USE_GDISP must be defined when mouse or touch calibration is required"
- #endif
+// The mouse poll timer
+static GTIMER_DECL(MouseTimer);
+// Calibration application
+#if !GINPUT_TOUCH_NOCALIBRATE
#include <string.h> // Required for memcpy
- #define GINPUT_MOUSE_CALIBRATION_FONT "* Double"
- #define GINPUT_MOUSE_CALIBRATION_FONT2 "* Narrow"
- #define GINPUT_MOUSE_CALIBRATION_TEXT "Calibration"
- #define GINPUT_MOUSE_CALIBRATION_ERROR_TEXT "Failed - Please try again!"
- #define GINPUT_MOUSE_CALIBRATION_SAME_TEXT "Error: Same Reading - Check Driver!"
+ static inline void CalibrationTransform(GMouseReading *pt, const GMouseCalibration *c) {
+ pt->x = (coord_t) (c->ax * pt->x + c->bx * pt->y + c->cx);
+ pt->y = (coord_t) (c->ay * pt->x + c->by * pt->y + c->cy);
+ }
+#endif
+
+static void SendMouseEvent(GSourceListener *psl, GMouse *m, GMouseReading *r) {
+ GEventMouse *pe;
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR < 0
- #define GINPUT_MOUSE_CALIBRATION_POINTS 3
+ // If there is no event buffer just mark a missed event
+ if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save the meta events that have happened
+ psl->srcflags |= ((r->buttons & GMETA_MASK)|GINPUT_MISSED_MOUSE_EVENT);
+ return;
+ }
+
+ // If we haven't really moved (and there are no meta events) don't bother sending the event
+ if (!(r->buttons & GMETA_MASK) && !psl->srcflags && !(psl->listenflags & GLISTEN_MOUSENOFILTER)
+ && r->x == m->r.x && r->y == m->r.y && (r->buttons & GINPUT_MOUSE_BTN_MASK) == (m->r.buttons & GINPUT_MOUSE_BTN_MASK))
+ return;
+
+ // Send the event only if we are listening for it
+ if (!((r->buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
+ && !(!(r->buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
+ && !((r->buttons & GMETA_MASK) && (psl->listenflags & GLISTEN_MOUSEMETA)))
+ return;
+
+ #if !GINPUT_TOUCH_NOTOUCH
+ pe->type = (gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH) ? GEVENT_TOUCH : GEVENT_MOUSE;
#else
- #define GINPUT_MOUSE_CALIBRATION_POINTS 4
+ pe->type = GEVENT_MOUSE;
#endif
+ pe->x = r->x;
+ pe->y = r->y;
+ pe->z = r->z;
+ pe->buttons = r->buttons | psl->srcflags;
+ psl->srcflags = 0;
+ pe->display = m->display;
+ geventSendEvent(psl);
+}
- typedef struct Calibration_t {
- float ax;
- float bx;
- float cx;
- float ay;
- float by;
- float cy;
- } Calibration;
-#endif
+static void GetMouseReading(GMouse *m) {
+ GMouseReading r;
-typedef struct MousePoint_t {
- coord_t x, y;
-} MousePoint;
+ // Step 1 - Get the Raw Reading
+ {
+ m->flags &= ~GMOUSE_FLG_NEEDREAD;
+ if (!gmvmt(m)->get(m, &r))
+ return;
+ }
-static GTIMER_DECL(MouseTimer);
+ // Step 2 - Handle touch and button 0 debouncing
+ {
+ // Clean off button garbage
+ r.buttons &= GINPUT_MOUSE_BTN_MASK;
+
+ #if !GINPUT_TOUCH_NOTOUCH
+ // If touch then calculate button 0 from z
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH)) {
+ if (gmvmt(m)->z_min <= gmvmt(m)->z_max) {
+ if (r.z >= gmvmt(m)->z_touchon) r.buttons |= GINPUT_MOUSE_BTN_LEFT;
+ else if (r.z <= gmvmt(m)->z_touchoff) r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
+ else return; // bad transitional reading
+ } else {
+ if (r.z <= gmvmt(m)->z_touchon) r.buttons |= GINPUT_MOUSE_BTN_LEFT;
+ else if (r.z >= gmvmt(m)->z_touchoff) r.buttons &= ~GINPUT_MOUSE_BTN_LEFT;
+ else return; // bad transitional reading
+ }
+ }
-static struct MouseConfig_t {
- MouseReading t;
- MousePoint movepos;
- MousePoint clickpos;
- systemticks_t clicktime;
- uint16_t last_buttons;
- uint16_t flags;
- #define FLG_INIT_DONE 0x8000
- #define FLG_CLICK_TIMER 0x0001
- #define FLG_IN_CAL 0x0010
- #define FLG_CAL_OK 0x0020
- #define FLG_CAL_SAVED 0x0040
- #define FLG_CAL_FREE 0x0080
- #define FLG_CAL_RAW 0x0100
- #if GINPUT_MOUSE_NEED_CALIBRATION
- GMouseCalibrationSaveRoutine fnsavecal;
- GMouseCalibrationLoadRoutine fnloadcal;
- Calibration caldata;
- #endif
- GDisplay * display;
-} MouseConfig;
-
-void _tsOrientClip(MouseReading *pt, GDisplay *g, bool_t doClip) {
- coord_t w, h;
-
- w = gdispGGetWidth(g);
- h = gdispGGetHeight(g);
-
- #if GDISP_NEED_CONTROL && !GINPUT_MOUSE_NO_ROTATION
- switch(gdispGGetOrientation(g)) {
- case GDISP_ROTATE_0:
- break;
- case GDISP_ROTATE_90:
- {
- coord_t t = pt->x;
- pt->x = w - 1 - pt->y;
- pt->y = t;
+ // Devices with poor button 0 transitioning need debouncing
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_POORUPDOWN)) {
+ // Are we in a transition test
+ if ((m->flags & GMOUSE_FLG_INDELTA)) {
+ if (!((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
+ // Transition failed
+ m->flags &= ~GMOUSE_FLG_INDELTA;
+ return;
+ }
+ // Transition succeeded
+ m->flags &= ~GMOUSE_FLG_INDELTA;
+
+ // Should we start a transition test
+ } else if (((r.buttons ^ m->r.buttons) & GINPUT_MOUSE_BTN_LEFT)) {
+ m->flags |= GMOUSE_FLG_INDELTA;
+ return;
}
- break;
- case GDISP_ROTATE_180:
- pt->x = w - 1 - pt->x;
- pt->y = h - 1 - pt->y;
- break;
- case GDISP_ROTATE_270:
- {
- coord_t t = pt->y;
- pt->y = h - 1 - pt->x;
- pt->x = t;
+ }
+ #endif
+
+ #if !GINPUT_TOUCH_NOCALIBRATE_GUI
+ // Stop here with just the raw x,y reading during calibration
+ if ((m->flags & GMOUSE_FLG_IN_CAL)) {
+ if ((r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
+ m->r.x = r.x;
+ m->r.y = r.y;
}
- break;
- default:
- break;
+ m->r.buttons = r.buttons;
+ return;
+ }
+ #endif
+ }
+
+ // Step 3 - Apply calibration, rotation and display clipping
+ {
+ // If the mouse is up we may need to keep our previous position
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_ONLY_DOWN) && !(r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
+ r.x = m->r.x;
+ r.y = m->r.y;
+
+ } else {
+
+ #if !GINPUT_TOUCH_NOCALIBRATE
+ // Do we need to calibrate the reading?
+ if ((m->flags & GMOUSE_FLG_CALIBRATE))
+ CalibrationTransform(&r, &m->caldata);
+ #endif
+
+ // We can't clip or rotate if we don't have a display
+ if (m->display) {
+ coord_t w, h;
+
+ // We now need display information
+ w = gdispGGetWidth(m->display);
+ h = gdispGGetHeight(m->display);
+
+ #if GDISP_NEED_CONTROL
+ // Do we need to rotate the reading to match the display
+ if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
+ coord_t t;
+
+ switch(gdispGGetOrientation(m->display)) {
+ case GDISP_ROTATE_0:
+ break;
+ case GDISP_ROTATE_90:
+ t = r.x;
+ r.x = w - 1 - r.y;
+ r.y = t;
+ break;
+ case GDISP_ROTATE_180:
+ r.x = w - 1 - r.x;
+ r.y = h - 1 - r.y;
+ break;
+ case GDISP_ROTATE_270:
+ t = r.y;
+ r.y = h - 1 - r.x;
+ r.x = t;
+ break;
+ default:
+ break;
+ }
+ }
+ #endif
+
+ // Do we need to clip the reading to the display
+ if ((m->flags & GMOUSE_FLG_CLIP)) {
+ if (r.x < 0) r.x = 0;
+ else if (r.x >= w) r.x = w-1;
+ if (r.y < 0) r.y = 0;
+ else if (r.y >= h) r.y = h-1;
+ }
+ }
}
- #endif
+ }
- if (doClip) {
- if (pt->x < 0) pt->x = 0;
- else if (pt->x >= w) pt->x = w-1;
- if (pt->y < 0) pt->y = 0;
- else if (pt->y >= h) pt->y = h-1;
+ // Step 4 - Apply jitter detection
+ #if !GINPUT_TOUCH_NOTOUCH
+ {
+ const GMouseJitter *pj;
+ uint32_t diff;
+
+ // Are we in pen or finger mode
+ pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter;
+
+ // Is this just movement jitter
+ if (pj->move > 0) {
+ diff = (uint32_t)(r.x - m->r.x) * (uint32_t)(r.x - m->r.x) + (uint32_t)(r.y - m->r.y) * (uint32_t)(r.y - m->r.y);
+ if (diff < (uint32_t)pj->move * (uint32_t)pj->move) {
+ r.x = m->r.x;
+ r.y = m->r.y;
+ }
+ }
+
+ // Check if the click has moved outside the click area and if so cancel the click
+ if (pj->click > 0 && (m->flags & GMOUSE_FLG_CLICK_TIMER)) {
+ diff = (uint32_t)(r.x - m->clickpos.x) * (uint32_t)(r.x - m->clickpos.x) + (uint32_t)(r.y - m->clickpos.y) * (uint32_t)(r.y - m->clickpos.y);
+ if (diff > (uint32_t)pj->click * (uint32_t)pj->click)
+ m->flags &= ~GMOUSE_FLG_CLICK_TIMER;
+ }
}
-}
+ #endif
+
+ // Step 5 - Click, context-click and other meta event detection
+ {
+ uint16_t upbtns, dnbtns;
+
+ // Calculate button transitions
+ dnbtns = r.buttons & ~m->r.buttons;
+ upbtns = ~r.buttons & m->r.buttons;
-#if GINPUT_MOUSE_NEED_CALIBRATION
- static inline void _tsSetIdentity(Calibration *c) {
- c->ax = 1;
- c->bx = 0;
- c->cx = 0;
- c->ay = 0;
- c->by = 1;
- c->cy = 0;
+ // Left mouse down generates the Mouse-down meta event
+ if ((dnbtns & GINPUT_MOUSE_BTN_LEFT))
+ r.buttons |= GMETA_MOUSE_DOWN;
+
+ // Left mouse up generates the Mouse-up meta event
+ if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
+ r.buttons |= GMETA_MOUSE_UP;
+
+ // Left/Right mouse down starts the click timer
+ if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
+ m->clickpos.x = r.x;
+ m->clickpos.y = r.y;
+ m->clicktime = gfxSystemTicks();
+ m->flags |= GMOUSE_FLG_CLICK_TIMER;
+ }
+
+ // Left/Right mouse up with the click timer still running may generate a click or context click
+ if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT)) && (m->flags & GMOUSE_FLG_CLICK_TIMER)) {
+ m->flags &= ~GMOUSE_FLG_CLICK_TIMER;
+ m->clicktime = gfxSystemTicks() - m->clicktime;
+
+ // Was this a short click?
+ if (m->clicktime <= gfxMillisecondsToTicks(GINPUT_MOUSE_CLICK_TIME)) {
+ if ((upbtns & GINPUT_MOUSE_BTN_RIGHT))
+ r.buttons |= GMETA_MOUSE_CXTCLICK;
+ if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
+ r.buttons |= GMETA_MOUSE_CLICK;
+ }
+
+ #if !GINPUT_TOUCH_NOTOUCH
+ // Was this a long click on a touch device?
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH) && m->clicktime >= gfxMillisecondsToTicks(GINPUT_TOUCH_CXTCLICK_TIME))
+ r.buttons |= GMETA_MOUSE_CXTCLICK;
+ #endif
+ }
}
- static inline void _tsDrawCross(const MousePoint *pp) {
- gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y, pp->x-2, pp->y, White);
- gdispGDrawLine(MouseConfig.display, pp->x+2, pp->y, pp->x+15, pp->y, White);
- gdispGDrawLine(MouseConfig.display, pp->x, pp->y-15, pp->x, pp->y-2, White);
- gdispGDrawLine(MouseConfig.display, pp->x, pp->y+2, pp->x, pp->y+15, White);
+ // Step 6 - Send the event to the listeners that are interested.
+ {
+ GSourceListener *psl;
- gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131));
- gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131));
+ // Send to the "All Mice" source listeners
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)&MouseTimer, psl)))
+ SendMouseEvent(psl, m, &r);
- gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131));
- gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131));
+ // Send to the mouse specific source listeners
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)m, psl)))
+ SendMouseEvent(psl, m, &r);
+ }
- gdispGDrawLine(MouseConfig.display, pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
- gdispGDrawLine(MouseConfig.display, pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131));
+ // Step 7 - Finally save the results
+ m->r.x = r.x;
+ m->r.y = r.y;
+ m->r.z = r.z;
+ m->r.buttons = r.buttons;
+}
- gdispGDrawLine(MouseConfig.display, pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131));
- gdispGDrawLine(MouseConfig.display, pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131));
+static void MousePoll(void *param) {
+ GMouse * m;
+ (void) param;
+
+ for(m = (GMouse *)gdriverGetNext(GDRIVER_TYPE_MOUSE, 0); m; m = (GMouse *)gdriverGetNext(GDRIVER_TYPE_MOUSE, (GDriver *)m)) {
+ if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_NOPOLL) || (m->flags & GMOUSE_FLG_NEEDREAD))
+ GetMouseReading(m);
}
+}
- static inline void _tsClearCross(const MousePoint *pp) {
- gdispGFillArea(MouseConfig.display, pp->x - 15, pp->y - 15, 42, 42, Blue);
+// Calibration user interface
+#if !GINPUT_TOUCH_NOCALIBRATE_GUI
+ #if !defined(GFX_USE_GDISP) || !GFX_USE_GDISP
+ #error "GINPUT: GFX_USE_GDISP must be defined when calibration is required"
+ #endif
+
+ static inline void CalibrationCrossDraw(GMouse *m, const point *pp) {
+ gdispGDrawLine(m->display, pp->x-CALIBRATION_CROSS_RADIUS, pp->y, pp->x-CALIBRATION_CROSS_INNERGAP, pp->y, CALIBRATION_CROSS_COLOR1);
+ gdispGDrawLine(m->display, pp->x+CALIBRATION_CROSS_INNERGAP, pp->y, pp->x+CALIBRATION_CROSS_RADIUS, pp->y, CALIBRATION_CROSS_COLOR1);
+ gdispGDrawLine(m->display, pp->x, pp->y-CALIBRATION_CROSS_RADIUS, pp->x, pp->y-CALIBRATION_CROSS_INNERGAP, CALIBRATION_CROSS_COLOR1);
+ gdispGDrawLine(m->display, pp->x, pp->y+CALIBRATION_CROSS_INNERGAP, pp->x, pp->y+CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR1);
+ gdispGDrawLine(m->display, pp->x-CALIBRATION_CROSS_RADIUS, pp->y+CALIBRATION_CROSS_RADIUS, pp->x-CALIBRATION_CROSS_RADIUS/2, pp->y+CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x-CALIBRATION_CROSS_RADIUS, pp->y+CALIBRATION_CROSS_RADIUS/2, pp->x-CALIBRATION_CROSS_RADIUS, pp->y+CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x-CALIBRATION_CROSS_RADIUS, pp->y-CALIBRATION_CROSS_RADIUS, pp->x-CALIBRATION_CROSS_RADIUS/2, pp->y-CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x-CALIBRATION_CROSS_RADIUS, pp->y-CALIBRATION_CROSS_RADIUS/2, pp->x-CALIBRATION_CROSS_RADIUS, pp->y-CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x+CALIBRATION_CROSS_RADIUS/2, pp->y+CALIBRATION_CROSS_RADIUS, pp->x+CALIBRATION_CROSS_RADIUS, pp->y+CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x+CALIBRATION_CROSS_RADIUS, pp->y+CALIBRATION_CROSS_RADIUS/2, pp->x+CALIBRATION_CROSS_RADIUS, pp->y+CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x+CALIBRATION_CROSS_RADIUS/2, pp->y-CALIBRATION_CROSS_RADIUS, pp->x+CALIBRATION_CROSS_RADIUS, pp->y-CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_COLOR2);
+ gdispGDrawLine(m->display, pp->x+CALIBRATION_CROSS_RADIUS, pp->y-CALIBRATION_CROSS_RADIUS, pp->x+CALIBRATION_CROSS_RADIUS, pp->y-CALIBRATION_CROSS_RADIUS/2, CALIBRATION_CROSS_COLOR2);
}
- static inline void _tsTransform(MouseReading *pt, const Calibration *c) {
- pt->x = (coord_t) (c->ax * pt->x + c->bx * pt->y + c->cx);
- pt->y = (coord_t) (c->ay * pt->x + c->by * pt->y + c->cy);
+ static inline void CalibrationCrossClear(GMouse *m, const point *pp) {
+ gdispGFillArea(m->display, pp->x - CALIBRATION_CROSS_RADIUS, pp->y - CALIBRATION_CROSS_RADIUS, CALIBRATION_CROSS_RADIUS*2+1, CALIBRATION_CROSS_RADIUS*2+1, CALIBRATION_BACKGROUND);
}
- static inline void _tsDo3PointCalibration(const MousePoint *cross, const MousePoint *points, GDisplay *g, Calibration *c) {
+ static inline void CalibrationCalculate(GMouse *m, const point *cross, const point *points) {
float dx;
coord_t c0, c1, c2;
+ (void) m;
+
+ // Work on x values
+ c0 = cross[0].x;
+ c1 = cross[1].x;
+ c2 = cross[2].x;
#if GDISP_NEED_CONTROL
- /* Convert all cross points back to GDISP_ROTATE_0 convention
- * before calculating the calibration matrix.
- */
- switch(gdispGGetOrientation(g)) {
- case GDISP_ROTATE_90:
- c0 = cross[0].y;
- c1 = cross[1].y;
- c2 = cross[2].y;
- break;
- case GDISP_ROTATE_180:
- c0 = c1 = c2 = gdispGGetWidth(g) - 1;
- c0 -= cross[0].x;
- c1 -= cross[1].x;
- c2 -= cross[2].x;
- break;
- case GDISP_ROTATE_270:
- c0 = c1 = c2 = gdispGGetHeight(g) - 1;
- c0 -= cross[0].y;
- c1 -= cross[1].y;
- c2 -= cross[2].y;
- break;
- case GDISP_ROTATE_0:
- default:
- c0 = cross[0].x;
- c1 = cross[1].x;
- c2 = cross[2].x;
- break;
+ if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
+ /* Convert all cross points back to GDISP_ROTATE_0 convention
+ * before calculating the calibration matrix.
+ */
+ switch(gdispGGetOrientation(m->display)) {
+ case GDISP_ROTATE_90:
+ c0 = cross[0].y;
+ c1 = cross[1].y;
+ c2 = cross[2].y;
+ break;
+ case GDISP_ROTATE_180:
+ c0 = c1 = c2 = gdispGGetWidth(m->display) - 1;
+ c0 -= cross[0].x;
+ c1 -= cross[1].x;
+ c2 -= cross[2].x;
+ break;
+ case GDISP_ROTATE_270:
+ c0 = c1 = c2 = gdispGGetHeight(m->display) - 1;
+ c0 -= cross[0].y;
+ c1 -= cross[1].y;
+ c2 -= cross[2].y;
+ break;
+ default:
+ break;
+ }
}
- #else
- (void) g;
-
- c0 = cross[0].x;
- c1 = cross[1].x;
- c2 = cross[2].x;
#endif
/* Compute all the required determinants */
dx = (float)(points[0].x - points[2].x) * (float)(points[1].y - points[2].y)
- (float)(points[1].x - points[2].x) * (float)(points[0].y - points[2].y);
- c->ax = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
- - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
- c->bx = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
- - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
- c->cx = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
- - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
- + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;
+ m->caldata.ax = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
+ - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
+ m->caldata.bx = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
+ - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
+ m->caldata.cx = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
+ - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
+ + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;
+
+ // Work on y values
+ c0 = cross[0].y;
+ c1 = cross[1].y;
+ c2 = cross[2].y;
#if GDISP_NEED_CONTROL
- switch(gdispGGetOrientation(g)) {
- case GDISP_ROTATE_90:
- c0 = c1 = c2 = gdispGGetWidth(g) - 1;
- c0 -= cross[0].x;
- c1 -= cross[1].x;
- c2 -= cross[2].x;
- break;
- case GDISP_ROTATE_180:
- c0 = c1 = c2 = gdispGGetHeight(g) - 1;
- c0 -= cross[0].y;
- c1 -= cross[1].y;
- c2 -= cross[2].y;
- break;
- case GDISP_ROTATE_270:
- c0 = cross[0].x;
- c1 = cross[1].x;
- c2 = cross[2].x;
- break;
- case GDISP_ROTATE_0:
- default:
- c0 = cross[0].y;
- c1 = cross[1].y;
- c2 = cross[2].y;
- break;
+ if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
+ switch(gdispGGetOrientation(m->display)) {
+ case GDISP_ROTATE_90:
+ c0 = c1 = c2 = gdispGGetWidth(m->display) - 1;
+ c0 -= cross[0].x;
+ c1 -= cross[1].x;
+ c2 -= cross[2].x;
+ break;
+ case GDISP_ROTATE_180:
+ c0 = c1 = c2 = gdispGGetHeight(m->display) - 1;
+ c0 -= cross[0].y;
+ c1 -= cross[1].y;
+ c2 -= cross[2].y;
+ break;
+ case GDISP_ROTATE_270:
+ c0 = cross[0].x;
+ c1 = cross[1].x;
+ c2 = cross[2].x;
+ break;
+ default:
+ break;
+ }
}
- #else
- c0 = cross[0].y;
- c1 = cross[1].y;
- c2 = cross[2].y;
#endif
- c->ay = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
- - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
- c->by = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
- - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
- c->cy = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
- - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
- + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;
- }
-#endif
-
-#if GINPUT_MOUSE_READ_CYCLES > 1
- static void get_raw_reading(MouseReading *pt) {
- int32_t x, y, z;
- unsigned i;
-
- x = y = z = 0;
- for(i = 0; i < GINPUT_MOUSE_READ_CYCLES; i++) {
- ginput_lld_mouse_get_reading(pt);
- x += pt->x;
- y += pt->y;
- z += pt->z;
- }
-
- /* Take the average of the readings */
- pt->x = x / GINPUT_MOUSE_READ_CYCLES;
- pt->y = y / GINPUT_MOUSE_READ_CYCLES;
- pt->z = z / GINPUT_MOUSE_READ_CYCLES;
+ m->caldata.ay = ((float)(c0 - c2) * (float)(points[1].y - points[2].y)
+ - (float)(c1 - c2) * (float)(points[0].y - points[2].y)) / dx;
+ m->caldata.by = ((float)(c1 - c2) * (float)(points[0].x - points[2].x)
+ - (float)(c0 - c2) * (float)(points[1].x - points[2].x)) / dx;
+ m->caldata.cy = (c0 * ((float)points[1].x * (float)points[2].y - (float)points[2].x * (float)points[1].y)
+ - c1 * ((float)points[0].x * (float)points[2].y - (float)points[2].x * (float)points[0].y)
+ + c2 * ((float)points[0].x * (float)points[1].y - (float)points[1].x * (float)points[0].y)) / dx;
}
-#else
- #define get_raw_reading(pt) ginput_lld_mouse_get_reading(pt)
-#endif
-
-static void get_calibrated_reading(MouseReading *pt) {
- get_raw_reading(pt);
- #if GINPUT_MOUSE_NEED_CALIBRATION
- _tsTransform(pt, &MouseConfig.caldata);
- #endif
+ static uint32_t CalibrateMouse(GMouse *m) {
+ coord_t w, h;
+ point cross[4]; // The locations of the test points on the display
+ point points[4]; // The x, y readings obtained from the mouse for each test point
+ uint32_t err;
+ #if GDISP_NEED_TEXT
+ font_t font1, font2;
+ #endif
- _tsOrientClip(pt, MouseConfig.display, !(MouseConfig.flags & FLG_CAL_RAW));
-}
+ #if GDISP_NEED_TEXT
+ font1 = gdispOpenFont(CALIBRATION_FONT);
+ if (!font1) font1 = gdispOpenFont("*");
+ font2 = gdispOpenFont(CALIBRATION_FONT2);
+ if (!font2) font2 = gdispOpenFont("*");
+ #endif
+ err = 0;
+ w = gdispGGetWidth(m->display);
+ h = gdispGGetHeight(m->display);
+ #if GDISP_NEED_CLIP
+ gdispGSetClip(m->display, 0, 0, w, h);
+ #endif
-static void MousePoll(void *param) {
- (void) param;
- GSourceListener *psl;
- GEventMouse *pe;
- unsigned meta;
- uint16_t upbtns, dnbtns;
- uint32_t cdiff;
- uint32_t mdiff;
-
- // Save the last mouse state
- MouseConfig.last_buttons = MouseConfig.t.buttons;
-
- // Get the new mouse reading
- get_calibrated_reading(&MouseConfig.t);
-
- // Calculate out new event meta value and handle CLICK and CXTCLICK
- dnbtns = MouseConfig.t.buttons & ~MouseConfig.last_buttons;
- upbtns = ~MouseConfig.t.buttons & MouseConfig.last_buttons;
- meta = GMETA_NONE;
-
- // As the touch moves up we need to return a point at the old position because some
- // controllers return garbage with the mouse up
- if ((upbtns & GINPUT_MOUSE_BTN_LEFT)) {
- MouseConfig.t.x = MouseConfig.movepos.x;
- MouseConfig.t.y = MouseConfig.movepos.y;
- }
+ // Ensure we get minimaly processed readings for the calibration
+ m->flags |= GMOUSE_FLG_IN_CAL;
+
+ // Set up our calibration locations
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_EXTREMES)) {
+ cross[0].x = 0; cross[0].y = 0;
+ cross[1].x = w-1; cross[1].y = 0;
+ cross[2].x = w-1; cross[2].y = h-1;
+ cross[3].x = w/2; cross[3].y = h/2;
+ } else {
+ cross[0].x = w/4; cross[0].y = h/4;
+ cross[1].x = w-w/4; cross[1].y = h/4;
+ cross[2].x = w-w/4; cross[2].y = h-h/4;
+ cross[3].x = w/2; cross[3].y = h/2;
+ }
+
+ // Set up the calibration display
+ gdispGClear(m->display, Blue);
+ #if GDISP_NEED_TEXT
+ gdispGFillStringBox(m->display,
+ 0, CALIBRATION_TITLE_Y, w, CALIBRATION_TITLE_HEIGHT,
+ CALIBRATION_TITLE, font1, CALIBRATION_TITLE_COLOR, CALIBRATION_TITLE_BACKGROUND,
+ justifyCenter);
+ #endif
- // Calculate the position difference from our movement reference (update the reference if out of range)
- mdiff = (MouseConfig.t.x - MouseConfig.movepos.x) * (MouseConfig.t.x - MouseConfig.movepos.x) +
- (MouseConfig.t.y - MouseConfig.movepos.y) * (MouseConfig.t.y - MouseConfig.movepos.y);
- if (mdiff > GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER) {
- MouseConfig.movepos.x = MouseConfig.t.x;
- MouseConfig.movepos.y = MouseConfig.t.y;
- }
-
- // Check if the click has moved outside the click area and if so cancel the click
- if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
- cdiff = (MouseConfig.t.x - MouseConfig.clickpos.x) * (MouseConfig.t.x - MouseConfig.clickpos.x) +
- (MouseConfig.t.y - MouseConfig.clickpos.y) * (MouseConfig.t.y - MouseConfig.clickpos.y);
- if (cdiff > GINPUT_MOUSE_MAX_CLICK_JITTER * GINPUT_MOUSE_MAX_CLICK_JITTER)
- MouseConfig.flags &= ~FLG_CLICK_TIMER;
- }
+ // Calculate the calibration
+ {
+ unsigned i, maxpoints;
+
+ maxpoints = (gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_TEST) ? 4 : 3;
+
+ // Loop through the calibration points
+ for(i = 0; i < maxpoints; i++) {
+ int32_t px, py;
+ unsigned j;
+
+ // Draw the current calibration point
+ CalibrationCrossDraw(m, &cross[i]);
+
+ // Get a valid "point pressed" average reading
+ do {
+ // Wait for the mouse to be pressed
+ while(!(m->r.buttons & GINPUT_MOUSE_BTN_LEFT))
+ gfxSleepMilliseconds(CALIBRATION_POLL_PERIOD);
+
+ // Sum samples taken every CALIBRATION_POLL_PERIOD milliseconds while the mouse is down
+ px = py = j = 0;
+ while((m->r.buttons & GINPUT_MOUSE_BTN_LEFT)) {
+ // Limit sampling period to prevent overflow
+ if (j < CALIBRATION_MAXPRESS_PERIOD/CALIBRATION_POLL_PERIOD) {
+ px += m->r.x;
+ py += m->r.y;
+ j++;
+ }
+ gfxSleepMilliseconds(CALIBRATION_POLL_PERIOD);
+ }
- // Mouse down
- if ((dnbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
- MouseConfig.clickpos.x = MouseConfig.t.x;
- MouseConfig.clickpos.y = MouseConfig.t.y;
- MouseConfig.clicktime = gfxSystemTicks();
- MouseConfig.flags |= FLG_CLICK_TIMER;
- if ((dnbtns & GINPUT_MOUSE_BTN_LEFT))
- meta |= GMETA_MOUSE_DOWN;
- }
+ // Ignore presses less than CALIBRATION_MAXPRESS_PERIOD milliseconds
+ } while(j < CALIBRATION_MINPRESS_PERIOD/CALIBRATION_POLL_PERIOD);
+ points[i].x = px / j;
+ points[i].y = py / j;
- // Mouse up
- if ((upbtns & (GINPUT_MOUSE_BTN_LEFT|GINPUT_MOUSE_BTN_RIGHT))) {
- if ((upbtns & GINPUT_MOUSE_BTN_LEFT))
- meta |= GMETA_MOUSE_UP;
- if ((MouseConfig.flags & FLG_CLICK_TIMER)) {
- if ((upbtns & GINPUT_MOUSE_BTN_LEFT)
- #if GINPUT_MOUSE_CLICK_TIME != TIME_INFINITE
- && gfxSystemTicks() - MouseConfig.clicktime < gfxMillisecondsToTicks(GINPUT_MOUSE_CLICK_TIME)
- #endif
- )
- meta |= GMETA_MOUSE_CLICK;
- else
- meta |= GMETA_MOUSE_CXTCLICK;
- MouseConfig.flags &= ~FLG_CLICK_TIMER;
+ // Clear the current calibration point
+ CalibrationCrossClear(m, &cross[i]);
+ }
}
- }
- // Send the event to the listeners that are interested.
- psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)(&MouseConfig), psl))) {
- if (!(pe = (GEventMouse *)geventGetEventBuffer(psl))) {
- // This listener is missing - save the meta events that have happened
- psl->srcflags |= meta;
- continue;
- }
+ // Apply 3 point calibration algorithm
+ CalibrationCalculate(m, cross, points);
+
+ /* Verification of correctness of calibration (optional) :
+ * See if the 4th point (Middle of the screen) coincides with the calibrated
+ * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
+ * Else return the error.
+ */
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_TEST)) {
+ const GMouseJitter *pj;
+
+ // Are we in pen or finger mode
+ pj = (m->flags & GMOUSE_FLG_FINGERMODE) ? &gmvmt(m)->finger_jitter : &gmvmt(m)->pen_jitter;
+
+ // Transform the co-ordinates
+ CalibrationTransform((GMouseReading *)&points[3], &m->caldata);
+
+ // Do we need to rotate the reading to match the display
+ #if GDISP_NEED_CONTROL
+ if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_SELFROTATION)) {
+ coord_t t;
+
+ switch(gdispGGetOrientation(m->display)) {
+ case GDISP_ROTATE_0:
+ break;
+ case GDISP_ROTATE_90:
+ t = points[3].x;
+ points[3].x = w - 1 - points[3].y;
+ points[3].y = t;
+ break;
+ case GDISP_ROTATE_180:
+ points[3].x = w - 1 - points[3].x;
+ points[3].y = h - 1 - points[3].y;
+ break;
+ case GDISP_ROTATE_270:
+ t = points[3].y;
+ points[3].y = h - 1 - points[3].x;
+ points[3].x = t;
+ break;
+ default:
+ break;
+ }
+ }
+ #endif
- // If we haven't really moved (and there are no meta events) don't bother sending the event
- if (mdiff <= GINPUT_MOUSE_MAX_MOVE_JITTER * GINPUT_MOUSE_MAX_MOVE_JITTER && !psl->srcflags
- && !meta && MouseConfig.last_buttons == MouseConfig.t.buttons && !(psl->listenflags & GLISTEN_MOUSENOFILTER))
- continue;
-
- // Send the event if we are listening for it
- if (((MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEDOWNMOVES))
- || (!(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT) && (psl->listenflags & GLISTEN_MOUSEUPMOVES))
- || (meta && (psl->listenflags & GLISTEN_MOUSEMETA))) {
- pe->type = GINPUT_MOUSE_EVENT_TYPE;
- pe->instance = 0;
- pe->x = MouseConfig.t.x;
- pe->y = MouseConfig.t.y;
- pe->z = MouseConfig.t.z;
- pe->current_buttons = MouseConfig.t.buttons;
- pe->last_buttons = MouseConfig.last_buttons;
- pe->meta = meta;
- if (psl->srcflags) {
- pe->current_buttons |= GINPUT_MISSED_MOUSE_EVENT;
- pe->meta |= psl->srcflags;
- psl->srcflags = 0;
- }
- pe->display = MouseConfig.display;
- geventSendEvent(psl);
+ // Is this accurate enough?
+ err = (points[3].x - cross[3].x) * (points[3].x - cross[3].x) + (points[3].y - cross[3].y) * (points[3].y - cross[3].y);
+ if (err > (uint32_t)pj->calibrate * (uint32_t)pj->calibrate) {
+ #if GDISP_NEED_TEXT
+ // No - Display error and return
+ gdispGFillStringBox(m->display,
+ 0, CALIBRATION_ERROR_Y, w, CALIBRATION_ERROR_HEIGHT,
+ CALIBRATION_ERROR_TEXT, font2, CALIBRATION_ERROR_COLOR, CALIBRATION_ERROR_BACKGROUND,
+ justifyCenter);
+ gfxSleepMilliseconds(CALIBRATION_ERROR_DELAY);
+ #endif
+ } else
+ err = 0;
}
- }
-}
-GSourceHandle ginputGetMouse(uint16_t instance) {
- #if GINPUT_MOUSE_NEED_CALIBRATION
- Calibration *pc;
- #endif
+ // We are done calibrating
+ #if GDISP_NEED_TEXT
+ gdispCloseFont(font1);
+ gdispCloseFont(font2);
+ #endif
+ m->flags &= ~GMOUSE_FLG_IN_CAL;
+ m->flags |= GMOUSE_FLG_CLIP;
- // We only support a single mouse instance currently
- // Instance 9999 is the same as instance 0 except that it installs
- // a special "raw" calibration if there isn't one we can load.
- if (instance && instance != 9999)
- return 0;
+ // Save the calibration data (if possible)
+ if (!err) {
+ m->flags |= GMOUSE_FLG_CALIBRATE;
- // Make sure we have a valid mouse display
- if (!MouseConfig.display)
- MouseConfig.display = GDISP;
+ #if GINPUT_TOUCH_USER_CALIBRATION_SAVE
+ SaveMouseCalibration(gdriverGetDriverInstanceNumber((GDriver *)m), &m->caldata, sizeof(GMouseCalibration));
+ #endif
+ if (gmvmt(m)->calsave)
+ gmvmt(m)->calsave(m, &m->caldata, sizeof(GMouseCalibration));
+ }
- // Do we need to initialise the mouse subsystem?
- if (!(MouseConfig.flags & FLG_INIT_DONE)) {
- ginput_lld_mouse_init();
+ // Force an initial reading
+ m->r.buttons = 0;
+ GetMouseReading(m);
- #if GINPUT_MOUSE_NEED_CALIBRATION
- #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
- if (!MouseConfig.fnloadcal) {
- MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
- MouseConfig.flags &= ~FLG_CAL_FREE;
- }
- if (!MouseConfig.fnsavecal)
- MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
- #endif
- if (MouseConfig.fnloadcal && (pc = (Calibration *)MouseConfig.fnloadcal(instance))) {
- memcpy(&MouseConfig.caldata, pc, sizeof(MouseConfig.caldata));
- MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED);
- if ((MouseConfig.flags & FLG_CAL_FREE))
- gfxFree((void *)pc);
- } else if (instance == 9999) {
- _tsSetIdentity(&MouseConfig.caldata);
- MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW);
- } else
- ginputCalibrateMouse(instance);
+ // Clear the screen using the GWIN default background color
+ #if GFX_USE_GWIN
+ gdispGClear(m->display, gwinGetDefaultBgColor());
+ #else
+ gdispGClear(m->display, GDISP_STARTUP_COLOR);
#endif
- // Get the first reading
- MouseConfig.last_buttons = 0;
- get_calibrated_reading(&MouseConfig.t);
-
- // Mark init as done and start the Poll timer
- MouseConfig.flags |= FLG_INIT_DONE;
- gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
+ return err;
}
+#endif
- // Return our structure as the handle
- return (GSourceHandle)&MouseConfig;
-}
+void _gmouseInit(void) {
+ // GINPUT_MOUSE_DRIVER_LIST is defined - create each driver instance
+ #if defined(GINPUT_MOUSE_DRIVER_LIST)
+ {
+ int i;
-void ginputSetMouseDisplay(uint16_t instance, GDisplay *g) {
- if (instance)
- return;
+ extern GDriverVMTList GINPUT_MOUSE_DRIVER_LIST;
+ static const struct GDriverVMT const * dclist[] = {GINPUT_MOUSE_DRIVER_LIST};
- MouseConfig.display = g ? g : GDISP;
-}
+ for(i = 0; i < sizeof(dclist)/sizeof(dclist[0]); i++) {
+ if (!(dclist[i]->flags & GMOUSE_VFLG_DYNAMICONLY))
+ gdriverRegister(dclist[i], GDISP);
+ }
+ }
-GDisplay *ginputGetMouseDisplay(uint16_t instance) {
- if (instance)
- return 0;
+ // One and only one mouse
+ #else
+ {
+ extern GDriverVMTList GMOUSEVMT_OnlyOne;
+
+ if (!(GMOUSEVMT_OnlyOne->flags & GMOUSE_VFLG_DYNAMICONLY))
+ gdriverRegister(GMOUSEVMT_OnlyOne, GDISP);
+ }
+ #endif
- return MouseConfig.display;
}
-bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {
- // Win32 threads don't seem to recognise priority and/or pre-emption
- // so we add a sleep here to prevent 100% polled applications from locking up.
- gfxSleepMilliseconds(1);
+void _gmouseDeinit(void) {
+ gtimerDeinit(&MouseTimer);
+}
- if (instance || (MouseConfig.flags & (FLG_INIT_DONE|FLG_IN_CAL)) != FLG_INIT_DONE)
- return FALSE;
+bool_t _gmouseInitDriver(GDriver *g, void *display, unsigned driverinstance, unsigned systeminstance) {
+ #define m ((GMouse *)g)
+ (void) systeminstance;
- pe->type = GINPUT_MOUSE_EVENT_TYPE;
- pe->instance = instance;
- pe->x = MouseConfig.t.x;
- pe->y = MouseConfig.t.y;
- pe->z = MouseConfig.t.z;
- pe->current_buttons = MouseConfig.t.buttons;
- pe->last_buttons = MouseConfig.last_buttons;
- if (pe->current_buttons & ~pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
- pe->meta = GMETA_MOUSE_DOWN;
- else if (~pe->current_buttons & pe->last_buttons & GINPUT_MOUSE_BTN_LEFT)
- pe->meta = GMETA_MOUSE_UP;
- else
- pe->meta = GMETA_NONE;
- return TRUE;
-}
+ // The initial display is passed in the parameter for mice
+ m->display = display;
-bool_t ginputCalibrateMouse(uint16_t instance) {
- #if !GINPUT_MOUSE_NEED_CALIBRATION
- (void) instance;
-
- return FALSE;
- #else
+ #if !GINPUT_TOUCH_NOTOUCH
+ // Should this mouse start in finger mode? (according to the VMT)
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_DEFAULTFINGER))
+ m->flags |= GMOUSE_FLG_FINGERMODE;
+ #endif
- const coord_t height = gdispGGetHeight(MouseConfig.display);
- const coord_t width = gdispGGetWidth(MouseConfig.display);
- #if GINPUT_MOUSE_CALIBRATE_EXTREMES
- const MousePoint cross[] = {{0, 0},
- {(width - 1) , 0},
- {(width - 1) , (height - 1)},
- {(width / 2), (height / 2)}}; /* Check point */
- #else
- const MousePoint cross[] = {{(width / 4), (height / 4)},
- {(width - (width / 4)) , (height / 4)},
- {(width - (width / 4)) , (height - (height / 4))},
- {(width / 2), (height / 2)}}; /* Check point */
- #endif
- MousePoint points[GINPUT_MOUSE_CALIBRATION_POINTS];
- const MousePoint *pc;
- MousePoint *pt;
- int32_t px, py;
- unsigned i, j;
- font_t font1, font2;
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
- unsigned err;
- #endif
+ // Init the mouse
+ if (!gmvmt(m)->init((GMouse *)g, driverinstance))
+ return FALSE;
- if (instance || (MouseConfig.flags & FLG_IN_CAL))
- return FALSE;
+ // Ensure the Poll timer is started
+ if (!gtimerIsActive(&MouseTimer))
+ gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
+
+ return TRUE;
- font1 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT);
- font2 = gdispOpenFont(GINPUT_MOUSE_CALIBRATION_FONT2);
+ #undef m
+}
- MouseConfig.flags |= FLG_IN_CAL;
- gtimerStop(&MouseTimer);
- MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW);
+void _gmousePostInitDriver(GDriver *g) {
+ #define m ((GMouse *)g)
- #if GDISP_NEED_CLIP
- gdispGSetClip(MouseConfig.display, 0, 0, width, height);
- #endif
+ #if !GINPUT_TOUCH_STARTRAW
+ m->flags |= GMOUSE_FLG_CLIP;
+ #endif
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
- while(1) {
- #endif
- gdispGClear(MouseConfig.display, Blue);
+ #if !GINPUT_TOUCH_NOCALIBRATE && !GINPUT_TOUCH_STARTRAW
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CALIBRATE)) {
+ GMouseCalibration *pc;
+
+ #if GINPUT_TOUCH_USER_CALIBRATION_LOAD
+ if ((pc = (GMouseCalibration *)LoadMouseCalibration(gdriverGetDriverInstanceNumber((GDriver *)m), sizeof(GMouseCalibration)))) {
+ memcpy(&m->caldata, pc, sizeof(GMouseCalibration));
+ #if GINPUT_TOUCH_USER_CALIBRATION_FREE
+ gfxFree(pc);
+ #endif
+ m->flags |= GMOUSE_FLG_CALIBRATE;
+ } else
+ #endif
+ if (gmvmt(m)->calload && (pc = (GMouseCalibration *)gmvmt(m)->calload(m, sizeof(GMouseCalibration)))) {
+ memcpy(&m->caldata, pc, sizeof(GMouseCalibration));
+ if ((gmvmt(m)->d.flags & GMOUSE_VFLG_CAL_LOADFREE))
+ gfxFree(pc);
+ m->flags |= GMOUSE_FLG_CALIBRATE;
+ }
+ #if !GINPUT_TOUCH_NOCALIBRATE_GUI
+ else
+ while (CalibrateMouse(m));
+ #endif
+ }
+ #endif
- gdispGFillStringBox(MouseConfig.display, 0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1, White, Blue, justifyCenter);
+ // Get the first reading
+ GetMouseReading(m);
- for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) {
- _tsDrawCross(pc);
+ #undef m
+}
- do {
+void _gmouseDeInitDriver(GDriver *g) {
+ (void) g;
+}
- /* Wait for the mouse to be pressed */
- while(get_raw_reading(&MouseConfig.t), !(MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT))
- gfxSleepMilliseconds(20);
+GSourceHandle ginputGetMouse(unsigned instance) {
+ if (instance == GMOUSE_ALL_INSTANCES)
+ return (GSourceHandle)&MouseTimer;
+ return (GSourceHandle)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance);
+}
- /* Average all the samples while the mouse is down */
- for(px = py = 0, j = 0;
- gfxSleepMilliseconds(20), /* Settling time between readings */
- get_raw_reading(&MouseConfig.t),
- (MouseConfig.t.buttons & GINPUT_MOUSE_BTN_LEFT);
- j++) {
- px += MouseConfig.t.x;
- py += MouseConfig.t.y;
- }
+void ginputSetMouseDisplay(unsigned instance, GDisplay *g) {
+ GMouse *m;
- } while(!j);
+ if (!(m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance)))
+ return;
- pt->x = px / j;
- pt->y = py / j;
+ m->display = g ? g : GDISP;
+}
- _tsClearCross(pc);
+GDisplay *ginputGetMouseDisplay(unsigned instance) {
+ GMouse *m;
- if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) {
- gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2, Red, Yellow, justifyCenter);
- gfxSleepMilliseconds(5000);
- gdispGFillArea(MouseConfig.display, 0, 35, width, 40, Blue);
- }
+ if (!(m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance)))
+ return 0;
- }
+ return m->display;
+}
- /* Apply 3 point calibration algorithm */
- _tsDo3PointCalibration(cross, points, MouseConfig.display, &MouseConfig.caldata);
+bool_t ginputGetMouseStatus(unsigned instance, GEventMouse *pe) {
+ GMouse *m;
- /* Verification of correctness of calibration (optional) :
- * See if the 4th point (Middle of the screen) coincides with the calibrated
- * result. If point is within +/- Squareroot(ERROR) pixel margin, then successful calibration
- * Else, start from the beginning.
- */
- #if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0
- /* Transform the co-ordinates */
- MouseConfig.t.x = points[3].x;
- MouseConfig.t.y = points[3].y;
- _tsTransform(&MouseConfig.t, &MouseConfig.caldata);
- _tsOrientClip(&MouseConfig.t, MouseConfig.display, FALSE);
-
- /* Calculate the delta */
- err = (MouseConfig.t.x - cross[3].x) * (MouseConfig.t.x - cross[3].x) +
- (MouseConfig.t.y - cross[3].y) * (MouseConfig.t.y - cross[3].y);
-
- if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR)
- break;
+ // Win32 threads don't seem to recognise priority and/or pre-emption
+ // so we add a sleep here to prevent 100% polled applications from locking up.
+ gfxSleepMilliseconds(1);
- gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2, Red, Yellow, justifyCenter);
- gfxSleepMilliseconds(5000);
- }
- #endif
+ if (!(m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance)))
+ return FALSE;
- // Restart everything
- gdispCloseFont(font1);
- gdispCloseFont(font2);
- MouseConfig.flags |= FLG_CAL_OK;
- MouseConfig.last_buttons = 0;
- get_calibrated_reading(&MouseConfig.t);
- MouseConfig.flags &= ~FLG_IN_CAL;
- if ((MouseConfig.flags & FLG_INIT_DONE))
- gtimerStart(&MouseTimer, MousePoll, 0, TRUE, GINPUT_MOUSE_POLL_PERIOD);
-
- // Save the calibration data (if possible)
- if (MouseConfig.fnsavecal) {
- MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
- MouseConfig.flags |= FLG_CAL_SAVED;
- }
+ #if !GINPUT_TOUCH_NOCALIBRATE_GUI
+ if ((m->flags & GMOUSE_FLG_IN_CAL))
+ return FALSE;
+ #endif
- // Clear the screen using the GWIN default background color
- #if GFX_USE_GWIN
- gdispGClear(MouseConfig.display, gwinGetDefaultBgColor());
- #else
- gdispGClear(MouseConfig.display, Black);
- #endif
-
- return TRUE;
+ #if !GINPUT_TOUCH_NOTOUCH
+ pe->type = (gmvmt(m)->d.flags & GMOUSE_VFLG_TOUCH) ? GEVENT_TOUCH : GEVENT_MOUSE;
+ #else
+ pe->type = GEVENT_MOUSE;
#endif
+ pe->x = m->r.x;
+ pe->y = m->r.y;
+ pe->z = m->r.z;
+ pe->buttons = m->r.buttons;
+ pe->display = m->display;
+ return TRUE;
}
-/* Set the routines to save and fetch calibration data.
- * This function should be called before first calling ginputGetMouse() for a particular instance
- * as the ginputGetMouse() 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 ginputGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained.
- * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.
- */
-void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree) {
- #if GINPUT_MOUSE_NEED_CALIBRATION
- if (instance)
+#if !GINPUT_TOUCH_NOTOUCH
+ void ginputSetFingerMode(unsigned instance, bool_t on) {
+ GMouse *m;
+
+ if (!(m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance)))
return;
- MouseConfig.fnloadcal = fnload;
- MouseConfig.fnsavecal = fnsave;
- if (requireFree)
- MouseConfig.flags |= FLG_CAL_FREE;
+ if (on)
+ m->flags |= GMOUSE_FLG_FINGERMODE;
else
- MouseConfig.flags &= ~FLG_CAL_FREE;
- #if GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
- if (!MouseConfig.fnloadcal) {
- MouseConfig.fnloadcal = ginput_lld_mouse_calibration_load;
- MouseConfig.flags &= ~FLG_CAL_FREE;
- }
- if (!MouseConfig.fnsavecal)
- MouseConfig.fnsavecal = ginput_lld_mouse_calibration_save;
- #endif
- if (MouseConfig.fnsavecal && (MouseConfig.flags & (FLG_CAL_OK|FLG_CAL_SAVED)) == FLG_CAL_OK) {
- MouseConfig.fnsavecal(instance, (const uint8_t *)&MouseConfig.caldata, sizeof(MouseConfig.caldata));
- MouseConfig.flags |= FLG_CAL_SAVED;
- }
- #else
- (void)instance, (void)fnsave, (void)fnload, (void)requireFree;
- #endif
-}
+ m->flags &= ~GMOUSE_FLG_FINGERMODE;
-/* Test if a particular mouse instance requires routines to save its calibration data. */
-bool_t ginputRequireMouseCalibrationStorage(uint16_t instance) {
- if (instance)
- return FALSE;
+ }
+#endif
- #if GINPUT_MOUSE_NEED_CALIBRATION && !GINPUT_MOUSE_LLD_CALIBRATION_LOADSAVE
- return TRUE;
- #else
- return FALSE;
- #endif
-}
+#if !GINPUT_TOUCH_NOCALIBRATE_GUI
+ uint32_t ginputCalibrateMouse(unsigned instance) {
+ GMouse *m;
+
+ // Find the instance
+ if (!(m = (GMouse *)gdriverGetInstance(GDRIVER_TYPE_MOUSE, instance)))
+ return 0;
+
+ // Check it needs calibration
+ if (!(gmvmt(m)->d.flags & GMOUSE_VFLG_CALIBRATE))
+ return 0;
+
+ return CalibrateMouse(m);
+ }
+#endif
/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
-void ginputMouseWakeup(void) {
+void _gmouseWakeup(GMouse *m) {
+ if (m)
+ m->flags |= GMOUSE_FLG_NEEDREAD;
gtimerJab(&MouseTimer);
}
/* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
-void ginputMouseWakeupI(void) {
+void _gmouseWakeupI(GMouse *m) {
+ if (m)
+ m->flags |= GMOUSE_FLG_NEEDREAD;
gtimerJabI(&MouseTimer);
}
diff --git a/src/ginput/ginput_mouse.h b/src/ginput/ginput_mouse.h
index 61ad35e0..29405e50 100644
--- a/src/ginput/ginput_mouse.h
+++ b/src/ginput/ginput_mouse.h
@@ -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 mouse instance number
*
- * @param[in] instance The ID of the mouse input instance (from 0 to 9999)
+ * @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(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.
*
- * @return The source handle of the created instance
+ * @param[in] instance The ID of the mouse input instance
+ * @param[in] on If true then finger mode is turned on.
*/
- GSourceHandle ginputGetMouse(uint16_t instance);
-
+ 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);
-
- /* 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 Set the routines to store and restore calibration data
+ uint32_t ginputCalibrateMouse(unsigned instance);
+
+ /**
+ * @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.
*
- * @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.
+ * @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 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.
*
- * @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
diff --git a/src/ginput/sys_options.h b/src/ginput/sys_options.h
index c606262b..e67a03ce 100644
--- a/src/ginput/sys_options.h
+++ b/src/ginput/sys_options.h
@@ -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 Use a custom board definition for the keyboard driver even if a board definition exists.
+ /**
+ * @brief Turn off the touch calibration GUI.
* @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 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_KEYBOARD_USE_CUSTOM_BOARD
- #define GINPUT_KEYBOARD_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_TOUCH_NOCALIBRATE_GUI
+ #define GINPUT_TOUCH_NOCALIBRATE_GUI FALSE
#endif
/**
- * @brief Use a custom board definition for the toggle driver even if a board definition exists.
+ * @brief Turn off all touch calibration 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 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_TOGGLE_USE_CUSTOM_BOARD
- #define GINPUT_TOGGLE_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_TOUCH_NOCALIBRATE
+ #define GINPUT_TOUCH_NOCALIBRATE FALSE
#endif
/**
- * @brief Use a custom board definition for the dial driver even if a board definition exists.
+ * @brief Turn off all touch support.
* @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.
+ * @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_DIAL_USE_CUSTOM_BOARD
- #define GINPUT_DIAL_USE_CUSTOM_BOARD FALSE
+ #ifndef GINPUT_TOUCH_NOTOUCH
+ #define GINPUT_TOUCH_NOTOUCH FALSE
+ #endif
+ /**
+ * @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_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
/** @} */
diff --git a/src/ginput/sys_rules.h b/src/ginput/sys_rules.h
index f98cc469..d9a367ce 100644
--- a/src/ginput/sys_rules.h
+++ b/src/ginput/sys_rules.h
@@ -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 */
diff --git a/src/gwin/gwin_widget.c b/src/gwin/gwin_widget.c
index f85e6f20..cf1f59c7 100644
--- a/src/gwin/gwin_widget.c
+++ b/src/gwin/gwin_widget.c
@@ -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
diff --git a/src/gwin/gwin_widget.h b/src/gwin/gwin_widget.h
index 81c76263..c6bc6d4c 100644
--- a/src/gwin/gwin_widget.h
+++ b/src/gwin/gwin_widget.h
@@ -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__)
diff --git a/tools/touch_driver_test/gfxconf.h b/tools/touch_driver_test/gfxconf.h
index 9cd0cf1f..3d93a138 100644
--- a/tools/touch_driver_test/gfxconf.h
+++ b/tools/touch_driver_test/gfxconf.h
@@ -57,5 +57,6 @@
/* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE
+#define GINPUT_TOUCH_STARTRAW TRUE
#endif /* _GFXCONF_H */
diff --git a/tools/touch_driver_test/main.c b/tools/touch_driver_test/main.c
index a8318edd..13136a57 100644
--- a/tools/touch_driver_test/main.c
+++ b/tools/touch_driver_test/main.c
@@ -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");
-
- pem = (GEventMouse *)&gl.event;
- ginputGetMouseStatus(0, pem);
- deviceType = pem->type;
-
- gwinSetColor(ghc, White);
- gwinPrintf(ghc, "This is detected as a %s device\n\n",
- deviceType == GEVENT_MOUSE ? "MOUSE" : (pem->type == GEVENT_TOUCH ? "TOUCH" : "UNKNOWN"));
-
- 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");
+ DrawHeader("1. Device Type", isCalibrated, isCalibrated && !isFirstTime, isCalibrated);
+
+ // 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";
+
+ 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 (!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,105 +344,118 @@ 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
+ * Test: Click Jitter
*/
-StepPolling:
+StepClickJitter:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
- gwinPrintf(ghc, "\n5. GINPUT_MOUSE_POLL_PERIOD\n\n");
+ gwinPrintf(ghc, "\n6. Click Jitter\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");
+ 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 %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);
- if (pem->y < bHeight && pem->x >= swidth-2*bWidth) {
- if ((pem->meta & GMETA_MOUSE_UP)) {
- if (pem->x >= swidth-bWidth)
- break;
- goto StepJitter;
+ 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;
}
- if ((pem->current_buttons & GINPUT_MOUSE_BTN_LEFT))
- gdispDrawPixel(pem->x, pem->y, Green);
+ break;
}
-
+
/*
- * Test: Click Jitter
+ * Test: Polling frequency
*/
-StepClickJitter:
+StepDrawing:
gwinClear(ghc);
gwinSetColor(ghc, Yellow);
- gwinPrintf(ghc, "\n6. GINPUT_MOUSE_MAX_CLICK_JITTER\n\n");
+ gwinPrintf(ghc, "\n7. Drawing\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. "
- "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");
+ 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;
}
diff --git a/tools/touch_raw_readings/gfxconf.h b/tools/touch_raw_readings/gfxconf.h
new file mode 100644
index 00000000..3d93a138
--- /dev/null
+++ b/tools/touch_raw_readings/gfxconf.h
@@ -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 */
diff --git a/tools/touch_raw_readings/main.c b/tools/touch_raw_readings/main.c
new file mode 100644
index 00000000..d6c97920
--- /dev/null
+++ b/tools/touch_raw_readings/main.c
@@ -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);
+ }
+}