forked from Mirror/GodMode9
- added touchscreen calibration code
- added very simple 12-bit precision fixed point arithmetic code as a fast float replacement
This commit is contained in:
parent
bf45ee3900
commit
1b04ca4fa1
@ -157,7 +157,7 @@ static void CODEC_GetRawData(u8 *buffer)
|
|||||||
|
|
||||||
void CODEC_Get(CODEC_Input *input)
|
void CODEC_Get(CODEC_Input *input)
|
||||||
{
|
{
|
||||||
u8 raw_data[0x34] = {0};
|
u8 raw_data[0x34];
|
||||||
s16 cpad_x, cpad_y;
|
s16 cpad_x, cpad_y;
|
||||||
bool ts_pressed;
|
bool ts_pressed;
|
||||||
|
|
||||||
@ -167,15 +167,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
|
||||||
if (abs(cpad_x) > CPAD_THRESH)
|
input->cpad_x = (abs(cpad_x) > CPAD_THRESH) ? -cpad_x / CPAD_FACTOR : 0;
|
||||||
input->cpad_x = -cpad_x / CPAD_FACTOR;
|
input->cpad_y = (abs(cpad_y) > CPAD_THRESH) ? cpad_y / CPAD_FACTOR : 0;
|
||||||
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));
|
ts_pressed = !(raw_data[0] & BIT(4));
|
||||||
if (ts_pressed) {
|
if (ts_pressed) {
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#define CODEC_TOUCH_VALID(x) ((x) != 0xFFFFFFFF)
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
s16 cpad_x, cpad_y;
|
s16 cpad_x, cpad_y;
|
||||||
s16 ts_x, ts_y;
|
s16 ts_x, ts_y;
|
||||||
|
@ -4,8 +4,12 @@
|
|||||||
#include "screenshot.h" // for screenshots
|
#include "screenshot.h" // for screenshots
|
||||||
|
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
#include "fixp.h"
|
||||||
#include "shmem.h"
|
#include "shmem.h"
|
||||||
|
|
||||||
|
#define HID_TOUCH_MAXPOINT (0x1000)
|
||||||
|
#define HID_TOUCH_MIDPOINT (HID_TOUCH_MAXPOINT / 2)
|
||||||
|
|
||||||
// there's some weird thing going on when reading this
|
// there's some weird thing going on when reading this
|
||||||
// with an LDRD instruction so for now they'll be two
|
// with an LDRD instruction so for now they'll be two
|
||||||
// separate things - hopefully LTO won't get in the way
|
// separate things - hopefully LTO won't get in the way
|
||||||
@ -19,6 +23,66 @@ u32 HID_ReadRawTouchState(void)
|
|||||||
return ARM_GetSHMEM()->hid_state >> 32;
|
return ARM_GetSHMEM()->hid_state >> 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 ts_x_org, ts_y_org;
|
||||||
|
static fixp_t ts_x_mult, ts_y_mult;
|
||||||
|
void HID_ReadTouchState(u16 *x, u16 *y)
|
||||||
|
{
|
||||||
|
u32 ts;
|
||||||
|
fixp_t tx, ty;
|
||||||
|
|
||||||
|
ts = HID_ReadRawTouchState();
|
||||||
|
tx = INT_TO_FIXP(HID_RAW_TX(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;
|
||||||
|
*y = FIXP_TO_INT(fixp_round(fixp_product(ty, ts_y_mult))) + ts_y_org;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, u32 screen_w, u32 screen_h)
|
||||||
|
{
|
||||||
|
int x_mid, y_mid;
|
||||||
|
fixp_t avg_x, avg_y;
|
||||||
|
|
||||||
|
if (!screen_w || !screen_h || point_cnt <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
x_mid = screen_w / 2;
|
||||||
|
y_mid = screen_h / 2;
|
||||||
|
|
||||||
|
avg_x = 0;
|
||||||
|
avg_y = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < point_cnt; i++) {
|
||||||
|
const HID_CalibrationData *data = &calibs[i];
|
||||||
|
fixp_t screen_x, screen_y, touch_x, touch_y;
|
||||||
|
|
||||||
|
// translate the [0, screen_w] x [0, screen_h] system
|
||||||
|
// 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_y = INT_TO_FIXP(data->screen_y - y_mid);
|
||||||
|
|
||||||
|
// same thing for raw touchscreen data
|
||||||
|
touch_x = INT_TO_FIXP(HID_RAW_TX(data->ts_raw) - HID_TOUCH_MIDPOINT);
|
||||||
|
touch_y = INT_TO_FIXP(HID_RAW_TY(data->ts_raw) - HID_TOUCH_MIDPOINT);
|
||||||
|
|
||||||
|
// if the data retrieved came right in the middle, it's invalid
|
||||||
|
if (!screen_x || !screen_y || !touch_x || !touch_y)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
avg_x += fixp_quotient(screen_x, touch_x);
|
||||||
|
avg_y += fixp_quotient(screen_y, touch_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts_x_mult = avg_x / point_cnt;
|
||||||
|
ts_y_mult = avg_y / point_cnt;
|
||||||
|
|
||||||
|
ts_x_org = x_mid;
|
||||||
|
ts_y_org = y_mid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
u32 InputWait(u32 timeout_sec) {
|
u32 InputWait(u32 timeout_sec) {
|
||||||
static u64 delay = 0;
|
static u64 delay = 0;
|
||||||
u64 timer = timer_start();
|
u64 timer = timer_start();
|
||||||
|
@ -6,13 +6,26 @@
|
|||||||
|
|
||||||
// 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_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))
|
||||||
|
|
||||||
|
#define HID_RAW_TX(t) ((s32)(((t) / (1 << 16)) & 0xFFF))
|
||||||
|
#define HID_RAW_TY(t) ((s32)((t) & 0xFFF))
|
||||||
|
|
||||||
|
u32 HID_ReadState(void);
|
||||||
|
|
||||||
|
// ts_raw is the raw touchscreen value obtained when pressing down
|
||||||
|
// the touchscreen at the screen coordinates [screen_x, screen_y]
|
||||||
|
// note: no point can be at the center
|
||||||
|
typedef struct {
|
||||||
|
u32 ts_raw;
|
||||||
|
int screen_x, screen_y;
|
||||||
|
} HID_CalibrationData;
|
||||||
|
|
||||||
|
u32 HID_ReadRawTouchState(void);
|
||||||
|
void HID_ReadTouchState(u16 *x, u16 *y);
|
||||||
|
bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, u32 screen_w, u32 screen_h);
|
||||||
|
|
||||||
u32 InputWait(u32 timeout_sec);
|
u32 InputWait(u32 timeout_sec);
|
||||||
bool CheckButton(u32 button);
|
bool CheckButton(u32 button);
|
||||||
|
|
||||||
|
@ -2184,7 +2184,7 @@ u32 GodMode(int entrypoint) {
|
|||||||
last_write_perm = GetWritePermissions();
|
last_write_perm = GetWritePermissions();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle user input
|
// handle user input
|
||||||
u32 pad_state = InputWait(3);
|
u32 pad_state = InputWait(3);
|
||||||
bool switched = (pad_state & BUTTON_R1);
|
bool switched = (pad_state & BUTTON_R1);
|
||||||
|
@ -7,6 +7,17 @@
|
|||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
#include "shmem.h"
|
#include "shmem.h"
|
||||||
|
|
||||||
|
#include "hid.h"
|
||||||
|
|
||||||
|
static const HID_CalibrationData default_calib = {
|
||||||
|
.screen_x = 0,
|
||||||
|
.screen_y = 0,
|
||||||
|
.ts_raw = 0
|
||||||
|
// ^ wrong: in my console it's 0x780086
|
||||||
|
// but this is very much console dependent
|
||||||
|
// so it's better to go with a sane default
|
||||||
|
};
|
||||||
|
|
||||||
void main(int argc, char** argv, int entrypoint)
|
void main(int argc, char** argv, int entrypoint)
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
@ -22,6 +33,10 @@ void main(int argc, char** argv, int entrypoint)
|
|||||||
// stored in the thread ID register in the ARM9
|
// stored in the thread ID register in the ARM9
|
||||||
ARM_InitSHMEM();
|
ARM_InitSHMEM();
|
||||||
|
|
||||||
|
// Hardcoding this isn't ideal but it's better than
|
||||||
|
// leaving the system without any state to work with
|
||||||
|
HID_SetCalibrationData(&default_calib, 1, 320, 240);
|
||||||
|
|
||||||
#ifdef SCRIPT_RUNNER
|
#ifdef SCRIPT_RUNNER
|
||||||
// Run the script runner
|
// Run the script runner
|
||||||
if (ScriptRunner(entrypoint) == GODMODE_EXIT_REBOOT)
|
if (ScriptRunner(entrypoint) == GODMODE_EXIT_REBOOT)
|
||||||
|
37
common/fixp.h
Executable file
37
common/fixp.h
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Fixed point math operations
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
typedef int32_t fixp_t;
|
||||||
|
|
||||||
|
// 12 bit precision was chosen because
|
||||||
|
// that's the touchscreen's ADC resolution
|
||||||
|
#define FIXP_PRECISION (12)
|
||||||
|
|
||||||
|
#define INT_TO_FIXP(i) ((fixp_t)((i) * (1 << FIXP_PRECISION)))
|
||||||
|
#define FIXP_TO_INT(f) ((fixp_t)((f) / (1 << FIXP_PRECISION)))
|
||||||
|
|
||||||
|
#define FIXP_WHOLE_UNIT INT_TO_FIXP(1)
|
||||||
|
#define FIXP_HALF_UNIT (FIXP_WHOLE_UNIT / 2)
|
||||||
|
#define FIXP_ZERO_UNIT (0)
|
||||||
|
|
||||||
|
#define FIXP_FRAC_MASK (FIXP_WHOLE_UNIT - 1)
|
||||||
|
#define FIXP_UNIT_MASK (~0 & ~FIXP_FRAC_MASK)
|
||||||
|
|
||||||
|
static inline fixp_t fixp_product(fixp_t a, fixp_t b)
|
||||||
|
{
|
||||||
|
return (((s64)a * (s64)b) >> FIXP_PRECISION);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline fixp_t fixp_quotient(fixp_t a, fixp_t b)
|
||||||
|
{
|
||||||
|
return ((s64)a << FIXP_PRECISION) / b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline fixp_t fixp_round(fixp_t n)
|
||||||
|
{
|
||||||
|
return (n + FIXP_HALF_UNIT) & FIXP_UNIT_MASK;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user