diff options
Diffstat (limited to 'pit.c')
-rw-r--r-- | pit.c | 126 |
1 files changed, 123 insertions, 3 deletions
@@ -16,13 +16,133 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <arrlen.h> +#include <cm4.h> +#include <reg/gpio.h> #include <reg/pit.h> +#include <reg/port.h> +#include <reg/sim.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> #include "pit.h" +#include "usb/endpt1.h" +#include "usb/keycodes.h" + +enum { + T0_CYCLES = 5000, +}; + +struct gpio { + uint32_t port; + uint32_t gpio; + uint32_t bit; + unsigned char pin; +}; +#define GPIO_PIN(port, pin) { \ + PORT##port##_BASE, \ + GPIO##port##_BASE, \ + BV((pin)), \ + (pin), \ +} + +static const struct gpio cols[] = { + GPIO_PIN(B, 2), + GPIO_PIN(B, 3), + GPIO_PIN(B, 18), + GPIO_PIN(B, 19), + GPIO_PIN(C, 0), + GPIO_PIN(C, 8), + GPIO_PIN(C, 9), + GPIO_PIN(C, 10), + GPIO_PIN(C, 11), +}; + +static const struct gpio rows[] = { + GPIO_PIN(D, 0), + GPIO_PIN(D, 1), + GPIO_PIN(D, 4), + GPIO_PIN(D, 5), + GPIO_PIN(D, 6), + GPIO_PIN(D, 7), + GPIO_PIN(C, 1), + GPIO_PIN(C, 2), +}; + +/* COL AND ROW SWAPPED!!! */ +static enum keycode keymap[ARRLEN(rows)][ARRLEN(cols)] = { + { /* S01 */ KEY_ESCAPE, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, }, + { /* S10 */ KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_NONE, KEY_BACKSPACE, KEY_GRAVE, KEY_TAB, KEY_Q, }, + { /* S19 */ KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, }, + { /* S28 */ KEY_LSQUARE, KEY_RSQUARE, KEY_NONE, KEY_DELETE, KEY_CAPSLK, KEY_A, KEY_S, KEY_D, KEY_F, }, + { /* S37 */ KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_QUOTE, KEY_BACKSLASH, KEY_ENTER, }, + { /* S46 */ KEY_PGUP, KEY_LSHIFT, KEY_NU_BACKSLASH, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, }, + { /* S55 */ KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_RSHIFT, KEY_UP, KEY_PGDN, KEY_LCTRL, KEY_LGUI, }, + { /* S64 */ KEY_LALT, KEY_SPACE, KEY_RALT, KEY_NONE, KEY_RCTRL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, }, +}; void pit_setup(void) { - /* TODO */ - while (1) - ; + /* Set up ports (could be done with GPC registers */ + for (size_t i = 0; i < ARRLEN(cols); i++) { + SET_BIT(GPIO_PDDR(cols[i].gpio), cols[i].pin); + GPIO_PCOR(cols[i].gpio) = cols[i].bit; + PORT_PCR(cols[i].port, cols[i].pin) = BV(PCR_SRE) | BV(PCR_DSE) + | 1 << PCR_MUX; + } + for (size_t i = 0; i < ARRLEN(rows); i++) { + UNSET_BIT(GPIO_PDDR(rows[i].gpio), rows[i].pin); + PORT_PCR(rows[i].port, rows[i].pin) = BV(PCR_PFE) | BV(PCR_PE) + | 1 << PCR_MUX; + } + + /* Enable clock */ + SET_BIT(SIM_SCGC6, SCGC6_PIT); + + /* NVIC Enable interrupt */ + ISR_CLRPEND(68); + ISR_SETENA(68); + INTPRI(68) = 0x10; + + /* First column strobe */ + GPIO_PSOR(cols[0].gpio) = cols[0].bit; + + /* Set up PIT0 */ + PIT_MCR = 0; + + PIT_LDVAL(0) = T0_CYCLES - 1; + PIT_TFLG(0) = BV(TFLG_TIF); + PIT_TCTRL(0) = BV(TCTRL_TIE) | BV(TCTRL_TEN); +} + +static uint8_t kstates[ARRLEN(cols)][ARRLEN(rows)] = { 0 }; + +static void key_state(int col, int row, bool state) +{ + uint8_t kstate; + + kstate = kstates[col][row] = kstates[col][row] << 1 | state; + + if (kstate == 0x7f) + usb_endpt1_setkey(keymap[row][col], true); + else if (kstate == 0x80) + usb_endpt1_setkey(keymap[row][col], false); +} + +void pit0_isr(void) +{ + static unsigned char col = 0; + + for (size_t row = 0; row < ARRLEN(rows); row++) + key_state(col, row, !!(GPIO_PDIR(rows[row].gpio) & rows[row].bit)); + + GPIO_PCOR(cols[col].gpio) = cols[col].bit; + col = (col + 1) % ARRLEN(cols); + GPIO_PSOR(cols[col].gpio) = cols[col].bit; + + if (col == 0) + usb_endpt1_send(); + + PIT_TFLG(0) = BV(TFLG_TIF); } |