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 @@ #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 |