summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-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 @@
#include "i2c-async.h"
#include <string.h>
+#define BYTES_PER_POINT 6
+
+#ifdef FT6x06_SWAP_AXES
+# define POS_X pos_y
+# define POS_Y pos_x
+#else
+# define POS_X pos_x
+# define POS_Y pos_y
+#endif
+
struct ft6x06_driver {
/* i2c bus data */
int i2c_cookie;
@@ -33,39 +43,42 @@ struct ft6x06_driver {
ft6x06_event_cb event_cb;
/* buffer for I2C transfers */
- uint8_t raw_data[6];
+ uint8_t raw_data[1 + 2 + BYTES_PER_POINT * FT6x06_NUM_POINTS];
};
static struct ft6x06_driver ft_drv;
struct ft6x06_state ft6x06_state;
+static inline void ft6x06_convert_point(const uint8_t* raw,
+ struct ft6x06_point* pt)
+{
+ pt->event = (raw[0] >> 6) & 0x3;
+ pt->touch_id = (raw[2] >> 4) & 0xf;
+ pt->POS_X = ((raw[0] & 0xf) << 8) | raw[1];
+ pt->POS_Y = ((raw[2] & 0xf) << 8) | raw[3];
+ pt->weight = raw[4];
+ pt->area = (raw[5] >> 4) & 0xf;
+}
+
static void ft6x06_i2c_callback(int status, i2c_descriptor* desc)
{
(void)desc;
if(status != I2C_STATUS_OK)
return;
- int evt = ft_drv.raw_data[1] >> 6;
- int tx = ft_drv.raw_data[2] | ((ft_drv.raw_data[1] & 0xf) << 8);
- int ty = ft_drv.raw_data[4] | ((ft_drv.raw_data[3] & 0xf) << 8);
-
- ft6x06_state.event = evt;
-#ifdef FT6x06_SWAP_AXES
- ft6x06_state.pos_x = ty;
- ft6x06_state.pos_y = tx;
-#else
- ft6x06_state.pos_x = tx;
- ft6x06_state.pos_y = ty;
-#endif
+ ft6x06_state.gesture = ft_drv.raw_data[1];
+ ft6x06_state.nr_points = ft_drv.raw_data[2] & 0xf;
+ for(int i = 0; i < FT6x06_NUM_POINTS; ++i) {
+ ft6x06_convert_point(&ft_drv.raw_data[3 + i * BYTES_PER_POINT],
+ &ft6x06_state.points[i]);
+ }
- ft_drv.event_cb(evt, ft6x06_state.pos_x, ft6x06_state.pos_y);
+ ft_drv.event_cb(&ft6x06_state);
}
-static void ft6x06_dummy_event_cb(int evt, int tx, int ty)
+static void ft6x06_dummy_event_cb(struct ft6x06_state* state)
{
- (void)evt;
- (void)tx;
- (void)ty;
+ (void)state;
}
void ft6x06_init(void)
@@ -74,9 +87,10 @@ void ft6x06_init(void)
memset(&ft_drv, 0, sizeof(ft_drv));
ft_drv.event_cb = ft6x06_dummy_event_cb;
- ft6x06_state.event = FT6x06_EVT_NONE;
- ft6x06_state.pos_x = 0;
- ft6x06_state.pos_y = 0;
+ memset(&ft6x06_state, 0, sizeof(struct ft6x06_state));
+ ft6x06_state.gesture = -1;
+ for(int i = 0; i < FT6x06_NUM_POINTS; ++i)
+ ft6x06_state.points[i].event = FT6x06_EVT_NONE;
/* Reserve bus management cookie */
ft_drv.i2c_cookie = i2c_async_reserve_cookies(FT6x06_BUS, 1);
@@ -85,16 +99,16 @@ void ft6x06_init(void)
ft_drv.i2c_desc.slave_addr = FT6x06_ADDR;
ft_drv.i2c_desc.bus_cond = I2C_START | I2C_STOP;
ft_drv.i2c_desc.tran_mode = I2C_READ;
- ft_drv.i2c_desc.buffer[0] = &ft_drv.raw_data[5];
+ ft_drv.i2c_desc.buffer[0] = &ft_drv.raw_data[0];
ft_drv.i2c_desc.count[0] = 1;
- ft_drv.i2c_desc.buffer[1] = &ft_drv.raw_data[0];
- ft_drv.i2c_desc.count[1] = 5;
+ ft_drv.i2c_desc.buffer[1] = &ft_drv.raw_data[1];
+ ft_drv.i2c_desc.count[1] = sizeof(ft_drv.raw_data) - 1;
ft_drv.i2c_desc.callback = ft6x06_i2c_callback;
ft_drv.i2c_desc.arg = 0;
ft_drv.i2c_desc.next = NULL;
/* Set I2C register address */
- ft_drv.raw_data[5] = 0x02;
+ ft_drv.raw_data[0] = 0x01;
}
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 @@
#define HAVE_I2C_ASYNC
#define HAVE_FT6x06
#define FT6x06_SWAP_AXES
+#define FT6x06_NUM_POINTS 1
/* Buffer for plugins and codecs. */
#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 @@
#define HAVE_TOUCHSCREEN
#define HAVE_BUTTON_DATA
#define HAVE_FT6x06
+#define FT6x06_NUM_POINTS 5
#define HAVE_HEADPHONE_DETECTION
/* 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 @@
#include "config.h"
#include <stdbool.h>
-typedef void(*ft6x06_event_cb)(int, int, int);
+enum ft6x06_event {
+ FT6x06_EVT_NONE = -1,
+ FT6x06_EVT_PRESS = 0,
+ FT6x06_EVT_RELEASE = 1,
+ FT6x06_EVT_CONTACT = 2,
+};
-struct ft6x06_state {
+struct ft6x06_point {
int event;
+ int touch_id;
int pos_x;
int pos_y;
+ int weight;
+ int area;
};
-enum ft6x06_event {
- FT6x06_EVT_NONE = -1,
- FT6x06_EVT_PRESS = 0,
- FT6x06_EVT_RELEASE = 1,
- FT6x06_EVT_CONTACT = 2,
+struct ft6x06_state {
+ int gesture;
+ int nr_points;
+ struct ft6x06_point points[FT6x06_NUM_POINTS];
};
extern struct ft6x06_state ft6x06_state;
+typedef void(*ft6x06_event_cb)(struct ft6x06_state* state);
+
void ft6x06_init(void);
void ft6x06_set_event_cb(ft6x06_event_cb fn);
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)
#ifdef FIIO_M3K
extern bool dbg_fiiom3k_touchpad(void);
#endif
+#ifdef SHANLING_Q1
+extern bool dbg_shanlingq1_touchscreen(void);
+#endif
#ifdef HAVE_AXP_PMU
extern bool axp_debug_menu(void);
#endif
@@ -170,6 +173,9 @@ static const struct {
#ifdef FIIO_M3K
{"Touchpad", &dbg_fiiom3k_touchpad},
#endif
+#ifdef SHANLING_Q1
+ {"Touchscreen", &dbg_shanlingq1_touchscreen},
+#endif
#ifdef HAVE_AXP_PMU
{"Power stats", &axp_debug_menu},
#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)
}
}
-static void ft_event_cb(int evt, int tx, int ty)
+static void ft_event_cb(struct ft6x06_state* state)
{
/* TODO: convert the touch positions to linear positions.
*
@@ -327,7 +327,8 @@ static void ft_event_cb(int evt, int tx, int ty)
* the middle of the touchpad than on the edges, so scrolling feels slow
* in the middle and faster near the edge.
*/
- ft_step_state(__ost_read32(), evt, tx, ty);
+ struct ft6x06_point* pt = &state->points[0];
+ ft_step_state(__ost_read32(), pt->event, pt->pos_x, pt->pos_y);
}
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 @@
#include "i2c-x1000.h"
#include <stdbool.h>
+#ifndef BOOTLOADER
+# include "lcd.h"
+# include "font.h"
+#endif
+
/* Volume wheel rotation */
static volatile int wheel_pos = 0;
@@ -109,6 +114,7 @@ void button_init_device(void)
int button_read_device(int* data)
{
+ const struct ft6x06_point* point;
int r = 0;
/* Read GPIO buttons, these are all active low */
@@ -138,16 +144,22 @@ int button_read_device(int* data)
reset_poweroff_timer();
}
- /* Handle touchscreen
- *
- * TODO: Support 2-point multitouch (useful for 3x3 grid mode)
- * TODO: Support simple gestures by converting them to fake buttons
- */
- int t = touchscreen_to_pixels(ft6x06_state.pos_x, ft6x06_state.pos_y, data);
- if(ft6x06_state.event == FT6x06_EVT_PRESS ||
- ft6x06_state.event == FT6x06_EVT_CONTACT) {
- /* Only set the button bit if the screen is being touched. */
- r |= t;
+ if(touchscreen_get_mode() == TOUCHSCREEN_POINT) {
+ /* Pointing mode can't use multitouch since we can only pass
+ * along coordinates for one touch event at a time */
+ point = &ft6x06_state.points[0];
+ int t = touchscreen_to_pixels(point->pos_x, point->pos_y, data);
+ if(point->event == FT6x06_EVT_PRESS ||
+ point->event == FT6x06_EVT_CONTACT)
+ r |= t;
+ } else {
+ /* 3x3 mode can have simultaneous 'button' presses via multitouch */
+ for(int i = 0; i < ft6x06_state.nr_points; ++i) {
+ point = &ft6x06_state.points[i];
+ if(point->event == FT6x06_EVT_PRESS ||
+ point->event == FT6x06_EVT_CONTACT)
+ r |= touchscreen_to_pixels(point->pos_x, point->pos_y, NULL);
+ }
}
return r;
@@ -193,3 +205,54 @@ void GPIOD03(void)
handle_wheel_irq();
gpio_flip_edge_irq(GPIO_WHEEL2);
}
+
+#ifndef BOOTLOADER
+static int getbtn(void)
+{
+ int btn;
+ do {
+ btn = button_get_w_tmo(1);
+ } while(btn & (BUTTON_REL|BUTTON_REPEAT));
+ return btn;
+}
+
+bool dbg_shanlingq1_touchscreen(void)
+{
+ /* definition of box used to represent the touchpad */
+ const int pad_w = LCD_WIDTH;
+ const int pad_h = LCD_HEIGHT;
+ const int box_h = pad_h - SYSFONT_HEIGHT*5;
+ const int box_w = pad_w * box_h / pad_h;
+ const int box_x = (LCD_WIDTH - box_w) / 2;
+ const int box_y = SYSFONT_HEIGHT * 9 / 2;
+
+ bool draw_border = true;
+
+ do {
+ int line = 0;
+ lcd_clear_display();
+ lcd_putsf(0, line++, "nr_points: %d gesture: %d",
+ ft6x06_state.nr_points, ft6x06_state.gesture);
+
+ /* draw touchpad box borders */
+ if(draw_border)
+ lcd_drawrect(box_x, box_y, box_w, box_h);
+
+ for(int i = 0; i < ft6x06_state.nr_points; ++i) {
+ const struct ft6x06_point* point = &ft6x06_state.points[i];
+ lcd_putsf(0, line++, "pt%d id:%d pos: %d,%d wgt: %d area:%d",
+ i, point->touch_id, point->pos_x, point->pos_y,
+ point->weight, point->area);
+
+ /* draw crosshair */
+ int tx = box_x + point->pos_x * box_w / pad_w;
+ int ty = box_y + point->pos_y * box_h / pad_h;
+ lcd_hline(tx-2, tx+2, ty);
+ lcd_vline(tx, ty-2, ty+2);
+ }
+
+ lcd_update();
+ } while(getbtn() != BUTTON_POWER);
+ return false;
+}
+#endif