diff --git a/arm11/source/main.c b/arm11/source/main.c index 7c186cc8f..48fecbc56 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -123,8 +123,8 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs) for(u32 i = 0; i < 256; i++) *(vu32 *)0x10400584 = 0x10101 * i; - //*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill - //*(vu32 *)0x10202A04 = 0x00000000; + *(vu32 *)0x10202204 = 0x00000000; //unset LCD fill + *(vu32 *)0x10202A04 = 0x00000000; } static void setupFramebuffers(struct fb *fbs) diff --git a/arm9/linker.ld b/arm9/linker.ld index 4cde67bb3..4365b8c38 100644 --- a/arm9/linker.ld +++ b/arm9/linker.ld @@ -45,19 +45,16 @@ SECTIONS chainloader.o(.text*) i2c.o(.text*) - mcu.o(.text*) arm9_exception_handlers.o(.text*) *(.arm9_exception_handlers.rodata*) chainloader.o(.rodata*) i2c.o(.rodata*) - mcu.o(.rodata*) arm9_exception_handlers.o(.rodata*) *(.arm9_exception_handlers.data*) chainloader.o(.data*) i2c.o(.data*) - mcu.o(.data*) arm9_exception_handlers.o(.data*) . = ALIGN(32); } >itcm AT>main :itcm @@ -70,7 +67,6 @@ SECTIONS *(.arm9_exception_handlers.bss*) chainloader.o(.bss* COMMON) i2c.o(.bss* COMMON) - mcu.o(.bss* COMMON) arm9_exception_handlers.o(.bss* COMMON) . = ALIGN(32); PROVIDE (__itcm_end__ = ABSOLUTE(.)); diff --git a/arm9/source/arm9_exception_handlers.c b/arm9/source/arm9_exception_handlers.c index 2cca61a3a..d7fbed38a 100644 --- a/arm9/source/arm9_exception_handlers.c +++ b/arm9/source/arm9_exception_handlers.c @@ -25,7 +25,8 @@ */ #include "arm9_exception_handlers.h" -#include "mcu.h" +#include "i2c.h" +#include "screen.h" #define FINAL_BUFFER 0x25000000 @@ -102,9 +103,10 @@ void __attribute__((noreturn)) arm9ExceptionHandlerMain(u32 *registerDump, u32 t //Copy header (actually optimized by the compiler) *(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader; - mcuPowerBacklightsOff(); + if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); //Shutdown LCD ((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed - mcuReboot(); + I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot + while(true); } diff --git a/arm9/source/exceptions.c b/arm9/source/exceptions.c index ae8f9f967..07106840e 100644 --- a/arm9/source/exceptions.c +++ b/arm9/source/exceptions.c @@ -200,5 +200,5 @@ void detectAndProcessExceptionDumps(void) exit: memset((void *)dumpHeader, 0, dumpHeader->totalSize); - powerOff(); + mcuPowerOff(); } diff --git a/arm9/source/firm.c b/arm9/source/firm.c index 210aaa5cc..ce44d7e43 100755 --- a/arm9/source/firm.c +++ b/arm9/source/firm.c @@ -37,7 +37,6 @@ #include "screen.h" #include "fmt.h" #include "chainloader.h" -#include "mcu.h" static Firm *firm = (Firm *)0x20001000; @@ -565,7 +564,6 @@ u32 patch1x2xNativeAndSafeFirm(void) void launchFirm(int argc, char **argv) { - mcuFinalize(); prepareArm11ForFirmlaunch(); chainload(argc, argv, firm); } diff --git a/arm9/source/gpio.h b/arm9/source/gpio.h deleted file mode 100644 index 4e5dd5fd9..000000000 --- a/arm9/source/gpio.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2021 Aurora Wright, TuxSH -* -* 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 . -* -* Additional Terms 7.b and 7.c of GPLv3 apply to this file: -* * Requiring preservation of specified reasonable legal notices or -* author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -* * Prohibiting misrepresentation of the origin of that material, -* or requiring that modified versions of such material be marked in -* reasonable ways as different from the original version. -*/ - -#pragma once - -#include "types.h" - -typedef struct GpioRegisters { - u8 gpio1_data; - u8 _0x001[0x010 - 0x001]; - - u8 gpio2_data; - u8 gpio2_dir; - u8 gpio2_intcfg; - u8 gpio2_inten; - u16 gpio2_data2; - u8 _0x016[0x020 - 0x016]; - - u16 gpio3_data; - u16 gpio3_dir; - u16 gpio3_intcfg; - u16 gpio3_inten; - u16 gpio3_data2; - u8 _0x02a[0x100 - 0x02A]; -} GpioRegisters; - -typedef enum GpioDirection { - GPIO_DIR_INPUT = 0, - GPIO_DIR_OUTPUT = 1, -} GpioDirection; - -typedef enum GpioInterruptConfig { - GPIO_INTCFG_FALLING_EDGE = 0, - GPIO_INTCFG_RISING_EDGE = 1, -} GpioInterruptConfig; - -#define GPIO_PIN(bank, idx) (((bank) << 4) | ((idx) & 0xF)) -#define BANK_OF(pin) ((pin) >> 4) -#define BIT_OF(pin) ((pin) & 0xF) - -typedef enum GpioPin { - // GPIO1 - GPIO_DEBUG_BUTTON = GPIO_PIN(1, 0), // active-low - GPIO_TOUCH_SCREEN = GPIO_PIN(1, 1), // active-low, 0 when the touch screen is pressed - GPIO_SHELL_CLOSED = GPIO_PIN(1, 2), - - // GPIO2 - GPIO_HEADPHONES_INSERTED = GPIO_PIN(2, 0), - GPIO_TWL_DEPOP = GPIO_PIN(2, 1), // active-low - - // GPIO2 (DATA2) - GPIO_WIFI_MODE = GPIO_PIN(4, 0), // 0 is CTR, 1 is MP (DS WiFi) - - // GPIO3 - GPIO_CSTICK_INT = GPIO_PIN(3, 0), - GPIO_IRDA_INT = GPIO_PIN(3, 1), // active-low - GPIO_GYRO_INT = GPIO_PIN(3, 2), - GPIO_CSTICK_STOP = GPIO_PIN(3, 3), // output - GPIO_IRDA_TXRC = GPIO_PIN(3, 4), // output - GPIO_IRDA_RXD = GPIO_PIN(3, 5), // active-low - GPIO_NFC_OUT1 = GPIO_PIN(3, 6), // output - GPIO_NFC_OUT2 = GPIO_PIN(3, 7), // output - GPIO_HEADPHONES_BUTTON = GPIO_PIN(3, 8), // active-low ("half-inserted") - GPIO_MCU_INT = GPIO_PIN(3, 9), - GPIO_NFC_INT = GPIO_PIN(3, 10), - GPIO_QTM_OUT = GPIO_PIN(3, 11), // output - - // GPIO3 (DATA2) - GPIO_WIFI_ENABLED = GPIO_PIN(5, 0), -} GpioPin; - -static volatile GpioRegisters *const GPIO = (volatile GpioRegisters *)0x10147000; - -static inline bool gpioRead(GpioPin pin) -{ - u32 bank = BANK_OF(pin); - u32 bit = BIT_OF(pin); - - switch (bank) { - case 1: - return (GPIO->gpio1_data & BIT(bit)) != 0; - case 2: - return (GPIO->gpio2_data & BIT(bit)) != 0; - case 3: - return (GPIO->gpio3_data & BIT(bit)) != 0; - case 4: - return (GPIO->gpio2_data2 & BIT(bit)) != 0; - case 5: - return (GPIO->gpio3_data2 & BIT(bit)) != 0; - - default: - return false; - } -} - -static inline void gpioWrite(GpioPin pin, bool val) -{ - u32 bank = BANK_OF(pin); - u32 bit = BIT_OF(pin); - - u32 valMask = (val ? 1 : 0) << bit; - u32 tmp; - - switch (bank) { - case 1: - tmp = GPIO->gpio1_data & ~BIT(bit); - GPIO->gpio1_data = (u8)(tmp | valMask); - break; - case 2: - tmp = GPIO->gpio2_data & ~BIT(bit); - GPIO->gpio2_data = (u8)(tmp | valMask); - break; - case 3: - tmp = GPIO->gpio3_data & ~BIT(bit); - GPIO->gpio3_data = (u16)(tmp | valMask); - break; - case 4: - tmp = GPIO->gpio2_data2 & ~BIT(bit); - GPIO->gpio2_data2 = (u16)(tmp | valMask); - break; - case 5: - tmp = GPIO->gpio3_data2 & ~BIT(bit); - GPIO->gpio3_data2 = (u16)(tmp | valMask); - break; - - default: - break; - } -} - -static inline void gpioSetDirection(GpioPin pin, GpioDirection direction) -{ - u32 bank = BANK_OF(pin); - u32 bit = BIT_OF(pin); - - u32 valMask = (direction == GPIO_DIR_OUTPUT ? 1 : 0) << bit; - u32 tmp; - - switch (bank) { - case 2: - tmp = GPIO->gpio2_dir & ~BIT(bit); - GPIO->gpio2_dir = (u8)(tmp | valMask); - break; - case 3: - tmp = GPIO->gpio3_dir & ~BIT(bit); - GPIO->gpio3_dir = (u16)(tmp | valMask); - break; - - default: - break; - } -} - -static inline void gpioConfigureInterrupt(GpioPin pin, GpioInterruptConfig cfg) -{ - u32 bank = BANK_OF(pin); - u32 bit = BIT_OF(pin); - - u32 valMask = (cfg == GPIO_INTCFG_RISING_EDGE ? 1 : 0) << bit; - u32 tmp; - - switch (bank) { - case 2: - tmp = GPIO->gpio2_intcfg & ~BIT(bit); - GPIO->gpio2_intcfg = (u8)(tmp | valMask); - break; - case 3: - tmp = GPIO->gpio3_data & ~BIT(bit); - GPIO->gpio3_intcfg = (u16)(tmp | valMask); - break; - - default: - break; - } -} - -static inline void gpioSetInterruptEnabled(GpioPin pin, bool enabled) -{ - u32 bank = BANK_OF(pin); - u32 bit = BIT_OF(pin); - - u32 valMask = (enabled ? 1 : 0) << bit; - u32 tmp; - - switch (bank) { - case 2: - tmp = GPIO->gpio2_inten & ~BIT(bit); - GPIO->gpio2_inten = (u8)(tmp | valMask); - break; - case 3: - tmp = GPIO->gpio3_inten & ~BIT(bit); - GPIO->gpio3_inten = (u16)(tmp | valMask); - break; - - default: - break; - } -} - -#undef GPIO_PIN -#undef BIT_OF -#undef BANK_OF diff --git a/arm9/source/i2c.c b/arm9/source/i2c.c index 20b60b302..d2d37e8bb 100644 --- a/arm9/source/i2c.c +++ b/arm9/source/i2c.c @@ -16,10 +16,7 @@ * along with this program. If not, see . */ -// Modified 2021 TuxSH - #include -#include #include "types.h" #include "i2c.h" #include "utils.h" @@ -161,11 +158,11 @@ static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, I2cRegs *co else return false; } -bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, void *out, u32 size) +bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size) { const u8 busId = i2cDevTable[devId].busId; I2cRegs *const regs = i2cGetBusRegsBase(busId); - u8 *out8 = (u8 *)out; + if(!i2cStartTransfer(devId, regAddr, true, regs)) return false; @@ -173,28 +170,27 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, void *out, u32 size) { regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK; i2cWaitBusy(regs); - *out8++ = regs->REG_I2C_DATA; + *out++ = regs->REG_I2C_DATA; } regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP; i2cWaitBusy(regs); - *out8 = regs->REG_I2C_DATA; // Last byte + *out = regs->REG_I2C_DATA; // Last byte return true; } -bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const void *in, u32 size) +bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size) { const u8 busId = i2cDevTable[devId].busId; I2cRegs *const regs = i2cGetBusRegsBase(busId); - const u8 *in8 = (const u8 *)in; if(!i2cStartTransfer(devId, regAddr, false, regs)) return false; while(--size) { - regs->REG_I2C_DATA = *in8++; + regs->REG_I2C_DATA = *in++; regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE; i2cWaitBusy(regs); if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed. @@ -204,7 +200,7 @@ bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const void *in, u32 size) } } - regs->REG_I2C_DATA = *in8; + regs->REG_I2C_DATA = *in; regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP; i2cWaitBusy(regs); if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed. diff --git a/arm9/source/i2c.h b/arm9/source/i2c.h index ce2e9cb83..ea9442250 100644 --- a/arm9/source/i2c.h +++ b/arm9/source/i2c.h @@ -66,7 +66,7 @@ void I2C_init(void); * * @return Returns true on success and false on failure. */ -bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, void *out, u32 size); +bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size); /** * @brief Writes a buffer to a I2C register. @@ -78,7 +78,7 @@ bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, void *out, u32 size); * * @return Returns true on success and false on failure. */ -bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const void *in, u32 size); +bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size); /** * @brief Reads a byte from a I2C register. diff --git a/arm9/source/main.c b/arm9/source/main.c index 7360cecb7..50b66668c 100644 --- a/arm9/source/main.c +++ b/arm9/source/main.c @@ -36,7 +36,7 @@ #include "crypto.h" #include "memory.h" #include "screen.h" -#include "mcu.h" +#include "i2c.h" #include "fatfs/sdmmc/sdmmc.h" extern u8 __itcm_start__[], __itcm_lma__[], __itcm_bss_start__[], __itcm_end__[]; @@ -116,8 +116,7 @@ void main(int argc, char **argv, u32 magicWord) // Set up the additional sections, overwrites argc memcpy(__itcm_start__, __itcm_lma__, __itcm_bss_start__ - __itcm_start__); memset(__itcm_bss_start__, 0, __itcm_end__ - __itcm_bss_start__); - mcuInit(); - + I2C_init(); if(isInvalidLoader) error("Launched using an unsupported loader."); installArm9Handlers(); @@ -142,7 +141,7 @@ void main(int argc, char **argv, u32 magicWord) { while(HID_PAD & NTRBOOT_BUTTONS); loadHomebrewFirm(0); - powerOff(); + mcuPowerOff(); } } else @@ -165,7 +164,7 @@ void main(int argc, char **argv, u32 magicWord) //Determine if this is a firmlaunch boot if(bootType == FIRMLAUNCH) { - if(needConfig == CREATE_CONFIGURATION) powerOff(); + if(needConfig == CREATE_CONFIGURATION) mcuPowerOff(); switch(firmlaunchTidLow & 0xF) { diff --git a/arm9/source/mcu.c b/arm9/source/mcu.c deleted file mode 100644 index f88a4a71d..000000000 --- a/arm9/source/mcu.c +++ /dev/null @@ -1,127 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2021 Aurora Wright, TuxSH -* -* 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 . -* -* Additional Terms 7.b and 7.c of GPLv3 apply to this file: -* * Requiring preservation of specified reasonable legal notices or -* author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -* * Prohibiting misrepresentation of the origin of that material, -* or requiring that modified versions of such material be marked in -* reasonable ways as different from the original version. -*/ - -#include "mcu.h" -#include "i2c.h" -#include "gpio.h" - -static u32 g_pendingMcuInterrupts = 0; - -u32 mcuGetInterruptMask(void) -{ - u32 mask; - I2C_readRegBuf(I2C_DEV_MCU, 0x18, &mask, 4); - return mask; -} - -void mcuSetInterruptMask(u32 mask) -{ - I2C_writeRegBuf(I2C_DEV_MCU, 0x18, &mask, 4); -} - -u32 mcuGetPendingInterrupts(u32 mask) -{ - u32 curMcuInts = 0; - if (gpioRead(GPIO_MCU_INT)) - { - // MCU IRQ pin raised - I2C_readRegBuf(I2C_DEV_MCU, 0x10, &curMcuInts, 4); // this clears the interrupts on the MCU side - - // Add all new MCU interrupts to the pending list - g_pendingMcuInterrupts |= curMcuInts; - } - - // Remove the interrupts we'll return from the pending list - u32 ret = g_pendingMcuInterrupts & mask; - g_pendingMcuInterrupts &= ~mask; - return ret; -} - -void mcuPowerBacklightsOn(void) -{ - // Doesn't matter if they're already on, it should be idempotent on the MCU side - - u32 prevMask = mcuGetInterruptMask(); - u32 pend = 0; - - mcuSetInterruptMask(~MCU_INT_LCD_BL_ON); - mcuGetPendingInterrupts(MCU_INT_LCD_BL_ON) ; // Clear any pending interrupts - I2C_writeReg(I2C_DEV_MCU, 0x22, (u8)(MCU_INT_LCD_BL_ON >> 24)); - - // Wait for LCD and backlights to be on - do - { - pend |= mcuGetPendingInterrupts(MCU_INT_LCD_BL_ON); - } while (pend != MCU_INT_LCD_BL_ON); - - mcuSetInterruptMask(prevMask); -} - -void mcuPowerBacklightsOff(void) -{ - // Doesn't matter if they're already off, it should be idempotent on the MCU side - - u32 prevMask = mcuGetInterruptMask(); - u32 pend = 0; - - mcuSetInterruptMask(~MCU_INT_LCD_BL_OFF); - mcuGetPendingInterrupts(MCU_INT_LCD_BL_OFF) ; // Clear any pending interrupts - I2C_writeReg(I2C_DEV_MCU, 0x22, (u8)(MCU_INT_LCD_BL_OFF >> 24)); - - // Wait for LCD and backlights to be off - do - { - pend |= mcuGetPendingInterrupts(MCU_INT_LCD_BL_OFF); - } while (pend != MCU_INT_LCD_BL_OFF); - - mcuSetInterruptMask(prevMask); -} - -void mcuPowerOff(void) -{ - mcuFinalize(); - I2C_writeReg(I2C_DEV_MCU, 0x20, BIT(0)); - while(true); -} - -void mcuReboot(void) -{ - mcuFinalize(); - I2C_writeReg(I2C_DEV_MCU, 0x20, BIT(2)); - while(true); -} - -void mcuInit(void) -{ - I2C_init(); - mcuSetInterruptMask(~MCU_INT_MASK_FOR_INPUT); -} - -void mcuFinalize(void) -{ - mcuGetPendingInterrupts(0xFFFFFFFF); // purge pending MCU interrupts & internal pending list - mcuSetInterruptMask(~MCU_INT_DEFAULT_MASK); // Reset MCU mask -} diff --git a/arm9/source/mcu.h b/arm9/source/mcu.h deleted file mode 100644 index e26a3a175..000000000 --- a/arm9/source/mcu.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2021 Aurora Wright, TuxSH -* -* 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 . -* -* Additional Terms 7.b and 7.c of GPLv3 apply to this file: -* * Requiring preservation of specified reasonable legal notices or -* author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -* * Prohibiting misrepresentation of the origin of that material, -* or requiring that modified versions of such material be marked in -* reasonable ways as different from the original version. -*/ - -#pragma once - -#include "types.h" - -/* - * Bit13: Battery low (at 10%, 5% and sub-1%) - * Bit7: MCU WDT reset - * Bit6: Shell opened (GPIO1_0 1->0) - * Bit5: Shell closed (GPIO1_0 0->1) - * Bit1: Power button held - * Bit0: Power button pressed - */ -#define MCU_INT_MASK_FOR_INPUT (BIT(13)|BIT(7)|BIT(6)|BIT(5)|BIT(1)|BIT(0)) -#define MCU_INT_LCD_BL_ON (BIT(29)|BIT(27)|BIT(25)) -#define MCU_INT_LCD_BL_OFF (BIT(28)|BIT(26)|BIT(24)) -#define MCU_INT_DEFAULT_MASK 0x0000E7FFu - -u32 mcuGetInterruptMask(void); -void mcuSetInterruptMask(u32 mask); // 1 for each interrupt you want to *disable* (mask) -u32 mcuGetPendingInterrupts(u32 mask); - -void mcuPowerBacklightsOn(void); -void mcuPowerBacklightsOff(void); - -void NORETURN mcuPowerOff(void); -void NORETURN mcuReboot(void); - -void mcuInit(void); -void mcuFinalize(void); diff --git a/arm9/source/pin.c b/arm9/source/pin.c index 50c79665b..a2cf2e2be 100644 --- a/arm9/source/pin.c +++ b/arm9/source/pin.c @@ -198,7 +198,7 @@ bool verifyPin(u32 pinMode) } while(!(pressed & PIN_BUTTONS)); - if(pressed & BUTTON_START) powerOff(); + if(pressed & BUTTON_START) mcuPowerOff(); pressed &= PIN_BUTTONS; diff --git a/arm9/source/screen.c b/arm9/source/screen.c index d6860190d..bb01525be 100644 --- a/arm9/source/screen.c +++ b/arm9/source/screen.c @@ -32,7 +32,8 @@ #include "screen.h" #include "config.h" #include "memory.h" -#include "mcu.h" +#include "i2c.h" +#include "utils.h" bool needToSetupScreens = true; @@ -68,7 +69,6 @@ void prepareArm11ForFirmlaunch(void) void deinitScreens(void) { - mcuPowerBacklightsOff(); if(ARESCREENSINITIALIZED) invokeArm11Function(DEINIT_SCREENS); } @@ -102,20 +102,19 @@ void initScreens(void) memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs)); invokeArm11Function(INIT_SCREENS); - mcuPowerBacklightsOn(); + //Turn on backlight + I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); + wait(5); } else updateBrightness(MULTICONFIG(BRIGHTNESS)); - clearScreens(false); - clearScreens(true); - memcpy((void *)ARM11_PARAMETERS_ADDRESS, fbs, sizeof(fbs)); invokeArm11Function(SETUP_FRAMEBUFFERS); + + clearScreens(true); needToSetupScreens = false; } - else - { - clearScreens(false); - swapFramebuffers(false); - } + + clearScreens(false); + swapFramebuffers(false); } diff --git a/arm9/source/types.h b/arm9/source/types.h index 01517b8c2..e4646bbc4 100644 --- a/arm9/source/types.h +++ b/arm9/source/types.h @@ -49,14 +49,6 @@ typedef volatile s16 vs16; typedef volatile s32 vs32; typedef volatile s64 vs64; -/// Creates a bitmask from a bit number. -#define BIT(n) (1U<<(n)) - -/// Aligns a struct (and other types?) to m, making sure that the size of the struct is a multiple of m. -#define ALIGN(m) __attribute__((aligned(m))) - -#define NORETURN __attribute__((noreturn)) - #include "3dsheaders.h" #define CFG_BOOTENV (*(vu32 *)0x10010000) diff --git a/arm9/source/utils.c b/arm9/source/utils.c index 7089071d5..d789761fe 100644 --- a/arm9/source/utils.c +++ b/arm9/source/utils.c @@ -37,7 +37,6 @@ #include "fmt.h" #include "memory.h" #include "fs.h" -#include "mcu.h" static void startChrono(void) { @@ -66,24 +65,13 @@ static u64 chrono(void) return res; } -void powerOff(void) -{ - if(!needToSetupScreens) clearScreens(false); - - mcuPowerBacklightsOff(); - - // Ensure that all memory transfers have completed and that the data cache has been flushed - flushEntireDCache(); - - mcuPowerOff(); -} - u32 waitInput(bool isMenu) { static u64 dPadDelay = 0ULL; u64 initialValue = 0ULL; u32 key, oldKey = HID_PAD; + bool shouldShellShutdown = bootType != B9SNTR && bootType != NTR; if(isMenu) { @@ -94,34 +82,21 @@ u32 waitInput(bool isMenu) while(true) { - // There are two sources of truth for the shell state: the gpio reg and the MCU - - /* - * Bit13: Battery low (at 10%, 5% and sub-1%) - * Bit7: MCU WDT reset - * Bit6: Shell opened (GPIO1_0 1->0) - * Bit5: Shell closed (GPIO1_0 0->1) - * Bit1: Power button held - * Bit0: Power button pressed - */ - - // Ignore "shell opened", just ack - u32 mcuInts = mcuGetPendingInterrupts(MCU_INT_MASK_FOR_INPUT); - - if (mcuInts & (BIT(7) | BIT(5) | BIT(1) | BIT(0))) - powerOff(); - - if (mcuInts & BIT(13)) - { - u8 battLevelIntPart = I2C_readReg(I2C_DEV_MCU, 0xB); - if (battLevelIntPart == 0) - powerOff(); - } - key = HID_PAD; if(!key) { + if(shouldShellShutdown) + { + u8 shellState = I2C_readReg(I2C_DEV_MCU, 0xF); + wait(5); + if(!(shellState & 2)) mcuPowerOff(); + } + + u8 intStatus = I2C_readReg(I2C_DEV_MCU, 0x10); + wait(5); + if(intStatus & 1) mcuPowerOff(); //Power button pressed + oldKey = 0; dPadDelay = 0; continue; @@ -138,6 +113,20 @@ u32 waitInput(bool isMenu) return key; } +void mcuPowerOff(void) +{ + if(!needToSetupScreens) clearScreens(false); + + //Shutdown LCD + if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); + + //Ensure that all memory transfers have completed and that the data cache has been flushed + flushEntireDCache(); + + I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0); + while(true); +} + void wait(u64 amount) { startChrono(); @@ -162,5 +151,6 @@ void error(const char *fmt, ...) drawString(true, 10, posY + 2 * SPACING_Y, COLOR_WHITE, "Press any button to shutdown"); waitInput(false); - powerOff(); + + mcuPowerOff(); } diff --git a/arm9/source/utils.h b/arm9/source/utils.h index 862310271..83bf7ea50 100644 --- a/arm9/source/utils.h +++ b/arm9/source/utils.h @@ -39,7 +39,7 @@ #define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) #define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) -void NORETURN powerOff(void); u32 waitInput(bool isMenu); +void mcuPowerOff(void); void wait(u64 amount); -void NORETURN error(const char *fmt, ...); +void error(const char *fmt, ...);