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
|
// license:BSD-3-Clause
// copyright-holders:Brian Johnson
/*
QX-10 Option bus
1 GND 2 GND
3 DTB0 4 DTB1
5 DTB2 6 DTB3
7 DTB4 8 DTB5
9 DTB6 10 DTB7
11 -12V 12 -12V
13 ADR0 14 ADR1
15 ADR2 16 ADR3
17 ADR4 18 ADR5
19 ADR6 20 ADR7
21 ADR8 22 ADR9
23 ADR10 24 ADR11
25 ADR12 26 ADR13
27 ADR14 28 ADR15
29 GND 30 GND
31 CLK 32 GND
33 /BSAK 34 /MEMX
35 /IRD 36 /IWR
37 /MRD 38 /MWR
39 /RSIN 40 INTH1
41 INTH2 42 INTL
43 +5V 44 /RSET
45 +5V 46 +5V
47 /DRQF 48 /DRQS
49 /RDYF 50 /RDYS
51 /WAIT 52 /IWS
53 /DAKF 54 /DAKS
55 /EOPF 56 /EOPS
57 +12V 58 +12V
59 GND 60 GND
The INTH1 and INTH2 singals are the two hihg priority interrupts and are
global to the entire option bus. The INTL signal is the low priority interrupt
and is local to each of the 5 option slots.
5 4 3 2 1
|---| |---| |---| |---| |---|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------IRQH1 (Master IR2)
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------IRQH2 (Master IR3)
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | *-|--------IRQL (Slave IR1)
| | | | | | | | | |
| | | | | | | *-|--|---|--------IRQL (Slave IR3)
| | | | | | | | | |
| | | | | *-|--|---|--|---|--------IRQL (Slave IR4)
| | | | | | | | | |
| | | *-|--|---|--|---|--|---|--------IRQL (Slave IR6)
| | | | | | | | | |
| *-|--|---|--|---|--|---|--|---|--------IRQL (Slave IR7)
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
|---| |---| |---| |---| |---|
The DREQ/DACK(F) signals are the high priorty DMA signals and are shared between all option slots.
The DREQ/DACK(S) signals are the lower priority DMA signals and are local to each slot, with the
exception of slot 5 which does not provide low priority DMA signals. The RDY/EOP(S) signals are
also connected to all 5 options slots since the DREQ(S) signals are all connected to the same
DMA controller.
5 4 3 2 1
|---| |---| |---| |---| |---|
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------DREQF (Master CH3)
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------DACKF (Master Ch3)
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------RDYF (Master RDY)
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------EOPF (Master EOP)
| | | | | | | | | |
| | | | | | | | | *-|--------DREQS (Slave CH0)
| | | | | | | | | *-|--------DACKS (Slave CH0)
| | | | | | | | | |
| | | | | | | *-|--|---|--------DREQS (Slave CH1)
| | | | | | | *-|--|---|--------DACKS (Slave CH1)
| | | | | | | | | |
| | | | | *-|--|---|--|---|--------DREQS (Slave CH2)
| | | | | *-|--|---|--|---|--------DACKS (Slave CH2)
| | | | | | | | | |
| | | *-|--|---|--|---|--|---|--------DREQS (Slave CH3)
| | | *-|--|---|--|---|--|---|--------DACKS (Slave CH3)
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------RDYS (Slave RDY)
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------EOPS (Slave EOP)
| | | | | | | | | |
|---| |---| |---| |---| |---|
*/
#ifndef MAME_BUS_EPSON_QX_OPTION_H
#define MAME_BUS_EPSON_QX_OPTION_H
#pragma once
#include <vector>
namespace bus::epson_qx {
//**************************************************************************
// FORWARD DECLARATIONS
//**************************************************************************
class option_bus_device;
class device_option_expansion_interface;
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/* Epson Slot Device */
class option_slot_device : public device_t, public device_single_card_slot_interface<device_option_expansion_interface>
{
public:
friend class option_bus_device;
// construction/destruction
template <typename T, typename U>
option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&bus_tag, int slot, U &&opts, const char *dflt)
: option_slot_device(mconfig, tag, owner, bus_tag->clock())
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
m_bus.set_tag(std::forward<T>(bus_tag));
m_slot = slot;
}
option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void inth1_w(int state);
void inth2_w(int state);
void intl_w(int state);
void drqf_w(int state);
void drqs_w(int state);
void rdyf_w(int state);
void rdys_w(int state);
void eopf(int state);
void eops(int state);
auto dmas_w_callback() { m_dmas_w_cb.bind(); }
auto dmas_r_callback() { m_dmas_r_cb.bind(); }
auto dmaf_w_callback() { m_dmaf_w_cb.bind(); }
auto dmaf_r_callback() { m_dmaf_r_cb.bind(); }
auto in_eopf_callback() { return m_eopf_cb.bind(); }
auto in_eops_callback() { return m_eops_cb.bind(); }
protected:
// device-level overrides
virtual void device_start() override ATTR_COLD;
// configuration
required_device<option_bus_device> m_bus;
devcb_write8 m_dmas_w_cb;
devcb_read8 m_dmas_r_cb;
devcb_write8 m_dmaf_w_cb;
devcb_read8 m_dmaf_r_cb;
devcb_write_line m_eopf_cb;
devcb_write_line m_eops_cb;
int m_slot;
};
/* Epson Bus Device */
class option_bus_device : public device_t
{
public:
// construction/destruction
option_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
void set_memview(memory_view::memory_view_entry &view) { m_view = &view; }
auto out_inth1_callback() { return m_inth1_cb.bind(); }
auto out_inth2_callback() { return m_inth2_cb.bind(); }
template <unsigned Slot> auto out_intl_callback() { return m_intl_cb[Slot].bind(); }
auto out_drqf_callback() { return m_drqf_cb.bind(); }
template <unsigned Slot> auto out_drqs_callback() { return m_drqs_cb[Slot].bind(); }
auto out_rdyf_callback() { return m_rdyf_cb.bind(); }
auto out_rdys_callback() { return m_rdys_cb.bind(); }
memory_view::memory_view_entry& memview() const { return *m_view; }
address_space &iospace() const { return *m_iospace; }
void dackf_w(uint8_t data);
uint8_t dackf_r();
template <unsigned Slot> void dacks_w(uint8_t data) { (*this)[Slot]->m_dmas_w_cb(data); }
template <unsigned Slot> uint8_t dacks_r() { return (*this)[Slot]->m_dmas_r_cb(); }
template <void (option_slot_device::*slot_callback)(int)> void slots_w(int state) {
for (option_slot_device *slot : m_slot_list) {
(slot->*slot_callback)(state);
}
}
void set_inth1_line(uint8_t state, uint8_t slot);
void set_inth2_line(uint8_t state, uint8_t slot);
void set_intl_line(uint8_t state, uint8_t slot) { m_intl_cb[slot](state); }
void set_drqf_line(uint8_t state, uint8_t slot);
void set_drqs_line(uint8_t state, uint8_t slot) { m_drqs_cb[slot](state); }
void set_rdyf_line(uint8_t state, uint8_t slot);
void set_rdys_line(uint8_t state, uint8_t slot);
void add_slot(option_slot_device &slot);
option_slot_device* operator[](int index) const {assert(index < m_slot_list.size()); return m_slot_list[index]; }
protected:
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
required_address_space m_iospace;
memory_view::memory_view_entry *m_view;
devcb_write_line m_inth1_cb;
devcb_write_line m_inth2_cb;
devcb_write_line::array<5> m_intl_cb;
devcb_write_line m_drqf_cb;
devcb_write_line::array<4> m_drqs_cb;
devcb_write_line m_rdyf_cb;
devcb_write_line m_rdys_cb;
std::vector<option_slot_device *> m_slot_list;
uint8_t m_inth1;
uint8_t m_inth2;
uint8_t m_drqf;
uint8_t m_rdyf;
uint8_t m_rdys;
};
/* Epson Option Card interface */
class device_option_expansion_interface : public device_interface
{
public:
void set_option_bus(option_bus_device &bus, int slot) { assert(!device().started()); m_bus = &bus; m_slot = slot; }
protected:
device_option_expansion_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
option_slot_device* get_slot() { return (*m_bus)[m_slot]; }
option_bus_device *m_bus;
int m_slot;
};
void option_bus_devices(device_slot_interface &device);
} // namespace bus::epson_qx
// device type definition
DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_BUS_SLOT, bus::epson_qx, option_slot_device)
DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_BUS, bus::epson_qx, option_bus_device)
#endif // MAME_BUS_EPSON_QX_OPTION_H
|