diff options
Diffstat (limited to 'src/devices/bus/rc2014/micro.cpp')
-rw-r--r-- | src/devices/bus/rc2014/micro.cpp | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/src/devices/bus/rc2014/micro.cpp b/src/devices/bus/rc2014/micro.cpp new file mode 100644 index 00000000000..10f3b5c3e8e --- /dev/null +++ b/src/devices/bus/rc2014/micro.cpp @@ -0,0 +1,299 @@ +// license:BSD-3-Clause +// copyright-holders:Miodrag Milanovic +/*************************************************************************** + + RC2014 Micro Module + +****************************************************************************/ + +#include "emu.h" +#include "micro.h" +#include "modules.h" + +#include "cpu/z80/z80.h" +#include "machine/6850acia.h" +#include "machine/clock.h" +#include "bus/ata/ataintf.h" +#include "bus/rs232/rs232.h" + +namespace { + +//************************************************************************** +// RC2014 Micro module +// Module author: Spencer Owen +//************************************************************************** + +class rc2014_micro : public device_t, public device_rc2014_card_interface +{ +public: + // construction/destruction + rc2014_micro(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +private: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_resolve_objects() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + virtual const tiny_rom_entry *device_rom_region() const override; + + DECLARE_WRITE_LINE_MEMBER( clk_w ) { m_bus->clk_w(state); } + DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); } + + void addrmap_mem(address_map &map) { map.unmap_value_high(); } + void addrmap_io(address_map &map) { map.unmap_value_high(); } + + required_device<z80_device> m_maincpu; + required_device<acia6850_device> m_acia; + required_memory_region m_rom; + required_ioport m_rom_selector; + required_ioport m_rom_present; + + std::unique_ptr<u8[]> m_ram; + + static constexpr XTAL MAIN_CLOCK = XTAL(7'372'800); +}; + +rc2014_micro::rc2014_micro(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, RC2014_MICRO, tag, owner, clock) + , device_rc2014_card_interface(mconfig, *this) + , m_maincpu(*this, "maincpu") + , m_acia(*this, "acia") + , m_rom(*this, "rom") + , m_rom_selector(*this, "JP2-JP4") + , m_rom_present(*this, "ROM") + , m_ram(nullptr) +{ +} + +void rc2014_micro::device_start() +{ + // Setup CPU + m_bus->set_bus_clock(MAIN_CLOCK); + m_maincpu->set_daisy_config(m_bus->get_daisy_chain()); + + // Setup RAM + m_ram = std::make_unique<u8[]>(0x8000); + std::fill_n(m_ram.get(), 0x8000, 0xff); + save_pointer(NAME(m_ram), 0x8000); + m_bus->installer(AS_PROGRAM)->install_ram(0x8000, 0xffff, m_ram.get()); +} + +void rc2014_micro::device_reset() +{ + // Setup ACIA + // A15-A8 and A5-A1 not connected + m_bus->installer(AS_IO)->install_readwrite_handler(0x80, 0x81, 0, 0xff3e, 0, read8sm_delegate(*m_acia, FUNC(acia6850_device::read)), write8sm_delegate(*m_acia, FUNC(acia6850_device::write))); + + // Setup ROM + if (m_rom_present->read()) + m_bus->installer(AS_PROGRAM)->install_rom(0x0000, 0x1fff, 0x0000, m_rom->base() + (m_rom_selector->read() & 7) * 0x2000); +} + +void rc2014_micro::device_resolve_objects() +{ + // Setup CPU + m_bus->assign_installer(AS_PROGRAM, &m_maincpu->space(AS_PROGRAM)); + m_bus->assign_installer(AS_IO, &m_maincpu->space(AS_IO)); + m_bus->int_callback().append_inputline(m_maincpu, INPUT_LINE_IRQ0); + + // Setup ACIA + m_bus->rx_callback().append(m_acia, FUNC(acia6850_device::write_rxd)); +} + +static DEVICE_INPUT_DEFAULTS_START( terminal ) + DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_115200 ) + DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_115200 ) + DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 ) + DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE ) + DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 ) +DEVICE_INPUT_DEFAULTS_END + +void rc2014_micro::device_add_mconfig(machine_config &config) +{ + Z80(config, m_maincpu, MAIN_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &rc2014_micro::addrmap_mem); + m_maincpu->set_addrmap(AS_IO, &rc2014_micro::addrmap_io); + + clock_device &clock(CLOCK(config, "clock", MAIN_CLOCK)); + clock.signal_handler().append(FUNC(rc2014_micro::clk_w)); + clock.signal_handler().append(m_acia, FUNC(acia6850_device::write_txc)); + clock.signal_handler().append(m_acia, FUNC(acia6850_device::write_rxc)); + + ACIA6850(config, m_acia, 0); + m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd)); + m_acia->txd_handler().append(FUNC(rc2014_micro::tx_w)); + m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts)); + m_acia->irq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + + rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal")); + rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd)); + rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal)); +} + +static INPUT_PORTS_START( rc2014_micro_jumpers ) + // JP1 is used to enable power from USB-to-Serial cable + PORT_START("JP2-JP4") + PORT_CONFNAME( 0x7, 0x0, "ROM Bank (A13-A15)" ) + PORT_CONFSETTING( 0x0, "BASIC" ) + PORT_CONFSETTING( 0x1, "EMPTY1" ) + PORT_CONFSETTING( 0x2, "EMPTY2" ) + PORT_CONFSETTING( 0x3, "EMPTY3" ) + PORT_CONFSETTING( 0x4, "EMPTY4" ) + PORT_CONFSETTING( 0x5, "EMPTY5" ) + PORT_CONFSETTING( 0x6, "EMPTY6" ) + PORT_CONFSETTING( 0x7, "SCM" ) + PORT_START("ROM") + PORT_CONFNAME( 0x1, 0x1, "ROM Socket" ) + PORT_CONFSETTING( 0x0, "Empty" ) + PORT_CONFSETTING( 0x1, "Populated" ) +INPUT_PORTS_END + +ioport_constructor rc2014_micro::device_input_ports() const +{ + return INPUT_PORTS_NAME( rc2014_micro_jumpers ); +} + +ROM_START(rc2014_rom) + ROM_REGION( 0x10000, "rom",0 ) + ROM_LOAD( "r0000009.bin", 0x0000, 0x10000, CRC(3fb1ced7) SHA1(40a030b931ebe6cca654ce056c228297f245b057) ) +ROM_END + +const tiny_rom_entry *rc2014_micro::device_rom_region() const +{ + return ROM_NAME( rc2014_rom ); +} + +//************************************************************************** +// RC2014 Mini CP/M Upgrade module +// Module author: Spencer Owen +//************************************************************************** + +class rc2014_mini_cpm : public device_t, public device_rc2014_card_interface +{ +public: + // construction/destruction + rc2014_mini_cpm(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_post_load() override { update_banks(); } + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + virtual const tiny_rom_entry *device_rom_region() const override; + + DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); } + + uint8_t ide_cs0_r(offs_t offset) { return m_ata->cs0_r(offset); } + void ide_cs0_w(offs_t offset, uint8_t data) { m_ata->cs0_w(offset, data); } + void reset_bank_w(offs_t, uint8_t) { m_view_num = 0; update_banks(); } + void toggle_bank_w(offs_t, uint8_t) { m_view_num = m_view_num ? 0 : 1; update_banks(); } + +private: + void update_banks() { m_view.select(m_view_num); } + + // base-class members + uint8_t m_view_num; + std::unique_ptr<u8[]> m_ram; + + required_device<ata_interface_device> m_ata; + required_device<rc2014_bus_device> m_rc2014_bus; + required_memory_region m_rom; + required_ioport m_jp1; + memory_view m_view; + memory_bank_creator m_rombank; + memory_bank_creator m_rambank; +}; + +rc2014_mini_cpm::rc2014_mini_cpm(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, RC2014_MINI_CPM, tag, owner, clock) + , device_rc2014_card_interface(mconfig, *this) + , m_ata(*this, "ata") + , m_rc2014_bus(*this, ":bus") + , m_rom(*this, "rom") + , m_jp1(*this, "JP1-JP2") + , m_view(*this, "view") + , m_rombank(*this, "bank") + , m_rambank(*this, "ram") +{ +} + +void rc2014_mini_cpm::device_start() +{ + // Additional 32K RAM + m_ram = std::make_unique<u8[]>(0x8000); + std::fill_n(m_ram.get(), 0x8000, 0xff); + save_pointer(NAME(m_ram), 0x8000); + save_item(NAME(m_view_num)); + + // Install RAM/ROM + m_bus->installer(AS_PROGRAM)->install_view(0x0000, 0x7fff, m_view); + m_view[0].install_read_bank(0x0000, 0x3fff, m_rombank); + m_view[0].install_write_bank(0x0000, 0x3fff, m_rambank); + m_view[1].install_readwrite_bank(0x0000, 0x7fff, m_rambank); + + // Setup banks + m_rombank->configure_entry(0, m_rom->base() + 0x0000); + m_rombank->configure_entry(1, m_rom->base() + 0x4000); + m_rombank->configure_entry(2, m_rom->base() + 0x8000); + m_rombank->configure_entry(3, m_rom->base() + 0xc000); + + m_rambank->configure_entry(0, m_ram.get()); +} + +void rc2014_mini_cpm::device_reset() +{ + // A15-A8, A7 and A2-A0 not connected, A6 must be 0 + m_bus->installer(AS_IO)->install_write_handler(0x30, 0x30, 0, 0xff87, 0, write8sm_delegate(*this, FUNC(rc2014_mini_cpm::reset_bank_w))); + m_bus->installer(AS_IO)->install_write_handler(0x38, 0x38, 0, 0xff87, 0, write8sm_delegate(*this, FUNC(rc2014_mini_cpm::toggle_bank_w))); + // A15-A8 and A7 not connected + m_bus->installer(AS_IO)->install_readwrite_handler(0x10, 0x17, 0, 0xff80, 0, read8sm_delegate(*this, FUNC(rc2014_mini_cpm::ide_cs0_r)), write8sm_delegate(*this, FUNC(rc2014_mini_cpm::ide_cs0_w))); + + // Set default banks + m_view_num = 0; + m_rombank->set_entry(m_jp1->read()); + update_banks(); +} + +void rc2014_mini_cpm::device_add_mconfig(machine_config &config) +{ + ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, true); + + RC2014_SLOT(config, "1", m_rc2014_bus, rc2014_bus_modules, nullptr); + RC2014_SLOT(config, "2", m_rc2014_bus, rc2014_bus_modules, nullptr); +} + +static INPUT_PORTS_START( rc2014_mini_cpm_jumpers ) + PORT_START("JP1-JP2") + PORT_CONFNAME( 0x3, 0x1, "Bank" ) + PORT_CONFSETTING( 0x0, "0" ) + PORT_CONFSETTING( 0x1, "1" ) + PORT_CONFSETTING( 0x2, "2" ) + PORT_CONFSETTING( 0x3, "3" ) +INPUT_PORTS_END + +ioport_constructor rc2014_mini_cpm::device_input_ports() const +{ + return INPUT_PORTS_NAME( rc2014_mini_cpm_jumpers ); +} + +ROM_START(rc2014_mini_cpm) + ROM_REGION( 0x10000, "rom",0 ) + ROM_LOAD( "r0881099.bin", 0x00000, 0x10000, CRC(5619f399) SHA1(c96e9ebd6ce019c264aaea156532fcf807d4c74c) ) +ROM_END + +const tiny_rom_entry *rc2014_mini_cpm::device_rom_region() const +{ + return ROM_NAME( rc2014_mini_cpm ); +} + +} +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(RC2014_MICRO, device_rc2014_card_interface, rc2014_micro, "rc2014_micro", "RC2014 Micro module") +DEFINE_DEVICE_TYPE_PRIVATE(RC2014_MINI_CPM, device_rc2014_card_interface, rc2014_mini_cpm, "rc2014_mini_cpm", "Mini CP/M Upgrade module") |