1 // license:BSD-3-Clause
2 // copyright-holders:AJR
3 /****************************************************************************
4 
5     Skeleton driver for Micro-Term ERGO 201 terminal.
6 
7     The ERGO 201 belongs to one half of a paired series of terminals. Half
8     of these terminals emulate the VT100 and support a 132 column mode; the
9     other half emulate the VT52, ADM3A and ACT-5A instead but do appear to
10     have been influenced by the VT100 in overall design.
11 
12     The first members of this series, the MIME 340 (non-VT100 emulation)
13     and MIME 740 (VT100 emulation), were single units with non-detachable
14     keyboards like Micro-Term's older ACT and MIME terminals. They were
15     respectively succeeded by the ERGO 2000 and ERGO 3001 with tiltable
16     screens and similar but detached keyboards. The ERGO 201 and ERGO 301
17     appear to be low-cost redesigns of these two with keyboards even more
18     closely resembling the VT100's, with a Plot 10 graphics board as an
19     option. Also introduced around this time was the ERGO 4000, a
20     portrait-mode terminal displaying 66 lines of 80 characters.
21 
22 ****************************************************************************/
23 
24 #include "emu.h"
25 //#include "bus/rs232/rs232.h"
26 #include "cpu/z80/z80.h"
27 #include "machine/ay31015.h"
28 #include "machine/clock.h"
29 #include "machine/er1400.h"
30 //#include "machine/ergo201_kbd.h"
31 #include "machine/z80ctc.h"
32 #include "machine/z80sio.h"
33 #include "video/tms9927.h"
34 #include "screen.h"
35 
36 class ergo201_state : public driver_device
37 {
38 public:
ergo201_state(const machine_config & mconfig,device_type type,const char * tag)39 	ergo201_state(const machine_config &mconfig, device_type type, const char *tag)
40 		: driver_device(mconfig, type, tag)
41 		, m_maincpu(*this, "maincpu")
42 		, m_earom(*this, "earom")
43 		, m_kbuart(*this, "kbuart")
44 		, m_vtac(*this, "vtac")
45 		, m_chargen(*this, "chargen")
46 	{
47 	}
48 
49 	void ergo201(machine_config &config);
50 
51 protected:
52 	virtual void machine_start() override;
53 
54 private:
55 	u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
56 
57 	void earom_latch_w(u8 data);
58 	u8 status_r();
59 
60 	void mem_map(address_map &map);
61 	void io_map(address_map &map);
62 
63 	required_device<z80_device> m_maincpu;
64 	required_device<er1400_device> m_earom;
65 	required_device<ay31015_device> m_kbuart;
66 	required_device<tms9927_device> m_vtac;
67 	required_region_ptr<u8> m_chargen;
68 };
69 
machine_start()70 void ergo201_state::machine_start()
71 {
72 	m_kbuart->write_tsb(0);
73 	m_kbuart->write_nb1(1);
74 	m_kbuart->write_nb2(1);
75 	m_kbuart->write_np(1);
76 	m_kbuart->write_cs(1);
77 	m_kbuart->write_swe(0);
78 }
79 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)80 u32 ergo201_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
81 {
82 	return 0;
83 }
84 
85 
earom_latch_w(u8 data)86 void ergo201_state::earom_latch_w(u8 data)
87 {
88 	m_earom->c1_w(BIT(data, 0));
89 	m_earom->data_w(BIT(data, 1));
90 	m_earom->c3_w(BIT(data, 2));
91 	m_earom->c2_w(BIT(data, 3));
92 	m_earom->clock_w(BIT(data, 4));
93 }
94 
status_r()95 u8 ergo201_state::status_r()
96 {
97 	return (m_kbuart->dav_r() << 1) | (m_earom->data_r() << 5);
98 }
99 
mem_map(address_map & map)100 void ergo201_state::mem_map(address_map &map)
101 {
102 	map(0x0000, 0x5fff).rom().region("program", 0);
103 	map(0x1000, 0x1000).nopw();
104 	map(0x2000, 0x2000).unmapw(); // screen brightness?
105 	map(0x3000, 0x300f).w(m_vtac, FUNC(tms9927_device::write));
106 	map(0x4000, 0x4000).w(FUNC(ergo201_state::earom_latch_w));
107 	map(0x5000, 0x5000).w(m_kbuart, FUNC(ay31015_device::transmit));
108 	map(0x6000, 0x6000).r(m_kbuart, FUNC(ay31015_device::receive));
109 	map(0x6001, 0x6001).r(FUNC(ergo201_state::status_r));
110 	map(0x7000, 0x77ff).ram();
111 	map(0x8000, 0x87ff).ram();
112 	map(0xc000, 0xc7ff).ram();
113 }
114 
io_map(address_map & map)115 void ergo201_state::io_map(address_map &map)
116 {
117 	map.global_mask(0xff);
118 	map(0xf4, 0xf7).rw("dart", FUNC(z80dart_device::cd_ba_r), FUNC(z80dart_device::cd_ba_w));
119 	map(0xf8, 0xfb).rw("ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
120 }
121 
122 
123 static INPUT_PORTS_START(ergo201)
124 INPUT_PORTS_END
125 
126 static const z80_daisy_config daisy_chain[] =
127 {
128 	{ "ctc" },
129 	{ "dart" },
130 	{ nullptr }
131 };
132 
ergo201(machine_config & config)133 void ergo201_state::ergo201(machine_config &config)
134 {
135 	Z80(config, m_maincpu, 16.313_MHz_XTAL / 4); // SGS Z8400AB1 (divider guessed)
136 	m_maincpu->set_addrmap(AS_PROGRAM, &ergo201_state::mem_map);
137 	m_maincpu->set_addrmap(AS_IO, &ergo201_state::io_map);
138 	m_maincpu->set_daisy_config(daisy_chain);
139 
140 	z80ctc_device &ctc(Z80CTC(config, "ctc", 16.313_MHz_XTAL / 4)); // SGS Z8430AB1
141 	ctc.set_clk<0>(16.313_MHz_XTAL / 53);
142 	ctc.set_clk<1>(16.313_MHz_XTAL / 53);
143 	ctc.set_clk<2>(16.313_MHz_XTAL / 53);
144 	ctc.zc_callback<0>().set("dart", FUNC(z80dart_device::rxca_w));
145 	ctc.zc_callback<1>().set("dart", FUNC(z80dart_device::txca_w));
146 	ctc.zc_callback<2>().set("dart", FUNC(z80dart_device::rxtxcb_w));
147 	ctc.intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
148 
149 	z80dart_device &dart(Z80DART(config, "dart", 16.313_MHz_XTAL / 4)); // Zilog Z8470A PS
150 	dart.out_txda_callback().set("dart", FUNC(z80dart_device::rxa_w));
151 	dart.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
152 
153 	AY31015(config, m_kbuart); // GI AY-3-1015D
154 	m_kbuart->set_auto_rdav(true);
155 
156 	clock_device &kbclock(CLOCK(config, "kbclock", 10000));
157 	kbclock.signal_handler().set(m_kbuart, FUNC(ay31015_device::write_rcp));
158 	kbclock.signal_handler().append(m_kbuart, FUNC(ay31015_device::write_tcp));
159 
160 	ER1400(config, m_earom); // GI ER-1400
161 
162 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
163 	screen.set_raw(16.313_MHz_XTAL, 855, 0, 720, 318, 0, 300);
164 	screen.set_screen_update(FUNC(ergo201_state::screen_update));
165 	screen.set_color(rgb_t::green()); // P31
166 
167 	CRT5037(config, m_vtac, 16.313_MHz_XTAL / 9); // TI TMS9937NL
168 	m_vtac->set_char_width(9);
169 	m_vtac->set_screen("screen");
170 }
171 
172 
173 ROM_START(ergo201)
174 	ROM_REGION(0x6000, "program", 0) // Checksum is off by a few bits, so at least one dump is bad
175 	ROM_LOAD("201.u18", 0x0000, 0x2000, CRC(fec9fa3c) SHA1(3c1f9de9f62e74fbd1c9b67736d0959c0f6b46b1) BAD_DUMP) // M5L2764K
176 	ROM_LOAD("r1.0_special_5786.u73", 0x2000, 0x2000, CRC(5a31b6bc) SHA1(6929fa8f6d481790cd43732a9a97a9110ad9fb6c)) // MBM2764-25
177 	ROM_LOAD("201.u17", 0x4000, 0x2000, CRC(e7197403) SHA1(96fff6fb30eeac616d71da731b0ea79c8cd35096)) // M5L2764K
178 
179 	ROM_REGION(0x1000, "chargen", 0)
180 	ROM_LOAD("201.u53", 0x0000, 0x1000, CRC(907dac04) SHA1(5bae6680f1ef3f5335a223bdf403e8f3ef272430)) // MBM2732A-35
181 ROM_END
182 
183 COMP(1985, ergo201, 0, 0, ergo201, ergo201, ergo201_state, empty_init, "Micro-Term / Kurzweil Computer Products", "ERGO 201 (Special #9233)", MACHINE_IS_SKELETON)
184