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.
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?
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.