diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/ft6x06.c | 64 | ||||
-rw-r--r-- | firmware/export/config/fiiom3k.h | 1 | ||||
-rw-r--r-- | firmware/export/config/shanlingq1.h | 1 | ||||
-rw-r--r-- | firmware/export/ft6x06.h | 23 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/debug-x1000.c | 6 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c | 5 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c | 83 |
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 | |||
27 | struct ft6x06_driver { | 37 | struct 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 | ||
39 | static struct ft6x06_driver ft_drv; | 49 | static struct ft6x06_driver ft_drv; |
40 | struct ft6x06_state ft6x06_state; | 50 | struct ft6x06_state ft6x06_state; |
41 | 51 | ||
52 | static 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 | |||
42 | static void ft6x06_i2c_callback(int status, i2c_descriptor* desc) | 63 | static 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 | ||
64 | static void ft6x06_dummy_event_cb(int evt, int tx, int ty) | 79 | static 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 | ||
71 | void ft6x06_init(void) | 84 | void 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 | ||
100 | void ft6x06_set_event_cb(ft6x06_event_cb cb) | 114 | void 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 | ||
28 | typedef void(*ft6x06_event_cb)(int, int, int); | 28 | enum 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 | ||
30 | struct ft6x06_state { | 35 | struct 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 | ||
36 | enum ft6x06_event { | 44 | struct 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 | ||
43 | extern struct ft6x06_state ft6x06_state; | 50 | extern struct ft6x06_state ft6x06_state; |
44 | 51 | ||
52 | typedef void(*ft6x06_event_cb)(struct ft6x06_state* state); | ||
53 | |||
45 | void ft6x06_init(void); | 54 | void ft6x06_init(void); |
46 | void ft6x06_set_event_cb(ft6x06_event_cb fn); | 55 | void ft6x06_set_event_cb(ft6x06_event_cb fn); |
47 | void ft6x06_enable(bool en); | 56 | void 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 |
150 | extern bool dbg_fiiom3k_touchpad(void); | 150 | extern bool dbg_fiiom3k_touchpad(void); |
151 | #endif | 151 | #endif |
152 | #ifdef SHANLING_Q1 | ||
153 | extern bool dbg_shanlingq1_touchscreen(void); | ||
154 | #endif | ||
152 | #ifdef HAVE_AXP_PMU | 155 | #ifdef HAVE_AXP_PMU |
153 | extern bool axp_debug_menu(void); | 156 | extern 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 | ||
321 | static void ft_event_cb(int evt, int tx, int ty) | 321 | static 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 | ||
333 | static void ft_init(void) | 334 | static 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 */ |
36 | static volatile int wheel_pos = 0; | 41 | static volatile int wheel_pos = 0; |
37 | 42 | ||
@@ -109,6 +114,7 @@ void button_init_device(void) | |||
109 | 114 | ||
110 | int button_read_device(int* data) | 115 | int 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 | ||
210 | static 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 | |||
219 | bool 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 | ||