Index: firmware/target/arm/sandisk/sansa-e200/button-e200.c =================================================================== --- firmware/target/arm/sandisk/sansa-e200/button-e200.c (revision 13357) +++ firmware/target/arm/sandisk/sansa-e200/button-e200.c (working copy) @@ -26,6 +26,9 @@ static unsigned int old_wheel_value = 0; static unsigned int wheel_repeat = BUTTON_NONE; +/* Variable to use for setting button status in interrupt handler */ +int int_btn = BUTTON_NONE; + void button_init_device(void) { /* Enable all buttons */ @@ -45,16 +48,118 @@ return (GPIOF_INPUT_VAL & 0x80)?true:false; } +int e200_button_read(void) +{ + unsigned char source, wheel_source, state, wheel_state; + int btn = BUTTON_NONE; + unsigned int new_wheel_value; + + /* get source(s) of interupt */ + source = GPIOF_INT_STAT & 0xff; + wheel_source = GPIOH_INT_STAT & 0xc0; + + if (source == 0 && wheel_source ==0) { + return BUTTON_NONE; /* not for us */ + } + + /* get current keypad & wheel status */ + state = GPIOF_INPUT_VAL & 0xff; + wheel_state = GPIOH_INPUT_VAL & 0xc0; + + /* toggle interrupt level */ + GPIOF_INT_LEV = ~state; + GPIOH_INT_LEV = ~wheel_state; + + /* device buttons */ + if (!button_hold()) + { + if(source) + { + /* Read normal buttons */ + 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 scrollwheel */ + if (wheel_source) + { + 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; + } + } + + /* ack any active interrupts */ + if (source) + GPIOF_INT_CLR = source; + if (wheel_source) + GPIOH_INT_CLR = wheel_source; + + return btn; +} + /* + * Respond to interrupt + */ +void button_int(void) +{ + CPU_HI_INT_CLR = 0x40; + int_btn = e200_button_read(); + CPU_HI_INT_EN = 0x40; +} + +/* * Get button pressed from hardware */ 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; @@ -68,83 +173,13 @@ } #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)); - } + + if( (int_btn & BUTTON_SCROLL_UP) || (int_btn & 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; } Index: firmware/target/arm/sandisk/sansa-e200/button-target.h =================================================================== --- firmware/target/arm/sandisk/sansa-e200/button-target.h (revision 13357) +++ firmware/target/arm/sandisk/sansa-e200/button-target.h (working copy) @@ -28,6 +28,7 @@ bool button_hold(void); void button_init_device(void); int button_read_device(void); +void button_int(void); /* Sandisk Sansa E200 button codes */ Index: firmware/target/arm/system-pp502x.c =================================================================== --- firmware/target/arm/system-pp502x.c (revision 13357) +++ firmware/target/arm/system-pp502x.c (working copy) @@ -64,6 +64,8 @@ TIMER1(); else if (CPU_INT_STAT & TIMER2_MASK) TIMER2(); + else if (HI_INT_STAT & 0x40) + button_int(); } else { if (COP_INT_STAT & TIMER1_MASK) TIMER1();