diff --git a/include/arm11/hardware/hid.h b/include/arm11/hardware/hid.h index 8cffbd8..ff10158 100644 --- a/include/arm11/hardware/hid.h +++ b/include/arm11/hardware/hid.h @@ -25,37 +25,76 @@ #include "types.h" -#define REG_HID_PAD (*((vu16*)(IO_MEM_ARM9_ARM11 + 0x46000)) ^ 0xFFFFu) +#define REG_HID_PAD (*((vu16*)(IO_MEM_ARM9_ARM11 + 0x46000)) ^ 0xFFFFu) -#define HID_KEY_MASK_ALL ((KEY_SHELL << 1) - 1) -#define HID_VERBOSE_MODE_BUTTONS (KEY_SELECT | KEY_START) +#define HID_KEY_MASK_ALL ((1u<<12) - 1) enum { - KEY_A = (1), - KEY_B = (1<<1), - KEY_SELECT = (1<<2), - KEY_START = (1<<3), - KEY_DRIGHT = (1<<4), - KEY_DLEFT = (1<<5), - KEY_DUP = (1<<6), - KEY_DDOWN = (1<<7), - KEY_R = (1<<8), - KEY_L = (1<<9), - KEY_X = (1<<10), - KEY_Y = (1<<11), - KEY_HOME = (1<<21), - KEY_SHELL = (1<<22) + KEY_A = (1u<<0), // A + KEY_B = (1u<<1), // B + KEY_SELECT = (1u<<2), // Select + KEY_START = (1u<<3), // Start + KEY_DRIGHT = (1u<<4), // D-Pad Right + KEY_DLEFT = (1u<<5), // D-Pad Left + KEY_DUP = (1u<<6), // D-Pad Up + KEY_DDOWN = (1u<<7), // D-Pad Down + KEY_R = (1u<<8), // R + KEY_L = (1u<<9), // L + KEY_X = (1u<<10), // X + KEY_Y = (1u<<11), // Y + KEY_ZL = (1u<<14), // ZL (New 3DS only) + KEY_ZR = (1u<<15), // ZR (New 3DS only) + KEY_TOUCH = (1u<<20), // Touch (Not actually provided by HID) + KEY_CSTICK_RIGHT = (1u<<24), // C-Stick Right (New 3DS only) + KEY_CSTICK_LEFT = (1u<<25), // C-Stick Left (New 3DS only) + KEY_CSTICK_UP = (1u<<26), // C-Stick Up (New 3DS only) + KEY_CSTICK_DOWN = (1u<<27), // C-Stick Down (New 3DS only) + KEY_CPAD_RIGHT = (1u<<28), // Circle Pad Right + KEY_CPAD_LEFT = (1u<<29), // Circle Pad Left + KEY_CPAD_UP = (1u<<30), // Circle Pad Up + KEY_CPAD_DOWN = (1u<<31), // Circle Pad Down + + // Generic catch-all directions + KEY_UP = KEY_DUP | KEY_CPAD_UP, // D-Pad Up or Circle Pad Up + KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN, // D-Pad Down or Circle Pad Down + KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT, // D-Pad Left or Circle Pad Left + KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT, // D-Pad Right or Circle Pad Right }; +// Extra keys use with hidGetExtraKeys() +enum +{ + KEY_POWER = (1u<<0), + KEY_POWER_HELD = (1u<<1), + KEY_HOME = (1u<<2), // Auto clear on release + KEY_WIFI = (1u<<3), + KEY_SHELL = (1u<<4), // Auto clear on open + KEY_CHARGER = (1u<<5), // Auto clears on unplugging + KEY_VOL_SLIDER = (1u<<6) +}; + +typedef struct +{ + u16 x; + u16 y; +} TouchPos; + +typedef struct +{ + s16 x; + s16 y; +} CpadPos; + void hidInit(void); -u32 hidGetPowerButton(bool resetState); -u32 hidGetWifiButton(bool resetState); bool hidIsHomeButtonHeldRaw(void); void hidScanInput(void); u32 hidKeysHeld(void); u32 hidKeysDown(void); u32 hidKeysUp(void); +//const TouchPos* hidGetTouchPosPtr(void); +//const CpadPos* hidGetCpadPosPtr(void); +u32 hidGetExtraKeys(u32 clearMask); diff --git a/source/arm11/debug.c b/source/arm11/debug.c index b4e014d..4b52211 100644 --- a/source/arm11/debug.c +++ b/source/arm11/debug.c @@ -45,11 +45,11 @@ PXI_sendPanicCmd(IPC_CMD9_PANIC); - // Wait for any button. + // Wait for A/B/X or Y do { hidScanInput(); - } while(!(hidKeysDown() & HID_KEY_MASK_ALL)); + } while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y))); MCU_triggerPowerOff(); while(1) __wfi(); @@ -68,11 +68,11 @@ PXI_sendPanicCmd(IPC_CMD9_PANIC); - // Wait for any button. + // Wait for A/B/X or Y do { hidScanInput(); - } while(!(hidKeysDown() & HID_KEY_MASK_ALL)); + } while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y))); MCU_triggerPowerOff(); while(1) __wfi(); @@ -137,11 +137,11 @@ PXI_sendPanicCmd(IPC_CMD9_EXCEPTION); - // Wait for any button. + // Wait for A/B/X or Y do { hidScanInput(); - } while(!(hidKeysDown() & HID_KEY_MASK_ALL)); + } while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y))); MCU_triggerPowerOff(); while(1) __wfi(); diff --git a/source/arm11/hardware/hid.c b/source/arm11/hardware/hid.c index f42f598..2246e6a 100644 --- a/source/arm11/hardware/hid.c +++ b/source/arm11/hardware/hid.c @@ -26,11 +26,17 @@ #include "arm11/hardware/mcu.h" #include "arm11/hardware/interrupt.h" #include "arm11/hardware/gpio.h" +#include "arm11/hardware/codec.h" -static u32 kHeld = 0, kDown = 0, kUp = 0; -static u32 homeShellState = 0, powerWifiState = 0; -static volatile bool mcuIrq = false; +#define CPAD_THRESHOLD (400) + + +static u32 kHeld, kDown, kUp; +static u32 extraKeys; +//TouchPos tPos; +//CpadPos cPos; +static volatile bool mcuIrq = true; @@ -38,14 +44,17 @@ void hidInit(void) { + extraKeys = kUp = kDown = kHeld = 0; + // When set after a reboot from TWL_FIRM while holding the HOME button this will // cause the MCU to spam IRQs infinitely after releasing the HOME button. // mcuBugs++ // Update: For some reason this is not reproduceable anymore. - MCU_setIrqBitmask(0xFFFF1800u); // Standard bitmask at cold boot - + MCU_setIrqBitmask(0xFFBFFC80u); IRQ_registerHandler(IRQ_MCU_HID, 14, 0, true, hidIrqHandler); GPIO_setBit(19, 9); // This enables the MCU IRQ. + + //CODEC_init(); } static void hidIrqHandler(UNUSED u32 intSource) @@ -61,35 +70,45 @@ const u32 state = MCU_readReceivedIrqs(); - u32 tmp = powerWifiState; - tmp |= state & 3; - tmp |= state>>2 & 4; - powerWifiState = tmp; - - tmp = homeShellState; - tmp |= (state & 4)<<19; - tmp |= (state & 0x20)<<17; - - if(tmp & KEY_HOME) tmp ^= (state & 8)<<18; - if(tmp & KEY_SHELL) tmp ^= (state & 0x40)<<16; - homeShellState = tmp; + u32 tmp = extraKeys; + tmp |= state & (KEY_POWER | KEY_POWER_HELD | KEY_HOME); // Power button pressed/held, HOME button pressed + if(state & 1u<<3) tmp &= ~KEY_HOME; // HOME released + tmp |= state>>1 & (KEY_WIFI | KEY_SHELL); // WiFi switch, shell closed + if(state & 1u<<6) tmp &= ~KEY_SHELL; // Shell opened + tmp |= state>>4 & KEY_CHARGER; // Charger plugged in + if(state & 1u<<8) tmp &= ~KEY_CHARGER; // Charger removed + tmp |= state>>16 & KEY_VOL_SLIDER; // Volume slider update + extraKeys = tmp; } -u32 hidGetPowerButton(bool resetState) +/*static u32 rawCodec2Hid(void) { - u32 tmp = powerWifiState; - // Mask out power button pressed and keep power button long pressed + WiFi button state. - if(resetState) powerWifiState = tmp & 6; - return tmp & 3; -} + alignas(4) u8 buf[13 * 4]; -u32 hidGetWifiButton(bool resetState) -{ - u32 tmp = powerWifiState; - // Mask out WiFi button and keep power button states. - if(resetState) powerWifiState = tmp & 3; - return tmp>>2; -} + CODEC_getRawData((u32*)buf); + + // Touchscreen + u32 emuButtons = !(buf[0] & 1u<<4)<<20; // KEY_TOUCH + tPos.x = (buf[0]<<8 | buf[1]) * 320u / 4096u; // TODO: Calibration + tPos.y = (buf[10]<<8 | buf[11]) * 240u / 4096u; + + // Circle-Pad + cPos.x = -(((buf[36]<<8 | buf[37]) & 0xFFFu) - 2048u); // X axis is inverted + cPos.y = ((buf[20]<<8 | buf[21]) & 0xFFFu) - 2048u; + + if((cPos.x > 0 ? cPos.x : -cPos.x) > CPAD_THRESHOLD) + { + if(cPos.x >= 0) emuButtons |= KEY_CPAD_RIGHT; + else emuButtons |= KEY_CPAD_LEFT; + } + if((cPos.y > 0 ? cPos.y : -cPos.y) > CPAD_THRESHOLD) + { + if(cPos.y >= 0) emuButtons |= KEY_CPAD_UP; + else emuButtons |= KEY_CPAD_DOWN; + } + + return emuButtons; +}*/ bool hidIsHomeButtonHeldRaw(void) { @@ -101,7 +120,7 @@ updateMcuIrqState(); u32 kOld = kHeld; - kHeld = homeShellState | REG_HID_PAD;; + kHeld = /*rawCodec2Hid() |*/ REG_HID_PAD; kDown = (~kOld) & kHeld; kUp = kOld & (~kHeld); } @@ -120,3 +139,21 @@ { return kUp; } + +/*const TouchPos* hidGetTouchPosPtr(void) +{ + return &tPos; +} + +const CpadPos* hidGetCpadPosPtr(void) +{ + return &cPos; +}*/ + +u32 hidGetExtraKeys(u32 clearMask) +{ + u32 tmp = extraKeys; + extraKeys &= ~clearMask; + + return tmp; +} diff --git a/source/arm11/main.c b/source/arm11/main.c index 8235a3d..e88fade 100644 --- a/source/arm11/main.c +++ b/source/arm11/main.c @@ -203,7 +203,7 @@ { GFX_waitForEvent(GFX_EVENT_PDC0, true); hidScanInput(); - if (hidKeysDown() & KEY_HOME) + if (hidGetExtraKeys(0) & KEY_HOME) { show_menu = true; startFirmLaunch = false; @@ -254,7 +254,7 @@ free(err_string); err_string = NULL; - if(hidGetPowerButton(false)) break; + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) break; } // bootrom dumper handling @@ -282,7 +282,7 @@ updateScreens(); // check POWER button - if(hidGetPowerButton(false)) break; + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) break; // check menu return value if (menu_ret == MENU_RET_FIRMLOADED) @@ -364,7 +364,7 @@ // Last chance to abort and enter boot menu hidScanInput(); - if (hidKeysDown() & KEY_HOME) + if (hidGetExtraKeys(0) & KEY_HOME) { show_menu = true; startFirmLaunch = false; @@ -393,7 +393,7 @@ if(err_string) free(err_string); // power off - if(hidGetPowerButton(true) || (menu_ret == MENU_RET_POWEROFF)) + if((hidGetExtraKeys(KEY_POWER) & (KEY_POWER | KEY_POWER_HELD)) || (menu_ret == MENU_RET_POWEROFF)) { storeBootslot(0); power_off(); diff --git a/source/arm11/menu/menu.c b/source/arm11/menu/menu.c index 2510de7..e703e93 100644 --- a/source/arm11/menu/menu.c +++ b/source/arm11/menu/menu.c @@ -308,7 +308,7 @@ while (menu_ret < MENU_RET_CONTINUE) { // handle power button - if(hidGetPowerButton(false)) + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) break; // deinits & poweroff outside of this function // handle battery state @@ -326,9 +326,10 @@ hidScanInput(); const u32 kDown = hidKeysDown(); + const u32 extraKeys = hidGetExtraKeys(0); // const u32 kHeld = hidKeysHeld(); - if (kDown & KEY_SHELL) + if (extraKeys & KEY_SHELL) { sleepmode(); } @@ -362,7 +363,7 @@ curr_menu = prev_menu[menu_lvl]; index = prev_index[menu_lvl]; } - else if ((kDown & KEY_HOME) && (menu_lvl > 0)) + else if ((extraKeys & KEY_HOME) && (menu_lvl > 0)) { // return to HOME menu menu_lvl = 0; diff --git a/source/arm11/menu/menu_fsel.c b/source/arm11/menu/menu_fsel.c index 017aa30..0763b6b 100644 --- a/source/arm11/menu/menu_fsel.c +++ b/source/arm11/menu/menu_fsel.c @@ -415,18 +415,19 @@ dbutton_cooldown = 0; // handle power button - if(hidGetPowerButton(false)) + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) result = false; hidScanInput(); const u32 kDown = hidKeysDown(); const u32 kHeld = hidKeysHeld(); + const u32 extraKeys = hidGetExtraKeys(0); - if (kDown & KEY_SHELL) + if (extraKeys & KEY_SHELL) { sleepmode(); } - else if (kDown & KEY_HOME) + else if (extraKeys & KEY_HOME) { result = false; } diff --git a/source/arm11/menu/menu_func.c b/source/arm11/menu/menu_func.c index b9ea0e4..fa42453 100644 --- a/source/arm11/menu/menu_func.c +++ b/source/arm11/menu/menu_func.c @@ -334,6 +334,7 @@ { u32 kDown = 0; u32 kHeld = 0; + u32 extraKeys = 0; // make sure duration stays within boundaries if (duration < SPLASH_MIN_MSEC) duration = SPLASH_MIN_MSEC; @@ -357,14 +358,15 @@ { GFX_waitForEvent(GFX_EVENT_PDC0, true); - if(hidGetPowerButton(false)) // handle power button + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) // handle power button return MENU_FAIL; hidScanInput(); kDown = hidKeysDown(); kHeld = hidKeysHeld(); - if (kDown & (KEY_SHELL)) sleepmode(); - else if (kDown & (KEY_B|KEY_HOME)) return MENU_OK; + extraKeys = hidGetExtraKeys(0); + if (extraKeys & KEY_SHELL) sleepmode(); + else if (kDown & KEY_B || extraKeys & KEY_HOME) return MENU_OK; else if (kDown & KEY_A) break; } while (!(kHeld & (KEY_DRIGHT|KEY_DLEFT|KEY_DUP|KEY_DDOWN))); @@ -485,16 +487,16 @@ do { GFX_waitForEvent(GFX_EVENT_PDC0, true); - if(hidGetPowerButton(false)) return MENU_FAIL; + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) return MENU_FAIL; hidScanInput(); kHeldNew = hidKeysHeld(); - if(hidKeysDown() & KEY_SHELL) sleepmode(); + if(hidGetExtraKeys(0) & KEY_SHELL) sleepmode(); } while ((kHeld == kHeldNew) && (++vBlanks < 100)); // check HOME key - if (kHeldNew & KEY_HOME) return MENU_FAIL; + if (hidGetExtraKeys(0) & KEY_HOME) return MENU_FAIL; } while (!((kHeld|kHeldNew) & 0xfff)); // repeat checks until actual buttons are held @@ -1182,21 +1184,23 @@ // handle user input u32 kDown = 0; + u32 extraKeys = 0; do { GFX_waitForEvent(GFX_EVENT_PDC0, true); - if(hidGetPowerButton(false)) // handle power button + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) // handle power button break; hidScanInput(); kDown = hidKeysDown(); + extraKeys = hidGetExtraKeys(0); if (kDown) k = (kDown & konami_code[k]) ? k + 1 : 0; if (!k && (kDown & KEY_B)) break; - if (kDown & KEY_SHELL) sleepmode(); + if (extraKeys & KEY_SHELL) sleepmode(); } - while (!(kDown & KEY_HOME) && (k < konami)); + while (!(extraKeys & KEY_HOME) && (k < konami)); // Konami code entered? @@ -1275,7 +1279,7 @@ hidScanInput(); } - while (!(hidKeysDown() & (KEY_B|KEY_HOME))); + while (!(hidKeysDown() & KEY_B || hidGetExtraKeys(0) & KEY_HOME)); return 0; } @@ -1316,7 +1320,7 @@ hidScanInput(); } - while (!(hidKeysDown() & (KEY_B|KEY_HOME))); + while (!(hidKeysDown() & KEY_B || hidGetExtraKeys(0) & KEY_HOME)); return 0; } diff --git a/source/arm11/menu/menu_util.c b/source/arm11/menu/menu_util.c index 44d6708..08af864 100644 --- a/source/arm11/menu/menu_util.c +++ b/source/arm11/menu/menu_util.c @@ -298,7 +298,7 @@ { __wfi(); hidScanInput(); - } while(!(hidKeysUp() & KEY_SHELL)); + } while(hidGetExtraKeys(0) & KEY_SHELL); MCU_setPowerLedState(PWLED_NORMAL); GFX_returnFromLowPowerState(); } @@ -315,7 +315,7 @@ { char buf[512]; char* instr = buf; - u32 kDown = 0, kHeld = 0; + u32 kHeld = 0, kDown = 0, extraKeys = 0; va_list args; va_start(args, fmt); @@ -330,17 +330,18 @@ { GFX_waitForEvent(GFX_EVENT_PDC0, true); - if(hidGetPowerButton(false)) // handle power button + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) // handle power button break; hidScanInput(); - kDown = hidKeysDown(); kHeld = hidKeysHeld(); + kDown = hidKeysDown(); + extraKeys = hidGetExtraKeys(0); if ((kHeld & KEY_A) && (kHeld & KEY_DLEFT)) return true; - if (kDown & (KEY_SHELL)) sleepmode(); + if (extraKeys & KEY_SHELL) sleepmode(); } - while (!(kDown & (KEY_B|KEY_HOME))); + while (!(kDown & KEY_B || extraKeys & KEY_HOME)); return false; } @@ -348,36 +349,38 @@ void outputEndWait(void) { u32 kDown = 0; + u32 extraKeys = 0; do { GFX_waitForEvent(GFX_EVENT_PDC0, true); - if(hidGetPowerButton(false)) // handle power button + if(hidGetExtraKeys(0) & (KEY_POWER | KEY_POWER_HELD)) // handle power button break; hidScanInput(); kDown = hidKeysDown(); - if (kDown & (KEY_SHELL)) sleepmode(); + extraKeys = hidGetExtraKeys(0); + if (extraKeys & KEY_SHELL) sleepmode(); } - while (!(kDown & (KEY_B|KEY_HOME))); + while (!(kDown & KEY_B || extraKeys & KEY_HOME)); } bool userCancelHandler(bool cancelAllowed) { hidScanInput(); u32 kDown = hidKeysDown(); - u32 powerHeld = hidGetPowerButton(false); + u32 extraKeys = hidGetExtraKeys(0); // detect force poweroff - if (powerHeld & (1<<1)) + if (extraKeys & KEY_POWER_HELD) return true; - if (kDown & KEY_SHELL) + if (extraKeys & KEY_SHELL) { sleepmode(); } - else if (kDown & (KEY_HOME|KEY_B) || powerHeld) + else if (kDown & KEY_B || extraKeys & (KEY_HOME | KEY_POWER_HELD | KEY_POWER)) { if (cancelAllowed) { @@ -390,11 +393,11 @@ hidScanInput(); kDown = hidKeysDown(); - powerHeld = hidGetPowerButton(false); + extraKeys = hidGetExtraKeys(0); - if (kDown & KEY_SHELL) sleepmode(); + if (extraKeys & KEY_SHELL) sleepmode(); if (kDown & KEY_A) return true; - if (powerHeld & (1<<1)) return true; + if (extraKeys & KEY_POWER_HELD) return true; } while (!(kDown & KEY_B)); } @@ -404,7 +407,7 @@ ee_printf("Cancel is not allowed here.\n\n"); } - hidGetPowerButton(true); // poweroff stopped + hidGetExtraKeys(KEY_POWER); // poweroff stopped } return false;