-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathuart.s
108 lines (97 loc) · 2.7 KB
/
uart.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
; UART ports: Base address is 0x20, total of 8 ports in use
uart_rbr: equ 0x20 ; RX Buffer/TX Holding Register
uart_ier: equ 0x21 ; Interrupt Enable Register
uart_iir: equ 0x22 ; Interrupt Identifier Register
uart_fcr: equ 0x22 ; FIFO Control Register
uart_lcr: equ 0x23 ; Line Control Register
uart_mcr: equ 0x24 ; Modem Control Register
uart_lsr: equ 0x25 ; Line Status Register
uart_msr: equ 0x26 ; Modem Status Register
uart_scr: equ 0x27 ; Scratch Register
uart_dll: equ 0x20 ; Divisor Latch LSB (when DLAB=1 in LCR)
uart_dlm: equ 0x21 ; Divisor Latch MSB (when DLAB=1 in LCR)
uart_dev_name: defm "ser0\0"
uart_driver: defw uart_rx
defw uart_tx
; Initialise the UART
uart_init: push af
;ld a,0x00 ; disable all interrupts
ld a,0x05 ; enable all RX interrupts
out (uart_ier),a
;ld a,0x0f ; enable and reset all FIFOs
;out (uart_fcr),a
ld a,0x80 ; Set DLAB
out (uart_lcr),a
ld a,12 ; Divisor of 12 = 9600 bps with 1.8432 MHz clock
out (uart_dll),a
ld a,00
out (uart_dlm),a
ld a,0x03 ; 8 bits, 1 stop, no parity (and clear DLAB)
out (uart_lcr),a ; write new value back
; Add a new device
ld a,0 ; ID
ld b,dev_flag_char ; Flags
ld de,uart_driver ; Driver
ld hl,uart_dev_name ; Name
call dev_add
pop af
ret
; uart_rx
; Wait for a byte from the UART, and save it in A
uart_rx: call uart_rx_ready
in a,(uart_rbr)
ret
; uart_rx_ready
; Returns when UART has received data
uart_rx_ready:
push af
uart_rx_ready_loop:
in a,(uart_lsr) ; fetch the conrtol register
bit 0,a ; bit will be set if UART has data
jp z,uart_rx_ready_loop
pop af
ret
; Name: uart_rx_ready_no_block
; Desc: Check if UART has data
; Out: ZF = cleared if UART has data
uart_rx_ready_no_block:
push af
in a,(uart_lsr) ; fetch the conrtol register
bit 0,a ; bit will be set if UART has data
pop af
ret
; uart_tx
; Sends byte in A to the UART
uart_tx: call uart_tx_ready
; cp '\n' ; Newlines are replaced with
; jp nz,uart_tx_send ; carriage returns so things
; ld a,'\r' ; are displayed right on the
uart_tx_send: ; terminal emulator.
out (uart_rbr),a
uart_tx_end:
ret
; uart_tx_str
; Sends null-terminated string starting at HL to UART
; XXX - can maybe optimised using CPI instruction?
uart_tx_str:
push af
uart_tx_str_loop:
ld a,(hl)
cp 0
jp z,uart_tx_str_end
call uart_tx
inc hl
jp uart_tx_str_loop
uart_tx_str_end:
pop af
ret
; uart_tx_ready
; Returns when UART is ready to receive
uart_tx_ready:
push af
uart_tx_ready_loop:
in a,(uart_lsr) ; fetch the control register
bit 5,a ; bit will be set if UART is ready
jp z,uart_tx_ready_loop
pop af
ret