summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/export/synaptics-rmi.h68
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c146
2 files changed, 186 insertions, 28 deletions
diff --git a/firmware/export/synaptics-rmi.h b/firmware/export/synaptics-rmi.h
index 59fbb807ab..2d7a0c8c1e 100644
--- a/firmware/export/synaptics-rmi.h
+++ b/firmware/export/synaptics-rmi.h
@@ -41,6 +41,74 @@
41#define RMI_2D_SENSOR_YMAX_MSB(s) RMI_2D_REG(8 * (s) + 0x6) 41#define RMI_2D_SENSOR_YMAX_MSB(s) RMI_2D_REG(8 * (s) + 0x6)
42#define RMI_2D_SENSOR_YMAX_LSB(s) RMI_2D_REG(8 * (s) + 0x7) 42#define RMI_2D_SENSOR_YMAX_LSB(s) RMI_2D_REG(8 * (s) + 0x7)
43#define RMI_2D_SENSOR_RESOLUTION(s) RMI_2D_REG(8 * (s) + 0x8) 43#define RMI_2D_SENSOR_RESOLUTION(s) RMI_2D_REG(8 * (s) + 0x8)
44#define RMI_2D_GLOBAL_SETTINGS RMI_2D_REG(0x41)
45#define RMI_2D_GESTURE_SETTINGS RMI_2D_REG(0x42)
46#define RMI_2D_GESTURE_PRESS_TIME_BM 0x7
47#define RMI_2D_GESTURE_PRESS_TIME_300MS 0
48#define RMI_2D_GESTURE_PRESS_TIME_400MS 1
49#define RMI_2D_GESTURE_PRESS_TIME_500MS 2
50#define RMI_2D_GESTURE_PRESS_TIME_600MS 3
51#define RMI_2D_GESTURE_PRESS_TIME_700MS 4
52#define RMI_2D_GESTURE_PRESS_TIME_800MS 5
53#define RMI_2D_GESTURE_PRESS_TIME_900MS 6
54#define RMI_2D_GESTURE_PRESS_TIME_1S 7
55#define RMI_2D_GESTURE_FLICK_DIST_BM (0x7 << 3)
56#define RMI_2D_GESTURE_FLICK_DIST_BP 3
57#define RMI_2D_GESTURE_FLICK_DIST_4MM 0
58#define RMI_2D_GESTURE_FLICK_DIST_5MM 1
59#define RMI_2D_GESTURE_FLICK_DIST_6MM 2
60#define RMI_2D_GESTURE_FLICK_DIST_7MM 3
61#define RMI_2D_GESTURE_FLICK_DIST_8MM 4
62#define RMI_2D_GESTURE_FLICK_DIST_9MM 5
63#define RMI_2D_GESTURE_FLICK_DIST_10MM 6
64#define RMI_2D_GESTURE_FLICK_DIST_11MM 7
65#define RMI_2D_GESTURE_FLICK_TIME_BM (2 << 6)
66#define RMI_2D_GESTURE_FLICK_TIME_BP 6
67#define RMI_2D_GESTURE_FLICK_TIME_250MS 0
68#define RMI_2D_GESTURE_FLICK_TIME_400MS 1
69#define RMI_2D_GESTURE_FLICK_TIME_550MS 2
70#define RMI_2D_GESTURE_FLICK_TIME_700MS 3
71#define RMI_2D_SENSITIVITY_ADJ RMI_2D_REG(0x44)
72#define RMI_2D_MIN_DIST RMI_2D_REG(0x45)
73/* 2D TouchPad/ClearPad data registers */
74struct rmi_2d_absolute_data_t
75{
76 unsigned char misc;
77 unsigned char z;
78 unsigned char x_msb;
79 unsigned char x_lsb;
80 unsigned char y_msb;
81 unsigned char y_lsb;
82} __attribute__((packed));
83
84#define RMI_2D_ABS_MISC_NR_FINGERS_BM 7
85#define RMI_2D_ABS_MISC_GESTURE (1 << 3)
86#define RMI_2D_ABS_MISC_WIDTH_BM 0xf0
87#define RMI_2D_ABS_MISC_WIDTH_BP 4
88#define RMI_2D_GEST_MISC_TAP_CODE_BM 7
89#define RMI_2D_GEST_MISC_NO_TAP 0
90#define RMI_2D_GEST_MISC_SINGLE_TAP 1
91#define RMI_2D_GEST_MISC_TAP_AND_HOLD 2
92#define RMI_2D_GEST_MISC_DOUBLE_TAP 3
93#define RMI_2D_GEST_MISC_PRESS (1 << 3)
94#define RMI_2D_GEST_MISC_FLICK (1 << 4)
95#define RMI_2D_GEST_MISC_PINCH (1 << 5)
96#define RMI_2D_GEST_MISC_CONFIRMED (1 << 7)
97#define RMI_2D_GEST_FLICK_X_BM 0x0f
98#define RMI_2D_GEST_FLICK_Y_BM 0xf0
99#define RMI_2D_GEST_FLICK_Y_BP 4
100
101struct rmi_2d_relative_data_t
102{
103 signed char x; /* signed */
104 signed char y; /* signed */
105} __attribute__((packed));
106
107struct rmi_2d_gesture_data_t
108{
109 unsigned char misc;
110 unsigned char flick;
111} __attribute__((packed));
44 112
45/* Initialize the RMI driver, the i2c_bus_index is the bus index returned by 113/* Initialize the RMI driver, the i2c_bus_index is the bus index returned by
46 * the generic_i2c driver; the i2c_dev_addr is the i2c address of the device. 114 * the generic_i2c driver; the i2c_dev_addr is the i2c address of the device.
diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c b/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c
index 1b8116b1b7..b6de9f73d8 100644
--- a/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c
+++ b/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c
@@ -25,6 +25,7 @@
25#include "generic_i2c.h" 25#include "generic_i2c.h"
26#include "synaptics-rmi.h" 26#include "synaptics-rmi.h"
27#include "lcd.h" 27#include "lcd.h"
28#include "string.h"
28 29
29static void i2c_scl_dir(bool out) 30static void i2c_scl_dir(bool out)
30{ 31{
@@ -84,51 +85,135 @@ void button_debug_screen(void)
84{ 85{
85 char product_id[RMI_PRODUCT_ID_LEN]; 86 char product_id[RMI_PRODUCT_ID_LEN];
86 rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id); 87 rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id);
88 int x_max = rmi_read_single(RMI_2D_SENSOR_XMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_XMAX_LSB(0));
89 int y_max = rmi_read_single(RMI_2D_SENSOR_YMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_YMAX_LSB(0));
90 int func_presence = rmi_read_single(RMI_FUNCTION_PRESENCE(RMI_2D_TOUCHPAD_FUNCTION));
91 int sensor_prop = rmi_read_single(RMI_2D_SENSOR_PROP2(0));
92 int sensor_resol = rmi_read_single(RMI_2D_SENSOR_RESOLUTION(0));
93 int min_dist = rmi_read_single(RMI_2D_MIN_DIST);
94 int gesture_settings = rmi_read_single(RMI_2D_GESTURE_SETTINGS);
95 union
96 {
97 unsigned char data;
98 signed char value;
99 }sensitivity;
100 rmi_read(RMI_2D_SENSITIVITY_ADJ, 1, &sensitivity.data);
87 101
102 /* Device to screen */
103 int zone_w = LCD_WIDTH;
104 int zone_h = (zone_w * y_max + x_max - 1) / x_max;
105 int zone_x = 0;
106 int zone_y = LCD_HEIGHT - zone_h;
107 #define DX2SX(x) (((x) * zone_w ) / x_max)
108 #define DY2SY(y) (zone_h - ((y) * zone_h ) / y_max)
109 struct viewport report_vp;
110 memset(&report_vp, 0, sizeof(report_vp));
111 report_vp.x = zone_x;
112 report_vp.y = zone_y;
113 report_vp.width = zone_w;
114 report_vp.height = zone_h;
115 struct viewport gesture_vp;
116 memset(&gesture_vp, 0, sizeof(gesture_vp));
117 gesture_vp.x = 0;
118 gesture_vp.y = zone_y - 80;
119 gesture_vp.width = LCD_WIDTH;
120 gesture_vp.height = 80;
121
88 while(1) 122 while(1)
89 { 123 {
124 lcd_set_viewport(NULL);
90 lcd_clear_display(); 125 lcd_clear_display();
91 int btns = button_read_device(); 126 int btns = button_read_device();
92 lcd_putsf(0, 0, "button bitmap: %x", btns); 127 lcd_putsf(0, 0, "button bitmap: %x", btns);
93 lcd_putsf(0, 1, "RMI: product=%s", product_id); 128 lcd_putsf(0, 1, "RMI: id=%s p=%x s=%x", product_id, func_presence, sensor_prop);
94 lcd_putsf(0, 2, "touchpad presence: %x", rmi_read_single(RMI_FUNCTION_PRESENCE(RMI_2D_TOUCHPAD_FUNCTION))); 129 lcd_putsf(0, 2, "xmax=%d ymax=%d res=%d", x_max, y_max, sensor_resol);
95 lcd_putsf(0, 3, "sensor prop: %x", rmi_read_single(RMI_2D_SENSOR_PROP2(0))); 130 lcd_putsf(0, 3, "attn=%d ctl=%x int=%x",
96 int x_max = rmi_read_single(RMI_2D_SENSOR_XMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_XMAX_LSB(0)); 131 imx233_get_gpio_input_mask(0, 0x08000000) ? 0 : 1,
97 int y_max = rmi_read_single(RMI_2D_SENSOR_YMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_YMAX_LSB(0)); 132 rmi_read_single(RMI_DEVICE_CONTROL),
98 lcd_putsf(0, 4, "xmax=%d ymax=%d res=%d", x_max, y_max, 133 rmi_read_single(RMI_INTERRUPT_REQUEST));
99 rmi_read_single(RMI_2D_SENSOR_RESOLUTION(0))); 134 lcd_putsf(0, 4, "sensi: %d min_dist: %d", (int)sensitivity.value, min_dist);
100 lcd_putsf(0, 5, "din0=%x", imx233_get_gpio_input_mask(0, 0x08000000)); 135 lcd_putsf(0, 5, "gesture: %x", gesture_settings);
101 lcd_putsf(0, 6, "dev ctl: %x", rmi_read_single(RMI_DEVICE_CONTROL)); 136
102 lcd_putsf(0, 7, "int en: %x", rmi_read_single(RMI_INTERRUPT_ENABLE));
103 lcd_putsf(0, 8, "int req: %x", rmi_read_single(RMI_INTERRUPT_REQUEST));
104 union 137 union
105 { 138 {
106 unsigned char data[10]; 139 unsigned char data[10];
107 struct 140 struct
108 { 141 {
109 unsigned char absolute_misc; 142 struct rmi_2d_absolute_data_t absolute;
110 unsigned char absolute_z; 143 struct rmi_2d_relative_data_t relative;
111 unsigned char absolute_x_msb; 144 struct rmi_2d_gesture_data_t gesture;
112 unsigned char absolute_x_lsb; 145 }s;
113 unsigned char absolute_y_msb;
114 unsigned char absolute_y_lsb;
115 signed char relative_x; /* signed */
116 signed char relative_y; /* signed */
117 unsigned char gesture_misc;
118 unsigned char gesture_flick;
119 } __attribute__((packed)) s;
120 }u; 146 }u;
121 int absolute_x = u.s.absolute_x_msb << 8 | u.s.absolute_x_lsb; 147 int absolute_x = u.s.absolute.x_msb << 8 | u.s.absolute.x_lsb;
122 int absolute_y = u.s.absolute_y_msb << 8 | u.s.absolute_y_lsb; 148 int absolute_y = u.s.absolute.y_msb << 8 | u.s.absolute.y_lsb;
149 int nr_fingers = u.s.absolute.misc & 7;
150 bool gesture = (u.s.absolute.misc & 8) == 8;
151 int palm_width = u.s.absolute.misc >> 4;
123 rmi_read(RMI_DATA_REGISTER(0), 10, u.data); 152 rmi_read(RMI_DATA_REGISTER(0), 10, u.data);
124 lcd_putsf(0, 9, "abs: %d %d", absolute_x, absolute_y); 153 lcd_putsf(0, 6, "abs: %d %d %d", absolute_x, absolute_y, (int)u.s.absolute.z);
125 lcd_putsf(0, 10, "rel: %d %d", (int)u.s.relative_x, (int)u.s.relative_y); 154 lcd_putsf(0, 7, "rel: %d %d", (int)u.s.relative.x, (int)u.s.relative.y);
126 lcd_putsf(0, 11, "gesture: %x %x", u.s.gesture_misc, u.s.gesture_flick); 155 lcd_putsf(0, 8, "gesture: %x %x", u.s.gesture.misc, u.s.gesture.flick);
127 156 lcd_putsf(0, 9, "misc: w=%d g=%d f=%d", palm_width, gesture, nr_fingers);
157
158 lcd_set_viewport(&report_vp);
159 lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0, 0), LCD_BLACK);
160 lcd_drawrect(0, 0, zone_w, zone_h);
161 if(nr_fingers == 1)
162 {
163 lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0, 0xff), LCD_BLACK);
164 lcd_drawline(DX2SX(absolute_x) - u.s.relative.x,
165 DY2SY(absolute_y) + u.s.relative.y,
166 DX2SX(absolute_x), DY2SY(absolute_y));
167 lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0xff, 0), LCD_BLACK);
168 lcd_fillrect(DX2SX(absolute_x) - 1, DY2SY(absolute_y) - 1, 3, 3);
169 }
170 lcd_set_viewport(&gesture_vp);
171 lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0xff, 0), LCD_BLACK);
172 if(u.s.gesture.misc & RMI_2D_GEST_MISC_CONFIRMED)
173 {
174 switch(u.s.gesture.misc & RMI_2D_GEST_MISC_TAP_CODE_BM)
175 {
176 case RMI_2D_GEST_MISC_NO_TAP: break;
177 case RMI_2D_GEST_MISC_SINGLE_TAP:
178 lcd_putsf(0, 0, "TAP!");
179 break;
180 case RMI_2D_GEST_MISC_DOUBLE_TAP:
181 lcd_putsf(0, 0, "DOUBLE TAP!");
182 break;
183 case RMI_2D_GEST_MISC_TAP_AND_HOLD:
184 lcd_putsf(0, 0, "TAP & HOLD!");
185 break;
186 default: break;
187 }
188
189 if(u.s.gesture.misc & RMI_2D_GEST_MISC_FLICK)
190 {
191 lcd_putsf(0, 1, "FLICK!");
192 int flick_x = u.s.gesture.flick & RMI_2D_GEST_FLICK_X_BM;
193 int flick_y = (u.s.gesture.flick & RMI_2D_GEST_FLICK_Y_BM) >> RMI_2D_GEST_FLICK_Y_BP;
194 #define SIGN4EXT(a) \
195 if(a & 8) a = -((a ^ 0xf) + 1);
196 SIGN4EXT(flick_x);
197 SIGN4EXT(flick_y);
198
199 int center_x = (LCD_WIDTH * 2) / 3;
200 int center_y = 40;
201 lcd_drawline(center_x, center_y, center_x + flick_x * 5, center_y - flick_y * 5);
202 }
203 }
128 lcd_update(); 204 lcd_update();
129 205
130 if(btns & BUTTON_POWER) 206 if(btns & BUTTON_POWER)
131 break; 207 break;
208 if(btns & BUTTON_VOL_DOWN || btns & BUTTON_VOL_UP)
209 {
210 if(btns & BUTTON_VOL_UP)
211 sensitivity.value++;
212 if(btns & BUTTON_VOL_DOWN)
213 sensitivity.value--;
214 rmi_write(RMI_2D_SENSITIVITY_ADJ, 1, &sensitivity.data);
215 }
216
132 yield(); 217 yield();
133 } 218 }
134} 219}
@@ -159,6 +244,11 @@ void button_init_device(void)
159 * 244 *
160 * ATTENTION line: B0P27 asserted low 245 * ATTENTION line: B0P27 asserted low
161 */ 246 */
247 rmi_write_single(RMI_2D_SENSITIVITY_ADJ, 5);
248 rmi_write_single(RMI_2D_GESTURE_SETTINGS,
249 RMI_2D_GESTURE_PRESS_TIME_300MS |
250 RMI_2D_GESTURE_FLICK_DIST_4MM << RMI_2D_GESTURE_FLICK_DIST_BP |
251 RMI_2D_GESTURE_FLICK_TIME_700MS << RMI_2D_GESTURE_FLICK_TIME_BP);
162} 252}
163 253
164int button_read_device(void) 254int button_read_device(void)