summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ss50/interface.cpp
blob: b10b64a0277c55a33654d289adfb398f41e972ea (plain) (blame)
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
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************

    SWTPC SS-50 I/O port interface

    The SS-50 bus is actually two buses in one: a 50-pin master bus
    used by RAM boards and such, and a 30-pin I/O bus derived from it
    either on the motherboard or a dedicated interface board, which
    provides each of eight "interface" cards with its specific chip
    select line and only a few address lines for register selection.
    This 30-pin bus is what is emulated here.

    As originally introduced in the 6800 Computer System, the
    interface bus only included two register select lines, just enough
    to drive one MC6820 PIA. No defined signals were placed on the
    first two lines, which cards were permitted to use for any
    purpose. The original MP-B motherboard also quite wastefully
    reserved 8K (technically 4K) of address space to map a maximum of
    32 read/write registers. The later MC6809-oriented systems not
    only reduced the I/O segment to a selectable 1K, but appropriated
    the two formerly undefined lines for two additional register
    select lines, making it possible to use more complex interface
    cards but breaking compatibility with some earlier ones.

    An unusual feature of the SS-50 bus is the presence of five baud
    rate frequencies, selected from among the (inverted) outputs of
    a MC14411 Bit Rate Generator. The 6800 Computer System provided
    only rates between 110 and 1200 (multiplied by 16), and also used
    the MC14411's master frequency to generate the CPU clocks. The
    MP-09 CPU board retained the MC14411 at first, but provided an
    independent XTAL for the MC6809 and jumpers to select higher
    baud rates. Later the MC14411 was removed from the CPU board so
    the five baud rate lines on the 50-pin bus could be reused to
    provide 20-bit addressing and DMA. This was accomplished by
    adding a separate MP-ID Interface Driver Board to decode I/O
    accesses (and optionally slow them down to allow old 1 MHz
    peripherals to be used with a faster CPU), generate the baud
    rates (whose selection was changed yet again) from a dedicated
    MC14411, and provide a few I/O functions of its own.

***********************************************************************

                        +-+
                     30 |o| RS2 (originally UD3)
                     29 |o| RS3 (originally UD4)
                     28 |o| -16V (originally -12V)
                     27 |o| +16V (originally +12V)
                     26 |o| GND
                     25 |o| GND
                     24 |o| INDEX
                     23 |o| /FIRQ (6800: /NMI)
                     22 |o| /IRQ
                     21 |o| RS0
                     20 |o| RS1
                     19 |o| D0
                     18 |o| D1
                     17 |o| D2
                     16 |o| D3
                     15 |o| D4
                     14 |o| D5
                     13 |o| D6
                     12 |o| D7
                     11 |o| E (6800: ϕ2)
                     10 |o| R/W
                      9 |o| +8V (unregulated)
                      8 |o| +8V (unregulated)
                      7 |o| 600b/1200b (originally 1200b)
                      6 |o| 4800b (originally 600b)
                      5 |o| 300b
                      4 |o| 150b/9600b (originally 150b)
                      3 |o| 110b
                      2 |o| /RESET
                      1 |o| I/O #
                        +-+

**********************************************************************/

#include "emu.h"
#include "bus/ss50/interface.h"

#include "bus/ss50/dc5.h"
#include "bus/ss50/mpc.h"
//#include "bus/ss50/mpl.h"
//#include "bus/ss50/mpr.h"
#include "bus/ss50/mps.h"
#include "bus/ss50/mps2.h"
#include "bus/ss50/mpt.h"
#include "bus/ss50/piaide.h"

//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

// device type definition
DEFINE_DEVICE_TYPE(SS50_INTERFACE, ss50_interface_port_device, "ss50_interface", "SS-50 Interface Port")

//**************************************************************************
//  SS-50 INTERFACE PORT DEVICE
//**************************************************************************

//-------------------------------------------------
//  ss50_interface_port_device - construction
//-------------------------------------------------

ss50_interface_port_device::ss50_interface_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
	: device_t(mconfig, SS50_INTERFACE, tag, owner, clock),
		device_slot_interface(mconfig, *this),
		m_irq_cb(*this),
		m_firq_cb(*this),
		m_card(nullptr)
{
}

//-------------------------------------------------
//  device_resolve_objects - resolve objects that
//  may be needed for other devices to set
//  initial conditions at start time
//-------------------------------------------------

void ss50_interface_port_device::device_resolve_objects()
{
	logerror("Resolving objects...\n");

	m_irq_cb.resolve_safe();
	m_firq_cb.resolve_safe();

	m_card = dynamic_cast<ss50_card_interface *>(get_card_device());
	if (m_card != nullptr)
		m_card->m_slot = this;
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void ss50_interface_port_device::device_start()
{
}

//-------------------------------------------------
//  read - interface read access (pre-decoded)
//-------------------------------------------------

u8 ss50_interface_port_device::read(offs_t offset)
{
	if (m_card == nullptr)
	{
		logerror("%s: Read from unspecified interface (RS = %X)\n", machine().describe_context(), offset);
		return 0xff;
	}

	return m_card->register_read(offset);
}

//-------------------------------------------------
//  write - interface write access (pre-decoded)
//-------------------------------------------------

void ss50_interface_port_device::write(offs_t offset, u8 data)
{
	if (m_card == nullptr)
	{
		logerror("%s: Write to unspecified interface (RS = %X, D = %02X)\n", machine().describe_context(), offset, data);
		return;
	}

	m_card->register_write(offset, data);
}

//-------------------------------------------------
//  fN_w - baud rate clocks for serial interfaces
//-------------------------------------------------

WRITE_LINE_MEMBER(ss50_interface_port_device::f110_w)
{
	if (m_card != nullptr)
		m_card->f110_w(state);
}

WRITE_LINE_MEMBER(ss50_interface_port_device::f150_9600_w)
{
	if (m_card != nullptr)
		m_card->f150_9600_w(state);
}

WRITE_LINE_MEMBER(ss50_interface_port_device::f300_w)
{
	if (m_card != nullptr)
		m_card->f300_w(state);
}

WRITE_LINE_MEMBER(ss50_interface_port_device::f600_4800_w)
{
	if (m_card != nullptr)
		m_card->f600_4800_w(state);
}

WRITE_LINE_MEMBER(ss50_interface_port_device::f600_1200_w)
{
	if (m_card != nullptr)
		m_card->f600_1200_w(state);
}

//**************************************************************************
//  SS-50 CARD INTERFACE
//**************************************************************************

template class device_finder<ss50_card_interface, false>;
template class device_finder<ss50_card_interface, true>;

//-------------------------------------------------
//  ss50_card_interface - construction
//-------------------------------------------------

ss50_card_interface::ss50_card_interface(const machine_config &mconfig, device_t &device)
	: device_slot_card_interface(mconfig, device),
		m_slot(nullptr)
{
}

void ss50_default_2rs_devices(device_slot_interface &device)
{
	device.option_add("dc5", SS50_DC5);
	device.option_add("mpc", SS50_MPC);
	//device.option_add("mpl", SS50_MPL);
	//device.option_add("mpn", SS50_MPN);
	device.option_add("mps", SS50_MPS);
	device.option_add("mps2", SS50_MPS2);
	device.option_add("mpt", SS50_MPT);
	device.option_add("piaide", SS50_PIAIDE);
}