diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-05-11 08:09:49 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-05-11 08:09:49 +0000 |
commit | d92e09556fdec3fbd65e153c6f41c31cb1e04c42 (patch) | |
tree | 38ceff3ef5ea2664f408675533dfe7292cb9c8b5 /firmware/target/arm/sandisk/sansa-e200/button-e200.c | |
parent | 198845fe91d09153c092df86e0337020eba79c87 (diff) |
GPIO IRQ ready button driver for e200 series. Can't actually use them yet but their status is polled. Easy to switch over once that works. Cheapo acceleration added or else it would be too fast for selecting items. Too much scrolling might cause the PCM buffer to empty out - beware. )
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13371 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-e200/button-e200.c')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/button-e200.c | 270 |
1 files changed, 176 insertions, 94 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/button-e200.c b/firmware/target/arm/sandisk/sansa-e200/button-e200.c index 028a76f7a8..168332e3c1 100644 --- a/firmware/target/arm/sandisk/sansa-e200/button-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/button-e200.c @@ -23,26 +23,193 @@ #include "button.h" #include "backlight.h" -static unsigned int old_wheel_value = 0; -static unsigned int wheel_repeat = BUTTON_NONE; +#define WHEEL_REPEAT_INTERVAL 30 +#define WHEEL_FAST_ON_INTERVAL 2 +#define WHEEL_FAST_OFF_INTERVAL 6 + +/* Clickwheel */ +static unsigned int old_wheel_value = 0; +static unsigned int wheel_repeat = BUTTON_NONE; +static unsigned int wheel_click_count = 0; +static int wheel_fast_mode = 0; +static unsigned long last_wheel_tick = 0; +static unsigned long last_wheel_post = 0; +#ifndef BOOTLOADER +static unsigned long next_backlight_on = 0; +#endif +/* Buttons */ +static bool hold_button = false; +static bool hold_button_old = false; +static int int_btn = BUTTON_NONE; void button_init_device(void) { /* Enable all buttons */ + GPIOF_OUTPUT_EN &= ~0xff; GPIOF_ENABLE |= 0xff; - GPIOH_ENABLE |= 0xc0; /* Scrollwheel light - enable control through GPIOG pin 7 and set timeout */ - GPIOG_ENABLE = 0x80; GPIOG_OUTPUT_EN |= 0x80; - + GPIOG_ENABLE = 0x80; + + GPIOH_ENABLE |= 0xc0; + GPIOH_OUTPUT_EN &= ~0xc0; + +#if 0 + CPU_INT_PRIORITY &= ~HI_MASK; + CPU_HI_INT_PRIORITY &= ~GPIO_MASK; + + CPU_INT_CLR = HI_MASK; + CPU_HI_INT_CLR = GPIO_MASK; +#endif + GPIOF_INT_CLR = 0xff; + GPIOH_INT_CLR = 0xc0; + + /* Read initial buttons */ + old_wheel_value = GPIOF_INPUT_VAL & 0xff; + GPIOF_INT_LEV = (GPIOF_INT_LEV & ~0xff) | (old_wheel_value ^ 0xff); + hold_button = (GPIOF_INPUT_VAL & 0x80) != 0; + /* Read initial wheel value (bit 6-7 of GPIOH) */ old_wheel_value = GPIOH_INPUT_VAL & 0xc0; + GPIOH_INT_LEV = (GPIOH_INT_LEV & ~0xc0) | (old_wheel_value ^ 0xc0); + + GPIOF_INT_EN = 0xff; + GPIOH_INT_EN = 0xc0; +#if 0 + CPU_HI_INT_EN = GPIO_MASK; + CPU_INT_EN = HI_MASK; +#endif + + last_wheel_tick = current_tick; + last_wheel_post = current_tick; } bool button_hold(void) { - return (GPIOF_INPUT_VAL & 0x80)?true:false; + return hold_button; +} + +void clickwheel_int(void) +{ + /* Read wheel + * Bits 6 and 7 of GPIOH change as follows: + * Clockwise rotation 01 -> 00 -> 10 -> 11 + * Counter-clockwise 11 -> 10 -> 00 -> 01 + * + * This is equivalent to wheel_value of: + * Clockwise rotation 0x40 -> 0x00 -> 0x80 -> 0xc0 + * Counter-clockwise 0xc0 -> 0x80 -> 0x00 -> 0x40 + */ + static const unsigned char wheel_tbl[2][4] = + { + /* 0x00 0x40 0x80 0xc0 */ /* Wheel value */ + { 0x40, 0xc0, 0x00, 0x80 }, /* Clockwise rotation */ + { 0x80, 0x00, 0xc0, 0x40 }, /* Counter-clockwise */ + }; + + unsigned int wheel_value; + + GPIOH_INT_CLR = GPIOH_INT_STAT & 0xc0; + + wheel_value = GPIOH_INPUT_VAL & 0xc0; + GPIOH_INT_LEV = (GPIOH_INT_LEV & ~0xc0) | (wheel_value ^ 0xc0); + + if (!hold_button) + { + unsigned int btn = BUTTON_NONE; + + if (old_wheel_value == wheel_tbl[0][wheel_value >> 6]) + btn = BUTTON_SCROLL_DOWN; + else if (old_wheel_value == wheel_tbl[1][wheel_value >> 6]) + btn = BUTTON_SCROLL_UP; + + if (btn != BUTTON_NONE) + { + int repeat = 1; + + if (btn != wheel_repeat) + { + wheel_repeat = btn; + repeat = + wheel_fast_mode = + wheel_click_count = 0; + } + + if (wheel_fast_mode) + { + if (TIME_AFTER(current_tick, + last_wheel_tick + WHEEL_FAST_OFF_INTERVAL)) + { + if (++wheel_click_count < 2) + btn = BUTTON_NONE; + wheel_fast_mode = 0; + } + } + else + { + if (repeat && TIME_BEFORE(current_tick, + last_wheel_tick + WHEEL_FAST_ON_INTERVAL)) + wheel_fast_mode = 1; + else if (++wheel_click_count < 2) + btn = BUTTON_NONE; + } + +#ifndef BOOTLOADER + if (TIME_AFTER(current_tick, next_backlight_on)) + { + next_backlight_on = current_tick + HZ/4; + backlight_on(); + button_backlight_on(); + } +#endif + if (btn != BUTTON_NONE) + { + wheel_click_count = 0; + + if (repeat && TIME_BEFORE(current_tick, + last_wheel_post + WHEEL_REPEAT_INTERVAL)) + btn |= BUTTON_REPEAT; + + last_wheel_post = current_tick; + + if (queue_empty(&button_queue)) + queue_post(&button_queue, btn, 0); + } + + last_wheel_tick = current_tick; + } + } + + old_wheel_value = wheel_value; +} + +void button_int(void) +{ + unsigned char state; + + GPIOF_INT_CLR = GPIOF_INT_STAT; + + state = GPIOF_INPUT_VAL & 0xff; + + GPIOF_INT_LEV = (GPIOF_INT_LEV & ~0xff) | (state ^ 0xff); + + int_btn = BUTTON_NONE; + + hold_button = (state & 0x80) != 0; + + /* device buttons */ + if (!hold_button) + { + /* Read normal buttons */ + if ((state & 0x01) == 0) int_btn |= BUTTON_REC; + if ((state & 0x02) == 0) int_btn |= BUTTON_DOWN; + if ((state & 0x04) == 0) int_btn |= BUTTON_RIGHT; + if ((state & 0x08) == 0) int_btn |= BUTTON_LEFT; + if ((state & 0x10) == 0) int_btn |= BUTTON_SELECT; /* The centre button */ + if ((state & 0x20) == 0) int_btn |= BUTTON_UP; /* The "play" button */ + if ((state & 0x40) != 0) int_btn |= BUTTON_POWER; + } } /* @@ -50,101 +217,16 @@ bool button_hold(void) */ int button_read_device(void) { - int btn = BUTTON_NONE; - unsigned char state; - static bool hold_button = false; - bool hold_button_old; - unsigned int new_wheel_value = 0; /* read later, but this stops a warning */ - /* Hold */ - hold_button_old = hold_button; - hold_button = button_hold(); - #ifndef BOOTLOADER /* light handling */ if (hold_button != hold_button_old) { + hold_button_old = hold_button; backlight_hold_changed(hold_button); } #endif - /* device buttons */ - if (!hold_button) - { - /* Read normal buttons */ - state = GPIOF_INPUT_VAL & 0xff; - if ((state & 0x1) == 0) btn |= BUTTON_REC; - if ((state & 0x2) == 0) btn |= BUTTON_DOWN; - if ((state & 0x4) == 0) btn |= BUTTON_RIGHT; - if ((state & 0x8) == 0) btn |= BUTTON_LEFT; - if ((state & 0x10) == 0) btn |= BUTTON_SELECT; /* The centre button */ - if ((state & 0x20) == 0) btn |= BUTTON_UP; /* The "play" button */ - if ((state & 0x40) != 0) btn |= BUTTON_POWER; - - /* Read wheel - * Bits 6 and 7 of GPIOH change as follows: - * Clockwise rotation 01 -> 00 -> 10 -> 11 - * Counter-clockwise 11 -> 10 -> 00 -> 01 - * - * This is equivalent to wheel_value of: - * Clockwise rotation 0x40 -> 0x00 -> 0x80 -> 0xc0 - * Counter-clockwise 0xc0 -> 0x80 -> 0x00 -> 0x40 - */ - new_wheel_value = GPIOH_INPUT_VAL & 0xc0; - switch(new_wheel_value){ - case 0x00: - if(old_wheel_value==0x80) - btn |= BUTTON_SCROLL_UP; - else if (old_wheel_value==0x40) - btn |= BUTTON_SCROLL_DOWN; - break; - case 0x40: - if(old_wheel_value==0x00) - btn |= BUTTON_SCROLL_UP; - else if (old_wheel_value==0xc0) - btn |= BUTTON_SCROLL_DOWN; - break; - case 0x80: - if(old_wheel_value==0xc0) - btn |= BUTTON_SCROLL_UP; - else if (old_wheel_value==0x00) - btn |= BUTTON_SCROLL_DOWN; - break; - case 0xc0: - if(old_wheel_value==0x40) - btn |= BUTTON_SCROLL_UP; - else if (old_wheel_value==0x80) - btn |= BUTTON_SCROLL_DOWN; - break; - } - - if(wheel_repeat == BUTTON_NONE){ - if(btn & BUTTON_SCROLL_UP) - wheel_repeat = BUTTON_SCROLL_UP; - - if(btn & BUTTON_SCROLL_DOWN) - wheel_repeat = BUTTON_SCROLL_DOWN; - } else if (wheel_repeat == BUTTON_SCROLL_UP) { - btn |= BUTTON_SCROLL_UP; - wheel_repeat = BUTTON_NONE; - } else if (wheel_repeat == BUTTON_SCROLL_DOWN) { - btn |= BUTTON_SCROLL_DOWN; - wheel_repeat = BUTTON_NONE; - } - - old_wheel_value = new_wheel_value; - } - - if( (btn & BUTTON_SCROLL_UP) || (btn & BUTTON_SCROLL_DOWN) ){ - /* only trigger once per click */ - if ((new_wheel_value == 0x00) || (new_wheel_value == 0xc0)) - { - btn = btn&(~(BUTTON_SCROLL_UP|BUTTON_SCROLL_DOWN)); - } -#ifndef BOOTLOADER - button_backlight_on(); -#endif - } - - return btn; + /* The int_btn variable is set in the button interrupt handler */ + return int_btn; } |