1 // license:BSD-3-Clause
2 // copyright-holders:Nigel Barnes
3 /**********************************************************************
4 
5     Tangerine TANDOS (MT0078)
6 
7     http://www.microtan.ukpc.net/pageProducts.html#DOS
8 
9 **********************************************************************/
10 
11 
12 #include "emu.h"
13 #include "tandos.h"
14 
15 
16 //**************************************************************************
17 //  DEVICE DEFINITIONS
18 //**************************************************************************
19 
20 DEFINE_DEVICE_TYPE(TANBUS_TANDOS, tanbus_tandos_device, "tanbus_tandos", "Tangerine Tandos Board")
21 
22 //-------------------------------------------------
23 //  SLOT_INTERFACE( tandos_floppies )
24 //-------------------------------------------------
25 
tandos_floppies(device_slot_interface & device)26 static void tandos_floppies(device_slot_interface &device)
27 {
28 	device.option_add("525sssd", FLOPPY_525_SSSD);
29 	device.option_add("525sd", FLOPPY_525_SD);
30 	device.option_add("525qd", FLOPPY_525_QD);
31 }
32 
33 //-------------------------------------------------
34 //  ROM( tandos )
35 //-------------------------------------------------
36 
37 ROM_START(tandos)
38 	ROM_REGION(0x1000, "dos_rom", 0)
39 	ROM_DEFAULT_BIOS("step30")
40 	ROM_SYSTEM_BIOS(0, "step30", "30ms Stepping Rate")
41 	ROMX_LOAD("tandos_sr30.f2", 0x0000, 0x1000, CRC(54f55771) SHA1(5a801039fa8c05cd9227e9138469959524516c9e), ROM_BIOS(0))
42 	ROM_SYSTEM_BIOS(1, "step6", "6ms Stepping Rate")
43 	ROMX_LOAD("tandos_sr6.f2", 0x0000, 0x1000, CRC(10ef90fa) SHA1(b1e42cbf7197e693073d2578561803ea4c8efa8c), ROM_BIOS(1))
44 ROM_END
45 
46 //-------------------------------------------------
47 //  device_add_mconfig - add device configuration
48 //-------------------------------------------------
49 
device_add_mconfig(machine_config & config)50 void tanbus_tandos_device::device_add_mconfig(machine_config &config)
51 {
52 	FD1793(config, m_fdc, 8_MHz_XTAL / 8);
53 	m_fdc->intrq_wr_callback().set(FUNC(tanbus_tandos_device::fdc_irq_w));
54 	m_fdc->drq_wr_callback().set(FUNC(tanbus_tandos_device::fdc_drq_w));
55 	m_fdc->hld_wr_callback().set(FUNC(tanbus_tandos_device::fdc_hld_w));
56 	m_fdc->set_force_ready(true);
57 
58 	FLOPPY_CONNECTOR(config, m_floppies[0], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
59 	FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
60 	FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
61 	FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
62 }
63 
device_rom_region() const64 const tiny_rom_entry *tanbus_tandos_device::device_rom_region() const
65 {
66 	return ROM_NAME(tandos);
67 }
68 
69 //**************************************************************************
70 //  LIVE DEVICE
71 //**************************************************************************
72 
73 //-------------------------------------------------
74 //  tanbus_tandos_device - constructor
75 //-------------------------------------------------
76 
tanbus_tandos_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)77 tanbus_tandos_device::tanbus_tandos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
78 	: device_t(mconfig, TANBUS_TANDOS, tag, owner, clock)
79 	, device_tanbus_interface(mconfig, *this)
80 	, m_dos_rom(*this, "dos_rom")
81 	, m_fdc(*this, "fdc")
82 	, m_floppies(*this, "fdc:%u", 0)
83 	, m_floppy(nullptr)
84 	, m_drive_control(0)
85 {
86 }
87 
88 
89 //-------------------------------------------------
90 //  device_start - device-specific startup
91 //-------------------------------------------------
92 
device_start()93 void tanbus_tandos_device::device_start()
94 {
95 	m_ram = std::make_unique<uint8_t[]>(0x0400);
96 
97 	save_pointer(NAME(m_ram), 0x0400);
98 }
99 
100 //-------------------------------------------------
101 //  device_reset - device-specific reset
102 //-------------------------------------------------
103 
device_reset()104 void tanbus_tandos_device::device_reset()
105 {
106 	// reset floppy control register
107 	control_w(0);
108 }
109 
110 //-------------------------------------------------
111 //  read - card read
112 //-------------------------------------------------
113 
read(offs_t offset,int inhrom,int inhram,int be)114 uint8_t tanbus_tandos_device::read(offs_t offset, int inhrom, int inhram, int be)
115 {
116 	uint8_t data = 0xff;
117 
118 	switch (offset & 0xfc00)
119 	{
120 	case 0xa800: case 0xac00: case 0xb000: case 0xb400:
121 		data = m_dos_rom->base()[offset & 0x0fff];
122 		break;
123 
124 	case 0xb800:
125 		data = m_ram[offset & 0x03ff];
126 		break;
127 
128 	default:
129 		switch (offset)
130 		{
131 		case 0xbf90: case 0xbf91: case 0xbf92: case 0xbf93:
132 			data = m_fdc->read(offset & 0x03);
133 			break;
134 		case 0xbf94: case 0xbf96:
135 			data = status_r();
136 			break;
137 		case 0xbf95: case 0xbf97:
138 			// GPIB PCB Switches
139 			break;
140 		case 0xbf98: case 0xbf99: case 0xbf9a: case 0xbf9b: case 0xbf9c: case 0xbf9d: case 0xbf9e: case 0xbf9f:
141 			// GPIB (9914)
142 			break;
143 		}
144 		break;
145 	}
146 
147 	return data;
148 }
149 
150 //-------------------------------------------------
151 //  write - card write
152 //-------------------------------------------------
153 
write(offs_t offset,uint8_t data,int inhrom,int inhram,int be)154 void tanbus_tandos_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
155 {
156 	switch (offset & 0xfc00)
157 	{
158 	case 0xb800:
159 		m_ram[offset & 0x03ff] = data;
160 		break;
161 
162 	default:
163 		switch (offset)
164 		{
165 		case 0xbf90: case 0xbf91: case 0xbf92: case 0xbf93:
166 			m_fdc->write(offset & 0x03, data);
167 			break;
168 		case 0xbf94: case 0xbf96:
169 			control_w(data);
170 			break;
171 		case 0xbf98: case 0xbf99: case 0xbf9a: case 0xbf9b: case 0xbf9c: case 0xbf9d: case 0xbf9e: case 0xbf9f:
172 			// GPIB (9914)
173 			break;
174 		}
175 		break;
176 	}
177 }
178 
179 //-------------------------------------------------
180 //  set_inhibit_lines
181 //-------------------------------------------------
182 
set_inhibit_lines(offs_t offset,int & inhram,int & inhrom)183 void tanbus_tandos_device::set_inhibit_lines(offs_t offset, int &inhram, int &inhrom)
184 {
185 	if (offset >= 0xa800 && offset < 0xbc00)
186 	{
187 		inhram = 1;
188 		inhrom = 1;
189 	}
190 };
191 
192 //**************************************************************************
193 //  IMPLEMENTATION
194 //**************************************************************************
195 
control_w(uint8_t data)196 void tanbus_tandos_device::control_w(uint8_t data)
197 {
198 	logerror("control_w %02x\n", data);
199 	m_drive_control = data;
200 
201 	// bit 0: irq enable
202 	m_irq_enable = BIT(data, 0);
203 
204 	// bit 1: data select (data stream controller)
205 
206 	// bit 2, 3: drive select
207 	m_floppy = m_floppies[(data >> 2) & 0x03]->get_device();
208 	m_fdc->set_floppy(m_floppy);
209 
210 	// bit 4: side select
211 	if (m_floppy)
212 		m_floppy->ss_w(BIT(data, 4));
213 
214 	// bit 5: density
215 	m_fdc->dden_w(BIT(data, 5));
216 
217 	// bit 6: head load timing
218 	m_fdc->hlt_w(BIT(data, 6));
219 	if (m_floppy)
220 		m_floppy->mon_w(!BIT(data, 6));
221 
222 	// bit 7: drq enable
223 	m_drq_enable = BIT(data, 7);
224 }
225 
status_r()226 uint8_t tanbus_tandos_device::status_r()
227 {
228 	uint8_t data = 0x00;
229 
230 	data |= m_drive_control & 0x3c;
231 	data |= m_fdc->intrq_r() << 0;
232 	data |= m_fdc->hld_r() << 6;
233 	data |= m_fdc->drq_r() << 7;
234 
235 	return data;
236 }
237 
238 
WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_drq_w)239 WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_drq_w)
240 {
241 	m_tanbus->so_w((m_drq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
242 }
243 
WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_irq_w)244 WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_irq_w)
245 {
246 	m_tanbus->irq_w((m_irq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
247 }
248 
WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_hld_w)249 WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_hld_w)
250 {
251 	logerror("fdc_hld_w %d\n", state);
252 	if (m_floppy)
253 		m_floppy->mon_w(state);
254 }
255