This is only a preview of the February 1994 issue of Silicon Chip. You can view 30 of the 96 pages in the full issue, including the advertisments. For full access, purchase the issue for $10.00 or subscribe for access to the latest issues. Items relevant to "Build A 90-Second Message Recorder":
Items relevant to "Compact & Efficient 12-240VAC 200W Inverter":
Articles in this series:
Items relevant to "A Single Chip Audio Amplifier":
Articles in this series:
Items relevant to "Build A Novel LED Torch":
Items relevant to "40V 3A Variable Power Supply; Pt.2":
Items relevant to "Computer Bits":
|
COMPUTER BITS
BY DARREN YATES
Experiments with your games card; Pt.4
This month, we look at the games card port &
learn how each bit is defined. We also discuss
how you can use the BIOS interrupt routines to
get fast information about the port.
In the January 1994 issue, we looked
at how you can tell whether or not a PC
has a games card installed (apart from
having a look at the back). This was
done using a machine code routine
inside a QBASIC program. A similar
process is used by games programs to
find out this information.
So far we’ve spent some time on the
analog inputs which read the X and Y
coordinates of a joystick. (Remember
that the card can handle two joysticks
at once). However, we haven’t covered the four digital inputs which are
accessible via the fire buttons of the
joysticks.
These digital inputs are quite easy
to use – in fact, much easier to use
than the printer port inputs. Let’s take
a look at the pinout diagram for the
joystick DB15 socket – see Fig.1. As
you can see, the four fire buttons in
the joysticks (S1-S4) simply pull their
corresponding inputs to ground. We
don’t need to worry about maintaining
5V logic lines or anything else – we
can simply pull each line to ground or
leave it open and we can do this with
a single transistor.
Bits 7 to 4 are initially set to ‘1’ and
become ‘0’ when the joystick button
is pressed. You can test this by soldering two wires to pins 10 and 12 of
the joystick adaptor plug and joining
them together while running this short
program in QBASIC.
WHILE A$=””
A=INP(&H201)
PRINT A
A$=INPUT$(1)
WEND
You should see the number ‘243’
flash down the lefthand side of your
screen and whenever you join the
wires together, the number should
change to ‘211’. The numbers themselves are not important but you
should see the number change every
Games card port
Just as your printer card and serial
card both have their own port addresses (the printer port is usually 0378H
and the serial port 03F8H), so too
does your games card and its address
is 0201H.
If we have a look at Table 1, we can
see how each of the 8 bits is used.
time you join the two wires.
Alternatively, you could plug in a
joystick if you have one handy, and
run the same program while pressing
the fire buttons. You should find that
a similar thing happens – the ‘243’
number on the screen should change.
What it changes to will depend upon
which input your joystick is connected
to – either A or B.
The four least significant bits each
determine (in a way) the coordinate
from the joysticks. This probably won’t
be obvious from the outset but they
work like this.
Remember how we looked previously at the 558 timer circuit and how
the joystick control formed part of the
monostable circuit? Well, the output
of each monostable appears at one of
these bits. Now the whole idea is that
while the bit remains high, a counter
should be counting elsewhere in the
program to keep track of the time.
When the bit goes low, the count
represents a proportional figure to the
joystick position.
As you’ll probably agree, while using this port for the digital inputs is
fairly straightforward, there is quite a
bit more work to be done on the data
from this port in order to obtain the
analog inputs.
If you think about your favourite
flight simulator, just imagine how
much calculation has to go on for
the joystick alone to figure out where
you are!
BIOS interrupt
Fig.1: the pin connection details for
the DB15 sockets on a games card.
Thankfully, this is where the BIOS
interrupt routines come in - in particular INT 15H, SERVICE 84H. Table
2 shows how this works.
Last time, we were able to obtain
hardware information about the games
card by using INT 11H and we can
February 1994 79
Table 1: Game Adapter AB Joystick Data Byte
Protect your valuable issues
Silicon Chip Binders
Bit Number
7
6
5
4
3
2
1
0
✔
Status of B joystick button 2
✔
Status of B joystick button 1
✔
Status of A joystick button 2
✔
Status of A joystick button 1
✔
B joystick Y coordinate*
✔
B joystick X coordinate*
✔
A joystick Y coordinate*
✔
These beautifully-made binders
will protect your copies of SILICON
CHIP. They feature heavy-board
covers & are made from a dis
tinctive 2-tone green vinyl. They
hold up to 14 issues & will look
great on your bookshelf.
★ High quality
★ Hold up to 14 issues
★ 80mm internal width
★ SILICON CHIP logo printed in
gold-coloured lettering on spine
& cover
Price: $A14.95 (includes postage
in Australia). NZ & PNG orders
please add $A5 each for postage.
Not available elsewhere.
Silicon Chip Publications
PO Box 139
Collaroy Beach 2097
Or fax (02) 979 6503; or ring (02)
979 5644 & quote your credit card
number.
➦
Use this handy form
Enclosed is my cheque/money order for
$________ or please debit my
❏ Bankcard ❏ Visa ❏ Mastercard
Card No:
______________________________
Card Expiry Date ____/____
Signature ________________________
Name ___________________________
Address__________________________
__________________ P/code_______
80 Silicon Chip
Function
A joystick X coordinate*
also obtain the joystick coordinates
as well as the button inputs using this
interrupt routine.
Interrupt routines
Before we dive headlong into more
machine code, the idea of interrupt
routines may well be new to some
readers, so we’ll take a more leisurely
approach.
Looking at Table 2, this routine,
like most of the BIOS and DOS
interrupts, uses the four general
purpose 16-bit registers inside the
8086/8088/80286/386/486 processor;
ie, AX, BX, CX and DX.
Each of these can be split in half
to give two 8-bit registers – high and
low. For the accumulator register AX,
we can access the high eight bits by
referring to AH and the low eight bits
by referring to AL. The other three 16bit registers give, respectively, BH, BL,
CH, CL, DH and DL.
Remember that there are only four
registers but they can be split or, more
accurately, ‘selected’ as eight bits
wide by using the ‘H’ and ‘L’ suffixes.
In the 80386/486 processors, the
AX to DX registers are themselves
the lower 16-bit ‘splits’ of 32-bit
registers EAX through to EDX, the
‘E’ prefix standing for ‘extended’.
It’s not possible though to access the
higher 16-bit sections of each of these
extended registers.
If we look back at Table 2, before
the interrupt can be called using the
instruction INT 15H, we have to load
the number 84H into the upper 8-bit
section of AX, namely AH. This tells
the PC that we want a particular service out of those available from INT
15H.
You can think of this service number
as a house number and the interrupt
number as a street name.
We still have a further choice to
make and that deals with the amount
of information returned. By setting
the DX register to ‘0’, the only information returned from the interrupt
routine is just the joystick fire button
settings and these are returned in
Table 2: Joystick Support (Interrupt 15h, Service 84h)
Registers on entry:
AH:84h
DX: 00h = read switches
01h = read joystick position
Registers on Return:
If reading switches (DX=0):
AL = switch settings (bits 4-7)
If reading position (DX=1);
AX=A(X) value
BX=A(Y) value
CX=B(X) value
DX=b(Y) value
Memory affected: None
Note: This service is not available on PC machines released prior to 1983.
register AL. However, if we set DX
to ‘1’, then register AX returns the
X-axis coordinate from joystick A, BX
the y-axis, CX the x-axis from joystick
B and DX the y-axis. Note that the
joystick button settings are ignored
in this case.
One good thing about this routine
is that it returns all four coordinates
at once, giving you the possibility of
having four analog inputs sampled at
the same time.
Example
OK, let’s take our new-found know
ledge and write a short program. Let’s
keep it simple and just return the
settings of the fire buttons.
Remember that these appear in
register AL. The program, called
BUTTON.BAS, uses a machine-code
program inside QBASIC to get the
information we want.
If you’ve been following this series,
you’ll notice the similarity between
this program and the Games Card
Finder program presented in the January 1994 issue.
Going through it briefly, the machine
code program is stored in the integer
array ASMPROG. Lines 3 and 4 of the
machine code load 84H into register
AH and 0H into DX. After that, the INT
15H call is made.
Again, the VARPTR and VARSEG
provide the specific address information of the first element in the program
array. This is so control is transferred
to the correct position and so the program starts and runs correctly.
The joystick fire button information
is returned in the variable BUTTON.
Each fire button bit is then separated
out and passed to the BUTTON array
from 1 to 4. As the comments in the
program show, bit 7 from port 201H
corresponds to button 1 which gives
the value 128 if the button is not
pressed, bit 6 corresponds to button
2 which gives 64 and so on – down
to 32 and finally a value of 16 in
BUTTON(4). If any of these buttons
have been pressed however, the corresponding BUTTON array will give
a value of ‘0’.
This information is then printed on
the screen for each of the four buttons.
The FOR..NEXT loop cuts down on the
program lines and simply checks each
BUTTON array in turn, calculating
what the correct number should be
in that array element if that button
wasn’t pressed.
Button.Bas: Joystick Button Finder Program
‘Joystick button finder
‘Copyright 1993 SILICON CHIP
‘Written by DARREN YATES B.Sc.
‘ This program uses the BIOS interrupt 15, service 84 to obtain
‘ the status of the four fire buttons without using the BASIC
‘ commands.
DEFINT A-Z
DIM ASMPROG(1 TO 10)
DIM button(1 TO 4)
‘The machine-code program is stored in the array ASMPROG and read
‘and read into the array.
ASMBYTES:
DATA &h55
: ‘PUSH BP
save base pointer
DATA &h8b,&hec
: ‘MOV BP,SP
get our own
DATA &hb4,&h84
: ‘MOV AH,84H
set service number
DATA &hba,&h00,&h00
: ‘MOV DX,0000
select button input data only
DATA &hcd,&h15
: ‘INT 15H
make ROM-BIOS call
DATA &h8b,&h5e,&h06
: ‘MOV BX,[BP+6]
get argument address
DATA &h88,&h07
: ‘MOV [BX],AL
save list in argument
DATA &h5d
: ‘POP BP
pop argument off stack
DATA &hca,&h02,&h00
: ‘RET 2
and make far return to BASIC
‘get the starting offset of the array
start = VARPTR(ASMPROG(1))
‘poke machine code program into the array ASMPROG
DEF SEG = VARSEG(ASMPROG(1))
RESTORE ASMBYTES
FOR index = 0 TO 18
READ byte
POKE (start + index), byte
NEXT index
‘run the machine-code program
start = VARPTR(ASMPROG(1))
CALL absolute(button, start)
DEF SEG
‘variable BUTTON now contains info on the joystick buttons
button(1) = button AND &H80
button(2) = button AND &H40
button(3) = button AND &H20
button(4) = button AND &H10
PRINT STRING$(18, 205)
‘this section selects the correct bit for each button
‘ bit 7 = button 1; bit 6 = button 2; bit 5 = button 3; bit 4 = button 4
‘ if that bit is 0 then button is pressed
FOR number = 1 TO 4
IF button(number) = 2 ^ (8 - number) THEN
PRINT “button “; number; “ is open”
ELSE
PRINT “button “; number; “ is pressed”
END IF
NEXT number
That’s it for this month. If you’re not
sure about any of the foregoing, then
read the article again – this topic is
fairly complex the first time you come
across it but it gets easier once you
become more familiar with it.
Next time, we’ll look at installing a
games card into a PC and give some
guidelines on using the in-built 5V
SC
power supply.
February 1994 81
|