2 * tslib/plugins/cy8mrln-palmpre.c
4 * Copyright (C) 2010 Frederik Sdun <frederik.sdun@googlemail.com>
5 * Thomas Zimmermann <ml@vdm-design.de>
8 * This file is placed under the LGPL. Please see the file
9 * COPYING for more details.
12 * Pluging for the cy8mrln touchscreen with the Firmware used on the Palm Pre
22 #include <sys/ioctl.h>
24 #include <sys/types.h>
28 #include "tslib-private.h"
29 #include "tslib-filter.h"
34 #define SCREEN_WIDTH 319
35 #define SCREEN_HEIGHT 527
41 #define container_of(ptr, type, member) ({ \
42 const typeof( ((type*)0)->member ) *__mptr = (ptr); \
43 (type *)( (char *)__mptr - offsetof(type, member)); })
45 struct cy8mrln_palmpre_input
48 uint16_t field[H_FIELDS * V_FIELDS];
49 uint16_t ffff; //seperator? always ff
50 uint8_t seq_nr1; //incremented if seq_nr0 = scanrate
51 uint16_t seq_nr2; //incremeted if seq_nr1 = 255
53 uint8_t seq_nr0; //incremented. 0- scanrate
55 }__attribute__((packed));
57 struct tslib_cy8mrln_palmpre
59 struct tslib_module_info module;
60 uint16_t nulls[H_FIELDS * V_FIELDS];
63 static int scanrate = 60;
64 static int verbose = 0;
65 static int wot_threshold = 22;
66 static int sleepmode = CY8MRLN_ON_STATE;
67 static int wot_scanrate = WOT_SCANRATE_512HZ;
68 static int timestamp_mode = 1;
71 cy8mrln_palmpre_set_scanrate(struct tsdev* dev, int rate)
73 if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_SCANRATE,&rate) < 0)
80 printf("TSLIB: cy8mrln_palmpre: ERROR: could not set scanrate value\n");
85 cy8mrln_palmpre_set_verbose(struct tsdev* dev, int v)
87 if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_VERBOSE_MODE,&v) < 0)
94 printf("TSLIB: cy8mrln_palmpre: ERROR: could not set verbose value\n");
99 cy8mrln_palmpre_set_sleepmode(struct tsdev* dev, int mode)
101 if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_SLEEPMODE,&mode) < 0)
108 printf("TSLIB: cy8mrln_palmpre: ERROR: could not set sleepmode value\n");
113 cy8mrln_palmpre_set_wot_scanrate(struct tsdev* dev, int rate)
115 if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_WOT_SCANRATE,&rate) < 0)
122 printf("TSLIB: cy8mrln_palmpre: ERROR: could not set scanrate value\n");
127 cy8mrln_palmpre_set_wot_threshold(struct tsdev* dev, int v)
131 if(v < WOT_THRESHOLD_MIN || v > WOT_THRESHOLD_MAX)
133 if(ioctl(dev->fd,CY8MRLN_IOCTL_SET_WOT_THRESHOLD,&v) < 0)
140 printf("TSLIB: cy8mrln_palmpre: ERROR: could not set wot treshhold value\n");
145 cy8mrln_palmpre_set_timestamp_mode(struct tsdev* dev, int v)
148 if(dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_TIMESTAMP_MODE,&v) < 0)
154 printf("TSLIB: cy8mrln_palmpre: ERROR: could not set timestamp value\n");
159 parse_scanrate(struct tslib_module_info *info, char *str, void *data)
161 struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
162 unsigned long rate = strtoul(str, NULL, 0);
164 if(rate == ULONG_MAX && errno == ERANGE)
167 return cy8mrln_palmpre_set_scanrate(i->module.dev, scanrate);
171 parse_verbose(struct tslib_module_info *info, char *str, void *data)
173 struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
174 unsigned long v = strtoul(str, NULL, 0);
176 if(v == ULONG_MAX && errno == ERANGE)
179 return cy8mrln_palmpre_set_verbose(i->module.dev, scanrate);
183 parse_wot_scanrate(struct tslib_module_info *info, char *str, void *data)
185 struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
186 unsigned long rate = strtoul(str, NULL, 0);
188 return cy8mrln_palmpre_set_wot_scanrate(i->module.dev, rate);
192 parse_wot_threshold(struct tslib_module_info *info, char *str, void *data)
194 struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
195 unsigned long threshold = strtoul(str, NULL, 0);
197 return cy8mrln_palmpre_set_wot_threshold(i->module.dev, threshold);
201 parse_sleepmode(struct tslib_module_info *info, char *str, void *data)
203 struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
204 unsigned long sleep = strtoul(str, NULL, 0);
206 return cy8mrln_palmpre_set_sleepmode(i->module.dev, sleep);
210 parse_timestamp_mode(struct tslib_module_info *info, char *str, void *data)
212 struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
213 unsigned long sleep = strtoul(str, NULL, 0);
215 return cy8mrln_palmpre_set_sleepmode(i->module.dev, sleep);
218 static const struct tslib_vars raw_vars[] =
220 { "scanrate", NULL, parse_scanrate},
221 { "verbose", NULL, parse_verbose},
222 { "wot_scanrate", NULL, parse_wot_scanrate},
223 { "wot_threshold", NULL, parse_wot_threshold},
224 { "sleepmode", NULL, parse_sleepmode},
225 { "timestamp_mode", NULL, parse_timestamp_mode}
228 #define NR_VARS (sizeof(raw_vars) / sizeof(raw_vars[0]))
231 interpolate(uint16_t field[H_FIELDS * V_FIELDS], int i, struct ts_sample *out) {
232 float f11, f12, f13, f21, f22, f23, f31, f32, f33;
233 int x = SCREEN_WIDTH / H_FIELDS * (H_FIELDS - (i % H_FIELDS));
234 int y = SCREEN_HEIGHT / (V_FIELDS - 1) * (i / H_FIELDS);
235 static int dx = SCREEN_WIDTH / H_FIELDS;
236 static int dy = SCREEN_HEIGHT / V_FIELDS;
238 /* caluculate corrections for top, bottom, left and right fields */
239 f12 = (i < (H_FIELDS + 1)) ? 0.0 : 0.5 * field[i - H_FIELDS] / field[i];
240 f32 = (i > (H_FIELDS * (V_FIELDS - 2)))
241 ? 0.0 : 0.5 * field[i + H_FIELDS] / field[i];
242 f21 = (i % H_FIELDS == (H_FIELDS - 1))
243 ? 0.0 : 0.5 * field[i + 1] / field[i];
244 f23 = (i % H_FIELDS == 0) ? 0.0 : 0.5 * field[i - 1] / field[i];
247 correct values for the edges, shift the mesuarment point by half a
248 field diminsion to the outside
255 } else if (i == (H_FIELDS - 1)) {
260 } else if (i % H_FIELDS == (H_FIELDS - 1)) {
263 } else if (i % H_FIELDS == 0) {
266 } else if (i < H_FIELDS) {
269 } else if (i == (H_FIELDS * (V_FIELDS - 2))) {
274 } else if (i == (H_FIELDS * (V_FIELDS - 1) - 1)) {
279 } else if (i > (H_FIELDS * (V_FIELDS - 2))) {
284 /* caluclate corrections for the corners */
286 f11 = (i % H_FIELDS == (H_FIELDS - 1) || i < (H_FIELDS + 1))
287 ? 0.0 : 0.4 * field[i - H_FIELDS + 1] / field[i];
288 f13 = (i % H_FIELDS == 0 || i < (H_FIELDS + 1))
289 ? 0.0 : 0.4 * field[i - H_FIELDS - 1] / field[i];
290 f31 = (i % H_FIELDS == (H_FIELDS - 1)
291 || i > (H_FIELDS * (V_FIELDS - 1) - 1))
292 ? 0.0 : 0.4 * field[i + H_FIELDS + 1] / field[i];
293 f33 = (i % H_FIELDS == 0 || i > (H_FIELDS * (V_FIELDS - 1) - 1))
294 ? 0.0 : 0.4 * field[i + H_FIELDS - 1] / field[i];
297 out->x = x // + (f13 + f33 - f11 - f31) * dx /* use corners too?*/
299 // + (f21 == 0.0) ? ((f23 * 2 + (dx / 2)) * dx) : (f23 * dx)
300 // - (f23 == 0.0) ? ((f21 * 2 + (dx / 2)) * dx) : (f21 * dx)
302 out->y = y // + (f31 + f33 - f11 - f13) * dy /* use corners too?*/
303 + (f32 - f12) * dy + (dy / 2);
305 out->pressure = field[i];
307 printf("RAW---------------------------> f22: %f (%d) f21: %f (%d), f23: %f (%d), f12: %f (%d), f32: %f (%d), \n",
309 f21, field[i - 1], f23, field[i + 1], f12,
310 field[i - H_FIELDS], f32, field[i + H_FIELDS]);
315 cy8mrln_palmpre_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
317 struct tsdev *ts = info->dev;
318 struct cy8mrln_palmpre_input *cy8mrln_evt;
319 struct tslib_cy8mrln_palmpre *cy8mrln_info;
320 int max_index = 0, max_value = 0, i = 0;
324 cy8mrln_info = container_of(info, struct tslib_cy8mrln_palmpre, module);
326 cy8mrln_evt = alloca(sizeof(*cy8mrln_evt) * nr);
327 ret = read(ts->fd, cy8mrln_evt, sizeof(*cy8mrln_evt) * nr);
331 while(ret >= (int)sizeof(*cy8mrln_evt)) {
332 for (i = 0; i < (H_FIELDS * V_FIELDS); i++) {
333 /* auto calibrate zero values */
334 if (cy8mrln_evt->field[i] > cy8mrln_info->nulls[i])
335 cy8mrln_info->nulls[i] = cy8mrln_evt->field[i];
337 tmp_value = abs(cy8mrln_info->nulls[i] - cy8mrln_evt->field[i]);
339 /* check for the maximum value */
340 if (tmp_value > max_value) {
341 max_value = tmp_value;
345 cy8mrln_evt->field[i] = tmp_value;
347 /* only caluclate events that are not noise */
348 if (max_value > NOISE) {
349 interpolate(cy8mrln_evt->field, max_index, samp);
351 fprintf(stderr,"RAW---------------------------> %d %d %d\n",
352 samp->x, samp->y, samp->pressure);
354 gettimeofday(&samp->tv,NULL);
359 ret -= sizeof(*cy8mrln_evt);
370 cy8mrln_palmpre_fini(struct tslib_module_info *inf)
376 static const struct tslib_ops cy8mrln_palmpre_ops =
378 .read = cy8mrln_palmpre_read,
379 .fini = cy8mrln_palmpre_fini,
382 TSAPI struct tslib_module_info *cy8mrln_palmpre_mod_init(struct tsdev *dev, const char *params)
384 struct tslib_cy8mrln_palmpre *info;
385 struct cy8mrln_palmpre_input input;
387 info = malloc(sizeof(struct tslib_cy8mrln_palmpre));
390 info->module.ops = &cy8mrln_palmpre_ops;
392 cy8mrln_palmpre_set_verbose(dev,verbose);
393 cy8mrln_palmpre_set_scanrate(dev,scanrate);
394 cy8mrln_palmpre_set_timestamp_mode(dev,timestamp_mode);
395 cy8mrln_palmpre_set_sleepmode(dev,sleepmode);
396 cy8mrln_palmpre_set_wot_scanrate(dev,wot_scanrate);
397 cy8mrln_palmpre_set_wot_threshold(dev,wot_threshold);
399 if (tslib_parse_vars(&info->module, raw_vars, NR_VARS, params)) {
404 // FIXME why do we read here one packet from fd?
405 read(dev->fd, &input, sizeof(input));
407 memcpy(info->nulls, input.field, H_FIELDS * V_FIELDS * sizeof(uint16_t));
409 return &(info->module);
411 #ifndef TSLIB_STATIC_CY8MRLN_MODULE
412 TSLIB_MODULE_INIT(cy8mrln_palmpre_mod_init);