+
Skip to content

add N3DS EXTHID driver #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/arm11/drivers/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
50 changes: 50 additions & 0 deletions include/arm11/drivers/n3ds_exthid.h
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef __cplusplus
extern "C"
{
#endif

#include "types.h"

enum N3DS_EXTHID_Button {
ZR = (1<<1),
ZL = (1<<2),
};

typedef struct
{
u8 _status;
enum N3DS_EXTHID_Button button;
s8 cstick_y_coarse;
s8 cstick_x_coarse;
u8 _ignored;
s8 cstick_y_fine;
s8 cstick_x_fine;

} N3DS_EXTHID;

void N3DS_EXTHID_Poll(void);

N3DS_EXTHID* N3DS_EXTHID_GetDevice(void);

#ifdef __cplusplus
} // extern "C"
#endif
45 changes: 43 additions & 2 deletions source/arm11/drivers/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
#include "arm11/drivers/interrupt.h"
#include "arm11/drivers/gpio.h"
#include "arm11/drivers/codec.h"
#include "arm11/drivers/n3ds_exthid.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 | \
Expand All @@ -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_useN3DSEXTHID = false;
TouchPos g_tPos = {0};
CpadPos g_cPos = {0};



bool hasN3DSEXTHID(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;
Expand All @@ -58,7 +76,7 @@ void hidInit(void)
state = MCU_getEarlyButtonsHeld();
tmp |= ~state<<1 & KEY_HOME; // Current HOME button state
g_extraKeys = tmp;

g_useN3DSEXTHID = hasN3DSEXTHID();
CODEC_init();
}

Expand Down Expand Up @@ -111,12 +129,35 @@ static u32 rawCodec2Hid(void)
return fakeKeys;
}

u32 N3DS_EXTHIDToHid(void)
{
u32 key = 0;
N3DS_EXTHID* dev = N3DS_EXTHID_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_useN3DSEXTHID) {
N3DS_EXTHID_Poll();
g_kHeld |= N3DS_EXTHIDToHid();
}

g_kDown = (~kOld) & g_kHeld;
g_kUp = kOld & (~g_kHeld);
}
Expand Down
60 changes: 60 additions & 0 deletions source/arm11/drivers/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions source/arm11/drivers/n3ds_exthid.c
Original file line number Diff line number Diff line change
@@ -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;
}
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载