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