summaryrefslogtreecommitdiff
path: root/firmware/drivers/ft6x06.c
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-11-20 19:05:16 +0000
committerAidan MacDonald <amachronic@protonmail.com>2021-11-24 18:49:03 -0500
commit44acbc66291da6a8ade8571b73a10e34341a622b (patch)
tree226f9d9f971756f481455da082443f700bcfc786 /firmware/drivers/ft6x06.c
parentb39acee3abd199d80b84c68ebfa7301b7e7a957e (diff)
downloadrockbox-44acbc66291da6a8ade8571b73a10e34341a622b.tar.gz
rockbox-44acbc66291da6a8ade8571b73a10e34341a622b.zip
Shanling Q1: enable multi-touch reporting
The FT6x06 driver used for the Shanling Q1's touchscreen has been extended to report more than one touch point. It can also return the gesture detected by the controller, but this doesn't seem to report anything useful on the Q1. Multi-touch is only useful in 3x3 grid mode since the Rockbox button API cannot report more than one touch point. The FiiO M3K uses the same driver so it's been updated to the multi-touch API, but functionality is unchanged. Change-Id: I4de42f44808d6eb902e3da212d8f936b7a5042c7
Diffstat (limited to 'firmware/drivers/ft6x06.c')
-rw-r--r--firmware/drivers/ft6x06.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/firmware/drivers/ft6x06.c b/firmware/drivers/ft6x06.c
index 538ca10480..c605ee0944 100644
--- a/firmware/drivers/ft6x06.c
+++ b/firmware/drivers/ft6x06.c
@@ -24,6 +24,16 @@
24#include "i2c-async.h" 24#include "i2c-async.h"
25#include <string.h> 25#include <string.h>
26 26
27#define BYTES_PER_POINT 6
28
29#ifdef FT6x06_SWAP_AXES
30# define POS_X pos_y
31# define POS_Y pos_x
32#else
33# define POS_X pos_x
34# define POS_Y pos_y
35#endif
36
27struct ft6x06_driver { 37struct ft6x06_driver {
28 /* i2c bus data */ 38 /* i2c bus data */
29 int i2c_cookie; 39 int i2c_cookie;
@@ -33,39 +43,42 @@ struct ft6x06_driver {
33 ft6x06_event_cb event_cb; 43 ft6x06_event_cb event_cb;
34 44
35 /* buffer for I2C transfers */ 45 /* buffer for I2C transfers */
36 uint8_t raw_data[6]; 46 uint8_t raw_data[1 + 2 + BYTES_PER_POINT * FT6x06_NUM_POINTS];
37}; 47};
38 48
39static struct ft6x06_driver ft_drv; 49static struct ft6x06_driver ft_drv;
40struct ft6x06_state ft6x06_state; 50struct ft6x06_state ft6x06_state;
41 51
52static inline void ft6x06_convert_point(const uint8_t* raw,
53 struct ft6x06_point* pt)
54{
55 pt->event = (raw[0] >> 6) & 0x3;
56 pt->touch_id = (raw[2] >> 4) & 0xf;
57 pt->POS_X = ((raw[0] & 0xf) << 8) | raw[1];
58 pt->POS_Y = ((raw[2] & 0xf) << 8) | raw[3];
59 pt->weight = raw[4];
60 pt->area = (raw[5] >> 4) & 0xf;
61}
62
42static void ft6x06_i2c_callback(int status, i2c_descriptor* desc) 63static void ft6x06_i2c_callback(int status, i2c_descriptor* desc)
43{ 64{
44 (void)desc; 65 (void)desc;
45 if(status != I2C_STATUS_OK) 66 if(status != I2C_STATUS_OK)
46 return; 67 return;
47 68
48 int evt = ft_drv.raw_data[1] >> 6; 69 ft6x06_state.gesture = ft_drv.raw_data[1];
49 int tx = ft_drv.raw_data[2] | ((ft_drv.raw_data[1] & 0xf) << 8); 70 ft6x06_state.nr_points = ft_drv.raw_data[2] & 0xf;
50 int ty = ft_drv.raw_data[4] | ((ft_drv.raw_data[3] & 0xf) << 8); 71 for(int i = 0; i < FT6x06_NUM_POINTS; ++i) {
51 72 ft6x06_convert_point(&ft_drv.raw_data[3 + i * BYTES_PER_POINT],
52 ft6x06_state.event = evt; 73 &ft6x06_state.points[i]);
53#ifdef FT6x06_SWAP_AXES 74 }
54 ft6x06_state.pos_x = ty;
55 ft6x06_state.pos_y = tx;
56#else
57 ft6x06_state.pos_x = tx;
58 ft6x06_state.pos_y = ty;
59#endif
60 75
61 ft_drv.event_cb(evt, ft6x06_state.pos_x, ft6x06_state.pos_y); 76 ft_drv.event_cb(&ft6x06_state);
62} 77}
63 78
64static void ft6x06_dummy_event_cb(int evt, int tx, int ty) 79static void ft6x06_dummy_event_cb(struct ft6x06_state* state)
65{ 80{
66 (void)evt; 81 (void)state;
67 (void)tx;
68 (void)ty;
69} 82}
70 83
71void ft6x06_init(void) 84void ft6x06_init(void)
@@ -74,9 +87,10 @@ void ft6x06_init(void)
74 memset(&ft_drv, 0, sizeof(ft_drv)); 87 memset(&ft_drv, 0, sizeof(ft_drv));
75 ft_drv.event_cb = ft6x06_dummy_event_cb; 88 ft_drv.event_cb = ft6x06_dummy_event_cb;
76 89
77 ft6x06_state.event = FT6x06_EVT_NONE; 90 memset(&ft6x06_state, 0, sizeof(struct ft6x06_state));
78 ft6x06_state.pos_x = 0; 91 ft6x06_state.gesture = -1;
79 ft6x06_state.pos_y = 0; 92 for(int i = 0; i < FT6x06_NUM_POINTS; ++i)
93 ft6x06_state.points[i].event = FT6x06_EVT_NONE;
80 94
81 /* Reserve bus management cookie */ 95 /* Reserve bus management cookie */
82 ft_drv.i2c_cookie = i2c_async_reserve_cookies(FT6x06_BUS, 1); 96 ft_drv.i2c_cookie = i2c_async_reserve_cookies(FT6x06_BUS, 1);
@@ -85,16 +99,16 @@ void ft6x06_init(void)
85 ft_drv.i2c_desc.slave_addr = FT6x06_ADDR; 99 ft_drv.i2c_desc.slave_addr = FT6x06_ADDR;
86 ft_drv.i2c_desc.bus_cond = I2C_START | I2C_STOP; 100 ft_drv.i2c_desc.bus_cond = I2C_START | I2C_STOP;
87 ft_drv.i2c_desc.tran_mode = I2C_READ; 101 ft_drv.i2c_desc.tran_mode = I2C_READ;
88 ft_drv.i2c_desc.buffer[0] = &ft_drv.raw_data[5]; 102 ft_drv.i2c_desc.buffer[0] = &ft_drv.raw_data[0];
89 ft_drv.i2c_desc.count[0] = 1; 103 ft_drv.i2c_desc.count[0] = 1;
90 ft_drv.i2c_desc.buffer[1] = &ft_drv.raw_data[0]; 104 ft_drv.i2c_desc.buffer[1] = &ft_drv.raw_data[1];
91 ft_drv.i2c_desc.count[1] = 5; 105 ft_drv.i2c_desc.count[1] = sizeof(ft_drv.raw_data) - 1;
92 ft_drv.i2c_desc.callback = ft6x06_i2c_callback; 106 ft_drv.i2c_desc.callback = ft6x06_i2c_callback;
93 ft_drv.i2c_desc.arg = 0; 107 ft_drv.i2c_desc.arg = 0;
94 ft_drv.i2c_desc.next = NULL; 108 ft_drv.i2c_desc.next = NULL;
95 109
96 /* Set I2C register address */ 110 /* Set I2C register address */
97 ft_drv.raw_data[5] = 0x02; 111 ft_drv.raw_data[0] = 0x01;
98} 112}
99 113
100void ft6x06_set_event_cb(ft6x06_event_cb cb) 114void ft6x06_set_event_cb(ft6x06_event_cb cb)