REF: TrackBall Programming Guide
From: Craig Lisowski (aa853@cleveland.Freenet.Edu)
Date: 04/21/94-11:21:57 PM Z
From: aa853@cleveland.Freenet.Edu (Craig Lisowski)
Subject: REF: TrackBall Programming Guide
Date: Thu Apr 21 23:21:57 1994
PROGRAMMING THE CX-22 TRACK BALL
William Bartlett
October 26, 1983
This document will attempt to provide programmers with an
understanding of what the Atari Trak-Ball is capable of doing,
how it does it, and how to tap it's potential from an appli-
cation program. The scope of this document is limited to
using the Trak-Ball in true trak-ball (TB) mode. Programming
the Trak-Ball in joystick (JS) mode is exactly the same as
programming a joystick.
Let me briefly review how the PIA chip handles the Atari
joystick. A joystick plugged into port 1 will toggle the lower
four bits of PORTA located at $D300 and shadowed at $278. One
bit is cleared (zero) to indicate the joystick is being pushed
in any of four directions; right, left, forward or back. If
the joystick is stationary, the four bits are set (one). Atari
BASIC provides the STICK function to provide the value of these
four bits to a BASIC programmer.
HOW DOES A TRAK-BALL DIFFER FROM A JOYSTICK?
A joystick is only capable of indicating direction whereas
a trak-ball is capable of indicating direction and speed. The
best implementation of trak-ball application programs will re-
flect the varying speeds of ball movement.
HOW IS DIRECTION AND SPEED IMPLEMENTED IN THE HARDWARE?
A trak-ball plugged into port 1 will toggle the lower four
bits of PORTA located at $D300 and shadowed at $278. There are
two direction bits and two rate bits; one each for the hori-
zontal and vertical axis. The direction bits indicate which
direction along the axis the ball is rolling. The rate bits
change from 0 to 1 and back to 0 as the ball is rolled. The
faster the ball rolls, the faster the rate bits change.
HOW CAN AN APPLICATION PROGRAM UTILIZE THE TRAK-BALL?
Unfortunately, Atari BASIC is very inefficient for using
the Trak-Ball. To quickly implement direction and speed it is
necessary to test the individual bits of PORTA. The AND func-
tion in Atari BASIC is byte-to-byte instead of a true bit-to-bit
test. Therefore, machine language is going to be required to
tap the potential of the Trak-Ball.
To determine the direction of ball movement, the direction
bits need to be tested only once. To determine the speed of
ball movement, the rate bits will have to be sampled many times
and a count made of the changes from 0 to 1 and back. The
lower four bits of PORTA are assigned as follows:
+---------------+---+---+---+---+
PORTA >> | | 4 | 3 | 2 | 1 |
+---------------+---+---+---+---+
* bit 4 = vertical rate,
* bit 3 = vertical direction (0=up, 1=down),
* bit 2 = horizontal rate,
* bit 1 = horizontal direction (0=left, 1=right).
Let's assume we wish to control an object on the screen
with a trak-ball. There are two logical approaches to this
programming problem. I shall refer to these as the vector
approach and the incremental approach.
VECTOR : The vector approach is to maintain a value for the
horizontal and vertical locations, sample the trak-ball N
times, calculate the new horizontal and vertical locations,
and then reposition the object. A complication is that if
the object is a player or missile, we could vector to a new
location without recognizing a collision. Another complication
is that of boundaries. What if the new location is outside of
a boundary? Should we ignore the boundary, ignore the sample,
or calculate where the vector crosses the boundary? Using the
vector method we will either have complicated coding or flaky
response.
INCREMENTAL : The incremental approach is to move the object
when the rate bit changes as you sample the trak-ball N times.
Boundary and collision checking is much simpler than that of
the vector approach.
SAMPLE PROGRAMS
I have provided three tutorial programs to be used in
conjunction with the trak-ball:
1) TBALLTST.BAS allows you to observe the lower four bits of
PORTA changing so that you can familiarize yourself with
their action.
2) TBALL.BAS will demonstrate how the trak-ball can be sampled
from Atari BASIC to provide a signed value of direction and
speed for each axis. The three numbers displayed are the
horizontal axis, the vertical axis, and the joystick value.
3) VBITBALL.BAS demonstrates a vertical blank routine to sample
the trak-ball and move a player using the incremental method
discussed above. Because the movement is done using a
vertical blank interrupt (background), other activity may
proceed in BASIC (foreground).
(Listing follows:)
10 REM :TBALLTST.BAS
100 DATA 169,0,133,212,133,213,104,104,104,133,203,104,104
101 DATA 37,203,240,2,230,212,96
110 FOR I=1536 TO 1555:READ J:K=K+J:POKE I,J:NEXT I
111 IF K-2736 THEN ? "BAD DATA!":END
120 GRAPHICS 0:POKE 710,0:TRAP 21:? "BIT OPTIONS (0-15)...";:INPUT OP
125 GRAPHICS 18
130 I=PEEK(632):POSITION 0,0
135 IF USR(1536,OP,8) THEN ? #6;USR(1536,I,8),"Y RATE"
136 IF USR(1536,OP,4) THEN ? #6;USR(1536,I,4),"Y DIR"
137 IF USR(1536,OP,2) THEN ? #6;USR(1536,I,2),"X RATE"
138 IF USR(1536,OP,1) THEN ? #6;USR(1536,I,1),"X DIR"
140 IF PEEK(53279)=6 THEN 120
141 GOTO 130
10 ;#D1:TBALLTST.SRC
20 ;TEST A BIT
00D4 30 BASIC = $D4
00CB 40 MASK = $CB
0000 50 *= $0600
0600 A900 60 LDA #0
0602 85D4 70 STA BASIC
0604 85D5 80 STA BASIC+1
0606 68 90 PLA ;BASIC
0607 68 0100 PLA ;MSB MASK
0608 68 0110 PLA ;LSB MASK
0609 85CB 0120 STA MASK
060B 68 0130 PLA ;MSB VALUE
060C 68 0140 PLA ;LSB VALUE
060D 25CB 0150 AND MASK
060F F002 0160 BEQ DONE
0611 E6D4 0170 INC BASIC
0613 60 0180 DONE RTS
10 REM :TBALL.BAS
100 REM 1536-1619
101 DATA 104,169,0,133,212,133,213,173,0,211,41,2,133,205,160,255,173,0,211
102 DATA 41,2,197,205,240,2,230,212,133,205,136,208,240,173,0,211,41,1,208
103 DATA 6,165,212,9,128,133,212,173,0,211,41,8,133,205,160,255,173,0,211
104 DATA 41,8,197,205,240,2,230,213,133,205,136,208,240,173,0,211,41,4,208
105 DATA 6,165,213,9,128,133,213,96,-1
110 FOR I=1536 TO 1619:READ J:K=K+J:POKE I,J:NEXT I
111 IF K-11306 THEN ? "BAD DATA!":END
200 U=USR(1536):Y=INT(U/256):X=U-Y*256
210 IF X>127 THEN X=X-128:IF X THEN X=-X
211 IF Y>127 THEN Y=Y-128:IF Y THEN Y=-Y
220 ? X,Y,PEEK(632):GOTO 200
10 ;#D1:TBALL.SRC
20 ;SAMPLE TBALL X,Y DIR, RATE
30 ;CALLED FROM BASIC U=USR(ORG) ;HIBYTE=Y AXIS ;LOBYTE=X AXIS
D300 40 PORTA = $D300
00D4 50 XCOUNT = $D4
00D5 60 YCOUNT = $D5
00CD 70 LAST = $CD
0000 80 *= $600
0600 68 90 PLA
0601 A900 0100 LDA #0
0603 85D4 0110 STA XCOUNT
0605 85D5 0120 STA YCOUNT
0607 AD00D3 0130 XINIT LDA PORTA
060A 2902 0140 AND #2
060C 85CD 0150 STA LAST
060E AOFF 0160 LDY #$FF
0610 AD00D3 0170 XSAMP LDA PORTA
0613 2902 0180 AND #2
0615 C5CD 0190 CMP LAST
0617 F002 0200 BEQ XDEC
0619 E6D4 0210 INC XCOUNT
061B 85CD 0220 XDEC STA LAST
061D 88 0230 DEY
061E D0F0 0240 BNE XSAMP
0620 AD00D3 0250 LDA PORTA
0623 2901 0260 AND #1
0625 D006 0270 BNE YINIT
0627 A5D4 0280 LDA XCOUNT
0629 0980 0290 ORA #128
062B 85D4 0300 STA XCOUNT
062D AD00D3 0310 YINIT LDA PORTA
0630 2908 0320 AND #8
0632 85CD 0330 STA LAST
0634 A0FF 0340 LDY #$FF
0636 AD00D3 0350 YSAMP LDA PORTA
0639 2908 0360 AND #8
063B C5CD 0370 CMP LAST
063D F002 0380 BEQ YDEC
063F E6D5 0390 INC YCOUNT
0641 85CD 0400 YDEC STA LAST
0643 88 0410 DEY
0644 D0F0 0420 BNE YSAMP
0646 AD00D3 0430 LDA PORTA
0649 2904 0440 AND #4
064B D006 0450 BNE RETURN
064D A5D5 0460 LDA YCOUNT
064F 0980 0470 ORA #128
0651 85D5 0480 STA YCOUNT
0653 60 0490 RETURN RTS
10 REM :VBITBALL.BAS
100 REM 1536-1762
101 DATA 160,255,173,0,211,41,2,133,203,173,0,211,41,2,197,203,240,39,133,203
102 DATA 173,0,211,41,1,240,16,174,149,6,232,224,196,240,22,142,149,6,142,0
103 DATA 208,208,14,174,149,6,202,224,48,240,6,142,149,6,142,0,208,136,208,205
104 DATA 160,255,173,0,211,41,8,133,203,173,0,211,41,8,197,203,240,65,133,203
105 DATA 173,0,211,41,4,208,29,174,150,6,224,32,240,49,202,142,150,6,152,72
106 DATA 160,8,189,1,44,157,0,44,232,136,16,246,104,168,208,27,174,150,6,224
107 DATA 218,240,20,232,142,150,6,152,72,160,8,189,6,44,157,7,44,202,136,16
108 DATA 246,104,168,136,208,179,76,98,228,0,0,104,160,255,169,0,153,0,44,136
109 DATA 208,250,185,219,6,153,120,44,200,192,8,208,245,169,120,141,149,6,141,150
110 DATA 6,141,0,208,169,34,141,192,2,169,1,141,8,208,169,40,141,7,212,169
111 DATA 62,141,47,2,169,3,141,29,208,169,7,162,6,160,0,32,92,228,96,24
112 DATA 24,24,231,231,24,24,24
113 REM * 227 BYTES
120 FOR I=1536 TO 1762:READ J
130 K=K+J:POKE I,J:NEXT I
140 IF K-26973 THEN ? "BAD DATA!":END
150 I=USR(1687)
10 ; :VBITBALL.SRC
20 ; VBLANK TO MOVE PLYR 0 WITH T-BALL
30 ; EQUATES
=D300 40 PORTA = $D300
=00CB 50 LASTA = $CB
0000 60 *= $0600
70 ;X-AXIS:BIT1=X DIR, BIT2=X RATE
0600 A0FF 80 VBI LDY #$FF
0602 AD00D3 90 LDA PORTA
0605 2902 0100 AND #2
0607 85CB 0110 STA LASTA
0609 AD00D3 0120 XSAMP LDA PORTA
060C 2902 0130 AND #2
060E C5CB 0140 CMP LASTA
0610 F027 0150 BEQ XNEXT
0612 85CB 0160 STA LASTA
0614 AD00D3 0170 LDA PORTA
0617 2901 0180 AND #1
0619 F010 0190 BEQ XLEFT
061B AE9506 0200 XRGHT LDX XPOS
061E E8 0210 INX
061F E0C4 0220 CPX #196
0621 F016 0230 BEQ XNEXT
0623 8E9506 0240 STX XPOS
0626 8E00D0 0250 STX P0HPOS
0629 D00E 0260 BNE XNEXT
062B AE9506 0270 XLEFT LDX XPOS
062E CA 0280 DEX
062F E030 0290 CPX #48
0631 F006 0300 BEQ XNEXT
0633 8E9506 0310 STX XPOS
0636 8E00D0 0320 STX P0HPOS
0639 88 0330 XNEXT DEY
063A D0CD 0350 ;Y AXIS: BIT3=Y DIR, BIT4=Y RATE
063C A0FF 0360 LDY #$FF
063E AD00D3 0370 LDA PORTA
0641 2908 0380 AND #8
0643 85CB 0390 STA LASTA
0645 AD00D3 0400 YSAMP LDA PORTA
0648 2908 0410 AND #8
064A C5CB 0420 CMP LASTA
064C F041 0430 BEQ YNEXT
064E 85CB 0440 STA LASTA
0650 AD00D3 0450 LDA PORTA
0653 2904 0460 AND #4
0655 D01D 0470 BNE YDOWN
0657 AE9606 0480 YUP LDX YPOS
065A E020 0490 CPX #32
065C F031 0500 BEQ YNEXT
065E CA 0510 DEX
065F 8E9606 0520 STX YPOS
0662 98 0530 TYA
0663 48 0540 PHA
0664 A008 0550 LDA #8
0666 BD012C 0560 YUP1 LDA P0BASE+1,X
0669 9D002C 0570 STA P0BASE,X
066C E8 0580 INX
066D 88 0590 DEY
066E 10F6 0600 BPL YUP1
0670 68 0610 PLA
0671 A8 0620 TAY
0672 D01B 0630 BNE YNEXT
0674 AE9606 0640 YDOWN LDX YPOS
0677 E0DA 0650 CPX #218
0679 F014 0660 BEQ YNEXT
067B E8 0670 INX
067C 8E9606 0680 STX XPOS
067F 98 0690 TYA
0680 48 0700 PHA
0681 A008 0710 LDY #8
0683 BD062C 0720 YDOWN1 LDA P0BASE+6,X
0686 9D072C 0730 STA P0BASE+7,X
0689 CA 0740 DEX
068A 88 0750 DEY
068B 10F6 0760 BPL YDOWN1
068D 68 0770 PLA
068E A8 0780 TAY
068F 88 0790 YNEXT DEY
0690 D0B3 0800 BNE YSAMP
0692 4C62E4 0810 JMP XITVBV
0695 00 0820 XPOS .BYTE 0
0696 00 0830 YPOS .BYTE 0
0840 ;INIT. PM/VBI
0850 ;EQUATES
=D407 0860 PMBASE = $D407
=2800 0870 PMRAM = $2800
=2C00 0880 P0BASE = PMRAM+$0400
=D000 0890 P0HPOS = $D000
=02C0 0900 P0COLR = $02C0
=D008 0910 P0SIZE = $D008
=022F 0920 SDMCTL = $022F
=D01D 0930 GRACTL = $D01D
=0224 0940 VVBLKD = $0224
=E45C 0950 SETVBV = $E45C
=E462 0960 XITVBV = $E462
0970 ;CLEAR PLAYER 0
0697 68 0980 PLA
0698 A0FF 0990 LDY #$FF
069A A900 1000 LDA #0
069C 99002C 1010 INIT1 STA P0BASE,Y
069F 88 1020 DEY
06A0 D0FA 1030 BNE INIT1
1040 ;DEFINE PLAYER 0
06A2 B9DB06 1050 INIT2 LDA P0SHAP,Y
06A5 99782C 1060 STA P0BASE+120,Y
06A8 C8 1070 INY
06A9 C008 1080 CPY #8
06AB D0F5 1090 BNE INIT2
06AD A978 1100 LDA #120
06AF 8D9506 1110 STA XPOS
06B2 8D9606 1120 STA YPOS
06B5 8D00D0 1130 STA P0HPOS
06B8 A922 1140 LDA #34
06BA 8DC002 1150 STA P0COLR
06BD A901 1160 LDA #1 ;DOUBLE WIDTH
06BF 8D08D0 1170 STA P0SIZE
06C2 A928 1180 LDA #PMRAM/256
06C4 8D07D4 1190 STA PMBASE
06C7 A93E 1200 LDA #$3E ;SINGLE LINE P/M
06C9 8D2F02 1210 STA SDMCTL
06CC A903 1220 LDA #$03 ;TURN ON P/M
06CE 8D1DD0 1230 STA GRACTL
1240 ;INIT. VBI
06D1 A907 1250 LDA #7
06D3 A206 1260 LDX #VBI/256
06D5 A000 1270 LDY #VBI&255
06D7 205CE4 1280 JSR SETVBV
06DA 60 1290 RTS
06DB 181818E7 1300 P0SHAP .BYTE $18,$18,$18,$E7,$E7,$18,$18,$18
06DF E7181818
[END]
-----------------------------------------
Return to message index