summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/ft6x06.c64
-rw-r--r--firmware/export/config/fiiom3k.h1
-rw-r--r--firmware/export/config/shanlingq1.h1
-rw-r--r--firmware/export/ft6x06.h23
-rw-r--r--firmware/target/mips/ingenic_x1000/debug-x1000.c6
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c5
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c83
7 files changed, 139 insertions, 44 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)
diff --git a/firmware/export/config/fiiom3k.h b/firmware/export/config/fiiom3k.h
index 29395bd433..61b6123a67 100644
--- a/firmware/export/config/fiiom3k.h
+++ b/firmware/export/config/fiiom3k.h
@@ -24,6 +24,7 @@
24#define HAVE_I2C_ASYNC 24#define HAVE_I2C_ASYNC
25#define HAVE_FT6x06 25#define HAVE_FT6x06
26#define FT6x06_SWAP_AXES 26#define FT6x06_SWAP_AXES
27#define FT6x06_NUM_POINTS 1
27 28
28/* Buffer for plugins and codecs. */ 29/* Buffer for plugins and codecs. */
29#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */ 30#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */
diff --git a/firmware/export/config/shanlingq1.h b/firmware/export/config/shanlingq1.h
index 1f1ee79ca7..16ce888958 100644
--- a/firmware/export/config/shanlingq1.h
+++ b/firmware/export/config/shanlingq1.h
@@ -59,6 +59,7 @@
59#define HAVE_TOUCHSCREEN 59#define HAVE_TOUCHSCREEN
60#define HAVE_BUTTON_DATA 60#define HAVE_BUTTON_DATA
61#define HAVE_FT6x06 61#define HAVE_FT6x06
62#define FT6x06_NUM_POINTS 5
62#define HAVE_HEADPHONE_DETECTION 63#define HAVE_HEADPHONE_DETECTION
63 64
64/* Storage defines */ 65/* Storage defines */
diff --git a/firmware/export/ft6x06.h b/firmware/export/ft6x06.h
index de1fdd0979..6596f89272 100644
--- a/firmware/export/ft6x06.h
+++ b/firmware/export/ft6x06.h
@@ -25,23 +25,32 @@
25#include "config.h" 25#include "config.h"
26#include <stdbool.h> 26#include <stdbool.h>
27 27
28typedef void(*ft6x06_event_cb)(int, int, int); 28enum ft6x06_event {
29 FT6x06_EVT_NONE = -1,
30 FT6x06_EVT_PRESS = 0,
31 FT6x06_EVT_RELEASE = 1,
32 FT6x06_EVT_CONTACT = 2,
33};
29 34
30struct ft6x06_state { 35struct ft6x06_point {
31 int event; 36 int event;
37 int touch_id;
32 int pos_x; 38 int pos_x;
33 int pos_y; 39 int pos_y;
40 int weight;
41 int area;
34}; 42};
35 43
36enum ft6x06_event { 44struct ft6x06_state {
37 FT6x06_EVT_NONE = -1, 45 int gesture;
38 FT6x06_EVT_PRESS = 0, 46 int nr_points;
39 FT6x06_EVT_RELEASE = 1, 47 struct ft6x06_point points[FT6x06_NUM_POINTS];
40 FT6x06_EVT_CONTACT = 2,
41}; 48};
42 49
43extern struct ft6x06_state ft6x06_state; 50extern struct ft6x06_state ft6x06_state;
44 51
52typedef void(*ft6x06_event_cb)(struct ft6x06_state* state);
53
45void ft6x06_init(void); 54void ft6x06_init(void);
46void ft6x06_set_event_cb(ft6x06_event_cb fn); 55void ft6x06_set_event_cb(ft6x06_event_cb fn);
47void ft6x06_enable(bool en); 56void ft6x06_enable(bool en);
diff --git a/firmware/target/mips/ingenic_x1000/debug-x1000.c b/firmware/target/mips/ingenic_x1000/debug-x1000.c
index 1965b0b74e..98b8f95fb5 100644
--- a/firmware/target/mips/ingenic_x1000/debug-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/debug-x1000.c
@@ -149,6 +149,9 @@ static bool dbg_cpuidle(void)
149#ifdef FIIO_M3K 149#ifdef FIIO_M3K
150extern bool dbg_fiiom3k_touchpad(void); 150extern bool dbg_fiiom3k_touchpad(void);
151#endif 151#endif
152#ifdef SHANLING_Q1
153extern bool dbg_shanlingq1_touchscreen(void);
154#endif
152#ifdef HAVE_AXP_PMU 155#ifdef HAVE_AXP_PMU
153extern bool axp_debug_menu(void); 156extern bool axp_debug_menu(void);
154#endif 157#endif
@@ -170,6 +173,9 @@ static const struct {
170#ifdef FIIO_M3K 173#ifdef FIIO_M3K
171 {"Touchpad", &dbg_fiiom3k_touchpad}, 174 {"Touchpad", &dbg_fiiom3k_touchpad},
172#endif 175#endif
176#ifdef SHANLING_Q1
177 {"Touchscreen", &dbg_shanlingq1_touchscreen},
178#endif
173#ifdef HAVE_AXP_PMU 179#ifdef HAVE_AXP_PMU
174 {"Power stats", &axp_debug_menu}, 180 {"Power stats", &axp_debug_menu},
175#endif 181#endif
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
index 04e3102d42..24daf2ef69 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c
@@ -318,7 +318,7 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
318 } 318 }
319} 319}
320 320
321static void ft_event_cb(int evt, int tx, int ty) 321static void ft_event_cb(struct ft6x06_state* state)
322{ 322{
323 /* TODO: convert the touch positions to linear positions. 323 /* TODO: convert the touch positions to linear positions.
324 * 324 *
@@ -327,7 +327,8 @@ static void ft_event_cb(int evt, int tx, int ty)
327 * the middle of the touchpad than on the edges, so scrolling feels slow 327 * the middle of the touchpad than on the edges, so scrolling feels slow
328 * in the middle and faster near the edge. 328 * in the middle and faster near the edge.
329 */ 329 */
330 ft_step_state(__ost_read32(), evt, tx, ty); 330 struct ft6x06_point* pt = &state->points[0];
331 ft_step_state(__ost_read32(), pt->event, pt->pos_x, pt->pos_y);
331} 332}
332 333
333static void ft_init(void) 334static void ft_init(void)
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
index 27c49a7bd7..13b0cdd078 100644
--- a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
@@ -32,6 +32,11 @@
32#include "i2c-x1000.h" 32#include "i2c-x1000.h"
33#include <stdbool.h> 33#include <stdbool.h>
34 34
35#ifndef BOOTLOADER
36# include "lcd.h"
37# include "font.h"
38#endif
39
35/* Volume wheel rotation */ 40/* Volume wheel rotation */
36static volatile int wheel_pos = 0; 41static volatile int wheel_pos = 0;
37 42
@@ -109,6 +114,7 @@ void button_init_device(void)
109 114
110int button_read_device(int* data) 115int button_read_device(int* data)
111{ 116{
117 const struct ft6x06_point* point;
112 int r = 0; 118 int r = 0;
113 119
114 /* Read GPIO buttons, these are all active low */ 120 /* Read GPIO buttons, these are all active low */
@@ -138,16 +144,22 @@ int button_read_device(int* data)
138 reset_poweroff_timer(); 144 reset_poweroff_timer();
139 } 145 }
140 146
141 /* Handle touchscreen 147 if(touchscreen_get_mode() == TOUCHSCREEN_POINT) {
142 * 148 /* Pointing mode can't use multitouch since we can only pass
143 * TODO: Support 2-point multitouch (useful for 3x3 grid mode) 149 * along coordinates for one touch event at a time */
144 * TODO: Support simple gestures by converting them to fake buttons 150 point = &ft6x06_state.points[0];
145 */ 151 int t = touchscreen_to_pixels(point->pos_x, point->pos_y, data);
146 int t = touchscreen_to_pixels(ft6x06_state.pos_x, ft6x06_state.pos_y, data); 152 if(point->event == FT6x06_EVT_PRESS ||
147 if(ft6x06_state.event == FT6x06_EVT_PRESS || 153 point->event == FT6x06_EVT_CONTACT)
148 ft6x06_state.event == FT6x06_EVT_CONTACT) { 154 r |= t;
149 /* Only set the button bit if the screen is being touched. */ 155 } else {
150 r |= t; 156 /* 3x3 mode can have simultaneous 'button' presses via multitouch */
157 for(int i = 0; i < ft6x06_state.nr_points; ++i) {
158 point = &ft6x06_state.points[i];
159 if(point->event == FT6x06_EVT_PRESS ||
160 point->event == FT6x06_EVT_CONTACT)
161 r |= touchscreen_to_pixels(point->pos_x, point->pos_y, NULL);
162 }
151 } 163 }
152 164
153 return r; 165 return r;
@@ -193,3 +205,54 @@ void GPIOD03(void)
193 handle_wheel_irq(); 205 handle_wheel_irq();
194 gpio_flip_edge_irq(GPIO_WHEEL2); 206 gpio_flip_edge_irq(GPIO_WHEEL2);
195} 207}
208
209#ifndef BOOTLOADER
210static int getbtn(void)
211{
212 int btn;
213 do {
214 btn = button_get_w_tmo(1);
215 } while(btn & (BUTTON_REL|BUTTON_REPEAT));
216 return btn;
217}
218
219bool dbg_shanlingq1_touchscreen(void)
220{
221 /* definition of box used to represent the touchpad */
222 const int pad_w = LCD_WIDTH;
223 const int pad_h = LCD_HEIGHT;
224 const int box_h = pad_h - SYSFONT_HEIGHT*5;
225 const int box_w = pad_w * box_h / pad_h;
226 const int box_x = (LCD_WIDTH - box_w) / 2;
227 const int box_y = SYSFONT_HEIGHT * 9 / 2;
228
229 bool draw_border = true;
230
231 do {
232 int line = 0;
233 lcd_clear_display();
234 lcd_putsf(0, line++, "nr_points: %d gesture: %d",
235 ft6x06_state.nr_points, ft6x06_state.gesture);
236
237 /* draw touchpad box borders */
238 if(draw_border)
239 lcd_drawrect(box_x, box_y, box_w, box_h);
240
241 for(int i = 0; i < ft6x06_state.nr_points; ++i) {
242 const struct ft6x06_point* point = &ft6x06_state.points[i];
243 lcd_putsf(0, line++, "pt%d id:%d pos: %d,%d wgt: %d area:%d",
244 i, point->touch_id, point->pos_x, point->pos_y,
245 point->weight, point->area);
246
247 /* draw crosshair */
248 int tx = box_x + point->pos_x * box_w / pad_w;
249 int ty = box_y + point->pos_y * box_h / pad_h;
250 lcd_hline(tx-2, tx+2, ty);
251 lcd_vline(tx, ty-2, ty+2);
252 }
253
254 lcd_update();
255 } while(getbtn() != BUTTON_POWER);
256 return false;
257}
258#endif