[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Info on Serial Cards
In article <3j6flf$5e1@st-james.comp.vuw.ac.nz>,
Electron Microscope Facility <EMF@vuw.ac.nz> wrote:
> Hi, I am thinking of making my own serial card for my IIe and want to
> know the standards for it.I know you have to put special numbers at
> certain locations but what else is there to know?
> Rob
Hey, wow! Another NZ Apple II user! :-)
The main problem with making an alternative serial card for the Apple
II is that a lot of software is written specifically for the Super
Serial Card, and due to the limitations of the firmware on that card,
they bypass the firmware and go straight to the hardware.
To support these programs, you're really stuck with a 6551 or
derivative, in a fixed locations (or an emulation of it, perhaps).
This is not usually a problem with programs that use the card for
simple printing (e.g. BASIC or Pascal), because they don't need much
in the way of special features and will use the firmware.
With some communcations programs (e.g. ProTerm, Spectrum and probably
most of the BBSes), the serial port driver can be replaced, so this is
less of a problem (a driver would have to be written, of course).
If you are planning to design a card, it should work on the IIe and
IIgs (you'd probably have to try pretty hard to get it to NOT work on
the IIgs).
The major firmware standard is the Apple Pascal 1.1 Firware Interface.
If you support this, the card should at least be usable as a serial
printer interface for any Pascal program and many ProDOS programs.
You should also implement the BASIC entry points for compatiblity with
most software.
To increase compatibility further, you should also implement a command
set similar to that of the Super Serial card (transmitting a Ctrl-A
followed by an optional parameter and a letter to indicate the
command, with various formatting options). There are too many of
these commands to document here - you would be better off looking at
the manual.
To be able to fit all of the code, you will have to implement the
IOSTROBE signal and the 2k ROM expansion space. If you need a lot of
features, you should consider bank-switching within this space.
The Pascal 1.1 firmware interface is identified and defined by the
following bytes in the $Cn00 (IOSEL) space
$Cn05 38 (sec instruction)
$Cn07 18 (clc instruction)
$Cn0B 01 (ID byte - not code)
$Cn0C xx (ID byte - identifies device type and product code)
$Cn0D xx (Low byte of address of INIT routine)
$Cn0E xx (Low byte of address of READ routine)
$Cn0F xx (Low byte of address of WRITE routine)
$Cn10 xx (Low byte of address of STATUS routine)
$Cn11 xx (Must be nonzero to indicate that no extra calls are present)
If $Cn11 is zero:
$Cn12 xx (Low byte of address of optional CONTROL routine)
$Cn13 xx (Low byte of address of optional INTERRUPT routine)
The BASIC entry points are defined as follows:
$Cn00 BASIC Initialization and output
On entry, A contains the character to be transmitted.
A, X and Y must be preserved.
You should check the I/O hooks ($36 and $37 for output,
$38 and $39 for input). If either of them is pointing to
this card, change the low byte to the entry point of the
output or input routine.
Note: if only the input vector is pointing to this card,
you should probably avoid transmitting the byte in A as
this is probably an input call.
If neither vector is pointing to this card, then no
vectors should be patched, but it should be treated as
an output call.
$Cn05 BASIC Read
Wait for a character then return it in A. X and Y must
be preserved.
$Cn07 BASIC Write
Transmit the character in A. A, X, Y must be preserved.
If transmission cannot be performed (e.g. flow control is
inactive), don't return until you can send the byte.
Note: the BASIC READ and WRITE entry points are also Pascal 1.1 ID
bytes, containing SEC and CLC instructions. The common technique is
for the three BASIC entry points to set up the carry and overflow
flags to identify which routine was called, then branch to common code
further in the page. i.e.
BASIC_INIT:
Cn00: BIT FF58 ; Known RTS instruction - this will set overflow
Cn03: BVS basic ; Always taken
BASIC_READ:
Cn05: SEC
Cn06: DFB $90 ; BCC opcode - never taken, hides CLC instruction
BASIC_WRITE:
Cn07: CLC
Cn08: CLV
Cn09: BVC basic ; Always taken
Cn0B: DFB $01 ; Pascal 1.1 ID byte
The Pascal 1.1 INIT, READ, WRITE and STATUS entry points are accessed
indirectly via $Cn0D to $Cn10. These locations contain the low order
byte of the address of the corresponding routine, which must be higher
up in the same page.
All of these routines are called with X containing $Cn and Y containing
$n0 (n is the slot). These indexes can be used to access your screen
holes (via X) or DEVSEL I/O locations (via Y).
A common technique with these entry points is to point them to four
consecutive locations, each containing an INY instruction. They then
fall into common code which enables the $C800 space and jumps to it.
The value in the lower nibble of Y then indicates which call was made.
The Pascal 1.1 device ID byte at $Cn0C contains a device class in the
high nibble (should be 3 for a serial or parallel card) and a unique
identifier in the lower nibble. As there are only 16 available
identifiers, it is not possible to guarantee this is unique. All
variations of the Apple Super Serial card (including the IIc and IIgs
serial firmware) have $31 in this byte. Unless your firmware supports
a command set which is very similar to the SSC or IIc/IIgs, you should
use a different value in the lower nibble.
The Pascal 1.1 INIT routine should initialize the firmware and
hardware and return to the caller. No characters should be input or
output. On return X contains an error code (used by Apple Pascal
as the the IOResult value, which is documented somewhere in the Pascal
manuals). A is undefined on entry. A and Y are undefined on exit.
The READ routine should wait for a character and return it in A.
Again, X should contain an error code and Y is undefined on exit.
The WRITE routine should wait until it can transmit the character in
A, then return with an error code in X. Y and A are undefined on exit.
The STATUS routine is used to test whether the device is ready for
reading or writing. On entry, A=0 means "are you ready for output?"
and A=1 means "do you have input ready?". The answer to the question
should be returned in the carry flag (C=0 means no, C=1 means yes).
Again, X contains the error code. Y and A are undefined on exit.
The CONTROL routine is not defined by the standard. It is used in
wildly varying ways by different cards.
The INTERRUPT routine has never been defined. This byte should be set
to zero if you are using the CONTROL routine.
If you are really keen, you could also implement the Pascal 1.0 entry
points, which are at specific locations in the $C800 and $C900 pages.
These are only used by Apple Pascal 1.0, which is _very_ old. E-Mail
me for further details.
There are all sorts of other rules you have to follow, such as
handling the screen holes, interrupts, the $C800 space, and the MSLOT
memory location ($07F8).
I'll be happy to answer any questions via E-Mail. I have all the
necessary documentation at home, and have made my own I/O card
(parllel, not serial) so I'm familiar with many of the issues.
If you'd like to discuss this with me by voice, my number is
+64-4-475-9755 (leave a message on my call minder if there is no
answer).
--
David Empson
dempson@actrix.gen.nz
Snail mail: P.O. Box 27-103, Wellington, New Zealand