GP32 How Does The Kernel Wait For Vsync?


RichTW

Still Fresh
Joined
Nov 2, 2004
Messages
3
Hi all,

I was wondering if anyone has looked at the kernel code and can explain exactly what it's doing when it waits for VSync.

There is a kernel disassembly here:
http://www.cs.helsinki.fi/u/jikorhon/conde.../doc/fw157e.txt

...I think the relevant code is at 0x1bf0 - the official SDK hooks its GpSurfaceFlip() function into this code (or a RAM copy of it):

Code:
00001C64: E10F5000	mrs	r5, CPSR
00001C68: E38540C0	orr	r4, r5, #192; this will turn off interrupts if written to CPSR
00001C6C: E5963000	ldr	r3, [r6]  ; r6 is LCDCON1 register
00001C70: E1A03923	mov	r3, r3, lsr #18  ; get current scanline
00001C74: E3530000	cmp	r3, #0; is it 0?
00001C78: C12FF004	msrgt	CPSR_fsxc, r4  ; if >0, turn off interrupts
00001C7C: E5963000	ldr	r3, [r6] ; read from LCDCON1 again
00001C80: E1A03923	mov	r3, r3, lsr #18 ; get current scanline (again??)
00001C84: E3530000	cmp	r3, #0; is it 0?
00001C88: CA000001	bgt	00001c94 ; if >0, branch out of this polling loop
00001C8C: E12FF005	msr	CPSR_fsxc, r5 ; otherwise reenable interrupts
00001C90: EAFFFFF5	b	00001c6c ; and reloop
00001C94: E2864014	add	r4, r6, #20; Actually set the framebuffer address
00001C98: E8840006	stmia	r4, {r1, r2}  ; (interrupts are reenabled a bit later)
(please excuse the naff formatting)

So I just don't get why it would read the scanline number twice in quick succession, and yet not appear to be waiting for it to change? Am I missing some detail to do with this turning off of interrupts?

Mr Mirko's SDK is brilliant and clear, and a fantastic reference, but I was just trying to discover whether it was necessary for his VSync routine to be idling for as long as it does:

Code:
static
void gp_waitVsync() {
  // The LINECNT is downcount from 319 to 0
  while ((rLCDCON1 >> 18) !=   1);
  // changeing Framebuffer
  while ((rLCDCON1 >> 18) != 319);
  // Framebuffer is changed
}

Is there some reason why this...
Code:
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) == 0);
...isn't sufficient?

Cheers,
Rich (trying to squeeze every last bit out of the CPU!)
 
Hi all,

I was wondering if anyone has looked at the kernel code and can explain exactly what it's doing when it waits for VSync.

There is a kernel disassembly here:
http://www.cs.helsinki.fi/u/jikorhon/conde.../doc/fw157e.txt

...I think the relevant code is at 0x1bf0 - the official SDK hooks its GpSurfaceFlip() function into this code (or a RAM copy of it):

Code:
00001C64: E10F5000 mrs r5, CPSR
00001C68: E38540C0 orr r4, r5, #192; this will turn off interrupts if written to CPSR
00001C6C: E5963000 ldr r3, [r6]  ; r6 is LCDCON1 register
00001C70: E1A03923 mov r3, r3, lsr #18  ; get current scanline
00001C74: E3530000 cmp r3, #0; is it 0?
00001C78: C12FF004 msrgt CPSR_fsxc, r4  ; if >0, turn off interrupts
00001C7C: E5963000 ldr r3, [r6]; read from LCDCON1 again
00001C80: E1A03923 mov r3, r3, lsr #18; get current scanline (again??)
00001C84: E3530000 cmp r3, #0; is it 0?
00001C88: CA000001 bgt 00001c94; if >0, branch out of this polling loop
00001C8C: E12FF005 msr CPSR_fsxc, r5; otherwise reenable interrupts
00001C90: EAFFFFF5 b 00001c6c; and reloop
00001C94: E2864014 add r4, r6, #20; Actually set the framebuffer address
00001C98: E8840006 stmia r4, {r1, r2}  ; (interrupts are reenabled a bit later)
(please excuse the naff formatting)

So I just don't get why it would read the scanline number twice in quick succession, and yet not appear to be waiting for it to change? Am I missing some detail to do with this turning off of interrupts?

Mr Mirko's SDK is brilliant and clear, and a fantastic reference, but I was just trying to discover whether it was necessary for his VSync routine to be idling for as long as it does:

Code:
static
void gp_waitVsync() {
  // The LINECNT is downcount from 319 to 0
  while ((rLCDCON1 >> 18) !=   1);
  // changeing Framebuffer
  while ((rLCDCON1 >> 18) != 319);
  // Framebuffer is changed
}

Is there some reason why this...
Code:
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) == 0);
...isn't sufficient?

Cheers,
Rich (trying to squeeze every last bit out of the CPU!)


LINECNT = rLCDCON1 >> 18

LINECNT is a number between 319 and 0.
if LINECNT is 0, and changing to 319, the new settings in the Frambeuffer registers will be active.

So if you change the Framebuffer, and the LINECNT has not changed from 0 to 319 in the meantime, the Frmabeuffer has not changed yet, and you are painting to the same screen. ( flickering is the result )

So you must wait for LINECNT = 0; ( or 1 in my code )
gp32 is changing the framebuffer
the earliest time to detect a change, is then LINECNT is 319. So
we wait for 319.
This is the only corecct (and fastest ) way for refresh detect.

Is there some reason why this...
Code:
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) == 0);
...isn't sufficient?

Yes, the screen is only changed then the jump from 0 to 319 was made.
 
Last edited by a moderator:
Hey, that was quick :D

Is there some reason why this...
Code:
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) == 0);
...isn't sufficient?

Yes, the screen is only changed then the jump from 0 to 319 was made.

Surely when the second while finishes, LINECNT must be 319 (as it is no longer 0, it must have gone back up to 319?).

I only ask because it looks as if currently the VSync routine idles for a scanline longer than it needs to... you could draw another few sprites in that time :)

Thanks for your excellent work on your SDK btw... As a GP32 newbie, but an old ARM/Acorn coder from years ago, it's great to be able to see exactly what the machine's doing, and I appreciate the time and effort you've put into it!

Cheers,
Rich
 
Last edited by a moderator:
Hey, that was quick :D

Is there some reason why this...
Code:
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) == 0);
...isn't sufficient?

Yes, the screen is only changed then the jump from 0 to 319 was made.

Surely when the second while finishes, LINECNT must be 319 (as it is no longer 0, it must have gone back up to 319?).

I only ask because it looks as if currently the VSync routine idles for a scanline longer than it needs to... you could draw another few sprites in that time :)

Thanks for your excellent work on your SDK btw... As a GP32 newbie, but an old ARM/Acorn coder from years ago, it's great to be able to see exactly what the machine's doing, and I appreciate the time and effort you've put into it!

Cheers,
Rich


In this case :
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) != 319);
and:
while ((rLCDCON1 >> 18) != 0);
while ((rLCDCON1 >> 18) == 0);

are the same.

But for me it was mutch 'understandable' to wait for 319
Yes, you are right, the 1 is wrong, one scanline is wasted.
But this is not a big bug :)
 
Last edited by a moderator:
Back
Top