diff --git a/ion/include/ion/keyboard.h b/ion/include/ion/keyboard.h index 7292f859c..22f82a0ee 100644 --- a/ion/include/ion/keyboard.h +++ b/ion/include/ion/keyboard.h @@ -3,24 +3,57 @@ #include -/* Platforms should simply set the ion_key_states pointer. - * Clients of Ion, (including ion_getchar) will then dereference this pointer to - * read the state of the keys: ion_key_states[ion_key] gives the last known - * state of ion_key */ - typedef enum { - ION_KEY_1, - ION_KEY_2, - ION_KEY_3, - ION_KEY_DIVIDE, - ION_KEY_POW, - ION_KEY_DOT + ION_KEY_A_1, + ION_KEY_A_2, + ION_KEY_A_3, + ION_KEY_A_4, + ION_KEY_A_5, + + ION_KEY_B_1, + ION_KEY_B_2, + ION_KEY_B_3, + ION_KEY_B_4, + ION_KEY_B_5, + + ION_KEY_FAKE_0, + ION_KEY_FAKE_1, + ION_KEY_C_1, + ION_KEY_C_2, + ION_KEY_C_3, + + ION_KEY_D_1, + ION_KEY_D_2, + ION_KEY_D_3, + ION_KEY_D_4, + ION_KEY_D_5, + + ION_KEY_E_1, + ION_KEY_E_2, + ION_KEY_E_3, + ION_KEY_E_4, + ION_KEY_E_5, + + ION_KEY_F_1, + ION_KEY_F_2, + ION_KEY_F_3, + ION_KEY_F_4, + ION_KEY_F_5, + + ION_KEY_G_1, + ION_KEY_G_2, + ION_KEY_G_3, + ION_KEY_G_4, + ION_KEY_G_5, + + ION_KEY_LAST } ion_key_t; -#define ION_NUMBER_OF_KEYS 6 +#define ION_NUMBER_OF_KEYS 35 -extern bool * ion_key_states; +bool ion_key_state(ion_key_t key); +// This is our keymap char ion_getchar(); #endif diff --git a/ion/platform/device/Makefile b/ion/platform/device/Makefile index a2fdd0e18..71b1e68aa 100644 --- a/ion/platform/device/Makefile +++ b/ion/platform/device/Makefile @@ -1,2 +1,2 @@ -objs += $(addprefix ion/platform/device/, platform.o init.o display.o framebuffer.o init_kbd.o display/dma.o display/gpio.o display/spi.o) -objs += $(addprefix ion/drivers/, st7586/st7586.o fx92kbd/fx92kbd.o) +objs += $(addprefix ion/platform/device/, platform.o init.o display.o framebuffer.o keyboard.o display/dma.o display/gpio.o display/spi.o) +objs += $(addprefix ion/drivers/, st7586/st7586.o) diff --git a/ion/platform/device/init.c b/ion/platform/device/init.c index 56e7f3f5f..569b22fe2 100644 --- a/ion/platform/device/init.c +++ b/ion/platform/device/init.c @@ -1,7 +1,7 @@ #include #include #include "display.h" -#include "init_kbd.h" +#include "keyboard.h" //#extern char _framebuffer_end; @@ -13,7 +13,7 @@ void ion_init() { #endif */ - init_kbd(); + init_keyboard(); init_display(); } diff --git a/ion/platform/device/keyboard.c b/ion/platform/device/keyboard.c new file mode 100644 index 000000000..325216c7f --- /dev/null +++ b/ion/platform/device/keyboard.c @@ -0,0 +1,88 @@ +/* Keyboard initialization code + * + * Our role here is to implement the "ion_key_state" function. + * The keyboard is a matrix that is as plugged as follow: + * + * | PA8 | PA9 | PA10 | PA11 | PA12 | + * ----+------+------+------+------+------+ + * PA0 | K_A1 | K_A2 | K_A3 | K_A4 | K_A5 | + * ----+------+------+------+------+------+ + * PA1 | K_B1 | K_B2 | K_B3 | K_B4 | K_B5 | + * ----+------+------+------+------+------+ + * PA2 | | | K_C1 | K_C2 | K_C3 | + * ----+------+------+------+------+------+ + * PA3 | K_D1 | K_D2 | K_D3 | K_D4 | K_D5 | + * ----+------+------+------+------+------+ + * PA4 | K_E1 | K_E2 | K_E3 | K_E4 | K_E5 | + * ----+------+------+------+------+------+ + * PA5 | K_F1 | K_F2 | K_F3 | K_F4 | K_F5 | + * ----+------+------+------+------+------+ + * PA6 | K_G1 | K_G2 | K_G3 | K_G4 | K_G5 | + * ----+------+------+------+------+------+ + * + * We decide to drive the rows (PA0-6) and read the columns (PA8-12). + * + * To avoid short-circuits, the pins A0-A6 will not be standard outputs but + * only open-drain. Open drain can either drive low or let it float. Otherwise, + * when a user presses multiple keys, a shortcut between rows could happen, + * which could trigger a short circuit between an output driving high and + * another driving low. + * + * If the outputs are open-drain, this means that the input must be pulled up. + * So if the input reads "1", this means the key is in fact *not* pressed, and + * if it reads "0" it means that there's a short to an open-drain output. Which + * means the corresponding key is pressed. + */ + +#include +#include "registers/registers.h" + +// We'll make the assertion that the row and column pins are contiguous +#define ROW_PIN_START 0 +#define ROW_PIN_END 6 +#define COLUMN_PIN_START 8 +#define COLUMN_PIN_END 12 + +static inline uint8_t row_for_key(ion_key_t key) { + return key/5; +} +static inline uint8_t column_for_key(ion_key_t key) { + return key%5; +} + +bool ion_key_state(ion_key_t key) { + /* Drive the corresponding row low, and let all the others float. + * Note: In open-drain mode, a 0 in the register drives low, and a 1 let the + * pin in Hi-Z (floating). */ + GPIO_ODR(GPIOA) = ~(1 << (column_for_key(key)+ROW_PIN_START)); + + // Wait a little... + for (int i=0;i<10000;i++) { + } + + // Read the input of the proper column + uint32_t input = (GPIO_IDR(GPIOA) & (1 << (row_for_key(key)+COLUMN_PIN_START))); + + // The key is pressed if the input is brought low by the output. In other + // words, we want to return "true" (1) if the input is low (0). + // Return the logical opposite of what we've just read + return (input == 0); +} + +void init_keyboard() { + /* We are using GPIO group A, which live on the AHB1 bus. Let's start by + * enabling its clock. */ + RCC_AHB1ENR |= GPIOAEN; + + // Configure the row pins as open-drain outputs + for (int pin=ROW_PIN_START; pin<=ROW_PIN_END; pin++) { + REGISTER_SET_VALUE(GPIO_MODER(GPIOA), MODER(pin), GPIO_MODE_OUTPUT); + REGISTER_SET_VALUE(GPIO_OTYPER(GPIOA), OTYPER(pin), GPIO_OTYPE_OPEN_DRAIN); + } + + // Configure the column as are pulled-up inputs + for (int pin=COLUMN_PIN_START; pin<=COLUMN_PIN_END; pin++) { + REGISTER_SET_VALUE(GPIO_MODER(GPIOA), MODER(pin), GPIO_MODE_INPUT); + REGISTER_SET_VALUE(GPIO_PUPDR(GPIOA), PUPDR(pin), GPIO_PUPD_PULL_UP); + } +} diff --git a/ion/platform/device/keyboard.h b/ion/platform/device/keyboard.h new file mode 100644 index 000000000..7726a3c48 --- /dev/null +++ b/ion/platform/device/keyboard.h @@ -0,0 +1 @@ +void init_keyboard(); diff --git a/ion/platform/device/registers/gpio.h b/ion/platform/device/registers/gpio.h index 304bf76c2..e1f312b6d 100644 --- a/ion/platform/device/registers/gpio.h +++ b/ion/platform/device/registers/gpio.h @@ -53,6 +53,16 @@ typedef struct { #define LOW_BIT_MODER(v) (2*v) #define HIGH_BIT_MODER(v) (2*v+1) +// GPIO port output type registers + +#define GPIO_OTYPER(gpio_group) GPIO_REGISTER_AT(gpio_group, 0x04) + +#define GPIO_OTYPE_PUSH_PULL 0 +#define GPIO_OTYPE_OPEN_DRAIN 1 + +#define LOW_BIT_OTYPER(v) (v) +#define HIGH_BIT_OTYPER(v) (v) + // GPIO port pull-up/pull-down registers #define GPIO_PUPDR(gpio_group) GPIO_REGISTER_AT(gpio_group, 0x0C) diff --git a/ion/src/keyboard.c b/ion/src/keyboard.c index d2828a22b..79e4bb855 100644 --- a/ion/src/keyboard.c +++ b/ion/src/keyboard.c @@ -1,8 +1,6 @@ #include #include -bool * ion_key_states; - char charForKey[ION_NUMBER_OF_KEYS] = { '1', '2', @@ -13,6 +11,20 @@ char charForKey[ION_NUMBER_OF_KEYS] = { }; char ion_getchar() { + while (1) { + ion_sleep(); + if (ion_key_state(0)) { + return charForKey[0]; + } + /* + for (ion_key_t k=0;k