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