1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     Commodore IEC Serial Bus emulation
6 
7 **********************************************************************/
8 
9 #ifndef MAME_BUS_CBMIEC_CBMIEC_H
10 #define MAME_BUS_CBMIEC_CBMIEC_H
11 
12 #pragma once
13 
14 
15 
16 
17 //**************************************************************************
18 //  MACROS / CONSTANTS
19 //**************************************************************************
20 
21 #define CBM_IEC_TAG         "iec_bus"
22 
23 
24 DECLARE_DEVICE_TYPE(CBM_IEC,      cbm_iec_device)
25 DECLARE_DEVICE_TYPE(CBM_IEC_SLOT, cbm_iec_slot_device)
26 
27 void cbm_iec_devices(device_slot_interface &device);
28 
29 //**************************************************************************
30 //  TYPE DEFINITIONS
31 //**************************************************************************
32 
33 // ======================> cbm_iec_device
34 
35 class cbm_iec_slot_device;
36 class device_cbm_iec_interface;
37 
38 class cbm_iec_device : public device_t
39 {
40 public:
41 	// construction/destruction
42 	cbm_iec_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
43 
srq_callback()44 	auto srq_callback() { return m_write_srq.bind(); }
atn_callback()45 	auto atn_callback() { return m_write_atn.bind(); }
clk_callback()46 	auto clk_callback() { return m_write_clk.bind(); }
data_callback()47 	auto data_callback() { return m_write_data.bind(); }
reset_callback()48 	auto reset_callback() { return m_write_reset.bind(); }
49 
50 	void add_device(cbm_iec_slot_device *slot, device_t *target);
51 
52 	// reads for both host and peripherals
DECLARE_READ_LINE_MEMBER(srq_r)53 	DECLARE_READ_LINE_MEMBER( srq_r ) { return get_signal(SRQ); }
DECLARE_READ_LINE_MEMBER(atn_r)54 	DECLARE_READ_LINE_MEMBER( atn_r ) { return get_signal(ATN); }
DECLARE_READ_LINE_MEMBER(clk_r)55 	DECLARE_READ_LINE_MEMBER( clk_r ) { return get_signal(CLK); }
DECLARE_READ_LINE_MEMBER(data_r)56 	DECLARE_READ_LINE_MEMBER( data_r ) { return get_signal(DATA); }
DECLARE_READ_LINE_MEMBER(reset_r)57 	DECLARE_READ_LINE_MEMBER( reset_r ) { return get_signal(RESET); }
58 
59 	// writes for host (driver_device)
DECLARE_WRITE_LINE_MEMBER(host_srq_w)60 	DECLARE_WRITE_LINE_MEMBER( host_srq_w ) { set_signal(this, SRQ, state); }
DECLARE_WRITE_LINE_MEMBER(host_atn_w)61 	DECLARE_WRITE_LINE_MEMBER( host_atn_w ) { set_signal(this, ATN, state); }
DECLARE_WRITE_LINE_MEMBER(host_clk_w)62 	DECLARE_WRITE_LINE_MEMBER( host_clk_w ) { set_signal(this, CLK, state); }
DECLARE_WRITE_LINE_MEMBER(host_data_w)63 	DECLARE_WRITE_LINE_MEMBER( host_data_w ) { set_signal(this, DATA, state); }
DECLARE_WRITE_LINE_MEMBER(host_reset_w)64 	DECLARE_WRITE_LINE_MEMBER( host_reset_w ) { set_signal(this, RESET, state); }
65 
66 	// writes for peripherals (device_t)
srq_w(device_t * device,int state)67 	void srq_w(device_t *device, int state) { set_signal(device, SRQ, state); }
atn_w(device_t * device,int state)68 	void atn_w(device_t *device, int state) { set_signal(device, ATN, state); }
clk_w(device_t * device,int state)69 	void clk_w(device_t *device, int state) { set_signal(device, CLK, state); }
data_w(device_t * device,int state)70 	void data_w(device_t *device, int state) { set_signal(device, DATA, state); }
reset_w(device_t * device,int state)71 	void reset_w(device_t *device, int state) { set_signal(device, RESET, state); }
72 
73 protected:
74 	enum
75 	{
76 		SRQ = 0,
77 		ATN,
78 		CLK,
79 		DATA,
80 		RESET,
81 		SIGNAL_COUNT
82 	};
83 
84 	// device-level overrides
85 	virtual void device_start() override;
86 	virtual void device_reset() override;
87 	virtual void device_stop() override;
88 
89 	class daisy_entry
90 	{
91 	public:
92 		daisy_entry(device_t *device);
next()93 		daisy_entry *next() const { return m_next; }
94 
95 		daisy_entry *               m_next;         // next device
96 		device_t *                  m_device;       // associated device
97 		device_cbm_iec_interface *  m_interface;    // associated device's daisy interface
98 
99 		int m_line[SIGNAL_COUNT];
100 	};
101 
102 	simple_list<daisy_entry> m_device_list;
103 
104 private:
105 	devcb_write_line   m_write_srq;
106 	devcb_write_line   m_write_atn;
107 	devcb_write_line   m_write_clk;
108 	devcb_write_line   m_write_data;
109 	devcb_write_line   m_write_reset;
110 
111 	void set_signal(device_t *device, int signal, int state);
112 	int get_signal(int signal);
113 
114 	int m_line[SIGNAL_COUNT];
115 };
116 
117 
118 // ======================> cbm_iec_slot_device
119 
120 class cbm_iec_slot_device : public device_t,
121 							public device_slot_interface
122 {
123 public:
124 	// construction/destruction
125 	template <typename T>
cbm_iec_slot_device(machine_config const & mconfig,char const * tag,device_t * owner,int address,T && opts,char const * dflt)126 	cbm_iec_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, int address, T &&opts, char const *dflt)
127 		: cbm_iec_slot_device(mconfig, tag, owner, (uint32_t)0)
128 	{
129 		option_reset();
130 		opts(*this);
131 		set_default_option(dflt);
132 		set_fixed(false);
133 		set_address(address);
134 	}
135 	cbm_iec_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
136 
add(machine_config & config,T && _bus_tag,const char * _default_drive)137 	template <typename T> static void add(machine_config &config, T &&_bus_tag, const char *_default_drive)
138 	{
139 		CBM_IEC_SLOT(config, "iec4", 4, cbm_iec_devices, nullptr);
140 		CBM_IEC_SLOT(config, "iec8", 8, cbm_iec_devices, _default_drive);
141 		CBM_IEC_SLOT(config, "iec9", 9, cbm_iec_devices, nullptr);
142 		CBM_IEC_SLOT(config, "iec10", 10, cbm_iec_devices, nullptr);
143 		CBM_IEC_SLOT(config, "iec11", 11, cbm_iec_devices, nullptr);
144 
145 		CBM_IEC(config, std::forward<T>(_bus_tag), 0);
146 	}
147 
set_address(int address)148 	void set_address(int address) { m_address = address; }
get_address()149 	int get_address() { return m_address; }
150 
151 	// device-level overrides
152 	virtual void device_start() override;
153 
154 protected:
155 	int m_address;
156 };
157 
158 
159 // ======================> device_cbm_iec_interface
160 
161 class device_cbm_iec_interface : public device_interface
162 {
163 	friend class cbm_iec_device;
164 
165 public:
166 	// construction/destruction
167 	virtual ~device_cbm_iec_interface();
168 
next()169 	device_cbm_iec_interface *next() const { return m_next; }
170 	device_cbm_iec_interface *m_next;
171 
172 	// optional operation overrides
cbm_iec_srq(int state)173 	virtual void cbm_iec_srq(int state) { }
cbm_iec_atn(int state)174 	virtual void cbm_iec_atn(int state) { }
cbm_iec_clk(int state)175 	virtual void cbm_iec_clk(int state) { }
cbm_iec_data(int state)176 	virtual void cbm_iec_data(int state) { }
cbm_iec_reset(int state)177 	virtual void cbm_iec_reset(int state) { }
178 
179 protected:
180 	device_cbm_iec_interface(const machine_config &mconfig, device_t &device);
181 
182 	cbm_iec_device *m_bus;
183 	cbm_iec_slot_device *m_slot;
184 };
185 
186 #endif // MAME_BUS_CBMIEC_CBMIEC_H
187