Classic Computer Magazine Archive COMPUTE II ISSUE 2 / JUNE/JULY 1980

Part 2: Implementing the IEEE-488 Bus on a SYM-1

DESIGNING AN IEEE-488 RECEIVER WITH THE SYM

Larry Isaacs, COMPUTE. Staff

This is the second part of an article describing the use of a SYM-1 to interface a PET to a Spinwriter with a serial interface. We will continue to divide the more complex functions into simpler sub-functions when necessary. Once the sub-functions are simple enough, they will be implemented. In the first part, the interface was divided into four sub-functions: INIT, PRINT, CYCLE, and INTERFACE. Implementations for PRINT and CYCLE have already been presented. Briefly, the PRINT routine handles the communication with the Spinwriter. By using the ETX/ACK protocol, the PRINT routine keeps the Spinwriter printing at its maximum speed. The CYCLE routine handles the handshaking necessary to transfer a byte from the IEEE 488 Bus to the SYM. For convenience, these routines are given again in the complete listing of the interface software found at the end of this article. Also, the hardware to connect the Spinwriter to the SYM is shown again in Figure 2.

Before we can begin work on the INTERFACE sub-function, we must first understand how the PET will try to communicate with the SYM using the IEEE 488 Bus. Now we will continue with a description of this communication procedure.

Communicating On The IEEE 488Bus

The next step is to become familiar with how the PET communicates on the IEEE Bus. This discussion will involve two more signal lines. These are the ATN (Attention) line and the EOI (End Or Identify) line.

Each communication on the IEEE 488 Bus can be described as a sequence of three parts. In the first part the PET identifies which device it wishes to communicate with. In the second part it sends or receives the data. And finally in third part, the PET terminates the communication sequence. Each part makes use of the byte transfer cycle described previously to transfer information. However, the information transferred in the first and third parts is differentiated from the second by the state of the ATN line. During the first and third parts the ATN line is low, indicating that the bytes transferred should be treated as commands and not data.

Here is a brief description of what happens during a communication sequence with a device, or devices, which only receives data, such as our printer. I will assume that prior to the beginning of the sequence, all devices on the bus are in the inactive state, i.e. the NRFD line is high.

The sequence begins with the PET setting the ATN line low. This brings all operating devices on the bus to the active state. The PET now executes a byte transfer cycle sending the device address to each device. Only those devices whose device address matches the one sent by the PET will continue with the communication sequence. All other devices will return to the inactive state at the end of this first part. The Commodore printers use device address 24 hex. The lower 5 bits contain the device number, in this case 4. The upper three bits, “001”, indicate that the device is to receive data. A “010” in the upper three bits would indicate the device is to send data. Now the PET may end the first part by setting the ATN line high, or transfer another byte known as the secondary address before setting ATN high. The secondary address is used to address different functions or channels within the selected device.

The second part consists of the required number of byte transfer cycles to transfer the data to the device. In most cases, the PET will signal that the last data byte is being transferred by setting the EOI line low during the last cycle. Because the EOI isn't always sent, it wouldn't be a reliable signal to use for determining the end of this part of the communication sequence.

For the third part, the PET sets the ATN line low again, and executes a byte transfer cycle which sends $3F hex to all active devices. This is the UNLISTEN command, which tells all listening devices to stop receiving data.

One requirement for the interface which may not be obvious is that once the communication sequence has reached the second part, all commands except for the UNLISTEN command should be ignored. It would not be a violation of the IEEE 488 Bus Standard for the PET to activate a device which sends data at the same time as one which receives data, and have them communicate directly with each other.

There is one other IEEE signal line which should be included in the interface. This is the IFC (Interface Clear) line. Whenever this line goes low, the interface should return to the inactive state.

Now we are ready to deal with the hardware requirements for communicating on the IEEE Bus. We will be using 6522 #2 on the SYM for the necessary I/O signals since all of the I/O lines from both ports go to the A-A connector. If necessary, the 6522 supplied as 6522 #3 could be moved to the #2 socket, losing only a few features which aren't needed for this interface. The main hardware requirement concerns a requirement for the delay between ATN going low to the time when NRFD is set low by a device. The IEEE 488 Standard calls for a maximum of 200 nanoseconds for this delay. Though the PET can't operate this fast, it does operate too fast for the SYM to meet this requirement using just software. The solution to obtain the necessary speed is to selectively send the ATN signal back out the NRFD line. The SYM can then assume control of the NRFD line when it is ready. The only other hardware needed are a couple of open-collector gates for the Wire-or requirements of the NRFD and NDAC lines. The circuitry shown in Figure 1 will meet these requirements.

Interface

The main function of the INTERFACE sub-function is to handle the communication sequence for the IEEE

Listing 4

procedure INTERFACE

procedure ATNIRQ begin … end; {handles the IEEE communication}
procedure IFCIRQ begin … end; {resets the interface}

begin {INTERFACE procedure}
   repeat
    if INTERRUPT=TRUE then
       begin
          if IRQ=ATN then ATNIRQ;
          if IRQ=IFC then IFCIRQ
       end
   until 2+2=5 {hopefully repeat forever}
end;

Bus. The first decision we must make is how the INTERFACE software will know when a communication sequence has begun, or when the IFC line goes low. Since the IFC signal is supposed to reset the device regardless of its current state, this signal should be tied to an interrupt. For greater flexibility we will tie the ATN line to an interrupt as well. This will allow the SYM to do other things when not being used as an interface.

The use of interrupts now provides a basis for dividing the INTERFACE sub-function into smaller parts. Listing 4 shows my division of the INTERFACE sub-function.

At this point we are almost ready to write the assembly language for the remaining parts of the software. However, ATNIRQ needs one more division. This involves addressing the question of how much intelligence to put in the interface. One answer is to program ATNIRQ in a way that leaves the door open for expansion. This can be done easily using the secondary address to call different interface routines. The division for ATNIRQ is shown in Listing 5. The “case” statement in this listing is a multiway subroutine jump. If SECADDRS is 0 when the “case” statement is executed, the DUMPCHRS procedure will be executed. For other secondary addresses, the DUMPCHRS procedure will be executed.

Listing 5

procedure ATNIRQ

procedure ATNINIT; begin … end; {get ready for communication}
procedure SENDASCII; begin … end; {input data and print it}
procedure DUMPCHRS; begin … end; {ignore data}

begin {ATNIRQ statements}
CYCLE; {get device address}
if DATA=MLA then
   begin
      ATNINIT;
      CYCLE; {get next byte, possibly a secondary address}
      if ATN=LOW then
         begin
            SECADDRS := DATA;
            CYCLE
         end;
      case SECADDRS of
            0 : SENDASCII;
        1..15 : DUMPCHRS;
      end {case statement}
   end {if statement}
end; {ATNIRQ}

Now we can write the assembly language for INIT, then IFCIRQ, and finally ATNIRQ. Not clearly shown by the preceeding PASCAL programs is how the machine language should actually handle the interrupts. After an interrupt occurs, the first thing the machine language must do is save the register contents. Then it must test to see what interrupt occured. If it was an ATN interrupt, then the current stack pointer must be saved and ATN interrupts disabled before continuing with the rest of the ATNIRQ routine. If the interrupt was an IFC interrupt, the IFCIRQ routine should test to see if the ATNIRQ routine was executing. If it was, the IFCIRQ routine must restore the stack pointer to the value saved by ATNIRQ and reenable the ATN interrupt before restoring the registers and returning to the interrupted program.

The full listing of the assembly language for the interface is given in Listing 6. I've tried to write the assembly language so it can be easily expanded. Just remember that when you put a different routine in SCTABLE, the first data byte will have already been fetched by CYCLE when your routine is entered.

Summary

I've tried to make this article as much an example of interface design as one describing an actual interface. Most of the material presented dealt with needed facts or the steps involved in reaching a solution. I do not wish to imply that designing an interface should proceed from start to finish as easily as this article makes it seem. It is very likely that during your design, you will come upon a piece of new information or see a different approach which would have been highly useful at some previous step. This occured a few times during this design. Sometimes it is necessary or perhaps desireable to return to that previous step and take a different path. However, if you do enough preparation and planning before you begin the design process, you shouldn't have to backup too many times.

	 	 	 	0010 	; IEEE INTERFACE 	 	 	
	 	 	 	0020 	; WITH HARDWARE
	 	 	 	0030 	; VERSION 2.5
	 	 	 	0040 	; 	 	 	
	 	 	 	0050 	; CONSTANTS 	 	 	
	 	 	 	0060 	UNLISTEN .DE 	$3F 	
	 	 	 	0070 	BS 	.DE 	$08 	
	 	 	 	0080 	UNDLN 	.DE 	$5F 	
	 	 	 	0090 	LF 	.DE 	$0A 	
	 	 	 	0100 	COLON 	.DE 	$3A 	
	 	 	 	0110 	SPACE 	.DE 	$20 	
	 	 	 	0120 	COMMA 	.DE 	$2C 	
	 	 	 	0130 	CR 	.DE 	$0D 	
	 	 	 	0140 	; 	 	 	
	 	 	 	0150 	; VARIABLES 	 	
	 	 	 	0160 	COUNT 	.DE 	$E0 	
	 	 	 	0170 	SIGNALS	.DE 	$E1 	
	 	 	 	0180 	DATA 	.DE 	$E2 	
	 	 	 	0190 	MLA1 	.DE 	$E3 	
	 	 	 	0200 	SEC.ADDRS	.DE 	$E4 	
	 	 	 	0210 	TEMP 	.DE 	$E5 	
	 	 	 	0220 	LENGTH 	.DE 	$E6 	
	 	 	 	0230 	NL.FLAG 	.DE 	$E7 	
	 	 	 	0240 	SCAN.CNT 	.DE 	$E8 	
	 	 	 	0250 	F.LEN 	.DE 	$E9 	
	 	 	 	0260 	SP.IEEE 	.DE 	$EA 	
	 	 	 	0270 	; 	 	 	
	 	 	 	0280 	; ADDRESSES 	 	
	 	 	 	0290 	ACCESS 	.DE 	$8B86 	
	 	 	 	0300 	TOUFL 	.DE 	$A654 	
	 	 	 	0310 	SDBYT 	.DE 	$A651 	
	 	 	 	0320 	TECHO 	.DE 	$A653 	
	 	 	 	0330 	OUTCHR 	.DE 	$8A47 	
	 	 	 	0340 	INCHR 	.DE 	$8A58 	
	 	 	 	0350 	CRLF 	.DE 	$834D 	
	 	 	 	0360 	TOUT 	.DE 	$8AA0 	
	 	 	 	0370 	@2ACR 	.DE 	$A80B 	
	 	 	 	0380 	@2DDRA 	.DE 	$A803 	
	 	 	 	0390 	@2DDRB 	.DE 	$A802 	
	 	 	 	0400 	@2PCR 	.DE 	$A80C 	
	 	 	 	0410 	@2IER 	.DE 	$A80E 	
	 	 	 	0420 	@2IORB 	.DE 	$A800 	
	 	 	 	0430 	@2IORA 	.DE 	$A801 	
	 	 	 	0440 	@2IFR 	.DE 	$A80D 	
	 	 	 	0450 	OUTVEC 	.DE 	$A663 	
	 	 	 	0460 	UIRQVC 	.DE 	$A678 	
	 	 	 	0470 	IND.JMP 	.DE 	$EE 	
	 	 	 	0480 	; 	 	 	
	 	 	 	0490 	 	.BA 	$200 	
0200– 	20 	86 	8B 	0500 	INIT 	JSR 	ACCESS 	;INITIALIZATION
0203– 	A9 	24 	 	0510 	 	LDA 	#$24 	
0205– 	85 	E3 	 	0520 	 	STA 	*MLA1 	;MY LISTEN ADDRESS
0207– 	A9 	90 	 	0530 	INIT.SYM 	LDA 	#$90 	
0209– 	8D 	54 	A6 	0540 	 	STA 	TOUFL 	;ENABLE CRT
020C– 	A9 	10 	 	0550 	 	LDA 	#$10 	
020E– 	8D 	51 	A6 	0560 	 	STA 	SDBYT 	;ENABLE CRT
0211– 	A9 	00 	 	0570 	 	LDA 	#$00 	
0213– 	8D 	53 	A6 	0580 	 	STA 	TECHO 	;OUTPUT & NO ECHO
0216– 	A9 	A0 	 	0590 	 	LDA 	#L, TOUT 	;SET OUTPUT VECTOR
0218– 	8D 	64 	A6 	0600 	 	STA 	OUTVEC+$1 	
021B- 	A9 	8A 	 	0610 	 	LDA 	#H, TOUT 	
021D- 	8D 	65 	A6 	0620 	 	STA 	OUTVEC+$2 	
0220- 	A9 	53 	 	0630 	 	LDA 	#L, INTERFACE 	
0222- 	8D 	78 	A6 	0640 	 	STA 	UIRQVC 	;SET USER IRQ VECTOR
0225- 	A9 	02 	 	0650 	 	LDA 	#H, INTERFACE 	
0227- 	8D 	79 	A6 	0660 	 	STA 	UIRQVC+$1 	
022A- 	A9 	02 	 	0670 	 	LDA 	#$02 	
022C- 	85 	E0 	 	0680 	 	STA 	*COUNT 	
022E- 	A9 	00 	 	0690 INITPORTS 	LDA 	#$00 	
0230- 	8D 	0B 	A8 	0700 	 	STA 	@2ACR 	; NO LATCHING
0233- 	8D 	03 	A8 	0710 	 	STA 	@2DDRA 	;2PA7-2PA0 ARE INPUTS
0236- 	A9 	07 	 	0720 	 	LDA 	#$07 	
0238- 	8D 	02 	A8 	0730 	 	STA 	@2DDRB 	;3PB2-3PB0 ARE OUTPUTS
023B- 	A9 	04 	 	0740 	 	LDA 	#$04 	
023D- 	8D 	0C 	A8 	0750 	 	STA 	@2PCR 	;INTERRUPTS
0240- 	20 	47 	02 	0760 	 	JSR 	EN.IEEE 	;ENABLE IRQS
0243- 	58 	 	 	0770 	 	CLI 	 	
0244- 	4C 	44 	02 	0780 	IDLE 	JMP 	IDLE 	;WAIT REAL FAST
	 	 	 	0790 	; 	 	 	
	 	 	 	0800 	; 	 	 	
0247- 	78 	 	 	0810 	EN.IEEE SEI 	 	
0248- 	A9 	83 	 	0820 	 	LDA 	#$83 	;ENABLE ATN AND IFC
024A- 	8D 	0E 	A8 	0830 	 	STA 	@2IER 	; INTERRUPTS
024D- 	A9 	06 	 	0840 	 	LDA 	#$06 	
024F- 	8D 	00 	A8 	0850 	 	STA 	@2IORB 	;NDAC=1, NRFD=ATN
0252- 	60 	 	 	0860 	 	RTS 	 	
	 	 	 	0870 	; 	 	 	
	 	 	 	0880 	; 	 	 	
0253- 	48 	 	 	0890	INTERFACE PHA 	;SAVE REGISTERS 	
0254- 	98 	 	 	0900 	 	TYA 	 	
0255- 	48 	 	 	0910 	 	PHA 	 	
0256- 	8A 	 	 	0920 	 	TXA 	 	
0257- 	48 	 	 	0930 	 	PHA 	 	
0258- 	AD 	0D 	A8 	0940 	 	LDA 	@2IFR 	
025B- 	10 	1D 	 	0950 	 	BPL 	EXIT.INTF
025D- 	29 	03 	 	0960 	IEEE.IRQ 	AND 	#$03 	;WHICH INTERRUPT?
025F- 	C9 	01 	 	0970 	 	CMP 	#$01 	
0261- 	F0 	1D 	 	0980 	 	BEQ 	ATN.IRQ 	
0263- 	C9 	02 	 	0990 	 	CMP 	#$02 	
0265- 	F0 	03 	 	1000 	 	BEQ 	IFC.IRQ
0267- 	4C 	7A 	02 	1010 	 	JMP 	EXIT.INTF 	
026A- 	AD 	01 	A8 	1020 	IFC.IRQ 	LDA 	@2IORA 	;CLEAR INTERRUPT
026D- 	A9 	01 	 	1030 	 	LDA 	#$01 	
026F- 	2C 	0E 	A8 	1040 	 	BIT 	@2IER 	;IEEE ACTIVE?
0272- 	D0 	06 	 	1050 	 	BNE 	EXIT.INTF 	;EXIT INTERFACE
0274- 	A6 	EA 	 	1060 	IEEE.OFF 	LDX 	*SP.IEEE 	
0276- 	9A 	 	 	1070 	 	TXS 	;RESTORE STACK POINTER 	
0277- 	20 	47 	02 	1080 	 	JSR 	EN.IEEE 	
027A- 	68 	 	 	1090 	EXIT.INTF	PLA 	 	
027B- 	AA 	 	 	1100 	 	TAX 	 	
027C- 	68 	 	 	1110 	 	PLA 	 	
027D- 	A8 	 	 	1120 	 	TAY 	 	
027E- 	68 	 	 	1130 	 	PLA 	 	
027F- 	40 	 	 	1140 	 	RTI 	 	
	 	 	 	1150 	; 	 	 	
	 	 	 	1160 	; 	 	 	
0280- 	BA 	 	 	1170 	ATN.IRQ 	TSX 	 	
0281- 	8E 	EA 	00 	1180 	 	STX 	SP.IEEE 	;SAVE STACK POINTER
0284- 	AD 	01 	A8 	1190 	ATNINIT 	LDA 	@2IORA 	;CLEAR INTERRUPT
0287- 	A9 	05 	 	1200 	 	LDA 	#$05 	
0289- 	8D 	00 	A8 	1210 	 	STA 	@2IORB 	;SET NDAC=0 NRFD=0
028C- 	A9 	01 	 	1220 	 	LDA 	#$01 	
028E- 	8D 	00 	A8 	1230 	 	STA 	@2IORB 	;TURN OFF ATN=NRFD
0291- 	8D 	0E 	A8 	1240 	 	STA 	@2IER 	;TURN OFF ATN IRQS
0294- 	58 	 	 	1250 	 	CLI 	 	
0295- 	A9 	00 	 	1260 	 	LDA 	#$00 	
0297- 	85 	E4 	 	1270 	 	STA 	*SEC.ADDRS 	;INIT SEC. ADDRS
0299- 	20 	EF 	02 	1280 	 	JSR 	CYCLE 	
029C- 	A5 	E2 	 	1290 	 	LDA 	*DATA 	
029E- 	C5 	E3 	 	1300 	 	CMP 	*MLAI 	
02A0- 	F0 	0C 	 	1310 	 	BEQ 	DEVICE1 	;BRANCH IF MY ADDRESS
02A2- 	A9 	02 	 	1320 	EXIT.IEEE	LDA 	#$02 	
02A4- 	8D 	00 	A8 	1330 	 	STA 	@2IORB 	;RELEASE ATN=NRFD
02A7- 	2C 	00 	A8 	1340 	@15 	BIT 	@2IORB 	
02AA- 	30 	FB 	 	1350 	 	BMI 	@15 	;WAIT FOR ATN=1
02AC- 	10 	BC 	 	1360 	 	BPL 	IFC.IRQ 	;BR ALWAYS
	 	 	 	1370 	; 	 	 	
02AE- 	20 	EF 	02 	1380 	DEVICE1	JSR 	CYCLE 	
02B1- 	24 	E1 	 	1390 	 	BIT 	*SIGNALS 	;SECONDARY ADDRESS?
02B3- 	10 	09 	 	1400 	 	BPL 	@3 	;BRANCH IF ATN IS OFF
02B5- 	A5 	E2 	 	1410 	 	LDA 	*DATA 	;GET SECONDARY ADDRESS
02B7- 	29 	0F 	 	1420 	 	AND 	#$0F 	;ALLOW 16 SEC.ADDRS'S
02B9- 	85 	E4 	 	1430 	 	STA 	*SEC.ADDRS 	
02BB- 	20 	EF 	02 	1440 	 	JSR 	CYCLE 	;GET FIRST CHAR.
02BE- 	A5 	E4 	 	1450 	@3 	LDA 	*SEC.ADDRS 	
02C0- 	0A 	 	 	1460 	 	ASL 	A 	
02C1- 	AA 	 	 	1470 	 	TAX 	 	
02C2- 	BD 	CF 	02 	1480 	 	LDA 	SCTABLE,X 	;FIX POINTER TO
02C5- 	85 	EE 	 	1490 	 	STA 	*IND.JMP 	; SELECTED ROUTINE
02C7- 	BD 	D0 	02 	1500 	 	LDA 	SCTABLE+$1,X 	
02CA- 	85 	EF 	 	1510 	 	STA 	*IND.JMP+$1 	
02CC- 	6C 	EE 	00 	1520 	 	JMP 	(IND.JMP) 	
02CF- 	37 	03 	 	1530 	SCTABLE 	.SI 	SENDASCII 	;NOMAL PRINTING
02D1- 	47 	03 	 	1540 	 	.SI 	DUMPCHRS 	
02D3- 	47 	03 	 	1550 	 	.SI 	DUMPCHRS 	
02D5- 	47 	03 	 	1560 	 	.SI 	DUMPCHRS 	
02D7- 	47 	03 	 	1570 	 	.SI 	DUMPCHRS 	
02D9- 	47 	03 	 	1580 	 	.SI 	DUMPCHRS 	
02DB- 	47 	03 	 	1590 	 	.SI 	DUMPCHRS 	
02DD- 	47 	03 	 	1600 	 	.SI 	DUMPCHRS 	
02DF- 	47 	03 	 	1610 	 	.SI 	DUMPCHRS 	
02E1- 	47 	03 	 	1620 	 	.SI 	DUMPCHRS 	
02E3- 	47 	03 	 	1630 	 	.SI 	DUMPCHRS 	
02E5- 	47 	03 	 	1640 	 	.SI 	DUMPCHRS 	
02E7- 	47 	03 	 	1650 	 	.SI 	DUMPCHRS 	
02E9- 	47 	03 	 	1660 	 	.SI 	DUMPCHRS 	
02EB- 	47 	03 	 	1670 	 	.SI 	DUMPCHRS 	
02ED- 	47 	03 	 	1680 	 	.SI 	DUMPCHRS 	
	 	 	 	1690 	; 	 	 	
	 	 	 	1700 	; 	 	 	
02EF- 	A9 	03 	 	1710 	CYCLE 	LDA 	#$03 	
02F1- 	8D 	00 	A8 	1720 	 	STA 	@2IORB 	;NRFD=1 NDAC=0
02F4- 	2C 	00 	A8 	1730 	@1 	BIT 	@2IORB 	;TEST DAV
02F7- 	70 	FB 	 	1740 	 	BVS 	@1 	;BRANCH IF DAV=1
02F9- 	6A 	 	 	1750 	 	ROR 	A 	
02FA- 	8D 	00 	A8 	1760 	 	STA 	@2IORB ;	NRFD=0 NDAC=0
02FD- 	AD 	01 	A8 	1770 	 	LDA 	@2IORA 	
0300- 	49 	FF 	 	1780 	 	EOR 	#$FF 	
0302- 	85 	E2 	 	1790 	 	STA 	*DATA 	
0304- 	AD 	00 	A8 	1800 	 	LDA 	@2IORB 	
0307- 	85 	E1 	 	1810 	 	STA 	*SIGNALS 	
0309- 	A9 	00 	 	1820 	 	LDA 	#$00 	
030B- 	8D 	00 	A8 	1830 	 	STA 	@2IORB 	;NRFD=0 NDAC=1
030E- 	2C 	00 	A8 	1840 	@2 	BIT 	@2IORB 	
0311- 	50 	FB 	 	1850 	 	BVC 	@2 	;BRANCH IF DAV=0
0313- 	A9 	01 	 	1860 	 	LDA 	#$01 	
0315- 	8D 	00 	A8 	1870 	 	STA 	@2IORB 	;NRFD=0 NDAC=0
0318- 	60 	 	 	1880 	 	RTS 	 	
0319- 	20 	47 	8A 	1890 	PRINT 	JSR 	OUTCHR 	;PRINT AND INC. COUNT
031C- 	E6 	E0 	 	1900 	 	INC 	*COUNT 	
031E- 	DO 	OC 	 	1910 	 	BNE 	RETURN 	
0320- 	A9 	03 	 	1920 	ACK 	LDA 	#$03 	;ASCII ETX
0322- 	20 	47 	8A 	1930 	 	JSR 	OUTCHR 	
0325- 	20 	58 	8A 	1940 	 	JSR 	INCHR 	;WAIT FOR ACK
0328- 	A9 	02 	 	1950 	 	LDA 	#$02 	
032A- 	85 	E0 	 	1960 	 	STA 	*COUNT 	
032C- 	60 	 	 	1970 	RETURN 	RTS 	 	
	 	 	 	1980 	; 	 	 	
	 	 	 	1990 	; 	 	 	
032D- 	A5 	E2 	 	2000 	@18 	LDA 	*DATA 	
032F- 	29 	7F 	 	2010 	 	AND 	#$7F 	
0331- 	20 	19 	03 	2020 	 	JSR 	PRINT 	
0334- 	20 	EF 	02 	2030 	NEXT 	JSR 	CYCLE 	
0337- 	24 	E1 	 	2040 	SENDASCII 	BIT 	*SIGNALS 	
0339- 	10 	F2 	 	2050 	 	BPL 	@18 	;BR IF ATN=1
033B- 	A5 	E2 	 	2060 	 	LDA 	*DATA 	
033D- 	C9 	3F 	 	2070 	 	CMP 	#UNLISTEN 	
033F- 	D0 	F3 	 	2080 	 	BNE 	NEXT 	
0341- 	4C 	A2 	02 	2090 	 	JMP 	EXIT.IEEE 	
	 	 	 	2100 	; 	 	 	
	 	 	 	2110 	; 	 	 	
0344- 	20 	EF 	02 	2120 	NEXT2 	JSR 	CYCLE 	
0347- 	24 	E1 	 	2130 	DUMPCHRS 	BIT 	*SIGNALS 	
0349- 	10 	F9 	 	2140 	 	BPL 	NEXT2 	
034B- 	A5 	E2 	 	2150 	 	LDA 	*DATA 	
034D- 	C9 	3F 	 	2160 	 	CMP 	#UNLISTEN 	
034F- 	D0 	F3 	 	2170 	 	BNE 	NEXT2 	
0351- 	4C 	A2 	02 	2180 	 	JMP 	EXIT.IEEE 	
0354- 	00 	 	 	2190 	 	.BY 	$0 	
	 	 	 	2200 	 	.EN 	 	
SYM to Spinwriter Hardware
Editor's Note: For those of you who don't have issue 1, we're reprinting these two charts. RCL

TABLE 1
NAME SET BY DESCRIPTION
DI01-DI08 Talker Data Input/Output. These lines carry the commands and data.
NRFD Listener Not Ready for Data. When low, it means the device is not ready to receive data. It is set high when the device is ready.
DAV Talker Data Valid. When high, it means the data on the data lines is not valid. It is set low once all NRFD goes high and valid data has been placed on the data lines.
NDAC Listener Not Data Accepted. When low, it means that the data has not been accepted. It is set low once DAV goes low and the data has been latched.
ATN Talker Attention. Signals that the byte on the DIO liens is a command.
EIO Talker End Or Identify. Signals that the last data byte is being transferred.
IFC Interface Clear. Resets all device.
Figure 1