summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/a2bus/uniprint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/a2bus/uniprint.cpp')
-rw-r--r--src/devices/bus/a2bus/uniprint.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/devices/bus/a2bus/uniprint.cpp b/src/devices/bus/a2bus/uniprint.cpp
new file mode 100644
index 00000000000..6af2662a846
--- /dev/null
+++ b/src/devices/bus/a2bus/uniprint.cpp
@@ -0,0 +1,250 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb, R. Belmont
+#include "emu.h"
+#include "uniprint.h"
+
+#include "bus/centronics/ctronics.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+class a2bus_uniprint_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ a2bus_uniprint_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // device_a2bus_card_interface implementation
+ virtual u8 read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+ virtual u8 read_cnxx(u8 offset) override;
+ virtual u8 read_c800(u16 offset) override;
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // timer handlers
+ TIMER_CALLBACK_MEMBER(update_strobe);
+
+private:
+ // printer status inputs
+ void ack_w(int state);
+
+ required_device<centronics_device> m_printer_conn;
+ required_device<output_latch_device> m_printer_out;
+ required_ioport m_s1, m_s2;
+ required_region_ptr<u8> m_rom;
+ emu_timer * m_strobe_timer;
+
+ u8 m_data_latch; // U6
+ u8 m_ack_latch; // U2 (pin 9)
+ u8 m_next_strobe; // U4 (pin 5)
+ u8 m_ack_in; // printer connector pin 10
+};
+
+
+ROM_START(uniprint)
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD("videx_uniprint_2732a.bin", 0x000000, 0x001000, CRC(e8423ef6) SHA1(0a2789ec2cb28f10a2836a91feabc24ceca8f142))
+ROM_END
+
+INPUT_PORTS_START(uniprint)
+ PORT_START("S1")
+ PORT_DIPNAME(0x70, 0x00, "Printer Type") PORT_DIPLOCATION("S1:1,2,3")
+ PORT_DIPSETTING( 0x00, "Apple DMP/C. Itoh 8510/NEC 8023A/Leading Edge Prowriter")
+ PORT_DIPSETTING( 0x10, "Epson MX, FX, RX/Mannesman Tally 160L, Sprit-80")
+ PORT_DIPSETTING( 0x20, "Star Gemini 10, 15")
+ PORT_DIPSETTING( 0x30, "Data Products (IDS) 440, 460, Prism, uPrism/Okidata 82A, 83A, 93A")
+ PORT_DIPSETTING( 0x40, "Anadex 9000, 9000A, 9001, 9001A, 9500A, 9501, 9501A")
+ PORT_DIPSETTING( 0x50, "Leading Edge Gorilla Banana/Commodore VIC Printer/Radio Shack DMP-100/Sekiosha GP-100A")
+ PORT_DIPSETTING( 0x60, "Centronics 739-1")
+ PORT_DIPSETTING( 0x70, "Reserved")
+ PORT_DIPNAME(0x0c, 0x00, "Default Page Width") PORT_DIPLOCATION("S1:4,5")
+ PORT_DIPSETTING( 0x00, "No Width")
+ PORT_DIPSETTING( 0x04, "80 Columns")
+ PORT_DIPSETTING( 0x08, "96 Columns")
+ PORT_DIPSETTING( 0x0c, "132 Columns")
+ PORT_DIPNAME(0x03, 0x00, "Default Page Length") PORT_DIPLOCATION("S1:6,7")
+ PORT_DIPSETTING( 0x00, "No Length")
+ PORT_DIPSETTING( 0x01, "54 Lines")
+ PORT_DIPSETTING( 0x02, "57 Lines")
+ PORT_DIPSETTING( 0x03, "60 Lines")
+
+ PORT_START("S2")
+ PORT_DIPNAME(0x01, 0x01, "Strobe Polarity") PORT_DIPLOCATION("S1:8")
+ PORT_DIPSETTING( 0x00, "Positive")
+ PORT_DIPSETTING( 0x01, "Negative")
+ PORT_DIPNAME(0x02, 0x02, "Acknowledge Polarity") PORT_DIPLOCATION("S1:9")
+ PORT_DIPSETTING( 0x00, "Positive")
+ PORT_DIPSETTING( 0x02, "Negative")
+INPUT_PORTS_END
+
+
+a2bus_uniprint_device::a2bus_uniprint_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, A2BUS_UNIPRINT, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_printer_conn(*this, "prn"),
+ m_printer_out(*this, "prn_out"),
+ m_s1(*this, "S1"),
+ m_s2(*this, "S2"),
+ m_rom(*this, "rom"),
+ m_strobe_timer(nullptr),
+ m_data_latch(0xffU),
+ m_ack_latch(0x01U),
+ m_next_strobe(1U),
+ m_ack_in(1U)
+{
+}
+
+
+
+//----------------------------------------------
+// device_a2bus_card_interface implementation
+//----------------------------------------------
+
+// address lines are connected only to the EPROM, so all C0NX accesses are the same
+u8 a2bus_uniprint_device::read_c0nx(u8 offset)
+{
+ // inverted /ACK?
+ if (m_s2->read() & 0x02U)
+ {
+ return (m_s1->read() & 0x07FU) | ((m_ack_latch ^ 1) << 7);
+ }
+
+ return (m_s1->read() & 0x07FU) | (m_ack_latch << 7);
+}
+
+void a2bus_uniprint_device::write_c0nx(u8 offset, u8 data)
+{
+ m_data_latch = data;
+ m_printer_out->write(data);
+
+ // clearing the ACK latch will acknowledge an interrupt
+ if (m_ack_in)
+ {
+ m_ack_latch = 0x00U;
+ }
+ else
+ {
+ LOG("/ACK asserted, not clearing acknowledge latch\n");
+ }
+
+ // generate strobe pulse after one clock cycle
+ m_next_strobe = 0U;
+ if (!m_strobe_timer->enabled())
+ {
+ LOG("Start strobe timer\n");
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+ }
+}
+
+u8 a2bus_uniprint_device::read_cnxx(u8 offset)
+{
+ return m_rom[offset + (slotno() * 0x100)];
+}
+
+u8 a2bus_uniprint_device::read_c800(u16 offset)
+{
+ return m_rom[offset + 0x800];
+}
+
+
+//----------------------------------------------
+// device_t implementation
+//----------------------------------------------
+
+tiny_rom_entry const *a2bus_uniprint_device::device_rom_region() const
+{
+ return ROM_NAME(uniprint);
+}
+
+
+void a2bus_uniprint_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_printer_conn, centronics_devices, "printer");
+ m_printer_conn->ack_handler().set(FUNC(a2bus_uniprint_device::ack_w));
+
+ OUTPUT_LATCH(config, m_printer_out);
+ m_printer_conn->set_output_latch(*m_printer_out);
+}
+
+
+ioport_constructor a2bus_uniprint_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(uniprint);
+}
+
+
+void a2bus_uniprint_device::device_start()
+{
+ m_strobe_timer = timer_alloc(FUNC(a2bus_uniprint_device::update_strobe), this);
+
+ m_next_strobe = 1U;
+
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_ack_latch));
+ save_item(NAME(m_next_strobe));
+ save_item(NAME(m_ack_in));
+
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+}
+
+
+void a2bus_uniprint_device::device_reset()
+{
+ m_ack_latch = 0x01U;
+}
+
+
+
+//----------------------------------------------
+// printer status inputs
+//----------------------------------------------
+
+void a2bus_uniprint_device::ack_w(int state)
+{
+ if (bool(state) != bool(m_ack_in))
+ {
+ LOG("/ACK=%d\n", state);
+ m_ack_in = state ? 1U : 0U;
+ if (!state)
+ {
+ if (!m_ack_latch)
+ LOG("Set acknowledge latch\n");
+ else
+ LOG("No data written since previous acknowledge\n");
+ m_ack_latch = 0x01U;
+ }
+ }
+}
+
+//----------------------------------------------
+// timer handlers
+//----------------------------------------------
+
+TIMER_CALLBACK_MEMBER(a2bus_uniprint_device::update_strobe)
+{
+ LOG("Output /STROBE=%u\n", m_next_strobe);
+ // invert strobe if DIP set to positive polarity
+ m_printer_conn->write_strobe(m_next_strobe ^ (m_s2->read() & 0x01) ? 0 : 1);
+ if (!m_next_strobe)
+ {
+ LOG("Start strobe timer\n");
+ m_next_strobe = 1U;
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+ }
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_UNIPRINT, device_a2bus_card_interface, a2bus_uniprint_device, "a2uniprint", "Videx Uniprint Printer Interface")