summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/mdisk.cpp
blob: 8c45c5da04e1fd5786e5cbf3f4d7d2c7cd9dc715 (plain) (tree)
1
2
3
4
5
6
7
8
9






                                                                            

                                                                      
 



                                                                         










































                                                                                       
                                      



























































                                                                                          
                                          













































                                                                                                                                      
                                                                                              








































































































                                                                                                                              
// license: GPL-2.0+
// copyright-holders: Dirk Best
/***************************************************************************

    mupid M-Disk Comp.-A
    Grundig FL-100

    Floppy disk station, usually connected to a mupid C2D2/C2A2 or the
    Grundig PTC-100.

    Everything here is guessed based on the software and a PCB image. You
    can see garbled output when you connect the builtin terminal to the
    first serial port ('ser'). It does boot from floppy too, so presumely
    only needs an emulated main system to work.

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

#include "emu.h"
#include "cpu/z80/z80.h"
#include "machine/clock.h"
#include "machine/i8251.h"
#include "machine/i8271.h"
#include "machine/ram.h"
#include "bus/rs232/rs232.h"
#include "imagedev/floppy.h"


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

class mdisk_state : public driver_device
{
public:
	mdisk_state(const machine_config &mconfig, device_type type, const char *tag) :
		driver_device(mconfig, type, tag),
		m_cpu(*this, "maincpu"),
		m_ram(*this, "ram"),
		m_fdc(*this, "fdc"),
		m_floppy(*this, "fdc:%u", 0),
		m_rom_timer(nullptr),
		m_uart1_rxrdy(0), m_uart1_txrdy(0),
		m_fdc_irq(0)
		{ }

		void mdisk(machine_config &config);

protected:
	virtual void machine_start() override;
	virtual void machine_reset() override;

private:
	TIMER_CALLBACK_MEMBER(rom_timer_callback);
	DECLARE_WRITE_LINE_MEMBER(uart1_rxrdy_w);
	DECLARE_WRITE_LINE_MEMBER(uart1_txrdy_w);
	DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
	DECLARE_WRITE_LINE_MEMBER(fdc_motor_w);
	void fdc_side_w(uint8_t data);

	void update_irq(uint8_t vector);

	required_device<z80_device> m_cpu;
	required_device<ram_device> m_ram;
	required_device<i8271_device> m_fdc;
	required_device_array<floppy_connector, 2> m_floppy;

	void mdisk_mem(address_map &map);
	void mdisk_io(address_map &map);

	emu_timer *m_rom_timer;

	int m_uart1_rxrdy, m_uart1_txrdy, m_fdc_irq;
};


//**************************************************************************
//  ADDRESS MAPS
//**************************************************************************

void mdisk_state::mdisk_mem(address_map &map)
{
	map(0x0000, 0x1fff).bankr("bank1r").bankw("bank1w");
	map(0x2000, 0xffff).bankrw("bank2");
}

void mdisk_state::mdisk_io(address_map &map)
{
	map.global_mask(0xff);
	map(0x20, 0x20).w(FUNC(mdisk_state::fdc_side_w));
	map(0x40, 0x40).rw("fdc", FUNC(i8271_device::data_r), FUNC(i8271_device::data_w));
	map(0x80, 0x81).rw("uart1", FUNC(i8251_device::read), FUNC(i8251_device::write));
	map(0x84, 0x85).rw("uart2", FUNC(i8251_device::read), FUNC(i8251_device::write));
	map(0x9c, 0x9e).m(m_fdc, FUNC(i8271_device::map));
}


//**************************************************************************
//  INPUTS
//**************************************************************************

INPUT_PORTS_START( mdisk )
	PORT_START("front")
	PORT_DIPNAME(0x01, 0x01, "Baudrate")
	PORT_DIPSETTING(0x00, "4800")
	PORT_DIPSETTING(0x01, "19200")
INPUT_PORTS_END


//**************************************************************************
//  FLOPPY
//**************************************************************************

WRITE_LINE_MEMBER(mdisk_state::fdc_motor_w)
{
	if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
	if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
}

void mdisk_state::fdc_side_w(uint8_t data)
{
	if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->ss_w(BIT(data, 0));
	if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->ss_w(BIT(data, 0));
}


//**************************************************************************
//  MACHINE
//**************************************************************************

void mdisk_state::machine_start()
{
	// timer to switch rom to ram
	m_rom_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mdisk_state::rom_timer_callback), this), nullptr);

	// register for save states
	save_item(NAME(m_uart1_rxrdy));
	save_item(NAME(m_uart1_txrdy));
	save_item(NAME(m_fdc_irq));
}

void mdisk_state::machine_reset()
{
	// read from rom, write to ram
	membank("bank1r")->set_base(memregion("firmware")->base());
	membank("bank1w")->set_base(m_ram->pointer());
	membank("bank2")->set_base(m_ram->pointer() + 0x2000);

	// timing unknown
	m_rom_timer->adjust(attotime::from_msec(50));

	m_uart1_rxrdy = 0;
	m_uart1_txrdy = 0;
	m_fdc_irq = 0;
}

TIMER_CALLBACK_MEMBER(mdisk_state::rom_timer_callback)
{
	// switch in ram
	logerror("Disabling ROM\n");
	membank("bank1r")->set_base(m_ram->pointer());
}

void mdisk_state::update_irq(uint8_t vector)
{
	if (m_uart1_rxrdy || m_uart1_txrdy || m_fdc_irq)
		m_cpu->set_input_line_and_vector(INPUT_LINE_IRQ0, ASSERT_LINE, vector); // Z80
	else
		m_cpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
}

WRITE_LINE_MEMBER(mdisk_state::fdc_irq_w)
{
	m_fdc_irq = state;
	update_irq(0x00);
}

WRITE_LINE_MEMBER(mdisk_state::uart1_rxrdy_w)
{
	m_uart1_rxrdy = state;
	update_irq(0x18);
}

WRITE_LINE_MEMBER(mdisk_state::uart1_txrdy_w)
{
	m_uart1_txrdy = state;
	update_irq(0x1c);
}


//**************************************************************************
//  MACHINE DEFINITIONS
//**************************************************************************

static void mdisk_floppies(device_slot_interface &device)
{
	device.option_add("525qd", FLOPPY_525_QD);
}

void mdisk_state::mdisk(machine_config &config)
{
	Z80(config, m_cpu, 4_MHz_XTAL);
	m_cpu->set_addrmap(AS_PROGRAM, &mdisk_state::mdisk_mem);
	m_cpu->set_addrmap(AS_IO, &mdisk_state::mdisk_io);

	// 64k internal ram
	RAM(config, m_ram).set_default_size("64K");

	// uart 1
	i8251_device &uart1(I8251(config, "uart1", 4_MHz_XTAL));
	uart1.rxrdy_handler().set(FUNC(mdisk_state::uart1_rxrdy_w));
	uart1.txrdy_handler().set(FUNC(mdisk_state::uart1_txrdy_w));
	uart1.txd_handler().set("ser", FUNC(rs232_port_device::write_txd));
	uart1.rts_handler().set("ser", FUNC(rs232_port_device::write_rts));
	uart1.dtr_handler().set("ser", FUNC(rs232_port_device::write_dtr));

	rs232_port_device &rs232_1(RS232_PORT(config, "ser", default_rs232_devices, nullptr));
	rs232_1.rxd_handler().set("uart1", FUNC(i8251_device::write_rxd));
	rs232_1.cts_handler().set("uart1", FUNC(i8251_device::write_cts));
	rs232_1.dsr_handler().set("uart1", FUNC(i8251_device::write_dsr));

	// uart 2
	i8251_device &uart2(I8251(config, "uart2", 4_MHz_XTAL));
	uart2.txd_handler().set("aux", FUNC(rs232_port_device::write_txd));
	uart2.rts_handler().set("aux", FUNC(rs232_port_device::write_rts));
	uart2.dtr_handler().set("aux", FUNC(rs232_port_device::write_dtr));

	rs232_port_device &rs232_2(RS232_PORT(config, "aux", default_rs232_devices, nullptr));
	rs232_2.rxd_handler().set("uart2", FUNC(i8251_device::write_rxd));
	rs232_2.cts_handler().set("uart2", FUNC(i8251_device::write_cts));
	rs232_2.dsr_handler().set("uart2", FUNC(i8251_device::write_dsr));

	// selectable 4800 or 19200
	clock_device &uart_clock(CLOCK(config, "uart_clock", 4.9152_MHz_XTAL / 32)); // just 9600 for now
	uart_clock.signal_handler().set("uart1", FUNC(i8251_device::write_txc));
	uart_clock.signal_handler().append("uart1", FUNC(i8251_device::write_rxc));
	uart_clock.signal_handler().append("uart2", FUNC(i8251_device::write_txc));
	uart_clock.signal_handler().append("uart2", FUNC(i8251_device::write_rxc));

	// floppy
	I8271(config, m_fdc, 4_MHz_XTAL);
	m_fdc->set_ready_line_connected(true);
	m_fdc->intrq_wr_callback().set(FUNC(mdisk_state::fdc_irq_w));
	m_fdc->drq_wr_callback().set_inputline(m_cpu, INPUT_LINE_NMI);
	m_fdc->hdl_wr_callback().set(FUNC(mdisk_state::fdc_motor_w));
	FLOPPY_CONNECTOR(config, m_floppy[0], mdisk_floppies, "525qd", floppy_image_device::default_floppy_formats);
	FLOPPY_CONNECTOR(config, m_floppy[1], mdisk_floppies, "525qd", floppy_image_device::default_floppy_formats);
}


//**************************************************************************
//  ROM DEFINITIONS
//**************************************************************************

ROM_START( mdisk )
	ROM_REGION(0x2000, "firmware", 0)
	ROM_LOAD("motronic_0090_6815_16.00.bin", 0x0000, 0x2000, CRC(931b3410) SHA1(4593708268d5ef7ffcb330f91218fc0c845abf5e))
ROM_END

ROM_START( fl100 )
	ROM_REGION(0x2000, "firmware", 0)
	ROM_LOAD("fl100.bin", 0x0000, 0x2000, CRC(68800982) SHA1(501c8877a18cef091476b780de605b2bea3853fb))
ROM_END


//**************************************************************************
//  SYSTEM DRIVERS
//**************************************************************************

//    YEAR  NAME   PARENT  COMPAT  MACHINE  INPUT  CLASS        INIT        COMPANY    FULLNAME          FLAGS
COMP( 198?, mdisk, 0,      0,      mdisk,   mdisk, mdisk_state, empty_init, "mupid",   "M-Disk Comp.-A", MACHINE_NOT_WORKING )
COMP( 198?, fl100, mdisk,  0,      mdisk,   mdisk, mdisk_state, empty_init, "Grundig", "FL-100",         MACHINE_NOT_WORKING )