#include "common.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ExitMode.h" #include "Arm7State.h" #include "tusb.h" #include "usb_descriptors.h" #include "microphone.h" rtos_mutex_t gCardMutex; static rtos_thread_t sUsbThread; static u32 sUsbThreadStack[512]; static rtos_event_t sVBlankEvent; static ExitMode sExitMode; static Arm7State sState; static volatile u8 sMcuIrqFlag = false; static void vblankIrq(u32 irqMask) { rtos_signalEvent(&sVBlankEvent); } static void mcuIrq(u32 irq2Mask) { sMcuIrqFlag = true; } static void checkMcuIrq(void) { // mcu only exists in DSi mode if (isDSiMode()) { // check and ack the flag atomically if (mem_swapByte(false, &sMcuIrqFlag)) { // check the irq mask u32 irqMask = mcu_getIrqMask(); if (irqMask & MCU_IRQ_RESET) { // power button was released sExitMode = ExitMode::Reset; sState = Arm7State::ExitRequested; } else if (irqMask & MCU_IRQ_POWER_OFF) { // power button was held long to trigger a power off sExitMode = ExitMode::PowerOff; sState = Arm7State::ExitRequested; } } } } static void initializeVBlankIrq() { rtos_createEvent(&sVBlankEvent); rtos_setIrqFunc(RTOS_IRQ_VBLANK, vblankIrq); rtos_enableIrqMask(RTOS_IRQ_VBLANK); gfx_setVBlankIrqEnabled(true); } static void usbThreadMain(void* arg) { while (true) { tud_task(); } } static void initializeArm7() { rtos_initIrq(); rtos_startMainThread(); ipc_initFifoSystem(); // clear sound registers dmaFillWords(0, (void*)0x04000400, 0x100); pmic_setAmplifierEnable(true); sys_setSoundPower(true); readUserSettings(); pmic_setPowerLedBlink(PMIC_CONTROL_POWER_LED_BLINK_NONE); sio_setGpioSiIrq(false); sio_setGpioMode(RCNT0_L_MODE_GPIO); rtc_init(); snd_setMasterVolume(0); snd_setMasterEnable(false); initializeVBlankIrq(); if (isDSiMode()) { rtos_setIrq2Func(RTOS_IRQ2_MCU, mcuIrq); rtos_enableIrq2Mask(RTOS_IRQ2_MCU); mic_initialize(); } pmic_setTopBacklightEnable(false); pmic_setBottomBacklightEnable(false); tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO }; tusb_init(0, &dev_init); rtos_createThread(&sUsbThread, 3, usbThreadMain, NULL, sUsbThreadStack, sizeof(sUsbThreadStack)); rtos_wakeupThread(&sUsbThread); ipc_setArm7SyncBits(7); } static void updateArm7IdleState() { checkMcuIrq(); if (sState == Arm7State::ExitRequested) { snd_setMasterVolume(0); // mute sound } } static bool performExit(ExitMode exitMode) { switch (exitMode) { case ExitMode::Reset: { mcu_setWarmBootFlag(true); mcu_hardReset(); break; } case ExitMode::PowerOff: { pmic_shutdown(); break; } } while (true); // wait infinitely for exit } static void updateArm7ExitRequestedState() { performExit(sExitMode); } static void updateArm7() { switch (sState) { case Arm7State::Idle: { updateArm7IdleState(); break; } case Arm7State::ExitRequested: { updateArm7ExitRequestedState(); break; } } } int main() { sState = Arm7State::Idle; initializeArm7(); while (true) { rtos_waitEvent(&sVBlankEvent, true, true); updateArm7(); } return 0; }