Add touch driver STMPE610 by lliypuk
parent
07a63f7143
commit
07707276f6
|
@ -0,0 +1,2 @@
|
|||
# List the required driver.
|
||||
GFXSRC += $(GFXLIB)/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 */
|
||||
|
|
@ -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 */
|
|
@ -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.
|
||||
|
|
@ -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 */
|
Loading…
Reference in New Issue