// license:BSD-3-Clause
// copyright-holders:AJR
/****************************************************************************

    Skeleton driver for Micro-Term ERGO 201 terminal.

    The ERGO 201 belongs to one half of a paired series of terminals. Half
    of these terminals emulate the VT100 and support a 132 column mode; the
    other half emulate the VT52, ADM3A and ACT-5A instead but do appear to
    have been influenced by the VT100 in overall design.

    The first members of this series, the MIME 340 (non-VT100 emulation)
    and MIME 740 (VT100 emulation), were single units with non-detachable
    keyboards like Micro-Term's older ACT and MIME terminals. They were
    respectively succeeded by the ERGO 2000 and ERGO 3001 with tiltable
    screens and similar but detached keyboards. The ERGO 201 and ERGO 301
    appear to be low-cost redesigns of these two with keyboards even more
    closely resembling the VT100's, with a Plot 10 graphics board as an
    option. Also introduced around this time was the ERGO 4000, a
    portrait-mode terminal displaying 66 lines of 80 characters.

****************************************************************************/

#include "emu.h"
//#include "bus/rs232/rs232.h"
#include "cpu/z80/z80.h"
#include "machine/ay31015.h"
#include "machine/clock.h"
#include "machine/er1400.h"
//#include "machine/ergo201_kbd.h"
#include "machine/z80ctc.h"
#include "machine/z80sio.h"
#include "video/tms9927.h"
#include "screen.h"

class ergo201_state : public driver_device
{
public:
	ergo201_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag)
		, m_maincpu(*this, "maincpu")
		, m_earom(*this, "earom")
		, m_kbuart(*this, "kbuart")
		, m_vtac(*this, "vtac")
		, m_chargen(*this, "chargen")
	{
	}

	void ergo201(machine_config &config);

protected:
	virtual void machine_start() override;

private:
	u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);

	void earom_latch_w(u8 data);
	u8 status_r();

	void mem_map(address_map &map);
	void io_map(address_map &map);

	required_device<z80_device> m_maincpu;
	required_device<er1400_device> m_earom;
	required_device<ay31015_device> m_kbuart;
	required_device<tms9927_device> m_vtac;
	required_region_ptr<u8> m_chargen;
};

void ergo201_state::machine_start()
{
	m_kbuart->write_tsb(0);
	m_kbuart->write_nb1(1);
	m_kbuart->write_nb2(1);
	m_kbuart->write_np(1);
	m_kbuart->write_cs(1);
	m_kbuart->write_swe(0);
}

u32 ergo201_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
	return 0;
}


void ergo201_state::earom_latch_w(u8 data)
{
	m_earom->c1_w(BIT(data, 0));
	m_earom->data_w(BIT(data, 1));
	m_earom->c3_w(BIT(data, 2));
	m_earom->c2_w(BIT(data, 3));
	m_earom->clock_w(BIT(data, 4));
}

u8 ergo201_state::status_r()
{
	return (m_kbuart->dav_r() << 1) | (m_earom->data_r() << 5);
}

void ergo201_state::mem_map(address_map &map)
{
	map(0x0000, 0x5fff).rom().region("program", 0);
	map(0x1000, 0x1000).nopw();
	map(0x2000, 0x2000).unmapw(); // screen brightness?
	map(0x3000, 0x300f).w(m_vtac, FUNC(tms9927_device::write));
	map(0x4000, 0x4000).w(FUNC(ergo201_state::earom_latch_w));
	map(0x5000, 0x5000).w(m_kbuart, FUNC(ay31015_device::transmit));
	map(0x6000, 0x6000).r(m_kbuart, FUNC(ay31015_device::receive));
	map(0x6001, 0x6001).r(FUNC(ergo201_state::status_r));
	map(0x7000, 0x77ff).ram();
	map(0x8000, 0x87ff).ram();
	map(0xc000, 0xc7ff).ram();
}

void ergo201_state::io_map(address_map &map)
{
	map.global_mask(0xff);
	map(0xf4, 0xf7).rw("dart", FUNC(z80dart_device::cd_ba_r), FUNC(z80dart_device::cd_ba_w));
	map(0xf8, 0xfb).rw("ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}


static INPUT_PORTS_START(ergo201)
INPUT_PORTS_END

static const z80_daisy_config daisy_chain[] =
{
	{ "ctc" },
	{ "dart" },
	{ nullptr }
};

void ergo201_state::ergo201(machine_config &config)
{
	Z80(config, m_maincpu, 16.313_MHz_XTAL / 4); // SGS Z8400AB1 (divider guessed)
	m_maincpu->set_addrmap(AS_PROGRAM, &ergo201_state::mem_map);
	m_maincpu->set_addrmap(AS_IO, &ergo201_state::io_map);
	m_maincpu->set_daisy_config(daisy_chain);

	z80ctc_device &ctc(Z80CTC(config, "ctc", 16.313_MHz_XTAL / 4)); // SGS Z8430AB1
	ctc.set_clk<0>(16.313_MHz_XTAL / 53);
	ctc.set_clk<1>(16.313_MHz_XTAL / 53);
	ctc.set_clk<2>(16.313_MHz_XTAL / 53);
	ctc.zc_callback<0>().set("dart", FUNC(z80dart_device::rxca_w));
	ctc.zc_callback<1>().set("dart", FUNC(z80dart_device::txca_w));
	ctc.zc_callback<2>().set("dart", FUNC(z80dart_device::rxtxcb_w));
	ctc.intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);

	z80dart_device &dart(Z80DART(config, "dart", 16.313_MHz_XTAL / 4)); // Zilog Z8470A PS
	dart.out_txda_callback().set("dart", FUNC(z80dart_device::rxa_w));
	dart.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);

	AY31015(config, m_kbuart); // GI AY-3-1015D
	m_kbuart->set_auto_rdav(true);

	clock_device &kbclock(CLOCK(config, "kbclock", 10000));
	kbclock.signal_handler().set(m_kbuart, FUNC(ay31015_device::write_rcp));
	kbclock.signal_handler().append(m_kbuart, FUNC(ay31015_device::write_tcp));

	ER1400(config, m_earom); // GI ER-1400

	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
	screen.set_raw(16.313_MHz_XTAL, 855, 0, 720, 318, 0, 300);
	screen.set_screen_update(FUNC(ergo201_state::screen_update));
	screen.set_color(rgb_t::green()); // P31

	CRT5037(config, m_vtac, 16.313_MHz_XTAL / 9); // TI TMS9937NL
	m_vtac->set_char_width(9);
	m_vtac->set_screen("screen");
}


ROM_START(ergo201)
	ROM_REGION(0x6000, "program", 0) // Checksum is off by a few bits, so at least one dump is bad
	ROM_LOAD("201.u18", 0x0000, 0x2000, CRC(fec9fa3c) SHA1(3c1f9de9f62e74fbd1c9b67736d0959c0f6b46b1) BAD_DUMP) // M5L2764K
	ROM_LOAD("r1.0_special_5786.u73", 0x2000, 0x2000, CRC(5a31b6bc) SHA1(6929fa8f6d481790cd43732a9a97a9110ad9fb6c)) // MBM2764-25
	ROM_LOAD("201.u17", 0x4000, 0x2000, CRC(e7197403) SHA1(96fff6fb30eeac616d71da731b0ea79c8cd35096)) // M5L2764K

	ROM_REGION(0x1000, "chargen", 0)
	ROM_LOAD("201.u53", 0x0000, 0x1000, CRC(907dac04) SHA1(5bae6680f1ef3f5335a223bdf403e8f3ef272430)) // MBM2732A-35
ROM_END

COMP(1985, ergo201, 0, 0, ergo201, ergo201, ergo201_state, empty_init, "Micro-Term / Kurzweil Computer Products", "ERGO 201 (Special #9233)", MACHINE_IS_SKELETON)
