Newsgroups: comp.sys.apple2 Path: news.uiowa.edu!hobbes.physics.uiowa.edu!math.ohio-state.edu!howland.reston.ans.net!gatech!udel!news.mathworks.com!newshost.marcam.com!uunet!comp.vuw.ac.nz!actrix.gen.nz!dempson From: dempson@atlantis.actrix.gen.nz (David Empson) Subject: Re: Info on Serial Cards Message-ID: Sender: news@actrix.gen.nz (News Administrator) Organization: Actrix Information Exchange Date: Fri, 3 Mar 1995 14:19:20 GMT References: <3j6flf$5e1@st-james.comp.vuw.ac.nz> X-Nntp-Posting-Host: atlantis.actrix.gen.nz Lines: 187 In article <3j6flf$5e1@st-james.comp.vuw.ac.nz>, Electron Microscope Facility 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