1 // license:LGPL-2.1+
2 // copyright-holders:Michael Zapf
3 /****************************************************************************
4 
5     Peripheral expansion box
6     See peribox.cpp for documentation
7 
8     Michael Zapf
9 
10     February 2012: Rewritten as class
11 
12 *****************************************************************************/
13 
14 #ifndef MAME_BUS_TI99_PEB_PERIBOX_H
15 #define MAME_BUS_TI99_PEB_PERIBOX_H
16 
17 #pragma once
18 
19 #include "bus/ti99/internal/ioport.h"
20 
21 #define TI_PERIBOX_TAG     "peb"
22 #define TI99_DSRROM        "dsrrom"
23 
24 namespace bus { namespace ti99 { namespace peb {
25 
26 class peribox_slot_device;
27 class device_ti99_peribox_card_interface;
28 
29 /*****************************************************************************
30     The overall Peripheral Expansion Box.
31 ******************************************************************************/
32 
33 class peribox_device : public bus::ti99::internal::ioport_attached_device
34 {
35 	friend class peribox_slot_device;
36 public:
37 	peribox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
38 
39 	// Next eight methods are called from the console
40 	void readz(offs_t offset, uint8_t *value) override;
41 	void write(offs_t offset, uint8_t data) override;
42 	void setaddress_dbin(offs_t offset, int state) override;
43 
44 	void crureadz(offs_t offset, uint8_t *value) override;
45 	void cruwrite(offs_t offset, uint8_t data) override;
46 
47 	DECLARE_WRITE_LINE_MEMBER(senila);
48 	DECLARE_WRITE_LINE_MEMBER(senilb);
49 
50 	DECLARE_WRITE_LINE_MEMBER( memen_in ) override;
51 	DECLARE_WRITE_LINE_MEMBER( msast_in ) override;
52 
53 	DECLARE_WRITE_LINE_MEMBER( clock_in ) override;
54 	DECLARE_WRITE_LINE_MEMBER( reset_in ) override;
55 
56 	// Part of configuration
set_prefix(int prefix)57 	void set_prefix(int prefix) { m_address_prefix = prefix; }
58 
59 	// Callbacks
inta_cb()60 	auto inta_cb() { return m_slot1_inta.bind(); }
intb_cb()61 	auto intb_cb() { return m_slot1_intb.bind(); }
ready_cb()62 	auto ready_cb() { return m_slot1_ready.bind(); }
lcp_cb()63 	auto lcp_cb() { return m_slot1_lcp.bind(); }
64 
65 protected:
66 	peribox_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
67 
68 	virtual void device_start() override;
69 	virtual void device_config_complete() override;
70 
71 	virtual void device_add_mconfig(machine_config &config) override;
72 
73 	// Next three methods call back the console via slot 1
74 	devcb_write_line m_slot1_inta;   // INTA line (Box to console)
75 	devcb_write_line m_slot1_intb;   // INTB line
76 	devcb_write_line m_slot1_lcp;       // For EVPC with SGCPU only
77 	devcb_write_line m_slot1_ready;  // READY line (to the datamux)
78 
79 	void set_slot_loaded(int slot, peribox_slot_device* slotdev);
80 	peribox_slot_device *m_slot[9];     // for the sake of simplicity we donate the first two positions (0,1)
81 
82 	required_device<peribox_slot_device> m_slot2;
83 	required_device<peribox_slot_device> m_slot3;
84 	required_device<peribox_slot_device> m_slot4;
85 	required_device<peribox_slot_device> m_slot5;
86 	required_device<peribox_slot_device> m_slot6;
87 	required_device<peribox_slot_device> m_slot7;
88 	required_device<peribox_slot_device> m_slot8;
89 
90 	// Propagators for the slot signals. All signals are active low, and
91 	// if any one slot asserts the line, the joint line is asserted.
92 	void inta_join(int slot, int state);
93 	void intb_join(int slot, int state);
94 	void lcp_join(int slot, int state);
95 	void ready_join(int slot, int state);
96 
97 	int m_inta_flag;
98 	int m_intb_flag;
99 	int m_lcp_flag;
100 	int m_ready_flag;
101 
102 	// The TI-99/4(A) Flex Cable Interface (slot 1) pulls up the AMA/AMB/AMC lines to 1/1/1.
103 	int m_address_prefix;
104 
105 	// Most significant address byte strobe. Defined by TI-99/8.
106 	bool    m_msast;
107 
108 	// Memory enable.
109 	bool    m_memen;
110 
111 	// Configured as a slot device (of the ioport)
112 	bool    m_ioport_connected;
113 };
114 
115 /************************************************************************
116     Specific Box compositions
117 ************************************************************************/
118 
119 /*
120     Variation for SGCPU (TI-99/4P). We put the EVPC and the HSGPL in slots 2 and 3.
121 */
122 class peribox_sg_device : public peribox_device
123 {
124 public:
125 	peribox_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
126 
127 protected:
128 	void device_add_mconfig(machine_config &config) override;
129 };
130 
131 /*
132     Variation for ti99_4ev. We put the EVPC in slot 2.
133 */
134 class peribox_ev_device : public peribox_device
135 {
136 public:
137 	peribox_ev_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
138 
139 protected:
140 	void device_add_mconfig(machine_config &config) override;
141 };
142 
143 
144 /*
145     Variation for Geneve.
146 */
147 class peribox_gen_device : public peribox_device
148 {
149 public:
150 	peribox_gen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
151 
152 protected:
153 	peribox_gen_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
154 	virtual void device_add_mconfig(machine_config &config) override;
155 };
156 
157 /*
158     Variation for Geneve with Genmod
159 */
160 class peribox_genmod_device : public peribox_gen_device
161 {
162 public:
163 	peribox_genmod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
164 
165 protected:
166 	void device_add_mconfig(machine_config &config) override;
167 };
168 
169 /*****************************************************************************
170     The parent class for all expansion cards.
171 ******************************************************************************/
172 
173 class device_ti99_peribox_card_interface : public device_interface
174 {
175 	friend class peribox_slot_device;
176 
177 public:
178 	virtual void readz(offs_t offset, uint8_t *value) = 0;
179 	virtual void write(offs_t offset, uint8_t data) = 0;
180 	virtual void crureadz(offs_t offset, uint8_t *value) = 0;
181 	virtual void cruwrite(offs_t offset, uint8_t data) = 0;
setaddress_dbin(offs_t offset,int state)182 	virtual void setaddress_dbin(offs_t offset, int state) { };
183 
DECLARE_WRITE_LINE_MEMBER(clock_in)184 	virtual DECLARE_WRITE_LINE_MEMBER(clock_in) { }
DECLARE_WRITE_LINE_MEMBER(reset_in)185 	virtual DECLARE_WRITE_LINE_MEMBER(reset_in) { }
186 
set_senila(int state)187 	void    set_senila(int state) { m_senila = state; }
set_senilb(int state)188 	void    set_senilb(int state) { m_senilb = state; }
189 
190 protected:
191 	device_ti99_peribox_card_interface(const machine_config &mconfig, device_t &device);
192 	virtual void interface_config_complete() override;
193 
194 	peribox_slot_device *m_slot;        // using a link to the slot for callbacks
195 	int m_senila;
196 	int m_senilb;
197 
198 	// When true, card is accessible. Indicated by a LED.
199 	bool    m_selected;
200 
201 	// CRU base. Used to configure the address by which a card is selected.
202 	int     m_cru_base;
203 
204 	// Methods to decide whether we are acccessing the 4000-5fff region (DSR)
205 	// or the cartridge region
206 	static bool in_dsr_space(offs_t offset, bool amadec);
207 	static bool in_cart_space(offs_t offset, bool amadec);
208 };
209 
210 /*****************************************************************************
211     A single slot in the box.
212 ******************************************************************************/
213 
214 class peribox_slot_device : public device_t, public device_single_card_slot_interface<device_ti99_peribox_card_interface>
215 {
216 	friend class peribox_device;
217 public:
218 	template <typename U>
peribox_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,int slot,U && opts,const char * dflt)219 	peribox_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, int slot, U &&opts, const char *dflt)
220 		: peribox_slot_device(mconfig, tag, owner, 0)
221 	{
222 		option_reset();
223 		opts(*this);
224 		set_default_option(dflt);
225 		set_fixed(false);
226 		m_slotnumber = slot;
227 	}
228 
229 	peribox_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
230 
231 	// Called from the box (direction to card)
232 	void readz(offs_t offset, uint8_t *value);
233 	void write(offs_t offset, uint8_t data);
234 	void setaddress_dbin(offs_t offset, int state);
235 
236 	DECLARE_WRITE_LINE_MEMBER(senila);
237 	DECLARE_WRITE_LINE_MEMBER(senilb);
238 	DECLARE_WRITE_LINE_MEMBER(clock_in);
239 	DECLARE_WRITE_LINE_MEMBER(reset_in);
240 
241 	// Called from the card (direction to box)
242 	DECLARE_WRITE_LINE_MEMBER( set_inta );
243 	DECLARE_WRITE_LINE_MEMBER( set_intb );
244 	DECLARE_WRITE_LINE_MEMBER( lcp_line );
245 	DECLARE_WRITE_LINE_MEMBER( set_ready );
246 
247 	void crureadz(offs_t offset, uint8_t *value);
248 	void cruwrite(offs_t offset, uint8_t data);
249 
250 	// called from the box itself
set_number(int number)251 	void set_number(int number) { m_slotnumber = number; }
252 
253 protected:
254 	void device_start() override;
255 	void device_config_complete() override;
256 
257 private:
258 	int get_index_from_tagname();
259 	device_ti99_peribox_card_interface *m_card;
260 	int m_slotnumber;
card_name()261 	const char* card_name() { return m_card->device().tag(); }
262 };
263 
264 } } } // end namespace bus::ti99::peb
265 
266 DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX,      bus::ti99::peb, peribox_device)
267 DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_EV,   bus::ti99::peb, peribox_ev_device)
268 DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SLOT, bus::ti99::peb, peribox_slot_device)
269 DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SG,   bus::ti99::peb, peribox_sg_device)
270 DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GEN,  bus::ti99::peb, peribox_gen_device)
271 DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GENMOD,  bus::ti99::peb, peribox_genmod_device)
272 
273 void ti99_peribox_slot_standard(device_slot_interface &device);
274 void ti99_peribox_slot_evpc(device_slot_interface &device);
275 void ti99_peribox_slot_geneve(device_slot_interface &device);
276 void ti99_peribox_slot_sgcpu(device_slot_interface &device);
277 
278 #endif // MAME_BUS_TI99_PEB_PERIBOX_H
279