Precise Timing, Root Counter ?

General help for the PSY-Q SDK, such as setting the SDK up, compiling correctly, linking and debugging
Post Reply
Orion_
Verified
Legendary Programmer
Legendary Programmer
Posts: 240
Joined: Aug 13, 2012
I am a: Programmer
PlayStation Model: Net Yaroze
Location: France
Contact:

Precise Timing, Root Counter ?

Post by Orion_ » August 8th, 2013, 2:44 am

I need to have a precise timer on Playstation (for example to measure things)
For the moment I use the VSync, so each VSync I increment a counter and depending on 50 or 60Hz I compute my timer.
But this is not very accurate, so I searched for a timer on psx, and the only thing I found was the Root counter.
Unfortunately the documentation on this is a bit confusing, and I really don't understand how to use the Psy-Q functions in order to get it working.
can someone help me on this ? thank you
Retro game development on Playstation and other consoles http://orionsoft.free.fr/

User avatar
Shendo
Verified
C Programming Expert
C Programming Expert
Posts: 250
Joined: Mar 21, 2012
I am a: Programmer
Motto: Never settle
PlayStation Model: SCPH-7502
Discord: ShendoXT
Location: Croatia, EU

Post by Shendo » August 8th, 2013, 11:39 am

There are four root counters available on PlayStation: DotClock, HBlank, SyClock/8, VBlank.

VBlank is used by many BIOS functions (Pad access, Memory Card access, etc...)
so beside using VSync() function it's not advised to mess with it.

However, other counters are freely available to the programmer, you just have to set them up properly.

First add this macros to your project:

Code: Select all

#include <libapi.h>

#define RCntCNT0		0xf2000000   	/*display pixel*/
#define RCntCNT1		0xf2000001   	/*horizontal sync*/
#define RCntCNT2		0xf2000002   	/*one-eighth of system clock*/
#define RCntCNT3		0xf2000003   	/*vertical sync target value fixed to 1*/

#define RCntIntr		0x1000				/*Interrupt mode*/
Now, let's set up HBlank counter:

Code: Select all

int CounterMaxValue = 240; /*This means this counter resets every 240 HBlanks*/

SetRCnt(RCntCNT1, CounterMaxValue, RCntIntr);
StartRCnt(RCntCNT1);
To read the value of the counter call this function:

Code: Select all

GetRCnt(RCntCNT1);
So to measure something you could do something like this:

Code: Select all

ResetRCnt(RCntCNT1);
OldValue = GetRCnt(RCntCNT1);
DoSomething();
NewValue = GetRCnt(RCntCNT1) - OldValue;

printf("It took %d HBlanks to execute DoSomething", NewValue);
There is also a possibility of using events for running a certain function when counter reaches zero.
Dev console: SCPH-7502, FreePSXBoot, CH340 serial cable.

Orion_
Verified
Legendary Programmer
Legendary Programmer
Posts: 240
Joined: Aug 13, 2012
I am a: Programmer
PlayStation Model: Net Yaroze
Location: France
Contact:

Post by Orion_ » August 9th, 2013, 7:52 pm

Thank you for detailed explanation.
it seems that the rootcounter are small and reseting fast, I guess it will not be compatible with my system.
I have a timer reference function which gives me a timer reference, so I can do difference between two time even if several minutes passed. I guess I would need an interrupt function who would increment a value each time a rootcounter reset or something like that.
Retro game development on Playstation and other consoles http://orionsoft.free.fr/

alexfree
Verified
Extreme PSXDEV User
Extreme PSXDEV User
Posts: 221
Joined: Oct 21, 2021
I am a: Programmer, Gamer
PlayStation Model: SCPH-1000
Location: USA
Contact:

Post by alexfree » November 16th, 2022, 8:34 pm

Shendo wrote: August 8th, 2013, 11:39 am There are four root counters available on PlayStation: DotClock, HBlank, SyClock/8, VBlank.

VBlank is used by many BIOS functions (Pad access, Memory Card access, etc...)
so beside using VSync() function it's not advised to mess with it.

However, other counters are freely available to the programmer, you just have to set them up properly.

First add this macros to your project:

Code: Select all

#include <libapi.h>

#define RCntCNT0		0xf2000000   	/*display pixel*/
#define RCntCNT1		0xf2000001   	/*horizontal sync*/
#define RCntCNT2		0xf2000002   	/*one-eighth of system clock*/
#define RCntCNT3		0xf2000003   	/*vertical sync target value fixed to 1*/

#define RCntIntr		0x1000				/*Interrupt mode*/
Now, let's set up HBlank counter:

Code: Select all

int CounterMaxValue = 240; /*This means this counter resets every 240 HBlanks*/

SetRCnt(RCntCNT1, CounterMaxValue, RCntIntr);
StartRCnt(RCntCNT1);
To read the value of the counter call this function:

Code: Select all

GetRCnt(RCntCNT1);
So to measure something you could do something like this:

Code: Select all

ResetRCnt(RCntCNT1);
OldValue = GetRCnt(RCntCNT1);
DoSomething();
NewValue = GetRCnt(RCntCNT1) - OldValue;

printf("It took %d HBlanks to execute DoSomething", NewValue);
There is also a possibility of using events for running a certain function when counter reaches zero.
I had this same exact problem and Googled it, was not expecting such a detailed and simple explanation. Thanks.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests