;******************************************************************* ; Altair 680 Program ; Load S-Record file into memory (below 8000h) from the 680-UIO ; serial port, with error checking and reporting ; ; Usage: ; Use the Altair 680 ACIA PROM Monitor's 'L' command to load this ; program from the Teletype's paper tape reader (connected to the ; Altair 680's onboard serial port). Then jump to address 8000h ; ('J 8000') to load a larger program (e.g. Altair 680 Basic) via ; a high-speed paper tape reader that is connected to the 680-UIO ; serial port. ; ; Error Codes: ; A -- Address error - attempt to write above 7FFFh ; C -- Checksum error ; H -- Hex error (illegal character encountered) ; M -- Memory error (memory read-back failed) ; ; Revision History: ; Date Author Comment ; 20OCT2011 M. Eberhard Created ; 21OCT2011 M. Eberhard Print initial CRLF, error messages ; 23OCT2011 M. Eberhard Cleanup, ignore nulls ; ; Program Notes: ; * Written to assemble with A68.com (DOS-based cross assembler) ; * A68.com vers. 1.2.02 assembles 'jsr' incorrectly. to fix, patch ; A68.com address AFABh to be 8Dh (was 9Dh). ; * A68.com does not generate 'direct' versions of lda and sta. We ; generate them the hard way (with .db) here. ; * The intention is to connect the 680-UIO serial port to a high- ; speed paper tape reader that is enabled by the RS232 RTS signal. ; * Runs in RAM at 8000h, which is the Altair 680's onboard RAM ; if the Altair has 32K of RAM in expansion boards. ; * Echo is turned off while this program loads, by writing to the ; PROM monitor's 'echo' flag. ; * This program uses some of the same RAM variables as the ; PROM monitor program. ; * The high-spead reader is enabled/disabled by RTS. ;******************************************************************* ;** ;* 6800 equates ;** .equ SKIP2,h'8c ;CPX instruction for SKIP2 trick ;stupid assembler can't do direct addressing for lda, sta .equ ldaad,h'96 ;ldaa direct .equ ldabd,h'd6 ;ldab direct .equ staad,h'97 ;staa direct .equ stabd,h'd7 ;stab direct ;** ;* ASCII equates ;** .equ CR,h'0d ;carriage return .equ LF,h'0a ;line feed ;** ;* MC6850 ACIA equates ;** .equ ACIACTL,h'f006 ;control port .equ ACIASTA,h'f006 ;Status port .equ ACIADAT,h'f007 ;data port .equ RESACIA,b'00000011 ;reset .equ RTSACIA,b'00010101 ;RTS active, no ints, /16 clock, 8N1 .equ NRTACIA,b'01010101 ;RTS inactive .equ RDRF,b'00000001 ;Rx reg full .equ TDRE,b'00000010 ;Tx reg empty .equ DCD,b'00000100 ;DCD input .equ CTS,b'00001000 ;CTS input .equ FE,b'00010000 ;Framing Error .equ OVRN,b'00100000 ;Rx Overrun .equ PE,b'01000000 ;Parity Error .equ IRQ,b'10000000 ;int request ;** ;* RAM variables, same as PROM monitor ;** .org h'f1 stack: .rs 1 ;top of stack brkadr: .rs 1 ;(not used) echo: .rs 1 ;bit 7 is tty Echo Flag extflg: .rs 1 ;(not used) bufull: .rs 1 ;(not used) savstk: .rs 2 ;(not used) temp: .rs 1 ;temporary Storage bytect: .rs 1 ;byte Count xhi: .rs 1 ;xreg High xlow: .rs 1 ;xreg Low shift: .rs 1 ;(not used) savex: .rs 2 ;(not used) buffer: .rs 1 ;(not used) ;** ;* PROM Monitor entry points ;** .equ out2h,h'ff6d ;print a in hex, clobber b .equ outch,h'ff81 ;print chr in b on console .equ reset,h'ffd8 ;cold start .equ crlf,h'ffab ;command interpreter re-entry ;** ;* Disable echo during load ;** .org echo .db b'10000000 ;** ;* Main Program ;** .org h'8000 ;run in onboard 1K RAM main: ldx #h'0000 ;clear xhi/xlow in case of error stx xhi ldab #CR ;initial CRLF bsr gooutc ldab #LF bsr gooutc ldab #RESACIA ;reset 680-UIO ACIA stab ACIACTL ldab #RTSACIA ;setup ACIA, enable CTS stab ACIACTL ;** ;* Load Paper Tape from 680-UIO ;* Load only S1 type records ;* Check address, memory write, checksum ;* Terminate on S9 or checksum error ;** load: bsr inch ;read chr from ACIA cmpb #'S' bne load ;wait for starting S clra ;zero checksum bsr inch ;read chr following S cmpb #'9' beq done ;S9 End Of File cmpb #'1' bne load ;Ignore all but S1 & S9 bsr byte ;read record byte count subb #h'03 ;subtract off checksum, address .db stabd,bytect ;save byte count in RAM bsr byte ;get & save high order address .db stabd,xhi bsr byte ;get & save low order address .db stabd,xlow ldx xhi ;load x with 16-bit address gdata: stx xhi ;test for illegal address .db ldabd,xhi bmi adderr ;only lower 32K allowed bsr byte ;get data byte stab 0,x ;store data at target address cmpb 0,x ;read back to test write bne memerr inx ;bump pointer dec bytect ;decrement byte count bne gdata ;loop through record's data bytes bsr byte ;get checksum inca ;increment checksum beq load ;checksum ok: go get another record ldab #'C' ;checksum error bra error ;** ;* normal exit after S9 record ;** done: ldaa #NRTACIA ;disable reader staa ACIACTL bra gores ;** ;* jump to outch for shorter code ;** gooutc: jmp outch ;** ;* Subroutine to input one chr from 88-UIO ACIA into b-register ;* Strip parity and ignore nulls ;** inch: ldab ACIASTA ;88-UIO ACIA status to B asrb ;rotate RDRF bit into Carry bcc inch ;spin until chr ready ldab #h'7f ;mask parity andb ACIADAT ;get chr beq inch ;ignore nulls rts ;** ;* Subroutine to a read byte (2 hex digits) into b-register ;* a-register is used for checksum ;** byte: bsr inhex ;(get 1st hex digit aslb ;shift to high order nibble aslb aslb aslb .db stabd,temp bsr inhex ;get 2nd hex digit addb temp ;combine digits aba ;add To checksum rts ;*** ;* Subroutine to input one hex digit into b-register ;* Jump to error if invalid character ;** inhex: bsr inch ;get a chr subb #'0' ;convert ASCII number to hex cmpb #h'09 ble in1hg ;done already? cmpb #h'11 bmi hexerr ;not hex cmpb #h'16 bgt hexerr ;not hex subb #h'07 ;convert ASCII letter to hex in1hg: rts ;** ;* Error Routines ;* Print error chr in b, then '?', then address in xhi/xlow ;* Return to PROM monitor via 'reset' to fix stack ;** adderr: ldab #'A' ;write to upper 32K .db SKIP2 ;CPX: SKIP2 the next 2 bytes memerr: ldab #'M' ;memory read-back error .db SKIP2 ;CPX: SKIP2 the next 2 bytes hexerr: ldab #'H' ;bad hex digit error: ldaa #NRTACIA ;disable reader staa ACIACTL ;...right away bsr gooutc ;print error code in b ldab #'?' bsr gooutc .db ldaad,xhi ;high byte of address jsr out2h .db ldaad,xlow ;low byte of address jsr out2h clrb ;a couple of nulls to flush the bsr gooutc ;...onboard ACIA transmitter before bsr gooutc ;...the PROM monitor resets it gores: jmp reset ;the only exit ;** ;* enable echo after load ;** .org echo .db b'00000000 .end