Touchscreen driver implementation and possibly dead code
michalk-exi opened this issue · comments
While I've been working on implementing touchscreen driver, I've stumbled across the gx_touch_driver_generic_resistive.c
file. It looks pretty promising and nicely implements all the structures for tracking touch state and generating all needed events (maybe missing the GX_EVENT_PEN_HOLD
- which doesn't exist, but that's something for another ticket). The only problem is, that this file looks like dead code. Functions are all there, but it has neither it's own header nor is part of any other header (for example gx_display.h
or gx_api.h
).
I was hoping that implementing the touch driver would be similar to implementing a display driver. Which is done by wrapping the default implementation provided by _gx_display_driver_xxx_setup
. Similarly the touch driver could be built using default implementation of _gx_touch_driver_generic_resistive_setup
. But again that function is not exposed anywhere.
Long story short, it is either that gx_touch_driver_generic_resistive.c
is a leftover that should be removed (or at least moved from /common/src
to /samples
if it only servers as a demonstration) or the gx_display.h
is missing three function prototypes for _gx_touch_driver_generic_resistive_setup
, _gx_touch_driver_generic_resistive_update
and _gx_touch_driver_generic_resistive_calibrate
, maybe guarded with some form of GX_TOUCH_SUPPORT
macro.
There is also a possibility that I'm doing this terribly wrong in which case I would appreciate some pointers as to how do you implement touchscreen driver in GUIX. And some hints as to what are the An,Bn,Cn,Dn,En,Fn
member of TOUCH_CALIBRATION_MATRIX
supposed to represent.
Hello @michalk-exi ,
Good question(s). So the generic resistive touch driver isn't really obsolete, but it isn't structured the same as the display driver. I'm open to suggestions as far as how to make it a little bit more user friendly. I was going to send you an example that uses this generic resistive driver, but it seems all of our dev boards for the last couple of years utilize capacitive touch screens so I don't have anything at my fingertips. Still digging on that one, I will try to get you an example.
The summary is the generic resistive touch driver tries to remove the repetitive code that we used to have to write for every touch screen: 1) Code to calibrate the resistive touch screen 2) Code to decide what to do with the latest touch status.
There are really three layers here: 1) The generic code to calibrate and send events to GUIX 2) Your hardware specific code to detect pen down and read raw touch coordinates and 3) Application code that provides prompts during calibration and a bitmap to use for the calibration target. We try to write one "driver" for the hardware, and then re-use this driver in different applications. Since the resource IDs are application specific, we divided the GX_RESISTIVE_TOUCH structure into the hardware-specific portion and the application defined portion. The application fills in the GX_RESISTIVE_TOUCH_INFO, and the hardware-specific driver fills in the remainder of the GX_RESISTIVE_TOUCH structure. Hope that all makes sense.
It's up to the application to provide the GX_RESISTIVE_TOUCH_INFO structure with the strings you want to display to the user for each calibration step (touch the target, stop touching the target, etc.., in whatever language you want to use), and a MULTI_LINE_TEXT_VIEW widget into which the generic code will display the prompts during calibration. You also have to provide callback functions via the GX_RESISTIVE_TOUCH::gx_resistive_touch_pen_down_detect and GX_RESISTIVE_TOUCH::gx_resistive_touch_sample_read function pointers. Once these structures are initialized, you call _gx_touch_driver_generic_resistive_calibrate(), and then go into a loop calling gx_touch_driver_generic_resistive_update. For our example drivers we just polled calling gx_touch_driver_generic_resistive_update on a timer, but it would be better to sleep until there is a pen_down interrupt, then poll until the pen is released.
So to get started do this:
extern the functions
VOID _gx_touch_driver_generic_resistive_setup(GX_RESISTIVE_TOUCH *touch, GX_RESISTIVE_TOUCH_INFO *info);
VOID _gx_touch_driver_generic_resistive_update(GX_RESISTIVE_TOUCH *touch);
VOID _gx_touch_driver_generic_resistive_calibrate(GX_RESISTIVE_TOUCH *touch);
in your touch driver source. From your application initialize a GX_RESISTIVE_TOUCH_INFO structure and call gx_touch_driver_resistive_setup. Initialize the remaining fields in the GX_RESISTIVE_TOUCH structure from your driver level code. Then call calibrate() and go into a loop calling update().
As soon as I find an example for one of our older dev boards I will forward that to you.
I should have noted that if you are using a capacitive (not resistive) touch screen, don't bother with the generic_resistive_touch. That code is mainly about implementing the calibration, which you don't need for a capacitive touch. If you are using capacitive, just follow the examples in the generic resistive touch in terms of how to send each event type into the GUIX event queue. I have several capacitive touch drivers I can send you if that is what you need.
Attached a real-hardware example that might be helpful.
Hi @jdeere5220,
Thanks for all your help, I especially appreciate the real world example of a driver. It also has reference values for stuff like gx_resistive_touch_max_retries
and gx_resistive_touch_sample_size
which is especially useful as it is impossible to find them anywhere else.
And yes, I'm working with resistive touchscreen, so to me all that will be very useful, thanks again.
I've also figured out that An-Fn
members of a TOUCH_CALIBRATION_MATRIX
are just coefficients, they don't have any special meaning.
In my case what I did in the end is what you've suggested. I've exposed the ..._update
, ..._setup
and ..._calibrate
function prototypes and wrote my driver around them.
As for suggestions, I think the driver is in a decent shape overall. What I would like to be a bit different is the gx_resistive_touch_sample_read
function to read both x
and y
coordinates at the same time and return them as GX_POINT
, but that is obviously a change that breaks current API. Other than that, the ..._event_send
functions hardcode the gx_event_display_handle
to be 0, which from my understanding sends these events to nowhere. I had no luck with handling them (I was not receiving any GX_EVENT_PEN_...
in my event handlers), until I changed that argument to point, to the gx_display_driver_data
from GX_DISPLAY
, following sample code of demo_guix_keyboard
. Figuring that out took me more time than I want to admit though. It is however entirely possible that my root window should set the display_handle to 0.
In any case, thanks again for all your help!