Jump to content

Writing a touch panel driver


crteensy

Recommended Posts

Is there some sort of walkthrough for writing a touch panel driver?

I've found the examples in /boards/addons/ginput/touch and /drivers/ginput/touch, but they don't really align with the wiki page - there seems to be more to it than simply writing a file with an implementation of getpin_pressed(). All examples implement a board initialization function and some sort of read_xyz(), but I have not found any guide that tells me what to set in the passed GMouseReading struct and what to return (TRUE or FALSE), and why.

What is the init sequence for the different modules? Is the ginput driver initialized before the gdisp driver? Where can I find that out?

Link to comment
Share on other sites

There is currently no walk-through for writing a touch panel driver. The existing drivers are really currently the best available form of documentation. The main reason this is not yet documented well is because a) this is fairly advanced coding - well beyond most users, and b) we never have enough time to do all we want and this hasn't been high enough priority yet as Tectu and I have been the ones to write all the touch drivers to date.

The wiki page article is probably old. The touch infrastructure recently went through a major change to a) support gdriver as the base, b) allow for multiple touch devices c) to fix lots of problems with data consistency, averaging and common controller problems. Getting touch to work reliably is really very complex with lots of different approaches taken on the internet in various libraries that try to compensate for the issues - usually the wrong way. Our current touch system is probably the best out there currently and writing drivers is now fairly simple.

To write a driver you need to fill in the GMouseVMT structure with the properties and routines for your touch device. This is a static structure usually compiled into the ROM. See the definition of GMouseVMT in src/ginput/ginput_driver_mouse.h. The comments describe the fields and their meanings fairly well. The existing drivers will give you good examples. The most basic is probably the MCU driver, and yet that is the worst case driver in terms of signal conditioning. The FT5x06 driver is a good controller based example. The STMPE811 driver is an example of a controller chip that has some problems.

Once you have initially written your driver there are some programs that you should use to test your touch device properly. The demos/tools/touch_raw_readings program is used to see exactly what your touch controller is returning in various situations. This is very handy for initial debugging. After that there is the demos/tools/touch_driver_test which does full touch screen testing including calibration, sensitivity areas etc.

Have fun and let us know how you go. We are keen to see support for some new controllers. We will help wherever we can. Private message me for any low level details you need help with.

Link to comment
Share on other sites

Well inmarket pretty much mentioned every point.

Just one more thing: Yes the wiki page is currently out of date on the GINPUT board file and I will put this on my higher priority list. However, please note that the wiki is just giving you information on how to implementing a board file and not the actual driver. The driver is part of the uGFX library and as inmarket already said it needs some advanced coding skills and hence we have not put up documentation on that yet. The board file on the other hand just describes how the interface between your microcontroller and the touch controller works. To use an existing driver you just have to implement the board file. The uGFX driver will use the functions in the board file to communicate with the touch controller chip.

~ Tectu

Link to comment
Share on other sites

Good, so I have these board files:

gmouse_lld_RA8875_board.h:

#ifndef _LLD_GMOUSE_RA8875_BOARD_H
#define _LLD_GMOUSE_RA8875_BOARD_H

#include "RA8875_regs.h"

// Resolution and Accuracy Settings
#define GMOUSE_RA8875_PEN_CALIBRATE_ERROR 8
#define GMOUSE_RA8875_PEN_CLICK_ERROR 6
#define GMOUSE_RA8875_PEN_MOVE_ERROR 4
#define GMOUSE_RA8875_FINGER_CALIBRATE_ERROR 14
#define GMOUSE_RA8875_FINGER_CLICK_ERROR 18
#define GMOUSE_RA8875_FINGER_MOVE_ERROR 14
#define GMOUSE_RA8875_Z_MIN 0 // The minimum Z reading
#define GMOUSE_RA8875_Z_MAX 1 // The maximum Z reading
#define GMOUSE_RA8875_Z_TOUCHON 1 // Values between this and Z_MAX are definitely pressed
#define GMOUSE_RA8875_Z_TOUCHOFF 0 // 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_RA8875_BOARD_DATA_SIZE 0

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
extern void ra8875_acquire_bus();
extern void ra8875_release_bus();
extern void ra8875_write_index(uint8_t index);
extern void ra8875_write_data(uint8_t data);
extern uint8_t ra8875_read_data();

static bool_t init_board(GMouse *m, unsigned driverinstance) {
return TRUE;
}

static bool_t read_xyz(GMouse *m, GMouseReading *prd) {
ra8875_acquire_bus();
ra8875_write_index(RA8875_INTC2);
uint8_t INTC2 = ra8875_read_data();
uint8_t pending = INTC2 & RA8875_INTCx_TP;
prd->buttons = 0;
prd->z = GMOUSE_RA8875_Z_MIN;
if (pending)
{
ra8875_write_index(RA8875_TPXH);
uint8_t touchx = ra8875_read_data();
ra8875_write_index(RA8875_TPYH);
uint8_t touchy = ra8875_read_data();
// clear touch flag
ra8875_write_index(RA8875_INTC2);
ra8875_write_data(RA8875_INTCx_TP);

static const int16_t xr = 20; // 16
static const int16_t xl = 240; // 240
static const int16_t yt = 220; // 220
static const int16_t yb = 35; // 35

coord_t x = (480*(touchx-xl))/(xr-xl);
coord_t y = (272*(touchy-yt))/(yb-yt);
prd->x = x;
prd->y = y;
prd->z = GMOUSE_RA8875_Z_MAX;
prd->buttons = GINPUT_TOUCH_PRESSED;
}
ra8875_release_bus();
return TRUE;
}

#endif /* _LLD_GMOUSE_RA8875_BOARD_H */

gmouse_lld_RA8875.c:

#include "gfx.h"

#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE

#define GMOUSE_DRIVER_VMT GMOUSEVMT_RA8875
#include "src/ginput/ginput_driver_mouse.h"

// Get the hardware interface
#include "gmouse_lld_RA8875_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_RA8875_BOARD_DATA_SIZE,
_gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
},
GMOUSE_RA8875_Z_MAX, // z_max
GMOUSE_RA8875_Z_MIN, // z_min
GMOUSE_RA8875_Z_TOUCHON, // z_touchon
GMOUSE_RA8875_Z_TOUCHOFF, // z_touchoff
{ // pen_jitter
GMOUSE_RA8875_PEN_CALIBRATE_ERROR, // calibrate
GMOUSE_RA8875_PEN_CLICK_ERROR, // click
GMOUSE_RA8875_PEN_MOVE_ERROR // move
},
{ // finger_jitter
GMOUSE_RA8875_FINGER_CALIBRATE_ERROR, // calibrate
GMOUSE_RA8875_FINGER_CLICK_ERROR, // click
GMOUSE_RA8875_FINGER_MOVE_ERROR // move
},
init_board, // init
0, // deinit
read_xyz, // get
0, // calsave
0 // calload
}};

#endif /* GFX_USE_GINPUT && GINPUT_NEED_MOUSE */

The raw touch reading example gets to the point where it displays the second line, like

4294940576, 8191, z=0 B=0x0000

but that line never changes. I have tested the touch reading code before and I'm confident that it works. The board's read_xyz() doesn't seem to get called as I should see activity on the SPI.

Link to comment
Share on other sites

A couple of thoughts here...

1. The read_xyz and the register definitions should go into the c file rather than the board file as they are not interface specific but rather controller dependant. I know MCU does that differently but in that case there is no controller.

2. I am wondering if the threading issues are something specific to the implementation of threading emulation with the particular compiler you are using. We have tested it with all the compilers we have access to but some compilers are strange. What compiler are you using?

Link to comment
Share on other sites

I can rearrange my code but I really don't think that this will solve my problem. Of course, better separation between driver and board is needed for portability, but I'm not facing a portability issue here (or am I?). As my display has a built-in touch panel controller such a separation will probably end with a mess anyway...

I've posted compiler details in my widget thread: viewtopic.php?f=23&t=198

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...