Getting vsync IRQs to work

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
randoll
Posts: 7
Joined: Thu Feb 13, 2014 5:58 am

Getting vsync IRQs to work

Post by randoll »

Code: Select all

ORG 0x7C00
BITS 16
;vga test
cli
mov ax,0
mov ss,ax
mov ds,ax
mov bx,0xa000
mov es,bx
mov bp,0x7C00
mov sp,bp
;enter vga
mov ah,0x00
mov al,0x13
int 0x10

;mov ax,0x4444
;mov word[es:0x0210],ax

;activate vsync
activate_vsync:
	;vga enable vsync
	;read vga 3d4h (r/W) index 11h
	;clear bit 5 to enable vsync interrupt
	mov dx,0x3b4
	mov ax,0x11
	out dx,ax
	mov dx,0x3b5
	in al,dx
	in al,dx ;read vga 3d4h (r/W) index 11h
	and al,11011111b;RtL bit numbering ;clear bit 5
	;write al to vga 3d4h (r/W) index 11h
	;select
	push ax
	mov dx,0x3b4
	mov ax,0x11
	out dx,ax
	pop ax
	;write
	mov dx,0x3b5
	out dx,al
	
reg_vsync:
	mov ax,0x0
	mov ds,ax
	
	mov word[ds:0x01C6],0
	mov word[ds:0x01C4],on_vsync
sti

l:
	hlt
	jmp l
on_vsync:
	mov ax,0x4444
	mov word[es:0x0210],ax
	mov al,0x20
	out 0x20,al
	iret
times 510-($-$$) db 0xff
dw 0AA55h
Hi I have the above piece of code and when I put the plotting code outside it plots the pixel, so now I am sure that I am not recieving any vsync IRQs. I have tested my code on both normal hardware and QEMU. Is there any way how to reliably get vsync IRQs to avoid polling?
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Getting vsync IRQs to work

Post by Octocontrabass »

No. Most hardware doesn't support it. The original IBM VGA doesn't support it either.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Getting vsync IRQs to work

Post by Brendan »

Hi,
randoll wrote:Is there any way how to reliably get vsync IRQs to avoid polling?
No (but yes).

Poll until vertical sync starts; then set a timer (e.g. PIT in "one shot mode") to generate an IRQ in "1/frame_rate - k" seconds (where "k" is a conservative safety precaution to ensure the timer IRQ happens before the next vertical sync starts). Also set some variables, like "min_polling_time = 999999; count = 0; maxCount = 100;".

Whenever the timer IRQ occurs, poll again while keeping track of how long you spent polling. When vertical sync actually starts adjust "K" by doing something like:
  • If you had to poll for too long (more than maybe "0.9/frame rate" seconds), assume that "k" was too long and that you missed an entire frame; and do "k = k / 1.25; min_polling_time = 999999999; count = 0;"
  • Otherwise, if the time spent polling is less than "min_polling_time" do "min_polling_time = time_spent_polling"; then increase "count". Then, if count is higher than maxCount do "k = k + min_polling_time/2; maxCount *= 1.5; count = 0;".
After all that, set the timer's count (so you get another IRQ in "k" seconds) and call your "do stuff on vertical sync" function.

The basic idea here is; over time, find the "k" that minimises time spent polling (while compensating for "worst case jitter" in your timer IRQ).

Note: I made up all the numbers - feel free to do whatever you like to find "k".


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply