summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/calypso
diff options
context:
space:
mode:
authorAndreas.Eversberg <jolly@eversberg.eu>2010-07-18 12:56:48 +0000
committerAndreas.Eversberg <jolly@eversberg.eu>2010-07-18 12:56:48 +0000
commit8d2ed53b45bf0f344d5f6f78cd165772e8a15dee (patch)
treeed4538370bfc84ecc8f9544730f2a5816284e860 /src/target/firmware/calypso
parent0f184d1dfef64ee33a2908c9a3b54aed96ed32ea (diff)
[calypso] Rework of keypad interrupt handler.
The keys are correctly detected and debounced. There is no delay_ms in the interrupt handler anymore. When a key is pressed, the columns of the keypad are polled and debounced via timer interrupt. If no key is pressed, the timer interrupt is ignored again.
Diffstat (limited to 'src/target/firmware/calypso')
-rw-r--r--src/target/firmware/calypso/keypad.c88
1 files changed, 56 insertions, 32 deletions
diff --git a/src/target/firmware/calypso/keypad.c b/src/target/firmware/calypso/keypad.c
index 8d9c9251..526437f2 100644
--- a/src/target/firmware/calypso/keypad.c
+++ b/src/target/firmware/calypso/keypad.c
@@ -53,13 +53,14 @@ void emit_key(uint8_t key, uint8_t state)
}
}
-volatile uint32_t lastbuttons;
+volatile uint32_t lastbuttons = 0;
#define BTN_TO_KEY(name) \
((diff & BTN_##name) == BTN_##name) \
{ \
key = KEY_##name; \
diff = diff & ~BTN_##name; \
+ state = (buttons & BTN_##name) ? PRESSED : RELEASED; \
}
void dispatch_buttons(uint32_t buttons)
@@ -69,11 +70,6 @@ void dispatch_buttons(uint32_t buttons)
if (buttons == lastbuttons)
return;
- if (buttons > lastbuttons)
- state = PRESSED;
- else
- state = RELEASED;
-
uint32_t diff = buttons ^ lastbuttons;
uint8_t key=KEY_INV;
@@ -105,21 +101,24 @@ void dispatch_buttons(uint32_t buttons)
printf("\nunknown keycode: 0x%08x\n", diff);
break;
}
- if ( key == KEY_POWER )
- diff = 0;
emit_key(key, state);
}
lastbuttons = buttons;
}
+static uint8_t polling = 0;
+
static void keypad_irq(__unused enum irq_nr nr)
{
- keypad_poll();
+ /* enable polling */
+ polling = 1;
+ irq_disable(IRQ_KEYPAD_GPIO);
}
void keypad_init(uint8_t interrupts)
{
lastbuttons = 0;
+ polling = 0;
writew(0, KBD_GPIO_MASKIT);
writew(0, KBC_REG);
@@ -137,32 +136,57 @@ void keypad_set_handler(key_handler_t handler)
void keypad_poll()
{
- uint16_t reg;
- uint16_t col;
- uint32_t buttons;
-
-// putchar('\n');
- buttons = 0x0;
- //scan for BTN_POWER
- writew(0xff, KBC_REG);
- delay_ms(1);
+ static uint16_t reg;
+ static uint16_t col;
+ static uint32_t buttons = 0, debounce1 = 0, debounce2 = 0;
+
+ if (!polling)
+ return;
+
+ /* start polling */
+ if (polling == 1) {
+ writew(0x1f & ~0x1, KBC_REG); /* first col */
+ col = 0;
+ polling = 2;
+ return;
+ }
+
+ /* enable keypad irq after the signal settles */
+ if (polling == 3) {
+ irq_enable(IRQ_KEYPAD_GPIO);
+ polling = 0;
+ return;
+ }
+
reg = readw(KBR_LATCH_REG);
-// printd("%02x ", (~reg & 0x1f));
- buttons = buttons | ((~reg & 0x1f) << 20 );
+ buttons = (buttons & ~(0x1f << (col * 5)))
+ | ((~reg & 0x1f) << (col * 5 ));
+ /* if key is released, stay in column for faster debounce */
+ if ((debounce1 | debounce2) & ~buttons) {
+ debounce2 = debounce1;
+ debounce1 = buttons;
+ return;
+ }
- //scan for muxed keys if not powerbtn
- if ((~reg & 0x1f) != 0x10)
- for (col=0;col<4;col++)
- {
- writew(0x1f & ~(0x1 << col ), KBC_REG);
- delay_ms(1);
- reg = readw(KBR_LATCH_REG);
- buttons = buttons | ((~reg & 0x1f) << (col * 5 ));
-// printd("%02x ", (~reg & 0x1f));
+ col++;
+ if (col > 4) {
+ col = 0;
+ /* if power button, ignore other states */
+ if (buttons & BTN_POWER)
+ buttons = lastbuttons | BTN_POWER;
+ else if (lastbuttons & BTN_POWER)
+ buttons = lastbuttons & ~BTN_POWER;
+ dispatch_buttons(buttons);
+ if (buttons == 0) {
+ writew(0x0, KBC_REG);
+ polling = 3;
+ return;
+ }
}
- //enable keypad irq via master 'or' gate (needs col lines low in idle to work)
- writew(0, KBC_REG);
- dispatch_buttons(buttons);
+ if (col == 4)
+ writew(0xff, KBC_REG);
+ else
+ writew(0x1f & ~(0x1 << col ), KBC_REG);
}