; ;======================================================================= ; HDIAG UART Driver ;======================================================================= ; ; Assumes the UART conventions for SBC/MBC/Zeta, base port at $68. ; Assuming a UART clock frequency of 1.8432 MHz, the baud rate ; will be 38400. ; uart_iob .equ $68 uart_osc .equ 1843200 uart_baudrate .equ 38400 uart_divisor .equ uart_osc / uart_baudrate / 16 ; uart_rbr .equ uart_iob + 0 ; dlab=0: rcvr buffer reg (read only) uart_thr .equ uart_iob + 0 ; dlab=0: xmit holding reg (write only) uart_ier .equ uart_iob + 1 ; dlab=0: int enable reg uart_iir .equ uart_iob + 2 ; int ident register (read only) uart_fcr .equ uart_iob + 2 ; fifo control reg (write only) uart_lcr .equ uart_iob + 3 ; line control reg uart_mcr .equ uart_iob + 4 ; modem control reg uart_lsr .equ uart_iob + 5 ; line status reg uart_msr .equ uart_iob + 6 ; modem status reg uart_scr .equ uart_iob + 7 ; scratch register uart_dll .equ uart_iob + 0 ; dlab=1: divisor latch (ls) uart_dlm .equ uart_iob + 1 ; dlab=1: divisor latch (ms) ; ; ; uart_jptbl: jp uart_cinit ; Initialize serial port jp uart_cin ; Read byte jp uart_cout ; Write byte jp uart_cist ; Input status jp uart_cost ; Output Status ; ; ; uart_cinit: ; Test for existence ;;;xor a ; zero accum ;;;out (uart_ier),a ; ier := 0 ;;;ld a,$80 ; dlab bit on ;;;out (uart_lcr),a ; output to lcr (dlab regs now active) ;;;ld a,$5A ; load test value ;;;out (uart_dlm),a ; output to dlm ;;;in a,(uart_dlm) ; read it back ;;;cp $5A ; check for test value ;;;ret nz ; nope, unknown uart or not present ;;;xor a ; dlab bit off ;;;out (uart_lcr),a ; output to lcr (dlab regs now inactive) ;;;in a,(uart_ier) ; read ier ;;;cp $5A ; check for test value ;;;jr nz,uart_cinit1 ; if *not* $5A, good to go ;;;or $FF ; signal error ;;;ret ; done ; uart_cinit1: ld a,$80 ; lcr := dlab on out (uart_lcr),a ; set lcr ld a,uart_divisor & $ff ; low byte of divisor out (uart_dll),a ; set divisor (lsb) ld a,uart_divisor / $100 ; high byte of divisor out (uart_dlm),a ; set divisor (msb) xor a ; zero accum out (uart_ier),a ; init ier (no ints) ld a,$03 ; value for lcr and mcr out (uart_lcr),a ; lcr := 3, dlab off, 8 data, 1 stop, no parity out (uart_mcr),a ; mcr := 3, dtr on, rts on ld a,$07 ; enable & reset fifo's out (uart_fcr),a ; do it xor a ; signal success ret ; ; ; uart_cin: call uart_cist ; received char ready? jr z,uart_cin ; loop if not in a,(uart_rbr) ; read byte ret ; and done ; ; ; uart_cout: push af ; save incoming uart_cout1: call uart_cost ; ready for char? jr z,uart_cout1 ; loop if not pop af ; restore incoming out (uart_thr),a ; write byte ret ; and done ; ; ; uart_cist: in a,(uart_lsr) ; get status and $01 ; isolate bit 0 (receive data ready) ret ; a != 0 if char ready, else 0 ; ; ; uart_cost: in a,(uart_lsr) ; get status and $20 ; isolate bit 5 ret ; a != 0 if char ready, else 0