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
|
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
h8_port.cpp
H8 8 bits digital port
TODO:
- Many I/O port pins have a double function, eg. for IRQs or timer input
strobe. Ideally this device should know the input pin state, instead
of having to implement it in the MAME drivers.
***************************************************************************/
#include "emu.h"
#include "h8_port.h"
DEFINE_DEVICE_TYPE(H8_PORT, h8_port_device, "h8_digital_port", "H8 digital port")
h8_port_device::h8_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, H8_PORT, tag, owner, clock),
m_cpu(*this, DEVICE_SELF_OWNER), m_address(0), m_default_ddr(0), m_ddr(0), m_pcr(0), m_odr(0), m_mask(0), m_dr(0), m_last_output(0)
{
}
void h8_port_device::ddr_w(u8 data)
{
//logerror("ddr_w %02x\n", data);
m_ddr = data;
update_output();
}
u8 h8_port_device::ddr_r()
{
return m_ddr;
}
void h8_port_device::dr_w(u8 data)
{
//logerror("dr_w %02x\n", data);
m_dr = data;
update_output();
}
u8 h8_port_device::dr_r()
{
//logerror("dr_r %02x\n", (dr | mask) & 0xff);
return m_dr | m_mask;
}
u8 h8_port_device::port_r()
{
u8 res = m_mask | (m_dr & m_ddr);
if((m_ddr & ~m_mask) != u8(~m_mask))
res |= m_cpu->do_read_port(m_address) & ~m_ddr;
//logerror("port_r %02x (%02x %02x)\n", res, ddr & ~mask, u8(~mask));
return res;
}
void h8_port_device::pcr_w(u8 data)
{
logerror("pcr_w %02x\n", data);
m_pcr = data;
}
u8 h8_port_device::pcr_r()
{
logerror("pcr_r %02x\n", (m_pcr | m_mask) & 0xff);
return m_pcr | m_mask;
}
void h8_port_device::odr_w(u8 data)
{
logerror("odr_w %02x\n", data);
m_odr = data;
}
u8 h8_port_device::odr_r()
{
logerror("odr_r %02x\n", (m_odr | ~m_mask) & 0xff);
return m_odr | ~m_mask;
}
void h8_port_device::update_output()
{
u8 data = (m_dr | ~m_ddr) & ~m_mask;
u8 ddr = m_ddr & ~m_mask; // 0-bits = hi-z
u16 res = ddr << 8 | data;
if(res != m_last_output) {
m_last_output = res;
m_cpu->do_write_port(m_address, data, ddr);
}
}
void h8_port_device::device_start()
{
save_item(NAME(m_ddr));
save_item(NAME(m_pcr));
save_item(NAME(m_odr));
save_item(NAME(m_dr));
save_item(NAME(m_last_output));
m_last_output = -1;
m_dr = 0;
m_ddr = m_default_ddr;
m_pcr = 0;
m_odr = 0;
}
void h8_port_device::device_reset()
{
update_output();
}
bool h8_port_device::nvram_write(util::write_stream &file)
{
u8 const buf[4]{ m_ddr, m_dr, m_pcr, m_odr };
auto const [err, actual] = write(file, buf, sizeof(buf));
return !err;
}
bool h8_port_device::nvram_read(util::read_stream &file)
{
u8 buf[4];
auto const [err, actual] = read(file, buf, sizeof(buf));
if(err || (sizeof(buf) != actual))
return false;
m_ddr = buf[0];
m_dr = buf[1];
m_pcr = buf[2];
m_odr = buf[3];
return true;
}
|