1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     Acorn Computers Econet local area network emulation
6 
7 **********************************************************************/
8 
9 #include "emu.h"
10 #include "econet.h"
11 
12 
13 
14 //**************************************************************************
15 //  MACROS / CONSTANTS
16 //**************************************************************************
17 
18 #define LOG 0
19 
20 
21 static const char *const SIGNAL_NAME[] = { "CLK", "DATA" };
22 
23 
24 
25 //**************************************************************************
26 //  DEVICE DEFINITIONS
27 //**************************************************************************
28 
29 DEFINE_DEVICE_TYPE(ECONET,      econet_device,      "econet",      "Econet")
30 DEFINE_DEVICE_TYPE(ECONET_SLOT, econet_slot_device, "econet_slot", "Econet station")
31 
32 
33 
34 //**************************************************************************
35 //  DEVICE INTERFACE
36 //**************************************************************************
37 
38 //-------------------------------------------------
39 //  device_econet_interface - constructor
40 //-------------------------------------------------
41 
device_econet_interface(const machine_config & mconfig,device_t & device)42 device_econet_interface::device_econet_interface(const machine_config &mconfig, device_t &device) :
43 	device_interface(device, "econet"), m_econet(nullptr), m_address(0), m_next(nullptr)
44 {
45 }
46 
47 
48 
49 //**************************************************************************
50 //  LIVE DEVICE
51 //**************************************************************************
52 
53 //-------------------------------------------------
54 //  econet_slot_device - constructor
55 //-------------------------------------------------
56 
econet_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)57 econet_slot_device::econet_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
58 	device_t(mconfig, ECONET_SLOT, tag, owner, clock),
59 	device_slot_interface(mconfig, *this),
60 	m_address(0), m_econet(*this, finder_base::DUMMY_TAG)
61 {
62 }
63 
64 
65 //-------------------------------------------------
66 //  device_start - device-specific startup
67 //-------------------------------------------------
68 
device_start()69 void econet_slot_device::device_start()
70 {
71 	device_econet_interface *dev = dynamic_cast<device_econet_interface *>(get_card_device());
72 	if (dev) m_econet->add_device(get_card_device(), m_address);
73 }
74 
75 
76 
77 //**************************************************************************
78 //  INLINE HELPERS
79 //**************************************************************************
80 
81 //-------------------------------------------------
82 //  set_signal -
83 //-------------------------------------------------
84 
set_signal(device_t * device,int signal,int state)85 inline void econet_device::set_signal(device_t *device, int signal, int state)
86 {
87 	bool changed = false;
88 
89 	if (device == this)
90 	{
91 		if (m_line[signal] != state)
92 		{
93 			if (LOG) logerror("Econet: '%s' %s %u\n", tag(), SIGNAL_NAME[signal], state);
94 			m_line[signal] = state;
95 			changed = true;
96 		}
97 	}
98 	else
99 	{
100 		daisy_entry *entry = m_device_list.first();
101 
102 		while (entry)
103 		{
104 			if (!strcmp(entry->m_device->tag(), device->tag()))
105 			{
106 				if (entry->m_line[signal] != state)
107 				{
108 					if (LOG) logerror("Econet: '%s' %s %u\n", device->tag(), SIGNAL_NAME[signal], state);
109 					entry->m_line[signal] = state;
110 					changed = true;
111 				}
112 			}
113 
114 			entry = entry->next();
115 		}
116 	}
117 
118 	if (changed)
119 	{
120 		switch (signal)
121 		{
122 		case CLK:   m_write_clk(state);  break;
123 		case DATA:  m_write_data(state); break;
124 		}
125 
126 		daisy_entry *entry = m_device_list.first();
127 
128 		while (entry)
129 		{
130 			switch (signal)
131 			{
132 			case CLK:
133 				entry->m_interface->econet_clk(state);
134 				break;
135 
136 			case DATA:
137 				entry->m_interface->econet_data(state);
138 				break;
139 			}
140 
141 			entry = entry->next();
142 		}
143 
144 		if (LOG) logerror("Econet: CLK %u DATA %u\n", get_signal(CLK), get_signal(DATA));
145 	}
146 }
147 
148 
149 //-------------------------------------------------
150 //  get_signal -
151 //-------------------------------------------------
152 
get_signal(int signal)153 inline int econet_device::get_signal(int signal)
154 {
155 	int state = m_line[signal];
156 
157 	if (state)
158 	{
159 		daisy_entry *entry = m_device_list.first();
160 
161 		while (entry)
162 		{
163 			if (!entry->m_line[signal])
164 			{
165 				state = 0;
166 				break;
167 			}
168 
169 			entry = entry->next();
170 		}
171 	}
172 
173 	return state;
174 }
175 
176 
177 
178 //**************************************************************************
179 //  LIVE DEVICE
180 //**************************************************************************
181 
182 //-------------------------------------------------
183 //  econet_device - constructor
184 //-------------------------------------------------
185 
econet_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)186 econet_device::econet_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
187 	device_t(mconfig, ECONET, tag, owner, clock),
188 	m_write_clk(*this),
189 	m_write_data(*this)
190 {
191 	for (auto & elem : m_line)
192 	{
193 		elem = 1;
194 	}
195 }
196 
197 
198 //-------------------------------------------------
199 //  device_start - device-specific startup
200 //-------------------------------------------------
201 
device_start()202 void econet_device::device_start()
203 {
204 	// resolve callbacks
205 	m_write_clk.resolve_safe();
206 	m_write_data.resolve_safe();
207 }
208 
209 
210 //-------------------------------------------------
211 //  device_stop - device-specific stop
212 //-------------------------------------------------
213 
device_stop()214 void econet_device::device_stop()
215 {
216 	m_device_list.reset();
217 }
218 
219 
220 //-------------------------------------------------
221 //  add_device -
222 //-------------------------------------------------
223 
add_device(device_t * target,int address)224 void econet_device::add_device(device_t *target, int address)
225 {
226 	auto entry = new daisy_entry(target);
227 
228 	entry->m_interface->m_econet = this;
229 	entry->m_interface->m_address = address;
230 
231 	m_device_list.append(*entry);
232 }
233 
234 
235 //-------------------------------------------------
236 //  daisy_entry - constructor
237 //-------------------------------------------------
238 
daisy_entry(device_t * device)239 econet_device::daisy_entry::daisy_entry(device_t *device) :
240 	m_next(nullptr),
241 	m_device(device),
242 	m_interface(nullptr)
243 {
244 	for (auto & elem : m_line)
245 	{
246 		elem = 1;
247 	}
248 
249 	device->interface(m_interface);
250 }
251 
252 
253 //-------------------------------------------------
254 //  clk_w -
255 //-------------------------------------------------
256 
WRITE_LINE_MEMBER(econet_device::host_clk_w)257 WRITE_LINE_MEMBER( econet_device::host_clk_w )
258 {
259 	set_signal(this, CLK, state);
260 }
261 
262 
263 //-------------------------------------------------
264 //  data_w -
265 //-------------------------------------------------
266 
WRITE_LINE_MEMBER(econet_device::host_data_w)267 WRITE_LINE_MEMBER( econet_device::host_data_w )
268 {
269 	set_signal(this, DATA, state);
270 }
271 
272 
273 //-------------------------------------------------
274 //  clk_w -
275 //-------------------------------------------------
276 
clk_w(device_t * device,int state)277 void econet_device::clk_w(device_t *device, int state)
278 {
279 	set_signal(device, CLK, state);
280 }
281 
282 
283 //-------------------------------------------------
284 //  data_w -
285 //-------------------------------------------------
286 
data_w(device_t * device,int state)287 void econet_device::data_w(device_t *device, int state)
288 {
289 	set_signal(device, DATA, state);
290 }
291 
292 
293 //-------------------------------------------------
294 //  SLOT_INTERFACE( econet_devices )
295 //-------------------------------------------------
296 
297 // slot devices
298 #include "e01.h"
299 
econet_devices(device_slot_interface & device)300 void econet_devices(device_slot_interface &device)
301 {
302 	device.option_add("e01",  ECONET_E01);
303 	device.option_add("e01s", ECONET_E01S);
304 }
305