diff options
author | Frank Dischner <phaedrus961@rockbox.org> | 2006-04-19 18:06:56 +0000 |
---|---|---|
committer | Frank Dischner <phaedrus961@rockbox.org> | 2006-04-19 18:06:56 +0000 |
commit | 5d9eccd85b46b90a9017bd7f334933b5f08c54ca (patch) | |
tree | d9046c5eaa7c3482f94eaa982b8f72acf0101de0 /firmware/drivers | |
parent | 1903fab9c568839a5e99c47fbe07d97c5318832a (diff) |
Fix button driver for ipod mini 1G.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9732 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/button.c | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 0c2e1e51f5..caf08e131d 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -225,6 +225,8 @@ void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) { int wheel_keycode = BUTTON_NONE; static int prev_scroll = -1; + static int direction = 0; + static int count = 0; static int scroll_state[4][4] = { {0, 1, -1, 0}, {-1, 0, 0, 1}, @@ -235,32 +237,39 @@ void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) if ( prev_scroll == -1 ) { prev_scroll = new_scroll; } + else if (direction != scroll_state[prev_scroll][new_scroll]) { + direction = scroll_state[prev_scroll][new_scroll]; + count = 0; + } else if (!was_hold) { - switch (scroll_state[prev_scroll][new_scroll]) { - case 1: - if (reverse) { - /* 'r' keypress */ - wheel_keycode = BUTTON_SCROLL_FWD; - } - else { - /* 'l' keypress */ - wheel_keycode = BUTTON_SCROLL_BACK; - } - break; - case -1: - if (reverse) { - /* 'l' keypress */ - wheel_keycode = BUTTON_SCROLL_BACK; - } - else { - /* 'r' keypress */ - wheel_keycode = BUTTON_SCROLL_FWD; - } - break; - default: - /* only happens if we get out of sync */ - break; - + backlight_on(); + if (++count == 6) { /* reduce sensitivity */ + count = 0; + switch (direction) { + case 1: + if (reverse) { + /* 'r' keypress */ + wheel_keycode = BUTTON_SCROLL_FWD; + } + else { + /* 'l' keypress */ + wheel_keycode = BUTTON_SCROLL_BACK; + } + break; + case -1: + if (reverse) { + /* 'l' keypress */ + wheel_keycode = BUTTON_SCROLL_BACK; + } + else { + /* 'r' keypress */ + wheel_keycode = BUTTON_SCROLL_FWD; + } + break; + default: + /* only happens if we get out of sync */ + break; + } } } if (wheel_keycode != BUTTON_NONE) @@ -273,13 +282,12 @@ void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) static int ipod_mini_button_read(void) { unsigned char source, wheel_source, state, wheel_state; + static bool was_hold = false; int btn = BUTTON_NONE; - /* - * we need some delay for mini, cause hold generates several interrupts, - * some of them delayed - */ - udelay(250); + /* The ipodlinux source had a udelay(250) here, but testing has shown that + it is not needed - tested on mini 1g. */ + /* udelay(250);*/ /* get source(s) of interupt */ source = GPIOA_INT_STAT & 0x3f; @@ -297,21 +305,27 @@ static int ipod_mini_button_read(void) GPIOA_INT_LEV = ~state; GPIOB_INT_LEV = ~wheel_state; - if (source & 0x1) - btn |= BUTTON_SELECT; - if (source & 0x2) - btn |= BUTTON_MENU; - if (source & 0x4) - btn |= BUTTON_PLAY; - if (source & 0x8) - btn |= BUTTON_RIGHT; - if (source & 0x10) - btn |= BUTTON_LEFT; + /* hold switch causes all outputs to go low */ + /* we shouldn't interpret these as key presses */ + if ((state & 0x20)) { + if (!(state & 0x1)) + btn |= BUTTON_SELECT; + if (!(state & 0x2)) + btn |= BUTTON_MENU; + if (!(state & 0x4)) + btn |= BUTTON_PLAY; + if (!(state & 0x8)) + btn |= BUTTON_RIGHT; + if (!(state & 0x10)) + btn |= BUTTON_LEFT; - if (wheel_source & 0x30) { - handle_scroll_wheel((wheel_state & 0x30) >> 4, 0, 1); + if (wheel_source & 0x30) { + handle_scroll_wheel((wheel_state & 0x30) >> 4, was_hold, 1); + } } + was_hold = button_hold(); + /* ack any active interrupts */ if (source) GPIOA_INT_CLR = source; @@ -645,8 +659,8 @@ void button_init(void) GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x3f); GPIOA_INT_CLR = GPIOA_INT_STAT & 0x3f; /* scroll wheel - set interrupt levels */ - GPIOB_INT_LEV = ~(GPIOB_INPUT_VAL & 0x3f); - GPIOB_INT_CLR = GPIOB_INT_STAT & 0x3f; + GPIOB_INT_LEV = ~(GPIOB_INPUT_VAL & 0x30); + GPIOB_INT_CLR = GPIOB_INT_STAT & 0x30; /* enable interrupts */ GPIOA_INT_EN = 0x3f; GPIOB_INT_EN = 0x30; |