1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Michael Sevakis 2007-05-11 08:09:49 +00:00
parent 198845fe91
commit d92e09556f
4 changed files with 213 additions and 103 deletions

View file

@ -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 },

View file

@ -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

View file

@ -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;
}

View file

@ -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