summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Arigo <markarigo@gmail.com>2008-12-17 04:38:53 +0000
committerMark Arigo <markarigo@gmail.com>2008-12-17 04:38:53 +0000
commitf2b66918e635dbd4860bf3af4303d2e86d182983 (patch)
tree492794a18c0036b8fca261501a71e8767245e131
parenta742c3cd56d802f72567167e6e5482308744de3e (diff)
downloadrockbox-f2b66918e635dbd4860bf3af4303d2e86d182983.tar.gz
rockbox-f2b66918e635dbd4860bf3af4303d2e86d182983.zip
Move the Synaptics touchpad driver for the m:robe 100 to a common place. It will (soon) be used for the Philips HDD1630.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19465 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/drivers/synaptics-mep.c482
-rw-r--r--firmware/export/synaptics-mep.h27
-rw-r--r--firmware/target/arm/olympus/mrobe-100/button-mr100.c495
4 files changed, 530 insertions, 477 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 5d1dd0d800..441f75d31d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -820,6 +820,9 @@ target/arm/tms320dm320/creative-zvm/usb-creativezvm.c
820 820
821#ifdef MROBE_100 821#ifdef MROBE_100
822#ifndef SIMULATOR 822#ifndef SIMULATOR
823#ifndef BOOTLOADER
824drivers/synaptics-mep.c
825#endif /* BOOTLOADER */
823drivers/sw_i2c.c 826drivers/sw_i2c.c
824target/arm/ata-as-arm.S 827target/arm/ata-as-arm.S
825target/arm/ata-pp5020.c 828target/arm/ata-pp5020.c
diff --git a/firmware/drivers/synaptics-mep.c b/firmware/drivers/synaptics-mep.c
new file mode 100644
index 0000000000..44b186034f
--- /dev/null
+++ b/firmware/drivers/synaptics-mep.c
@@ -0,0 +1,482 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Mark Arigo
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdlib.h>
23#include "config.h"
24#include "cpu.h"
25#include "system.h"
26#include "kernel.h"
27#include "system.h"
28
29#define LOGF_ENABLE
30#include "logf.h"
31
32/* Driver for the Synaptics Touchpad based on the "Synaptics Modular Embedded
33 Protocol: 3-Wire Interface Specification" documentation */
34
35#define ACK (GPIOD_INPUT_VAL & 0x1)
36#define ACK_HI GPIOD_OUTPUT_VAL |= 0x1
37#define ACK_LO GPIOD_OUTPUT_VAL &= ~0x1
38
39#define CLK ((GPIOD_INPUT_VAL & 0x2) >> 1)
40#define CLK_HI GPIOD_OUTPUT_VAL |= 0x2
41#define CLK_LO GPIOD_OUTPUT_VAL &= ~0x2
42
43#define DATA ((GPIOD_INPUT_VAL & 0x4) >> 2)
44#define DATA_HI GPIOD_OUTPUT_EN |= 0x4; GPIOD_OUTPUT_VAL |= 0x4
45#define DATA_LO GPIOD_OUTPUT_EN |= 0x4; GPIOD_OUTPUT_VAL &= ~0x4
46#define DATA_CL GPIOD_OUTPUT_EN &= ~0x4
47
48#define LO 0
49#define HI 1
50
51#define READ_RETRY 8
52#define READ_ERROR -1
53
54#define MEP_HELLO_HEADER 0x19
55#define MEP_HELLO_ID 0x1
56
57#define MEP_READ 0x1
58#define MEP_WRITE 0x3
59
60static int syn_wait_clk_change(unsigned int val)
61{
62 int i;
63
64 for (i = 0; i < 10000; i++)
65 {
66 if (CLK == val)
67 return 1;
68 }
69
70 return 0;
71}
72
73static inline int syn_get_data(void)
74{
75 DATA_CL;
76 return DATA;
77}
78
79static void syn_wait_guest_flush(void)
80{
81 /* Flush receiving (flushee) state:
82 handshake until DATA goes high during P3 stage */
83 if (CLK == LO)
84 {
85 ACK_HI; /* P1 -> P2 */
86 syn_wait_clk_change(HI); /* P2 -> P3 */
87 }
88
89 while (syn_get_data() == LO)
90 {
91 ACK_HI; /* P3 -> P0 */
92 syn_wait_clk_change(LO); /* P0 -> P1 */
93 ACK_LO; /* P1 -> P2 */
94 syn_wait_clk_change(HI); /* P2 -> P3 */
95 }
96
97 /* Continue handshaking until back to P0 */
98 ACK_HI; /* P3 -> P0 */
99}
100
101static void syn_flush(void)
102{
103 int i;
104
105 logf("syn_flush...");
106
107 /* Flusher holds DATA low for at least 36 handshake cycles */
108 DATA_LO;
109
110 for (i = 0; i < 36; i++)
111 {
112 syn_wait_clk_change(LO); /* P0 -> P1 */
113 ACK_LO; /* P1 -> P2 */
114 syn_wait_clk_change(HI); /* P2 -> P3 */
115 ACK_HI; /* P3 -> P0 */
116 }
117
118 /* Raise DATA in P1 stage */
119 syn_wait_clk_change(LO); /* P0 -> P1 */
120 DATA_HI;
121
122 /* After a flush, the flushing device enters a flush-receiving (flushee)
123 state */
124 syn_wait_guest_flush();
125}
126
127static int syn_send_data(int *data, int len)
128{
129 int i, bit;
130 int parity = 0;
131
132 logf("syn_send_data...");
133
134 /* 1. Lower DATA line to issue a request-to-send to guest */
135 DATA_LO;
136
137 /* 2. Wait for guest to lower CLK */
138 syn_wait_clk_change(LO);
139
140 /* 3. Lower ACK (with DATA still low) */
141 ACK_LO;
142
143 /* 4. Wait for guest to raise CLK */
144 syn_wait_clk_change(HI);
145
146 /* 5. Send data */
147 for (i = 0; i < len; i++)
148 {
149 logf(" sending byte: %d", data[i]);
150
151 bit = 0;
152 while (bit < 8)
153 {
154 /* 5a. Drive data low if bit is 0, or high if bit is 1 */
155 if (data[i] & (1 << bit))
156 {
157 DATA_HI;
158 parity++;
159 }
160 else
161 {
162 DATA_LO;
163 }
164 bit++;
165
166 /* 5b. Invert ACK to indicate that the data bit is ready */
167 ACK_HI;
168
169 /* 5c. Wait for guest to invert CLK */
170 syn_wait_clk_change(LO);
171
172 /* Repeat for next bit */
173 if (data[i] & (1 << bit))
174 {
175 DATA_HI;
176 parity++;
177 }
178 else
179 {
180 DATA_LO;
181 }
182 bit++;
183
184 ACK_LO;
185
186 syn_wait_clk_change(HI);
187 }
188 }
189
190 /* 7. Transmission termination sequence: */
191 /* 7a. Host may put parity bit on DATA. Hosts that do not generate
192 parity should set DATA high. Parity is 1 if there's an odd
193 number of '1' bits, or 0 if there's an even number of '1' bits. */
194 parity = parity % 2;
195 if (parity)
196 {
197 DATA_HI;
198 }
199 else
200 {
201 DATA_LO;
202 }
203 logf(" send parity = %d", parity);
204
205 /* 7b. Raise ACK to indicate that the optional parity bit is ready */
206 ACK_HI;
207
208 /* 7c. Guest lowers CLK */
209 syn_wait_clk_change(LO);
210
211 /* 7d. Pull DATA high (if parity bit was 0) */
212 DATA_HI;
213
214 /* 7e. Lower ACK to indicate that the stop bit is ready */
215 ACK_LO;
216
217 /* 7f. Guest raises CLK */
218 syn_wait_clk_change(HI);
219
220 /* 7g. If DATA is low, guest is flushing this transfer. Host should
221 enter the flushee state. */
222 if (syn_get_data() == LO)
223 {
224 logf(" module flushing");
225
226 syn_wait_guest_flush();
227 return -1;
228 }
229
230 /* 7h. Host raises ACK and the link enters the idle state */
231 ACK_HI;
232
233 return len;
234}
235
236static int syn_read_data(int *data, int data_len)
237{
238 int i, len, bit, parity, tmp;
239 int *data_ptr;
240
241 logf("syn_read_data...");
242
243 /* 1. Guest drives CLK low */
244 if (CLK != LO)
245 return 0;
246
247 /* 1a. If the host is willing to receive a packet it lowers ACK */
248 ACK_LO;
249
250 /* 2. Guest may issue a request-to-send by lowering DATA. If the
251 guest decides not to transmit a packet, it may abort the
252 transmission by not lowering DATA. */
253
254 /* 3. The guest raises CLK */
255 syn_wait_clk_change(HI);
256
257 /* 4. If the guest is still driving DATA low, the transfer is commited
258 to occur. Otherwise, the transfer is aborted. In either case,
259 the host raises ACK. */
260 if (syn_get_data() == HI)
261 {
262 logf(" read abort");
263
264 ACK_HI;
265 return READ_ERROR;
266 }
267 else
268 {
269 ACK_HI;
270 }
271
272 /* 5. Read the incoming data packet */
273 i = 0;
274 len = 0;
275 parity = 0;
276 while (i <= len)
277 {
278 bit = 0;
279
280 if (i < data_len)
281 data_ptr = &data[i];
282 else
283 data_ptr = &tmp;
284
285 *data_ptr = 0;
286 while (bit < 8)
287 {
288 /* 5b. Guset inverts CLK to indicate that data is ready */
289 syn_wait_clk_change(LO);
290
291 /* 5d. Read the data bit from DATA */
292 if (syn_get_data() == HI)
293 {
294 *data_ptr |= (1 << bit);
295 parity++;
296 }
297 bit++;
298
299 /* 5e. Invert ACK to indicate that data has been read */
300 ACK_LO;
301
302 /* Repeat for next bit */
303 syn_wait_clk_change(HI);
304
305 if (syn_get_data() == HI)
306 {
307 *data_ptr |= (1 << bit);
308 parity++;
309 }
310 bit++;
311
312 ACK_HI;
313 }
314
315 /* First byte is the packet header */
316 if (i == 0)
317 {
318 /* Format control (bit 3) should be 1 */
319 if (*data_ptr & 0x8)
320 {
321 /* Packet length is bits 0:2 */
322 len = *data_ptr & 0x7;
323 logf(" packet length = %d", len);
324 }
325 else
326 {
327 logf(" invalid format ctrl bit");
328 return READ_ERROR;
329 }
330 }
331
332 i++;
333 }
334
335 /* 7. Transmission termination cycle */
336 /* 7a. The guest generates a parity bit on DATA */
337 /* 7b. The host waits for guest to lower CLK */
338 syn_wait_clk_change(LO);
339
340 /* 7c. The host verifies the parity bit is correct */
341 parity = parity % 2;
342 logf(" parity check: %d / %d", syn_get_data(), parity);
343
344 /* TODO: parity error handling */
345
346 /* 7d. The host lowers ACK */
347 ACK_LO;
348
349 /* 7e. The host waits for the guest to raise CLK indicating
350 that the stop bit is ready */
351 syn_wait_clk_change(HI);
352
353 /* 7f. The host reads DATA and verifies that it is 1 */
354 if (syn_get_data() == LO)
355 {
356 logf(" framing error");
357
358 ACK_HI;
359 return READ_ERROR;
360 }
361
362 ACK_HI;
363
364 return len;
365}
366
367int syn_read_device(int *data, int len)
368{
369 int i;
370 int ret = READ_ERROR;
371
372 for (i = 0; i < READ_RETRY; i++)
373 {
374 if (syn_wait_clk_change(LO))
375 {
376 /* module is sending data */
377 ret = syn_read_data(data, len);
378 if (ret != READ_ERROR)
379 return ret;
380
381 syn_flush();
382 }
383 else
384 {
385 /* module is idle */
386 return 0;
387 }
388 }
389
390 return ret;
391}
392
393static int syn_reset(void)
394{
395 int val, id;
396 int data[2];
397
398 logf("syn_reset...");
399
400 /* reset module 0 */
401 val = (0 << 4) | (1 << 3) | 0;
402 syn_send_data(&val, 1);
403
404 val = syn_read_device(data, 2);
405 if (val == 1)
406 {
407 val = data[0] & 0xff; /* packet header */
408 id = (data[1] >> 4) & 0xf; /* packet id */
409 if ((val == MEP_HELLO_HEADER) && (id == MEP_HELLO_ID))
410 {
411 logf(" module 0 reset");
412 return 1;
413 }
414 }
415
416 logf(" reset failed");
417 return 0;
418}
419
420int syn_init(void)
421{
422 syn_flush();
423 return syn_reset();
424}
425
426#ifdef ROCKBOX_HAS_LOGF
427void syn_info(void)
428{
429 int i, val;
430 int data[8];
431
432 logf("syn_info...");
433
434 /* module base info */
435 logf("module base info:");
436 data[0] = MEP_READ;
437 data[1] = 0x80;
438 syn_send_data(data, 2);
439 val = syn_read_device(data, 8);
440 if (val > 0)
441 {
442 for (i = 0; i < 8; i++)
443 logf(" data[%d] = 0x%02x", i, data[i]);
444 }
445
446 /* module product info */
447 logf("module product info:");
448 data[0] = MEP_READ;
449 data[1] = 0x81;
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 serialization */
459 logf("module serialization:");
460 data[0] = MEP_READ;
461 data[1] = 0x82;
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 /* 1-D sensor info */
471 logf("1-d sensor info:");
472 data[0] = MEP_READ;
473 data[1] = 0x80 + 0x20;
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#endif
diff --git a/firmware/export/synaptics-mep.h b/firmware/export/synaptics-mep.h
new file mode 100644
index 0000000000..8f717da884
--- /dev/null
+++ b/firmware/export/synaptics-mep.h
@@ -0,0 +1,27 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Mark Arigo
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22int syn_init(void);
23int syn_read_device(int *data, int len);
24
25#ifdef ROCKBOX_HAS_LOGF
26void syn_info(void);
27#endif
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}