Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PDN_sleep and PDN_wakeup #2

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

EvansJahja
Copy link

Supersedes #1

This change is mostly to support open_agb_firm sleep functionality.

Waking up from sleep is achieved by binding IRQ_PDN to a handler and disabling wake_enable and confirming by writing to wake_reason.

GFX_waitForVBlank0();
GFX_waitForVBlank0();
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused why you added new functions here. GFX_sleep() and GFX_sleepAwake() were supposed to be the functions to call to bring the GFX driver into and out of sleep state.

The problem that PDN stuff is hardcoded in this driver also remains.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for your comment. My apologies, I think when playing around, I was trying to first get the old function from the old commit to work, and rebase. I think I forgot to remove these 2 functions. I intend to use the GFX_sleep and GFX_sleepAwake.

d7a3066

Let me try to address your other comments...

gx->pdc1.swap = state->swap>>1;
gx->pdc0.cnt = PDC_CNT_OUT_EN | GFX_PDC0_IRQS | PDC_CNT_EN;
gx->pdc1.cnt = PDC_CNT_OUT_EN | GFX_PDC1_IRQS | PDC_CNT_EN;
displayControllerInit(GFX_TOP_2D);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the warning i had in the comments. If we fully reinitialize PDC here the current display mode is not restored. For example 2D, 3D or wide mode.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reverted this change. Turns out I made a mistake in the open agb firm changes which errorneously made me think this was required.

waitForEvent(pdnWakeEvent);
getPdnRegs()->wake_enable = 0;
getPdnRegs()->wake_reason = PDN_WAKE_SHELL_OPENED;
unbindInterruptEvent(IRQ_PDN);
Copy link
Owner

@profi200 profi200 Apr 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me summarize what i know about hardware sleep mode:

HOS first notifies the sysmodules about sleep so they can prepare sleep mode. This is for example the GFX_sleep() function that's being called. Other ones to call are CODEC_deinit() (poorly documented, sleep is basically the same as deinit). And the power LED is set to the sleep mode animation via the MCU.
After all the hardware we don't need in sleep mode is in sleep mode Kernel11 does check this bit:
https://github.com/profi200/libn3ds/blob/master/include/arm11/drivers/pdn.h#L71

If it's set it does extra steps to disable VRAM banks and clock via:
https://github.com/profi200/libn3ds/blob/master/include/arm11/drivers/pdn.h#L103

Then it disables FCRAM clock. In GBA mode we already did this but just for reference:
https://github.com/profi200/libn3ds/blob/master/include/arm11/drivers/pdn.h#L114
https://github.com/profi200/libn3ds/blob/master/source/arm11/drivers/lgy11.c#L59

Then finally comes the sleep mode part. This bit is set and the CPU has to enter wait for interrupt state somewhere. This would likely be the kernel idle thread if nothing has to be done:
https://github.com/profi200/libn3ds/blob/master/include/arm11/drivers/pdn.h#L70

I think PDN wake reasons are managed externall by some sysmodule. Not sure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have modified this part again.

I have moved the PDN related function calls from gfx.c to pdn.c, so disabling GPU clock and VRAM now is handled by pdn.c

I haven't implemented disabling FCRAM clock mostly because I'm not familiar with it, and my motivation is mostly on the GBA side, but please let me know if here's any reference that I can follow, especially for re-enabling it after waking up.

After testing with the sleep mode again, it seems that calling _wfi is enough to ensure that it stays asleep until next interrupt, which is when the lid is opened again. I haven't found other source of interrupt other than opening the lid when it's sleeping, so I'm guessing it would work.
As for PDN wake reasons, from my testing, it doesn't seem to do anything other than flags for the developer. i.e., I could change it to PDN_WAKE_TOUCHPEN_DOWN and it will still behave the same.

I have reverted the previous use of bindEvent on IRQ_PDN, since it seems there are different expectations of what should happen during the ISR of sleep mode.

GFX_enterLowPowerState and GFX_returnFromLowPowerState was
introduced because the branch was based on old commmit
PDN_sleep now blocks. Also, controlling pdn is now
done in pdn.c instead of gfx.c
@EvansJahja EvansJahja requested a review from profi200 April 27, 2024 07:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants