mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
- added extremely simple calibration dialog, to be replaced by something prettier/saner/safer at a later point in time
- moved all SPI code to the ARM11 - reimplemented NVRAM reading for the new SPI interface
This commit is contained in:
parent
b52bf3b9a5
commit
70757e3385
@ -1,21 +1,18 @@
|
|||||||
#include <arm.h>
|
#include <arm.h>
|
||||||
|
|
||||||
.arm
|
.arm
|
||||||
.align 2
|
.align 3
|
||||||
|
|
||||||
.section .vector, "ax"
|
.section .vector, "ax"
|
||||||
vectors:
|
vectors:
|
||||||
ldr pc, =XRQ_Reset
|
b XRQ_Reset @ RESET
|
||||||
ldr pc, =XRQ_Reset
|
b XRQ_Reset @ UNDEFINED
|
||||||
ldr pc, =XRQ_Reset
|
b XRQ_Reset @ SVC
|
||||||
ldr pc, =XRQ_Reset
|
b XRQ_Reset @ PREFETCH ABORT
|
||||||
ldr pc, =XRQ_Reset
|
b XRQ_Reset @ DATA ABORT
|
||||||
b . @ RESERVED
|
b XRQ_Reset @ RESERVED
|
||||||
ldr pc, =XRQ_IRQ
|
b XRQ_IRQ @ IRQ
|
||||||
ldr pc, =XRQ_Reset
|
b XRQ_Reset @ FIQ
|
||||||
.pool
|
|
||||||
|
|
||||||
.section .text.XRQS, "ax"
|
|
||||||
|
|
||||||
XRQ_Reset:
|
XRQ_Reset:
|
||||||
mov r0, #0x18000000
|
mov r0, #0x18000000
|
||||||
@ -24,12 +21,9 @@ XRQ_Reset:
|
|||||||
1:
|
1:
|
||||||
cmp r0, r1
|
cmp r0, r1
|
||||||
strne r2, [r0], #4
|
strne r2, [r0], #4
|
||||||
bne 1b
|
moveq r0, #0x18000000
|
||||||
2:
|
b 1b
|
||||||
wfi
|
|
||||||
b 2b
|
|
||||||
|
|
||||||
.global XRQ_IRQ
|
|
||||||
XRQ_IRQ:
|
XRQ_IRQ:
|
||||||
sub lr, lr, #4 @ Fix return address
|
sub lr, lr, #4 @ Fix return address
|
||||||
srsfd sp!, #SR_SVC_MODE @ Store IRQ mode LR and SPSR on the SVC stack
|
srsfd sp!, #SR_SVC_MODE @ Store IRQ mode LR and SPSR on the SVC stack
|
||||||
@ -39,7 +33,8 @@ XRQ_IRQ:
|
|||||||
and r4, sp, #7 @ Fix SP to be 8byte aligned
|
and r4, sp, #7 @ Fix SP to be 8byte aligned
|
||||||
sub sp, sp, r4
|
sub sp, sp, r4
|
||||||
|
|
||||||
bl GIC_MainHandler
|
mov lr, pc
|
||||||
|
ldr pc, =GIC_MainHandler
|
||||||
|
|
||||||
add sp, sp, r4
|
add sp, sp, r4
|
||||||
|
|
||||||
|
@ -18,11 +18,9 @@
|
|||||||
#include "hw/codec.h"
|
#include "hw/codec.h"
|
||||||
#include "hw/spi.h"
|
#include "hw/spi.h"
|
||||||
|
|
||||||
#define CODEC_SPI_DEV (3)
|
#define CODEC_SPI_DEV 3
|
||||||
|
|
||||||
#define MAX_12BIT (BIT(12) - 1)
|
|
||||||
#define CPAD_THRESH (150)
|
#define CPAD_THRESH (150)
|
||||||
#define CPAD_FACTOR (150)
|
|
||||||
|
|
||||||
/* SPI stuff */
|
/* SPI stuff */
|
||||||
static void CODEC_WriteRead(u32 *txb, u8 txl, u32 *rxb, u8 rxl)
|
static void CODEC_WriteRead(u32 *txb, u8 txl, u32 *rxb, u8 rxl)
|
||||||
@ -141,8 +139,8 @@ void CODEC_Get(CODEC_Input *input)
|
|||||||
cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048;
|
cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048;
|
||||||
|
|
||||||
// X axis is inverted
|
// X axis is inverted
|
||||||
input->cpad_x = (abs(cpad_x) > CPAD_THRESH) ? -cpad_x / CPAD_FACTOR : 0;
|
input->cpad_x = (abs(cpad_x) > CPAD_THRESH) ? -cpad_x : 0;
|
||||||
input->cpad_y = (abs(cpad_y) > CPAD_THRESH) ? cpad_y / CPAD_FACTOR : 0;
|
input->cpad_y = (abs(cpad_y) > CPAD_THRESH) ? cpad_y : 0;
|
||||||
|
|
||||||
ts_pressed = !(raw_data[0] & BIT(4));
|
ts_pressed = !(raw_data[0] & BIT(4));
|
||||||
if (ts_pressed) {
|
if (ts_pressed) {
|
||||||
|
77
arm11/source/hw/nvram.c
Executable file
77
arm11/source/hw/nvram.c
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include "hw/spi.h"
|
||||||
|
#include "hw/nvram.h"
|
||||||
|
|
||||||
|
#define NVRAM_SPI_DEV 1
|
||||||
|
|
||||||
|
// returns manuf id, memory type and size
|
||||||
|
// size = (1 << id[2]) ?
|
||||||
|
// apparently unreliable on some Sanyo chips?
|
||||||
|
#define CMD_RDID 0x9F
|
||||||
|
|
||||||
|
#define CMD_READ 0x03
|
||||||
|
#define CMD_WREN 0x06
|
||||||
|
#define CMD_WRDI 0x04
|
||||||
|
|
||||||
|
#define CMD_RDSR 0x05
|
||||||
|
|
||||||
|
#define CMD_DPD 0xB9 // deep power down
|
||||||
|
#define CMD_RDP 0xAB // release from deep power down
|
||||||
|
|
||||||
|
static u32 NVRAM_SendStatusCommand(u32 cmd, u32 width)
|
||||||
|
{
|
||||||
|
u32 ret;
|
||||||
|
SPI_XferInfo xfer[2];
|
||||||
|
|
||||||
|
xfer[0].buf = &cmd;
|
||||||
|
xfer[0].len = 1;
|
||||||
|
xfer[0].read = false;
|
||||||
|
|
||||||
|
xfer[1].buf = &ret;
|
||||||
|
xfer[1].len = width;
|
||||||
|
xfer[1].read = true;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
SPI_DoXfer(NVRAM_SPI_DEV, xfer, 2);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 NVRAM_Status(void)
|
||||||
|
{
|
||||||
|
return NVRAM_SendStatusCommand(CMD_RDSR, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 NVRAM_ReadID(void)
|
||||||
|
{
|
||||||
|
return NVRAM_SendStatusCommand(CMD_RDID, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NVRAM_DeepStandby(void)
|
||||||
|
{
|
||||||
|
NVRAM_SendStatusCommand(CMD_DPD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NVRAM_Wakeup(void)
|
||||||
|
{
|
||||||
|
NVRAM_SendStatusCommand(CMD_RDP, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NVRAM_Read(u32 address, u32 *buffer, u32 len)
|
||||||
|
{
|
||||||
|
SPI_XferInfo xfer[2];
|
||||||
|
u32 cmd;
|
||||||
|
|
||||||
|
address &= BIT(24) - 1;
|
||||||
|
cmd = __builtin_bswap32(address) | CMD_READ;
|
||||||
|
|
||||||
|
xfer[0].buf = &cmd;
|
||||||
|
xfer[0].len = 4;
|
||||||
|
xfer[0].read = false;
|
||||||
|
|
||||||
|
xfer[1].buf = buffer;
|
||||||
|
xfer[1].len = len;
|
||||||
|
xfer[1].read = true;
|
||||||
|
|
||||||
|
SPI_DoXfer(NVRAM_SPI_DEV, xfer, 2);
|
||||||
|
}
|
16
arm11/source/hw/nvram.h
Executable file
16
arm11/source/hw/nvram.h
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#include "hw/spi.h"
|
||||||
|
|
||||||
|
#define NVRAM_SR_WIP BIT(0) // work in progress / busy
|
||||||
|
#define NVRAM_SR_WEL BIT(1) // write enable latch
|
||||||
|
|
||||||
|
u32 NVRAM_Status(void);
|
||||||
|
u32 NVRAM_ReadID(void);
|
||||||
|
|
||||||
|
void NVRAM_Read(u32 offset, u32 *buffer, u32 len);
|
||||||
|
|
||||||
|
void NVRAM_DeepStandby(void);
|
||||||
|
void NVRAM_Wakeup(void);
|
@ -42,12 +42,12 @@
|
|||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
u32 bus;
|
u32 bus;
|
||||||
u32 regcfg;
|
u32 reg;
|
||||||
} SPI_Devices[] = {
|
} SPI_Devices[] = {
|
||||||
{REG_SPI_BUS0, SPI_CONTROL_RATE(2) | SPI_CONTROL_CS(0)}, // device 0
|
{REG_SPI_BUS0, SPI_CONTROL_RATE(2) | SPI_CONTROL_CS(0)},
|
||||||
{REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(1)},
|
{REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(1)}, // NVRAM
|
||||||
{REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(2)},
|
{REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(2)},
|
||||||
{REG_SPI_BUS1, SPI_CONTROL_RATE(5) | SPI_CONTROL_CS(0)},
|
{REG_SPI_BUS1, SPI_CONTROL_RATE(5) | SPI_CONTROL_CS(0)}, // CODEC
|
||||||
// TODO: complete this table
|
// TODO: complete this table
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,6 +74,8 @@ static void SPI_SingleXfer(u32 reg, u32 bus, u32 *buffer, u32 len, bool read)
|
|||||||
REG_SPI(bus, REG_SPI_CONTROL) = reg |
|
REG_SPI(bus, REG_SPI_CONTROL) = reg |
|
||||||
(read ? SPI_DIRECTION_READ : SPI_DIRECTION_WRITE) | SPI_CONTROL_START;
|
(read ? SPI_DIRECTION_READ : SPI_DIRECTION_WRITE) | SPI_CONTROL_START;
|
||||||
|
|
||||||
|
SPI_WaitFIFO(bus);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((pos % SPI_FIFO_WIDTH) == 0)
|
if ((pos % SPI_FIFO_WIDTH) == 0)
|
||||||
SPI_WaitFIFO(bus);
|
SPI_WaitFIFO(bus);
|
||||||
@ -88,19 +90,21 @@ static void SPI_SingleXfer(u32 reg, u32 bus, u32 *buffer, u32 len, bool read)
|
|||||||
} while(pos < len);
|
} while(pos < len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfers, u32 xfer_cnt)
|
int SPI_DoXfer(u32 dev, const SPI_XferInfo *xfers, u32 xfer_cnt)
|
||||||
{
|
{
|
||||||
u32 bus;
|
u32 bus, reg;
|
||||||
u32 dev_reg;
|
|
||||||
|
|
||||||
bus = SPI_Devices[dev].bus;
|
bus = SPI_Devices[dev].bus;
|
||||||
dev_reg = SPI_Devices[dev].regcfg;
|
reg = SPI_Devices[dev].reg;
|
||||||
|
|
||||||
for (u32 i = 0; i < xfer_cnt; i++) {
|
for (u32 i = 0; i < xfer_cnt; i++) {
|
||||||
SPI_XferInfo *xfer = &xfers[i];
|
const SPI_XferInfo *xfer = &xfers[i];
|
||||||
|
|
||||||
|
if (!xfer->buf || !xfer->len)
|
||||||
|
continue;
|
||||||
|
|
||||||
SPI_WaitBusy(bus);
|
SPI_WaitBusy(bus);
|
||||||
SPI_SingleXfer(dev_reg, bus, xfer->buf, xfer->len, xfer->read);
|
SPI_SingleXfer(reg, bus, xfer->buf, xfer->len, xfer->read);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPI_WaitBusy(bus);
|
SPI_WaitBusy(bus);
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 *buf;
|
u32 *buf;
|
||||||
u8 len;
|
u32 len;
|
||||||
bool read;
|
bool read;
|
||||||
} SPI_XferInfo;
|
} SPI_XferInfo;
|
||||||
|
|
||||||
int SPI_DoXfer(u32 dev, SPI_XferInfo *xfer, u32 xfer_cnt);
|
int SPI_DoXfer(u32 dev, const SPI_XferInfo *xfer, u32 xfer_cnt);
|
||||||
|
|
||||||
void SPI_Init(void);
|
void SPI_Init(void);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#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/nvram.h"
|
||||||
|
|
||||||
#include "system/sys.h"
|
#include "system/sys.h"
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
cmd = msg & 0xFFFF;
|
cmd = msg & 0xFFFF;
|
||||||
argc = msg >> 16;
|
argc = msg >> 16;
|
||||||
|
|
||||||
if (argc > PXI_MAX_ARGS) {
|
if (argc >= PXI_MAX_ARGS) {
|
||||||
PXI_Send(0xFFFFFFFF);
|
PXI_Send(0xFFFFFFFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -74,6 +75,7 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
|
|
||||||
case PXI_I2C_READ:
|
case PXI_I2C_READ:
|
||||||
{
|
{
|
||||||
|
ARM_InvDC_Range((void*)args[2], args[3]);
|
||||||
ret = I2C_readRegBuf(args[0], args[1], (u8*)args[2], args[3]);
|
ret = I2C_readRegBuf(args[0], args[1], (u8*)args[2], args[3]);
|
||||||
ARM_WbDC_Range((void*)args[2], args[3]);
|
ARM_WbDC_Range((void*)args[2], args[3]);
|
||||||
ARM_DMB();
|
ARM_DMB();
|
||||||
@ -88,6 +90,16 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PXI_NVRAM_READ:
|
||||||
|
{
|
||||||
|
ARM_InvDC_Range((void*)args[1], args[2]);
|
||||||
|
NVRAM_Read(args[0], (u32*)args[1], args[2]);
|
||||||
|
ARM_WbDC_Range((void*)args[1], args[2]);
|
||||||
|
ARM_DMB();
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* New CMD template:
|
/* New CMD template:
|
||||||
case CMD_ID:
|
case CMD_ID:
|
||||||
{
|
{
|
||||||
|
@ -85,8 +85,10 @@ void SYS_CoreZeroInit(void)
|
|||||||
|
|
||||||
// Initialize peripherals
|
// Initialize peripherals
|
||||||
PXI_Reset();
|
PXI_Reset();
|
||||||
|
|
||||||
I2C_init();
|
I2C_init();
|
||||||
MCU_Init();
|
MCU_Init();
|
||||||
|
|
||||||
SPI_Init();
|
SPI_Init();
|
||||||
CODEC_Init();
|
CODEC_Init();
|
||||||
|
|
||||||
|
@ -23,8 +23,14 @@ u32 HID_ReadRawTouchState(void)
|
|||||||
return ARM_GetSHMEM()->hid_state >> 32;
|
return ARM_GetSHMEM()->hid_state >> 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 ts_x_org, ts_y_org;
|
// ts_mult indicates a scalar for each axis
|
||||||
static fixp_t ts_x_mult, ts_y_mult;
|
// if |ts_mult| > 1 => point must be "scaled out"
|
||||||
|
// if |ts_mult| < 1 => point must be "scaled in"
|
||||||
|
// if ts_mult < 0 => axis is inverted
|
||||||
|
static fixp_t ts_mult[2];
|
||||||
|
|
||||||
|
// ts_org indicates the coordinate system origin
|
||||||
|
static u32 ts_org[2];
|
||||||
void HID_ReadTouchState(u16 *x, u16 *y)
|
void HID_ReadTouchState(u16 *x, u16 *y)
|
||||||
{
|
{
|
||||||
u32 ts;
|
u32 ts;
|
||||||
@ -34,20 +40,20 @@ void HID_ReadTouchState(u16 *x, u16 *y)
|
|||||||
tx = INT_TO_FIXP(HID_RAW_TX(ts) - HID_TOUCH_MIDPOINT);
|
tx = INT_TO_FIXP(HID_RAW_TX(ts) - HID_TOUCH_MIDPOINT);
|
||||||
ty = INT_TO_FIXP(HID_RAW_TY(ts) - HID_TOUCH_MIDPOINT);
|
ty = INT_TO_FIXP(HID_RAW_TY(ts) - HID_TOUCH_MIDPOINT);
|
||||||
|
|
||||||
*x = FIXP_TO_INT(fixp_round(fixp_product(tx, ts_x_mult))) + ts_x_org;
|
*x = FIXP_TO_INT(fixp_round(fixp_product(tx, ts_mult[0]))) + ts_org[0];
|
||||||
*y = FIXP_TO_INT(fixp_round(fixp_product(ty, ts_y_mult))) + ts_y_org;
|
*y = FIXP_TO_INT(fixp_round(fixp_product(ty, ts_mult[1]))) + ts_org[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, u32 screen_w, u32 screen_h)
|
bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, u32 screen_w, u32 screen_h)
|
||||||
{
|
{
|
||||||
int x_mid, y_mid;
|
int mid_x, mid_y;
|
||||||
fixp_t avg_x, avg_y;
|
fixp_t avg_x, avg_y;
|
||||||
|
|
||||||
if (!screen_w || !screen_h || point_cnt <= 0)
|
if (!screen_w || !screen_h || point_cnt <= 0 || point_cnt > 7)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
x_mid = screen_w / 2;
|
mid_x = screen_w / 2;
|
||||||
y_mid = screen_h / 2;
|
mid_y = screen_h / 2;
|
||||||
|
|
||||||
avg_x = 0;
|
avg_x = 0;
|
||||||
avg_y = 0;
|
avg_y = 0;
|
||||||
@ -58,8 +64,8 @@ bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, u3
|
|||||||
|
|
||||||
// translate the [0, screen_w] x [0, screen_h] system
|
// translate the [0, screen_w] x [0, screen_h] system
|
||||||
// to [-screen_w/2, screen_w/2] x [-screen_h/2, screen_h/2]
|
// to [-screen_w/2, screen_w/2] x [-screen_h/2, screen_h/2]
|
||||||
screen_x = INT_TO_FIXP(data->screen_x - x_mid);
|
screen_x = INT_TO_FIXP(data->screen_x - mid_x);
|
||||||
screen_y = INT_TO_FIXP(data->screen_y - y_mid);
|
screen_y = INT_TO_FIXP(data->screen_y - mid_y);
|
||||||
|
|
||||||
// same thing for raw touchscreen data
|
// same thing for raw touchscreen data
|
||||||
touch_x = INT_TO_FIXP(HID_RAW_TX(data->ts_raw) - HID_TOUCH_MIDPOINT);
|
touch_x = INT_TO_FIXP(HID_RAW_TX(data->ts_raw) - HID_TOUCH_MIDPOINT);
|
||||||
@ -69,15 +75,16 @@ bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, u3
|
|||||||
if (!screen_x || !screen_y || !touch_x || !touch_y)
|
if (!screen_x || !screen_y || !touch_x || !touch_y)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
avg_x += fixp_quotient(screen_x, touch_x);
|
// prevent integer overflows by dividing in this step
|
||||||
avg_y += fixp_quotient(screen_y, touch_y);
|
avg_x += fixp_quotient(screen_x, touch_x * point_cnt);
|
||||||
|
avg_y += fixp_quotient(screen_y, touch_y * point_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_x_mult = avg_x / point_cnt;
|
// set state variables
|
||||||
ts_y_mult = avg_y / point_cnt;
|
ts_mult[0] = avg_x;
|
||||||
|
ts_mult[1] = avg_y;
|
||||||
ts_x_org = x_mid;
|
ts_org[0] = mid_x;
|
||||||
ts_y_org = y_mid;
|
ts_org[1] = mid_y;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,3 +1062,83 @@ bool ShowProgress(u64 current, u64 total, const char* opstr)
|
|||||||
|
|
||||||
return !CheckButton(BUTTON_B);
|
return !CheckButton(BUTTON_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DrawSimpleCircle(unsigned char *screen, int x, int y, int color, int bgcolor)
|
||||||
|
{
|
||||||
|
x -= GetFontWidth() / 2;
|
||||||
|
y -= GetFontHeight() / 2;
|
||||||
|
DrawCharacter(screen, 'O', x, y, color, bgcolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShowCalibrationDialog(void)
|
||||||
|
{
|
||||||
|
int current_dot;
|
||||||
|
static const u32 dot_positions[][2] = {
|
||||||
|
{16, 16},
|
||||||
|
{320 - 16, 240 - 16},
|
||||||
|
{16, 240 - 16},
|
||||||
|
{320 - 16, 16},
|
||||||
|
};
|
||||||
|
HID_CalibrationData calibrations[countof(dot_positions)];
|
||||||
|
|
||||||
|
ClearScreenF(true, true, COLOR_BLACK);
|
||||||
|
for (u32 i = 0; i < countof(dot_positions); i++) {
|
||||||
|
calibrations[i].screen_x = dot_positions[i][0];
|
||||||
|
calibrations[i].screen_y = dot_positions[i][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
current_dot = 0;
|
||||||
|
while(current_dot < countof(dot_positions)) {
|
||||||
|
for (int i = 0; i < current_dot; i++)
|
||||||
|
DrawSimpleCircle(BOT_SCREEN, dot_positions[i][0], dot_positions[i][1], COLOR_BRIGHTGREEN, COLOR_BLACK);
|
||||||
|
DrawSimpleCircle(BOT_SCREEN, dot_positions[current_dot][0], dot_positions[current_dot][1], COLOR_RED, COLOR_BLACK);
|
||||||
|
for (u32 i = current_dot+1; i < countof(dot_positions); i++)
|
||||||
|
DrawSimpleCircle(BOT_SCREEN, dot_positions[i][0], dot_positions[i][1], COLOR_WHITE, COLOR_BLACK);
|
||||||
|
|
||||||
|
while(HID_ReadState());
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
u32 pressed = HID_ReadState();
|
||||||
|
if (pressed & BUTTON_B) {
|
||||||
|
if (current_dot == 0)
|
||||||
|
return false;
|
||||||
|
current_dot--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pressed & BUTTON_TOUCH) {
|
||||||
|
calibrations[current_dot].ts_raw = HID_ReadRawTouchState();
|
||||||
|
current_dot++;
|
||||||
|
if (current_dot == countof(dot_positions)) {
|
||||||
|
return HID_SetCalibrationData(calibrations, countof(dot_positions), 320, 240);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowTouchPlayground(void)
|
||||||
|
{
|
||||||
|
ClearScreenF(true, true, COLOR_BLACK);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
u16 tx, ty;
|
||||||
|
u32 pressed = HID_ReadState();
|
||||||
|
|
||||||
|
if (pressed & BUTTON_TOUCH) {
|
||||||
|
HID_ReadTouchState(&tx, &ty);
|
||||||
|
if (tx < 320 && ty < 240)
|
||||||
|
DrawRectangle(BOT_SCREEN, tx, ty, 1, 1, COLOR_BRIGHTYELLOW);
|
||||||
|
} else {
|
||||||
|
tx = ty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawStringF(TOP_SCREEN, 16, 16, COLOR_WHITE, COLOR_BLACK, "Current touchscreen coordinates: %d, %d", tx, ty);
|
||||||
|
if (pressed & BUTTON_B)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -82,3 +82,6 @@ u64 ShowNumberPrompt(u64 start_val, const char *format, ...);
|
|||||||
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...);
|
bool ShowDataPrompt(u8* data, u32* size, const char *format, ...);
|
||||||
bool ShowRtcSetterPrompt(void* time, const char *format, ...);
|
bool ShowRtcSetterPrompt(void* time, const char *format, ...);
|
||||||
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
||||||
|
|
||||||
|
bool ShowCalibrationDialog(void);
|
||||||
|
void ShowTouchPlayground(void);
|
||||||
|
@ -2506,11 +2506,15 @@ u32 GodMode(int entrypoint) {
|
|||||||
const char* optionstr[8];
|
const char* optionstr[8];
|
||||||
const char* buttonstr = (pad_state & BUTTON_HOME) ? "HOME" : "POWER";
|
const char* buttonstr = (pad_state & BUTTON_HOME) ? "HOME" : "POWER";
|
||||||
u32 n_opt = 0;
|
u32 n_opt = 0;
|
||||||
|
int calib = ++n_opt;
|
||||||
|
int playground = ++n_opt;
|
||||||
int poweroff = ++n_opt;
|
int poweroff = ++n_opt;
|
||||||
int reboot = ++n_opt;
|
int reboot = ++n_opt;
|
||||||
int scripts = ++n_opt;
|
int scripts = ++n_opt;
|
||||||
int payloads = ++n_opt;
|
int payloads = ++n_opt;
|
||||||
int more = ++n_opt;
|
int more = ++n_opt;
|
||||||
|
if (calib > 0) optionstr[calib - 1] = "Calibrate touchscreen";
|
||||||
|
if (playground > 0) optionstr[playground - 1] = "Test touchscreen";
|
||||||
if (poweroff > 0) optionstr[poweroff - 1] = "Poweroff system";
|
if (poweroff > 0) optionstr[poweroff - 1] = "Poweroff system";
|
||||||
if (reboot > 0) optionstr[reboot - 1] = "Reboot system";
|
if (reboot > 0) optionstr[reboot - 1] = "Reboot system";
|
||||||
if (scripts > 0) optionstr[scripts - 1] = "Scripts...";
|
if (scripts > 0) optionstr[scripts - 1] = "Scripts...";
|
||||||
@ -2531,6 +2535,10 @@ u32 GodMode(int entrypoint) {
|
|||||||
ClearScreenF(true, true, COLOR_STD_BG);
|
ClearScreenF(true, true, COLOR_STD_BG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (user_select == calib) {
|
||||||
|
ShowPrompt(true, "CALIB: %d", ShowCalibrationDialog());
|
||||||
|
} else if (user_select == playground) {
|
||||||
|
ShowTouchPlayground();
|
||||||
} else if (user_select == payloads) {
|
} else if (user_select == payloads) {
|
||||||
if (!CheckSupportDir(PAYLOADS_DIR)) ShowPrompt(false, "Payloads directory not found.\n(default path: 0:/gm9/" PAYLOADS_DIR ")");
|
if (!CheckSupportDir(PAYLOADS_DIR)) ShowPrompt(false, "Payloads directory not found.\n(default path: 0:/gm9/" PAYLOADS_DIR ")");
|
||||||
else if (FileSelectorSupport(loadpath, "HOME payloads... menu.\nSelect payload:", PAYLOADS_DIR, "*.firm"))
|
else if (FileSelectorSupport(loadpath, "HOME payloads... menu.\nSelect payload:", PAYLOADS_DIR, "*.firm"))
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of fastboot 3DS
|
|
||||||
* Copyright (C) 2017 derrek, profi200
|
|
||||||
*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "spiflash.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define SPI_REGS_BUS2_BASE (0x10000000 + 0x100000 + 0x60000)
|
|
||||||
#define REG_SPI_BUS2_CNT *((vu16*)(SPI_REGS_BUS2_BASE + 0x00))
|
|
||||||
#define REG_SPI_BUS2_DATA *((vu8* )(SPI_REGS_BUS2_BASE + 0x02))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void spi_busy_wait()
|
|
||||||
{
|
|
||||||
while(REG_SPI_BUS2_CNT & 0x80);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spi_put_byte(u8 data)
|
|
||||||
{
|
|
||||||
REG_SPI_BUS2_DATA = data;
|
|
||||||
spi_busy_wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 spi_receive_byte()
|
|
||||||
{
|
|
||||||
// clock out a dummy byte
|
|
||||||
REG_SPI_BUS2_DATA = 0x00;
|
|
||||||
spi_busy_wait();
|
|
||||||
return REG_SPI_BUS2_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
// select spiflash if select=true, deselect otherwise
|
|
||||||
static void spiflash_select(bool select)
|
|
||||||
{
|
|
||||||
// select device 1, enable SPI bus
|
|
||||||
REG_SPI_BUS2_CNT = 0x8100 | (select << 11);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool spiflash_get_status()
|
|
||||||
{
|
|
||||||
u8 resp;
|
|
||||||
|
|
||||||
spi_busy_wait();
|
|
||||||
spiflash_select(1);
|
|
||||||
spi_put_byte(SPIFLASH_CMD_RDSR);
|
|
||||||
spiflash_select(0);
|
|
||||||
resp = spi_receive_byte();
|
|
||||||
|
|
||||||
if(resp & 1) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spiflash_read(u32 offset, u32 size, u8 *buf)
|
|
||||||
{
|
|
||||||
spi_busy_wait();
|
|
||||||
spiflash_select(1);
|
|
||||||
spi_put_byte(SPIFLASH_CMD_READ);
|
|
||||||
|
|
||||||
// write addr (24-bit, msb first)
|
|
||||||
for(int i=0; i<3; i++)
|
|
||||||
{
|
|
||||||
offset <<= 8;
|
|
||||||
spi_put_byte((offset >> 24) & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
// read bytes
|
|
||||||
for(u32 i=0; i<size; i++)
|
|
||||||
buf[i] = spi_receive_byte();
|
|
||||||
|
|
||||||
// end of read
|
|
||||||
spiflash_select(0);
|
|
||||||
spi_receive_byte();
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is part of fastboot 3DS
|
* This file is part of fastboot 3DS
|
||||||
* Copyright (C) 2017 derrek, profi200
|
* Copyright (C) 2017 derrek, profi200
|
||||||
@ -20,13 +19,22 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "arm.h"
|
||||||
|
#include "pxi.h"
|
||||||
|
|
||||||
#define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB)
|
#define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB)
|
||||||
#define SPIFLASH_CMD_RDSR (0x05)
|
|
||||||
#define SPIFLASH_CMD_READ (0x03)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// true if spiflash is installed, false otherwise
|
// true if spiflash is installed, false otherwise
|
||||||
bool spiflash_get_status();
|
static inline bool spiflash_get_status(void)
|
||||||
void spiflash_read(u32 offset, u32 size, u8 *buf);
|
{ // there should probably be a command for this...
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void spiflash_read(u32 offset, u32 size, u8 *buf)
|
||||||
|
{
|
||||||
|
u32 args[] = {offset, (u32)buf, size};
|
||||||
|
ARM_WbDC_Range(buf, size);
|
||||||
|
ARM_DSB();
|
||||||
|
PXI_DoCMD(PXI_NVRAM_READ, args, 3);
|
||||||
|
ARM_InvDC_Range(buf, size);
|
||||||
|
}
|
||||||
|
@ -20,6 +20,8 @@ enum {
|
|||||||
|
|
||||||
PXI_I2C_READ,
|
PXI_I2C_READ,
|
||||||
PXI_I2C_WRITE,
|
PXI_I2C_WRITE,
|
||||||
|
|
||||||
|
PXI_NVRAM_READ,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -32,9 +34,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define PXI_FIFO_LEN (16)
|
#define PXI_FIFO_LEN (16)
|
||||||
#define PXI_MAX_ARGS (32)
|
#define PXI_MAX_ARGS (64)
|
||||||
|
|
||||||
#define PXI_INIT_MAGIC (0xDD)
|
|
||||||
|
|
||||||
#define PXI_SYNC_RECV ((vu8*)(PXI_BASE + 0x00))
|
#define PXI_SYNC_RECV ((vu8*)(PXI_BASE + 0x00))
|
||||||
#define PXI_SYNC_SEND ((vu8*)(PXI_BASE + 0x01))
|
#define PXI_SYNC_SEND ((vu8*)(PXI_BASE + 0x01))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user