summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/keymaps/keymap-e200.c10
-rw-r--r--firmware/export/pp5024.h6
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/button-e200.c270
-rw-r--r--firmware/target/arm/system-pp502x.c30
4 files changed, 213 insertions, 103 deletions
diff --git a/apps/keymaps/keymap-e200.c b/apps/keymaps/keymap-e200.c
index 8e11cadb8b..c946b5feca 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 3ed3d5dade..b9238ae98d 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 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;
}
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index 1f1cdf47b6..72e3a9b361 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