From 7be0213030d2ce50e618e72b5a90e4c5b63c59a4 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 16 Aug 2011 13:19:29 +0200 Subject: checked in clean osmocombb lib --- Src/osmocombb/src/target/firmware/calypso/keypad.c | 198 +++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 Src/osmocombb/src/target/firmware/calypso/keypad.c (limited to 'Src/osmocombb/src/target/firmware/calypso/keypad.c') diff --git a/Src/osmocombb/src/target/firmware/calypso/keypad.c b/Src/osmocombb/src/target/firmware/calypso/keypad.c new file mode 100644 index 0000000..fd4e0ff --- /dev/null +++ b/Src/osmocombb/src/target/firmware/calypso/keypad.c @@ -0,0 +1,198 @@ +/* Driver for the keypad attached to the TI Calypso */ + +/* (C) 2010 by roh + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +#define KBR_LATCH_REG 0xfffe480a +#define KBC_REG 0xfffe480c +#define KBD_GPIO_INT 0xfffe4816 +#define KBD_GPIO_MASKIT 0xfffe4818 + +static key_handler_t key_handler = NULL; + +void emit_key(uint8_t key, uint8_t state) +{ + printf("key=%u %s\n", key, state == PRESSED ? "pressed" : "released"); + + if (state == RELEASED) + if (key == KEY_POWER) + twl3025_power_off(); + + if(key_handler) { + key_handler(key, state); + } +} + +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) +{ + uint8_t state; + + if (buttons == lastbuttons) + return; + + uint32_t diff = buttons ^ lastbuttons; + uint8_t key=KEY_INV; + + while (diff != 0) + { + if BTN_TO_KEY(POWER) + else if BTN_TO_KEY(0) + else if BTN_TO_KEY(1) + else if BTN_TO_KEY(2) + else if BTN_TO_KEY(3) + else if BTN_TO_KEY(4) + else if BTN_TO_KEY(5) + else if BTN_TO_KEY(6) + else if BTN_TO_KEY(7) + else if BTN_TO_KEY(8) + else if BTN_TO_KEY(9) + else if BTN_TO_KEY(STAR) + else if BTN_TO_KEY(HASH) + else if BTN_TO_KEY(MENU) + else if BTN_TO_KEY(LEFT_SB) + else if BTN_TO_KEY(RIGHT_SB) + else if BTN_TO_KEY(UP) + else if BTN_TO_KEY(DOWN) + else if BTN_TO_KEY(LEFT) + else if BTN_TO_KEY(RIGHT) + else if BTN_TO_KEY(OK) + else + { + printf("\nunknown keycode: 0x%08x\n", diff); + break; + } + emit_key(key, state); + } + lastbuttons = buttons; +} + +static uint8_t polling = 0; +static uint8_t with_interrupts = 0; + +static void keypad_irq(__unused enum irq_nr nr) +{ + /* 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); + + if(interrupts) { + with_interrupts = 1; + irq_register_handler(IRQ_KEYPAD_GPIO, &keypad_irq); + irq_config(IRQ_KEYPAD_GPIO, 0, 0, 0); + irq_enable(IRQ_KEYPAD_GPIO); + } +} + +void keypad_set_handler(key_handler_t handler) +{ + key_handler = handler; +} + +void keypad_poll() +{ + static uint16_t reg; + static uint16_t col; + static uint32_t buttons = 0, debounce1 = 0, debounce2 = 0; + + if (with_interrupts && !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) { + if(with_interrupts) { + irq_enable(IRQ_KEYPAD_GPIO); + polling = 0; + } else { + polling = 1; + } + return; + } + + reg = readw(KBR_LATCH_REG); + 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; + } + + 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; + } + } + if (col == 4) + writew(0xff, KBC_REG); + else + writew(0x1f & ~(0x1 << col ), KBC_REG); + +} + -- cgit v1.2.3-55-g7522