1 // license:BSD-3-Clause
2 // copyright-holders:AJR
3 /**********************************************************************
4
5 SWTPC SS-50 I/O port interface
6
7 The SS-50 bus is actually two buses in one: a 50-pin master bus
8 used by RAM boards and such, and a 30-pin I/O bus derived from it
9 either on the motherboard or a dedicated interface board, which
10 provides each of eight "interface" cards with its specific chip
11 select line and only a few address lines for register selection.
12 This 30-pin bus is what is emulated here.
13
14 As originally introduced in the 6800 Computer System, the
15 interface bus only included two register select lines, just enough
16 to drive one MC6820 PIA. No defined signals were placed on the
17 first two lines, which cards were permitted to use for any
18 purpose. The original MP-B motherboard also quite wastefully
19 reserved 8K (technically 4K) of address space to map a maximum of
20 32 read/write registers. The later MC6809-oriented systems not
21 only reduced the I/O segment to a selectable 1K, but appropriated
22 the two formerly undefined lines for two additional register
23 select lines, making it possible to use more complex interface
24 cards but breaking compatibility with some earlier ones.
25
26 An unusual feature of the SS-50 bus is the presence of five baud
27 rate frequencies, selected from among the (inverted) outputs of
28 a MC14411 Bit Rate Generator. The 6800 Computer System provided
29 only rates between 110 and 1200 (multiplied by 16), and also used
30 the MC14411's master frequency to generate the CPU clocks. The
31 MP-09 CPU board retained the MC14411 at first, but provided an
32 independent XTAL for the MC6809 and jumpers to select higher
33 baud rates. Later the MC14411 was removed from the CPU board so
34 the five baud rate lines on the 50-pin bus could be reused to
35 provide 20-bit addressing and DMA. This was accomplished by
36 adding a separate MP-ID Interface Driver Board to decode I/O
37 accesses (and optionally slow them down to allow old 1 MHz
38 peripherals to be used with a faster CPU), generate the baud
39 rates (whose selection was changed yet again) from a dedicated
40 MC14411, and provide a few I/O functions of its own.
41
42 ***********************************************************************
43
44 +-+
45 30 |o| RS2 (originally UD3)
46 29 |o| RS3 (originally UD4)
47 28 |o| -16V (originally -12V)
48 27 |o| +16V (originally +12V)
49 26 |o| GND
50 25 |o| GND
51 24 |o| INDEX
52 23 |o| /FIRQ (6800: /NMI)
53 22 |o| /IRQ
54 21 |o| RS0
55 20 |o| RS1
56 19 |o| D0
57 18 |o| D1
58 17 |o| D2
59 16 |o| D3
60 15 |o| D4
61 14 |o| D5
62 13 |o| D6
63 12 |o| D7
64 11 |o| E (6800: ϕ2)
65 10 |o| R/W
66 9 |o| +8V (unregulated)
67 8 |o| +8V (unregulated)
68 7 |o| 600b/1200b (originally 1200b)
69 6 |o| 4800b (originally 600b)
70 5 |o| 300b
71 4 |o| 150b/9600b (originally 150b)
72 3 |o| 110b
73 2 |o| /RESET
74 1 |o| I/O #
75 +-+
76
77 **********************************************************************/
78
79 #include "emu.h"
80 #include "bus/ss50/interface.h"
81
82 #include "bus/ss50/dc5.h"
83 #include "bus/ss50/mpc.h"
84 //#include "bus/ss50/mpl.h"
85 //#include "bus/ss50/mpr.h"
86 #include "bus/ss50/mps.h"
87 #include "bus/ss50/mps2.h"
88 #include "bus/ss50/mpt.h"
89 #include "bus/ss50/piaide.h"
90
91 //**************************************************************************
92 // GLOBAL VARIABLES
93 //**************************************************************************
94
95 // device type definition
96 DEFINE_DEVICE_TYPE(SS50_INTERFACE, ss50_interface_port_device, "ss50_interface", "SS-50 Interface Port")
97
98 //**************************************************************************
99 // SS-50 INTERFACE PORT DEVICE
100 //**************************************************************************
101
102 //-------------------------------------------------
103 // ss50_interface_port_device - construction
104 //-------------------------------------------------
105
ss50_interface_port_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)106 ss50_interface_port_device::ss50_interface_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
107 device_t(mconfig, SS50_INTERFACE, tag, owner, clock),
108 device_single_card_slot_interface<ss50_card_interface>(mconfig, *this),
109 m_irq_cb(*this),
110 m_firq_cb(*this),
111 m_card(nullptr)
112 {
113 }
114
115 //-------------------------------------------------
116 // device_resolve_objects - resolve objects that
117 // may be needed for other devices to set
118 // initial conditions at start time
119 //-------------------------------------------------
120
device_resolve_objects()121 void ss50_interface_port_device::device_resolve_objects()
122 {
123 m_irq_cb.resolve_safe();
124 m_firq_cb.resolve_safe();
125
126 m_card = get_card_device();
127 if (m_card != nullptr)
128 m_card->m_slot = this;
129 }
130
131 //-------------------------------------------------
132 // device_start - device-specific startup
133 //-------------------------------------------------
134
device_start()135 void ss50_interface_port_device::device_start()
136 {
137 }
138
139 //-------------------------------------------------
140 // read - interface read access (pre-decoded)
141 //-------------------------------------------------
142
read(offs_t offset)143 u8 ss50_interface_port_device::read(offs_t offset)
144 {
145 if (m_card == nullptr)
146 {
147 if (!machine().side_effects_disabled())
148 logerror("%s: Read from unspecified interface (RS = %X)\n", machine().describe_context(), offset);
149 return 0xff;
150 }
151
152 return m_card->register_read(offset);
153 }
154
155 //-------------------------------------------------
156 // write - interface write access (pre-decoded)
157 //-------------------------------------------------
158
write(offs_t offset,u8 data)159 void ss50_interface_port_device::write(offs_t offset, u8 data)
160 {
161 if (m_card == nullptr)
162 {
163 logerror("%s: Write to unspecified interface (RS = %X, D = %02X)\n", machine().describe_context(), offset, data);
164 return;
165 }
166
167 m_card->register_write(offset, data);
168 }
169
170 //-------------------------------------------------
171 // fN_w - baud rate clocks for serial interfaces
172 //-------------------------------------------------
173
WRITE_LINE_MEMBER(ss50_interface_port_device::f110_w)174 WRITE_LINE_MEMBER(ss50_interface_port_device::f110_w)
175 {
176 if (m_card != nullptr)
177 m_card->f110_w(state);
178 }
179
WRITE_LINE_MEMBER(ss50_interface_port_device::f150_9600_w)180 WRITE_LINE_MEMBER(ss50_interface_port_device::f150_9600_w)
181 {
182 if (m_card != nullptr)
183 m_card->f150_9600_w(state);
184 }
185
WRITE_LINE_MEMBER(ss50_interface_port_device::f300_w)186 WRITE_LINE_MEMBER(ss50_interface_port_device::f300_w)
187 {
188 if (m_card != nullptr)
189 m_card->f300_w(state);
190 }
191
WRITE_LINE_MEMBER(ss50_interface_port_device::f600_4800_w)192 WRITE_LINE_MEMBER(ss50_interface_port_device::f600_4800_w)
193 {
194 if (m_card != nullptr)
195 m_card->f600_4800_w(state);
196 }
197
WRITE_LINE_MEMBER(ss50_interface_port_device::f600_1200_w)198 WRITE_LINE_MEMBER(ss50_interface_port_device::f600_1200_w)
199 {
200 if (m_card != nullptr)
201 m_card->f600_1200_w(state);
202 }
203
204 //**************************************************************************
205 // SS-50 CARD INTERFACE
206 //**************************************************************************
207
208 template class device_finder<ss50_card_interface, false>;
209 template class device_finder<ss50_card_interface, true>;
210
211 //-------------------------------------------------
212 // ss50_card_interface - construction
213 //-------------------------------------------------
214
ss50_card_interface(const machine_config & mconfig,device_t & device)215 ss50_card_interface::ss50_card_interface(const machine_config &mconfig, device_t &device) :
216 device_interface(device, "ss50card"),
217 m_slot(nullptr)
218 {
219 }
220
interface_pre_start()221 void ss50_card_interface::interface_pre_start()
222 {
223 if (!m_slot)
224 throw device_missing_dependencies();
225 }
226
ss50_default_2rs_devices(device_slot_interface & device)227 void ss50_default_2rs_devices(device_slot_interface &device)
228 {
229 device.option_add("dc5", SS50_DC5);
230 device.option_add("mpc", SS50_MPC);
231 //device.option_add("mpl", SS50_MPL);
232 //device.option_add("mpn", SS50_MPN);
233 device.option_add("mps", SS50_MPS);
234 device.option_add("mps2", SS50_MPS2);
235 device.option_add("mpt", SS50_MPT);
236 device.option_add("piaide", SS50_PIAIDE);
237 }
238