summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ti99/peb/peribox.h
blob: a936a5346ef1c779cb3bcd610bb50eb0feb7b983 (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
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
// license:LGPL-2.1+
// copyright-holders:Michael Zapf
/****************************************************************************

    Peripheral expansion box
    See peribox.c for documentation

    Michael Zapf

    February 2012: Rewritten as class

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

#ifndef MAME_BUS_TI99_PEB_PERIBOX_H
#define MAME_BUS_TI99_PEB_PERIBOX_H

#pragma once

#include "bus/ti99/ti99defs.h"
#include "bus/ti99/internal/ioport.h"

namespace bus { namespace ti99 { namespace peb {

class peribox_slot_device;
class device_ti99_peribox_card_interface;

/*****************************************************************************
    The overall Peripheral Expansion Box.
******************************************************************************/

class peribox_device : public bus::ti99::internal::ioport_attached_device
{
	friend class peribox_slot_device;
public:
	peribox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// Next eight methods are called from the console
	DECLARE_READ8Z_MEMBER(readz) override;
	DECLARE_WRITE8_MEMBER(write) override;
	DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;

	DECLARE_READ8Z_MEMBER(crureadz) override;
	DECLARE_WRITE8_MEMBER(cruwrite) override;

	DECLARE_WRITE_LINE_MEMBER(senila);
	DECLARE_WRITE_LINE_MEMBER(senilb);

	DECLARE_WRITE_LINE_MEMBER( memen_in ) override;
	DECLARE_WRITE_LINE_MEMBER( msast_in ) override;

	DECLARE_WRITE_LINE_MEMBER( clock_in ) override;

	// Part of configuration
	void set_prefix(int prefix) { m_address_prefix = prefix; }

	// Callbacks
	auto inta_cb() { return m_slot1_inta.bind(); }
	auto intb_cb() { return m_slot1_intb.bind(); }
	auto ready_cb() { return m_slot1_ready.bind(); }
	auto lcp_cb() { return m_slot1_lcp.bind(); }

protected:
	peribox_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	virtual void device_start() override;
	virtual void device_config_complete() override;

	virtual void device_add_mconfig(machine_config &config) override;

	// Next three methods call back the console via slot 1
	devcb_write_line m_slot1_inta;   // INTA line (Box to console)
	devcb_write_line m_slot1_intb;   // INTB line
	devcb_write_line m_slot1_lcp;       // For EVPC with SGCPU only
	devcb_write_line m_slot1_ready;  // READY line (to the datamux)

	void set_slot_loaded(int slot, peribox_slot_device* slotdev);
	peribox_slot_device *m_slot[9];     // for the sake of simplicity we donate the first two positions (0,1)

	required_device<peribox_slot_device> m_slot2;
	required_device<peribox_slot_device> m_slot3;
	required_device<peribox_slot_device> m_slot4;
	required_device<peribox_slot_device> m_slot5;
	required_device<peribox_slot_device> m_slot6;
	required_device<peribox_slot_device> m_slot7;
	required_device<peribox_slot_device> m_slot8;

	// Propagators for the slot signals. All signals are active low, and
	// if any one slot asserts the line, the joint line is asserted.
	void inta_join(int slot, int state);
	void intb_join(int slot, int state);
	void lcp_join(int slot, int state);
	void ready_join(int slot, int state);

	int m_inta_flag;
	int m_intb_flag;
	int m_lcp_flag;
	int m_ready_flag;

	// The TI-99/4(A) Flex Cable Interface (slot 1) pulls up the AMA/AMB/AMC lines to 1/1/1.
	int m_address_prefix;

	// Most significant address byte strobe. Defined by TI-99/8.
	bool    m_msast;

	// Memory enable.
	bool    m_memen;

	// Configured as a slot device (of the ioport)
	bool    m_ioport_connected;

	// Used for Genmod
	bool    m_genmod;
};

/************************************************************************
    Specific Box compositions
************************************************************************/

/*
    Variation for SGCPU (TI-99/4P). We put the EVPC and the HSGPL in slots 2 and 3.
*/
class peribox_sg_device : public peribox_device
{
public:
	peribox_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	void device_add_mconfig(machine_config &config) override;
};

/*
    Variation for ti99_4ev. We put the EVPC in slot 2.
*/
class peribox_ev_device : public peribox_device
{
public:
	peribox_ev_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	void device_add_mconfig(machine_config &config) override;
};


/*
    Variation for Geneve.
*/
class peribox_gen_device : public peribox_device
{
public:
	peribox_gen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	peribox_gen_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
	virtual void device_add_mconfig(machine_config &config) override;
};

/*
    Variation for Geneve with Genmod
*/
class peribox_genmod_device : public peribox_gen_device
{
public:
	peribox_genmod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	void device_add_mconfig(machine_config &config) override;
};

/*****************************************************************************
    The parent class for all expansion cards.
******************************************************************************/

class device_ti99_peribox_card_interface : public device_slot_card_interface
{
	friend class peribox_slot_device;

public:
	virtual DECLARE_READ8Z_MEMBER(readz) = 0;
	virtual DECLARE_WRITE8_MEMBER(write) = 0;
	virtual DECLARE_READ8Z_MEMBER(crureadz) = 0;
	virtual DECLARE_WRITE8_MEMBER(cruwrite) = 0;
	virtual DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) { };

	virtual DECLARE_WRITE_LINE_MEMBER(clock_in) { }
	void    set_senila(int state) { m_senila = state; }
	void    set_senilb(int state) { m_senilb = state; }

protected:
	using device_slot_card_interface::device_slot_card_interface;
	device_ti99_peribox_card_interface(const machine_config &mconfig, device_t &device);
	virtual void interface_config_complete() override;

	peribox_slot_device *m_slot;        // using a link to the slot for callbacks
	int m_senila;
	int m_senilb;

	// When true, card is accessible. Indicated by a LED.
	bool    m_selected;

	// When true, GenMod is selected. Modified by peribox_slot_device.
	bool    m_genmod;

	// CRU base. Used to configure the address by which a card is selected.
	int     m_cru_base;

	// Used to decide whether this card has been selected.
	int     m_select_mask;
	int     m_select_value;
};

/*****************************************************************************
    A single slot in the box.
******************************************************************************/

class peribox_slot_device : public device_t, public device_slot_interface
{
	friend class peribox_device;
public:
	template <typename U>
	peribox_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, int slot, U &&opts, const char *dflt)
		: peribox_slot_device(mconfig, tag, owner, 0)
	{
		option_reset();
		opts(*this);
		set_default_option(dflt);
		set_fixed(false);
		m_slotnumber = slot;
	}

	peribox_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// Called from the box (direction to card)
	DECLARE_READ8Z_MEMBER(readz);
	DECLARE_WRITE8_MEMBER(write);
	DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin);

	DECLARE_WRITE_LINE_MEMBER(senila);
	DECLARE_WRITE_LINE_MEMBER(senilb);
	DECLARE_WRITE_LINE_MEMBER(clock_in);

	// Called from the card (direction to box)
	DECLARE_WRITE_LINE_MEMBER( set_inta );
	DECLARE_WRITE_LINE_MEMBER( set_intb );
	DECLARE_WRITE_LINE_MEMBER( lcp_line );
	DECLARE_WRITE_LINE_MEMBER( set_ready );

	DECLARE_READ8Z_MEMBER(crureadz);
	DECLARE_WRITE8_MEMBER(cruwrite);

	// called from the box itself
	void set_genmod(bool set);
	void set_number(int number) { m_slotnumber = number; }

protected:
	void device_start() override;
	void device_config_complete() override;

private:
	int get_index_from_tagname();
	device_ti99_peribox_card_interface *m_card;
	int m_slotnumber;
	const char* card_name() { return m_card->device().tag(); }
};

} } } // end namespace bus::ti99::peb

DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX,      bus::ti99::peb, peribox_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_EV,   bus::ti99::peb, peribox_ev_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SLOT, bus::ti99::peb, peribox_slot_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SG,   bus::ti99::peb, peribox_sg_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GEN,  bus::ti99::peb, peribox_gen_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GENMOD,  bus::ti99::peb, peribox_genmod_device)

void ti99_peribox_slot_standard(device_slot_interface &device);
void ti99_peribox_slot_evpc(device_slot_interface &device);
void ti99_peribox_slot_geneve(device_slot_interface &device);
void ti99_peribox_slot_sgcpu(device_slot_interface &device);

#endif // MAME_BUS_TI99_PEB_PERIBOX_H