1 // license:BSD-3-Clause
2 // copyright-holders:
3 /***************************************************************************
4
5 2013-09-10 Skeleton driver for Televideo TS816
6
7 TODO:
8 - Connect up the devices to each other
9 - Connect up RS232 terminal instead of parallel one
10 - Connect centronics printer to PIO
11 - 4 diagnostic LEDs
12 - Hard Drive
13 - Tape Drive
14 - Get a good dump of the rom. If the undocumented DSW is enabled, it
15 calls up code in the missing half of the rom. Also it isn't possible
16 at the moment to get any useful response to commands.
17
18 ****************************************************************************/
19
20 #include "emu.h"
21 #include "cpu/z80/z80.h"
22 #include "machine/terminal.h"
23 #include "machine/z80daisy.h"
24 #include "machine/z80ctc.h"
25 #include "machine/z80pio.h"
26 #include "machine/z80sio.h"
27 #include "machine/z80dma.h"
28
29 class ts816_state : public driver_device
30 {
31 public:
ts816_state(const machine_config & mconfig,device_type type,const char * tag)32 ts816_state(const machine_config &mconfig, device_type type, const char *tag)
33 : driver_device(mconfig, type, tag)
34 , m_maincpu(*this, "maincpu")
35 , m_terminal(*this, "terminal")
36 { }
37
38 void ts816(machine_config &config);
39
40 void init_ts816();
41
42 private:
43 void kbd_put(u8 data);
44 uint8_t keyin_r();
45 uint8_t status_r();
46 void port68_w(uint8_t data);
47 void port78_w(uint8_t data);
48 void porte0_w(uint8_t data);
49 void portf0_w(uint8_t data);
50
51 void ts816_io(address_map &map);
52 void ts816_mem(address_map &map);
53
54 uint8_t m_term_data;
55 uint8_t m_status;
56 bool m_2ndbank;
57 bool m_endram;
58 void set_banks();
59 virtual void machine_reset() override;
60 required_device<z80_device> m_maincpu;
61 required_device<generic_terminal_device> m_terminal;
62 };
63
ts816_mem(address_map & map)64 void ts816_state::ts816_mem(address_map &map)
65 {
66 map.unmap_value_high();
67 map(0x0000, 0x3fff).bankr("bankr0").bankw("bankw0");
68 map(0x4000, 0xdfff).bankrw("bank1");
69 map(0xe000, 0xffff).bankrw("bank2");
70 }
71
ts816_io(address_map & map)72 void ts816_state::ts816_io(address_map &map)
73 {
74 map.global_mask(0xff);
75 map(0x00, 0x00); // Tape status byte 1
76 map(0x01, 0x01); // Tape status byte 2 and diagnostics mode
77 map(0x02, 0x02); // Hard Disk status
78 map(0x03, 0x03); // Hard Disk output latch
79 map(0x04, 0x04); // Tape output latch byte 2
80 map(0x05, 0x05); // Tape output latch byte 1
81 map(0x07, 0x07); // Indicator load (LED)
82 map(0x10, 0x13).rw("sio1", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 1 for user 1 & 2
83 map(0x18, 0x1b).rw("sio5", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 5 for user 9 & 10
84 map(0x20, 0x23).rw("sio2", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 2 for user 3 & 4
85 map(0x28, 0x2b).rw("sio6", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 6 for user 11 & 12
86 map(0x30, 0x33).rw("sio3", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 3 for user 5 & 6
87 map(0x38, 0x3b).rw("sio7", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 7 for user 13 & 14
88 map(0x40, 0x43).rw("sio4", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 4 for user 7 & 8
89 map(0x48, 0x4b).rw("sio8", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 8 for user 15 & 16
90 //map(0x50, 0x53) // SIO 0 for RS232 1 and part of tape interface
91 map(0x50, 0x50).r(FUNC(ts816_state::keyin_r)).w(m_terminal, FUNC(generic_terminal_device::write));
92 map(0x52, 0x52).r(FUNC(ts816_state::status_r));
93 map(0x58, 0x5b).rw("sio9", FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w)); // SIO 9 for RS232 2 & 3
94 map(0x60, 0x60).portr("DSW");
95 map(0x68, 0x68).w(FUNC(ts816_state::port68_w)); // set 2nd bank latch
96 map(0x70, 0x78).w(FUNC(ts816_state::port78_w)); // reset 2nd bank latch (manual can't decide between 70 and 78, so we take both)
97 map(0x80, 0x83).rw("ctc1", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); // CTC 1 (ch 0 baud A)
98 map(0x90, 0x93).rw("dma", FUNC(z80dma_device::read), FUNC(z80dma_device::write)); // DMA
99 map(0xA0, 0xA0); // WDC status / command
100 map(0xA1, 0xA1); // WDC data
101 map(0xB0, 0xB0).noprw(); // undocumented, written to at @0707 and @0710
102 map(0xC0, 0xC3).rw("ctc2", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); // CTC 2 (ch 0 baud B, ch 1 baud C)
103 map(0xD0, 0xD3).rw("pio", FUNC(z80pio_device::read), FUNC(z80pio_device::write));
104 map(0xE0, 0xE0).w(FUNC(ts816_state::porte0_w)); // set ENDRAM memory banking
105 map(0xF0, 0xF0).w(FUNC(ts816_state::portf0_w)); // reset ENDRAM memory banking
106 }
107
108
109 /* Input ports */
110 static INPUT_PORTS_START( ts816 )
111 PORT_START("DSW") //
112 PORT_DIPNAME( 0x07, 0x01, "System Terminal") // read at @0368
113 PORT_DIPSETTING( 0x00, "19200 baud")
114 PORT_DIPSETTING( 0x01, "9600 baud")
115 PORT_DIPSETTING( 0x02, "4800 baud")
116 PORT_DIPSETTING( 0x03, "2400 baud")
117 PORT_DIPSETTING( 0x04, "1200 baud")
118 PORT_DIPSETTING( 0x05, "600 baud")
119 PORT_DIPSETTING( 0x06, "300 baud")
120 PORT_DIPSETTING( 0x07, "150 baud")
121 PORT_DIPNAME( 0x80, 0x00, "Operation Switch") // this switch checked @006F (undocumented)
DEF_STR(On)122 PORT_DIPSETTING( 0x80, DEF_STR(On))
123 PORT_DIPSETTING( 0x00, DEF_STR(Off))
124 INPUT_PORTS_END
125
126
127 uint8_t ts816_state::keyin_r()
128 {
129 uint8_t ret = m_term_data;
130 m_term_data = 0;
131 return ret;
132 }
133
status_r()134 uint8_t ts816_state::status_r()
135 {
136 if (m_status)
137 {
138 m_status--;
139 return 5;
140 }
141 else
142 return 4;
143 }
144
port68_w(uint8_t data)145 void ts816_state::port68_w(uint8_t data)
146 {
147 m_2ndbank = 1;
148 set_banks();
149 }
150
port78_w(uint8_t data)151 void ts816_state::port78_w(uint8_t data)
152 {
153 m_2ndbank = 0;
154 set_banks();
155 }
156
porte0_w(uint8_t data)157 void ts816_state::porte0_w(uint8_t data)
158 {
159 m_endram = 1;
160 set_banks();
161 }
162
portf0_w(uint8_t data)163 void ts816_state::portf0_w(uint8_t data)
164 {
165 m_endram = 0;
166 set_banks();
167 }
168
set_banks()169 void ts816_state::set_banks()
170 {
171 if (!m_2ndbank)
172 {
173 if (!m_endram)
174 {
175 // bootup setting
176 membank("bankr0")->set_entry(2); // point at rom
177 membank("bankw0")->set_entry(0);
178 membank("bank1")->set_entry(0);
179 membank("bank2")->set_entry(0);
180 }
181 else
182 {
183 // 64k ram (lower half)
184 membank("bankr0")->set_entry(0);
185 membank("bankw0")->set_entry(0);
186 membank("bank1")->set_entry(0);
187 membank("bank2")->set_entry(0);
188 }
189 }
190 else
191 {
192 if (!m_endram)
193 {
194 // not documented, so assuming roms with ram (upper half)
195 membank("bankr0")->set_entry(2);
196 membank("bankw0")->set_entry(1);
197 membank("bank1")->set_entry(1);
198 membank("bank2")->set_entry(1);
199 }
200 else
201 {
202 // split of upper and lower ram (not documented if ram has a new address, assuming not)
203 membank("bankr0")->set_entry(1);
204 membank("bankw0")->set_entry(1);
205 membank("bank1")->set_entry(1);
206 membank("bank2")->set_entry(0);
207 }
208 }
209 }
210
kbd_put(u8 data)211 void ts816_state::kbd_put(u8 data)
212 {
213 m_term_data = data;
214 m_status = 3;
215 }
216
machine_reset()217 void ts816_state::machine_reset()
218 {
219 m_2ndbank = 0;
220 m_endram = 0;
221 m_term_data = 0;
222 m_status = 1;
223 set_banks();
224 m_maincpu->reset();
225 }
226
227 // correct order yet to be determined
228 static const z80_daisy_config daisy_chain[] =
229 {
230 { "dma" },
231 { "pio" },
232 { "ctc1" },
233 { "ctc2" },
234 // { "sio0" },
235 { "sio1" },
236 { "sio2" },
237 { "sio3" },
238 { "sio4" },
239 { "sio5" },
240 { "sio6" },
241 { "sio7" },
242 { "sio8" },
243 { "sio9" },
244 { nullptr }
245 };
246
init_ts816()247 void ts816_state::init_ts816()
248 {
249 uint8_t *roms = memregion("roms")->base();
250 uint8_t *rams = memregion("rams")->base();
251
252 // 0000-3FFF
253 membank("bankr0")->configure_entry(2, &roms[0x00000]); // roms
254 membank("bankr0")->configure_entry(0, &rams[0x00000]);
255 membank("bankr0")->configure_entry(1, &rams[0x10000]);
256 membank("bankw0")->configure_entry(0, &rams[0x00000]);
257 membank("bankw0")->configure_entry(1, &rams[0x10000]);
258 // 4000-DFFF
259 membank("bank1")->configure_entry(0, &rams[0x04000]);
260 membank("bank1")->configure_entry(1, &rams[0x14000]);
261 // E000-FFFF
262 membank("bank2")->configure_entry(0, &rams[0x0e000]);
263 membank("bank2")->configure_entry(1, &rams[0x1e000]);
264 }
265
ts816(machine_config & config)266 void ts816_state::ts816(machine_config &config)
267 {
268 /* basic machine hardware */
269 Z80(config, m_maincpu, XTAL(16'000'000) / 4);
270 m_maincpu->set_addrmap(AS_PROGRAM, &ts816_state::ts816_mem);
271 m_maincpu->set_addrmap(AS_IO, &ts816_state::ts816_io);
272 m_maincpu->set_daisy_config(daisy_chain);
273
274 /* video hardware */
275 GENERIC_TERMINAL(config, m_terminal, 0);
276 m_terminal->set_keyboard_callback(FUNC(ts816_state::kbd_put));
277
278 //z80sio_device& sio0(Z80SIO(config, "sio0", XTAL(16'000'000) / 4));
279 //sio0.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
280 z80sio_device& sio1(Z80SIO(config, "sio1", XTAL(16'000'000) / 4));
281 sio1.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
282 z80sio_device& sio2(Z80SIO(config, "sio2", XTAL(16'000'000) / 4));
283 sio2.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
284 z80sio_device& sio3(Z80SIO(config, "sio3", XTAL(16'000'000) / 4));
285 sio3.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
286 z80sio_device& sio4(Z80SIO(config, "sio4", XTAL(16'000'000) / 4));
287 sio4.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
288 z80sio_device& sio5(Z80SIO(config, "sio5", XTAL(16'000'000) / 4));
289 sio5.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
290 z80sio_device& sio6(Z80SIO(config, "sio6", XTAL(16'000'000) / 4));
291 sio6.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
292 z80sio_device& sio7(Z80SIO(config, "sio7", XTAL(16'000'000) / 4));
293 sio7.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
294 z80sio_device& sio8(Z80SIO(config, "sio8", XTAL(16'000'000) / 4));
295 sio8.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
296 z80sio_device& sio9(Z80SIO(config, "sio9", XTAL(16'000'000) / 4));
297 sio9.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
298
299 z80pio_device& pio(Z80PIO(config, "pio", XTAL(16'000'000) / 4));
300 pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
301 //pio.in_pa_callback().set(FUNC(ts816_state::porta_r));
302 //pio.in_pb_callback().set(FUNC(ts816_state::portb_r));
303 //pio.out_pb_callback().set(FUNC(ts816_state::portb_w));
304
305 z80ctc_device& ctc1(Z80CTC(config, "ctc1", XTAL(16'000'000) / 4));
306 ctc1.intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
307
308 z80ctc_device& ctc2(Z80CTC(config, "ctc2", XTAL(16'000'000) / 4));
309 ctc2.intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
310
311 z80dma_device& dma(Z80DMA(config, "dma", XTAL(16'000'000) / 4));
312 //dma.out_busreq_callback().set(FUNC(ts816_state::busreq_w));
313 dma.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
314 }
315
316 /* ROM definition */
317 ROM_START( ts816 )
318 ROM_REGION(0x4000, "roms", 0)
319 ROM_LOAD( "81640v11.rom", 0x0000, 0x1000, BAD_DUMP CRC(295a15e7) SHA1(6f49078ab3cd49aecd2afafcbed3af0e3bcfd48c) ) // both halves identical
320
321 ROM_REGION(0x20000, "rams", ROMREGION_ERASEFF)
322 ROM_END
323
324 /* Driver */
325
326 // YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
327 COMP( 1980, ts816, 0, 0, ts816, ts816, ts816_state, init_ts816, "Televideo", "TS816", MACHINE_IS_SKELETON )
328