diff options
| -rw-r--r-- | apps/keymaps/keymap-e200.c | 10 | ||||
| -rw-r--r-- | firmware/export/pp5024.h | 6 | ||||
| -rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/button-e200.c | 270 | ||||
| -rw-r--r-- | firmware/target/arm/system-pp502x.c | 30 |
4 files changed, 213 insertions, 103 deletions
diff --git a/apps/keymaps/keymap-e200.c b/apps/keymaps/keymap-e200.c index 8e11cad..c946b5f 100644 --- a/apps/keymaps/keymap-e200.c +++ b/apps/keymaps/keymap-e200.c @@ -31,9 +31,9 @@ * Insert LAST_ITEM_IN_LIST at the end of each mapping */ static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_SCROLL_UP|BUTTON_REL, BUTTON_NONE }, + { ACTION_STD_PREV, BUTTON_SCROLL_UP, BUTTON_NONE }, { ACTION_STD_PREVREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_SCROLL_DOWN|BUTTON_REL, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_SCROLL_DOWN, BUTTON_NONE }, { ACTION_STD_NEXTREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_STD_MENU, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, @@ -159,9 +159,9 @@ static const struct button_mapping button_context_quickscreen[] = { }; /* button_context_quickscreen */ static const struct button_mapping button_context_settings_right_is_inc[] = { - { ACTION_SETTINGS_INC, BUTTON_SCROLL_DOWN|BUTTON_REL, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_SCROLL_UP|BUTTON_REL, BUTTON_NONE }, + { ACTION_SETTINGS_INC, BUTTON_SCROLL_DOWN, BUTTON_NONE }, + { ACTION_SETTINGS_INCREPEAT, BUTTON_SCROLL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_DEC, BUTTON_SCROLL_UP, BUTTON_NONE }, { ACTION_SETTINGS_DECREPEAT, BUTTON_SCROLL_UP|BUTTON_REPEAT,BUTTON_NONE }, { ACTION_STD_PREV, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, diff --git a/firmware/export/pp5024.h b/firmware/export/pp5024.h index 3ed3d5d..b9238ae 100644 --- a/firmware/export/pp5024.h +++ b/firmware/export/pp5024.h @@ -23,4 +23,10 @@ completely */ #include "pp5020.h" +#undef GPIO_IRQ +#define GPIO_IRQ (32+6) + +#undef GPIO_MASK +#define GPIO_MASK (1 << (GPIO_IRQ-32)) + #endif diff --git a/firmware/target/arm/sandisk/sansa-e200/button-e200.c b/firmware/target/arm/sandisk/sansa-e200/button-e200.c index 028a76f..168332e 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; } diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c index 1f1cdf4..72e3a9b 100644 --- a/firmware/target/arm/system-pp502x.c +++ b/firmware/target/arm/system-pp502x.c @@ -56,12 +56,21 @@ void irq(void) /* TODO: this should really be in the target tree, but moving it there caused crt0.S not to find it while linking */ /* TODO: Even if it isn't in the target tree, this should be the default case */ +extern void button_int(void); +extern void clickwheel_int(void); + void irq(void) { - if(CURRENT_CORE == CPU) - { - if (CPU_INT_STAT & TIMER1_MASK) + if(CURRENT_CORE == CPU) { + if (CPU_INT_STAT & TIMER1_MASK) { +#ifdef SANSA_E200 + if (GPIOF_INT_STAT & 0xff) + button_int(); + if (GPIOH_INT_STAT & 0xc0) + clickwheel_int(); +#endif TIMER1(); + } else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); } else { @@ -222,7 +231,20 @@ void system_init(void) COP_INT_CLR = -1; CPU_INT_CLR = -1; INT_FORCED_CLR = -1; - + + GPIOA_INT_EN = 0; + GPIOB_INT_EN = 0; + GPIOC_INT_EN = 0; + GPIOD_INT_EN = 0; + GPIOE_INT_EN = 0; + GPIOF_INT_EN = 0; + GPIOG_INT_EN = 0; + GPIOH_INT_EN = 0; + GPIOI_INT_EN = 0; + GPIOJ_INT_EN = 0; + GPIOK_INT_EN = 0; + GPIOL_INT_EN = 0; + # if NUM_CORES > 1 && defined(HAVE_ADJUSTABLE_CPU_FREQ) spinlock_init(&boostctrl_mtx); # endif |