-
Notifications
You must be signed in to change notification settings - Fork 0
/
comms.z80
369 lines (312 loc) · 14.9 KB
/
comms.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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
; SAM Coupé Printer and RS232 Comms Ports
; ---------------------------------------
;
; Author: Simon Cooke (spectecjr@gmail.com)
; Licensed under the MIT license (see LICENSE file).
; ==========================
; Parallel Printer Interface
; ==========================
; Printer ports
PRINTER_0_DATA: EQU 232
PRINTER_0_CONTROL: EQU 233
PRINTER_1_DATA: EQU 234
PRINTER_1_CONTROL: EQU 235
; Write PRINTER_STROBE to PRINTER_x_CONTROL to strobe.
; Set = Data is ready. Set->Reset transition = Send.
PRINTER_STROBE: EQU %00000001
; Read PRINTER_x_CONTROL and mask with PRINTER_BUSY
; to see if printer is ready for next byte.
PRINTER_BUSY: EQU %00000001
; Example of usage:
; send_byte_to_LPT0:
; ; you may want to implement a watchdog timeout
; ; here...
; IN A,(PRINTER_0_CONTROL)
; AND PRINTER_BUSY
; JP NZ, send_byte_to_LPT0
; ; emit byte.
; LD A,E
; OUT (PRINTER_0_DATA), A
; LD A,PRINTER_STROBE
; OUT (PRINTER_0_CONTROL), A
; XOR A
; OUT (PRINTER_0_CONTROL), A
; RET
; ==============================
; Serial Communications Inteface
; ==============================
; The SAM Coupé uses an SCC2691 UART from Philips Semiconductor
;
; Data sheet: https://www.nxp.com/docs/en/data-sheet/SCC2691.pdf
; RS232 Serial Comms port base address
COMMS_PORT_BASE: EQU 236
COMMS_0_BASE: EQU COMMS_PORT_BASE + 0
COMMS_1_BASE: EQU COMMS_PORT_BASE + 1
COMMS_2_BASE: EQU COMMS_PORT_BASE + 2
COMMS_3_BASE: EQU COMMS_PORT_BASE + 3
; [R/W] - Mode registers 1 & 2
COMMS_MR: EQU &0000
COMMS_MR_H: EQU &00
; [RO] - Channel Status register
COMMS_SR: EQU &0100
COMMS_SR_H: EQU &01
; [RO] - BRG Test mode - reading toggles to 2nd alternate set of baud rates
COMMS_BRG_TEST: EQU &0200
COMMS_BRG_TEST_H: EQU &02
; [RO] - Recieve Holding register
COMMS_RHR: EQU &0300
COMMS_RHR_H: EQU &03
; [RO] -
COMMS_1X_16X_TEST: EQU &0400
COMMS_1X_16X_TEST_H: EQU &04
; [RO] - Interrupt Status register
COMMS_ISR: EQU &0500
COMMS_ISR_H: EQU &05
; [R/W] - Counter/Timer Upper
COMMS_CTU: EQU &0600
COMMS_CTU_H: EQU &06
; [R/W] - Counter/Timer Lower
COMMS_CTL: EQU &0700
COMMS_CTL_H: EQU &07
; [WO] - Clock Select register
COMMS_CSR: EQU &0100
COMMS_CSR_H: EQU &01
; [WO] - Command register
COMMS_CR: EQU &0200
COMMS_CR_H: EQU &02
; [WO] - Transmit Holding register
COMMS_THR: EQU &0300
COMMS_THR_H: EQU &03
; [WO] - Auxiliary Control register
COMMS_ACR: EQU &0400
COMMS_ACR_H: EQU &04
; [WO] - Interrupt Mask register
COMMS_IMR: EQU &0500
COMMS_IMR_H: EQU &05
; Mode Register 1 [R/W]
; =====================
; Mode Register 1 Parity Mode values
COMMS_MR1_WITH_PARITY: EQU %00000000
COMMS_MR1_FORCE_PARITY: EQU %00001000
COMMS_MR1_NO_PARITY: EQU %00010000
COMMS_MR1_SPECIAL_MODE: EQU %00011000
COMMS_MR1_PARITY_MODE_MASK: EQU %00011000
; Mode Register 1 Parity Types
COMMS_MR1_EVEN_PARITY: EQU %00000000
COMMS_MR1_ODD_PARITY: EQU %00000100
COMMS_MR1_PARITY_TYPE_MASK: EQU %00000100
; Mode Register 1 Bits per Character
COMMS_MR1_5_BITS_PER_CHAR: EQU %00000000
COMMS_MR1_6_BITS_PER_CHAR: EQU %00000001
COMMS_MR1_7_BITS_PER_CHAR: EQU %00000010
COMMS_MR1_8_BITS_PER_CHAR: EQU %00000011
COMMS_MR1_BITS_PER_CHAR_MASK: EQU %00000011
; Mode Register 1 Error Mode
COMMS_MR1_ERROR_MODE_MASK: EQU %00100000
COMMS_MR1_CHAR_ERROR_MODE: EQU %00000000
COMMS_MR1_BLOCK_ERROR_MODE: EQU %00100000
; Mode Register 1 Receiver Interrupt Mode Select
COMMS_MR1_RX_INT_MASK: EQU %01000000
COMMS_MR1_RX_INT_ON_RX_READY: EQU %00000000
COMMS_MR1_RX_INT_ON_FIFO_FULL: EQU %01000000
; Mode Register 1 RTS Control Mode Select
COMMS_MR1_RX_RTS_MASK: EQU %10000000
COMMS_MR1_RX_RTS_DISABLED: EQU %00000000
COMMS_MR1_RX_RTS_ENABLED: EQU %10000000
; Mode Register 2 [R/W]
; =====================
; Mode Register 2 Channel Mode setting
COMMS_MR2_CHANNEL_MODE_MASK: EQU %11000000
COMMS_MR2_CHANNEL_MODE_NORMAL: EQU %00000000
COMMS_MR2_CHANNEL_MODE_AUTO_ECHO: EQU %01000000
COMMS_MR2_CHANNEL_MODE_LOCAL_LOOP: EQU %10000000
COMMS_MR2_CHANNEL_MODE_REMOTE_LOOP: EQU %11000000
; Mode Register 2 TX Request-To-Send (RTS) Mode select
COMMS_MR2_TX_RTS_MASK: EQU %00100000
COMMS_MR2_TX_RTS_DISABLED: EQU %00000000
COMMS_MR2_TX_RTS_ENABLED: EQU %00100000
; Mode Register 2 Clear-to-Send (CTS) Mode select
COMMS_MR2_CTS_ENABLE_MASK: EQU %00010000
COMMS_MR2_CTS_DISABLED: EQU %00000000
COMMS_MR2_CTS_ENABLED: EQU %00010000
; Mode Register 2 Stop Bit Length
; Length of a stop bit vs. normal bit duration.
; Note: If MR1 is set to 5 Bits per Character mode
; the first 8 settings are 0.5 longer than normal.
; This is reflected in the naming below.
COMMS_MR2_STOP_BIT_LENGTH_MASK: EQU %00001111
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_063: EQU %0000
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_125: EQU %0001
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_188: EQU %0010
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_250: EQU %0011
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_313: EQU %0100
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_375: EQU %0101
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_438: EQU %0110
COMMS_MR2_STOP_BIT_LENGTH_5BPC_1_500: EQU %0111
COMMS_MR2_STOP_BIT_LENGTH_0_563: EQU %0000
COMMS_MR2_STOP_BIT_LENGTH_0_625: EQU %0001
COMMS_MR2_STOP_BIT_LENGTH_0_688: EQU %0010
COMMS_MR2_STOP_BIT_LENGTH_0_750: EQU %0011
COMMS_MR2_STOP_BIT_LENGTH_0_813: EQU %0100
COMMS_MR2_STOP_BIT_LENGTH_0_875: EQU %0101
COMMS_MR2_STOP_BIT_LENGTH_0_938: EQU %0110
COMMS_MR2_STOP_BIT_LENGTH_1_000: EQU %0111
COMMS_MR2_STOP_BIT_LENGTH_1_563: EQU %1000
COMMS_MR2_STOP_BIT_LENGTH_1_625: EQU %1001
COMMS_MR2_STOP_BIT_LENGTH_1_688: EQU %1010
COMMS_MR2_STOP_BIT_LENGTH_1_750: EQU %1011
COMMS_MR2_STOP_BIT_LENGTH_1_813: EQU %1100
COMMS_MR2_STOP_BIT_LENGTH_1_875: EQU %1101
COMMS_MR2_STOP_BIT_LENGTH_1_938: EQU %1110
COMMS_MR2_STOP_BIT_LENGTH_2_000: EQU %1111
; Clock Select Register [WO]
; ==========================
; Multiplier for CLOCKRATE values to align with bits in
; clock register for RX clock.
;
; e.g. to set the clockrate for the RX channel to 7200 baud,
; use: COMMS_RX_CLOCK_MALIGN * COMMS_CLOCKRATE_7200_BAUD (and
; set COMMS_ACR_BRG_SET to ACR_BRG_SET_1).
COMMS_RX_CLOCK_MALIGN: EQU 16
; Multiplier for CLOCKRATE values to align with bits in
; clock register for TX clock.
COMMS_TX_CLOCK_MALIGN: EQU 1
; Masks for the two clock settings.
COMMS_RX_CLOCK_MASK: EQU &F0
COMMS_TX_CLOCK_MASK: EQU &0F
; Baud rates:
; With ACR Baud Generator Set to 0
COMMS_CLOCKRATE_50_BAUD: EQU %0000
COMMS_CLOCKRATE_200_BAUD: EQU %0011
COMMS_CLOCKRATE_1050_BAUD: EQU %0111
COMMS_CLOCKRATE_7200_BAUD: EQU %1010
COMMS_CLOCKRATE_38400_BAUD: EQU %1100
; With ACR Baud Generator Set to 1
; (Holes are same as set to 0)
COMMS_CLOCKRATE_75_BAUD: EQU %0000
COMMS_CLOCKRATE_150_BAUD: EQU %0011
COMMS_CLOCKRATE_2000_BAUD: EQU %0111
COMMS_CLOCKRATE_1800_BAUD: EQU %1010
COMMS_CLOCKRATE_19200_BAUD: EQU %1100
; Same rate /regardless/ of ACR Baud settings
COMMS_CLOCKRATE_110_BAUD: EQU %0001
COMMS_CLOCKRATE_134_5_BAUD: EQU %0010
COMMS_CLOCKRATE_300_BAUD: EQU %0100
COMMS_CLOCKRATE_600_BAUD: EQU %0101
COMMS_CLOCKRATE_1200_BAUD: EQU %0110
COMMS_CLOCKRATE_2400_BAUD: EQU %1000
COMMS_CLOCKRATE_4800_BAUD: EQU %1001
COMMS_CLOCKRATE_9600_BAUD: EQU %1011
COMMS_CLOCKRATE_TIMER: EQU %1101
COMMS_CLOCKRATE_MPI_16X: EQU %1110
COMMS_CLOCKRATE_MPI_1X: EQU %1111
; Command Register [WO]
; =====================
COMMS_COMMAND_TXRX_ENABLE_MASK: EQU %00001111
; ENABLE/DISABLE TX and RX commands.
; These are weird; you can specify ENABLE/DISABLE RX
; and ENABLE/DISABLE TX, or even none of them.
COMMS_COMMAND_RX_ENABLE_CMD_MASK: EQU %00000011
COMMS_COMMAND_ENABLE_RX: EQU %00000001
COMMS_COMMAND_DISABLE_RX: EQU %00000010
COMMS_COMMAND_TX_ENABLE_CMD_MASK: EQU %00001100
COMMS_COMMAND_ENABLE_TX: EQU %00000100
COMMS_COMMAND_DISABLE_TX: EQU %00001000
COMMS_MISC_COMMAND_MASK: EQU %11110000
COMMS_COMMAND_NONE: EQU %00000000
COMMS_COMMAND_RESET_MR_POINTER: EQU %00010000
COMMS_COMMAND_RESET_RX: EQU %00100000
COMMS_COMMAND_RESET_TX: EQU %00110000
COMMS_COMMAND_RESET_ERROR_STATUS: EQU %01000000
COMMS_COMMAND_RESET_BREAK_CHANGE_INT: EQU %01010000
COMMS_COMMAND_START_BREAK: EQU %01100000
COMMS_COMMAND_STOP_BREAK: EQU %01110000
COMMS_COMMAND_START_COUNTERTIMER: EQU %10000000
COMMS_COMMAND_STOP_COUNTERTIMER: EQU %10010000
COMMS_COMMAND_ASSERT_RTSN_LOW: EQU %10100000
COMMS_COMMAND_NEGATE_RTSN_HIGH: EQU %10110000
COMMS_COMMAND_RESET_MPI_CHANGE_INT: EQU %11000000
; Note: Commands %11100000 and %11110000 are reserved.
; Status Register [RO]
; ====================
; Break signal was detected on the reciever
COMMS_STATUS_RECEIVED_BREAK: EQU %10000000
; Stop bit wasn't detected at end of character
COMMS_STATUS_FRAMING_ERROR: EQU %01000000
; Parity error detected (or wake-up mode bit)
COMMS_STATUS_PARITY_ERROR: EQU %00100000
; Overrun error detected (data not read quick enough)
COMMS_STATUS_OVERRUN_ERROR: EQU %00010000
; The transmitter is ready for new data, and its queue is
; empty (underrun)
COMMS_STATUS_TX_EMPTY: EQU %00001000
; Transmitter is ready
COMMS_STATUS_TX_READY: EQU %00000100
; The receiver FIFO queue is full. Another byte arriving
; in this state will cause an overrun error.
COMMS_STATUS_FIFO_FULL: EQU %00000010
; The receiver is ready to be read.
COMMS_STATUS_RX_READY: EQU %00000001
; Auxiliary Control Register [WO]
; ===============================
COMMS_ACR_BAUD_RATE_GENERATOR_SET_MASK: EQU %10000000
COMMS_ACR_BAUD_RATE_GENERATOR_SET_1: EQU %00000000
COMMS_ACR_BAUD_RATE_GENERATOR_SET_2: EQU %10000000
COMMS_ACR_OPERATING_MODE_MASK: EQU %01110000
COMMS_ACR_COUNTER_MODE_CLK_SRC_MPI: EQU %00000000
COMMS_ACR_COUNTER_MODE_CLK_SRC_MPI_DIV_16: EQU %00010000
COMMS_ACR_COUNTER_MODE_CLK_SRC_TX: EQU %00100000
COMMS_ACR_COUNTER_MODE_CLK_SRC_XTAL_DIV_16:EQU %00110000
COMMS_ACR_TIMER_MODE_CLK_SRC_MPI: EQU %01000000
COMMS_ACR_TIMER_MODE_CLK_SRC_MPI_DIV_16: EQU %01010000
COMMS_ACR_TIMER_MODE_CLK_SRC_TX: EQU %01100000
COMMS_ACR_TIMER_MODE_CLK_SRC_XTAL_DIV_16: EQU %01110000
COMMS_ACR_POWERDOWN_MODE_MASK: EQU %00001000
COMMS_ACR_POWERDOWN_MODE_ENABLE: EQU %00000000
COMMS_ACR_POWERDOWN_MODE_DISABLE: EQU %00001000
COMMS_ACR_MPO_OUTPUT_SELECT_MASK: EQU %00000111
COMMS_ACR_MPO_RTSN: EQU %00000000
COMMS_ACR_MPO_COUNTERTIMER: EQU %00000001
COMMS_ACR_MPO_1X_TX_CLOCK: EQU %00000010
COMMS_ACR_MPO_16X_TX_CLOCK: EQU %00000011
COMMS_ACR_MPO_1X_RX_CLOCK: EQU %00000100
COMMS_ACR_MPO_16X_RX_CLOCK: EQU %00000101
COMMS_ACR_MPO_TX_EMPTY_LOW: EQU %00000110
; The next two are the same value, and their meaning will
; depend on how MR1 was configured.
COMMS_ACR_MPO_RXRDY_LOW: EQU %00000111
COMMS_ACR_MPO_FIFO_LOW: EQU %00000111
; Interrupt Status Register [RO]
; ==============================
COMMS_ISR_MPI_CHANGED: EQU %10000000
COMMS_ISR_MPI_STATE: EQU %01000000
COMMS_ISR_COUNTER_READY: EQU %00010000
COMMS_ISR_BREAK_CHANGED: EQU %00001000
; The next two are the same value, and their meaning will
; depend on how MR1 was configured.
COMMS_ISR_RXRDY: EQU %00000100
COMMS_ISR_FIFO_FULL: EQU %00000100
COMMS_ISR_TX_EMPTY: EQU %00000010
COMMS_ISR_TX_READY: EQU %00000001
; Interrupt Mask Register [WO]
; ============================
; note: These are the same as the ISR values for their
; corresponding status bits.
COMMS_IMR_MPI_CHANGED_ENABLE: EQU %10000000
COMMS_IMR_MPI_CHANGED_DISABLE: EQU 0
COMMS_IMR_MPI_STATE_ENABLE: EQU %01000000
COMMS_IMR_MPI_STATE_DISABLE: EQU 0
COMMS_IMR_COUNTER_READY_ENABLE: EQU %00010000
COMMS_IMR_COUNTER_READY_DISABLE: EQU 0
COMMS_IMR_BREAK_CHANGED_ENABLE: EQU %00001000
COMMS_IMR_BREAK_CHANGED_DISABLE: EQU 0
; The next two are the same value, and their meaning will
; depend on how MR1 was configured.
COMMS_IMR_RXRDY_ENABLE: EQU %00000100
COMMS_IMR_RXRDY_DISABLE: EQU 0
COMMS_IMR_FIFO_FULL_ENABLE: EQU %00000100
COMMS_IMR_FIFO_FULL_DISABLE: EQU 0
COMMS_IMR_TX_EMPTY_ENABLE: EQU %00000010
COMMS_IMR_TX_EMPTY_DISABLE: EQU 0
COMMS_IMR_TX_READY_ENABLE: EQU %00000001
COMMS_IMR_TX_READY_DISABLE: EQU 0