!!!Atari Trackball Taming your machine with a mouse has long been a dream of the ATARI 8-bitters. The mouse had it's origins around the 1960's, but did see much use until the 1980's when the Mac,ST and Amiga were unveiled. The mouse was also used by the engineering world as an input device for graphics workstations in the late 70's. The Track-ball is a close relative to the Mouse. A track-ball is basicly the same device flipped over allowing the hand position the ball directly. The Old ATARI did have some foresight in developing input devices for the 8-bit machines. The TrackBall is one of them. The Track-ball allows smooth tracking of 2 dimensional motion and its associated velocity. Atari Basic is too slow so it can not be read with atari basic. Faster langauges such ACTION and Assembly can read the velocity vectors directly from the joystick registers. (mention something about which bits represent the direction and speed.) One thing the Atari Trak Ball lacks is a separate button that can function as the left mouse button. Since the mouse and the Track-ball are virtually the same device it should be possible to read and ST mouse using the Trak-ball read code. The 8-bits can read the ST left mouse if a pull-up resistor is added to pin 6. Heres the pinout on the ST mouse. {{{ _____________ \ 1 2 3 4 5 / \ 6 7 8 9 / --------- 1- up/xb 2- down/xa 3- left/ya 4- right/yb 5- not connected 6- Fire/left mouse button 7- +5vdc 8- ground 9- Joystick 1 Fire/Right Mouse button. }}} I have included 3 programs that demostrate the trak-balls ability to read direction and velocity. One program is written in basic with a short assemble used to read the T-ball input vector. The other 2 programs are written in ACTION! {{{ | | | Mike Buford | | | 8-bits Forever/ Dflint02@ulkyvx.bitnet or | | | Whether i buy a new CL150652@ulkyvm.bitnet / | \ machine or not! (An Action Programmer!) / | \ }}} ------- {{{ 10 REM :TBALL2.BAS 100 REM *** POKE MACHINE CODE *** 110 REM 1536-1619 111 DATA 104,169,0,133,212,133,213,173,0,211,41,2,133,205,160,255,173,0,211 112 DATA 41,2,197,205,240,2,230,212,133,205,136,208,240,173,0,211,41,1,208 113 DATA 6,165,212,9,128,133,212,173,0,211,41,8,133,205,160,255,173,0,211 114 DATA 41,8,197,205,240,2,230,213,133,205,136,208,240,173,0,211,41,4,208 115 DATA 6,165,213,9,128,133,213,96,-1 116 FOR I=1536 TO 1619:READ J:K=K+J:POKE I,J:NEXT I 117 IF K-11306 THEN ? "BAD DATA!":END 120 REM 130 GRAPHICS 0:POKE 710,0:POKE 752,1:REM BLACK BACKGROUND ,NO CUSOR 131 POSITION COL,ROW:? " ";:REM ERASE OLD OBJECT 200 REM READ TBALL 210 U=USR(1536):Y=INT(U/256):X=U-Y*256 220 IF X>127 THEN X=X-128:IF X THEN X=-X 221 IF Y>127 THEN Y=Y-128:IF Y THEN Y=-Y 310 POSITION COL,ROW:? " "; 320 COL=COL+X:REM CALCULATE NEW COLUNM 321 IF COL>39 THEN COL=39 322 IF COL<0 THEN COL=0 330 ROW=ROW+Y 331 IF ROW<0 THEN ROW=0 332 IF ROW>22 THEN ROW=22 340 POSITION COL,ROW:? "+"; 350 GOTO 200 }}} -------- {{{ ;TRACK1.ACT ;Display the value read from ;port 1 as track-ball values. ;9/87 Written bye Joe McFarland PROC PrintT(BYTE val) ;Binary number print: ;Print byte in base Two. ;Modified to only print 4 LSbits. BYTE mask,n mask=$08 FOR n=0 TO 3 DO IF val&mask THEN Put('1) ELSE Put('0) FI mask==RSH 1 OD RETURN PROC Main() BYTE b,cursor=752,consol=53279 cursor=1 Position(2,3) PrintE("|||LHorizontal Dir 0=left, 1=right") PrintE("||LHorizontal Rate") PrintE("|Vertical Dir 0=up, 1=down") PrintE("Vertical Rate") DO b=Stick(0) Position(2,2) PrintT(b) Until consol<>7 OD cursor=1 RETURN }}} -------- {{{ ;TRACK3.ACT ;Rudimentary PM cursor positioning ;using Track-Ball peripheral ;PM routines added ;Single line rez. ;9/87 BYTE ARRAY player_base BYTE ARRAY shposp(4) ;pm horiz shadow array. CHAR ARRAY imagep=[ $F0 $90 $90 $90 $90 $90 $90 $F0 $00 $18 $18 $7E $7E $18 $18 $00 ] ;************************************ ;Move specified player to the ;ABSOLUTE x location (0 to ?). PROC MovePlayerHor(BYTE pl_num BYTE pl_x) BYTE ARRAY hposp=53248 shposp(pl_num)=48+pl_x hposp(pl_num)=shposp(pl_num) RETURN ;************************************ MODULE BYTE ARRAY old_pl_y(4)=~[0 0 0 0] ;Move specified player to the ;ABSOLUTE y location. (from 0 to ?.) PROC MovePlayerVer(CARD pl_num BYTE pl_y) BYTE playery CARD pl_offset pl_offset=player_base+$400+pl_num LSH 7 Zero(pl_offset+old_pl_y(pl_num),8) playery=15+pl_y MoveBlock(pl_offset+playery, imagep+pl_num LSH 3,8) old_pl_y(pl_num)=playery RETURN ;************************************ ;Move player to absolute x,y ;x=0 to ?, y=0 to ? PROC MovePlayer(BYTE pl_num,pl_x,pl_y) MovePlayerHor(pl_num,pl_x) MovePlayerVer(pl_num,pl_y) RETURN ;************************************ PROC PlayerCursor() BYTE pmbase=54279,gractl=53277, gprior=623 BYTE ARRAY pl_color=704, PMWidth(5)=$D008 BYTE ramtop=106,sdmactl=$22F ramtop=$A0-8 ;presumes 40K of memory Graphics(0) player_base=(ramtop)*256 pmbase=player_base/256 sdmactl=32+8+2+16 ;no missles... gractl=2 ;again no missles. Zero(player_base,$800) pl_color(0)=110 ;pl_color(1)=70 gprior=1 MovePlayer(0,0,0) ;MovePlayer(1,4,10) RETURN ;************************************ PROC ClearPM() BYTE ramtop=106,sdmactl=$22F BYTE cursor=752 BYTE pmbase=54279,gractl=53277, gprior=623 cursor=0 gractl=0 sdmactl=32+2 ;Zero(hposp,4) ramtop=$A0 Graphics(0) RETURN ;************************************ PROC Main() BYTE cursor=752,consol=53279, left_margin=82 BYTE lastx,lasty,vx,vy,st INT x,y,oldx=~[0],oldy=~[0] PlayerCursor() cursor=1 left_margin=0 SetColor(2,9,0) PutE() PrintE("This is a line of normal text.") PutE() PrintE("This is a line of inverse text.") X=0 Y=0 lastx=0 lasty=0 WHILE consol&$01 DO st=stick(0) vx=st&$02 vy=st&$08 IF lastx<>vx THEN IF st&$01 THEN x==+1 ELSE x==-1 FI FI IF lasty<>vy THEN IF st&$04 THEN y==+1 ELSE y==-1 FI FI lastx=vx lasty=vy IF x>157 THEN x=157 FI IF y>201 THEN y=201 FI IF x<0 THEN x=0 FI IF y<17 THEN y=17 FI IF oldx<>x OR oldy<>y THEN MovePlayer(0,X,Y) FI IF STRIG(0) THEN ELSE Position(0,10) PrintF("X=%I %EY=%I %E",X,Y) FI oldx=x oldy=y OD ClearPM() Graphics(0) left_margin=2 cursor=0 RETURN }}} -------------- The next program demostrates ACTION!'s Ability to run 2 or more procedures at the same time. The Move_cursor routine runs independent of Main Proc. This Program is extra for Action Programers. ------------- {{{ ;TRACK4.ACT ;Rudimentary PM cursor positioning ;using Track-Ball peripheral ;PM routines added ;Single line rez. ;Vertical blank ;9/87 DEFINE SPEED="2" DEFINE JMP="$4C", XITVBV="$E462", SAVETEMPS= "[$A2 $07 $B5 $C0 $48 $B5 $A0 $48 $B5 $80 10 dF1 $A5 $D3 $48]", GETTEMPS= "[$68 $85 $D3 $A2 $00 $68 $95 $A8 $68 $95 $80 $68 $95 $A0 $68 $95 $C0 $E8 $E0 $08 $D0 $EF]" CARD OldVbi,VBIvec=$224 BYTE critic=$42 BYTE ARRAY player_base BYTE ARRAY shposp(4) ;pm horiz shadow array. CHAR ARRAY imagep=[ $0 $90 $90 $90 $90 $90 $90 $F0 $00 $18 $18 $7E $7E $18 $18 $00 ] INT x=~[0],y=~[0] ;************************************ ;Move specified player to the ;ABSOLUTE x location (0 to ?). PROC MovePlayerHor(BYTE pl_num BYTE pl_x) BYTE ARRAY hposp=53248 shposp(pl_num)=48+pl_x hposp(pl_num)=shposp(pl_num) RETURN ;************************************ MODULE BYTE ARRAY old_pl_y(4)=~[0 0 0 0] ;Move specified player to the ;ABSOLUTE y location. (from 0 to ?.) PROC MovePlayerVer(CARD pl_num BYTE pl_y) BYTE playery CARD pl_offset pl_offset=player_base+$400+pl_num LSH 7 Zero(pl_offset+old_pl_y(pl_num),8) playery=15+pl_y MoveBlock(pl_offset+playery, imagep+pl_num LSH 3,8) old_pl_y(pl_num)=playery RETURN ;************************************ ;Move player to absolute x,y ;x=0 to ?, y=0 to ? PROC MovePlayer(BYTE pl_num,pl_x,pl_y) MovePlayerHor(pl_num,pl_x) MovePlayerVer(pl_num,pl_y) RETURN ;************************************ PROC PlayerCursor() BYTE pmbase=54279,gractl=53277, gprior=623 BYTE ARRAY pl_color=704, PMWidth(5)=$D008 BYTE ramtop=106,sdmactl=$22F ramtop=$A0-8 ;presumes 40K of memory Graphics(0) player_base=(ramtop)*256 pmbase=player_base/256 sdmactl=32+8+2+16 ;no missles... gractl=2 ;again no missles. Zero(player_base,$800) pl_color(0)=110 ;pl_color(1)=70 gprior=1 MovePlayer(0,0,0) ;MovePlayer(1,4,10) RETURN ;************************************ PROC ClearPM() BYTE ramtop=106,sdmactl=$22F BYTE cursor=752 BYTE pmbase=54279,gractl=53277, gprior=623 cursor=0 gractl=0 sdmactl=32+2 ;Zero(hposp,4) ramtop=$A0 Graphics(0) RETURN ;************************************ PROC Move_Cursor() BYTE lastx=~[0],lasty=~[0], vx=~[0],vy=~[0],st INT oldx=~[0],oldy=~[0] SAVETEMPS st=stick(0) vx=st&$02 vy=st&$08 IF lastx<>vx THEN IF st&$01 THEN x==+SPEED ELSE x==-SPEED FI FI IF lasty<>vy THEN IF st&$04 THEN y==+SPEED ELSE y==-SPEED FI FI lastx=vx lasty=vy IF x>157 THEN x=157 FI IF y>201 THEN y=201 FI IF x<0 THEN x=0 FI IF y<17 THEN y=17 FI IF oldx<>x OR oldy<>y THEN MovePlayer(0,X,Y) FI oldx=x oldy=y GETTEMPS ; get temp registers ~[JMP XITVBV] ; exit the VBI ;************************************** PROC ClearVB() critic=1 VBIvec=OldVBI critic=0 RETURN ;************************************** PROC VBinst(); install the VBI critic=1 ; turn off the interrupts OldVBI=VBIvec VBIvec=Move_Cursor ; VBI routine. critic=0 ; turn the interrupts back on RETURN ;************************************ PROC Main() BYTE cursor=752,consol=53279, left_margin=82 PlayerCursor() cursor=1 left_margin=0 SetColor(2,9,0) PutE() PrintE("This is a line of normal text.") PutE() PrintE("This is a line of inverse text.") VBinst();This is where we start the Move_Cursor proc WHILE consol&$01 DO Position(0,10) PrintF("X=%I %EY=%I %E",X,Y) OD ClearVB();This is where the Move_Cursor is terminated ClearPM() Graphics(0) left_margin=2 cursor=0 RETURN }}}