summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ss50/mpt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/ss50/mpt.cpp')
-rw-r--r--src/devices/bus/ss50/mpt.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/devices/bus/ss50/mpt.cpp b/src/devices/bus/ss50/mpt.cpp
new file mode 100644
index 00000000000..70ce9d0e3fa
--- /dev/null
+++ b/src/devices/bus/ss50/mpt.cpp
@@ -0,0 +1,199 @@
+// license:BSD-3-Clause
+// copyright-holders:68bit
+/**********************************************************************
+
+ SWTPC MP-T Timer / counter
+
+ MC6821 PIA + MK5009 timer/counter
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mpt.h"
+#include "machine/6821pia.h"
+#include "machine/mc14411.h"
+
+
+class ss50_mpt_device : public device_t, public ss50_card_interface
+{
+public:
+ ss50_mpt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SS50_MPT, tag, owner, clock)
+ , ss50_card_interface(mconfig, *this)
+ , m_pia(*this, "pia")
+ , m_irqa_jumper(*this, "irqa")
+ , m_irqb_jumper(*this, "irqb")
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+ virtual u8 register_read(offs_t offset) override;
+ virtual void register_write(offs_t offset, u8 data) override;
+
+private:
+ DECLARE_WRITE8_MEMBER(pia_b_w);
+ DECLARE_READ8_MEMBER(pia_cb1_r);
+ DECLARE_WRITE_LINE_MEMBER(pia_irq_b);
+ TIMER_CALLBACK_MEMBER(mpt_timer_callback);
+ DECLARE_WRITE_LINE_MEMBER(pia_irqa_w);
+ DECLARE_WRITE_LINE_MEMBER(pia_irqb_w);
+
+ required_device<pia6821_device> m_pia;
+ required_ioport m_irqa_jumper;
+ required_ioport m_irqb_jumper;
+
+ emu_timer *m_mpt_timer;
+ attotime m_mpt_duration;
+ uint8_t m_mpt_timer_state;
+};
+
+
+static INPUT_PORTS_START( mpt )
+ PORT_START("irqa")
+ PORT_DIPNAME(1, 0, "IRQ-A")
+ PORT_DIPSETTING(0, DEF_STR(Off))
+ PORT_DIPSETTING(1, DEF_STR(On))
+
+ PORT_START("irqb")
+ PORT_DIPNAME(1, 1, "IRQ-B")
+ PORT_DIPSETTING(0, DEF_STR(Off))
+ PORT_DIPSETTING(1, DEF_STR(On))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor ss50_mpt_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mpt);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device-specific
+// machine configuration
+//-------------------------------------------------
+
+void ss50_mpt_device::device_add_mconfig(machine_config &config)
+{
+ PIA6821(config, m_pia, 0);
+ m_pia->writepb_handler().set(FUNC(ss50_mpt_device::pia_b_w));
+ m_pia->readcb1_handler().set(FUNC(ss50_mpt_device::pia_cb1_r));
+ m_pia->irqa_handler().set(FUNC(ss50_mpt_device::pia_irqa_w));
+ m_pia->irqb_handler().set(FUNC(ss50_mpt_device::pia_irqb_w));
+}
+
+void ss50_mpt_device::device_start()
+{
+ m_mpt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ss50_mpt_device::mpt_timer_callback),this));
+ m_mpt_timer_state = 0;
+}
+
+//-------------------------------------------------
+// register_read - read from a port register
+//-------------------------------------------------
+
+u8 ss50_mpt_device::register_read(offs_t offset)
+{
+ return m_pia->read(offset & 3);
+}
+
+//-------------------------------------------------
+// register_write - write to a port register
+//-------------------------------------------------
+
+void ss50_mpt_device::register_write(offs_t offset, u8 data)
+{
+ m_pia->write(offset & 3, data);
+}
+
+
+WRITE8_MEMBER(ss50_mpt_device::pia_b_w)
+{
+ if (data & 0x80)
+ {
+ // Reset state.
+ m_mpt_timer->enable(false);
+ return;
+ }
+
+ data &= 0x0f;
+
+ if (data == 0x0c || data == 0x0d || data == 0x0f)
+ {
+ // No output for these input settings.
+ m_mpt_timer->enable(false);
+ return;
+ }
+
+ if (data == 0x00)
+ {
+ // Hack: could not keep up with this 1us period
+ // anyway, and this is the initial state and it blocks
+ // progress, so just give up on this setting.
+ m_mpt_timer->enable(false);
+ return;
+ }
+
+ attotime duration;
+ // Set the duration for half the period, the time that the next
+ // transition of state will occur.
+ switch (data & 0x0f)
+ {
+ case 0: duration = attotime::from_nsec(500); break;
+ case 1: duration = attotime::from_usec(5); break;
+ case 2: duration = attotime::from_usec(50); break;
+ case 3: duration = attotime::from_usec(500); break;
+ case 4: duration = attotime::from_msec(5); break;
+ case 5: duration = attotime::from_msec(50); break;
+ case 6: duration = attotime::from_msec(500); break;
+ case 7: duration = attotime::from_seconds(5); break;
+ case 8: duration = attotime::from_seconds(50); break;
+ case 9: duration = attotime::from_seconds(30); break;
+ case 10: duration = attotime::from_seconds(30 * 60); break;
+ case 11: duration = attotime::from_seconds(5 * 60); break;
+ case 14: duration = attotime::from_msec(10); break;
+ }
+
+ if (duration != m_mpt_duration)
+ {
+ // TODO when would a change be latched?
+ m_mpt_timer->adjust(duration);
+ m_mpt_duration = duration;
+ }
+ m_mpt_timer->enable(true);
+}
+
+READ8_MEMBER(ss50_mpt_device::pia_cb1_r)
+{
+ return m_mpt_timer_state;
+}
+
+TIMER_CALLBACK_MEMBER(ss50_mpt_device::mpt_timer_callback)
+{
+ m_mpt_timer_state = !m_mpt_timer_state;
+ m_pia->cb1_w(m_mpt_timer_state);
+ m_mpt_timer->adjust(m_mpt_duration);
+ m_mpt_timer->enable(true);
+}
+
+WRITE_LINE_MEMBER(ss50_mpt_device::pia_irqa_w)
+{
+ if (m_irqa_jumper->read())
+ write_irq(state);
+}
+
+WRITE_LINE_MEMBER(ss50_mpt_device::pia_irqb_w)
+{
+ if (m_irqb_jumper->read())
+ write_irq(state);
+}
+
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(SS50_MPT, ss50_card_interface, ss50_mpt_device, "ss50_mpt", "MP-T Timer / Counter")