//--- // gint:keysc - The SH7305 and I/O Key Scan Interfaces //--- #include #include #include #include #include #include #include #include #include #include #include /* Keyboard scan frequency in Hertz. Start with 128 Hz, this frequency *must be high* for the keyboard to work! Reading at low frequencies produces a lot of artifacts. See https://www.casiopeia.net/forum/viewtopic.php?p=20592. */ int keysc_scan_Hz = 128; /* Approximation in microseconds, used by the timer and repeat delays */ uint32_t keysc_scan_us = 7812; /* 1000000 / keysc_scan_Hz */ /* Keyboard scanner timer */ int keysc_tid = -1; /* Keyboard input device for this Key Scan Interface */ static keydev_t keysc_dev; /* keydev_std(): Standard keyboard input device */ keydev_t *keydev_std(void) { return &keysc_dev; } /* keysc_tick(): Update the keyboard to the next state */ static int keysc_tick(void) { GALIGNED(2) uint8_t scan[12] = { 0 }; /* Scan the key matrix: from I/O ports on SH3, KEYSC on SH4 */ if(isSH3()) iokbd_scan(scan); else { volatile uint16_t *KEYSC = (void *)0xa44b0000; uint16_t *array = (void *)&scan; for(int i = 0; i < 6; i++) { array[i] = KEYSC[i]; array[i] = (array[i] << 8) | (array[i] >> 8); } } keydev_process_state(&keysc_dev, scan); keydev_tick(&keysc_dev, keysc_scan_us); return TIMER_CONTINUE; } /* pollevent() - poll the next keyboard event */ key_event_t pollevent(void) { return keydev_unqueue_event(&keysc_dev); } /* waitevent() - wait for the next keyboard event */ key_event_t waitevent(volatile int *timeout) { while(1) { key_event_t ev = pollevent(); if(ev.type != KEYEV_NONE) return ev; if(timeout && *timeout) break; sleep(); } key_event_t ev = { .type = KEYEV_NONE, .time = keysc_dev.time }; return ev; } /* clearevents(): Read all events waiting in the queue */ void clearevents(void) { while(pollevent().type != KEYEV_NONE); } /* keydown(): Current key state */ int keydown(int key) { return keydev_keydown(&keysc_dev, key); } //--- // Driver initialization //--- static void configure(void) { keydev_init(&keysc_dev); /* Set the default repeat to 400/40 ms */ keydev_t *d = keydev_std(); keydev_set_transform(d, (keydev_transform_t){ KEYDEV_TR_REPEATS, NULL }); keydev_set_standard_repeats(d, 400 * 1000, 40 * 1000); /* The timer will be stopped when the timer driver is unloaded */ keysc_tid = timer_configure(TIMER_ANY, keysc_scan_us, GINT_CALL(keysc_tick)); if(keysc_tid >= 0) timer_start(keysc_tid); gint[HWKBD] = HW_LOADED | (isSH3() ? HWKBD_IO : HWKBD_KSI); } //--- // State and driver metadata //--- gint_driver_t drv_keysc = { .name = "KEYSC", .configure = configure, }; GINT_DECLARE_DRIVER(23, drv_keysc);