summaryrefslogtreecommitdiff
path: root/firmware/target/arm/olympus/mrobe-100/button-mr100.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/olympus/mrobe-100/button-mr100.c')
-rw-r--r--firmware/target/arm/olympus/mrobe-100/button-mr100.c495
1 files changed, 18 insertions, 477 deletions
diff --git a/firmware/target/arm/olympus/mrobe-100/button-mr100.c b/firmware/target/arm/olympus/mrobe-100/button-mr100.c
index e8fc8b97ea..9cfd8affa9 100644
--- a/firmware/target/arm/olympus/mrobe-100/button-mr100.c
+++ b/firmware/target/arm/olympus/mrobe-100/button-mr100.c
@@ -19,480 +19,24 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include <stdlib.h>
23#include "config.h"
24#include "cpu.h"
25#include "system.h" 22#include "system.h"
26#include "button.h" 23#include "button.h"
27#include "kernel.h"
28#include "backlight.h" 24#include "backlight.h"
29#include "backlight-target.h" 25#include "backlight-target.h"
30#include "system.h" 26#include "synaptics-mep.h"
31 27
32#define LOGF_ENABLE 28#define LOGF_ENABLE
33#include "logf.h" 29#include "logf.h"
34 30
31#define MEP_BUTTON_HEADER 0x1a
32#define MEP_BUTTON_ID 0x9
33#define MEP_ABSOLUTE_HEADER 0x0b
34
35static int int_btn = BUTTON_NONE; 35static int int_btn = BUTTON_NONE;
36 36
37#ifndef BOOTLOADER 37#ifndef BOOTLOADER
38/* Driver for the Synaptics Touchpad based on the "Synaptics Modular Embedded
39 Protocol: 3-Wire Interface Specification" documentation */
40
41#define ACK (GPIOD_INPUT_VAL & 0x1)
42#define ACK_HI GPIOD_OUTPUT_VAL |= 0x1
43#define ACK_LO GPIOD_OUTPUT_VAL &= ~0x1
44
45#define CLK ((GPIOD_INPUT_VAL & 0x2) >> 1)
46#define CLK_HI GPIOD_OUTPUT_VAL |= 0x2
47#define CLK_LO GPIOD_OUTPUT_VAL &= ~0x2
48
49#define DATA ((GPIOD_INPUT_VAL & 0x4) >> 2)
50#define DATA_HI GPIOD_OUTPUT_EN |= 0x4; GPIOD_OUTPUT_VAL |= 0x4
51#define DATA_LO GPIOD_OUTPUT_EN |= 0x4; GPIOD_OUTPUT_VAL &= ~0x4
52
53#define LO 0
54#define HI 1
55
56#define STATUS_READY 1
57#define READ_RETRY 8
58#define READ_ERROR -1
59
60#define HELLO_HEADER 0x19
61#define HELLO_ID 0x1
62#define BUTTONS_HEADER 0x1a
63#define BUTTONS_ID 0x9
64#define ABSOLUTE_HEADER 0x0b
65
66#define MEP_READ 0x1
67#define MEP_WRITE 0x3
68
69static int syn_status = 0; 38static int syn_status = 0;
70 39
71static int syn_wait_clk_change(unsigned int val)
72{
73 int i;
74
75 for (i = 0; i < 10000; i++)
76 {
77 if (CLK == val)
78 return 1;
79 }
80
81 return 0;
82}
83
84static inline int syn_get_data(void)
85{
86 GPIOD_OUTPUT_EN &= ~0x4;
87 return DATA;
88}
89
90static void syn_wait_guest_flush(void)
91{
92 /* Flush receiving (flushee) state:
93 handshake until DATA goes high during P3 stage */
94 if (CLK == LO)
95 {
96 ACK_HI; /* P1 -> P2 */
97 syn_wait_clk_change(HI); /* P2 -> P3 */
98 }
99
100 while (syn_get_data() == LO)
101 {
102 ACK_HI; /* P3 -> P0 */
103 syn_wait_clk_change(LO); /* P0 -> P1 */
104 ACK_LO; /* P1 -> P2 */
105 syn_wait_clk_change(HI); /* P2 -> P3 */
106 }
107
108 /* Continue handshaking until back to P0 */
109 ACK_HI; /* P3 -> P0 */
110}
111
112static void syn_flush(void)
113{
114 int i;
115#if defined(LOGF_ENABLE)
116 logf("syn_flush...");
117#endif
118 /* Flusher holds DATA low for at least 36 handshake cycles */
119 DATA_LO;
120
121 for (i = 0; i < 36; i++)
122 {
123 syn_wait_clk_change(LO); /* P0 -> P1 */
124 ACK_LO; /* P1 -> P2 */
125 syn_wait_clk_change(HI); /* P2 -> P3 */
126 ACK_HI; /* P3 -> P0 */
127 }
128
129 /* Raise DATA in P1 stage */
130 syn_wait_clk_change(LO); /* P0 -> P1 */
131 DATA_HI;
132
133 /* After a flush, the flushing device enters a flush-receiving (flushee)
134 state */
135 syn_wait_guest_flush();
136}
137
138static int syn_send_data(int *data, int len)
139{
140 int i, bit;
141 int parity = 0;
142#if defined(LOGF_ENABLE)
143 logf("syn_send_data...");
144#endif
145 /* 1. Lower DATA line to issue a request-to-send to guest */
146 DATA_LO;
147
148 /* 2. Wait for guest to lower CLK */
149 syn_wait_clk_change(LO);
150
151 /* 3. Lower ACK (with DATA still low) */
152 ACK_LO;
153
154 /* 4. Wait for guest to raise CLK */
155 syn_wait_clk_change(HI);
156
157 /* 5. Send data */
158 for (i = 0; i < len; i++)
159 {
160#if defined(LOGF_ENABLE)
161 logf(" sending byte: %d", data[i]);
162#endif
163 bit = 0;
164 while (bit < 8)
165 {
166 /* 5a. Drive data low if bit is 0, or high if bit is 1 */
167 if (data[i] & (1 << bit))
168 {
169 DATA_HI;
170 parity++;
171 }
172 else
173 {
174 DATA_LO;
175 }
176 bit++;
177
178 /* 5b. Invert ACK to indicate that the data bit is ready */
179 ACK_HI;
180
181 /* 5c. Wait for guest to invert CLK */
182 syn_wait_clk_change(LO);
183
184 /* Repeat for next bit */
185 if (data[i] & (1 << bit))
186 {
187 DATA_HI;
188 parity++;
189 }
190 else
191 {
192 DATA_LO;
193 }
194 bit++;
195
196 ACK_LO;
197
198 syn_wait_clk_change(HI);
199 }
200 }
201
202 /* 7. Transmission termination sequence: */
203 /* 7a. Host may put parity bit on DATA. Hosts that do not generate
204 parity should set DATA high. Parity is 1 if there's an odd
205 number of '1' bits, or 0 if there's an even number of '1' bits. */
206 parity = parity % 2;
207#if defined(LOGF_ENABLE)
208 logf(" send parity = %d", parity);
209#endif
210 if (parity)
211 {
212 DATA_HI;
213 }
214 else
215 {
216 DATA_LO;
217 }
218
219 /* 7b. Raise ACK to indicate that the optional parity bit is ready */
220 ACK_HI;
221
222 /* 7c. Guest lowers CLK */
223 syn_wait_clk_change(LO);
224
225 /* 7d. Pull DATA high (if parity bit was 0) */
226 DATA_HI;
227
228 /* 7e. Lower ACK to indicate that the stop bit is ready */
229 ACK_LO;
230
231 /* 7f. Guest raises CLK */
232 syn_wait_clk_change(HI);
233
234 /* 7g. If DATA is low, guest is flushing this transfer. Host should
235 enter the flushee state. */
236 if (syn_get_data() == LO)
237 {
238#if defined(LOGF_ENABLE)
239 logf(" module flushing");
240#endif
241 syn_wait_guest_flush();
242 return -1;
243 }
244
245 /* 7h. Host raises ACK and the link enters the idle state */
246 ACK_HI;
247
248 return len;
249}
250
251static int syn_read_data(int *data, int data_len)
252{
253 int i, len, bit, parity, tmp;
254 int *data_ptr;
255#if defined(LOGF_ENABLE)
256 logf("syn_read_data...");
257#endif
258 /* 1. Guest drives CLK low */
259 if (CLK != LO)
260 return 0;
261
262 /* 1a. If the host is willing to receive a packet it lowers ACK */
263 ACK_LO;
264
265 /* 2. Guest may issue a request-to-send by lowering DATA. If the
266 guest decides not to transmit a packet, it may abort the
267 transmission by not lowering DATA. */
268
269 /* 3. The guest raises CLK */
270 syn_wait_clk_change(HI);
271
272 /* 4. If the guest is still driving DATA low, the transfer is commited
273 to occur. Otherwise, the transfer is aborted. In either case,
274 the host raises ACK. */
275 if (syn_get_data() == HI)
276 {
277 logf(" read abort");
278
279 ACK_HI;
280 return READ_ERROR;
281 }
282 else
283 {
284 ACK_HI;
285 }
286
287 /* 5. Read the incoming data packet */
288 i = 0;
289 len = 0;
290 parity = 0;
291 while (i <= len)
292 {
293 bit = 0;
294
295 if (i < data_len)
296 data_ptr = &data[i];
297 else
298 data_ptr = &tmp;
299
300 *data_ptr = 0;
301 while (bit < 8)
302 {
303 /* 5b. Guset inverts CLK to indicate that data is ready */
304 syn_wait_clk_change(LO);
305
306 /* 5d. Read the data bit from DATA */
307 if (syn_get_data() == HI)
308 {
309 *data_ptr |= (1 << bit);
310 parity++;
311 }
312 bit++;
313
314 /* 5e. Invert ACK to indicate that data has been read */
315 ACK_LO;
316
317 /* Repeat for next bit */
318 syn_wait_clk_change(HI);
319
320 if (syn_get_data() == HI)
321 {
322 *data_ptr |= (1 << bit);
323 parity++;
324 }
325 bit++;
326
327 ACK_HI;
328 }
329
330 /* First byte is the packet header */
331 if (i == 0)
332 {
333 /* Format control (bit 3) should be 1 */
334 if (*data_ptr & 0x8)
335 {
336 /* Packet length is bits 0:2 */
337 len = *data_ptr & 0x7;
338#if defined(LOGF_ENABLE)
339 logf(" packet length = %d", len);
340#endif
341 }
342 else
343 {
344 logf(" invalid format ctrl bit");
345 return READ_ERROR;
346 }
347 }
348
349 i++;
350 }
351
352 /* 7. Transmission termination cycle */
353 /* 7a. The guest generates a parity bit on DATA */
354 /* 7b. The host waits for guest to lower CLK */
355 syn_wait_clk_change(LO);
356
357 /* 7c. The host verifies the parity bit is correct */
358 parity = parity % 2;
359#if defined(LOGF_ENABLE)
360 logf(" parity check: %d / %d", syn_get_data(), parity);
361#endif
362 /* TODO: parity error handling */
363
364 /* 7d. The host lowers ACK */
365 ACK_LO;
366
367 /* 7e. The host waits for the guest to raise CLK indicating
368 that the stop bit is ready */
369 syn_wait_clk_change(HI);
370
371 /* 7f. The host reads DATA and verifies that it is 1 */
372 if (syn_get_data() == LO)
373 {
374 logf(" framing error");
375
376 ACK_HI;
377 return READ_ERROR;
378 }
379
380 ACK_HI;
381
382 return len;
383}
384
385static int syn_read_device(int *data, int len)
386{
387 int i;
388 int ret = READ_ERROR;
389
390 for (i = 0; i < READ_RETRY; i++)
391 {
392 if (syn_wait_clk_change(LO))
393 {
394 /* module is sending data */
395 ret = syn_read_data(data, len);
396 if (ret != READ_ERROR)
397 return ret;
398
399 syn_flush();
400 }
401 else
402 {
403 /* module is idle */
404 return 0;
405 }
406 }
407
408 return ret;
409}
410
411static int syn_reset(void)
412{
413 int val, id;
414 int data[2];
415#if defined(LOGF_ENABLE)
416 logf("syn_reset...");
417#endif
418 /* reset module 0 */
419 val = (0 << 4) | (1 << 3) | 0;
420 syn_send_data(&val, 1);
421
422 val = syn_read_device(data, 2);
423 if (val == 1)
424 {
425 val = data[0] & 0xff; /* packet header */
426 id = (data[1] >> 4) & 0xf; /* packet id */
427 if ((val == HELLO_HEADER) && (id == HELLO_ID))
428 {
429 logf(" module 0 reset");
430 return 1;
431 }
432 }
433
434 logf(" reset failed");
435 return 0;
436}
437
438#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
439static void syn_info(void)
440{
441 int i, val;
442 int data[8];
443
444 logf("syn_info...");
445
446 /* module base info */
447 logf("module base info:");
448 data[0] = MEP_READ;
449 data[1] = 0x80;
450 syn_send_data(data, 2);
451 val = syn_read_device(data, 8);
452 if (val > 0)
453 {
454 for (i = 0; i < 8; i++)
455 logf(" data[%d] = 0x%02x", i, data[i]);
456 }
457
458 /* module product info */
459 logf("module product info:");
460 data[0] = MEP_READ;
461 data[1] = 0x81;
462 syn_send_data(data, 2);
463 val = syn_read_device(data, 8);
464 if (val > 0)
465 {
466 for (i = 0; i < 8; i++)
467 logf(" data[%d] = 0x%02x", i, data[i]);
468 }
469
470 /* module serialization */
471 logf("module serialization:");
472 data[0] = MEP_READ;
473 data[1] = 0x82;
474 syn_send_data(data, 2);
475 val = syn_read_device(data, 8);
476 if (val > 0)
477 {
478 for (i = 0; i < 8; i++)
479 logf(" data[%d] = 0x%02x", i, data[i]);
480 }
481
482 /* 1-D sensor info */
483 logf("1-d sensor info:");
484 data[0] = MEP_READ;
485 data[1] = 0x80 + 0x20;
486 syn_send_data(data, 2);
487 val = syn_read_device(data, 8);
488 if (val > 0)
489 {
490 for (i = 0; i < 8; i++)
491 logf(" data[%d] = 0x%02x", i, data[i]);
492 }
493}
494#endif
495
496void button_init_device(void) 40void button_init_device(void)
497{ 41{
498 /* enable touchpad leds */ 42 /* enable touchpad leds */
@@ -514,15 +58,13 @@ void button_init_device(void)
514 GPIOD_OUTPUT_EN |= 0x4; /* DATA */ 58 GPIOD_OUTPUT_EN |= 0x4; /* DATA */
515 GPIOD_OUTPUT_VAL |= 0x4; /* high */ 59 GPIOD_OUTPUT_VAL |= 0x4; /* high */
516 60
517 syn_flush(); 61 if (syn_init())
518
519 if (syn_reset())
520 { 62 {
521#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE) 63#ifdef ROCKBOX_HAS_LOGF
522 syn_info(); 64 syn_info();
523#endif 65#endif
524 66
525 syn_status = STATUS_READY; 67 syn_status = 1;
526 68
527 /* enable interrupts */ 69 /* enable interrupts */
528 GPIOD_INT_LEV &= ~0x2; 70 GPIOD_INT_LEV &= ~0x2;
@@ -544,24 +86,25 @@ void button_int(void)
544 86
545 int_btn = BUTTON_NONE; 87 int_btn = BUTTON_NONE;
546 88
547 if (syn_status == STATUS_READY) 89 if (syn_status)
548 { 90 {
549 /* disable interrupt while we read the touchpad */ 91 /* disable interrupt while we read the touchpad */
550 GPIOD_INT_EN &= ~0x2; 92 GPIOD_INT_EN &= ~0x2;
93 GPIOD_INT_CLR |= 0x2;
551 94
552 val = syn_read_device(data, 4); 95 val = syn_read_device(data, 4);
553 if (val > 0) 96 if (val > 0)
554 { 97 {
555 val = data[0] & 0xff; /* packet header */ 98 val = data[0] & 0xff; /* packet header */
556 id = (data[1] >> 4) & 0xf; /* packet id */ 99 id = (data[1] >> 4) & 0xf; /* packet id */
557#if defined(LOGF_ENABLE) 100
558 logf("button_read_device..."); 101 logf("button_read_device...");
559 logf(" data[0] = 0x%08x", data[0]); 102 logf(" data[0] = 0x%08x", data[0]);
560 logf(" data[1] = 0x%08x", data[1]); 103 logf(" data[1] = 0x%08x", data[1]);
561 logf(" data[2] = 0x%08x", data[2]); 104 logf(" data[2] = 0x%08x", data[2]);
562 logf(" data[3] = 0x%08x", data[3]); 105 logf(" data[3] = 0x%08x", data[3]);
563#endif 106
564 if ((val == BUTTONS_HEADER) && (id == BUTTONS_ID)) 107 if ((val == MEP_BUTTON_HEADER) && (id == MEP_BUTTON_ID))
565 { 108 {
566 /* Buttons packet - touched one of the 5 "buttons" */ 109 /* Buttons packet - touched one of the 5 "buttons" */
567 if (data[1] & 0x1) 110 if (data[1] & 0x1)
@@ -577,22 +120,21 @@ void button_int(void)
577 120
578 /* An Absolute packet should follow which we ignore */ 121 /* An Absolute packet should follow which we ignore */
579 val = syn_read_device(data, 4); 122 val = syn_read_device(data, 4);
580#if defined(LOGF_ENABLE) 123
581 logf(" int_btn = 0x%04x", int_btn); 124 logf(" int_btn = 0x%04x", int_btn);
582#endif
583 } 125 }
584 else if (val == ABSOLUTE_HEADER) 126 else if (val == MEP_ABSOLUTE_HEADER)
585 { 127 {
586 /* Absolute packet - the finger is on the vertical strip. 128 /* Absolute packet - the finger is on the vertical strip.
587 Position ranges from 1-4095, with 1 at the bottom. */ 129 Position ranges from 1-4095, with 1 at the bottom. */
588 val = ((data[1] >> 4) << 8) | data[2]; /* position */ 130 val = ((data[1] >> 4) << 8) | data[2]; /* position */
589#if defined(LOGF_ENABLE) 131
590 logf(" pos %d", val); 132 logf(" pos %d", val);
591 logf(" z %d", data[3]); 133 logf(" z %d", data[3]);
592 logf(" finger %d", data[1] & 0x1); 134 logf(" finger %d", data[1] & 0x1);
593 logf(" gesture %d", data[1] & 0x2); 135 logf(" gesture %d", data[1] & 0x2);
594 logf(" RelPosVld %d", data[1] & 0x4); 136 logf(" RelPosVld %d", data[1] & 0x4);
595#endif 137
596 if(data[1] & 0x1) /* if finger on touch strip */ 138 if(data[1] & 0x1) /* if finger on touch strip */
597 { 139 {
598 if ((val > 0) && (val <= 1365)) 140 if ((val > 0) && (val <= 1365))
@@ -607,7 +149,6 @@ void button_int(void)
607 149
608 /* re-enable interrupts */ 150 /* re-enable interrupts */
609 GPIOD_INT_LEV &= ~0x2; 151 GPIOD_INT_LEV &= ~0x2;
610 GPIOD_INT_CLR |= 0x2;
611 GPIOD_INT_EN |= 0x2; 152 GPIOD_INT_EN |= 0x2;
612 } 153 }
613} 154}