mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 21:52:48 +00:00
- added new SPI and CODEC drivers ported from linux, thanks to xerpi
- circle pad simulates dpad keys (up, right, down, left) - raw touchscreen data is provided but currently unused - added a simple shared memory region thing - fixed the 10ms delay to be _after_ the backlights are turned on, thanks to profi again as always, other stuff I probably forgot about
This commit is contained in:
parent
bcff09a389
commit
bf45ee3900
188
arm11/source/hw/codec.c
Executable file
188
arm11/source/hw/codec.c
Executable file
@ -0,0 +1,188 @@
|
|||||||
|
// Based on xerpi's CODEC driver for Linux
|
||||||
|
// Original comment follows:
|
||||||
|
/*
|
||||||
|
* nintendo3ds_codec.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Sergi Granell (xerpi)
|
||||||
|
* Copyright (C) 2017 Paul LaMendola (paulguy)
|
||||||
|
* based on ad7879-spi.c
|
||||||
|
*
|
||||||
|
* Licensed under the GPL-2 or later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include <hid_map.h>
|
||||||
|
|
||||||
|
#include "hw/codec.h"
|
||||||
|
#include "hw/spi.h"
|
||||||
|
|
||||||
|
#define CODEC_SPI_DEV (3)
|
||||||
|
|
||||||
|
#define MAX_12BIT (BIT(12) - 1)
|
||||||
|
#define CPAD_THRESH (150)
|
||||||
|
#define CPAD_FACTOR (150)
|
||||||
|
|
||||||
|
/* SPI stuff */
|
||||||
|
static void CODEC_DualTX(u8 *tx0, u8 len0, u8 *tx1, u8 len1)
|
||||||
|
{
|
||||||
|
SPI_XferInfo xfers[2];
|
||||||
|
|
||||||
|
xfers[0].buf = (u32*)tx0;
|
||||||
|
xfers[0].len = len0;
|
||||||
|
xfers[0].read = false;
|
||||||
|
|
||||||
|
xfers[1].buf = (u32*)tx1;
|
||||||
|
xfers[1].len = len1;
|
||||||
|
xfers[1].read = false;
|
||||||
|
|
||||||
|
SPI_DoXfer(CODEC_SPI_DEV, xfers, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CODEC_WriteRead(u8 *tx_buf, u8 tx_len,
|
||||||
|
u8 *rx_buf, u8 rx_len)
|
||||||
|
{
|
||||||
|
SPI_XferInfo xfers[2];
|
||||||
|
|
||||||
|
xfers[0].buf = (u32*)tx_buf;
|
||||||
|
xfers[0].len = tx_len;
|
||||||
|
xfers[0].read = false;
|
||||||
|
|
||||||
|
xfers[1].buf = (u32*)rx_buf;
|
||||||
|
xfers[1].len = rx_len;
|
||||||
|
xfers[1].read = true;
|
||||||
|
|
||||||
|
SPI_DoXfer(CODEC_SPI_DEV, xfers, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CODEC_RegSelect(u8 reg)
|
||||||
|
{
|
||||||
|
u8 buffer1[4];
|
||||||
|
u8 buffer2[0x40];
|
||||||
|
|
||||||
|
buffer1[0] = 0;
|
||||||
|
buffer2[0] = reg;
|
||||||
|
|
||||||
|
CODEC_DualTX(buffer1, 1, buffer2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 CODEC_RegRead(u8 offset)
|
||||||
|
{
|
||||||
|
u8 buffer_wr[8];
|
||||||
|
u8 buffer_rd[0x40];
|
||||||
|
|
||||||
|
buffer_wr[0] = 1 | (offset << 1);
|
||||||
|
|
||||||
|
CODEC_WriteRead(buffer_wr, 1, buffer_rd, 1);
|
||||||
|
|
||||||
|
return buffer_rd[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CODEC_RegWrite(u8 reg, u8 val)
|
||||||
|
{
|
||||||
|
u8 buffer1[8];
|
||||||
|
u8 buffer2[0x40];
|
||||||
|
|
||||||
|
buffer1[0] = (reg << 1); // Write
|
||||||
|
buffer2[0] = val;
|
||||||
|
|
||||||
|
CODEC_DualTX(buffer1, 1, buffer2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CODEC_RegReadBuf(u8 offset, void *buffer, u8 size)
|
||||||
|
{
|
||||||
|
u8 buffer_wr[0x10];
|
||||||
|
|
||||||
|
buffer_wr[0] = 1 | (offset << 1);
|
||||||
|
|
||||||
|
CODEC_WriteRead(buffer_wr, 1, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CODEC_RegMask(u8 offset, u8 mask0, u8 mask1)
|
||||||
|
{
|
||||||
|
u8 buffer1[4];
|
||||||
|
u8 buffer2[0x40];
|
||||||
|
|
||||||
|
buffer1[0] = 1 | (offset << 1);
|
||||||
|
|
||||||
|
CODEC_WriteRead(buffer1, 1, buffer2, 1);
|
||||||
|
|
||||||
|
buffer1[0] = offset << 1;
|
||||||
|
buffer2[0] = (buffer2[0] & ~mask1) | (mask0 & mask1);
|
||||||
|
|
||||||
|
CODEC_DualTX(buffer1, 1, buffer2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CODEC_Init(void)
|
||||||
|
{
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x24, 0x98);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x26, 0x00);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x25, 0x43);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x24, 0x18);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x17, 0x43);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x19, 0x69);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x1B, 0x80);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x27, 0x11);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x26, 0xEC);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x24, 0x18);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegWrite(0x25, 0x53);
|
||||||
|
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegMask(0x26, 0x80, 0x80);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegMask(0x24, 0x00, 0x80);
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegMask(0x25, 0x10, 0x3C);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CODEC_GetRawData(u8 *buffer)
|
||||||
|
{
|
||||||
|
CODEC_RegSelect(0x67);
|
||||||
|
CODEC_RegRead(0x26);
|
||||||
|
CODEC_RegSelect(0xFB);
|
||||||
|
CODEC_RegReadBuf(1, buffer, 0x34);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CODEC_Get(CODEC_Input *input)
|
||||||
|
{
|
||||||
|
u8 raw_data[0x34] = {0};
|
||||||
|
s16 cpad_x, cpad_y;
|
||||||
|
bool ts_pressed;
|
||||||
|
|
||||||
|
CODEC_GetRawData(raw_data);
|
||||||
|
|
||||||
|
cpad_x = ((raw_data[0x24] << 8 | raw_data[0x25]) & 0xFFF) - 2048;
|
||||||
|
cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048;
|
||||||
|
|
||||||
|
// X axis is inverted
|
||||||
|
if (abs(cpad_x) > CPAD_THRESH)
|
||||||
|
input->cpad_x = -cpad_x / CPAD_FACTOR;
|
||||||
|
else
|
||||||
|
input->cpad_x = 0;
|
||||||
|
|
||||||
|
if (abs(cpad_y) > CPAD_THRESH)
|
||||||
|
input->cpad_y = cpad_y / CPAD_FACTOR;
|
||||||
|
else
|
||||||
|
input->cpad_y = 0;
|
||||||
|
|
||||||
|
ts_pressed = !(raw_data[0] & BIT(4));
|
||||||
|
if (ts_pressed) {
|
||||||
|
input->ts_x = (raw_data[0] << 8) | raw_data[1];
|
||||||
|
input->ts_y = (raw_data[10] << 8) | raw_data[11];
|
||||||
|
} else {
|
||||||
|
input->ts_x = 0xFFFF;
|
||||||
|
input->ts_y = 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
14
arm11/source/hw/codec.h
Executable file
14
arm11/source/hw/codec.h
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#define CODEC_TOUCH_VALID(x) ((x) != 0xFFFFFFFF)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
s16 cpad_x, cpad_y;
|
||||||
|
s16 ts_x, ts_y;
|
||||||
|
} CODEC_Input;
|
||||||
|
|
||||||
|
void CODEC_Init(void);
|
||||||
|
|
||||||
|
void CODEC_Get(CODEC_Input *input);
|
55
arm11/source/hw/hid.c
Executable file
55
arm11/source/hw/hid.c
Executable file
@ -0,0 +1,55 @@
|
|||||||
|
#include <common.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <hid_map.h>
|
||||||
|
|
||||||
|
#include "hw/codec.h"
|
||||||
|
#include "hw/hid.h"
|
||||||
|
#include "hw/mcu.h"
|
||||||
|
|
||||||
|
#define REG_HID (~(*(vu16*)(0x10146000)) & BUTTON_ANY)
|
||||||
|
|
||||||
|
static u32 HID_ConvertCPAD(s16 cpad_x, s16 cpad_y)
|
||||||
|
{
|
||||||
|
u32 ret = 0;
|
||||||
|
|
||||||
|
switch(int_sign(cpad_x)) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ret |= BUTTON_RIGHT;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
ret |= BUTTON_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(int_sign(cpad_y)) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ret |= BUTTON_UP;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
ret |= BUTTON_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 HID_GetState(void)
|
||||||
|
{
|
||||||
|
CODEC_Input codec;
|
||||||
|
u64 ret = 0;
|
||||||
|
|
||||||
|
CODEC_Get(&codec);
|
||||||
|
|
||||||
|
ret = REG_HID | MCU_GetSpecialHID();
|
||||||
|
if (!(ret & BUTTON_ARROW))
|
||||||
|
ret |= HID_ConvertCPAD(codec.cpad_x, codec.cpad_y);
|
||||||
|
|
||||||
|
if (codec.ts_x <= 0xFFF)
|
||||||
|
ret |= BUTTON_TOUCH;
|
||||||
|
|
||||||
|
ret |= (((u64)codec.ts_x << 16) | (u64)codec.ts_y) << 32;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
6
arm11/source/hw/hid.h
Executable file
6
arm11/source/hw/hid.h
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <hid_map.h>
|
||||||
|
|
||||||
|
u64 HID_GetState(void);
|
129
arm11/source/hw/spi.c
Executable file
129
arm11/source/hw/spi.c
Executable file
@ -0,0 +1,129 @@
|
|||||||
|
// Somewhat based on xerpi's SPI driver for Linux
|
||||||
|
// Original comment follows:
|
||||||
|
/*
|
||||||
|
* nintendo3ds_spi.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Sergi Granell (xerpi)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include "hw/spi.h"
|
||||||
|
|
||||||
|
#define CFG_SPI_CNT ((vu32*)0x101401C0)
|
||||||
|
|
||||||
|
// TODO: CURRENTLY HARDCODED FOR DEVICE 3 (TOUCHSCREEN)
|
||||||
|
// IF ANY OTHER DEVICES ARE TO BE USED, ANOTHER BUS MUST
|
||||||
|
// BE ACCESSED, CHECK 3dbrew.org/wiki/SPI_{Registers, Services}
|
||||||
|
static const u32 SPI_Buses[] = { 0x10142800 };
|
||||||
|
#define REG_SPI(b, n) (*(vu32*)(SPI_Buses[b] + (n)))
|
||||||
|
|
||||||
|
#define REG_SPI_CNT REG_SPI(0, 0x00)
|
||||||
|
#define REG_SPI_DONE REG_SPI(0, 0x04)
|
||||||
|
#define REG_SPI_BLKLEN REG_SPI(0, 0x08)
|
||||||
|
#define REG_SPI_FIFO REG_SPI(0, 0x0C)
|
||||||
|
#define REG_SPI_STATUS REG_SPI(0, 0x10)
|
||||||
|
|
||||||
|
#define SPI_CNT_BUSY BIT(15)
|
||||||
|
#define SPI_CNT_START BIT(15)
|
||||||
|
|
||||||
|
#define SPI_CNT_READ (0)
|
||||||
|
#define SPI_CNT_WRITE BIT(13)
|
||||||
|
|
||||||
|
#define SPI_CNT_RATE(n) (n)
|
||||||
|
#define SPI_CNT_CS(n) ((n) << 6)
|
||||||
|
|
||||||
|
#define SPI_STAT_BUSY BIT(0)
|
||||||
|
|
||||||
|
#define SPI_FIFO_WIDTH (32)
|
||||||
|
|
||||||
|
static u8 SPI_GetDevSelect(u32 dev)
|
||||||
|
{
|
||||||
|
static const u8 SPI_DevSelect[] = { 0, 1, 2, 0, 1, 2 };
|
||||||
|
if (dev < countof(SPI_DevSelect)) {
|
||||||
|
return SPI_DevSelect[dev];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 SPI_GetDevBaudrate(u32 dev)
|
||||||
|
{
|
||||||
|
static const u8 SPI_BaudRates[] = { 2, 0, 0, 5 };
|
||||||
|
if (dev < countof(SPI_BaudRates)) {
|
||||||
|
return SPI_BaudRates[dev];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SPI_WaitBusy(void)
|
||||||
|
{
|
||||||
|
while(REG_SPI_CNT & SPI_CNT_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SPI_WaitFIFO(void)
|
||||||
|
{
|
||||||
|
while(REG_SPI_STATUS & SPI_STAT_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SPI_Done(void)
|
||||||
|
{
|
||||||
|
REG_SPI_DONE = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SPI_SingleXfer(u32 reg, bool read, u32 *buffer, u32 len)
|
||||||
|
{
|
||||||
|
u32 pos = 0;
|
||||||
|
|
||||||
|
REG_SPI_BLKLEN = len;
|
||||||
|
REG_SPI_CNT = reg | (read ? SPI_CNT_READ : SPI_CNT_WRITE) | SPI_CNT_START;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((pos % SPI_FIFO_WIDTH) == 0)
|
||||||
|
SPI_WaitFIFO();
|
||||||
|
|
||||||
|
if (read) {
|
||||||
|
buffer[pos / 4] = REG_SPI_FIFO;
|
||||||
|
} else {
|
||||||
|
REG_SPI_FIFO = buffer[pos / 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += 4;
|
||||||
|
} while(pos < len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfers, u32 xfer_cnt)
|
||||||
|
{
|
||||||
|
u32 dev_cfg;
|
||||||
|
int baud, cs;
|
||||||
|
|
||||||
|
baud = SPI_GetDevBaudrate(dev);
|
||||||
|
cs = SPI_GetDevSelect(dev);
|
||||||
|
dev_cfg = SPI_CNT_RATE(baud) | SPI_CNT_CS(cs);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < xfer_cnt; i++) {
|
||||||
|
SPI_XferInfo *xfer = &xfers[i];
|
||||||
|
|
||||||
|
SPI_WaitBusy();
|
||||||
|
SPI_SingleXfer(dev_cfg, xfer->read, xfer->buf, xfer->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI_WaitBusy();
|
||||||
|
SPI_Done();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPI_Init(void)
|
||||||
|
{
|
||||||
|
// Hack: here all registers should be set to the "new" mode
|
||||||
|
// but GM9 uses the old interface to access NVRAM
|
||||||
|
// as such, only the bus used by CODEC will be set to new
|
||||||
|
// *CFG_SPI_CNT = 7;
|
||||||
|
*CFG_SPI_CNT = BIT(1);
|
||||||
|
}
|
13
arm11/source/hw/spi.h
Executable file
13
arm11/source/hw/spi.h
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 *buf;
|
||||||
|
u8 len;
|
||||||
|
bool read;
|
||||||
|
} SPI_XferInfo;
|
||||||
|
|
||||||
|
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfer, u32 xfer_cnt);
|
||||||
|
|
||||||
|
void SPI_Init(void);
|
@ -1,12 +1,12 @@
|
|||||||
#include <hid_map.h>
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <vram.h>
|
#include <shmem.h>
|
||||||
#include <arm.h>
|
#include <arm.h>
|
||||||
#include <pxi.h>
|
#include <pxi.h>
|
||||||
|
|
||||||
#include "arm/gic.h"
|
#include "arm/gic.h"
|
||||||
|
|
||||||
|
#include "hw/hid.h"
|
||||||
#include "hw/gpulcd.h"
|
#include "hw/gpulcd.h"
|
||||||
#include "hw/i2c.h"
|
#include "hw/i2c.h"
|
||||||
#include "hw/mcu.h"
|
#include "hw/mcu.h"
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
static bool legacy = false;
|
static bool legacy = false;
|
||||||
|
|
||||||
#define REG_HID (~(*(vu16*)(0x10146000)) & BUTTON_ANY)
|
static GlobalSharedMemory SharedMemory_State;
|
||||||
static const u8 brightness_lvls[] = {
|
static const u8 brightness_lvls[] = {
|
||||||
0x10, 0x17, 0x1E, 0x25,
|
0x10, 0x17, 0x1E, 0x25,
|
||||||
0x2C, 0x34, 0x3C, 0x44,
|
0x2C, 0x34, 0x3C, 0x44,
|
||||||
@ -23,7 +23,6 @@ static const u8 brightness_lvls[] = {
|
|||||||
0x79, 0x8C, 0xA7, 0xD2
|
0x79, 0x8C, 0xA7, 0xD2
|
||||||
};
|
};
|
||||||
static int prev_bright_lvl = -1;
|
static int prev_bright_lvl = -1;
|
||||||
static vu32 global_hid_state = 0;
|
|
||||||
|
|
||||||
void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
||||||
{
|
{
|
||||||
@ -38,8 +37,8 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
// the state should probably be stored on its own
|
// the state should probably be stored on its own
|
||||||
// setion without caching enabled, since it must
|
// setion without caching enabled, since it must
|
||||||
// be readable by the ARM9 at all times anyway
|
// be readable by the ARM9 at all times anyway
|
||||||
global_hid_state = REG_HID | MCU_GetSpecialHID();
|
SharedMemory_State.hid_state = HID_GetState();
|
||||||
ARM_WbDC_Range((void*)&global_hid_state, 4);
|
ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State));
|
||||||
ARM_DMB();
|
ARM_DMB();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +68,7 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
|
|
||||||
case PXI_GET_SHMEM:
|
case PXI_GET_SHMEM:
|
||||||
{
|
{
|
||||||
ret = (u32)&global_hid_state;
|
ret = (u32)&SharedMemory_State;
|
||||||
//ret = 0xFFFFFFFF;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,13 +108,13 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
|
|
||||||
void __attribute__((noreturn)) MainLoop(void)
|
void __attribute__((noreturn)) MainLoop(void)
|
||||||
{
|
{
|
||||||
// enable MCU interrupts
|
|
||||||
GIC_Enable(MCU_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO, MCU_HandleInterrupts);
|
|
||||||
|
|
||||||
// enable PXI RX interrupt
|
// enable PXI RX interrupt
|
||||||
GIC_Enable(PXI_RX_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler);
|
GIC_Enable(PXI_RX_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO, PXI_RX_Handler);
|
||||||
|
|
||||||
GIC_Enable(VBLANK_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 1, VBlank_Handler);
|
// enable MCU interrupts
|
||||||
|
GIC_Enable(MCU_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 1, MCU_HandleInterrupts);
|
||||||
|
|
||||||
|
GIC_Enable(VBLANK_INTERRUPT, BIT(0), GIC_HIGHEST_PRIO + 2, VBlank_Handler);
|
||||||
|
|
||||||
// ARM9 won't try anything funny until this point
|
// ARM9 won't try anything funny until this point
|
||||||
PXI_Barrier(ARM11_READY_BARRIER);
|
PXI_Barrier(ARM11_READY_BARRIER);
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
#include "arm/scu.h"
|
#include "arm/scu.h"
|
||||||
#include "arm/timer.h"
|
#include "arm/timer.h"
|
||||||
|
|
||||||
|
#include "hw/codec.h"
|
||||||
#include "hw/gpulcd.h"
|
#include "hw/gpulcd.h"
|
||||||
#include "hw/i2c.h"
|
#include "hw/i2c.h"
|
||||||
#include "hw/mcu.h"
|
#include "hw/mcu.h"
|
||||||
|
#include "hw/spi.h"
|
||||||
|
|
||||||
#include "system/sections.h"
|
#include "system/sections.h"
|
||||||
|
|
||||||
@ -85,6 +87,8 @@ void SYS_CoreZeroInit(void)
|
|||||||
PXI_Reset();
|
PXI_Reset();
|
||||||
I2C_init();
|
I2C_init();
|
||||||
MCU_Init();
|
MCU_Init();
|
||||||
|
SPI_Init();
|
||||||
|
CODEC_Init();
|
||||||
|
|
||||||
GPU_Init();
|
GPU_Init();
|
||||||
GPU_PSCFill(VRAM_START, VRAM_END, 0);
|
GPU_PSCFill(VRAM_START, VRAM_END, 0);
|
||||||
@ -95,8 +99,8 @@ void SYS_CoreZeroInit(void)
|
|||||||
GPU_SetFramebufferMode(0, PDC_RGB24);
|
GPU_SetFramebufferMode(0, PDC_RGB24);
|
||||||
GPU_SetFramebufferMode(1, PDC_RGB24);
|
GPU_SetFramebufferMode(1, PDC_RGB24);
|
||||||
|
|
||||||
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
|
||||||
MCU_WriteReg(0x22, 0x2A);
|
MCU_WriteReg(0x22, 0x2A);
|
||||||
|
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SYS_CoreInit(void)
|
void SYS_CoreInit(void)
|
||||||
|
@ -4,10 +4,19 @@
|
|||||||
#include "screenshot.h" // for screenshots
|
#include "screenshot.h" // for screenshots
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
#include "shmem.h"
|
||||||
|
|
||||||
|
// there's some weird thing going on when reading this
|
||||||
|
// with an LDRD instruction so for now they'll be two
|
||||||
|
// separate things - hopefully LTO won't get in the way
|
||||||
u32 HID_ReadState(void)
|
u32 HID_ReadState(void)
|
||||||
{ // this should probably be abstracted away in something like "SHMEM_GetHID"
|
{
|
||||||
return *(u32*)ARM_GetTID();
|
return ARM_GetSHMEM()->hid_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 HID_ReadRawTouchState(void)
|
||||||
|
{
|
||||||
|
return ARM_GetSHMEM()->hid_state >> 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 InputWait(u32 timeout_sec) {
|
u32 InputWait(u32 timeout_sec) {
|
||||||
|
@ -6,17 +6,13 @@
|
|||||||
|
|
||||||
// see: http://3dbrew.org/wiki/CONFIG9_Registers
|
// see: http://3dbrew.org/wiki/CONFIG9_Registers
|
||||||
// see: http://3dbrew.org/wiki/EMMC_Registers
|
// see: http://3dbrew.org/wiki/EMMC_Registers
|
||||||
|
|
||||||
u32 HID_ReadState(void);
|
u32 HID_ReadState(void);
|
||||||
|
u32 HID_ReadRawTouchState(void);
|
||||||
|
|
||||||
#define CART_STATE (~(*(volatile u8*)0x10000010) & 0x1)
|
#define CART_STATE (~(*(volatile u8*)0x10000010) & 0x1)
|
||||||
#define SD_STATE ((*(volatile u16*)0x1000601C) & (0x1<<5))
|
#define SD_STATE ((*(volatile u16*)0x1000601C) & (0x1<<5))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// strings for button conversion
|
|
||||||
#define BUTTON_STRINGS "A", "B", "SELECT", "START", "RIGHT", "LEFT", "UP", "DOWN", "R", "L", "X", "Y"
|
|
||||||
|
|
||||||
|
|
||||||
u32 InputWait(u32 timeout_sec);
|
u32 InputWait(u32 timeout_sec);
|
||||||
bool CheckButton(u32 button);
|
bool CheckButton(u32 button);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
#include "shmem.h"
|
||||||
|
|
||||||
void main(int argc, char** argv, int entrypoint)
|
void main(int argc, char** argv, int entrypoint)
|
||||||
{
|
{
|
||||||
@ -19,7 +20,7 @@ void main(int argc, char** argv, int entrypoint)
|
|||||||
|
|
||||||
// A pointer to the shared memory region is
|
// A pointer to the shared memory region is
|
||||||
// stored in the thread ID register in the ARM9
|
// stored in the thread ID register in the ARM9
|
||||||
ARM_SetTID(PXI_DoCMD(PXI_GET_SHMEM, NULL, 0));
|
ARM_InitSHMEM();
|
||||||
|
|
||||||
#ifdef SCRIPT_RUNNER
|
#ifdef SCRIPT_RUNNER
|
||||||
// Run the script runner
|
// Run the script runner
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
#define min(a,b) \
|
#define min(a,b) \
|
||||||
(((a) < (b)) ? (a) : (b))
|
(((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define abs(x) \
|
||||||
|
(((x) >= 0) ? (x) : -(x))
|
||||||
|
|
||||||
|
#define int_sign(x) \
|
||||||
|
(((x) > 0) - ((x) < 0))
|
||||||
|
|
||||||
#define getbe16(d) \
|
#define getbe16(d) \
|
||||||
(((d)[0]<<8) | (d)[1])
|
(((d)[0]<<8) | (d)[1])
|
||||||
#define getbe32(d) \
|
#define getbe32(d) \
|
||||||
|
@ -15,13 +15,18 @@
|
|||||||
#define BUTTON_ANY 0x00000FFF
|
#define BUTTON_ANY 0x00000FFF
|
||||||
#define BUTTON_ARROW (BUTTON_RIGHT|BUTTON_LEFT|BUTTON_UP|BUTTON_DOWN)
|
#define BUTTON_ARROW (BUTTON_RIGHT|BUTTON_LEFT|BUTTON_UP|BUTTON_DOWN)
|
||||||
|
|
||||||
// special buttons / cart / sd
|
// strings for button conversion
|
||||||
|
#define BUTTON_STRINGS "A", "B", "SELECT", "START", "RIGHT", "LEFT", "UP", "DOWN", "R", "L", "X", "Y"
|
||||||
|
|
||||||
|
// special buttons / touchscreen / cart / sd
|
||||||
#define BUTTON_POWER ((u32)1 << 12)
|
#define BUTTON_POWER ((u32)1 << 12)
|
||||||
#define BUTTON_HOME ((u32)1 << 13)
|
#define BUTTON_HOME ((u32)1 << 13)
|
||||||
#define BUTTON_WIFI ((u32)1 << 14)
|
#define BUTTON_WIFI ((u32)1 << 14)
|
||||||
#define CART_INSERT ((u32)1 << 15)
|
#define BUTTON_TOUCH ((u32)1 << 15)
|
||||||
#define CART_EJECT ((u32)1 << 16)
|
|
||||||
#define SD_INSERT ((u32)1 << 17)
|
#define CART_INSERT ((u32)1 << 16)
|
||||||
#define SD_EJECT ((u32)1 << 18)
|
#define CART_EJECT ((u32)1 << 17)
|
||||||
|
#define SD_INSERT ((u32)1 << 18)
|
||||||
|
#define SD_EJECT ((u32)1 << 19)
|
||||||
|
|
||||||
#define TIMEOUT_HID ((u32)1 << 31)
|
#define TIMEOUT_HID ((u32)1 << 31)
|
||||||
|
21
common/shmem.h
Executable file
21
common/shmem.h
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <arm.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 hid_state;
|
||||||
|
} GlobalSharedMemory;
|
||||||
|
|
||||||
|
#ifdef ARM9
|
||||||
|
#include <pxi.h>
|
||||||
|
|
||||||
|
static inline const GlobalSharedMemory *ARM_GetSHMEM(void)
|
||||||
|
{
|
||||||
|
return (const GlobalSharedMemory*)ARM_GetTID();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ARM_InitSHMEM(void)
|
||||||
|
{
|
||||||
|
ARM_SetTID(PXI_DoCMD(PXI_GET_SHMEM, NULL, 0));
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user