After setting up the required registers and global variables, Poll starts the polling loop. The first iteration of the polling loop occurs before the OUT to address 0x201; this is to ensure that the joystick's monostable vibrators have stabilized since the last poll. After the first iteration, Poll starts the timers by outputting a zero byte to address 0x201.
Each iteration of the polling loop checks the resistive flags. If the flag for a given axis is still set, the timeout has not yet occurred. Poll adds the delta value for that axis to the appropriate position variable. When all the flags are clear, Poll exits the loop. The value returned by this process depends on CPU speed; a fast CPU will complete more polling loops during the timeout period and therefore return higher coordinate values. This is why the IBMJOY driver requires calibration.
An unplugged joystick continually returns high bits for the position values. If a position counter exceeds a certain value (hard-coded as 0x30000 in POLL.ASM), assume the joystick is unplugged. Because the position value is dependent on CPU speed, the use of a constant ceiling value can present a problem with a very fast CPU (for example, a 50-MHz i486).
The following code fragment continues where the previous fragment ended:
; Start the timers!
poll_timers:
mov dx,JOYPORT ; Set joystick port address
cmp wClear, 1 ; Dummy loop?
je poll_skipout
xor ax,ax
out dx,al
poll_skipout:
mov ah,bl ; bl contains x-position bit mask
or ah,bh ; bh contains y-position bit mask
poll_loop:
in al,dx ; Get position info from joystick port
and al,ah ; Only watch bits of interest
jz poll_done ; Counters cleared?
poll_x_test:
test al,bl ; If x bit is cleared, stop
jz poll_y_test ; incrementing the x counter.
add _wXpos,cx ; X still high, increment counter
adc _wXpos_Hi,0
cmp _wXpos_Hi,3 ; Check for overflow (unplugged)
jl poll_y_test
xor ax,ax ; Unplugged. Return 0 and exit loop
jz poll_sti
poll_y_test:
test al,bh ; If y bit clear, stop incrementing
jz poll_loop
add _wYpos,di ; Y still high, increment counter
adc _wYpos_Hi,0
cmp _wYpos_Hi,3 ; Check for overflow (unplugged)
jl poll_loop ; No overflow, loop again
xor ax,ax ; Unplugged (return 0 and exit loop)
jz poll_sti
poll_done:
dec wClear ; Loop again if this is the dummy poll
jnz poll_sti
jmp Real_Poll
poll_sti:
pop bx ; Pop flags
test bx,200h ; Was interrupt flag already clear?
jz poll_fix_x ; Yes; don't reset it
sti ; No; reset interrupt flag
poll_fix_x: ; Clean up final x position value
xor bx,bx
cmp _wXpos_Hi,bx ; Check overflow variable
jz poll_fix_y ; If wXpos_Hi == 0, wXpos is OK
jl @f ; If wXpos_Hi < 0, set wXpos = 0
dec bx ; If wXpos_Hi > 0, set wXpos = 65535
@@: mov _wXpos,bx
poll_fix_y: ; Clean up final y position value
xor bx,bx
cmp _wYpos_Hi,bx
jz poll_fix_done
jl @f
dec bx
@@: mov _wYpos,bx
poll_fix_done:
mov al,ah ; ax = 0 for unplugged joystick
xor ah,ah ; ax != 0 if good read
cEnd ; All done