#152849 - ghuldan - Fri Mar 21, 2008 5:33 pm
Hi everyone,
Here is my code to calculate fps :
Code: |
#define TICK ( (TIMER1_DATA >> 5) + (TIMER2_DATA << 11) )
TIMER1_DATA = 0;
TIMER2_DATA = 0;
TIMER1_CR = TIMER_DIV_1024 | TIMER_ENABLE;
TIMER2_CR = TIMER_CASCADE | TIMER_ENABLE;
while (1) {
u32 start = TICK;
... doing stuff
PA_WaitForVBL();
u32 end = TICK - start;
PA_OutputText(1, 0, 22, "FPS: %d ", 1000 / end);
} |
Putting it that way, i got 58fps while desmume running at 7fps
Putting PA_WaitForVBL(); after PA_OutputText, and i got 250fps while desmume running at 7fps.
What does it means actually ? Is desmume so slow ? Or am i wrong in my FPS calculation ? If not, would it means that code would run at my FPS on real hardware ?
Thanks a lot.
#152851 - Lazy1 - Fri Mar 21, 2008 5:50 pm
Easier way to calculate frames per second...
Global variables:
Code: |
int FramesDrawn = 0;
int VBlanks = 0;
int FPS = 0;
|
VBlank handler:
Code: |
void IRQVBlank( void ) {
if ( VBlanks == 60 ) {
FPS = FramesDrawn;
FramesDrawn = 0;
VBlanks = 0;
}
VBlanks++;
}
|
Main loop:
Code: |
while ( 1 ) {
// Do some stuff
FramesDrawn++;
}
|
Then your current framerate will be in the FPS variable and you don't need to use timers.
I just typed this in the reply box so it might not work right off the bat.
#152852 - simonjhall - Fri Mar 21, 2008 6:34 pm
Huh. Never thought of doing it like that! I normally time how long one frame takes and then average that over a few frames (eg 20-100).
_________________
Big thanks to everyone who donated for Quake2
#152896 - Programix - Sat Mar 22, 2008 9:27 am
If you are using PAlib, you can use PA_RTC.FPS for getting fps ^^
_________________
My blog
#152933 - HyperHacker - Sat Mar 22, 2008 11:29 pm
VBlanks may as well be a static local variable of the VBlank handler.
_________________
I'm a PSP hacker now, but I still <3 DS.
#153124 - ghuldan - Tue Mar 25, 2008 10:47 am
Hi everyone, thanks for for your help.
1) PA_RTC.FPS return 0 for me ...
2) I tried the IRQVBlank thing but it's staying at 0;
Tried to put VBlanks in global and static local ...
One thing i wonder, how do the program "knows" it must launch IRQVBlank after each VBlank ? Is there anything else to set set up to make it work ? I'm not good with Interrupts.
In addition, i heard libfat shouldnt be used with interrupt ... I'm using libfat and will always use it ... so ?
I understand my calculation is wrong to be used with libfat because of the timer dependance but, this FPS calculation is not required to be that much sharp for me, i know when libfat is called when i manipulate my homebrew and i know when it is not used. So initially i wanted to know if, with this calculation would mean my program would run at my FPS on real hardware ?
#153126 - Programix - Tue Mar 25, 2008 12:06 pm
PA_RTC.FPS works only if you put PA_InitVBL() on start of the program and if you are calling PA_WaitForVBL() every frame. Hope it helps :)
_________________
My blog
#153133 - silent_code - Tue Mar 25, 2008 1:54 pm
it dosn't "know". interrupts are fired by the hw and are "interrupting" normal code execution to handle the interrupt event. ;^)
btw.: software interrupts also exist (in general).
#153134 - ghuldan - Tue Mar 25, 2008 1:58 pm
but how can it "knows" to launch void IRQVBlank(void) each VBlank here and not another procedure ? Is there anything to set in registeries before ?
#153135 - ghuldan - Tue Mar 25, 2008 1:59 pm
Programix wrote: |
PA_RTC.FPS works only if you put PA_InitVBL() on start of the program and if you are calling PA_WaitForVBL() every frame. Hope it helps :) |
Both are in my code ... and it does not work for me.
#153137 - silent_code - Tue Mar 25, 2008 2:06 pm
ah!
you need to set it up!
irqInit();
irqSet(IRQ_VBLANK, drawOnIRQ);
irqEnable(IRQ_VBLANK);
happy coding! :^)
#153138 - ghuldan - Tue Mar 25, 2008 2:44 pm
I ran some test :
Code: |
void IRQVBlank() {
FPS++;
}
irqInit();
irqSet(IRQ_VBLANK, IRQVBlank);
irqEnable(IRQ_VBLANK);
|
then i write FPS each loop.
It appears IRQVBlank() is called only one time ...
I use libfat
#153140 - simonjhall - Tue Mar 25, 2008 2:48 pm
Try putting a printf in the vblank handler instead.
Also, make sure the variable that you're incrementing in the handler is volatile. If the main loop that you check the variable in is small enough then there's a chance that the value won't be updated in the local copy.
_________________
Big thanks to everyone who donated for Quake2
#153149 - Lazy1 - Tue Mar 25, 2008 6:50 pm
This raises an interesting point actually, if newlib is not interrupt safe then really you should not be calling printf in the vblank handler.
One way around that would be to make a printf wrapper which disables the vblank interrupt, calls printf and re-enables vblank.
Sounds kinda hacky though, what is the proper way to handle this anyway?
#153153 - simonjhall - Tue Mar 25, 2008 7:24 pm
If you never use newlib stuff in your main thread and only ever use it in interrupt handlers you should be alright ;-)
Though seriously, the interrupt handlers aren't nested and only the main thread can be paused mid-execution so this should be fine, right?
But I realise that in more complex programs it may not feasible to do nothing in your main thread*, so I always stick locks around juicy stuff like file access.
*no, I don't want some dull example of how old games were written entirely in their hblank interrupt
_________________
Big thanks to everyone who donated for Quake2