summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/epson_qx/multifont.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/epson_qx/multifont.cpp')
-rw-r--r--src/devices/bus/epson_qx/multifont.cpp289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/devices/bus/epson_qx/multifont.cpp b/src/devices/bus/epson_qx/multifont.cpp
new file mode 100644
index 00000000000..27486cb5d4c
--- /dev/null
+++ b/src/devices/bus/epson_qx/multifont.cpp
@@ -0,0 +1,289 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * Q10MF Multifont card
+ * Schematic: https://github.com/brijohn/qx10/raw/master/schematics/multifont/multifont.pdf
+ * Documentation: http://www.bitsavers.org/pdf/epson/QX-10/options/QX-10-multifont.pdf
+ *
+ * I/O Ports:
+ * 0xFC:
+ * Read:
+ * Reading from this will read a status byte followed by the character data for a requested character.
+ * Status byte:
+ * -------------------------------------------------
+ * | VALID | MODE | 0 0 | UP | RIGHT | LEFT | DOWN |
+ * -------------------------------------------------
+ * Valid: 1 = Character is valid, 0 = Character is invalid
+ * Mode: 1 = Pattern is for CRT, 0 = Pattern is for printer
+ * Up: Extends upwards 0 = No, 1 = Yes
+ * Right: Extends to the right 0 = No, 1 = Yes
+ * Left: Extends to the left 0 = No, 1 = Yes
+ * Down: Extends downwards 0 = No, 1 = Yes
+ * Write:
+ * Data written to this consists of a command byte followed by two bytes representing
+ * the character code being requested, least significant byte first. (0x0000-0x0DFF)
+ * Command byte:
+ * ------------------------------------------
+ * | 1 | MODE | 0 0 0 0 0 | BIT |
+ * ------------------------------------------
+ * Mode: 0 = Pattern for printer, 1 = Pattern for CRT
+ * Bit: 0 = Non-DMA Pattern for CRT, 1 = DMA pattern for CRT
+ * 0xFD:
+ * Read:
+ * This is the status register for the multifont card.
+ * ----------------------------------------------
+ * | IBF | X X X | X X | ERR | OBF |
+ * ----------------------------------------------
+ * IBF: 1 = Data available to read, 0 = Data not available
+ * ERR: 1 = Error occured, 0 = No error
+ * OBF: 1 = Not ready for data to be written , 0 = Ready for data
+ * Write:
+ * Writing any value will trigger an INTL interrupt. This used by cpm to determine
+ * which slot the card is installed in. To reset the interrupt simply read from the
+ * status port.
+ *
+ *******************************************************************/
+#include "emu.h"
+#include "multifont.h"
+
+
+//**************************************************************************
+// EPSON Q10MF MULTIFONT DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_MULTIFONT, bus::epson_qx::multifont_device, "epson_qx_option_multifont", "Epson Multifont Card")
+
+
+namespace bus::epson_qx {
+
+ROM_START(multifont)
+ /* This is the i8039 program ROM for the Q10MF Multifont card */
+ ROM_REGION( 0x0800, "i8039", 0 )
+ ROM_LOAD( "m12020a.3e", 0x0000, 0x0800, CRC(fa27f333) SHA1(73d27084ca7b002d5f370220d8da6623a6e82132))
+
+ ROM_REGION( 0x4000, "font0", 0 )
+ ROM_LOAD( "hn43128.1a", 0x0000, 0x4000, CRC(0ba54615) SHA1(d718e9b3b6cab29a17c2d4d72a7b397121d96ffd))
+ ROM_REGION( 0x4000, "font1", 0 )
+ ROM_LOAD( "hn43128.2a", 0x0000, 0x4000, CRC(968a8848) SHA1(e19ef2bd46c7471ed682a6d456be9cb1db5ce321))
+ ROM_REGION( 0x4000, "font2", 0 )
+ ROM_LOAD( "hn43128.1b", 0x0000, 0x4000, CRC(e4ed0fb1) SHA1(77e825061f9af77d3f1963aa9cbbb46f49e86f92))
+ ROM_REGION( 0x4000, "font3", 0 )
+ ROM_LOAD( "hn43128.2b", 0x0000, 0x4000, CRC(27e9c1da) SHA1(926985f0fec6b00960acd616bc73596bcb3d3884))
+ ROM_REGION( 0x4000, "font4", 0 )
+ ROM_LOAD( "hn43128.3a", 0x0000, 0x4000, CRC(3e5dd796) SHA1(ffa6eb775545833b8e7647c450595fab6d6aa341))
+ ROM_REGION( 0x4000, "font5", 0 )
+ ROM_LOAD( "hn43128.3b", 0x0000, 0x4000, CRC(adc569bf) SHA1(19246af07d6728ccd74a021265df827ecc6fe2b5))
+ /* Sockets 1c and 2c are empty */
+ ROM_REGION( 0x4000, "font6", 0 )
+ ROM_LOAD( "hn43128.1c", 0x0000, 0x4000, NO_DUMP)
+ ROM_REGION( 0x4000, "font7", 0 )
+ ROM_LOAD( "hn43128.2c", 0x0000, 0x4000, NO_DUMP)
+ROM_END
+
+INPUT_PORTS_START(multifont)
+ PORT_START("IOBASE")
+ PORT_CONFNAME(0x06, 0x04, "IO Base Address Selection")
+ PORT_CONFSETTING(0x00, "&F8")
+ PORT_CONFSETTING(0x02, "&FA")
+ PORT_CONFSETTING(0x04, "&FC")
+ PORT_CONFSETTING(0x06, "&FE")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// multifont_device - constructor
+//-------------------------------------------------
+multifont_device::multifont_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EPSON_QX_OPTION_MULTIFONT, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_mcu(*this, "mcu"),
+ m_i8243(*this, "i8243"),
+ m_fonts(*this, "font%u",0),
+ m_ioport(*this, "IOBASE")
+{
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+ioport_constructor multifont_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(multifont);
+}
+
+//-------------------------------------------------
+// device_rom_region - device-specific roms
+//-------------------------------------------------
+const tiny_rom_entry *multifont_device::device_rom_region() const
+{
+ return ROM_NAME(multifont);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void multifont_device::device_add_mconfig(machine_config &config)
+{
+ I8039(config, m_mcu, 9_MHz_XTAL);
+ m_mcu->set_addrmap(AS_PROGRAM, &multifont_device::rom_map);
+ m_mcu->prog_out_cb().set(m_i8243, FUNC(i8243_device::prog_w));
+ m_mcu->p1_out_cb().set(FUNC(multifont_device::p1_w));
+ m_mcu->p2_out_cb().set(FUNC(multifont_device::p2_w));
+ m_mcu->bus_out_cb().set(FUNC(multifont_device::write_bus));
+ m_mcu->bus_in_cb().set(FUNC(multifont_device::read_bus));
+ m_mcu->t1_in_cb().set(FUNC(multifont_device::t1_r));
+ m_mcu->t0_in_cb().set(FUNC(multifont_device::t0_r));
+ I8243(config, m_i8243);
+ m_i8243->p4_out_cb().set(FUNC(multifont_device::rom_addr_w<0>));
+ m_i8243->p5_out_cb().set(FUNC(multifont_device::rom_addr_w<4>));
+ m_i8243->p6_out_cb().set(FUNC(multifont_device::rom_addr_w<8>));
+ m_i8243->p7_out_cb().set(FUNC(multifont_device::rom_select_w));
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void multifont_device::device_start()
+{
+ m_hard_reset = true;
+
+ m_data_out = 0x00;
+ m_data_in = 0x00;
+ m_p1 = 0xff;
+ m_p2 = 0xff;
+
+ save_item(NAME(m_status));
+ save_item(NAME(m_data_out));
+ save_item(NAME(m_data_in));
+ save_item(NAME(m_p1));
+ save_item(NAME(m_p2));
+ save_item(NAME(m_rom_sel));
+ save_item(NAME(m_address));
+ save_item(NAME(m_rom_bank));
+ save_item(NAME(m_bus_reset));
+ save_item(NAME(m_hard_reset));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void multifont_device::device_reset()
+{
+ uint8_t iobase;
+
+ m_status = 0x00;
+
+ if (m_hard_reset) {
+ address_space &space = m_bus->iospace();
+ iobase = (m_ioport->read() & 0x06) + 0xf8;
+ space.install_device(iobase, iobase+1, *this, &multifont_device::map);
+ m_hard_reset = false;
+ }
+
+ m_bus_reset = true;
+}
+
+uint8_t multifont_device::t0_r()
+{
+ return BIT(m_status, 0);
+}
+
+uint8_t multifont_device::t1_r()
+{
+ return BIT(m_status, 7);
+}
+
+void multifont_device::write_bus(uint8_t data)
+{
+ if (!m_bus_reset) {
+ m_status = m_status | 0x80;
+ m_data_out = data;
+ } else {
+ m_bus_reset = false;
+ }
+}
+
+uint8_t multifont_device::read_bus()
+{
+ if (BIT(m_p1, 0)) {
+ m_status = (m_status & 0xfe);
+ return m_data_in;
+ } else if (BIT(m_p1, 1)) {
+ uint8_t *rom = m_fonts[m_rom_bank]->base();
+ return rom[m_address];
+ }
+ return 0xff;
+}
+
+void multifont_device::p1_w(uint8_t data)
+{
+ m_p1 = data;
+ if (BIT(m_p1, 7) == 0) {
+ get_slot()->intl_w(ASSERT_LINE);
+ }
+}
+
+void multifont_device::p2_w(uint8_t data)
+{
+ m_p2 = data;
+ m_i8243->p2_w(m_p2 & 0x0f);
+ update_bank_select();
+ m_status = (m_status & 0xfd) | ((m_p2 & 0x20) >> 4);
+}
+
+template<int Shift>
+void multifont_device::rom_addr_w(uint8_t data)
+{
+ m_address = (m_address & ~(0x00f << Shift)) | ((data & 0x0f) << Shift);
+}
+
+void multifont_device::rom_select_w(uint8_t data)
+{
+ m_rom_sel = (data & 0x0f) >> 2;
+ m_address = (m_address & 0xfff) | ((data & 0x03) << 12);
+ update_bank_select();
+}
+
+void multifont_device::update_bank_select()
+{
+ m_rom_bank = ((m_p2 & 0x80) >> 5) | (m_rom_sel & 0x03);
+}
+
+uint8_t multifont_device::read(offs_t offset)
+{
+ if (offset) {
+ if (!machine().side_effects_disabled()) {
+ if (BIT(m_p1, 7)) {
+ get_slot()->intl_w(CLEAR_LINE);
+ }
+ }
+ return m_status;
+ }
+ if (!machine().side_effects_disabled()) {
+ m_status = (m_status & 0x7f);
+ }
+ return m_data_out;
+}
+
+void multifont_device::write(offs_t offset, uint8_t data)
+{
+ if (offset) {
+ get_slot()->intl_w(ASSERT_LINE);
+ } else {
+ m_status = m_status | 0x01;
+ m_data_in = data;
+ }
+}
+
+void multifont_device::rom_map(address_map &map)
+{
+ map.global_mask(0x07ff);
+ map(0x0000, 0x07ff).rom().region("i8039", 0);
+}
+
+void multifont_device::map(address_map &map)
+{
+ map(0x00, 0x01).rw(FUNC(multifont_device::read), FUNC(multifont_device::write));
+}
+
+} // namespace bus::epson_qx