From 352a54218288318fdf1dadcd90115efaf7b31ad1 Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Mon, 29 Apr 2024 00:03:00 +0900 Subject: [PATCH 1/2] add device 17h driver --- include/arm11/drivers/device17.h | 50 ++++++++++++++++++++++++++ include/arm11/drivers/i2c.h | 2 ++ source/arm11/drivers/device17.c | 14 ++++++++ source/arm11/drivers/hid.c | 45 ++++++++++++++++++++++-- source/arm11/drivers/i2c.c | 60 ++++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 include/arm11/drivers/device17.h create mode 100644 source/arm11/drivers/device17.c diff --git a/include/arm11/drivers/device17.h b/include/arm11/drivers/device17.h new file mode 100644 index 0000000..d99245c --- /dev/null +++ b/include/arm11/drivers/device17.h @@ -0,0 +1,50 @@ +#pragma once + +/* + * This file is part of open_agb_firm + * Copyright (C) 2024 EvansJahja + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "types.h" + +enum Device17_Button { + ZR = (1<<1), + ZL = (1<<2), +}; + +typedef struct +{ + u8 _status; + enum Device17_Button button; + s8 cstick_y_coarse; + s8 cstick_x_coarse; + u8 _ignored; + s8 cstick_y_fine; + s8 cstick_x_fine; + +} Device17; + +void Device17_Poll(void); + +Device17* Device17_GetDevice(void); + +#ifdef __cplusplus +} // extern "C" +#endif \ No newline at end of file diff --git a/include/arm11/drivers/i2c.h b/include/arm11/drivers/i2c.h index f5ffd43..0d881c0 100644 --- a/include/arm11/drivers/i2c.h +++ b/include/arm11/drivers/i2c.h @@ -123,6 +123,8 @@ void I2C_init(void); */ bool I2C_readRegArray(const I2cDevice devId, const u8 regAddr, void *out, u32 size); +bool I2C_readArray(const I2cDevice devId, void *out, u32 size); + /** * @brief Writes an array of bytes to an array of registers via I2C. * diff --git a/source/arm11/drivers/device17.c b/source/arm11/drivers/device17.c new file mode 100644 index 0000000..a9c2ce4 --- /dev/null +++ b/source/arm11/drivers/device17.c @@ -0,0 +1,14 @@ +#include "arm11/drivers/device17.h" +#include "arm11/drivers/i2c.h" + +static Device17 device; + +void Device17_Poll(void) +{ + I2C_readArray(I2C_DEV_N3DS_HID, &device, sizeof device); +} + +Device17* Device17_GetDevice(void) +{ + return &device; +} \ No newline at end of file diff --git a/source/arm11/drivers/hid.c b/source/arm11/drivers/hid.c index cb67f3c..964b089 100644 --- a/source/arm11/drivers/hid.c +++ b/source/arm11/drivers/hid.c @@ -27,7 +27,9 @@ #include "arm11/drivers/interrupt.h" #include "arm11/drivers/gpio.h" #include "arm11/drivers/codec.h" +#include "arm11/drivers/device17.h" +#include "arm11/fmt.h" #define MCU_HID_IRQ_MASK (MCU_IRQ_VOL_SLIDER_CHANGE | MCU_IRQ_BATT_CHARGE_START | \ MCU_IRQ_BATT_CHARGE_STOP | MCU_IRQ_SHELL_OPEN | \ @@ -36,15 +38,31 @@ MCU_IRQ_POWER_HELD | MCU_IRQ_POWER_PRESS) #define CPAD_THRESHOLD (400) - +#define CSTICK_THRESHOLD (3) static u32 g_kHeld = 0, g_kDown = 0, g_kUp = 0; static u32 g_extraKeys = 0; +static bool g_useDevice17 = false; TouchPos g_tPos = {0}; CpadPos g_cPos = {0}; +bool hasDevice17(void) +{ + McuSysModel model = MCU_getSystemModel(); + switch(model) + { + case SYS_MODEL_N2DS_XL: + case SYS_MODEL_N3DS: + case SYS_MODEL_N3DS_XL: + return true; + + default: + return false; + } +} + void hidInit(void) { static bool inited = false; @@ -58,7 +76,7 @@ void hidInit(void) state = MCU_getEarlyButtonsHeld(); tmp |= ~state<<1 & KEY_HOME; // Current HOME button state g_extraKeys = tmp; - + g_useDevice17 = hasDevice17(); CODEC_init(); } @@ -111,12 +129,35 @@ static u32 rawCodec2Hid(void) return fakeKeys; } +u32 device17ToHid(void) +{ + u32 key = 0; + Device17* dev = Device17_GetDevice(); + + key |= (dev->button & ZL) ? KEY_ZL : 0; + key |= (dev->button & ZR) ? KEY_ZR : 0; + + if (dev->cstick_y_coarse >= CSTICK_THRESHOLD) key |= KEY_CSTICK_UP; + if (dev->cstick_y_coarse <= -CSTICK_THRESHOLD) key |= KEY_CSTICK_DOWN; + if (dev->cstick_x_coarse >= CSTICK_THRESHOLD) key |= KEY_CSTICK_LEFT; + if (dev->cstick_x_coarse <= -CSTICK_THRESHOLD) key |= KEY_CSTICK_RIGHT; + + return key; +} + void hidScanInput(void) { updateMcuHidState(); const u32 kOld = g_kHeld; g_kHeld = rawCodec2Hid() | REG_HID_PAD; + + + if (g_useDevice17) { + Device17_Poll(); + g_kHeld |= device17ToHid(); + } + g_kDown = (~kOld) & g_kHeld; g_kUp = kOld & (~g_kHeld); } diff --git a/source/arm11/drivers/i2c.c b/source/arm11/drivers/i2c.c index f5b662e..618a48d 100644 --- a/source/arm11/drivers/i2c.c +++ b/source/arm11/drivers/i2c.c @@ -144,6 +144,41 @@ static bool startTransfer(const u8 devAddr, const u8 regAddr, const bool read, c return tries > 0; } +static bool startTransfer_no_reg(const u8 devAddr, const bool read, const I2cState *const state) +{ + u32 tries = 8; + I2cBus *const i2cBus = state->i2cBus; + const KHandle event = state->event; + do + { + // Edge case on previous transfer error (NACK). + // This is a special case where we can't predict when or if + // the IRQ has fired. If it fires after checking but + // before a wfi this would hang. + if(i2cBus->cnt & I2C_EN) waitForEvent(event); + clearEvent(event); + + // Select device and start. + sendByte(i2cBus, devAddr, I2C_START, event); + if(!checkAck(i2cBus)) continue; + + // Select register. + // sendByte(i2cBus, regAddr, 0, event); + // if(!checkAck(i2cBus)) continue; + + // Select device in read mode for read transfer. + if(read) + { + sendByte(i2cBus, devAddr | 1u, I2C_START, event); + if(!checkAck(i2cBus)) continue; + } + + break; + } while(--tries > 0); + + return tries > 0; +} + bool I2C_readRegArray(const I2cDevice devId, const u8 regAddr, void *out, u32 size) { const u8 devAddr = g_i2cDevTable[devId].devAddr; @@ -169,6 +204,31 @@ bool I2C_readRegArray(const I2cDevice devId, const u8 regAddr, void *out, u32 si return res; } +bool I2C_readArray(const I2cDevice devId, void *out, u32 size) +{ + const u8 devAddr = g_i2cDevTable[devId].devAddr; + const I2cState *const state = &g_i2cState[g_i2cDevTable[devId].busId]; + I2cBus *const i2cBus = state->i2cBus; + const KHandle event = state->event; + const KHandle mutex = state->mutex; + u8 *ptr8 = out; + + + bool res = true; + lockMutex(mutex); + if(startTransfer_no_reg(devAddr, true, state)) + { + while(--size) *ptr8++ = recvByte(i2cBus, I2C_ACK, event); + + // Last byte transfer. + *ptr8 = recvByte(i2cBus, I2C_STOP, event); + } + else res = false; + unlockMutex(mutex); + + return res; +} + bool I2C_writeRegArray(const I2cDevice devId, const u8 regAddr, const void *in, u32 size) { const u8 devAddr = g_i2cDevTable[devId].devAddr; From e80c04bd6d350b1f14286401e194c3221d493268 Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Mon, 29 Apr 2024 23:44:42 +0900 Subject: [PATCH 2/2] rename device17 to n3ds_exthid --- .../drivers/{device17.h => n3ds_exthid.h} | 10 +++++----- source/arm11/drivers/device17.c | 14 -------------- source/arm11/drivers/hid.c | 18 +++++++++--------- source/arm11/drivers/n3ds_exthid.c | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 28 deletions(-) rename include/arm11/drivers/{device17.h => n3ds_exthid.h} (87%) delete mode 100644 source/arm11/drivers/device17.c create mode 100644 source/arm11/drivers/n3ds_exthid.c diff --git a/include/arm11/drivers/device17.h b/include/arm11/drivers/n3ds_exthid.h similarity index 87% rename from include/arm11/drivers/device17.h rename to include/arm11/drivers/n3ds_exthid.h index d99245c..507cbe4 100644 --- a/include/arm11/drivers/device17.h +++ b/include/arm11/drivers/n3ds_exthid.h @@ -24,7 +24,7 @@ extern "C" #include "types.h" -enum Device17_Button { +enum N3DS_EXTHID_Button { ZR = (1<<1), ZL = (1<<2), }; @@ -32,18 +32,18 @@ enum Device17_Button { typedef struct { u8 _status; - enum Device17_Button button; + enum N3DS_EXTHID_Button button; s8 cstick_y_coarse; s8 cstick_x_coarse; u8 _ignored; s8 cstick_y_fine; s8 cstick_x_fine; -} Device17; +} N3DS_EXTHID; -void Device17_Poll(void); +void N3DS_EXTHID_Poll(void); -Device17* Device17_GetDevice(void); +N3DS_EXTHID* N3DS_EXTHID_GetDevice(void); #ifdef __cplusplus } // extern "C" diff --git a/source/arm11/drivers/device17.c b/source/arm11/drivers/device17.c deleted file mode 100644 index a9c2ce4..0000000 --- a/source/arm11/drivers/device17.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "arm11/drivers/device17.h" -#include "arm11/drivers/i2c.h" - -static Device17 device; - -void Device17_Poll(void) -{ - I2C_readArray(I2C_DEV_N3DS_HID, &device, sizeof device); -} - -Device17* Device17_GetDevice(void) -{ - return &device; -} \ No newline at end of file diff --git a/source/arm11/drivers/hid.c b/source/arm11/drivers/hid.c index 964b089..ee2f508 100644 --- a/source/arm11/drivers/hid.c +++ b/source/arm11/drivers/hid.c @@ -27,7 +27,7 @@ #include "arm11/drivers/interrupt.h" #include "arm11/drivers/gpio.h" #include "arm11/drivers/codec.h" -#include "arm11/drivers/device17.h" +#include "arm11/drivers/n3ds_exthid.h" #include "arm11/fmt.h" @@ -42,13 +42,13 @@ static u32 g_kHeld = 0, g_kDown = 0, g_kUp = 0; static u32 g_extraKeys = 0; -static bool g_useDevice17 = false; +static bool g_useN3DSEXTHID = false; TouchPos g_tPos = {0}; CpadPos g_cPos = {0}; -bool hasDevice17(void) +bool hasN3DSEXTHID(void) { McuSysModel model = MCU_getSystemModel(); switch(model) @@ -76,7 +76,7 @@ void hidInit(void) state = MCU_getEarlyButtonsHeld(); tmp |= ~state<<1 & KEY_HOME; // Current HOME button state g_extraKeys = tmp; - g_useDevice17 = hasDevice17(); + g_useN3DSEXTHID = hasN3DSEXTHID(); CODEC_init(); } @@ -129,10 +129,10 @@ static u32 rawCodec2Hid(void) return fakeKeys; } -u32 device17ToHid(void) +u32 N3DS_EXTHIDToHid(void) { u32 key = 0; - Device17* dev = Device17_GetDevice(); + N3DS_EXTHID* dev = N3DS_EXTHID_GetDevice(); key |= (dev->button & ZL) ? KEY_ZL : 0; key |= (dev->button & ZR) ? KEY_ZR : 0; @@ -153,9 +153,9 @@ void hidScanInput(void) g_kHeld = rawCodec2Hid() | REG_HID_PAD; - if (g_useDevice17) { - Device17_Poll(); - g_kHeld |= device17ToHid(); + if (g_useN3DSEXTHID) { + N3DS_EXTHID_Poll(); + g_kHeld |= N3DS_EXTHIDToHid(); } g_kDown = (~kOld) & g_kHeld; diff --git a/source/arm11/drivers/n3ds_exthid.c b/source/arm11/drivers/n3ds_exthid.c new file mode 100644 index 0000000..ea97bee --- /dev/null +++ b/source/arm11/drivers/n3ds_exthid.c @@ -0,0 +1,14 @@ +#include "arm11/drivers/n3ds_exthid.h" +#include "arm11/drivers/i2c.h" + +static N3DS_EXTHID device; + +void N3DS_EXTHID_Poll(void) +{ + I2C_readArray(I2C_DEV_N3DS_HID, &device, sizeof device); +} + +N3DS_EXTHID* N3DS_EXTHID_GetDevice(void) +{ + return &device; +} \ No newline at end of file