*  UIOROM - PROM FOR THE ALTAIR 680 TO SUPPORT A HIGH SPEED
*     READER/PUNCH ON THE UIO SERIAL PORT. READS AN S-RECORD
*     FILE AT THE $FD00 ENTRY POINT AND READS A BINARY (BINLOAD
*     CHECKSUM FORMAT) AT THE $FD80 ENTRY POINT.

ROMBASE	EQU	$FD00

* 680 MONITOR EQUATES

OUTCH	EQU	$FF81		;DISPLAY CHARACTER FROM B
XHIB2X	EQU	$FF68		;LOAD XHI:B INTO X
MONITR	EQU	$FFAB		;RE-ENTER MONITOR

* UIO EQUATES

SIOSR	EQU	$F006		;UIO 6850 STATUS REGISTER
SIODR	EQU	$F007		;DATA REGISTER
RDRF	EQU	$01		;RECEIVE DATA AVAILABLE
TDRE	EQU	$02		;READY TO TRANSMIT

* BINARY FILE EQUATES

DATAREC	EQU	$3C		;FLAG THAT A DATA RECORD FOLLOWS
JUMPREC	EQU	$78		;FLAG THAT A JUMP RECORD FOLLOWS

*----------------------------------------------------------------
*  S-RECORD LOAD ENTRY POINT IS $FD00. LOAD S-RECORD DATA FROM
*     THE UIO SERIAL PORT INTO MEMORY.
*----------------------------------------------------------------
	ORG	ROMBASE
	LDS	#STACK		;INIT STACK
	BSR	INITSIO		;INIT 6850

SRLOAD	BSR	UIOREAD		;LOOK FOR AN S RECORD
	SUBB	#'S
	BNE	SRLOAD

	BSR	UIOREAD		;READ NEXT TO SEE IF S1 OR S9
	CMPB	#'9
	BEQ	S9REC		;S9
	CMPB	#'1		;S1?
	BNE	SRLOAD		;NO, IGNORE

	CLRA			;ACCUMULATE CHECKSUM IN A
	BSR	RDBYTE		;GET THE BYTE COUNT
	SUBB	#2		;TAKE OUT THE ADDRESS BYTES
	STAB	BYTECNT		;SAVE THE READ COUNTER
	BSR	RDWORD		;READ THE ADDRESS AND PUT IN X

RDLINE	BSR	RDBYTE		;READ A DATA BYTE
	DEC	BYTECNT		;REPEAT FOR ALL BYTES ON THE LINE
	BEQ	VALCSUM		;DONE, GO VALIDATE THE CHECKSUM

	STAB	0,X		;SAVE THE BYTE
	CMPB	0,X
	BNE	MEMERR		;DIDN'T SAVE PROPERLY
	INX
	BRA	RDLINE

* RDNIBL - READ AN ASCII HEX NIBBLE INTO B IN BINARY. TO SAVE SPACE,
*    ERROR CHECKING IS NOT DONE AND HOPEFULLY THE LINE CHECKSUM
*    WILL DETECT ANY ERRORS.

RDNIBL	BSR	UIOREAD		;GET NEXT CHARACTER
	SUBB	#'0		;CONVERT TO BINARY
	CMPB	#9
	BLS	RNEXIT		;VALID 0-9
	SUBB	#7		;ELSE ADJUST FOR A TO F
RNEXIT	RTS

* RDBYTE - READ AN ASCII HEX BYTE INTO B IN BINARY

RDBYTE	BSR	RDNIBL		;GET MSN IN B
	ASLB			;PUT IN MSN
	ASLB
	ASLB
	ASLB
	STAB	TEMP
	BSR	RDNIBL		;GET LSN IN B
	ADDB	TEMP		;FORM FINAL BYTE
	ABA			;UPDATE CHECKSUM
	RTS

* RDWORD - READ AN ASCII HEX WORD INTO X IN BINARY

RDWORD	BSR	RDBYTE		;READ MSB INTO XHI
	STAB	SAVEX
	BSR	RDBYTE		;READ LSB INTO B
	STAB	SAVEX+1
	LDX	SAVEX
	RTS

* UIOREAD - READ A CHARACTER FROM THE UIO SERIAL PORT INTO B

UIOREAD	LDAB	SIOSR		;WAIT FOR NEW CHARACTER
	RORB
	BCC	UIOREAD

	LDAB	SIODR		;LOAD AND RETURN CHAR
	ANDB	#$7F
	RTS

* VALCSUM - VALIDATE THE CHECKSUM. IF GOOD, GO LOOK FOR ANOTHER LINE

VALCSUM	INCA			;VALIDATE CHECKSUM
	BEQ	SRLOAD		;GOOD - KEEP GOING

* HEXERR, MEMERR - DIE IN A LOOP DISPLAYING THE ERROR CODE

HEXERR	LDAB	#'C		;INDICATE HEX/CHECKSUM ERROR
	FCB	$8C		;CPX SKIP TRICK
MEMERR	LDAB	#'M

DIELOOP	JSR	OUTCH		;DIE HERE SENDING ERROR CODE
	BRA	DIELOOP

* S9REC - LOAD COMPLETE, EXIT TO THE 680 MONITOR

S9REC	JMP	MONITR

* INITSIO - INITIALIZE THE 6850 ON THE UIO

INITSIO	LDAA	#3		;RESET
	STAA	SIOSR
	LDAA	#$15		;8N1
	STAA	SIOSR
	RTS

*----------------------------------------------------------------
*  BINARY LOAD ENTRY POINT IS $FD80. LOAD BINLOAD CHECKSUM
*     FORMAT BINARY DATA INTO MEMORY.
*----------------------------------------------------------------
	ORG	ROMBASE+$80
	LDS	#STACK		;INIT STACK
	BSR	INITSIO		;INIT 6850

BINLOAD	BSR	BINREAD		;LOOK FOR A SYNC BYTE
	CMPB	#DATAREC	;DATA RECORD?
	BEQ	LOADREC		;YES

	CMPB	#JUMPREC	;JUMP RECORD?
	BNE	BINLOAD		;NO, KEEP LOOKING

	BSR	GETADDR		;GET JUMP-TO ADDRESS IN X
	LDX	SAVEX		;X=START ADDDRESS
	JMP	0,X		;JUMP TO LOADED CODE

* LOADREC - LOAD A DATA RECORD

LOADREC	BSR	GETADDR		;GET POINTER IN X FOR DATA	
	BSR	BINREAD		;GET BYTE COUNT TO READ
	STAB	BYTECNT
	CLRA			;INIT CHECKSUM

LOADLP	BSR	BINREAD		;LOAD, SAVE, AND VERIFY BYTE
	STAB	0,X
	CMPB	0,X
	BNE	MEMERR

	ABA			;UPDATE CHECKSUM
	INX
	DEC	BYTECNT
	BNE	LOADLP

	BSR	BINREAD		;READ CHECKSUM
	SBA
	BNE	HEXERR		;DIDN'T MATCH

	BRA	BINLOAD		;ELSE, LOOK FOR NEXT RECORD

* GETADDR - READ TWO BYTE ADDRESS FROM THE CASSETTE INTERFACE
*   AND RETURN IT IN X

GETADDR	BSR	BINREAD		;GET MSB
	STAB	SAVEX
	BSR	BINREAD		;GET LSB
	STAB	SAVEX+1
	LDX	SAVEX		;X CONTAINS THE ADDRESS
	RTS

* BINREAD - READ A BYTE FROM THE CONSOLE SERIAL PORT INTO B

BINREAD	LDAB	SIOSR		;WAIT FOR NEW BYTE
	RORB
	BCC	BINREAD

	LDAB	SIODR		;LOAD AND RETURN BYTE
	RTS

* DATA AND STACK ARE IN THE TOP 16 BYTES OF THE FIRST 16K OF RAM

	ORG	$3FF0
	RMB	11		;12 BYTES OF STACK SPACE
STACK	RMB	1
SAVEX	RMB	2		;X REGISTER SAVE
TEMP	RMB	1
BYTECNT	RMB	1		;BYTE COUNTER

	END
