summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/olympus/mrobe-100/button-mr100.c
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 /firmware/target/arm/olympus/mrobe-100/button-mr100.c
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
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 @@
*
****************************************************************************/
-#include <stdlib.h>
-#include "config.h"
-#include "cpu.h"
#include "system.h"
#include "button.h"
-#include "kernel.h"
#include "backlight.h"
#include "backlight-target.h"
-#include "system.h"
+#include "synaptics-mep.h"
#define LOGF_ENABLE
#include "logf.h"
+#define MEP_BUTTON_HEADER 0x1a
+#define MEP_BUTTON_ID 0x9
+#define MEP_ABSOLUTE_HEADER 0x0b
+
static int int_btn = BUTTON_NONE;
#ifndef BOOTLOADER
-/* Driver for the Synaptics Touchpad based on the "Synaptics Modular Embedded
- Protocol: 3-Wire Interface Specification" documentation */
-
-#define ACK (GPIOD_INPUT_VAL & 0x1)
-#define ACK_HI GPIOD_OUTPUT_VAL |= 0x1
-#define ACK_LO GPIOD_OUTPUT_VAL &= ~0x1
-
-#define CLK ((GPIOD_INPUT_VAL & 0x2) >> 1)
-#define CLK_HI GPIOD_OUTPUT_VAL |= 0x2
-#define CLK_LO GPIOD_OUTPUT_VAL &= ~0x2
-
-#define DATA ((GPIOD_INPUT_VAL & 0x4) >> 2)
-#define DATA_HI GPIOD_OUTPUT_EN |= 0x4; GPIOD_OUTPUT_VAL |= 0x4
-#define DATA_LO GPIOD_OUTPUT_EN |= 0x4; GPIOD_OUTPUT_VAL &= ~0x4
-
-#define LO 0
-#define HI 1
-
-#define STATUS_READY 1
-#define READ_RETRY 8
-#define READ_ERROR -1
-
-#define HELLO_HEADER 0x19
-#define HELLO_ID 0x1
-#define BUTTONS_HEADER 0x1a
-#define BUTTONS_ID 0x9
-#define ABSOLUTE_HEADER 0x0b
-
-#define MEP_READ 0x1
-#define MEP_WRITE 0x3
-
static int syn_status = 0;
-static int syn_wait_clk_change(unsigned int val)
-{
- int i;
-
- for (i = 0; i < 10000; i++)
- {
- if (CLK == val)
- return 1;
- }
-
- return 0;
-}
-
-static inline int syn_get_data(void)
-{
- GPIOD_OUTPUT_EN &= ~0x4;
- return DATA;
-}
-
-static void syn_wait_guest_flush(void)
-{
- /* Flush receiving (flushee) state:
- handshake until DATA goes high during P3 stage */
- if (CLK == LO)
- {
- ACK_HI; /* P1 -> P2 */
- syn_wait_clk_change(HI); /* P2 -> P3 */
- }
-
- while (syn_get_data() == LO)
- {
- ACK_HI; /* P3 -> P0 */
- syn_wait_clk_change(LO); /* P0 -> P1 */
- ACK_LO; /* P1 -> P2 */
- syn_wait_clk_change(HI); /* P2 -> P3 */
- }
-
- /* Continue handshaking until back to P0 */
- ACK_HI; /* P3 -> P0 */
-}
-
-static void syn_flush(void)
-{
- int i;
-#if defined(LOGF_ENABLE)
- logf("syn_flush...");
-#endif
- /* Flusher holds DATA low for at least 36 handshake cycles */
- DATA_LO;
-
- for (i = 0; i < 36; i++)
- {
- syn_wait_clk_change(LO); /* P0 -> P1 */
- ACK_LO; /* P1 -> P2 */
- syn_wait_clk_change(HI); /* P2 -> P3 */
- ACK_HI; /* P3 -> P0 */
- }
-
- /* Raise DATA in P1 stage */
- syn_wait_clk_change(LO); /* P0 -> P1 */
- DATA_HI;
-
- /* After a flush, the flushing device enters a flush-receiving (flushee)
- state */
- syn_wait_guest_flush();
-}
-
-static int syn_send_data(int *data, int len)
-{
- int i, bit;
- int parity = 0;
-#if defined(LOGF_ENABLE)
- logf("syn_send_data...");
-#endif
- /* 1. Lower DATA line to issue a request-to-send to guest */
- DATA_LO;
-
- /* 2. Wait for guest to lower CLK */
- syn_wait_clk_change(LO);
-
- /* 3. Lower ACK (with DATA still low) */
- ACK_LO;
-
- /* 4. Wait for guest to raise CLK */
- syn_wait_clk_change(HI);
-
- /* 5. Send data */
- for (i = 0; i < len; i++)
- {
-#if defined(LOGF_ENABLE)
- logf(" sending byte: %d", data[i]);
-#endif
- bit = 0;
- while (bit < 8)
- {
- /* 5a. Drive data low if bit is 0, or high if bit is 1 */
- if (data[i] & (1 << bit))
- {
- DATA_HI;
- parity++;
- }
- else
- {
- DATA_LO;
- }
- bit++;
-
- /* 5b. Invert ACK to indicate that the data bit is ready */
- ACK_HI;
-
- /* 5c. Wait for guest to invert CLK */
- syn_wait_clk_change(LO);
-
- /* Repeat for next bit */
- if (data[i] & (1 << bit))
- {
- DATA_HI;
- parity++;
- }
- else
- {
- DATA_LO;
- }
- bit++;
-
- ACK_LO;
-
- syn_wait_clk_change(HI);
- }
- }
-
- /* 7. Transmission termination sequence: */
- /* 7a. Host may put parity bit on DATA. Hosts that do not generate
- parity should set DATA high. Parity is 1 if there's an odd
- number of '1' bits, or 0 if there's an even number of '1' bits. */
- parity = parity % 2;
-#if defined(LOGF_ENABLE)
- logf(" send parity = %d", parity);
-#endif
- if (parity)
- {
- DATA_HI;
- }
- else
- {
- DATA_LO;
- }
-
- /* 7b. Raise ACK to indicate that the optional parity bit is ready */
- ACK_HI;
-
- /* 7c. Guest lowers CLK */
- syn_wait_clk_change(LO);
-
- /* 7d. Pull DATA high (if parity bit was 0) */
- DATA_HI;
-
- /* 7e. Lower ACK to indicate that the stop bit is ready */
- ACK_LO;
-
- /* 7f. Guest raises CLK */
- syn_wait_clk_change(HI);
-
- /* 7g. If DATA is low, guest is flushing this transfer. Host should
- enter the flushee state. */
- if (syn_get_data() == LO)
- {
-#if defined(LOGF_ENABLE)
- logf(" module flushing");
-#endif
- syn_wait_guest_flush();
- return -1;
- }
-
- /* 7h. Host raises ACK and the link enters the idle state */
- ACK_HI;
-
- return len;
-}
-
-static int syn_read_data(int *data, int data_len)
-{
- int i, len, bit, parity, tmp;
- int *data_ptr;
-#if defined(LOGF_ENABLE)
- logf("syn_read_data...");
-#endif
- /* 1. Guest drives CLK low */
- if (CLK != LO)
- return 0;
-
- /* 1a. If the host is willing to receive a packet it lowers ACK */
- ACK_LO;
-
- /* 2. Guest may issue a request-to-send by lowering DATA. If the
- guest decides not to transmit a packet, it may abort the
- transmission by not lowering DATA. */
-
- /* 3. The guest raises CLK */
- syn_wait_clk_change(HI);
-
- /* 4. If the guest is still driving DATA low, the transfer is commited
- to occur. Otherwise, the transfer is aborted. In either case,
- the host raises ACK. */
- if (syn_get_data() == HI)
- {
- logf(" read abort");
-
- ACK_HI;
- return READ_ERROR;
- }
- else
- {
- ACK_HI;
- }
-
- /* 5. Read the incoming data packet */
- i = 0;
- len = 0;
- parity = 0;
- while (i <= len)
- {
- bit = 0;
-
- if (i < data_len)
- data_ptr = &data[i];
- else
- data_ptr = &tmp;
-
- *data_ptr = 0;
- while (bit < 8)
- {
- /* 5b. Guset inverts CLK to indicate that data is ready */
- syn_wait_clk_change(LO);
-
- /* 5d. Read the data bit from DATA */
- if (syn_get_data() == HI)
- {
- *data_ptr |= (1 << bit);
- parity++;
- }
- bit++;
-
- /* 5e. Invert ACK to indicate that data has been read */
- ACK_LO;
-
- /* Repeat for next bit */
- syn_wait_clk_change(HI);
-
- if (syn_get_data() == HI)
- {
- *data_ptr |= (1 << bit);
- parity++;
- }
- bit++;
-
- ACK_HI;
- }
-
- /* First byte is the packet header */
- if (i == 0)
- {
- /* Format control (bit 3) should be 1 */
- if (*data_ptr & 0x8)
- {
- /* Packet length is bits 0:2 */
- len = *data_ptr & 0x7;
-#if defined(LOGF_ENABLE)
- logf(" packet length = %d", len);
-#endif
- }
- else
- {
- logf(" invalid format ctrl bit");
- return READ_ERROR;
- }
- }
-
- i++;
- }
-
- /* 7. Transmission termination cycle */
- /* 7a. The guest generates a parity bit on DATA */
- /* 7b. The host waits for guest to lower CLK */
- syn_wait_clk_change(LO);
-
- /* 7c. The host verifies the parity bit is correct */
- parity = parity % 2;
-#if defined(LOGF_ENABLE)
- logf(" parity check: %d / %d", syn_get_data(), parity);
-#endif
- /* TODO: parity error handling */
-
- /* 7d. The host lowers ACK */
- ACK_LO;
-
- /* 7e. The host waits for the guest to raise CLK indicating
- that the stop bit is ready */
- syn_wait_clk_change(HI);
-
- /* 7f. The host reads DATA and verifies that it is 1 */
- if (syn_get_data() == LO)
- {
- logf(" framing error");
-
- ACK_HI;
- return READ_ERROR;
- }
-
- ACK_HI;
-
- return len;
-}
-
-static int syn_read_device(int *data, int len)
-{
- int i;
- int ret = READ_ERROR;
-
- for (i = 0; i < READ_RETRY; i++)
- {
- if (syn_wait_clk_change(LO))
- {
- /* module is sending data */
- ret = syn_read_data(data, len);
- if (ret != READ_ERROR)
- return ret;
-
- syn_flush();
- }
- else
- {
- /* module is idle */
- return 0;
- }
- }
-
- return ret;
-}
-
-static int syn_reset(void)
-{
- int val, id;
- int data[2];
-#if defined(LOGF_ENABLE)
- logf("syn_reset...");
-#endif
- /* reset module 0 */
- val = (0 << 4) | (1 << 3) | 0;
- syn_send_data(&val, 1);
-
- val = syn_read_device(data, 2);
- if (val == 1)
- {
- val = data[0] & 0xff; /* packet header */
- id = (data[1] >> 4) & 0xf; /* packet id */
- if ((val == HELLO_HEADER) && (id == HELLO_ID))
- {
- logf(" module 0 reset");
- return 1;
- }
- }
-
- logf(" reset failed");
- return 0;
-}
-
-#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
-static void syn_info(void)
-{
- int i, val;
- int data[8];
-
- logf("syn_info...");
-
- /* module base info */
- logf("module base info:");
- data[0] = MEP_READ;
- data[1] = 0x80;
- syn_send_data(data, 2);
- val = syn_read_device(data, 8);
- if (val > 0)
- {
- for (i = 0; i < 8; i++)
- logf(" data[%d] = 0x%02x", i, data[i]);
- }
-
- /* module product info */
- logf("module product info:");
- data[0] = MEP_READ;
- data[1] = 0x81;
- syn_send_data(data, 2);
- val = syn_read_device(data, 8);
- if (val > 0)
- {
- for (i = 0; i < 8; i++)
- logf(" data[%d] = 0x%02x", i, data[i]);
- }
-
- /* module serialization */
- logf("module serialization:");
- data[0] = MEP_READ;
- data[1] = 0x82;
- syn_send_data(data, 2);
- val = syn_read_device(data, 8);
- if (val > 0)
- {
- for (i = 0; i < 8; i++)
- logf(" data[%d] = 0x%02x", i, data[i]);
- }
-
- /* 1-D sensor info */
- logf("1-d sensor info:");
- data[0] = MEP_READ;
- data[1] = 0x80 + 0x20;
- syn_send_data(data, 2);
- val = syn_read_device(data, 8);
- if (val > 0)
- {
- for (i = 0; i < 8; i++)
- logf(" data[%d] = 0x%02x", i, data[i]);
- }
-}
-#endif
-
void button_init_device(void)
{
/* enable touchpad leds */
@@ -514,15 +58,13 @@ void button_init_device(void)
GPIOD_OUTPUT_EN |= 0x4; /* DATA */
GPIOD_OUTPUT_VAL |= 0x4; /* high */
- syn_flush();
-
- if (syn_reset())
+ if (syn_init())
{
-#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
+#ifdef ROCKBOX_HAS_LOGF
syn_info();
#endif
- syn_status = STATUS_READY;
+ syn_status = 1;
/* enable interrupts */
GPIOD_INT_LEV &= ~0x2;
@@ -544,24 +86,25 @@ void button_int(void)
int_btn = BUTTON_NONE;
- if (syn_status == STATUS_READY)
+ if (syn_status)
{
/* disable interrupt while we read the touchpad */
- GPIOD_INT_EN &= ~0x2;
+ GPIOD_INT_EN &= ~0x2;
+ GPIOD_INT_CLR |= 0x2;
val = syn_read_device(data, 4);
if (val > 0)
{
val = data[0] & 0xff; /* packet header */
id = (data[1] >> 4) & 0xf; /* packet id */
-#if defined(LOGF_ENABLE)
+
logf("button_read_device...");
logf(" data[0] = 0x%08x", data[0]);
logf(" data[1] = 0x%08x", data[1]);
logf(" data[2] = 0x%08x", data[2]);
logf(" data[3] = 0x%08x", data[3]);
-#endif
- if ((val == BUTTONS_HEADER) && (id == BUTTONS_ID))
+
+ if ((val == MEP_BUTTON_HEADER) && (id == MEP_BUTTON_ID))
{
/* Buttons packet - touched one of the 5 "buttons" */
if (data[1] & 0x1)
@@ -577,22 +120,21 @@ void button_int(void)
/* An Absolute packet should follow which we ignore */
val = syn_read_device(data, 4);
-#if defined(LOGF_ENABLE)
+
logf(" int_btn = 0x%04x", int_btn);
-#endif
}
- else if (val == ABSOLUTE_HEADER)
+ else if (val == MEP_ABSOLUTE_HEADER)
{
/* Absolute packet - the finger is on the vertical strip.
Position ranges from 1-4095, with 1 at the bottom. */
val = ((data[1] >> 4) << 8) | data[2]; /* position */
-#if defined(LOGF_ENABLE)
+
logf(" pos %d", val);
logf(" z %d", data[3]);
logf(" finger %d", data[1] & 0x1);
logf(" gesture %d", data[1] & 0x2);
logf(" RelPosVld %d", data[1] & 0x4);
-#endif
+
if(data[1] & 0x1) /* if finger on touch strip */
{
if ((val > 0) && (val <= 1365))
@@ -607,7 +149,6 @@ void button_int(void)
/* re-enable interrupts */
GPIOD_INT_LEV &= ~0x2;
- GPIOD_INT_CLR |= 0x2;
GPIOD_INT_EN |= 0x2;
}
}