mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
- turn off the LCDs when the lid closes, and turn them back on when it's open
- reset LEDs on boot - add code to set the notification LED - add a PXI command to verify the NVRAM is actually online - notify the ARM9 about the shell state through the HID thing
This commit is contained in:
parent
79aa9191f7
commit
ad9a9bd5a0
@ -2,86 +2,188 @@
|
||||
#include <types.h>
|
||||
#include <arm.h>
|
||||
|
||||
#include "arm/timer.h"
|
||||
|
||||
#include "hw/gpio.h"
|
||||
#include "hw/gpulcd.h"
|
||||
#include "hw/i2c.h"
|
||||
#include "hw/mcu.h"
|
||||
|
||||
enum {
|
||||
PWR_BTN = 0,
|
||||
PWR_HOLD = 1,
|
||||
HOME_BTN = 2,
|
||||
HOME_HOLD = 3,
|
||||
WIFI_SWITCH = 4,
|
||||
SHELL_CLOSE = 5,
|
||||
SHELL_OPEN = 6,
|
||||
VOL_SLIDER = 22,
|
||||
MCU_PWR_BTN = 0,
|
||||
MCU_PWR_HOLD = 1,
|
||||
MCU_HOME_BTN = 2,
|
||||
MCU_HOME_LIFT = 3,
|
||||
MCU_WIFI_SWITCH = 4,
|
||||
MCU_SHELL_CLOSE = 5,
|
||||
MCU_SHELL_OPEN = 6,
|
||||
MCU_VOL_SLIDER = 22,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_VOL_SLIDER = 0x09,
|
||||
|
||||
REG_BATTERY_LEVEL = 0x0B,
|
||||
REG_CONSOLE_STATE = 0x0F,
|
||||
|
||||
REG_INT_MASK = 0x10,
|
||||
REG_INT_EN = 0x18,
|
||||
|
||||
REG_LCD_STATE = 0x22,
|
||||
|
||||
REG_LED_WIFI = 0x2A,
|
||||
REG_LED_CAMERA = 0x2B,
|
||||
REG_LED_SLIDER = 0x2C,
|
||||
REG_LED_NOTIF = 0x2D,
|
||||
|
||||
REG_RTC = 0x30,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u8 delay;
|
||||
u8 smoothing;
|
||||
u8 loop_delay;
|
||||
u8 unk;
|
||||
u32 red[8];
|
||||
u32 green[8];
|
||||
u32 blue[8];
|
||||
} __attribute__((packed)) MCU_NotificationLED;
|
||||
|
||||
static u8 cached_volume_slider = 0;
|
||||
static u32 spec_hid = 0;
|
||||
static u32 spec_hid = 0, shell_state = SHELL_OPEN;
|
||||
|
||||
static void MCU_UpdateVolumeSlider(void)
|
||||
{
|
||||
cached_volume_slider = MCU_ReadReg(0x09);
|
||||
cached_volume_slider = MCU_ReadReg(REG_VOL_SLIDER);
|
||||
}
|
||||
|
||||
void MCU_HandleInterrupts(u32 __attribute__((unused)) irqn)
|
||||
static void MCU_UpdateShellState(bool open)
|
||||
{
|
||||
u32 ints;
|
||||
|
||||
// Reading the pending mask automagically acknowledges
|
||||
// all the interrupts, so we must be sure to process all
|
||||
// of them in one go, possibly keep reading from the
|
||||
// register until it returns all zeroes
|
||||
MCU_ReadRegBuf(0x10, (u8*)&ints, sizeof(ints));
|
||||
|
||||
while(ints != 0) {
|
||||
u32 mcu_int_id = 31 - __builtin_clz(ints);
|
||||
|
||||
switch(mcu_int_id) {
|
||||
case PWR_BTN:
|
||||
case PWR_HOLD:
|
||||
spec_hid |= BUTTON_POWER;
|
||||
break;
|
||||
|
||||
case HOME_BTN:
|
||||
case HOME_HOLD:
|
||||
spec_hid |= BUTTON_HOME;
|
||||
break;
|
||||
|
||||
case WIFI_SWITCH:
|
||||
spec_hid |= BUTTON_WIFI;
|
||||
break;
|
||||
|
||||
case VOL_SLIDER:
|
||||
MCU_UpdateVolumeSlider();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ints &= ~BIT(mcu_int_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MCU_Init(void)
|
||||
{
|
||||
u32 mask = 0xFFBF0000 | BIT(11);
|
||||
I2C_writeRegBuf(3, 0x18, (const u8*)&mask, sizeof(mask));
|
||||
MCU_UpdateVolumeSlider();
|
||||
GPIO_setBit(19, 9); // enables MCU interrupts?
|
||||
shell_state = open ? SHELL_OPEN : SHELL_CLOSED;
|
||||
}
|
||||
|
||||
u8 MCU_GetVolumeSlider(void)
|
||||
{
|
||||
return cached_volume_slider;
|
||||
return cached_volume_slider;
|
||||
}
|
||||
|
||||
u32 MCU_GetSpecialHID(void)
|
||||
{
|
||||
u32 ret = spec_hid;
|
||||
spec_hid = 0;
|
||||
return ret;
|
||||
u32 ret = spec_hid | shell_state;
|
||||
spec_hid = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MCU_SetNotificationLED(u32 period_ms, u32 color)
|
||||
{
|
||||
u32 r, g, b;
|
||||
MCU_NotificationLED led_state;
|
||||
|
||||
// handle proper non-zero periods
|
||||
// so small the hardware can't handle it
|
||||
if (period_ms != 0 && period_ms < 63)
|
||||
period_ms = 63;
|
||||
|
||||
led_state.delay = (period_ms * 0x10) / 1000;
|
||||
led_state.smoothing = 0x40;
|
||||
led_state.loop_delay = 0x10;
|
||||
led_state.unk = 0;
|
||||
|
||||
// all colors look like 0x00ZZ00ZZ
|
||||
// in order to alternate between
|
||||
// LED "off" and the wanted color
|
||||
r = (color >> 16) & 0xFF;
|
||||
r |= r << 16;
|
||||
for (int i = 0; i < 8; i++)
|
||||
led_state.red[i] = r;
|
||||
|
||||
g = (color >> 8) & 0xFF;
|
||||
g |= g << 16;
|
||||
for (int i = 0; i < 8; i++)
|
||||
led_state.green[i] = g;
|
||||
|
||||
b = color & 0xFF;
|
||||
b |= b << 16;
|
||||
for (int i = 0; i < 8; i++)
|
||||
led_state.blue[i] = b;
|
||||
|
||||
MCU_WriteRegBuf(REG_LED_NOTIF, (const u8*)&led_state, sizeof(led_state));
|
||||
}
|
||||
|
||||
void MCU_ResetLED(void)
|
||||
{
|
||||
MCU_WriteReg(REG_LED_WIFI, 0);
|
||||
MCU_WriteReg(REG_LED_CAMERA, 0);
|
||||
MCU_WriteReg(REG_LED_SLIDER, 0);
|
||||
MCU_SetNotificationLED(0, 0);
|
||||
}
|
||||
|
||||
void MCU_PushToLCD(bool enable)
|
||||
{
|
||||
MCU_WriteReg(REG_LCD_STATE, enable ? 0x2A : 0x01);
|
||||
}
|
||||
|
||||
void MCU_HandleInterrupts(u32 __attribute__((unused)) irqn)
|
||||
{
|
||||
u32 ints;
|
||||
|
||||
// Reading the pending mask automagically acknowledges
|
||||
// the interrupts so all of them must be processed in one go
|
||||
MCU_ReadRegBuf(REG_INT_MASK, (u8*)&ints, sizeof(ints));
|
||||
|
||||
while(ints != 0) {
|
||||
u32 mcu_int_id = 31 - __builtin_clz(ints);
|
||||
|
||||
switch(mcu_int_id) {
|
||||
case MCU_PWR_BTN:
|
||||
case MCU_PWR_HOLD:
|
||||
spec_hid |= BUTTON_POWER;
|
||||
break;
|
||||
|
||||
case MCU_HOME_BTN:
|
||||
spec_hid |= BUTTON_HOME;
|
||||
break;
|
||||
|
||||
case MCU_HOME_LIFT:
|
||||
spec_hid &= ~BUTTON_HOME;
|
||||
break;
|
||||
|
||||
case MCU_WIFI_SWITCH:
|
||||
spec_hid |= BUTTON_WIFI;
|
||||
break;
|
||||
|
||||
case MCU_SHELL_OPEN:
|
||||
MCU_PushToLCD(true);
|
||||
MCU_UpdateShellState(true);
|
||||
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
||||
MCU_ResetLED();
|
||||
break;
|
||||
|
||||
case MCU_SHELL_CLOSE:
|
||||
MCU_PushToLCD(false);
|
||||
MCU_UpdateShellState(false);
|
||||
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
||||
break;
|
||||
|
||||
case MCU_VOL_SLIDER:
|
||||
MCU_UpdateVolumeSlider();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ints &= ~BIT(mcu_int_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MCU_Init(void)
|
||||
{
|
||||
u32 mask = 0xFFBF0800;
|
||||
MCU_WriteRegBuf(REG_INT_EN, (const u8*)&mask, sizeof(mask));
|
||||
MCU_ResetLED();
|
||||
|
||||
MCU_UpdateVolumeSlider();
|
||||
MCU_UpdateShellState(MCU_ReadReg(REG_CONSOLE_STATE) & BIT(1));
|
||||
|
||||
GPIO_setBit(19, 9);
|
||||
}
|
||||
|
@ -7,12 +7,18 @@
|
||||
#define MCU_INTERRUPT (0x71)
|
||||
#define I2C_MCU_DEVICE (3)
|
||||
|
||||
void MCU_HandleInterrupts(u32 irqn);
|
||||
void MCU_Init(void);
|
||||
|
||||
u8 MCU_GetVolumeSlider(void);
|
||||
u32 MCU_GetSpecialHID(void);
|
||||
|
||||
void MCU_SetNotificationLED(u32 period_ms, u32 color);
|
||||
void MCU_ResetLED(void);
|
||||
|
||||
void MCU_PushToLCD(bool enable);
|
||||
|
||||
void MCU_HandleInterrupts(u32 irqn);
|
||||
|
||||
void MCU_Init(void);
|
||||
|
||||
static inline u8 MCU_ReadReg(u8 addr)
|
||||
{
|
||||
u8 val;
|
||||
@ -20,7 +26,7 @@ static inline u8 MCU_ReadReg(u8 addr)
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline bool MCU_ReadRegBuf(u8 addr, u8 *buf, u8 size)
|
||||
static inline bool MCU_ReadRegBuf(u8 addr, u8 *buf, u32 size)
|
||||
{
|
||||
return I2C_readRegBuf(I2C_MCU_DEVICE, addr, buf, size);
|
||||
}
|
||||
@ -30,7 +36,7 @@ static inline bool MCU_WriteReg(u8 addr, u8 val)
|
||||
return I2C_writeRegBuf(I2C_MCU_DEVICE, addr, &val, 1);
|
||||
}
|
||||
|
||||
static inline bool MCU_WriteRegBuf(u8 addr, const u8 *buf, u8 size)
|
||||
static inline bool MCU_WriteRegBuf(u8 addr, const u8 *buf, u32 size)
|
||||
{
|
||||
return I2C_writeRegBuf(I2C_MCU_DEVICE, addr, buf, size);
|
||||
}
|
||||
|
@ -14,9 +14,8 @@
|
||||
|
||||
#include "system/sys.h"
|
||||
|
||||
static bool legacy = false;
|
||||
|
||||
static GlobalSharedMemory SharedMemory_State;
|
||||
|
||||
static const u8 brightness_lvls[] = {
|
||||
0x10, 0x17, 0x1E, 0x25,
|
||||
0x2C, 0x34, 0x3C, 0x44,
|
||||
@ -27,9 +26,7 @@ static int prev_bright_lvl = -1;
|
||||
|
||||
void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
||||
{
|
||||
int cur_bright_lvl = (MCU_GetVolumeSlider() >> 2);
|
||||
cur_bright_lvl %= countof(brightness_lvls);
|
||||
|
||||
int cur_bright_lvl = (MCU_GetVolumeSlider() >> 2) % countof(brightness_lvls);
|
||||
if (cur_bright_lvl != prev_bright_lvl) {
|
||||
prev_bright_lvl = cur_bright_lvl;
|
||||
LCD_SetBrightness(brightness_lvls[cur_bright_lvl]);
|
||||
@ -43,6 +40,8 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn)
|
||||
ARM_DMB();
|
||||
}
|
||||
|
||||
static bool legacy = false;
|
||||
|
||||
void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
||||
{
|
||||
u32 ret, msg, cmd, argc, args[PXI_MAX_ARGS];
|
||||
@ -90,6 +89,12 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
||||
break;
|
||||
}
|
||||
|
||||
case PXI_NVRAM_ONLINE:
|
||||
{
|
||||
ret = (NVRAM_Status() & NVRAM_SR_WIP) == 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case PXI_NVRAM_READ:
|
||||
{
|
||||
ARM_InvDC_Range((void*)args[1], args[2]);
|
||||
@ -100,6 +105,13 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
|
||||
break;
|
||||
}
|
||||
|
||||
case PXI_NOTIFY_LED:
|
||||
{
|
||||
MCU_SetNotificationLED(args[0], args[1]);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* New CMD template:
|
||||
case CMD_ID:
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ void SYS_CoreZeroInit(void)
|
||||
GPU_SetFramebufferMode(0, PDC_RGB24);
|
||||
GPU_SetFramebufferMode(1, PDC_RGB24);
|
||||
|
||||
MCU_WriteReg(0x22, 0x2A);
|
||||
MCU_PushToLCD(true);
|
||||
TIMER_WaitTicks(CLK_MS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,6 @@ bool HID_SetCalibrationData(const HID_CalibrationData *calibs, int point_cnt, in
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "ui.h"
|
||||
|
||||
u32 InputWait(u32 timeout_sec) {
|
||||
static u64 delay = 0;
|
||||
u64 timer = timer_start();
|
||||
|
@ -27,7 +27,7 @@
|
||||
// true if spiflash is installed, false otherwise
|
||||
static inline bool spiflash_get_status(void)
|
||||
{ // there should probably be a command for this...
|
||||
return true;
|
||||
return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0);
|
||||
}
|
||||
|
||||
static inline void spiflash_read(u32 offset, u32 size, u8 *buf)
|
||||
|
@ -24,9 +24,12 @@
|
||||
#define BUTTON_WIFI ((u32)1 << 14)
|
||||
#define BUTTON_TOUCH ((u32)1 << 15)
|
||||
|
||||
#define CART_INSERT ((u32)1 << 16)
|
||||
#define CART_EJECT ((u32)1 << 17)
|
||||
#define SD_INSERT ((u32)1 << 18)
|
||||
#define SD_EJECT ((u32)1 << 19)
|
||||
#define SHELL_OPEN ((u32)1 << 16)
|
||||
#define SHELL_CLOSED ((u32)1 << 17)
|
||||
|
||||
#define CART_INSERT ((u32)1 << 18)
|
||||
#define CART_EJECT ((u32)1 << 19)
|
||||
#define SD_INSERT ((u32)1 << 20)
|
||||
#define SD_EJECT ((u32)1 << 21)
|
||||
|
||||
#define TIMEOUT_HID ((u32)1 << 31)
|
||||
|
@ -21,7 +21,10 @@ enum {
|
||||
PXI_I2C_READ,
|
||||
PXI_I2C_WRITE,
|
||||
|
||||
PXI_NVRAM_ONLINE,
|
||||
PXI_NVRAM_READ,
|
||||
|
||||
PXI_NOTIFY_LED,
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user