cleanup a bit, put keyboard init & reading things into a semi-nicer API

still pretty low-level. will be fleshing this out more soon. :-)
This commit is contained in:
Gered 2021-02-15 18:48:00 -05:00
parent d3a8c22b67
commit 7429c134f8
4 changed files with 128 additions and 85 deletions

View file

@ -8,7 +8,7 @@ project(${PROJECT_NAME} C ASM)
set(CMAKE_VERBOSE_MAKEFILE OFF)
set(CMAKE_C_STANDARD 99)
add_executable(${PROJECT_NAME}.elf src/main.c)
add_executable(${PROJECT_NAME}.elf src/main.c src/gckeybrd.c)
target_link_directories(${PROJECT_NAME}.elf PRIVATE ${DEVKITPRO}/libogc/lib/wii)
target_link_libraries(${PROJECT_NAME}.elf PRIVATE db wiiuse bte ogc m)

83
src/gckeybrd.c Normal file
View file

@ -0,0 +1,83 @@
#include <gccore.h>
#if defined(HW_DOL)
#define SI_REG_BASE 0xCC006400
#elif defined(HW_RVL)
#define SI_REG_BASE 0xCD006400
#else
#error Hardware model unknown? Missing a preprocessor definition somewhere...
#endif
#define SIREG(n) ((vu32*)(SI_REG_BASE + (n)))
#define SICOUTBUF(n) (SIREG(0x00 + (n)*12)) /* SI Channel n Output Buffer (Joy-channel n Command) (4 bytes) */
#define SICINBUFH(i) (SIREG(0x04 + (i)*12)) /* SI Channel n Input Buffer High (Joy-channel n Buttons 1) (4 bytes) */
#define SICINBUFL(i) (SIREG(0x08 + (i)*12)) /* SI Channel n Input Buffer Low (Joy-channel n Buttons 2) (4 bytes) */
#define SIPOLL (SIREG(0x30)) /* SI Poll Register (4 bytes) */
#define SICOMCSR (SIREG(0x34)) /* SI Communication Control Status Register (command) (4 bytes) */
#define SISR (SIREG(0x38)) /* SI Status Register (4 bytes) */
#define SIIOBUF (SIREG(0x80)) /* SI I/O buffer (access by word) (128 bytes) */
#define PAD_ENABLEDMASK(chan) (0x80000000 >> chan)
static void SI_AwaitPendingCommands(void) {
while(*SICOMCSR & 0x1);
}
int GCKB_Detect(void) {
SI_AwaitPendingCommands();
u32 buf[2];
for (int i = 0; i < 4; ++i) {
SI_GetResponse(i, buf);
SI_SetCommand(i, 0x00400300);
SI_EnablePolling(PAD_ENABLEDMASK(i));
}
SI_AwaitPendingCommands();
int keyboardChan = -1;
for (int i = 0; i < 4; ++i) {
u32 type = SI_DecodeType(SI_GetType(i));
if (type == SI_GC_KEYBOARD)
keyboardChan = i;
}
return keyboardChan;
}
int GCKB_Init(int chan) {
if (chan == -1)
return 0;
u32 buf[2];
SI_GetResponse(chan, buf);
SI_SetCommand(chan, 0x00540000);
SI_EnablePolling(PAD_ENABLEDMASK(chan));
SI_TransferCommands();
SI_AwaitPendingCommands();
return 1;
}
int GCKB_ReadKeys(int chan, u8 *pressedKeys) {
if (chan == -1)
return 0;
if (!pressedKeys)
return 0;
u32 buffer[2];
if (SI_GetResponse(chan, buffer)) {
pressedKeys[0] = buffer[1] >> 24;
pressedKeys[1] = (buffer[1] >> 16) & 0xff;
pressedKeys[2] = (buffer[1] >> 8) & 0xff;
return 1;
} else {
pressedKeys[0] = 0;
pressedKeys[1] = 0;
pressedKeys[2] = 0;
}
return 0;
}

29
src/gckeybrd.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef GCKEYBRD_H_INCLUDED
#define GCKEYBRD_H_INCLUDED
#include <gctypes.h>
/**
* Attempts to detect the presence of a GC Keyboard Controller connected to any of the controller ports.
* Returns the SI channel of the found keyboard controller, or -1 if one could not be found.
*/
int GCKB_Detect(void);
/**
* Initializes the keyboard controller, previously detected on the given SI channel. This must be called before
* key press information can be read. Returns 1 on success, 0 on failure.
*/
int GCKB_Init(int chan);
/**
* Reads current key press information from the previously initialized keyboard controller, located on the given
* SI channel. Returns 1 if key press data has been returned, or 0 on failure.
*
* The pressedKeys buffer passed in should be large enough to hold 3 bytes. Each byte will correspond to one key
* pressed. The keyboard controller can only recognize 3 simultaneous key presses at a time (and, depending on the
* specific keys, probably only 2 at a time). If too many keys are held down, all of the values returned will be 0x02.
* A value of 0x00 indicates no key press.
*/
int GCKB_ReadKeys(int chan, u8 *pressedKeys);
#endif

View file

@ -3,72 +3,11 @@
#include <gccore.h>
#include <debug.h>
#include "gckeybrd.h"
static void *xfb = NULL;
static GXRModeObj *rmode = NULL;
#if defined(HW_DOL)
#define SI_REG_BASE 0xCC006400
#elif defined(HW_RVL)
#define SI_REG_BASE 0xCD006400
#else
#error HW model unknown.
#endif
#define SIREG(n) ((vu32*)(SI_REG_BASE + (n)))
#define SICOUTBUF(n) (SIREG(0x00 + (n)*12)) /* SI Channel n Output Buffer (Joy-channel n Command) (4 bytes) */
#define SICINBUFH(i) (SIREG(0x04 + (i)*12)) /* SI Channel n Input Buffer High (Joy-channel n Buttons 1) (4 bytes) */
#define SICINBUFL(i) (SIREG(0x08 + (i)*12)) /* SI Channel n Input Buffer Low (Joy-channel n Buttons 2) (4 bytes) */
#define SIPOLL (SIREG(0x30)) /* SI Poll Register (4 bytes) */
#define SICOMCSR (SIREG(0x34)) /* SI Communication Control Status Register (command) (4 bytes) */
#define SISR (SIREG(0x38)) /* SI Status Register (4 bytes) */
#define SIIOBUF (SIREG(0x80)) /* SI I/O buffer (access by word) (128 bytes) */
#define PAD_ENABLEDMASK(chan) (0x80000000 >> chan)
static void SI_AwaitPendingCommands(void) {
while(*SICOMCSR & 0x1);
}
static int SI_DetectGCKeyboard(void) {
SI_AwaitPendingCommands();
u32 buf[2];
for (int i = 0; i < 4; ++i) {
SI_GetResponse(i, buf);
SI_SetCommand(i, 0x00400300);
SI_EnablePolling(PAD_ENABLEDMASK(i));
}
SI_AwaitPendingCommands();
int keyboardChan = -1;
for (int i = 0; i < 4; ++i) {
u32 type = SI_DecodeType(SI_GetType(i));
if (type == SI_GC_KEYBOARD)
keyboardChan = i;
}
return keyboardChan;
}
static int SI_InitGCKeyboard(int chan) {
if (chan == -1)
return 0;
u32 buf[2];
SI_GetResponse(chan, buf);
SI_SetCommand(chan, 0x00540000);
SI_EnablePolling(PAD_ENABLEDMASK(chan));
SI_TransferCommands();
SI_AwaitPendingCommands();
return 1;
}
int main(int argc, char **argv) {
VIDEO_Init();
@ -87,31 +26,27 @@ int main(int argc, char **argv) {
printf("\n\nHello ...\n");
DEBUG_Init(GDBSTUB_DEVICE_USB,1);
printf("Waiting for debugger ...\n");
_break();
printf("debugger connected ...\n");
//DEBUG_Init(GDBSTUB_DEVICE_USB,1);
//printf("Waiting for debugger ...\n");
//_break();
//printf("debugger connected ...\n");
PAD_Init();
int keyboardChan = SI_DetectGCKeyboard();
printf("Keyboard located at chan %d\n", keyboardChan);
int keyboardChan = GCKB_Detect();
printf("GC Keyboard located at chan %d\n", keyboardChan);
int keyboardEnabled = SI_InitGCKeyboard(keyboardChan);
int keyboardEnabled = GCKB_Init(keyboardChan);
if (keyboardEnabled)
printf("keyboard initialized on chan %d\n", keyboardChan);
printf("GC Keyboard initialized on chan %d\n", keyboardChan);
printf("start of main loop ...\n");
printf("Start of main loop.\nPress Start on the controller plugged into slot 1 to exit ...\n");
while(1) {
if (keyboardEnabled) {
u32 buf[2];
if (SI_GetResponse(keyboardChan, buf)) {
u8 key1 = buf[1] >> 24;
u8 key2 = (buf[1] >> 16) & 0xff;
u8 key3 = (buf[1] >> 8) & 0xff;
if (key1 | key2 | key3)
printf("keyboard data - raw: 0x%08x 0x%08x - keys: 0x%02x, 0x%02x, 0x%02x\n",
buf[0], buf[1], key1, key2, key3);
u8 keys[3];
if (GCKB_ReadKeys(keyboardChan, keys)) {
if (keys[0] | keys[1] | keys[2])
printf("keys pressed: 0x%02x, 0x%02x, 0x%02x\n", keys[0], keys[1], keys[2]);
}
}
@ -124,10 +59,6 @@ int main(int argc, char **argv) {
printf("exiting ...\n");
exit(0);
}
if (pressed & PAD_BUTTON_A) {
_break();
printf("A pressed\n");
}
VIDEO_WaitVSync();
}