-
Notifications
You must be signed in to change notification settings - Fork 1
/
uart.z80
277 lines (257 loc) · 6.13 KB
/
uart.z80
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
; Basic driver for NXP SCC2692 DUART
; Register definitions
.MRA: equ DUARTBASE + 0x00 ; Mode Register A (R/W)
.SRA: equ DUARTBASE + 0x01 ; Status Register A (R)
.CSRA: equ DUARTBASE + 0x01 ; Clock Select Register A (W)
.BRG: equ DUARTBASE + 0x02 ; BRG test (R)
.CRA: equ DUARTBASE + 0x02 ; Command Register A (W)
.RHRA: equ DUARTBASE + 0x03 ; Rx Holding Register A (R)
.THRA: equ DUARTBASE + 0x03 ; Tx Holding Register A (W)
.IPCR: equ DUARTBASE + 0x04 ; Input Port Change Register (R)
.ACR: equ DUARTBASE + 0x04 ; Aux Control Register (W)
.ISR: equ DUARTBASE + 0x05 ; Interrupt Status Register (R)
.IMR: equ DUARTBASE + 0x05 ; Interrupt Mask Register (W)
.CTU: equ DUARTBASE + 0x06 ; Counter/timer upper value (R)
.CRUR: equ DUARTBASE + 0x06 ; Counter/timer upper preset value (W)
.CTL: equ DUARTBASE + 0x07 ; Counter/timer lower value (R)
.CTLR: equ DUARTBASE + 0x07 ; Counter/timer lower preset value (W)
.MRB: equ DUARTBASE + 0x08 ; Mode Register B (R/W)
.SRB: equ DUARTBASE + 0x09 ; Status Register B (R)
.CSRB: equ DUARTBASE + 0x09 ; Clock Select Register B (W)
.1X16X: equ DUARTBASE + 0x0A ; 1X/16X Test (R)
.CRB: equ DUARTBASE + 0x0A ; Command Register B (W)
.RHRB: equ DUARTBASE + 0x0B ; Rx Holding Register B (R)
.THRB: equ DUARTBASE + 0x0B ; Tx Holding Register B (W)
.RES: equ DUARTBASE + 0x0C ; Reserved (R/W)
.IP: equ DUARTBASE + 0x0D ; Input Ports IP0 to IP6 (R)
.OPCR: equ DUARTBASE + 0x0D ; Output Port Conf. Register (W)
.START: equ DUARTBASE + 0x0E ; Start Counter Command (R)
.SETOP: equ DUARTBASE + 0x0E ; Set Output Port Bits Command (W)
.STOP: equ DUARTBASE + 0x0F ; Stop Counter Command (R)
.RSTOP: equ DUARTBASE + 0x0F ; Reset Output Port Bits Command (W)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PUBLIC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UartInitA:
; Initialise channel A of UART according to value of A
; A1,A0 - 00: 5 bits per char
; 01: 6 bits per char
; 10: 7 bits per char
; 11: 8 bits per char
; A2 - 0: 1 stop char
; 1: 2 stop chars
; A4,A3 - 00: no parityar
; 01: odd parity
; 10: no parity
; 11: even parity
; A7,A6,A5 - 000: 600 baud
; 001: 1.2k baud
; 010: 2.4k baud
; 011: 4.8k baud
; 100: 7.2k baud
; 101: 9.6k baud
; 110: 19.2k baud
; 111: 38.4k baud
ld b, a
; Disable transmitter and receiver
ld a, 00001010b
out (.CRA), a
; Set MR1 and MR2 registers on UART
ld c, .MRA
call UartInitMR1
call UartInitMR2
; Set ACR register on UART
ld c, .ACR
call UartInitACR
; Set CSR register on UART
ld c, .CSRA
call UartInitCSR
; Enable transmitter and receiver
ld a, 00000101b
out (.CRA), a
ret
UartInitB:
; Initialise channel B of UART according to value of A
; Mapping from a to settings as per UartInitA
ld b, a
; Disable transmitter and receiver
ld a, 00001010b
out (.CRB), a
; Set MR1 and MR2 registers on UART
ld c, .MRB
call UartInitMR1
call UartInitMR2
; Set ACR register on UART
ld c, .ACR
call UartInitACR
; Set CSR register on UART
ld c, .CSRB
call UartInitCSR
; Enable transmitter and receiver
ld a, 00000101b
out (.CRB), a
ret
UartInitMR1:
; STEP 1, set bits per char and parity
; Derive a byte from A:
; 00 00 00 00 A4 A3 A1 A0
ld a, b
and 00011000b
srl a
ld d, a
ld a, b
and 00000011b
or d
; Use this byte to read MR1 from table
ld hl, MR1TABLE
ld d, 0x00
ld e, a
add hl, de
ld a, (hl)
out (c), a
ret
UartInitMR2:
; STEP 2, set stop characters
; Derive a byte from A:
; 00 00 00 00 00 00 00 A2
ld a, b
and 00000100
srl a
srl a
; Use this byte to read MR2 from table
ld hl, MR2TABLE
ld d, 0x00
ld e, a
add hl, de
ld a, (hl)
out (c), a
ret
UartInitACR:
; STEP 3, set baud
; Derive a byte from A:
; 00 00 00 00 00 A7 A6 A5
ld a, b
srl a
srl a
srl a
srl a
srl a
; Save this derived byte in B.
; Note that this overrides the user-provided value of A
; which is an input to the UartInitA or UartInitB function
; which is calling *this* function. This saved byte in B
; will later be used by UartInitCSR. I'm documenting this
; because if I ever try to use the UartInit* sub-functions
; independent of UartInitA or UartInitB, this will be confusing.
ld b, a
cp 00000110b
jr z, UartInitACR_1
ld a, 00110000b
jr UartInitACR_set
UartInitACR_1:
ld a, 10110000b
UartInitACR_set:
out (c), a
ret
UartInitCSR:
; Use this byte to read CSR from table
ld hl, CSRTABLE
ld d, 0x00
ld e, b
add hl, de
ld a, (hl)
out (c), a
ret
ReadA:
call WaitToReadA
in a, (.RHRA)
ret
WriteA:
push af
call WaitToWriteA
pop af
out (.THRA), a
ret
ReadB:
call WaitToReadB
in a, (.RHRB)
ret
WriteB:
push af
call WaitToWriteB
pop af
out (.THRB), a
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PRIVATE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WaitToReadA:
in a, (.SRA) ; Read status reg
and 00000001b ; Mask off receive ready
xor 00000001b ; Compare receive ready to 1
jr nz, WaitToReadA ; Read status again if not ready
ret
WaitToWriteA:
in a, (.SRA) ; Read status reg
and 00000100b ; Mask off receive ready
xor 00000100b ; Compare receive ready to 1
jr nz, WaitToWriteA ; Read status again if not ready
ret
WaitToReadB:
in a, (.SRB) ; Read status reg
and 00000001b ; Mask off receive ready
xor 00000001b ; Compare receive ready to 1
jr nz, WaitToReadB ; Read status again if not ready
ret
WaitToWriteB:
in a, (.SRB) ; Read status reg
and 00000100b ; Mask off receive ready
xor 00000100b ; Compare receive ready to 1
jr nz, WaitToWriteB ; Read status again if not ready
ret
MR1TABLE:
defb 00010000b
defb 00010001b
defb 00010010b
defb 00010011b
defb 00000100b
defb 00000101b
defb 00000110b
defb 00000111b
defb 00010000b
defb 00010001b
defb 00010010b
defb 00010011b
defb 00000000b
defb 00000001b
defb 00000010b
defb 00000011b
MR2TABLE:
defb 00000111b
defb 00001111b
CSRTABLE:
defb 01010101b
defb 01100110b
defb 10001000b
defb 10011001b
defb 10101010b
defb 10111011b
defb 11001100b
defb 11001100b
;Led1On:
; ld a, 0x80
; jr LedReset
;Led2On:
; ld a, 0x40
;LedReset:
; out (.RSTOP), a
; ret
;
;Led1Off:
; ld a, 0x80
; jr LedSet
;Led2Off:
; ld a, 0x40
;LedSet:
out (.SETOP), a
ret