Following are the pinouts for the printer cables for my Apple and PC.

Apple Parallel Port Printer Cable Connections (Apple DB25 -> Printer Centronics)
=============================================

 Apple DB25      | Centronics 36
-----------------+------------------
Strobe Out    15 > Strobe In      1
Data Out 0     5 > Data In 1      2
Data Out 1     6 > Data In 2      3
Data Out 2     8 > Data In 3      4
Data Out 3    22 > Data In 4      5
Data Out 4    23 > Data In 5      6
Data Out 5    11 > Data In 6      7
Data Out 6    12 > Data In 7      8
Data Out 7    13 > Data In 8      9
ACK In        16 < ACK Out       10
Data In 5     19 < Paper Error   12
Data In 6     21 < Selected      13
Signal Ground 24 - Logic Ground  16
Signal Ground  2 - Signal Ground 19
Data In 3     25 < Error         32
Data In 7     18 < 5v            35

PC Parallel Port Printer Cable Connections (PC DB25 -> Printer Centronics)
==========================================

 PC DB25            | Centronics 36
--------------------+--------------------
Strobe Out        1 > Strobe In        1
Data Out 0        2 > Data In 1        2
Data Out 1        3 > Data In 2        3
Data Out 2        4 > Data In 3        4
Data Out 3        5 > Data In 4        5
Data Out 4        6 > Data In 5        6
Data Out 5        7 > Data In 6        7
Data Out 6        8 > Data In 7        8
Data Out 7        9 > Data In 8        9
ACK              10 < ACK Out         10
Busy             11 < Busy            11
Paper Error      12 < Paper Out       12
Select           13 < Select          13
Auto Feed        14 > Auto Feed       14
Signal Ground 18-25 - Ground    16,19-30
Initialise       16 > Init            31
Error            15 < Error Out       32
Select           17 > Select In       36

*******************************************************************************
*******************************************************************************

30th September 1991
Original Adapter Connections (Apple DB25 <--> PC Centronics)
============================

Following are the pins connections for my first Apple<-->PC connector. It
allowed 8-bit transfer from the PC to the Apple, but only 5 bits from the
Apple to the PC. It was designed to plug directly into the Apple's DB25. The
PC printer cable then plugged into the other side of the connector.

Description | IBM DB25 | Printer 36 | | Apple DB25 | Description
------------+----------+------------+-+------------+------------
DATA 0      |    2  O  |      2  I  |>|     1      | DATA IN  0
DATA 1      |    3  O  |      3  I  |>|    17      | DATA IN  1
DATA 2      |    4  O  |      4  I  |>|     3      | DATA IN  2
DATA 3      |    5  O  |      5  I  |>|    25      | DATA IN  3
DATA 4      |    6  O  |      6  I  |>|    14      | DATA IN  4
DATA 5      |    7  O  |      7  I  |>|    19      | DATA IN  5
DATA 6      |    8  O  |      8  I  |>|    21      | DATA IN  6
DATA 7      |    9  O  |      9  I  |>|    18      | DATA IN  7
ACK         |   10  I  |     10  O  |<|    22      | DATA OUT 3
BUSY        |   11  I  |     11  O  |<|    23      | DATA OUT 4
PAPEROUT    |   12  I  |     12  O  |<|     8      | DATA OUT 2
SELECT      |   13  I  |     13  O  |<|     6      | DATA OUT 1
ERROR       |   15  I  |     32  O  |<|     5      | DATA OUT 0

Nibble transfer protocol was an alternating bit 4 and a stop-and-wait flow
control for each nibble. Bit 4 toggled for every nibble transferred. The
problem with this arrangement was that if one side missed a toggle, it was left
waiting for the bit to toggle, and the other end was waiting for the
acknowledgement. I never got around to implementing timeouts, but it worked
well enough for me to transfer all but my copy-protected disks at ~1200cps.

*******************************************************************************
*******************************************************************************

6th October 1994
New Apple <--> PC Link Adapter (Centronics <--> Centronics)
==============================

Below is the latest design for my Apple<-->PC connector. It allows 5-bit data
transfer both ways. The biggest plus is that I can use my Apple and PC printer
cables to plug into the adaptor (I used two female Centronics sockets, the same
as what you see on the back of your printer (no, not the female DB25 serial
connector, if your printer has one)). The only down side is that it can no
longer transmit 8-bits from the PC to the Apple. My original protocol only
supported 5 bits both ways (for symmetry) so the new design fits it
perfectly. Unfortunately, I've created a new protocol incompatible with my
first attempt.

Apple            | Cent         Cent | PC
-----------------+-------------------+------------------
Data Out 0     5 |     2  >       32 |    15 Error
Data Out 1     6 |     3  >       13 |    13 Select
Data Out 2     8 |     4  >       12 |    12 Paper Out
Data Out 3    22 |     5  >       10 |    10 ACK
Data Out 4    23 |     6  >       11 |    11 Busy
Ground      2,24 | 19,16 19 16,19-30 | 18-25 Ground
Data In 3     25 |    32  <        2 |     2 Data Out 0
Data In 5     19 |    12  <        3 |     3 Data Out 1
Data In 6     21 |    13  <        4 |     4 Data Out 2
Data In 7     18 |    35  <        5 |     5 Data Out 3
ACK In        16 |    10  <        6 |     6 Data Out 4

Parallel Adapter Nibble Protocol
================================

For the new adapter, I have created a new protocol. Since only 5 data lines
exist in each direction, four are used for data and the fifth is used for
synchronisation. Bits 3-0 are the data and bit 4 is the 'clock'.

8-bit bytes are split into two 4-bit nibbles before transmission and joined
back together when received. When a byte is split into nibbles and transmitted,
the low nibble is sent first followed by the high nibble. For example, if $17
is to be transmitted, $7 is transmitted first followed by $1.

When sending a nibble, the clock is first lowered. A short wait is performed to
give the receiver a chance to notice the low clock signal. The low nibble is
sent, raising the clock signal at the same time. Another wait is performed to
give the receiver a chance to read the low nibble. The high nibble is sent,
lowering the clock signal at the same time. Another wait is performed to give
the receiver a chance to read the low nibble.

To receive a nibble, the receiver waits until the clock signal is low. Then it
waits for the clock signal to rise. When that happens it knows that a nibble
(the low nibble) has been received. The nibble is stored in a buffer. Then the
receiver waits for the clock signal to drop. When that happens it knows that
another nibble (the high nibble) has been received. That nibble is merged with
the previously received nibble to form a byte and stored in a buffer.

A diagram showing the clock signal and the phases associated with it follows:

 -.     .-------.
  |     |       |
  |     |       |
  |     |       |
  `-----'       `--------
|<--1-->|<--2-->|<--3-->|

Phase 1 is the pre-nibble phase. It extends from the time the reciever starts
scanning the clock signal, until the time a rising edge on the clock signal is
detected. Think of it as the delay between *bytes*.

Phase 2 is the low-nibble phase. It extends from the rising edge to the falling
edge of the clock signal. It must be long enough for the receiver to detect the
rising edge and read the data.

Phase 3 is the high-nibble phase. It starts from the time the falling edge is
detected. It must be long enough for the receiver to detect the falling edge
and read the data.

The length of phases 2 and 3 are usually the same since they serve the same
purpose: to give the receiver enough time to get the nibble.

The lengths of all the phases should be modifiable at the transmitter. The
receiver should not expect certain delays between bytes or nibbles, but should
have some sort of timeout mechanism to handle spurious 'clock' signals.

Apple <--> IBM Packet Protocol
==============================
This protocol is not specific to the parallel port data transfer mechanism. It
should be easily adapted to serial port communications.

Bytes are arranged into packets of length 1-4096 bytes. Each packet has encoded
type and length prefixed, and a CRC-CCITT checksum appended. For synchronisation
purposes, each packet must start with an ASCII SYN character, followed by an
ASCII SOH character. The CRC checksum includes the encoded type and length
bytes, and the data, but not the SYN and SOH characters. The packet must end
with an ASCII EOT character.

The maximum number of bytes that can be transmitted for each packet is 4103
(4 + 4096 + 3). A packet with 4096 bytes of data will have its' length given
as $000 ($1000 truncated). A packet with no data bytes cannot be transmitted
(therefore a packet will have a minimum length of 4 + 1 + 3 = 8 bytes).

 Byte 0 | Byte 1 | Byte 2 | Byte 3 | L Data bytes |CRC-CCITT Checksum|Byte L+6
76543210|76543210|76543210|76543210| ...          |76543210|76543210 |76543210
00010110|00000001|ST00LLLL|LLLLLLLL| ...          |CCCCCCCC|CCCCCCCC |00000100

S - Packet sequence (0/1) is bit 7 of byte 2.
T - Packet Type (0=supervisory,1=data) is bit 6 of byte 2.
L - Packet Length is bits 3-0 of byte 2 and all of byte 3.
C - CRC-CCITT Checksum (low byte first).

Example, a data packet (sequence 0) with a length of $3BF bytes, byte 2 will be
$83, and byte 3 will be $BF.

Supervisory Packets
-------------------

1. Packet Acknowledge:
    Data Byte 0:ACK (ASCII 6) or NAK (ASCII 21)
    The packet sequence number for these packets must match the sequence number
    of the related packet (the packet being ACK'd or NAK'd).
    For example, a packet with a sequence of 0 being ACK'd will be as follows:

     ,----------------------ASCII SYN character
     |  ,-------------------ASCII SOH character
     |  |  ,----------------sequence(0), type(0), and bits 11-8 of length(1)
     |  |  |  ,-------------bits 7-0 of length(1)
     |  |  |  |  ,----------ASCII ACK character
     |  |  |  |  |  ,--.----CRC
     |  |  |  |  |  |  |  ,-ASCII EOT character
     |  |  |  |  |  |  |  |
     v  v  v  v  v  v  v  v
    16 01 00 01 06 xx xx 04

   ** These packets are generated internally by the Packet Send/Receive
      routines. They should not be generated by user programs.

2. Sequence Synchronisation:
    Data Byte 0:SYN (ASCII 22)
    The packet sequence number is the new sequence number to be expected. The
    sender will send this packet to make sure the receiver is in-sync with its
    transmissions.
    For example, to set the receiver's current packet sequence to 1 the
    following will be sent:

     ,----------------------ASCII SYN character
     |  ,-------------------ASCII SOH character
     |  |  ,----------------sequence(1), type(0), and bits 11-8 of length(1)
     |  |  |  ,-------------bits 7-0 of length(1)
     |  |  |  |  ,----------ASCII SYN character
     |  |  |  |  |  ,--.----CRC
     |  |  |  |  |  |  |  ,-ASCII EOT character
     |  |  |  |  |  |  |  |
     v  v  v  v  v  v  v  v
    16 01 80 01 16 xx xx 04

   ** This packet is never generated by the Packet Send/Receive routines, but
      is handled completely internally by the Packet Receive routine. In other
      words, it is up to the user program to generate this packet, but at the
      receiving end the user program there will never see this packet.

  Here is how this packet works:

    1. The Sender transmits a Sequence Synchronisation packet to synchronise
       the packet sequence to 1 (as in the above example).
    2. The Receiver receives the packet. The Receiver will always receive
       Sequence Synchronisation packets (normally it would discard packets with
       an incorrect sequence number). The internal packet sequence counter is
       set and Acknowledged using the new packet sequence number. The Receiver
       increments it's internal sequence counter so that it will expect the
       *next* sequence number (i.e. from the above example it will expect 0).
    3. The Sender receives the Acknowledgement and increments its sequence
       counter so that the next packet it transmits will have the sequence
       number after the one set (i.e. from the above example it will transmit
       the next packet using sequence 0).

Data Packets
------------

For example, a data packet of sequence 1 with a length of 7 bytes and data
"HELLO",CR,LF will be as follows:

     ,----------------------------------------ASCII SYN character
     |  ,-------------------------------------ASCII SOH character
     |  |  ,----------------------------------sequence(1), type(1), and
     |  |  |                                  bits 11-8 of length(7)
     |  |  |  ,-------------------------------bits 7-0 of length(7)
     |  |  |  |  ,----------------------------H
     |  |  |  |  |  ,-------------------------E
     |  |  |  |  |  |  ,----------------------L
     |  |  |  |  |  |  |  ,-------------------L
     |  |  |  |  |  |  |  |  ,----------------O
     |  |  |  |  |  |  |  |  |  ,-------------CR
     |  |  |  |  |  |  |  |  |  |  ,----------LF
     |  |  |  |  |  |  |  |  |  |  |  ,--.----CRC
     |  |  |  |  |  |  |  |  |  |  |  |  |  ,-ASCII EOT character
     |  |  |  |  |  |  |  |  |  |  |  |  |  |
     v  v  v  v  v  v  v  v  v  v  v  v  v  v
    16 01 C0 07 41 45 4C 4C 4F 0D 0A xx xx 04

Function Interface
------------------

There are two levels of the protocol: connectionless, and connection-oriented.

Connectionless communications is the Datagram or "best try" mode. Data is sent
then forgotten.

Connection-oriented communications form a logical connection between the two
computers. Data that is sent must be acknowledged before the next lot of data
may be sent. Received data must be acknowledged as either received correctly,
or received with errors. This is also known as Idle-RQ flow control.

When receiving, the length of the buffer is specifed. When a packet is received,
the data will not exceed the specified buffer size. Any excess data is
discarded. You can tell if some data was discarded by checking buffer length
field. It will contain the length of the data received including the discarded
data.

Connection Detection
--------------------

To detect if there is a connection with the remote computer, send a sequence
synchronisation packet. If the send function times out, then it can be assumed
that the remote computer is either not turned on, connected, not running the
communications program, or not listening.

