aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ginput
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2015-02-23 18:14:37 +1000
committerinmarket <andrewh@inmarket.com.au>2015-02-23 18:14:37 +1000
commit07707276f61fa9cfcc7a44859c07c816b4b9ae81 (patch)
tree53ca92b78bef06e0b984755001c5af8a89f5e391 /drivers/ginput
parent07a63f714373859ace005c0686a7ac6982ba30f9 (diff)
downloaduGFX-07707276f61fa9cfcc7a44859c07c816b4b9ae81.tar.gz
uGFX-07707276f61fa9cfcc7a44859c07c816b4b9ae81.tar.bz2
uGFX-07707276f61fa9cfcc7a44859c07c816b4b9ae81.zip
Add touch driver STMPE610 by lliypuk
Diffstat (limited to 'drivers/ginput')
-rw-r--r--drivers/ginput/touch/STMPE610/driver.mk2
-rw-r--r--drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610.c268
-rw-r--r--drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610_board_template.h60
-rw-r--r--drivers/ginput/touch/STMPE610/readme.txt11
-rw-r--r--drivers/ginput/touch/STMPE610/stmpe610.h70
5 files changed, 411 insertions, 0 deletions
diff --git a/drivers/ginput/touch/STMPE610/driver.mk b/drivers/ginput/touch/STMPE610/driver.mk
new file mode 100644
index 00000000..364a01ff
--- /dev/null
+++ b/drivers/ginput/touch/STMPE610/driver.mk
@@ -0,0 +1,2 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610.c
diff --git a/drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610.c b/drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610.c
new file mode 100644
index 00000000..2175da94
--- /dev/null
+++ b/drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610.c
@@ -0,0 +1,268 @@
+/*
+ * 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_STMPE610
+#include "src/ginput/ginput_driver_mouse.h"
+
+// Hardware definitions
+#include "drivers/ginput/touch/STMPE610/stmpe610.h"
+
+// Get the hardware interface
+#include "gmouse_lld_STMPE610_board.h"
+
+// Extra settings for the users gfxconf.h file. See readme.txt
+#ifndef GMOUSE_STMPE610_SELF_CALIBRATE
+ #define GMOUSE_STMPE610_SELF_CALIBRATE FALSE
+#endif
+#ifndef GMOUSE_STMPE610_READ_PRESSURE
+ #define GMOUSE_STMPE610_READ_PRESSURE FALSE
+#endif
+#ifndef GMOUSE_STMPE610_TEST_MODE
+ #define GMOUSE_STMPE610_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_STMPE610_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, STMPE610_REG_SYS_CTRL1, 0x02); // Software chip reset
+ gfxSleepMilliseconds(10);
+
+ write_reg(m, STMPE610_REG_SYS_CTRL2, 0x04); // Temperature sensor clock off, GPIO clock off, touch clock on, ADC clock on
+
+ #if GMOUSE_STMPE610_GPIO_IRQPIN
+ write_reg(m, STMPE610_REG_INT_EN, 0x03); // Interrupt on INT pin when there is a sample or a touch transition.
+ #else
+ write_reg(m, STMPE610_REG_INT_EN, 0x00); // Don't Interrupt on INT pin
+ #endif
+
+ write_reg(m, STMPE610_REG_ADC_CTRL1, 0x48); // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage refernce
+ gfxSleepMilliseconds(2);
+ write_reg(m, STMPE610_REG_ADC_CTRL2, 0x01); // ADC speed 3.25MHz
+ write_reg(m, STMPE610_REG_GPIO_AF, 0x00); // GPIO alternate function - OFF
+ write_reg(m, STMPE610_REG_TSC_CFG, 0xA3); // Averaging 4, touch detect delay 1ms, panel driver settling time 1ms
+ write_reg(m, STMPE610_REG_FIFO_TH, 0x01); // FIFO threshold = 1
+ write_reg(m, STMPE610_REG_FIFO_STA, 0x01); // FIFO reset enable
+ write_reg(m, STMPE610_REG_FIFO_STA, 0x00); // FIFO reset disable
+ write_reg(m, STMPE610_REG_TSC_FRACT_XYZ, 0x07); // Z axis data format
+ write_reg(m, STMPE610_REG_TSC_I_DRIVE, 0x01); // max 50mA touchscreen line current
+ #if GMOUSE_STMPE610_READ_PRESSURE
+ write_reg(m, STMPE610_REG_TSC_CTRL, 0x30); // X&Y&Z, 16 reading window
+ write_reg(m, STMPE610_REG_TSC_CTRL, 0x31); // X&Y&Z, 16 reading window, TSC enable
+ #else
+ write_reg(m, STMPE610_REG_TSC_CTRL, 0x32); // X&Y, 16 reading window
+ write_reg(m, STMPE610_REG_TSC_CTRL, 0x33); // X&Y, 16 reading window, TSC enable
+ #endif
+ write_reg(m, STMPE610_REG_INT_STA, 0xFF); // Clear all interrupts
+ write_reg(m, STMPE610_REG_INT_CTRL, 0x01); // Level interrupt, enable interrupts
+
+ release_bus(m);
+ return TRUE;
+}
+
+static bool_t read_xyz(GMouse* m, GMouseReading* pdr)
+{
+ #if GMOUSE_STMPE610_TEST_MODE
+ static GMouseReading n;
+ #endif
+ uint8_t status;
+
+ // Button information will be regenerated
+ pdr->buttons = 0;
+
+ #if GMOUSE_STMPE610_TEST_MODE
+ aquire_bus(m);
+
+ // Set the buttons to match various touch signals
+ if ((read_byte(m, STMPE610_REG_TSC_CTRL) & 0x80))
+ pdr->buttons |= 0x02;
+
+ status = read_byte(m, STMPE610_REG_FIFO_STA);
+ if (!(status & 0x20))
+ pdr->buttons |= 0x04;
+
+ #if GMOUSE_STMPE610_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_STMPE610_GPIO_IRQPIN
+ write_reg(m, STMPE610_REG_INT_STA, 0xFF);
+ #endif
+ release_bus(m);
+ return TRUE;
+ }
+
+ #else
+ // Is there a new sample or a touch transition
+ #if GMOUSE_STMPE610_GPIO_IRQPIN
+ if(!getpin_irq(m))
+ return FALSE;
+ #endif
+
+ // Is there something in the fifo
+ status = read_byte(m, STMPE610_REG_FIFO_STA);
+ if ((status & 0x20)) {
+
+ // Nothing in the fifo.
+
+ // If not touched return the pseudo result
+ if (!(read_byte(m, STMPE610_REG_TSC_CTRL) & 0x80)) {
+
+ pdr->z = gmvmt(m)->z_min;
+ #if GMOUSE_STMPE610_GPIO_IRQPIN
+ write_reg(m, STMPE610_REG_INT_STA, 0xFF);
+ #endif
+ release_bus(m);
+ return TRUE;
+ }
+
+ // No new result
+ #if GMOUSE_STMPE610_GPIO_IRQPIN
+ write_reg(m, STMPE610_REG_INT_STA, 0xFF);
+ #endif
+ release_bus(m);
+ return FALSE;
+ }
+
+ #endif
+
+ // Time to get some readings
+ pdr->x = (coord_t)read_word(m, STMPE610_REG_TSC_DATA_X);
+ pdr->y = (coord_t)read_word(m, STMPE610_REG_TSC_DATA_Y);
+ #if GMOUSE_STMPE610_READ_PRESSURE
+ pdr->z = (coord_t)read_byte(m, STMPE610_REG_TSC_DATA_Z);
+ #else
+ pdr->z = gmvmt(m)->z_max;
+ #endif
+
+ #if !GMOUSE_STMPE610_SLOW_CPU
+ if (!(status & 0xC0)) {
+ // Is there more data to come
+ if (!(read_byte(m, STMPE610_REG_FIFO_STA) & 0x20))
+ _gmouseWakeup(m);
+ } else
+ #endif
+
+ // Clear the rest of the fifo
+ {
+ write_reg(m, STMPE610_REG_FIFO_STA, 0x01); // FIFO reset enable
+ write_reg(m, STMPE610_REG_FIFO_STA, 0x00); // FIFO reset disable
+ }
+
+ // All done
+ #if GMOUSE_STMPE610_GPIO_IRQPIN
+ write_reg(m, STMPE610_REG_INT_STA, 0xFF);
+ #endif
+ release_bus(m);
+
+ #if GMOUSE_STMPE610_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
+ // Not working currently.
+ #if GMOUSE_STMPE610_SELF_CALIBRATE
+ #if GDISP_NEED_CONTROL
+ switch(gdispGGetOrientation(m->display)) {
+ case GDISP_ROTATE_0:
+ case GDISP_ROTATE_180:
+ default:
+ pdr->x = pdr->x / (4096/gdispGGetWidth(m->display));
+ pdr->y = gdispGGetHeight(m->display) - pdr->y / (4096/gdispGGetHeight(m->display));
+ case GDISP_ROTATE_90:
+ case GDISP_ROTATE_270:
+ pdr->x = pdr->x / (4096/gdispGGetHeight(m->display));
+ pdr->y = gdispGGetWidth(m->display) - pdr->y / (4096/gdispGGetWidth(m->display));
+ }
+ #else
+ pdr->x = gdispGGetWidth(m->display) - pdr->x / (4096/gdispGGetWidth(m->display));
+ pdr->y = pdr->y / (4096/gdispGGetHeight(m->display));
+ #endif
+ #endif
+
+ return TRUE;
+}
+
+const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
+ {
+ GDRIVER_TYPE_TOUCH,
+ #if GMOUSE_STMPE610_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_STMPE610_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_STMPE610_PEN_CALIBRATE_ERROR, // calibrate
+ GMOUSE_STMPE610_PEN_CLICK_ERROR, // click
+ GMOUSE_STMPE610_PEN_MOVE_ERROR // move
+ },
+ { // finger_jitter
+ GMOUSE_STMPE610_FINGER_CALIBRATE_ERROR, // calibrate
+ GMOUSE_STMPE610_FINGER_CLICK_ERROR, // click
+ GMOUSE_STMPE610_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/STMPE610/gmouse_lld_STMPE610_board_template.h b/drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610_board_template.h
new file mode 100644
index 00000000..f3beb19e
--- /dev/null
+++ b/drivers/ginput/touch/STMPE610/gmouse_lld_STMPE610_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_STMPE610_PEN_CALIBRATE_ERROR 8
+#define GMOUSE_STMPE610_PEN_CLICK_ERROR 6
+#define GMOUSE_STMPE610_PEN_MOVE_ERROR 4
+#define GMOUSE_STMPE610_FINGER_CALIBRATE_ERROR 14
+#define GMOUSE_STMPE610_FINGER_CLICK_ERROR 18
+#define GMOUSE_STMPE610_FINGER_MOVE_ERROR 14
+
+// How much extra data to allocate at the end of the GMouse structure for the board's use
+#define GMOUSE_STMPE610_BOARD_DATA_SIZE 0
+
+// Options - Leave these commented to make it user configurable in the gfxconf.h
+//#define GMOUSE_STMPE610_READ_PRESSURE FALSE
+//#define GMOUSE_STMPE610_SELF_CALIBRATE FALSE
+//#define GMOUSE_STMPE610_TEST_MODE FALSE
+
+// If TRUE this board has the STMPE610 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_STMPE610_GPIO_IRQPIN FALSE
+
+// If TRUE this is a really slow CPU and we should always clear the FIFO between reads.
+#define GMOUSE_STMPE610_SLOW_CPU FALSE
+
+static bool_t init_board(GMouse* m, unsigned driverinstance) {
+}
+
+#if GMOUSE_STMPE610_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/STMPE610/readme.txt b/drivers/ginput/touch/STMPE610/readme.txt
new file mode 100644
index 00000000..03ff9019
--- /dev/null
+++ b/drivers/ginput/touch/STMPE610/readme.txt
@@ -0,0 +1,11 @@
+This driver has a number of optional settings which can be specified in gfxconf.h:
+
+#define GMOUSE_STMPE610_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_STMPE610_SELF_CALIBRATE TRUE
+ Scale the touch readings to avoid calibration. This is not as accurate as real calibration.
+
+#define GMOUSE_STMPE610_TEST_MODE TRUE
+ Return raw readings for diagnostic use with the "touch_raw_readings" tool.
+
diff --git a/drivers/ginput/touch/STMPE610/stmpe610.h b/drivers/ginput/touch/STMPE610/stmpe610.h
new file mode 100644
index 00000000..c84f1e6a
--- /dev/null
+++ b/drivers/ginput/touch/STMPE610/stmpe610.h
@@ -0,0 +1,70 @@
+/*
+ * 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 _STMPE610_H
+#define _STMPE610_H
+
+// Identification registers
+#define STMPE610_REG_CHP_ID 0x00 // 16-bit
+#define STMPE610_REG_ID_VER 0x02
+
+// System registers
+#define STMPE610_REG_SYS_CTRL1 0x03
+#define STMPE610_REG_SYS_CTRL2 0x04
+#define STMPE610_REG_SPI_CFG 0x08
+
+// Interrupt control registers
+#define STMPE610_REG_INT_CTRL 0x09
+#define STMPE610_REG_INT_EN 0x0A
+#define STMPE610_REG_INT_STA 0x0B
+#define STMPE610_REG_GPIO_INT_EN 0x0C
+#define STMPE610_REG_GPIO_INT_STA 0x0D
+#define STMPE610_REG_ADC_INT_EN 0x0E
+#define STMPE610_REG_ADC_INT_STA 0x0F
+
+// GPIO registers
+#define STMPE610_REG_GPIO_SET_PIN 0x10
+#define STMPE610_REG_GPIO_CLR_PIN 0x11
+#define STMPE610_REG_GPIO_MP_STA 0x12
+#define STMPE610_REG_GPIO_DIR 0x13
+#define STMPE610_REG_GPIO_ED 0x14
+#define STMPE610_REG_GPIO_RE 0x15
+#define STMPE610_REG_GPIO_FE 0x16
+#define STMPE610_REG_GPIO_AF 0x17
+
+// ADC registers
+#define STMPE610_REG_ADC_CTRL1 0x20
+#define STMPE610_REG_ADC_CTRL2 0x21
+#define STMPE610_REG_ADC_CAPT 0x22
+#define STMPE610_REG_ADC_DATA_CH0 0x30 // 16-bit
+#define STMPE610_REG_ADC_DATA_CH1 0x32 // 16-bit
+#define STMPE610_REG_ADC_DATA_CH4 0x38 // 16-bit
+#define STMPE610_REG_ADC_DATA_CH5 0x3A // 16-bit
+#define STMPE610_REG_ADC_DATA_CH6 0x3C // 16-bit
+#define STMPE610_REG_ADC_DATA_CH7 0x3E // 16-bit
+
+// Touchscreen registers
+#define STMPE610_REG_TSC_CTRL 0x40
+#define STMPE610_REG_TSC_CFG 0x41
+#define STMPE610_REG_WDW_TR_X 0x42 // 16-bit
+#define STMPE610_REG_WDW_TR_Y 0x44 // 16-bit
+#define STMPE610_REG_WDW_BL_X 0x46 // 16-bit
+#define STMPE610_REG_WDW_BL_Y 0x48 // 16-bit
+#define STMPE610_REG_FIFO_TH 0x4A
+#define STMPE610_REG_FIFO_STA 0x4B
+#define STMPE610_REG_FIFO_SIZE 0x4C
+#define STMPE610_REG_TSC_DATA_X 0x4D // 16-bit
+#define STMPE610_REG_TSC_DATA_Y 0x4F // 16-bit
+#define STMPE610_REG_TSC_DATA_Z 0x51
+#define STMPE610_REG_TSC_DATA_XYZ 0x52 // 32-bit
+#define STMPE610_REG_TSC_FRACT_XYZ 0x56
+#define STMPE610_REG_TSC_DATA 0x57
+#define STMPE610_REG_TSC_I_DRIVE 0x58
+#define STMPE610_REG_TSC_SHIELD 0x59
+
+
+#endif /* _STMPE610_H */