Fixed screen init once and for all.
Some gfx code cleanup. Note: The screen init fix requires the same changes in other homebrew FIRMs to work properly. Particularly waiting for MCU events.
This commit is contained in:
parent
c3b57bda29
commit
602ec58777
|
@ -19,19 +19,33 @@
|
|||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "arm11/hardware/i2c.h"
|
||||
|
||||
|
||||
#define MCU_HID_POWER_BUTTON_PRESSED (1u)
|
||||
#define MCU_HID_POWER_BUTTON_LONG_PRESSED (1u<<1)
|
||||
#define MCU_HID_HOME_BUTTON_PRESSED (1u<<2)
|
||||
#define MCU_HID_HOME_BUTTON_RELEASED (1u<<3)
|
||||
#define MCU_HID_HOME_BUTTON_NOT_HELD (1u<<1)
|
||||
#define MCU_HID_SHELL_GOT_CLOSED (1u<<5)
|
||||
#define MCU_HID_SHELL_GOT_OPENED (1u<<6)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWLED_NORMAL = 0u,
|
||||
MCU_REG_VERS_HIGH = 0x00u,
|
||||
MCU_REG_VERS_LOW = 0x01u,
|
||||
MCU_REG_3D_SLIDER = 0x08u,
|
||||
MCU_REG_VOL_SLIDER = 0x09u, // 0-0x3F
|
||||
MCU_REG_BATTERY = 0x0Bu,
|
||||
MCU_REG_EX_HW_STATE = 0x0Fu,
|
||||
MCU_REG_EVENTS = 0x10u,
|
||||
MCU_REG_EVENT_MASK = 0x18u,
|
||||
MCU_REG_POWER = 0x20u,
|
||||
MCU_REG_LCDs = 0x22u,
|
||||
MCU_REG_POWER_LED = 0x29u,
|
||||
MCU_REG_WIFI_LED = 0x2Au,
|
||||
MCU_REG_CAM_LED = 0x2Bu,
|
||||
MCU_REG_3D_LED = 0x2Cu,
|
||||
MCU_REG_RTC_TIME = 0x30u,
|
||||
MCU_REG_RAW_STATE = 0x7Fu
|
||||
} McuReg;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWLED_AUTO = 0u,
|
||||
//PWLED_BLUE = 1u, // wtf is "forced default blue"?
|
||||
PWLED_SLEEP = 2u,
|
||||
PWLED_OFF = 3u,
|
||||
PWLED_RED = 4u,
|
||||
|
@ -42,17 +56,89 @@ typedef enum
|
|||
|
||||
|
||||
void MCU_init(void);
|
||||
void MCU_disableLEDs(void);
|
||||
void MCU_powerOnLCDs(void);
|
||||
void MCU_powerOffLCDs(void);
|
||||
void MCU_triggerPowerOff(void);
|
||||
void MCU_triggerReboot(void);
|
||||
u8 MCU_readBatteryLevel(void);
|
||||
u8 MCU_readExternalHwState(void);
|
||||
u8 MCU_readSystemModel(void);
|
||||
void MCU_readRTC(void *rtc);
|
||||
u32 MCU_readReceivedIrqs(void);
|
||||
bool MCU_setIrqBitmask(u32 mask);
|
||||
u8 MCU_readHidHeld(void);
|
||||
bool MCU_powerOnLcdBacklights(void);
|
||||
bool MCU_setPowerLedState(PwLedState state);
|
||||
|
||||
bool MCU_setEventMask(u32 mask);
|
||||
|
||||
u32 MCU_getEvents(u32 mask);
|
||||
|
||||
u32 MCU_waitEvents(u32 mask);
|
||||
|
||||
u8 MCU_readReg(McuReg reg);
|
||||
|
||||
bool MCU_writeReg(McuReg reg, u8 data);
|
||||
|
||||
bool MCU_readRegBuf(McuReg reg, u8 *out, u32 size);
|
||||
|
||||
bool MCU_writeRegBuf(McuReg reg, const u8 *const in, u32 size);
|
||||
|
||||
|
||||
static inline u8 MCU_getBatteryLevel(void)
|
||||
{
|
||||
u8 state;
|
||||
|
||||
if(!MCU_readRegBuf(MCU_REG_BATTERY, &state, 1)) return 0;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static inline u8 MCU_getExternalHwState(void)
|
||||
{
|
||||
return MCU_readReg(MCU_REG_EX_HW_STATE);
|
||||
}
|
||||
|
||||
static inline void MCU_powerOffSys(void)
|
||||
{
|
||||
I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, MCU_REG_POWER, 1u);
|
||||
}
|
||||
|
||||
static inline void MCU_rebootSys(void)
|
||||
{
|
||||
I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, MCU_REG_POWER, 1u<<2);
|
||||
}
|
||||
|
||||
static inline void MCU_powerOnLCDs(void)
|
||||
{
|
||||
// bit1 = lcd power enable for both screens
|
||||
MCU_writeReg(MCU_REG_LCDs, 1u<<1);
|
||||
}
|
||||
|
||||
static inline void MCU_powerOffLCDs(void)
|
||||
{
|
||||
// bit0 = lcd power disable for both screens (also disables backlight)
|
||||
MCU_writeReg(MCU_REG_LCDs, 1u);
|
||||
}
|
||||
|
||||
static inline bool MCU_powerOnLcdLights(void)
|
||||
{
|
||||
return MCU_writeReg(MCU_REG_LCDs, 1<<5 | 1<<3); // bit3 = lower screen, bit5 = upper
|
||||
}
|
||||
|
||||
static inline bool MCU_setPowerLedState(PwLedState state)
|
||||
{
|
||||
return MCU_writeReg(MCU_REG_POWER_LED, state);
|
||||
}
|
||||
|
||||
static inline bool MCU_getRTCTime(u8 *rtc)
|
||||
{
|
||||
if(!rtc) return true;
|
||||
|
||||
return MCU_readRegBuf(MCU_REG_RTC_TIME, rtc, 8);
|
||||
}
|
||||
|
||||
static inline u8 MCU_getSystemModel(void)
|
||||
{
|
||||
u8 buf[10];
|
||||
|
||||
if(!MCU_readRegBuf(MCU_REG_RAW_STATE, buf, sizeof(buf))) return 0xFF;
|
||||
|
||||
return buf[9];
|
||||
}
|
||||
|
||||
static inline u8 MCU_getHidHeld(void)
|
||||
{
|
||||
u8 data[19];
|
||||
|
||||
if(!MCU_readRegBuf(MCU_REG_RAW_STATE, data, sizeof(data))) return 0xFF;
|
||||
|
||||
return data[18];
|
||||
}
|
||||
|
|
|
@ -22,23 +22,23 @@
|
|||
#include "types.h"
|
||||
|
||||
|
||||
#define SCREEN_TOP (1)
|
||||
#define SCREEN_SUB (0)
|
||||
#define SCREEN_TOP (0u)
|
||||
#define SCREEN_BOT (1u)
|
||||
|
||||
#define SCREEN_WIDTH_TOP (400)
|
||||
#define SCREEN_HEIGHT_TOP (240)
|
||||
#define SCREEN_WIDTH_TOP (400u)
|
||||
#define SCREEN_HEIGHT_TOP (240u)
|
||||
#define SCREEN_SIZE_TOP (SCREEN_WIDTH_TOP * SCREEN_HEIGHT_TOP * 2)
|
||||
#define SCREEN_WIDTH_SUB (320)
|
||||
#define SCREEN_HEIGHT_SUB (240)
|
||||
#define SCREEN_SIZE_SUB (SCREEN_WIDTH_SUB * SCREEN_HEIGHT_SUB * 2)
|
||||
#define SCREEN_WIDTH_BOT (320u)
|
||||
#define SCREEN_HEIGHT_BOT (240u)
|
||||
#define SCREEN_SIZE_BOT (SCREEN_WIDTH_BOT * SCREEN_HEIGHT_BOT * 2)
|
||||
|
||||
#define FRAMEBUF_TOP_A_1 (VRAM_BASE)
|
||||
#define FRAMEBUF_SUB_A_1 (FRAMEBUF_TOP_A_1 + SCREEN_SIZE_TOP)
|
||||
#define FRAMEBUF_TOP_A_2 (VRAM_BASE + 0x100000)
|
||||
#define FRAMEBUF_SUB_A_2 (FRAMEBUF_TOP_A_2 + SCREEN_SIZE_TOP)
|
||||
#define FRAMEBUF_TOP_A_1 ((void*)VRAM_BASE)
|
||||
#define FRAMEBUF_BOT_A_1 ((void*)FRAMEBUF_TOP_A_1 + SCREEN_SIZE_TOP)
|
||||
#define FRAMEBUF_TOP_A_2 ((void*)VRAM_BASE + 0x100000)
|
||||
#define FRAMEBUF_BOT_A_2 ((void*)FRAMEBUF_TOP_A_2 + SCREEN_SIZE_TOP)
|
||||
|
||||
#define RENDERBUF_TOP (VRAM_BASE + 0x200000 - SCREEN_SIZE_TOP - SCREEN_SIZE_SUB)
|
||||
#define RENDERBUF_SUB (VRAM_BASE + 0x200000 - SCREEN_SIZE_SUB)
|
||||
#define RENDERBUF_TOP ((void*)VRAM_BASE + 0x200000 - SCREEN_SIZE_TOP - SCREEN_SIZE_BOT)
|
||||
#define RENDERBUF_BOT ((void*)VRAM_BASE + 0x200000 - SCREEN_SIZE_BOT)
|
||||
|
||||
#define DEFAULT_BRIGHTNESS (0x30)
|
||||
|
||||
|
@ -66,9 +66,9 @@ void GFX_setBrightness(u32 top, u32 sub);
|
|||
void* GFX_getFramebuffer(u8 screen);
|
||||
void GFX_swapFramebufs(void);
|
||||
void GFX_waitForEvent(GfxEvent event, bool discard);
|
||||
void GFX_init(bool clearScreens);
|
||||
void GFX_enterLowPowerState(void);
|
||||
void GFX_returnFromLowPowerState(void);
|
||||
void GFX_init(void);
|
||||
//void GFX_enterLowPowerState(void);
|
||||
//void GFX_returnFromLowPowerState(void);
|
||||
void GFX_deinit(bool keepLcdsOn);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -526,12 +526,12 @@ PrintConsole* consoleInit(int screen, PrintConsole* console, bool clear) {
|
|||
|
||||
console->consoleInitialised = 1;
|
||||
|
||||
if(screen==1) {
|
||||
if(screen==0) {
|
||||
console->frameBuffer = (u16*)RENDERBUF_TOP;
|
||||
console->consoleWidth = 66;
|
||||
console->windowWidth = 66;
|
||||
}
|
||||
else console->frameBuffer = (u16*)RENDERBUF_SUB;
|
||||
else console->frameBuffer = (u16*)RENDERBUF_BOT;
|
||||
|
||||
|
||||
if(clear) consoleCls('2');
|
||||
|
|
|
@ -36,10 +36,10 @@ noreturn void panic()
|
|||
{
|
||||
enterCriticalSection();
|
||||
|
||||
consoleInit(SCREEN_SUB, NULL, false);
|
||||
consoleInit(SCREEN_BOT, NULL, false);
|
||||
ee_printf("\x1b[41m\x1b[0J\x1b[15C****PANIC!!!****\n");
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)GFX_getFramebuffer(SCREEN_TOP),
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB);
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT);
|
||||
GFX_swapFramebufs();
|
||||
|
||||
//PXI_sendPanicCmd(IPC_CMD9_PANIC);
|
||||
|
@ -50,7 +50,7 @@ noreturn void panic()
|
|||
hidScanInput();
|
||||
} while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
|
||||
MCU_triggerPowerOff();
|
||||
MCU_powerOffSys();
|
||||
while(1) __wfi();
|
||||
}
|
||||
|
||||
|
@ -58,11 +58,11 @@ noreturn void panicMsg(const char *msg)
|
|||
{
|
||||
enterCriticalSection();
|
||||
|
||||
consoleInit(SCREEN_SUB, NULL, false);
|
||||
consoleInit(SCREEN_BOT, NULL, false);
|
||||
ee_printf("\x1b[41m\x1b[0J\x1b[15C****PANIC!!!****\n\n");
|
||||
ee_printf("\nERROR MESSAGE:\n%s\n", msg);
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)GFX_getFramebuffer(SCREEN_TOP),
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB);
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT);
|
||||
GFX_swapFramebufs();
|
||||
|
||||
//PXI_sendPanicCmd(IPC_CMD9_PANIC);
|
||||
|
@ -73,7 +73,7 @@ noreturn void panicMsg(const char *msg)
|
|||
hidScanInput();
|
||||
} while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
|
||||
MCU_triggerPowerOff();
|
||||
MCU_powerOffSys();
|
||||
while(1) __wfi();
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ noreturn void guruMeditation(u8 type, const u32 *excStack)
|
|||
if(prevHash != debugHash)
|
||||
codeChanged = true;*/
|
||||
|
||||
consoleInit(SCREEN_SUB, NULL, false);
|
||||
consoleInit(SCREEN_BOT, NULL, false);
|
||||
|
||||
if(excStack[16] & 0x20) instSize = 2; // Processor was in Thumb mode?
|
||||
if(type == 2) realPc = excStack[15] - (instSize * 2); // Data abort
|
||||
|
@ -131,7 +131,7 @@ noreturn void guruMeditation(u8 type, const u32 *excStack)
|
|||
|
||||
//if(codeChanged) ee_printf("Attention: RO section data changed!!");
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)GFX_getFramebuffer(SCREEN_TOP),
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB);
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT);
|
||||
GFX_swapFramebufs();
|
||||
|
||||
//PXI_sendPanicCmd(IPC_CMD9_EXCEPTION);
|
||||
|
@ -142,7 +142,7 @@ noreturn void guruMeditation(u8 type, const u32 *excStack)
|
|||
hidScanInput();
|
||||
} while(!(hidKeysDown() & (KEY_A | KEY_B | KEY_X | KEY_Y)));
|
||||
|
||||
MCU_triggerPowerOff();
|
||||
MCU_powerOffSys();
|
||||
while(1) __wfi();
|
||||
}
|
||||
|
||||
|
|
|
@ -85,103 +85,97 @@
|
|||
#define REG_GX_PPF_TC_OUTDIM *((vu32*)(GX_REGS_BASE + 0x0C28)) // Texture copy output width and gap in 16 byte units.
|
||||
|
||||
|
||||
static u32 activeFb = 0;
|
||||
static bool eventTable[6] = {false};
|
||||
static struct
|
||||
{
|
||||
u16 lcdIds; // Bits 0-7 top screen, 8-15 bottom screen.
|
||||
bool lcdIdsRead;
|
||||
bool events[6];
|
||||
u32 activeFb;
|
||||
void *framebufs[2][4]; // A1, A2, B1, B2
|
||||
u32 formats[2]; // Top, bottom
|
||||
} g_gfxState =
|
||||
{
|
||||
0,
|
||||
false,
|
||||
{false, false, false, false, false, false},
|
||||
0,
|
||||
{
|
||||
{FRAMEBUF_TOP_A_1, FRAMEBUF_TOP_A_2, FRAMEBUF_TOP_A_1, FRAMEBUF_TOP_A_2},
|
||||
{FRAMEBUF_BOT_A_1, FRAMEBUF_BOT_A_2, FRAMEBUF_BOT_A_1, FRAMEBUF_BOT_A_2}
|
||||
},
|
||||
{8<<16 | 3<<8 | 1<<6 | 0<<4 | 3, 8<<16 | 3<<8 | 0<<6 | 0<<4 | 3}
|
||||
};
|
||||
|
||||
|
||||
|
||||
static u8 fmt2PixSize(u32 format)
|
||||
{
|
||||
u8 size;
|
||||
|
||||
switch(format & 7u)
|
||||
{
|
||||
// Pretend RGBA8 doesn't exist because it makes no sense for framebuffers.
|
||||
//case 0: // RGBA8888
|
||||
// size = 4;
|
||||
// break;
|
||||
case 1: // RGBA8880
|
||||
size = 3;
|
||||
break;
|
||||
default: // 2 = RGBA5650, 3 = RGBA5551, 4 = RGBA4444
|
||||
size = 2;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void gfxSetupFramebuf(u8 lcd)
|
||||
{
|
||||
if(lcd > 1) return;
|
||||
|
||||
static const u32 framebufCfgs[2][25] =
|
||||
static const u32 framebufCfgs[2][24] =
|
||||
{
|
||||
{
|
||||
// 0-0x4C
|
||||
450,
|
||||
209,
|
||||
449,
|
||||
449,
|
||||
0,
|
||||
207,
|
||||
209,
|
||||
453<<16 | 449,
|
||||
1<<16 | 0,
|
||||
413,
|
||||
2,
|
||||
402,
|
||||
402,
|
||||
402,
|
||||
1,
|
||||
2,
|
||||
406<<16 | 402,
|
||||
0,
|
||||
0<<4 | 0,
|
||||
0<<16 | 0xFF<<8 | 0,
|
||||
450, 209, 449, 449, 0, 207, 209, 453<<16 | 449,
|
||||
1<<16 | 0, 413, 2, 402, 402, 402, 1, 2,
|
||||
406<<16 | 402, 0, 0<<4 | 0, 0<<16 | 0xFF<<8 | 0,
|
||||
// 0x5C-0x64
|
||||
SCREEN_WIDTH_TOP<<16 | SCREEN_HEIGHT_TOP, // Width and height
|
||||
400<<16 | 240, // Width and height
|
||||
449<<16 | 209,
|
||||
402<<16 | 2,
|
||||
// 0x90
|
||||
SCREEN_HEIGHT_TOP * 2, // Stride (no gap)
|
||||
// 0x9C
|
||||
0<<16 | 0
|
||||
},
|
||||
{
|
||||
// 0-0x4C
|
||||
450,
|
||||
209,
|
||||
449,
|
||||
449,
|
||||
205,
|
||||
207,
|
||||
209,
|
||||
453<<16 | 449,
|
||||
1<<16 | 0,
|
||||
413,
|
||||
82,
|
||||
402,
|
||||
402,
|
||||
79,
|
||||
80,
|
||||
82,
|
||||
408<<16 | 404,
|
||||
0,
|
||||
1<<4 | 1,
|
||||
0<<16 | 0<<8 | 0xFF,
|
||||
450, 209, 449, 449, 205, 207, 209, 453<<16 | 449,
|
||||
1<<16 | 0, 413, 82, 402, 402, 79, 80, 82,
|
||||
408<<16 | 404, 0, 1<<4 | 1, 0<<16 | 0<<8 | 0xFF,
|
||||
// 0x5C-0x64
|
||||
SCREEN_WIDTH_SUB<<16 | SCREEN_HEIGHT_SUB, // Width and height
|
||||
320<<16 | 240, // Width and height
|
||||
449<<16 | 209,
|
||||
402<<16 | 82,
|
||||
// 0x90
|
||||
SCREEN_HEIGHT_SUB * 2, // Stride (no gap)
|
||||
// 0x9C
|
||||
0<<16 | 0
|
||||
}
|
||||
};
|
||||
|
||||
const u32 *const cfg = framebufCfgs[lcd];
|
||||
vu32 *regs;
|
||||
if(lcd == 0) regs = (vu32*)0x10400400;
|
||||
else regs = (vu32*)0x10400500;
|
||||
vu32 *const regs = (vu32*)(GX_REGS_BASE + 0x400 + (0x100u * lcd));
|
||||
|
||||
iomemcpy(regs, cfg, 0x50); // 0-0x4C
|
||||
iomemcpy(regs + 23, &cfg[20], 0xC); // 0x5C-0x64
|
||||
regs[36] = cfg[23]; // 0x90
|
||||
regs[39] = cfg[24]; // 0x9C
|
||||
const u32 format = g_gfxState.formats[lcd];
|
||||
iomemcpy(regs, cfg, 0x50); // 0-0x4C
|
||||
iomemcpy(regs + 23, &cfg[20], 0xC); // 0x5C-0x64
|
||||
regs[36] = 240u * fmt2PixSize(format); // 0x90 stride without gap.
|
||||
regs[39] = cfg[23]; // 0x9C
|
||||
|
||||
|
||||
static const u32 addrAndFmt[2][3] =
|
||||
{
|
||||
{FRAMEBUF_TOP_A_1, FRAMEBUF_TOP_A_2, 8<<16 | 3<<8 | 1<<6 | 0<<4 | 3},
|
||||
{FRAMEBUF_SUB_A_1, FRAMEBUF_SUB_A_2, 8<<16 | 3<<8 | 0<<6 | 0<<4 | 3}
|
||||
};
|
||||
// 0x68, 0x6C, 0x94, 0x98 and 0x70
|
||||
regs[26] = addrAndFmt[lcd][0]; // Framebuffer A first address.
|
||||
regs[27] = addrAndFmt[lcd][1]; // Framebuffer A second address.
|
||||
regs[37] = addrAndFmt[lcd][0]; // Framebuffer B first address.
|
||||
regs[38] = addrAndFmt[lcd][1]; // Framebuffer B second address.
|
||||
regs[28] = addrAndFmt[lcd][2]; // Format GL_RGB5_A1_OES
|
||||
regs[26] = (u32)g_gfxState.framebufs[lcd][0]; // Framebuffer A first address.
|
||||
regs[27] = (u32)g_gfxState.framebufs[lcd][1]; // Framebuffer A second address.
|
||||
regs[37] = (u32)g_gfxState.framebufs[lcd][2]; // Framebuffer B first address.
|
||||
regs[38] = (u32)g_gfxState.framebufs[lcd][3]; // Framebuffer B second address.
|
||||
regs[28] = format; // Format
|
||||
|
||||
|
||||
regs[32] = 0; // Gamma table index 0.
|
||||
|
@ -245,52 +239,73 @@ void GFX_setBrightness(u32 top, u32 sub)
|
|||
|
||||
void* GFX_getFramebuffer(u8 screen)
|
||||
{
|
||||
static void *const framebufTable[2][2] =
|
||||
{
|
||||
{(void*)FRAMEBUF_SUB_A_2, (void*)FRAMEBUF_SUB_A_1},
|
||||
{(void*)FRAMEBUF_TOP_A_2, (void*)FRAMEBUF_TOP_A_1}
|
||||
};
|
||||
|
||||
return framebufTable[screen][activeFb];
|
||||
return g_gfxState.framebufs[screen][g_gfxState.activeFb ^ 1u];
|
||||
}
|
||||
|
||||
void GFX_swapFramebufs(void)
|
||||
{
|
||||
activeFb ^= 1u;
|
||||
u32 fb = g_gfxState.activeFb;
|
||||
fb ^= 1u;
|
||||
g_gfxState.activeFb = fb;
|
||||
|
||||
const u32 tmp = 0x70000u | activeFb; // Acknowledge IRQs?
|
||||
*((vu32*)0x10400478) = tmp;
|
||||
*((vu32*)0x10400578) = tmp;
|
||||
fb |= 0x70000u; // Acknowledge IRQs.
|
||||
*((vu32*)0x10400478) = fb;
|
||||
*((vu32*)0x10400578) = fb;
|
||||
}
|
||||
|
||||
static void gfxIrqHandler(u32 intSource)
|
||||
{
|
||||
atomic_store_explicit(&eventTable[intSource - IRQ_PSC0], true, memory_order_relaxed);
|
||||
bool *const events = g_gfxState.events;
|
||||
|
||||
atomic_store_explicit(&events[intSource - IRQ_PSC0], true, memory_order_relaxed);
|
||||
}
|
||||
|
||||
void GFX_waitForEvent(GfxEvent event, bool discard)
|
||||
{
|
||||
if(discard) atomic_store_explicit(&eventTable[event], false, memory_order_relaxed);
|
||||
while(!atomic_load_explicit(&eventTable[event], memory_order_relaxed)) __wfe();
|
||||
atomic_store_explicit(&eventTable[event], false, memory_order_relaxed);
|
||||
bool *const events = g_gfxState.events;
|
||||
|
||||
if(discard) atomic_store_explicit(&events[event], false, memory_order_relaxed);
|
||||
while(!atomic_load_explicit(&events[event], memory_order_relaxed)) __wfe();
|
||||
atomic_store_explicit(&events[event], false, memory_order_relaxed);
|
||||
}
|
||||
|
||||
static u16 getLcdIds(void)
|
||||
{
|
||||
u16 ids;
|
||||
|
||||
if(!g_gfxState.lcdIdsRead)
|
||||
{
|
||||
g_gfxState.lcdIdsRead = true;
|
||||
|
||||
u16 top, bot;
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x40, 0xFF);
|
||||
I2C_readRegBuf(I2C_DEV_LCD0, 0x40, (u8*)&top, 2);
|
||||
I2C_writeReg(I2C_DEV_LCD1, 0x40, 0xFF);
|
||||
I2C_readRegBuf(I2C_DEV_LCD1, 0x40, (u8*)&bot, 2);
|
||||
|
||||
ids = top>>8;
|
||||
ids |= bot & 0xFF00u;
|
||||
g_gfxState.lcdIds = ids;
|
||||
}
|
||||
else ids = g_gfxState.lcdIds;
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
static void resetLcdsMaybe(void)
|
||||
{
|
||||
u16 top, bot;
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x40, 0xFF);
|
||||
I2C_readRegBuf(I2C_DEV_LCD0, 0x40, (u8*)&top, 2);
|
||||
I2C_writeReg(I2C_DEV_LCD1, 0x40, 0xFF);
|
||||
I2C_readRegBuf(I2C_DEV_LCD1, 0x40, (u8*)&bot, 2);
|
||||
const u16 ids = getLcdIds();
|
||||
|
||||
if(top>>8) I2C_writeReg(I2C_DEV_LCD0, 0xFE, 0xAA);
|
||||
// Top screen
|
||||
if(ids & 0xFFu) I2C_writeReg(I2C_DEV_LCD0, 0xFE, 0xAA);
|
||||
else
|
||||
{
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x11, 0x10);
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x50, 1);
|
||||
}
|
||||
|
||||
if(bot>>8) I2C_writeReg(I2C_DEV_LCD1, 0xFE, 0xAA);
|
||||
// Bottom screen
|
||||
if(ids>>8) I2C_writeReg(I2C_DEV_LCD1, 0xFE, 0xAA);
|
||||
else I2C_writeReg(I2C_DEV_LCD1, 0x11, 0x10);
|
||||
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x60, 0);
|
||||
|
@ -301,13 +316,9 @@ static void resetLcdsMaybe(void)
|
|||
|
||||
static void waitLcdsReady(void)
|
||||
{
|
||||
u16 top, bot;
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x40, 0xFF);
|
||||
I2C_readRegBuf(I2C_DEV_LCD0, 0x40, (u8*)&top, 2);
|
||||
I2C_writeReg(I2C_DEV_LCD1, 0x40, 0xFF);
|
||||
I2C_readRegBuf(I2C_DEV_LCD1, 0x40, (u8*)&bot, 2);
|
||||
const u16 ids = getLcdIds();
|
||||
|
||||
if((top>>8) == 0 || (bot>>8) == 0) // Unknown LCD?
|
||||
if((ids & 0xFFu) == 0 || (ids>>8) == 0) // Unknown LCD?
|
||||
{
|
||||
TIMER_sleepMs(150);
|
||||
}
|
||||
|
@ -316,6 +327,7 @@ static void waitLcdsReady(void)
|
|||
u32 i = 0;
|
||||
do
|
||||
{
|
||||
u16 top, bot;
|
||||
I2C_writeReg(I2C_DEV_LCD0, 0x40, 0x62);
|
||||
I2C_readRegBuf(I2C_DEV_LCD0, 0x40, (u8*)&top, 2);
|
||||
I2C_writeReg(I2C_DEV_LCD1, 0x40, 0x62);
|
||||
|
@ -329,87 +341,7 @@ static void waitLcdsReady(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*void GFX_init(bool clearScreens)
|
||||
{
|
||||
if(REG_PDN_GPU_CNT == 0x1007F) GFX_deinit(false);
|
||||
|
||||
// Reset
|
||||
REG_PDN_GPU_CNT = 0x10000;
|
||||
wait(12);
|
||||
REG_PDN_GPU_CNT = 0x1007F;
|
||||
REG_GX_GPU_CLK = 0x100; // 0x70100 on GPU init.
|
||||
REG_GX_PSC_UNK = 0;
|
||||
|
||||
// LCD framebuffer setup.
|
||||
gfxSetupFramebuf(0);
|
||||
gfxSetupFramebuf(1);
|
||||
// Bit 0 next framebuffer, bit 4 current framebuffer?, bit 8 reset FIFO?,
|
||||
// bit 16 ack HBlank IRQ, bit 17 ack VBlank IRQ, bit 18 ack error IRQ?
|
||||
*((vu32*)0x10400478) = 0x70100; // Framebuffer select 0.
|
||||
*((vu32*)0x10400578) = 0x70100; // Framebuffer select 0.
|
||||
*((vu32*)0x10400474) = 0x10700;
|
||||
*((vu32*)0x10400574) = 0x10700;
|
||||
|
||||
// LCD reg setup.
|
||||
REG_LCD_FILL_TOP = 1u<<24; // Force blackscreen
|
||||
REG_LCD_FILL_BOT = 1u<<24; // Force blackscreen
|
||||
*((vu32*)0x10202000) = 0;
|
||||
*((vu32*)0x10202004) = 0xA390A39;
|
||||
*((vu32*)0x10202014) = 0;
|
||||
*((vu32*)0x1020200C) = 0x10001;
|
||||
|
||||
// Register IRQ handlers.
|
||||
IRQ_registerHandler(IRQ_PSC0, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerHandler(IRQ_PSC1, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerHandler(IRQ_PDC0, 14, 0, true, gfxIrqHandler);
|
||||
IRQ_registerHandler(IRQ_PPF, 14, 0, true, gfxIrqHandler);
|
||||
//IRQ_registerHandler(IRQ_P3D, 14, 0, true, gfxIrqHandler);
|
||||
|
||||
// Backlight related stuff.
|
||||
if((REG_LCD_LIGHT_PWM_TOP & 1u<<16) == 0)
|
||||
{
|
||||
*((vu32*)0x10202240) = 64;
|
||||
*((vu32*)0x10202200) &= ~1u;
|
||||
REG_LCD_LIGHT_PWM_TOP &= ~0x20000u;
|
||||
}
|
||||
if((REG_LCD_LIGHT_PWM_BOT & 1u<<16) == 0)
|
||||
{
|
||||
*((vu32*)0x10202A40) = 64;
|
||||
*((vu32*)0x10202A00) &= ~1u;
|
||||
REG_LCD_LIGHT_PWM_BOT &= ~0x20000u;
|
||||
}
|
||||
|
||||
GFX_setBrightness(DEFAULT_BRIGHTNESS, DEFAULT_BRIGHTNESS);
|
||||
*((vu32*)0x10202014) = 1;
|
||||
*((vu32*)0x1020200C) = 0;
|
||||
|
||||
MCU_powerOnLCDs(); // Power on LCDs.
|
||||
if(clearScreens)
|
||||
{
|
||||
// Warning. The GPU mem fill races against the console.
|
||||
GX_memoryFill((u64*)FRAMEBUF_TOP_A_1, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB, 0,
|
||||
(u64*)FRAMEBUF_TOP_A_2, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC1, true);
|
||||
GX_memoryFill((u64*)RENDERBUF_TOP, 1u<<9, SCREEN_SIZE_TOP, 0, (u64*)RENDERBUF_SUB, 1u<<9, SCREEN_SIZE_SUB, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC0, true);
|
||||
|
||||
// The transfer engine is (sometimes) borked on screen init.
|
||||
// Doing a dummy texture copy fixes it.
|
||||
// TODO: Proper fix.
|
||||
//GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)RENDERBUF_SUB, 0, 16);
|
||||
}
|
||||
waitLcdsReady();
|
||||
// Bit 0 enable? bit 8 HBlank IRQ enable, bit 9 VBlank IRQ enable, bit 10 error IRQ enable?, bit 16 output enable?
|
||||
*((vu32*)0x10400474) = 0x10501;
|
||||
*((vu32*)0x10400574) = 0x10501;
|
||||
REG_LCD_LIGHT_PWM_TOP = 0x1023E;
|
||||
REG_LCD_LIGHT_PWM_BOT = 0x1023E;
|
||||
MCU_powerOnLcdBacklights();
|
||||
|
||||
REG_LCD_FILL_TOP = 0;
|
||||
REG_LCD_FILL_BOT = 0;
|
||||
}*/
|
||||
void GFX_init(bool clearScreens)
|
||||
void GFX_init(void)
|
||||
{
|
||||
if(REG_PDN_GPU_CNT == 0x1007F) GFX_deinit(false);
|
||||
|
||||
|
@ -458,33 +390,32 @@ void GFX_init(bool clearScreens)
|
|||
TIMER_sleepMs(10);
|
||||
resetLcdsMaybe();
|
||||
MCU_powerOnLCDs(); // Power on LCDs.
|
||||
// Wait for MCU event 25. 24 on poweroff.
|
||||
if(clearScreens) // TODO: Where does this belong?
|
||||
{
|
||||
// Warning. The GPU mem fill races against the console.
|
||||
GX_memoryFill((u64*)FRAMEBUF_TOP_A_1, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB, 0,
|
||||
(u64*)FRAMEBUF_TOP_A_2, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC1, true);
|
||||
GX_memoryFill((u64*)RENDERBUF_TOP, 1u<<9, SCREEN_SIZE_TOP, 0, (u64*)RENDERBUF_SUB, 1u<<9, SCREEN_SIZE_SUB, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC0, true);
|
||||
MCU_waitEvents(0x3Fu<<24); // Wait for MCU event 25. 24 on poweroff.
|
||||
|
||||
GX_memoryFill((u64*)FRAMEBUF_TOP_A_1, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT, 0,
|
||||
(u64*)FRAMEBUF_TOP_A_2, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC1, true);
|
||||
GX_memoryFill((u64*)RENDERBUF_TOP, 1u<<9, SCREEN_SIZE_TOP, 0, (u64*)RENDERBUF_BOT, 1u<<9, SCREEN_SIZE_BOT, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC0, true);
|
||||
|
||||
// The transfer engine is (sometimes) borked on screen init.
|
||||
// Doing a dummy texture copy fixes it.
|
||||
// TODO: Proper fix.
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)RENDERBUF_BOT, 0, 16);
|
||||
|
||||
// The transfer engine is (sometimes) borked on screen init.
|
||||
// Doing a dummy texture copy fixes it.
|
||||
// TODO: Proper fix.
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)RENDERBUF_SUB, 0, 16);
|
||||
}
|
||||
waitLcdsReady();
|
||||
REG_LCD_LIGHT_PWM_TOP = 0x1023E;
|
||||
REG_LCD_LIGHT_PWM_BOT = 0x1023E;
|
||||
MCU_powerOnLcdBacklights();
|
||||
// Wait for MCU event 29 and 27. 28 and 26 on poweroff.
|
||||
MCU_powerOnLcdLights();
|
||||
MCU_waitEvents(0x3Fu<<24); // Wait for MCU event 29 (top) and 27 (bot). 28 and 26 on poweroff.
|
||||
// Weird VBlank wait?
|
||||
|
||||
REG_LCD_FILL_TOP = 0;
|
||||
REG_LCD_FILL_BOT = 0;
|
||||
}
|
||||
|
||||
void GFX_enterLowPowerState(void)
|
||||
// TODO: Sleep mode stuff needs some work.
|
||||
/*void GFX_enterLowPowerState(void)
|
||||
{
|
||||
REG_LCD_FILL_TOP = 1u<<24; // Force blackscreen
|
||||
REG_LCD_FILL_BOT = 1u<<24; // Force blackscreen
|
||||
|
@ -494,28 +425,29 @@ void GFX_enterLowPowerState(void)
|
|||
|
||||
void GFX_returnFromLowPowerState(void)
|
||||
{
|
||||
GFX_init(false);
|
||||
}
|
||||
GFX_init();
|
||||
}*/
|
||||
|
||||
void GFX_deinit(bool keepLcdsOn)
|
||||
{
|
||||
if(keepLcdsOn)
|
||||
{
|
||||
GX_memoryFill((u64*)FRAMEBUF_TOP_A_1, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB + 0x2A300, 0,
|
||||
(u64*)FRAMEBUF_TOP_A_2, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB + 0x2A300, 0);
|
||||
GX_memoryFill((u64*)FRAMEBUF_TOP_A_1, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT + 0x2A300, 0,
|
||||
(u64*)FRAMEBUF_TOP_A_2, 1u<<9, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT + 0x2A300, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC1, true);
|
||||
*((vu32*)(0x10400400+0x70)) = 0x80341; // Format GL_RGB8_OES.
|
||||
*((vu32*)(0x10400400+0x78)) = 0; // Select first framebuffer.
|
||||
*((vu32*)(0x10400400+0x90)) = SCREEN_HEIGHT_TOP * 3; // Stride (no gap).
|
||||
*((vu32*)(0x10400500+0x68)) = FRAMEBUF_SUB_A_1 + 0x17700; // Bottom framebuffer first address.
|
||||
*((vu32*)(0x10400500+0x6C)) = FRAMEBUF_SUB_A_2 + 0x17700; // Bottom framebuffer second address.
|
||||
*((vu32*)(0x10400500+0x70)) = 0x80301; // Format GL_RGB8_OES.
|
||||
*((vu32*)(0x10400500+0x78)) = 0; // Select first framebuffer.
|
||||
*((vu32*)(0x10400500+0x90)) = SCREEN_HEIGHT_SUB * 3; // Stride (no gap).
|
||||
*((vu32*)(0x10400400+0x70)) = 0x80341; // Format GL_RGB8_OES.
|
||||
*((vu32*)(0x10400400+0x78)) = 0; // Select first framebuffer.
|
||||
*((vu32*)(0x10400400+0x90)) = SCREEN_HEIGHT_TOP * 3; // Stride (no gap).
|
||||
*((vu32*)(0x10400500+0x68)) = (u32)FRAMEBUF_BOT_A_1 + 0x17700; // Bottom framebuffer first address.
|
||||
*((vu32*)(0x10400500+0x6C)) = (u32)FRAMEBUF_BOT_A_2 + 0x17700; // Bottom framebuffer second address.
|
||||
*((vu32*)(0x10400500+0x70)) = 0x80301; // Format GL_RGB8_OES.
|
||||
*((vu32*)(0x10400500+0x78)) = 0; // Select first framebuffer.
|
||||
*((vu32*)(0x10400500+0x90)) = SCREEN_HEIGHT_BOT * 3; // Stride (no gap).
|
||||
}
|
||||
else
|
||||
{
|
||||
MCU_powerOffLCDs();
|
||||
MCU_waitEvents(0x3Fu<<24);
|
||||
GFX_setBrightness(0, 0);
|
||||
REG_LCD_LIGHT_PWM_TOP = 0;
|
||||
REG_LCD_LIGHT_PWM_BOT = 0;
|
||||
|
|
|
@ -36,44 +36,32 @@ static u32 kHeld, kDown, kUp;
|
|||
static u32 extraKeys;
|
||||
//TouchPos tPos;
|
||||
//CpadPos cPos;
|
||||
static volatile bool mcuIrq;
|
||||
|
||||
|
||||
|
||||
static void hidIrqHandler(UNUSED u32 intSource);
|
||||
|
||||
void hidInit(void)
|
||||
{
|
||||
kUp = kDown = kHeld = 0;
|
||||
mcuIrq = false;
|
||||
static bool inited = false;
|
||||
if(inited) return;
|
||||
inited = true;
|
||||
|
||||
(void)MCU_readReceivedIrqs();
|
||||
u8 state = MCU_readExternalHwState();
|
||||
kUp = kDown = kHeld = 0;
|
||||
|
||||
MCU_init();
|
||||
u8 state = MCU_getExternalHwState();
|
||||
u32 tmp = ~state<<3 & KEY_SHELL; // Current shell state. Bit is inverted.
|
||||
tmp |= state<<1 & KEY_BAT_CHARGING; // Current battery charging state
|
||||
state = MCU_readHidHeld();
|
||||
state = MCU_getHidHeld();
|
||||
tmp |= ~state<<1 & KEY_HOME; // Current HOME button state
|
||||
extraKeys = tmp;
|
||||
|
||||
IRQ_registerHandler(IRQ_CTR_MCU, 14, 0, true, hidIrqHandler);
|
||||
MCU_setIrqBitmask(0xFFBF3F80u);
|
||||
// Configure GPIO for MCU event IRQs
|
||||
GPIO_config(GPIO_4_MCU, GPIO_INPUT | GPIO_EDGE_FALLING | GPIO_IRQ_ENABLE);
|
||||
|
||||
//CODEC_init();
|
||||
}
|
||||
|
||||
static void hidIrqHandler(UNUSED u32 intSource)
|
||||
static void updateMcuHidState(void)
|
||||
{
|
||||
mcuIrq = true;
|
||||
}
|
||||
|
||||
static void updateMcuIrqState(void)
|
||||
{
|
||||
if(!mcuIrq) return;
|
||||
mcuIrq = false;
|
||||
|
||||
const u32 state = MCU_readReceivedIrqs();
|
||||
const u32 state = MCU_getEvents(0x40C07F);
|
||||
if(state == 0) return;
|
||||
|
||||
u32 tmp = extraKeys;
|
||||
tmp |= state & (KEY_POWER | KEY_POWER_HELD | KEY_HOME); // Power button pressed/held, HOME button pressed
|
||||
|
@ -117,7 +105,7 @@ static void updateMcuIrqState(void)
|
|||
|
||||
void hidScanInput(void)
|
||||
{
|
||||
updateMcuIrqState();
|
||||
updateMcuHidState();
|
||||
|
||||
const u32 kOld = kHeld;
|
||||
kHeld = /*rawCodec2Hid() |*/ REG_HID_PAD;
|
||||
|
|
|
@ -16,125 +16,94 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on code from https://github.com/smealum/ctrulib
|
||||
*/
|
||||
|
||||
#include "mem_map.h"
|
||||
#include "arm11/hardware/i2c.h"
|
||||
#include <stdatomic.h>
|
||||
#include "arm11/hardware/mcu.h"
|
||||
#include "arm11/hardware/i2c.h"
|
||||
#include "arm11/hardware/interrupt.h"
|
||||
#include "arm11/hardware/gpio.h"
|
||||
|
||||
|
||||
enum McuRegisters {
|
||||
RegBattery = 0x0Bu,
|
||||
RegExHW = 0x0Fu,
|
||||
RegPower = 0x20u,
|
||||
RegLCDs = 0x22u,
|
||||
RegWifiLED = 0x2Au,
|
||||
RegCamLED = 0x2Bu,
|
||||
Reg3DLED = 0x2Cu,
|
||||
RegRTC = 0x30u,
|
||||
RegSysModel = 0x7Fu
|
||||
};
|
||||
static bool g_mcuIrq = false;
|
||||
static u32 g_events = 0;
|
||||
|
||||
|
||||
|
||||
static void mcuIrqHandler(UNUSED u32 intSource);
|
||||
|
||||
void MCU_init(void)
|
||||
{
|
||||
static bool inited = false;
|
||||
if(inited) return;
|
||||
inited = true;
|
||||
|
||||
I2C_init();
|
||||
|
||||
atomic_store_explicit(&g_mcuIrq, true, memory_order_relaxed);
|
||||
(void)MCU_getEvents(0xFFFFFFFFu);
|
||||
|
||||
MCU_setEventMask(0xC0BF3F80);
|
||||
// Configure GPIO for MCU event IRQs
|
||||
GPIO_config(GPIO_4_MCU, GPIO_INPUT | GPIO_EDGE_FALLING | GPIO_IRQ_ENABLE);
|
||||
IRQ_registerHandler(IRQ_CTR_MCU, 14, 0, true, mcuIrqHandler);
|
||||
}
|
||||
|
||||
void MCU_disableLEDs(void)
|
||||
static void mcuIrqHandler(UNUSED u32 intSource)
|
||||
{
|
||||
// disable wifi LED
|
||||
I2C_writeReg(I2C_DEV_CTR_MCU, RegWifiLED, 0);
|
||||
|
||||
// disable 3D LED
|
||||
I2C_writeReg(I2C_DEV_CTR_MCU, Reg3DLED, 0);
|
||||
|
||||
// disable camera LED
|
||||
I2C_writeReg(I2C_DEV_CTR_MCU, RegCamLED, 0);
|
||||
g_mcuIrq = true;
|
||||
}
|
||||
|
||||
void MCU_powerOnLCDs(void)
|
||||
bool MCU_setEventMask(u32 mask)
|
||||
{
|
||||
// bit1 = lcd power enable for both screens
|
||||
I2C_writeReg(I2C_DEV_CTR_MCU, RegLCDs, 1<<1);
|
||||
return MCU_writeRegBuf(MCU_REG_EVENT_MASK, (const u8*)&mask, 4);
|
||||
}
|
||||
|
||||
void MCU_powerOffLCDs(void)
|
||||
u32 MCU_getEvents(u32 mask)
|
||||
{
|
||||
// bit0 = lcd power disable for both screens (also disables backlight)
|
||||
I2C_writeReg(I2C_DEV_CTR_MCU, RegLCDs, 1);
|
||||
u32 events = g_events;
|
||||
|
||||
if(atomic_load_explicit(&g_mcuIrq, memory_order_relaxed))
|
||||
{
|
||||
atomic_store_explicit(&g_mcuIrq, false, memory_order_relaxed);
|
||||
|
||||
u32 data;
|
||||
if(!MCU_readRegBuf(MCU_REG_EVENTS, (u8*)&data, 4)) return 0;
|
||||
|
||||
events |= data;
|
||||
}
|
||||
|
||||
g_mcuIrq = events & ~mask;
|
||||
|
||||
return events & mask;
|
||||
}
|
||||
|
||||
void MCU_triggerPowerOff(void)
|
||||
u32 MCU_waitEvents(u32 mask)
|
||||
{
|
||||
I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, RegPower, 1);
|
||||
u32 events;
|
||||
|
||||
while((events = MCU_getEvents(mask)) == 0u)
|
||||
{
|
||||
__wfi();
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
void MCU_triggerReboot(void)
|
||||
u8 MCU_readReg(McuReg reg)
|
||||
{
|
||||
I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, RegPower, 1u << 2);
|
||||
return I2C_readReg(I2C_DEV_CTR_MCU, reg);
|
||||
}
|
||||
|
||||
u8 MCU_readBatteryLevel(void)
|
||||
bool MCU_writeReg(McuReg reg, u8 data)
|
||||
{
|
||||
u8 state;
|
||||
|
||||
if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, RegBattery, &state, 1))
|
||||
return 0;
|
||||
|
||||
return state;
|
||||
return I2C_writeReg(I2C_DEV_CTR_MCU, reg, data);
|
||||
}
|
||||
|
||||
u8 MCU_readExternalHwState(void)
|
||||
bool MCU_readRegBuf(McuReg reg, u8 *out, u32 size)
|
||||
{
|
||||
return I2C_readReg(I2C_DEV_CTR_MCU, RegExHW);
|
||||
return I2C_readRegBuf(I2C_DEV_CTR_MCU, reg, out, size);
|
||||
}
|
||||
|
||||
u8 MCU_readSystemModel(void)
|
||||
bool MCU_writeRegBuf(McuReg reg, const u8 *const in, u32 size)
|
||||
{
|
||||
u8 sysinfo[0x13];
|
||||
|
||||
if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, RegSysModel, sysinfo, sizeof sysinfo))
|
||||
return 0xFF;
|
||||
|
||||
return sysinfo[9];
|
||||
}
|
||||
|
||||
void MCU_readRTC(void *rtc)
|
||||
{
|
||||
if(!rtc) return;
|
||||
|
||||
I2C_readRegBuf(I2C_DEV_CTR_MCU, RegRTC, rtc, 8);
|
||||
}
|
||||
|
||||
u32 MCU_readReceivedIrqs(void)
|
||||
{
|
||||
u32 data;
|
||||
if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, 0x10, (u8*)&data, 4)) return 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
bool MCU_setIrqBitmask(u32 mask)
|
||||
{
|
||||
return I2C_writeRegBuf(I2C_DEV_CTR_MCU, 0x18, (const u8*)&mask, 4);
|
||||
}
|
||||
|
||||
u8 MCU_readHidHeld(void)
|
||||
{
|
||||
u8 data[19];
|
||||
if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, 0x7F, data, sizeof(data))) return 0xFF;
|
||||
return data[18];
|
||||
}
|
||||
|
||||
bool MCU_powerOnLcdBacklights(void)
|
||||
{
|
||||
return I2C_writeReg(I2C_DEV_CTR_MCU, 0x22, 1<<5 | 1<<3); // bit3 = lower screen, bit5 = upper
|
||||
}
|
||||
|
||||
bool MCU_setPowerLedState(PwLedState state)
|
||||
{
|
||||
return I2C_writeReg(I2C_DEV_CTR_MCU, 0x29, state);
|
||||
return I2C_writeRegBuf(I2C_DEV_CTR_MCU, reg, in, size);
|
||||
}
|
||||
|
|
|
@ -31,14 +31,14 @@
|
|||
|
||||
void clearScreens(void)
|
||||
{
|
||||
GX_memoryFill((u64*)RENDERBUF_TOP, 1u<<9, SCREEN_SIZE_TOP, 0, (u64*)RENDERBUF_SUB, 1u<<9, SCREEN_SIZE_SUB, 0);
|
||||
GX_memoryFill((u64*)RENDERBUF_TOP, 1u<<9, SCREEN_SIZE_TOP, 0, (u64*)RENDERBUF_BOT, 1u<<9, SCREEN_SIZE_BOT, 0);
|
||||
GFX_waitForEvent(GFX_EVENT_PSC0, true);
|
||||
}
|
||||
|
||||
void updateScreens(void)
|
||||
{
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)GFX_getFramebuffer(SCREEN_TOP),
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB);
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT);
|
||||
GFX_waitForEvent(GFX_EVENT_PPF, true); // Texture copy
|
||||
GFX_swapFramebufs();
|
||||
GFX_waitForEvent(GFX_EVENT_PDC0, true); // VBlank
|
||||
|
@ -46,7 +46,7 @@ void updateScreens(void)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
GFX_init(true);
|
||||
GFX_init();
|
||||
consoleInit(SCREEN_TOP, NULL, false);
|
||||
CODEC_init();
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ noreturn void power_off(void)
|
|||
{
|
||||
power_safe_halt();
|
||||
|
||||
MCU_triggerPowerOff();
|
||||
MCU_powerOffSys();
|
||||
|
||||
__cpsid(aif);
|
||||
while(1) __wfi();
|
||||
|
@ -52,7 +52,7 @@ noreturn void power_reboot(void)
|
|||
{
|
||||
power_safe_halt();
|
||||
|
||||
MCU_triggerReboot();
|
||||
MCU_rebootSys();
|
||||
|
||||
__cpsid(aif);
|
||||
while(1) __wfi();
|
||||
|
|
|
@ -39,8 +39,8 @@ noreturn void panic()
|
|||
while(1)
|
||||
{
|
||||
const u32 color = RGB8_to_565(0, 255, 0)<<16 | RGB8_to_565(0, 255, 0);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_1, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_2, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_1, color, SCREEN_SIZE_BOT);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_2, color, SCREEN_SIZE_BOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ noreturn void panicMsg(UNUSED const char *msg)
|
|||
while(1)
|
||||
{
|
||||
const u32 color = RGB8_to_565(0, 255, 0)<<16 | RGB8_to_565(0, 255, 0);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_1, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_2, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_1, color, SCREEN_SIZE_BOT);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_2, color, SCREEN_SIZE_BOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@ noreturn void guruMeditation(UNUSED u8 type, UNUSED const u32 *excStack)
|
|||
while(1)
|
||||
{
|
||||
const u32 color = RGB8_to_565(255, 0, 0)<<16 | RGB8_to_565(255, 0, 0);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_1, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_2, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_1, color, SCREEN_SIZE_BOT);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_2, color, SCREEN_SIZE_BOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ noreturn void __fb_assert(const char *const str, u32 line)
|
|||
#elif ARM11
|
||||
ee_printf("Assertion failed: %s:%" PRIu32, str, line);
|
||||
GX_textureCopy((u64*)RENDERBUF_TOP, 0, (u64*)GFX_getFramebuffer(SCREEN_TOP),
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_SUB);
|
||||
0, SCREEN_SIZE_TOP + SCREEN_SIZE_BOT);
|
||||
GFX_swapFramebufs();
|
||||
//PXI_sendCmd(IPC_CMD9_PANIC, NULL, 0);
|
||||
#endif
|
||||
|
@ -52,8 +52,8 @@ noreturn void __fb_assert(const char *const str, u32 line)
|
|||
{
|
||||
#ifdef ARM9
|
||||
const u32 color = RGB8_to_565(0, 0, 255)<<16 | RGB8_to_565(0, 0, 255);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_1, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_SUB_A_2, color, SCREEN_SIZE_SUB);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_1, color, SCREEN_SIZE_BOT);
|
||||
NDMA_fill((u32*)FRAMEBUF_BOT_A_2, color, SCREEN_SIZE_BOT);
|
||||
#elif ARM11
|
||||
__wfi();
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue