;PAGE	38

;		.TITLE	'SIO ( SERIAL BUS INPUT/OUTPUT CONTROLLER )'
;	COLLEEN OPERATING SYSTEM
;
;	SIO	( SERIAL BUS INPUT/OUTPUT CONTROLLER )
;	WITH SOFTWARE BAUD RATE CORRECTION ON CASSETTE
;
;
;		AL MILLER	3-APR-79
;
;
; THIS MODULE HAS ONE ENTRY POINT.	IT IS CALLED BY THE DEVICE
; HANDLERS.	IT INTERPRETS A PREVIOUSLY ESTABLISHED DEVICE CONTROL
; BLOCK (STORED IN GLOBAL RAM) TO ISSUE COMMANDS
; TO THE SERIAL BUS TO CONTROL TRANSMITTING AND RECEIVING DATA.
;
;
;
; 
;PAGE	39

;	.PAGE
; EQUATES
;
; DCD DEVICE BUS ID NUMBERS
FLOPPY	=	$30
;PRINTR =	$40
;CASSET =	$60		;!!!!! *****
CASET	=	$60		;!!!!! *****
;
;
;BUS COMMANDS
;
READ	=	'R'
WRITE	=	'W'
;STATIS = 'S'
;FORMAT = '!'
;
;
; COMMAND AUX BYTES
;
SIDWAY	=	'S'		;PRINT 16 CHARACTERS SIDEWAYS
NORMAL	=	'N'		;PRINT 40 CHARACTERS NORMALLY
DOUBLE	=	'D'		;PRINT 20 CHARACTERS DOUBLE WIDE
PLOT	=	'P'		;PLOT MODE
;
;
; BUS RESPONSES
;
ACK	=	'A'		;DEVICE ACKNOWLEDGES INFORMATION
NACK	=	'N'		;DEVICE DID NOT UNDERSTAND
COMPLT	=	'C'		;DEVICE SUCCESSFULLY COMPLETED OPERATION
ERROR	=	'E'		;DEVICE INCURRED AN ERROR IN AN ATTEMPTED OP
;
;
; MISCELLANEOUS EQUATES
;
B192LO	=	$28		;19200 BAUD RATE POKEY COUNTER VALUES (LO BY
B192HI	=	$00		;(HI BYTE)
B600LO	=	$CC		;600 BAUD (LO BYTE)
B600HI	=	$05		;(HI BYTE)
HITONE	=	$05		;FSK HI FREQ POKEY COUNTE VALUE (5326 HZ)
LOTONE	=	$07		;FSK LO FREQ POKEY COUNTER VALUE (3995 HZ)
;
	.IF	PALFLG
WIRGLO	=	150		;WRITE INTER RECORD GAP (IN 1/60 SEC)
RIRGLO	=	100		;READ INTER RECORD GAP (IN 1/60 SEC)
WSIRG	=	13		;SHORT WRITE INTER RECORD GAP
RSIRG	=	8		;SHORT READ INTER RECORD GAP
	.ENDIF
	.IF	PALFLG-1
WIRGLO	=	180		;WRITE INTER RECORD GAP (IN 1/60 SEC)
RIRGLO	=	120		;READ INTER RECORD GAP (IN 1/60 SEC)
WSIRG	=	15		;SHORT WRITE INTER RECORD GAP
RSIRG	=	10		;SHORT READ INTER RECORD GAP
 
;PAGE	40

	.ENDIF
WIRGHI	=	0
RIRGHI	=	0
;
NCOMLO	=	$34		;PIA COMMAND TO LOWER NOT COMMAND LINE
NCOMHI	=	$3C		;PIA COMMAND TO RAISE NOT COMMAND LINE
MOTRGO	=	$34		;PIA COMMAND TO TURN ON CASSETTE MOTOR
MOTRST	=	$3C		;PIA COMMAND TO TURN OFF MOTOR
;
TEMPHI	=	TEMP/256		;ADDRESS OF TEMP CELL (HI BYTE)
TEMPLO	=	(-256)*TEMPHI+TEMP	;(LO BYTE)
CBUFHI	=	CDEVIC/256		;ADDRESS OF COMMAND BUFFER (HI BYTE)
CBUFLO	=	(-256)*CBUFHI+CDEVIC	;(LO BYTE)
;
CRETRI	=	13		;NUMBER OF COMMAND FRAME RETRIES
DRETRI	=	1		;NUMBER OF DEVICE RETRIES
CTIMLO	=	2		;COMMAND FRAME ACK TIME OUT (LO BYTE)
CTIMHI	=	0		;COMMAND FRAME ACK TIME OUT (HI BYTE)
;
;
;JTADRH	=	JTIMER/256		;HI BYTE OF JUMP TIMER ROUTINE ADDR	"M
;JTADRL	=	(-256)*JTADRH+JTIMER	;"MOVED TO LINE 1428"
;
 

;PAGE	41

;	.PAGE
;	SIO
;
;
	.ORG	SIOV
	JMP	SIO		;SIO ENTRY POINT
;
	.ORG	SIOINV
	JMP	SIOINT		;SIO INITIALIZATION ENTRY POINT
;
	.ORG	SENDEV
	JMP	SENDEN		;SEND ENABLE ENTRY POINT
;
.ORG	VCTABL-INTABS+VSERIN
;
	.WORD	ISRSIR		;VSERIN
	.WORD	ISRODN		;VSEROR
	.WORD	ISRTD		;VSEROC
;
;
;
	.ORG	SIOORG
;
; SIO INITIALIZATION SUBROUTINE
;
SIOINT: LDA	#MOTRST
	STA	PACTL		;TURN OFF MOTOR
;
	LDA	#NCOMHI
	STA	PBCTL		;RAISE NOT COMMAND LINE
;
;
	LDA	#3
	STA	SSKCTL		;GET POKEY OUT OF INITIALIZE MODE
	STA	SOUNDR		;INIT POKE ADDRESS FOR QUIET I/O
	STA	SKCTL
;
;
	RTS			;RETURN
;
;
;
;
;
;
SIO:	TSX
	STX	STACKP		;SAVE STACK POINTER
	LDA	#1
	STA	CRITIC
;
	LDA	DDEVIC
	CMP	#CASET
	BNE	NOTCST		;BRANCH IF NOT CASSETTE
	JMP	CASENT		;OTHERWISE JUMP TO CASSETTE ENTER
 

;PAGE	42

;
; ALL DEVICES EXCEPT CASSETTE ARE INTELLIGENT
;
NOTCST: LDA	#0
	STA	CASFLG		;INIT CASSETTE FLAG TO NO CASSETTE
;
	LDA	#DRETRI		;SET NUMBER OF DEVICE RETRIES
	STA	DRETRY
COMMND: LDA	#CRETRI		;SET NUMBER OF COMMAND FRAME RETRIES
	STA	CRETRY
;
; SEND A COMMAND FRAME
;
COMFRM: LDA	#B192LO		;SET BAUD RATE TO 19200
	STA	AUDF3
	LDA	#B192HI
	STA	AUDF4
;
	CLC			;SET UP COMMAND BUFFER
	LDA	DDEVIC
	ADC	DUNIT
	ADC	#$FF		;SUBTRACT 1
	STA	CDEVIC		;SET BUS ID NUMBER
;
	LDA	DCOMND
	STA	CCOMND		;SET BUS COMMAND
;
	LDA	DAUX1		;STORE COMMAND FRAME AUX BYTES 1 AND 2
	STA	CAUX1
	LDA	DAUX2
	STA	CAUX2		;DONE SETTING UP COMMAND BUFFER
;
	CLC			;SET BUFFER POINTER TO COMMAND FRAME BUFFER
	LDA	#CBUFLO
	STA	BUFRLO		;AND BUFFER END ADDRESS
	ADC	#4
	STA	BFENLO
	LDA	#CBUFHI
	STA	BUFRHI
	STA	BFENHI		;DONE SETTING UP BUFFER POINTER
;
	LDA	#NCOMLO		;LOWER NOT COMMAND LINE
	STA	PBCTL
;
	JSR	SENDIN		;SEND THE COMMAND FRAME TO A SMART DEVICE
;
	LDA	ERRFLG
	BNE	BADCOM		;BRANCH IF AN ERROR RECEIVED
;
	TYA
	BNE	ACKREC		;BRANCH IF ACK RECEIVED
;
;
BADCOM: DEC	CRETRY		;A NACK OR TIME OUT OCCURED
 

;PAGE	43

	BPL	COMFRM		;SO BRANCH IF ANY RETRIES LEFT
;
	JMP	DERR1		;OTHERWISE, JUMP TO RETURN SECTION
;
;
ACKREC: LDA	DSTATS		;ACK WAS RECEIVED
	BPL	WATCOM		;BRANCH TO WAIT FOR COMPLETE ,
; IF THERE IS NO DATA TO BE SENT
;
;
;
; SEND A DATA FRAME TO PERIPHERAL
;
	LDA	#CRETRI		;SET NUMBER OF RETRIES
	STA	CRETRY
;
	JSR	LDPNTR		;LOAD BUFFER POINTER WITH DCB INFORMATION
;
	JSR	SENDIN		;GO SEND THE DATA FRAME TO A SMART DEVICE
;
	BEQ	BADCOM		;BRANCH IF BAD
;
;
;
; WAIT FOR COMPLETE SIGNAL FROM PERIPHERAL
;
WATCOM: JSR	STTMOT		;SET DDEVICE TIME OUT VALUES IN Y,X
;
	LDA	#$00
	STA	ERRFLG		;CLEAR ERROR FLAG
;
	JSR	WAITER		;SET UP TIMER AND WAIT
	BEQ	DERR		;BRANCH IF TIME OUT
;
;
; DEVICE DID NOT TIME OUT
;
	BIT	DSTATS
	BVS	MODATA		;BRANCH IF MORE DATA FOLLOWS
;
	LDA	ERRFLG
	BNE	DERR1		;BRANCH IF AN ERROR OCCURRED
	BEQ	RETURN		;OTHERWISE RETURN
;
;
;
;
; RECEIVE A DATA FRAME FROM PERIPHERAL
;
MODATA: JSR	LDPNTR		;LOAD BUFFER POINTER WITH DCB INFORMATION
;
	JSR	RECEIV		;GO RECEIVE A DATA FRAME
;
DERR:	LDA	ERRFLG
 

;PAGE	44

	BEQ	NOTERR		;BRANCH IF NO ERROR PRECEEDED DATA
;
	LDA	TSTAT		;GET TEMP STATUS
	STA	STATUS		;STORE IN REAL STATUS
;
;
NOTERR: LDA	STATUS
	CMP	#SUCCES
	BEQ	RETURN		;BRANCH IF COMPLETELY SUCCESSFUL
;
DERR1:	DEC	DRETRY
	BMI	RETURN		;BRANCH IF OUT OF DEVICE RETRIES
;
	JMP	COMMND		;OTHERWISE, ONE MORE TIME
;
;
;
;

RETURN: JSR	SENDDS		;DISABLE POKEY INTERRUPTS
	LDA	#0
	STA	CRITIC
	LDY	STATUS		;RETURN STATUS IN Y
	STY	DSTATS		;AND THE DCB STATUS WORD
	RTS			; RETURN	KH!!!

;
;
;
;
; WAIT SUBROUTINE
;
; WAITS FOR COMPLETE OR ACK
; RETURNS Y=$FF IF SUCCESSFUL, Y=$00 IF NOT
;
WAIT:	LDA	#$00
	STA	ERRFLG		;CLEAR ERROR FLAG
;

	CLC			;LOAD BUFFER POINTER WITH ADDRESS
	LDA	#TEMPLO		;OF TEMPORARY RAM CELL
	STA	BUFRLO
	ADC	#1
	STA	BFENLO		;ALSO SET BUFFER END +1 ADDRESS
	LDA	#TEMPHI
	STA	BUFRHI
	STA	BFENHI		;DONE LOADING POINTER
;
	LDA	#$FF
	STA	NOCKSM		;SET NO CHECKSUM FOLLOWS DATA FLAG
;
	JSR	RECEIV		;GO RECEIVE A BYTE
;
	LDY	#$FF		;ASSUME SUCCESS
	LDA	STATUS
	CMP	#SUCCES
	BNE	NWOK		;BRANCH IF IT DID NOT WORK OK

;PAGE	45
;
WOK:	LDA	TEMP		;MAKE SURE THE BYTE SUCCESSFULLY RECEIVED
	CMP	#ACK		;WAS ACTUALLY AN ACK OR COMPLETE
	BEQ	GOOD
	CMP	#COMPLT
	BEQ	GOOD
;
	CMP	#ERROR
	BNE	NOTDER		;BRANCH IF DEVICE DID NOT SEND BACK
; A DEVICE ERROR CODE
	LDA	#DERROR
	STA	STATUS		;SET DEVICE ERROR STATUS
	BNE	NWOK
;
NOTDER: LDA	#DNACK		;OTHERWISE SET NACK STATUS
	STA	STATUS
;
NWOK:	LDA	STATUS
	CMP	#TIMOUT
	BEQ	BAD		;BRANCH IF TIME OUT
;
	LDA	#$FF
	STA	ERRFLG		;SET SOME ERROR FLAG
	BNE	GOOD		;RETURN WITH OUT SETTING Y = 0
;
BAD:	LDY	#0
;
GOOD:	LDA	STATUS
	STA	TSTAT
	RTS			;RETURN
;
;
;
;
;
; SEND SUBROUTINE
;
; SENDS A BUFFER OF BYTES OUT OVER THE SERIAL BUS
;
;
SEND:	LDA	#SUCCES		;ASSUME SUCCESS
	STA	STATUS
;
	JSR	SENDEN		;ENABLE SENDING
;
	LDY	#0
	STY	CHKSUM		;CLEAR CHECK SUM
	STY	CHKSNT		;CHECKSUM SENT FLAG
	STY	XMTDON		;TRANSMISSION DONE FLAG
;
;
 

;PAGE	46

	LDA	(BUFRLO),Y	;PUT FIRST BYTE FROM BUFFER
	STA	SEROUT		;INTO THE SERIAL OUTPUT REGISTER
;
;
	STA	CHKSUM		;PUT IT IN CHECKSUM
;
NOTDON: LDA	BRKKEY
	BNE	NTBRKO
	JMP	BROKE		;JUMP IF BREAK KEY PRESSED
;
NTBRKO: LDA	XMTDON		;LOOP UNTIL TRANSMISSION IS DONE
	BEQ	NOTDON
;
	JSR	SENDDS		;DISABLE SENDING
;
	RTS			;RETURN
;
;
;
;
;
;
; OUTPUT DATA NEEDED INTERRUPT SERVICE ROUTINE
;
ISRODN: TYA
	PHA			;SAVE Y REG ON STACK
;
	INC	BUFRLO		;INCREMENT BUFFER POINTER
	BNE	NOWRPO
	INC	BUFRHI
;
NOWRPO: LDA	BUFRLO		;CHECK IF PAST END OF BUFFER
	CMP	BFENLO
	LDA	BUFRHI		;HIGH PART
	SBC	BFENHI
	BCC	NOTEND		;BRANCH IF NOT PAST END OF BUFFER
;
	LDA	CHKSNT
	BNE	RELONE		;BRANCH IF CHECKSUM ALREADY SENT
;
	LDA	CHKSUM
	STA	SEROUT		;SEND CHECK SUM
	LDA	#$FF
	STA	CHKSNT		;SET CHECKSUM SENT FLAG
	BNE	CHKDON
;
RELONE: LDA	POKMSK		;ENABLE TRANSMIT DONE INTERRUPT
	ORA	#$08
	STA	POKMSK
	STA	IRQEN
;
CHKDON: PLA
	TAY			;RESTORE Y REG
	PLA			;RETURN FROM INTERRUPT
 

;PAGE	47

	RTI
;
;
NOTEND: LDY	#0
	LDA	(BUFRLO),Y	;PUT NEXT BYTE FROM BUFFER
	STA	SEROUT		;INTO THE SERIAL OUTPUT REGISTER
;
	CLC			;ADD IT TO CHECKSUM
	ADC	CHKSUM
	ADC	#0
	STA	CHKSUM
;
	JMP	CHKDON		;GO RETURN
;
;
;
;
;
;
; TRANSMIT DONE INTERRUPT SERVICE ROUTINE
;
ISRTD:	LDA	CHKSNT
	BEQ	FOOEY		;BRANCH IF CHECKSUM NOT YET SENT
;
	STA	XMTDON		;OTHERWISE SET TRANSMISSION DONE FLAG
;
	LDA	POKMSK		;DISABLE TRANSMIT DONE INTERRUPT
	AND	#$F7
	STA	POKMSK
	STA	IRQEN
;
FOOEY:	PLA			;RETURN FROM INTERRUPT
	RTI
;
;
;
;
;
;
;
;
; RECEIVE SUBROUTINE
;
RECEIV: LDA	#0
;
	LDY	CASFLG
	BNE	NOCLR		;BRANCH IF CASSETTE
;
	STA	CHKSUM		;CLEAR CHKSUM
NOCLR:	STA	BUFRFL		;BUFFER FULL FLAG
	STA	RECVDN		;RECEIVE DONE FLAG
;
;
;
 

;PAGE	48

	LDA	#SUCCES
	STA	STATUS		;SET GOOD STATUS FOR DEFAULT CASE
	JSR	RECVEN		;DO RECEIVE ENABLE
	LDA	#NCOMHI		;COMMAND FRAME HI COMMAND
	STA	PBCTL		;STORE IN PIA
CHKTIM: LDA	BRKKEY
	BNE	NTBRK1
	JMP	BROKE		;JUMP IF BREAK KEY PRESSED
;
NTBRK1: LDA	TIMFLG		;NO
	BEQ	TOUT		;IF TIMEOUT, GO SET ERROR STATUS
	LDA	RECVDN
	BEQ	CHKTIM		;DONE ?
GOBACK: RTS
TOUT:	LDA	#TIMOUT		;YES,
	STA	STATUS		;SET TIMEOUT STATUS
;
;
;
;
;
;
RRETRN: RTS			;RETURN
;
;
;
;
;
;
;
; SERIAL INPUT READY INTERRUPT SERVICE ROUTINE
;
ISRSIR: TYA
	PHA			;SAVE Y REG ON STACK
;
;
;
	LDA	SKSTAT
	STA	SKRES		;RESET STATUS REGISTER
; ********	THIS MAY NOT BE THE PLACE TO DO IT	*********
;
	BMI	NTFRAM		;BRANCH IF NO FRAMING ERROR
;
	LDY	#FRMERR
	STY	STATUS		;SET FRAME ERRORR STATUS
;
NTFRAM: AND	#$20
	BNE	NTOVRN		;BRANCH IF NO OVERRUN ERROR
;
	LDY	#OVRRUN
	STY	STATUS		;SET OVERRUN ERROR STATUS
;
NTOVRN: LDA	BUFRFL
	BEQ	NOTYET		;BRANCH IF BUFFER WAS NOT YET FILLED
 

;PAGE	49

;
	LDA	SERIN		;THIS INPUT BYTE IS THE CHECKSUM
	CMP	CHKSUM
	BEQ	SRETRN		;BRANCH IF CHECKSUMS MATCH
;
	LDY	#CHKERR
	STY	STATUS		;SET CHECKSUM ERROR STATUS
;
SRETRN: LDA	#$FF		;SET RECEIVE DONE FLAG
	STA	RECVDN
;
SUSUAL: PLA
	TAY			;RESTORE Y REG
	PLA			;RETURN FROM INTERRUPT
	RTI
;
;
;
NOTYET: LDA	SERIN
	LDY	#0
	STA	(BUFRLO),Y	;STORE INPUT REGISTER INTO BUFFER
;
	CLC			;ADD IT TO CHECKSUM
	ADC	CHKSUM
	ADC	#0
	STA	CHKSUM
;
	INC	BUFRLO		;INCREMENT BUFFER POINTER
	BNE	NTWRP1
	INC	BUFRHI
;
NTWRP1: LDA	BUFRLO
	CMP	BFENLO
	LDA	BUFRHI
	SBC	BFENHI
	BCC	SUSUAL		;BRANCH IF NEW BUFFER ADDRESS IS IN BUFFER L
;
	LDA	NOCKSM
	BEQ	GOON		;BRANCH IF A CHECKSUM WILL FOLLOW DATA
;
	LDA	#0
	STA	NOCKSM		;CLEAR NO CHECKSUM FLAG
;
	BEQ	SRETRN		;GO RETURN AND SET RECEIVE DONE FLAG
;
;
GOON:	LDA	#$FF
	STA	BUFRFL		;SET BUFFER FULL FLAG
;
	BNE	SUSUAL		;GO RETURN
;
;
;
;
 

;PAGE	50

;
;
;
;
; LOAD BUFFER POINTER SUBROUTINE
;
; LOAD BUFFER POINTER WITH DCB BUFFER INFORMATION
;
LDPNTR: CLC
	LDA	DBUFLO
	STA	BUFRLO
	ADC	DBYTLO
	STA	BFENLO		;ALSO SET BUFFER END + 1 ADDRESS
;
	LDA	DBUFHI
	STA	BUFRHI
	ADC	DBYTHI
	STA	BFENHI
;
	RTS			;RETURN
;
;
;
;
;
;
;
;
; CASSETTE HANDLING CODE
;
CASENT: LDA	DSTATS
	BPL	CASRED		;BRANCH IF INPUT FROM CASSETTE
;
; WRITE A RECORD
;
	LDA	#B600LO		;SET BAUD RATE TO 600
	STA	AUDF3
	LDA	#B600HI
	STA	AUDF4
;
	JSR	SENDEN		;TURN ON POKEY MARK TONE
;
	LDY	#WSIRG		;LOAD SHORT WRITE INTER RECORD GAP TIME
	LDA	DAUX2
	BMI	SRTIRO		;BRANCH IF SHORT GAP IS DESIRED
;
	LDY	#WIRGLO		;SET WRITE IRG TIME
SRTIRO: LDX	#WIRGHI
	JSR	SETVBX
;
	LDA	#MOTRGO
	STA	PACTL		;TURN ON MOTOR
;
TIMIT:	LDA	TIMFLG		;LOOP UNTIL DONE
 

;PAGE	51

	BNE	TIMIT
;
	JSR	LDPNTR		;LOAD BUFFER POINTER WITH DCB INFORMATION
;
	JSR	SEND		;SEND A BUFFER
;
	JMP	CRETRN		;GO RETURN
;
;
;
; RECEIVE A RECORD
;
CASRED: LDA	#$FF
	STA	CASFLG		;SET SET CASSETTE FLAG
;
	LDY	#RSIRG		;LOAD SHORT READ INTER RECORD GAP TIME
	LDA	DAUX2
	BMI	SRTIR1		;BRANCH IF SHORT GAP IS DESIRED
;
	LDY	#RIRGLO		;SET TIME OUT FOR READ IRG
SRTIR1: LDX	#RIRGHI
	JSR	SETVBX
;
	LDA	#MOTRGO
	STA	PACTL		;TURN ON MOTOR
;
TIMIT1: LDA	TIMFLG		;LOOP UNTIL DONE
	BNE	TIMIT1
;
	JSR	LDPNTR		;LOAD BUFFER POINTER WITH DCB INFORMATION
;
	JSR	STTMOT		;SET DEVICE TIME OUT IN Y,X
	JSR	SETVBX
;
	JSR	BEGIN		;SET INITIAL BAUD RATE
;
	JSR	RECEIV		;GO RECEIVE A BLOCK
;
CRETRN: LDA	DAUX2
	BMI	SRTIR2		;BRANCH IF DOING SHORT INTER RECORD GAPS
; DON'T TURN OFF CASSETTE MOTOR
	LDA	#MOTRST
	STA	PACTL		;TURN OFF MOTOR
;
SRTIR2: JMP	RETURN		;GO RETURN
;
;
;
;
;
JTIMER: LDA	#$00
JTADRH	=	JTIMER/256		;HI BYTE OF JUMP TIMER ROUTINE ADDR
JTADRL	=	(-256)*JTADRH+JTIMER
	STA	TIMFLG			;SET TIME OUT FLAG
 

;PAGE	52

	RTS
;
;
;
;
;
;;
; SEND ENABLE SUBROUTINE
;
SENDEN: LDA	#$07		;MASK OFF PREVIOUS SERIAL BUS CONTROL BITS
	AND	SSKCTL
	ORA	#$20		;SET TRANSMIT MODE
;
	LDY	DDEVIC
	CPY	#CASET
	BNE	NOTCAS		;BRANCH IF NOT CASSETTE
;
	ORA	#$08		;SET THE FSK OUTPUT BIT
;
	LDY	#LOTONE		;SET FSK TONE FREQUENCIES
	STY	AUDF2
	LDY	#HITONE
	STY	AUDF1
;
NOTCAS: STA	SSKCTL		;STORE NEW VALUE TO SYSTEM MASK
	STA	SKCTL		;STORE TO ACTUAL REGISTER
;
	LDA	#$C7		;MASK OFF PREVIOUS SERIAL BUS INTERRUPT BITS
	AND	POKMSK
	ORA	#$10		;ENABLE OUTPUT DATA NEEDED INTERRUPT
;
;
	JMP	CONTIN		;GO CONTINUE IN RECEIVE ENABLE SUBROUTINE
;
;
;
;
;
;
;
;
;
;
; RECEIVE ENABLE SUBROUTINE
;
RECVEN: LDA	#$07		;MASK OFF PREVIOUS SERIAL BUS CONTROL BITS
	AND	SSKCTL
	ORA	#$10		;SET RECEIVE MODE ASYNCH.
	STA	SSKCTL		;STORE NEW VALUE TO SYSTEM MASK
	STA	SKCTL		;STORE TO ACTUAL REGISTER
;
	STA	SKRES		;RESET SERIAL PORT/KEYBOARD STATUS REGISTER
;
	LDA	#$C7		;MASK OFF PREVIOUS SERIAL BUS INTERRUPT BITS
 

;PAGE	53

	AND	POKMSK
	ORA	#$20		;ENABLE RECEIVE INTERRUPT
CONTIN: STA	POKMSK		;STORE NEW VALUE TO SYSTEM MASK
	STA	IRQEN		;STORE TO ACTUAL REGISTER
;
;
	LDA	#$28		;CLOCK CH.3 WITH 1.79 MHZ
	STA	AUDCTL		;CLOCK CH.4 WITH CH. 3
;
	LDX	#6		;SET PURE TONES, NO VOLUME
	LDA	#$A8
	LDY	SOUNDR		;TEST QUIET I/O FLAG
	BNE	NOISE1		;NE IS NORMAL (NOISY)
	LDA	#$A0
NOISE1: STA	AUDC1,X
	DEX
	DEX
	BPL	NOISE1
;
	LDA	#$A0
	STA	AUDC3		;TURN OFF SOUND ON CHANNEL 3
	LDY	DDEVIC
	CPY	#CASET
	BEQ	CAS31		;BRANCH IF CASSETTE IS DESIRED
	STA	AUDC1		;OTHERWISE TURN OFF CHANNELS 1 AND 2
	STA	AUDC2
;
;
CAS31:	RTS			;RETURN
;
;
;
;
;
;
;
;
;
;
; DISABLE SEND AND DISABLE RECEIVE SUBROUTINES
;
SENDDS: NOP
RECVDS: LDA	#$C7		;MASK OFF SERIAL BUS INTERRUPTS
	AND	POKMSK
	STA	POKMSK		;STORE NEW VALUE TO SYSTEM MASK
	STA	IRQEN		;STORE TO ACTUAL REGISTER
;
	LDX	#6
	LDA	#0
ZERIT:	STA	AUDC1,X
	DEX
	DEX
	BPL	ZERIT		;TURN OFF AUDIO VOLUME
;
 

;PAGE	54

	RTS			;RETURN
;
;
;
;
;
;
;
;
;
;
; SET DDEVICE TIME OUT VALUES IN Y,X SUBROUTINE
;
STTMOT: LDA	DTIMLO		;GET DEVICE TIME OUT IN 1 SECOND INCR
	ROR	A		;PUT 6 HI BITS IN X, LO 2 BITS IN Y
	ROR	A
	TAY			;TEMP SAVE
	AND	#$3F		;MASK OFF 2 HI BITS
	TAX			;THIS IS HI BYTE OF TIME OUT
;
	TYA			;RESTORE
	ROR	A
	AND	#$C0		;MASK OFF ALL BUT 2 HI BITS
	TAY			;THIS IS LO BYTE OF TIME OUT
;
	RTS
;
;
;
;
;
;
;
;
;
;
INTTBL: .WORD	ISRSIR		;SERIAL INPUT READY
	.WORD	ISRODN		;OUTPUT DATA NEEDED
	.WORD	ISRTD		;TRANSMISSION DONE
;
SIRHI	=	ISRSIR/256		;SERIAL INPUT READY ISR ADDRESS
SIRLO	=	(-256)*SIRHI+ISRSIR
ODNHI	=	ISRODN/256		;OUTPUT DATA NEEDED ISR ADDRESS
ODNLO	=	(-256)*ODNHI+ISRODN
TDHI	=	ISRTD/256		;TRANSMISSION DONE ISR ADDRESS
TDLO	=	(-256)*TDHI+ISRTD
;
;
;
;
; SEND A DATA FRAME TO AN INTELLIGENT PERIPHERAL SUBROUTINE
;
;
SENDIN: LDX	#$01
 
;PAGE	55

DELAY0: LDY	#$FF
DELAY1: DEY
	BNE	DELAY1
	DEX
	BNE	DELAY0
;
	JSR	SEND		;GO SEND THE DATA FRAME
;
	LDY	#CTIMLO		;SET ACK TINE OUT
	LDX	#CTIMHI
WAITER: JSR	SETVBX
;
	JSR	WAIT		;WAIT FOR ACK
;
	TYA			;IF Y=0, A TIME OUT OR NACK OCCURED
;
	RTS			;RETURN
;
;
;
;
;
;
;
;
;
;
;
; COMPUTE VALUE FOR POKEY FREQ REGS FOR THE BAUD RATE AS
; MEASURED BY AN INTERVAL OF THE 'VCOUNT' TIMER.
;
COMPUT: STA	TIMER2
	STY	TIMER2+1		;SAVE FINAL TIMER VALUE
	JSR	ADJUST		;ADJUST VCOUNT VALUE
	STA	TIMER2		;SAVE ADJUSTED VALUE
	LDA	TIMER1
	JSR	ADJUST		;ADJUST
	STA	TIMER1		;SAVE ADJUSTED TIMER1 VALUE
	LDA	TIMER2
	SEC
	SBC	TIMER1
	STA	TEMP1		;FIND VCOUNT DIFFERENCE
	LDA	TIMER2+1
	SEC
	SBC	TIMER1+1
	TAY			;FIND VBLANK COUNT DIFFERENCE
	.IF	PALFLG
	LDA	#-$9C
HITIMR: CLC
	ADC	#$9C
	.ENDIF
	.IF	PALFLG-1
	LDA	#-$83
HITIMR: CLC
 

;PAGE	56

	ADC	#$83		;ACCUMULATE MULTIPLICATION
	.ENDIF
	DEY
	BPL	HITIMR		;DONE?
	CLC
	ADC	TEMP1		;TOTAL VCOUNT DIFFERENCE
FINDX:	TAY			;SAVE ACCUM
	LSR	A
	LSR	A
	LSR	A
	ASL	A
	SEC
	SBC	#22		;ADJUST TABLE INDEX
	TAX			;DIVIDE INTERVAL BY 4 TO GET TABLE INDEX
	TYA			;RESTORE ACCUM
	AND	#7
	TAY			;PULL OFF 3 LO BITS OF INTERVAL
	LDA	#-11
DOINTP: CLC
	ADC	#11		;ACCUMULATE INTERPOLATION CONSTANT
	DEY
	BPL	DOINTP		;INTERPOLATION CONSTANT COMPUTATION DONE?
;
ENINTP: LDY	#0
	STY	ADDCOR		;CLEAR ADDITION CORRECTION FLAG
	SEC
	SBC	#7		;ADJUST INTERPOLATION CONSTANT
	BPL	PLUS
	DEC	ADDCOR
PLUS:	CLC
	ADC	POKTAB,X	;ADD CONSTANT TO LO BYTE TABLE VALUE
	TAY			;LO BYTE POKEY FREQ VALUE
	LDA	ADDCOR
	ADC	POKTAB+1,X	;ADD CARRY TO HI BYTE TABLE VALUE
; HI BYTE POKEY FREQ VALUE
	RTS
;
;
;
;	ROUTINE TO ADJUST VCOUNT VALUE
;
ADJUST: CMP	#$7C
	BMI	ADJ1		;LARGER THAN '7C' ?
	SEC			;YES,
	SBC	#$7C
	RTS
ADJ1:	CLC
	.IF	PALFLG
	ADC	#$20
	.ENDIF
	.IF	PALFLG-1
	ADC	#$7
	.ENDIF
	RTS
 

;PAGE	57

;
;
;
;
;
;
;
;	INITIAL BAUD RATE MEASUREMENT -- USED TO SET THE
;		BAUD RATE AT THE START OF A RECORD.
;
;		IT IS ASSUMED THAT THE FIRST TWO BYTES OF EVERY
; RECORD ARE 'AA' HEX.
;
BEGIN:	LDA	BRKKEY
	BNE	NTBRK2
	JMP	BROKE		;JUMP IF BREAK KEY PRESSED
;
NTBRK2: SEI
;
	LDA	TIMFLG
	BNE	OKTIM1		;BRANCH IF NOT TIMED OUT
	BEQ	TOUT1		;BRANCH IF TIME OUT
;
OKTIM1: LDA	SKSTAT
	AND	#$10		;READ SERIAL PORT
	BNE	BEGIN		;START BIT?
	STA	SAVIO		;SAVE SER. DATA IN
	LDX	VCOUNT		;READ VERTICAL LINE COUNTER
	LDY	RTCLOK+2	;READ LO BYTE OF VBLANK CLOCK
	STX	TIMER1
	STY	TIMER1+1	;SAVE INITIAL TIMER VALUE
;
	LDX	#1		;SET MODE FLAG
	STX	TEMP3
	LDY	#10		;SET BIT COUNTER FOR 10 BITS
COUNT:	LDA	BRKKEY
	BEQ	BROKE		;BRANCH IF BREAK KEY PRESSED
;
	LDA	TIMFLG
	BNE	OKTIMR		;BRANCH IF NOT TIMED OUT
TOUT1:	CLI
	JMP	TOUT		;BRANCH IF TIME OUT
;
OKTIMR: LDA	SKSTAT
	AND	#$10		;READ SERIAL PORT
	CMP	SAVIO		;DATA IN CHANGED YET?
	BEQ	COUNT
	STA	SAVIO		;YES,SAVE SER. DATA IN
	DEY			;DECR. BIT COUNTER
	BNE	COUNT		;DONE?
;
	DEC	TEMP3		;YES,
	BMI	GOREAD		;DONE WITH BOTH MODES?
	LDA	VCOUNT
 

;PAGE	58

	LDY	RTCLOK+2	;READ TIMER LO & HI BYTES
	JSR	COMPUT		;NO, COMPUTE BAUD RATE
	STY	CBAUDL
	STA	CBAUDH		;SET BAUD RATE INTO RAM CELLS
	LDY	#9		;SET BIT COUNTER FOR 9 BITS
	BNE	COUNT
;
GOREAD: LDA	CBAUDL
	STA	AUDF3
	LDA	CBAUDH
	STA	AUDF4		;SET POKEY FREQ REGS FOR BAUD RATE
	LDA	#0
	STA	SKSTAT
	LDA	SSKCTL
	STA	SKSTAT		;INIT. POKEY SERIAL PORT
	LDA	#$55
	STA	(BUFRLO),Y	;STORE '$55' AS FIRST RCV. BUFFER
	INY
	STA	(BUFRLO),Y
	LDA	#$AA
	STA	CHKSUM		;STORE CHECKSUM FOR 2 BYTES OF '$AA'
	CLC
	LDA	BUFRLO
	ADC	#2
	STA	BUFRLO
	LDA	BUFRHI
	ADC	#0
	STA	BUFRHI		;INCR. BUFFER POINTER BY 1
	CLI
	RTS
;
;
;
BROKE:	JSR	SENDDS		;BREAK KEY WAS PRESSED, SO PREPARE
	LDA	#MOTRST		;TO RETURN
	STA	PACTL		;TURN OFF MOTOR
	STA	PBCTL		;RAISE NOT COMMAND LINE
;
	LDA	#BRKABT
	STA	STATUS		;STORE BREAK ABORT STATUS CODE
;
	LDX	STACKP
	TXS			;RESTORE STACK POINTER
;
	DEC	BRKKEY		;SET BREAK KEY FLAG TO NONZERO
	CLI			;ALLOW IRQ'S
;
	JMP	RETURN		;GO RETURN
;
;
;
;
;
SETVBX: LDA	#JTADRL		;STORE TIME OUT ROUTINE ADDRESS
 

  
;PAGE	59

	STA	CDTMA1
	LDA	#JTADRH
	STA	CDTMA1+1
;
	LDA	#1		;SET FOR TIMER 1
;
	SEI			;THE SETVBL ROUTINE NEEDS THIS TO CUT SHORT
	JSR	SETVBV		;ANY VBLANKS THAT OCCUR
	LDA	#1		;SET FOR TIMER 1
	STA	TIMFLG		;SET FLAG TO NOT TIMED OUT
	CLI
	RTS
;
;
;
;
;
;
;
; 'VCOUNT' INTERVAL TIMER MEASUREMENT -- TO -- POKEY FREQ REG VALUE
;		CONVERSION TABLE
;
;
; THE VALUES STORED IN THE TABLE ARE 'AUDF+7'.
;
;	THE FOLLOWING FORMULAS WERE USED TO DETERMINE THE TABLE VALUES:
;
;		F OUT= F IN/(2*(AUDF+M)) , WHERE F IN=1.78979 MHZ. & M=7
;
;	FROM THIS WAS DERIVED THE FORMULA USED TO COMPUTE THE
;	TABLE VALUES BASED ON A MEASUREMENT OF THE PERIOD BY
;	AN INTERVAL OF THE 'VCOUNT' TIMER.
;
;		AUDF+7=(11.365167)*T OUT, WHERE T OUT=# OF COUNTS
;		(127 USEC.RESOLUTION) OF 'VCOUNT' FOR 1
;		CHARACTER TIME (10 BIT TIMES).
;
;
;
;
;		AUDF+7		BAUD RATE	VCOUNT INTERVAL
;		------		-----------	----------------
;	.WORD	$27C		;1407		56
;	.WORD	$2D7		;1231		64
;	.WORD	$332		;1094		72
;	.WORD	$38D		;985		80
POKTAB:
	.WORD	$3E8		;895		88
	.WORD	$443		;820		96
	.WORD	$49E		;757		104
	.WORD	$4F9		;703		112
	.WORD	$554		;656		120
	.WORD	$5AF		;615		128
	.WORD	$60A		;579		136
	.WORD	$665		;547		144
 

;PAGE	60

	.WORD	$6C0		;518		152
	.WORD	$71A		;492		160
	.WORD	$775		;469		168
	.WORD	$7D0		;447		176
;	.WORD	$82B		;428		184
;	.WORD	$886		;410		192
;	.WORD	$8E1		;394		200
;	.WORD	$93C		;379		208
;	.WORD	$997		;365		216
;	.WORD	$9F2		;352		224
;	.WORD	$A4D		;339		232
;	.WORD	$AA8		;328		240
;	.WORD	$B03		;318		248
;
;
;
;
;***********************************************************************
CRNTP3	=*
	.ORG	$14
SIOSPR: .BYTE	DSKORG-CRNTP3 ;^GSIOL IS TOO LONG
 

