Serial interface with RTS CTS handshake

To use a HEathkit H14 matrix printer in 1980 I have written a serial send character routine, inspired by OUTCH on Port B pin 0.
The first version was simple, like OUTCH, at low speed to let the printer have time to do its work.
The second version added RTS/CTS handshaking via a second Port B pin as input.
Both were published in the Dutch KIM Club magazine in 1980 and 1981, together with a parallel keyboard routine and integration into the MICO ADE Editor/Assembler.

Here I present the drivers, in a more general format to have a second serial output on the KIM-1 optionally with handshake.

The hardware to adapt the KIM-1 to the RS232C levels can be kept simple. Here some examples:

You can find the sources in TASM32 format here.


0001   0000             ;
0002   0000             ; Serial output for example to drive a printer connected to a KIM-1
0003   0000             ; 1980 Original by Hans Otten
0004   0000             ; 2026 Cleaned of MICRO ADE artefacts and converted to TASM 
0005   0000             ;
0006   0000             ; Original in MICRO ADE syntax, curent version TASM32 Hans Otten, 2026
0007   0000             ;
0008   0000             ; Serial output routine (inspired by OUTCH in KIM-1 monitor) 
0009   0000             ; 
0010   0000             ; Send a byte in RS232C format via a PIA bit
0011   0000             ; 
0012   0000             ; Choose MASK0 and MASK1 so any pin of a PIA can be ued
0013   0000             ; Choose OUT for any PIA 6520/6521/6522/6530/6820/21. A 6522 VIA needs other initialization
0014   0000             ;
0015   0000             ; The baud rate is determined by using the following table for calling delay routine
0016   0000             ; BAUD    A   Y
0017   0000             ;   75   189  10
0018   0000             ;  110    80  0A
0019   0000             ;  300    9C  03
0020   0000             ;  600    D8  01
0021   0000             ; 1200    71  01
0022   0000             ; 2400        4C
0023   0000             ; 4800        22
0024   0000             ; 9600        14
0025   0000             ;
0026   0000             ; Use the second delay routine if only one value is given, w.o.w. above 1200 baud.
0027   0000             ;
0028   0000             ; In the following driver pin PB0 of the KIM-1 is chosen as output, and a baudrate of 4800. 
0029   0000             ; Adapt OUT, TI, TII, MSKO, MASKI and choose the applicable delay routine
0030   0000             ;
0031   0000             ; Serial driver without handshake via PB0 KIM-1  
0032   0000             ; Original Hans Otten KIM Kenner 12
0033   0000             ;
0034   0000             ;
0035   0000             ; Zeropage used, only during sending character
0036   0000             ;
0037   0000             CHAR	= $FE
0038   0000             TEMP	= $FD 
0039   0000             TMPX	= $FC
0040   0000             ;
0041   0000             MASKI	= $01				; set PB0 bit 0 of port for serial OUT 
0042   0000             MASKO	= $FE				; clear PB	 
0043   0000             ;
0044   0000             ; Port PBO address
0045   0000             ;
0046   0000             OUT		=  $1702	; PBDD data Port B
0047   0000             OUTD	=  $1703	; PBD  data direction Port B
0048   0000             
0049   0000             ;
0050   0200             		.ORG 	$0200
0051   0200             ;		
0052   0200 48          OUTPR	PHA					; save character
0053   0201 84 FD       		STY		TEMP		; save Y
0054   0203 86 FC       		STX		TMPX		; save X
0055   0205 85 FE       		STA		CHAR		; save character to send
0056   0207 AD 03 17    		LDA 	OUTD		;
0057   020A 09 01       		ORA		#MASKI		;
0058   020C 8D 03 17    		STA 	OUTD		; set Port B PB0 as output
0059   020F AD 02 17    		LDA		OUT			;
0060   0212 09 01       		ORA		#MASKI		; 
0061   0214 8D 02 17    		STA		OUT			; 
0062   0217 20 51 02    		JSR		TDELAY		; send out startbit 1
0063   021A A2 08       		LDX		#$08		; 8N1 8 databits
0064   021C AD 02 17    NEXTB	LDA		OUT			
0065   021F 46 FE       		LSR		CHAR		; lsb in carry
0066   0221 B0 04       		BCS		ONE			; bit is 1?
0067   0223 09 01       		ORA		#MASKI		; 
0068   0225 90 02       		BCC		BOUT			; set bit
0069   0227 29 FE       ONE		AND		#MASKO		; bit is 0
0070   0229 8D 02 17    BOUT	STA		OUT			; set bit
0071   022C 20 51 02    		JSR		TDELAY		; wait bit time
0072   022F CA          		DEX					; next bit
0073   0230 D0 EA       		BNE		NEXTB		;
0074   0232 AD 02 17    		LDA		OUT			; stop bit
0075   0235 29 FE       		AND		#MASKO		; is zero	
0076   0237 8D 02 17    		STA 	OUT		
0077   023A 20 51 02    		JSR 	TDELAY
0078   023D             ;		JSR		TDELAY		; if you want 2 stop bits
0079   023D A6 FC       		LDX		TMPX		; resatore X, Y, A
0080   023F A4 FD       		LDY		TEMP
0081   0241 68          		PLA
0082   0242 60          		RTS
0083   0243             
0084   0243             ;
0085   0243             ; 	Delay for 110 baud A, Y from table
0086   0243             ;
0087   0243 A0 0A       DELAY	LDY		#$0A		
0088   0245 A9 80       OLOOP	LDA		#$80
0089   0247 38          ILOOP	SEC
0090   0248 E9 01       		SBC		#$01		; inner loop A*7 -1
0091   024A D0 FB       		BNE		ILOOP
0092   024C EA          		NOP
0093   024D 88          		DEY
0094   024E D0 F5       		BNE		OLOOP		; 
0095   0250 60          		RTS
0096   0251             	
0097   0251 A0 0E       TDELAY	LDY		#14			; time = Y+5 -1
0098   0253 88          TDLOOP	DEY
0099   0254 D0 FD       		BNE 	TDLOOP
0100   0256 60          		RTS
0101   0257             		
0102   0257             		.END



Label        Value      Label        Value      Label        Value
------------------      ------------------      ------------------
BOUT          0229      CHAR          00FE      DELAY         0243      
ILOOP         0247      MASKI         0001      MASKO         00FE      
NEXTB         021C      OUT           1702      OUTD          1703      
OUTPR         0200      ONE           0227      OLOOP         0245      
TEMP          00FD      TMPX          00FC      TDELAY        0251      
TDLOOP        0253      

tasm: Number of errors = 0


0001   0000             ;
0002   0000             ; Serial output for example to drive e.g. a serial interface printer connected to a KIM-1
0003   0000             ; 1980 Original by Hans Otten
0004   0000             ; 1981 adapted to RTS CTS handshaking
0005   0000             ; 2026 Cleaned of MICRO ADE artefacts and converted to TASM 
0006   0000             ;
0007   0000             ; Original in MICRO ADE syntax, curent version TASM32 Hans Otten, 2026
0008   0000             ;
0009   0000             ; Serial output routine (inspired by OUTCH in KIM-1 monitor) 
0010   0000             ; 
0011   0000             ; Send a byte in RS232C format via a PIA bit
0012   0000             ; 
0013   0000             ; Choose MASK0 and MASK1 so any pin of a Port can be used for serial output
0014   0000             ; Chsooe MSKCTS to select a pin for input of the RTS/CTA handshake line.
0015   0000             ; Assumed both pins are on the same port.
0016   0000             ; Choose OUT for any PIA 6520/6521/6522/6530/6820/21. A 6522 VIA needs other initialization
0017   0000             ;
0018   0000             ; The baud rate is determined by using the following table for calling delay routine
0019   0000             ; BAUD    A   Y
0020   0000             ;   75   189  10
0021   0000             ;  110    80  0A
0022   0000             ;  300    9C  03
0023   0000             ;  600    D8  01
0024   0000             ; 1200    71  01
0025   0000             ; 2400        4C
0026   0000             ; 4800        22
0027   0000             ; 9600        14
0028   0000             ;
0029   0000             ; Use the second delay routine if only one value is given, w.ow above 1200 baud.
0030   0000             ;
0031   0000             ; In the following driver pin PB0 of the KIM-1 is chosen as output, and a baudrate of 4800
0032   0000             ; For RTS/CTS handling pin PB1 is used as input
0033   0000             ; Adapt OUT, TI, TII, MASKO, MASKI and MSKCTS and choose the applicable delay routine
0034   0000             ;
0035   0000             ; Serial driver with via PB0 KIM-1  
0036   0000             ; Original Hans Otten PGJ de Beer KIM Kenner 19
0037   0000             ;
0038   0000             ; Zeropage used, only during sending character
0039   0000             ;
0040   0000             CHAR	= $FE
0041   0000             TEMP	= $FD 
0042   0000             TMPX	= $FC
0043   0000             ;
0044   0000             MASKI	= $01				; set PB0 bit 0 of port for serial OUT 
0045   0000             MASKO	= $FE				; clear PB	 
0046   0000             MSKCTS  = $02				; isolate RTS CTS pin, here PB1
0047   0000             MSKCTI	= $FD 
0048   0000             ;
0049   0000             ; Port PBO, PB1 addresses
0050   0000             ;
0051   0000             OUT		=  $1702	; PBDD data  Port B
0052   0000             OUTD	=  $1703	; PBD  data direction Port B
0053   0000             
0054   0000             ;
0055   0300             		.ORG 	$0300
0056   0300             ;		
0057   0300 08          OUTPR	PHP
0058   0301 48          		PHA					; save character
0059   0302 84 FD       		STY		TEMP		; save Y
0060   0304 86 FC       		STX		TMPX		; save X
0061   0306 85 FE       		STA		CHAR		; save character to send
0062   0308 AD 03 17    		LDA 	OUTD		;
0063   030B 09 01       		ORA		#MASKI		; output pin serial
0064   030D 29 FD       		AND		#MSKCTI		; input pin RTS
0065   030F 8D 03 17    		STA 	OUTD		; set Port B PB0 as output, PB1 as input
0066   0312 AD 02 17    BUFF	LDA		OUT
0067   0315 29 02       		AND		#MSKCTS		; is RTS active?
0068   0317 F0 F9       		BEQ		BUFF		; wait
0069   0319 AD 02 17    		LDA		OUT			;
0070   031C 09 01       		ORA		#MASKI		; 
0071   031E 8D 02 17    		STA		OUT			; 
0072   0321 20 5B 03    		JSR		TDELAY		; send out startbit 1
0073   0324 A2 08       		LDX		#$08		; 8N1 8 databits
0074   0326 AD 02 17    NEXTB	LDA		OUT			
0075   0329 46 FE       		LSR		CHAR		; lsb in carry
0076   032B B0 04       		BCS		ONE			; bit is 1?
0077   032D 09 01       		ORA		#MASKI		; 
0078   032F 90 02       		BCC		BOUT			; set bit
0079   0331 29 FE       ONE		AND		#MASKO		; bit is 0
0080   0333 8D 02 17    BOUT	STA		OUT			; set bit
0081   0336 20 5B 03    		JSR		TDELAY		; wait bit time
0082   0339 CA          		DEX					; next bit
0083   033A D0 EA       		BNE		NEXTB		;
0084   033C AD 02 17    		LDA		OUT			; stop bit
0085   033F 29 FE       		AND		#MASKO		; is zero	
0086   0341 8D 02 17    		STA 	OUT		
0087   0344 20 5B 03    		JSR 	TDELAY
0088   0347             ;		JSR		TDELAY		; if you want 2 stop bits
0089   0347 A6 FC       		LDX		TMPX		; resatore X, Y, A
0090   0349 A4 FD       		LDY		TEMP
0091   034B 68          		PLA
0092   034C 60          		RTS
0093   034D             
0094   034D             ;
0095   034D             ; 	Delay for 110 baud A, Y from table
0096   034D             ;
0097   034D A0 0A       DELAY	LDY		#$0A		
0098   034F A9 80       OLOOP	LDA		#$80
0099   0351 38          ILOOP	SEC
0100   0352 E9 01       		SBC		#$01		; inner loop A*7 -1
0101   0354 D0 FB       		BNE		ILOOP
0102   0356 EA          		NOP
0103   0357 88          		DEY
0104   0358 D0 F5       		BNE		OLOOP		; 
0105   035A 60          		RTS
0106   035B             	
0107   035B A0 0E       TDELAY	LDY		#14			; time = Y+5 -1
0108   035D 88          TDLOOP	DEY
0109   035E D0 FD       		BNE 	TDLOOP
0110   0360 60          		RTS
0111   0361             		
0112   0361             		.END



Label        Value      Label        Value      Label        Value
------------------      ------------------      ------------------
BUFF          0312      BOUT          0333      CHAR          00FE      
DELAY         034D      ILOOP         0351      MASKI         0001      
MASKO         00FE      MSKCTS        0002      MSKCTI        00FD      
NEXTB         0326      OUT           1702      OUTD          1703      
OUTPR         0300      ONE           0331      OLOOP         034F      
TEMP          00FD      TMPX          00FC      TDELAY        035B      
TDLOOP        035D      

tasm: Number of errors = 0