Ms. Milazzo's interface is designed specifically with the Commodore in mind. We are adding an alternate interface which provides an RS232-compatible output. You could then use your ZX81/TS1000 to send ASCII text to an RS232 terminal, printer, or other device. We'll leave the exact implementation up to you. Although parameters like baud rate and stop bits are elegantly catered to, others (like parity check bits, presence/absence of inverse characters or lower case) will have to be added if your outside device requires them.
Some of you may recall that we had intended to publish Bob Berch's article on driving RS232 printers with your ZX81. However, since Bob's implementation has been readily available from him for some time (and at a most reasonable price), and since it was considerably longer than we have had space for in this medium, we had to postpone it, and postpone it again. Ms. Milazzo's alternative is considerably shorter, and more easily extensible to other applications.
TS2068 CHALLENGES: Can any of you 2068'ers work out a similar way of shipping ASCII text via your EAR port? This one should be easy, since your character set is already coded in ASCII. How about a routine for transmitting ZX8I programs/data to the 2068, and vice versa, through the MIC and EAR ports? In this case, you might want to take a slightly different approach, and translate the tokens as well as the alphanumeric and symbol characters. Also, you'll have to figure out a way to emulate a tape signal (Hint: "borrow" the required code snippets from the 2068 EXROM, and from David Wood's book "Practical Guide to M/L on the TS1000").
Whatever your preference machine-wise, we hope you can find uses for the techniques presented here.
The program described here consists of a portion in BASIC which is used to set the parameters, and to relocate the 327-byte Zilog Z80 machine language (ML) program which is in the first REM statement. Typically, 327 bytes can be reserved above RAMTOP by lowering it to 32441 (in 16K) using the following sequence: POKE 16388,185; POKE 16389,126; NEW; then LOAD "PET ASCII".
The computer then requests, "BAUD RATE?", which can be selected up to 2400 baud. Then it prompts "STOP BITS?" to select the number of stop bits between characters. By experience, one stop bit is usually sufficient for data speeds up to 1200 baud. At least 2 stop bits should be used for higher speeds.
In lines 290-400, the program calculates the required constants and POKEs them into the appropriate locations. The variable F in line 310 is set to the computer's clock frequency, nominally 3.25 MHz. Variable G in line 320 represents a fixed number of clock cycles in the bit length delay loop. (The "+10" adjusts the duration of the M/L commands at 40D3h and 40D4h, which only exist to allow a very fine adjustment in bit duration.) Then, "PRESS ENTER TO TRANSFER PROGRAM," and the ML routine is activated. (You can use this as a "test run" to make sure your system is working before transferring other programs.)
After the original program is NEWed, any desired BASIC program can be LOADed and transferred to a receiving computer by entering PRINT USR 32685, since the ML program is protected from the NEW command.
0 REM...(327 BYTES FOR ML)...
10 REM PET ASCII OUTPUT PROGRAM BY CAROL F. MILAZZO
20 PRINT "RELOCATE?"
30 INPUT A$
40 CLS
50 LET ORG=16514
60 LET DIS=0
70 IF A$<"Y" THEN GOTO230
80 PRINT "NEW LOCATION=";
90 INPUT LOC
100 PPINT LOC
110 LET DIS=LOC-ORG
120 FOR I=ORG TO ORG+326
130 POKE I+DIS,PEEK I
140 NEXT I
150 LET A$="166011661416619166261668416726167381674816753167881683216839"
160 FOR 1=1 TO 56 STEP 5
170 LET A=VAL A$(I TO I+4)
180 LET AD=PEEK A+256*PEEK (A+1)+DIS
190 LET H=INT (AD/256)
200 POKE A+DIS+1,H
210 POKE A+DIS,AD-256*H
220 NEXT I
230 LET BH=16587+DIS
240 LET BL=16588+DIS
250 LET SB=16624+DIS
260 LET OS=16641+DIS
270 LET OP=16758+DIS
280 PRINT "OUTSCREEN = RAND USR ";OS,"OUTPROG = PRINT USR ";OP
290 PRINT "BAUD RATE? ";
300 INPUT R
310 LET F=3.25E6
320 LET G-93+10
330 LET M=INT (F/R+.5)
340 LET C=INT ((M-G+3310)/3339)
350 LET B=(M-G-3339*C+3323)/13
360 POKE BH,C
370 POKE BL,INT B
380 PRINT R,,"STOP BITS? "
390 INPUT S
400 POKE SB,S
410 PRINT S,,"PRESS ENTER TO TRANSFER PROGRAM"
420 INPUT A$
430 PRINT USR OP
440 PRINT "BYTES"
450 PRINT
460 GOTO290
470 SAVE "PET ASCII"
480 RUN
Otherwise, the successive program lines are printed on the screen, and from there are transmitted by a call to the OUTSCREEN subroutine. This routine will stop and display any line exceeding the 704 raster screen size. Such lines should be deleted to enable OUTPROG to transfer the program. The CONTROL characters are sent in case the receiving terminal program requires them for text loading. They may be changed as required by POKEing the needed values at 4192h and 41C5h.
The OUTSCREEN subroutine transmits text printed on the screen up to the display file character counter (DF-CC), which is used as an end marker. At 4101h, the blank spaces after the last screen line are eliminated by adjusting DF-CC to point right after the last printed character. The screen contents are then scanned and converted at OUTCHAR to PET ASCII characters and graphic symbols, with any appropriate RVS ON and RVS OFF characters. When the last screen character is sent, a jump is made to OUTCR which sends a carriage return and exits the subroutine.
The OUTBYTE subroutine (40D8h) sends out each byte (loaded into the E register) through the computer's TV/TAPE port. Each bit is rotated through the carry bit, and the appropriate SPACE or MARK subroutine is called. The text byte counter is incremented before exiting back to the calling routine.
PET ASCII OUTPUT MACHINE LANGUAGE PROGRAM FOR ZX81 BY CAROL F. MILAZZO TABLE 4082 20 BE BC A2 BB Al BF AC A6 A8 A2 22 5C 24 3A 3F 4092 28 29 3E 3C 3D 2B 2D 2A 2F 3B 2C 2E 36 31 32 33 40A2 34 35 36 37 38 39 41 42 43 44 45 46 47 48 49 4A 4082 4B 4C 40 4E 4F 50 51 52 53 54 55 56 57 58 59 5A MARK 40C2 DBFE IN A,(FE) 40C4 1804 JR DELAY SPACE 40C6 D3FF OUT (FF),A 40C8 1800 JR DELAY DELAY 40CA 01015F LD BC,5F01 (2400 BAUD RATE CONSTANT) LOOP 40CD lOFE DJNZ LOOP 40CF 0D DEC C 40D0 20FB JRNZ LOOP 40D2 AF XOR A 40D3 C0 RET NZ 40D4 C0 RET NZ 40D5 C9 RET OUTCR 40D6 lE0D LD E,0D (SEND CR) OUTBYTE*40D8 CDC640 CALL SPACE (START BIT) 40DB 00 NOP 40DC 00 NOP 40DD 37 SCF NEXTBIT 40DE CBlB RR E (FETCH EACH DATA BIT) 40E0 280D JRZ STOP 40E2 3006 JRNC SP 40E4 D0 RET NC * 40E5 CDC240 CALL MARK 40E8 18F4 JR NEXTBIT SP* 40EA CDC640 CALL SPACE 40ED 18EF JR NEXTBIT STOP 40EF 1E02 LD E,02 (# OF STOP BITS) STOPBIT*40F1 CDC240 CALL MARK 40F4 1D DEC E 40F5 20FA JRNZ STOPBIT 40F7 ED4B7B40 LD BC,(407B) 40FB 03 INC BC (INCREMENT BYTE COUNTER) 40FC ED437B40 LD (407B),BC 4100 C9 RET OUTSCREEN4101 2A0E40 LD HL,(DF-CC) 4104 AF XOR A COLLAPSE4105 2B DEC HL (COLLAPSE LAST SCREEN LINE) 4106 BE CP (HL) 4107 28FC JRZ COLLAPSE 4109 CB76 BIT 6,(HL) 4l0B 20F8 JRNZ COLLAPSE 410D 23 INC HL 410E 220E40 LD (DF-CC),HL OUTSCR2 4111 1600 LD D,00 (RVS FLAG OFF) 4113 2A0C40 LD HL,(D-FILE) NEXTCHAR4116 23 INC HL 4117 E5 PUSH HL 4118 ED4B0E40 LD BC,(DF-CC) (CHECK FOR END OF SCREEN) 411C A7 AND A 411D ED42 SBC HL,BC 411F 7C LD A,H 4120 B5 OR L 4121 E1 POP HL 4122 28BB JRZ OUTCR (RETURN IF END) 4124 7E LD A,(HL) (FETCH A CHARACTER) 4125 FE76 CP 76 4127 2007 JRNZ OUTCHAR 4129 18EB JR NEXTCHAR (1800 TO SEND CR AFTER EACH LINE) ENDLINE*412B CDD640 CALL OUTCR 412E 18E6 JR NEXTCHAR OUTCHAR 4130 07 RLCA 4131 FE16 CP 16 4133 3016 JRNC NORM 4135 FE06 CP 06 4137 3812 JRC NORM 4139 FE08 CP 08 413B 380C JRC INV 413D FE0C CP 0C 413F 380A JRC NORM 4141 FE12 CP 12 4143 3804 JRC INV 4145 FE14 CP 14 4147 3802 JRC NORM INV 4149 EE01 XOR 01 NORM 414B CB3F SRL A 414D F5 PUSH AF 414E 300C JRNC RVS-OFF RVS-ON 4150 15 DEC D 4151 2805 JRZ SET-D 4153 1E12 LD E,12 (SEND RVS-ON) * 4155 CDD840 CALL OUTBYTE SET-D 4158 1601 LD D,01 415A 180A JR CONT RVS-OFF 415C 15 DEC D 415D 2005 JRNZ RESET-D 415F 1E92 LD E, 92 (SEND RVS-OFF) * 4161 CDD840 CALL OUTBYTE RESET-D 4164 1600 LD D,00 CONT 4166 Fl POP AF 4167 E5 PUSH HL 4168 0600 LD B,00 (TRANSLATE ZX81 TO PET ASCII) 416A 4F LD C,A * 416B 218240 LD HL,TABLE 416E 09 ADD HL,BC 416F 5E LD E,(HL) * 4170 CDD840 CALL OUTBYTE 4173 El POP HL 4174 18A0 JR NEXTCHAR OUTPROG 4176 CDE702 CALL FAST 4179 210024 LD HL,2400 DELAYl 417C CD460F CALL BREAK-1 (CHECK FOR BREAK KEY) 417F D0 RET NC (EXIT IF BREAK PRESSED) DELAY2 4180 l0FE DJNZ DELAY2 4182 48 LD C,B 4183 2B DEC HL 4184 7C LD A,H 4185 B5 OR L 4186 20F4 JRNZ DELAYl 4188 227B40 LD (407B),HL (ZERO BYTE COUNTER) 418B 217D40 LD HL,PROGRAM (START OF PROGRAM) 418E 22EC40 LD (403C),HL 4191 1E11 LD E,11 (SEND CONTROL Q) * 4193 CDD840 CALL OUTBYTE NEWSCREEN4196 CD2A0A CALL CLS (CLEAR SCREEN) 4199 CD460F CALL BREAK-l (CHECK BREAK KEY) 419C 3026 JRNC EXIT (EXIT IF BREAK PRESSED) 419E 2A3C40 LD HL,(403C) (CHECK FOR END OF PROGRAM) 41A1 ED4B0C40 LD BC,(D-FILE) 41A5 A7 AND A 41A6 ED42 SBC HL,BC 41A8 7C LD A,H 41A9 B5 OR L 41AA 2818 JRZ EXIT 41AC 2A3C40 LD HL,(403C) 41AF CD4507 CALL PRLINE (PRINT NEXT BASIC LINE) 41B2 2A3C40 LD HL,(403C) 41B5 23 INC HL 41B6 23 INC HL 41B7 4E LD C,(HL) 41B8 23 INC HL 41B9 46 LD B,(HL) 41BA 23 INC HL 41BB 09 ADD HL,BC 41BC 223C40 LD (403C),HL (STORE ADDRESS OF NEXT LINE) * 41BF CD0141 CALL OUTSCREEN (SEND SCREEN) 41C2 18D2 JR NEWSCREEN EXIT 41C4 1E03 LD E,03 (SEND CONTROL C) * 41C6 C3D840 JP OUTBYTE * THESE INSTRUCTIONS REQUIRE OFFSET CALCULATIONS WHEN RELOCATED CHANGE THE FOLLOWING LINES TO GET STANDARD ASCII OUTPUT FOR OTHER COMPUTERS BY ELIMINATING THE REVERSE AND GRAPHIC CHARACTERS: TABLE 4082 20 20 20 20 20 20 20 20 20 20 20 22 5C 24 3A 3F OUTCHAR 4130 E63F AND 3F 4132 1833 JR CONT+1
1 FAST
2 FOR 1=1 TO 2000
3 NEXT I
4 LET OUTSCREEN=32568 (ML above 32441)
5 LET AD=9000
6 GOSUB 21
7 PRINT " DIM A(100):FOR I=1 TO 100:READ A:NEXT I"
8 GOSUB 18
9 FOR I=0 TO 95 STEP 5
10 PRINT " DATA ";
11 FOR J=1 TO 5
12 PRINT A(I+J);
13 IF J<5 THEN PRINT ".";
14 NEXT J
15 GOSUB 18
16 NEXT I
17 STOP
18 RAND USR OUTSCREEN
19 LET AD=AD+10
20 CLS
21 PRINT AD;
22 RETURN
Graphic displays can also be sent by using the OUTSCREEN subroutine. OUTSCREEN normally ignores the NEWLINE character at the end of each display line, but for sending graphic displays these should be used to send a carriage return (CR). This is done by POKEing 00 at 412Fh. Displays produced using the AT command may set DF-CC before the end of the screen text, causing OUTSCREEN to send only that part up to DF-CC. This can be corrected by inserting the command PRINT AT 21,31; before the RAND USR OUTSCREEN within the program. Non-ASCII text, e.g. machine-language files, can be transmitted by using the OUTCR subroutine. Each text byte must be POKEd into 40D7h, followed by executing RAND USR OUTCR. For example:
1 FAST
2 FOR 1=1 TO 2000
3 NEXT I
4 LET OUTCR-32525 (ML above 32441)
5 FOR 1=32441 TO 32767 (Send PET ASCII program)
6 POKE OUTCR+1,PEEK I
7 RAND USR OUTCR
8 NEXT I
Figure 1. Schematic diagram of hardware interface to connect the output of the Timex/Sinclair ZX81 to a Commodore 64 computer.
PART RADIO SHACK# DESCRIPTION D1 276-1122 1N914 diode Q1, Q2 276-2009 NPN silicon transistor, 2N2222 etc. R1 271-010 68 ohm 1/2W resistor SO1 C1-12 24-contact polarizing connector (DIGI KEY) CR1164-1 2 polarizing keys for SOl (DIGI KEY)Point "A" is connected to the TV/TAPE output of the computer logic chip. This is pin 16 of IC1 (ULA) on the ZX81/TS1000 (junction of D9 and R29), or pin 53 of U5 (SCLD) on the T51500 (junction of D19 and R20). Point "B" is connected to +5V, and point "C" is connected to ground. In the interface circuit, D1 is used to protect the computer logic chip in case of Q1 failure. Q1 is connected as an emitter follower, identical to the common video output modification for these machines. Q2 converts the signal from Q1 to provide the proper on-off switching required by the Commodore user port. The edgeboard connector is used to connect the interface to the Commodore 64 user port. Point D is connected to pins B and C, and point E is connected to pin A of the user port.
After any text transmission is terminated, the number of bytes sent is displayed in the upper left corner of the screen. The text buffer in the receiving computer should be closed, and the transmitted text saved to disk or tape. This ASCII file must be converted into BASIC tokens. The PLUS/TERM program described above includes a utility called "TOKENIZER", which performs this task for disk-drive users. Another utility program called "RECRUNCHER" appeared in July 1985 "Compute!" and works with tape or disk drive. Sinclair BASIC programs will rarely run on other computers without some translation of commands. Translation can be done line-by-i me, or with the aid of a utility like "METABASIC" in April 1985 "Compute Gazette."
FIGURE 2
Here is an alternate interface circuit, which provides an RS232-compatible output signal. It uses an LM311 comparator, which is inexpensive, capable of about 100 mA output drive, and is commonly available. However, you could use other comparators or op amps instead.
Power can be provided with a bi-polar 9V supply, or from two 9V "transistor" batteries. Depending on the output drive requirement, a pair of alkaline batteries can run for up to about 28 hours. Note that the power on/off switch must be double-pole, to insure that both batteries are disconnected.
The connection shown is for a non-inverting configuration. If your system requires the signal to be inverted, exchange the two connections marked with "X".
Resistor R3 provides hysteresis (positive feedback) for rapid output transistions. Bypass capacitors Cl and C2 are for glitch-protection, and should be tantalum types rated at 10V or better. Exact capacitance values are non-critical, anywhere from .47 uF to 10 uF. is fine.