-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathacia.c
141 lines (122 loc) · 2.48 KB
/
acia.c
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
/*
* MC6805 ACIA Connected to
*
* D0-D7 BUS:D0-D7
* E CPU:E
* R/W R/W
* CS0 GLUE:6850CS
* CS1 +5V
* CS2 BUS:A2
* RS BUS:A1
* IRQ MFP:I4
* TX CLK 0.5MHz
* RX CLK 0.5MHz
* TX DATA IKBD
* RX DATA IKBD
* CTS GND
* RTS -
* DCD GND
*/
#include "common.h"
#include "mmu.h"
#include "mfp.h"
#include "ikbd.h"
#include "diag.h"
#define ACIASIZE 4
#define ACIABASE 0xfffc00
#define ACIA_RX_FULL 0x01
#define ACIA_TX_EMPTY 0x02
#define ACIA_RX_OVERRUN 0x20
#define ACIA_IRQ 0x80
#define ACIA_IE 0x80
static BYTE acia_control;
static BYTE acia_status;
static BYTE rx_data;
HANDLE_DIAGNOSTICS(acia)
int acia_rx_full()
{
return acia_status & ACIA_RX_FULL;
}
static void set_status(BYTE data)
{
acia_status = data;
if((acia_control & ACIA_IE) && (acia_status & ACIA_IRQ))
mfp_clr_GPIP(MFP_GPIP_ACIA);
else
mfp_set_GPIP(MFP_GPIP_ACIA);
}
void acia_rx_data(BYTE data)
{
TRACE("Rx %02x", data);
rx_data = data;
set_status(acia_status | ACIA_RX_FULL | ACIA_IRQ);
}
static void acia_reset(void)
{
acia_control = 0;
rx_data = 0;
set_status(ACIA_TX_EMPTY);
}
static BYTE acia_read_byte(LONG addr)
{
BYTE data;
CLOCK("Wait states: 6");
cpu_add_extra_cycles(6);
switch(addr) {
case 0xfffc00:
return acia_status;
case 0xfffc02:
set_status(acia_status & ~(ACIA_RX_FULL | ACIA_IRQ));
data = rx_data;
TRACE("Read %02x", data);
return data;
default:
return 0;
}
}
static WORD acia_read_word(LONG addr)
{
return (acia_read_byte(addr)<<8)|acia_read_byte(addr+1);
}
static void acia_write_byte(LONG addr, BYTE data)
{
CLOCK("Wait states: 6");
cpu_add_extra_cycles(6);
switch(addr) {
case 0xfffc00:
DEBUG("Control %02x", data);
if(data == 3) {
DEBUG("Reset");
acia_reset();
} else if((data & 0x7C) != 0x14)
DEBUG("Unsupported configuration");
acia_control = data;
break;
case 0xfffc02:
TRACE("Write %02x", data);
ikbd_write_byte(data);
break;
}
}
static void acia_write_word(LONG addr, WORD data)
{
acia_write_byte(addr, (data&0xff00)>>8);
acia_write_byte(addr+1, (data&0xff));
}
void acia_init()
{
struct mmu *acia;
acia = mmu_create("ACIA", "ACIA");
if(!acia) {
return;
}
acia->start = ACIABASE;
acia->size = ACIASIZE;
acia->read_byte = acia_read_byte;
acia->read_word = acia_read_word;
acia->write_byte = acia_write_byte;
acia->write_word = acia_write_word;
acia->diagnostics = acia_diagnostics;
mmu_register(acia);
acia_reset();
}