summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/pcf2100.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/pcf2100.cpp')
-rw-r--r--src/devices/video/pcf2100.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/devices/video/pcf2100.cpp b/src/devices/video/pcf2100.cpp
new file mode 100644
index 00000000000..1d21947c90d
--- /dev/null
+++ b/src/devices/video/pcf2100.cpp
@@ -0,0 +1,125 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+Philips PCF2100 family LCD Driver
+
+PCF2100: 2*20 LCD segments
+PCF2110: 2*30 LCD segments, S31,S32 are LED outputs
+PCF2111: 2*32 LCD segments
+PCF2112: 1*32 LCD segments
+
+OSC is R/C, 2100/10/11: 60-100Hz, 2112: 30-50Hz
+Actual segment output frequency is divided by number of LCD commons.
+
+*/
+
+#include "emu.h"
+#include "pcf2100.h"
+
+
+DEFINE_DEVICE_TYPE(PCF2100, pcf2100_device, "pcf2100", "Philips PCF2100 LCD Driver")
+DEFINE_DEVICE_TYPE(PCF2110, pcf2110_device, "pcf2110", "Philips PCF2110 LCD Driver")
+DEFINE_DEVICE_TYPE(PCF2111, pcf2111_device, "pcf2111", "Philips PCF2111 LCD Driver")
+DEFINE_DEVICE_TYPE(PCF2112, pcf2112_device, "pcf2112", "Philips PCF2112 LCD Driver")
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+pcf2100_device::pcf2100_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bpmax, u8 smax) :
+ device_t(mconfig, type, tag, owner, clock),
+ m_bpmax(bpmax), m_smax(smax), m_write_segs(*this)
+{ }
+
+pcf2100_device::pcf2100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pcf2100_device(mconfig, PCF2100, tag, owner, clock, 2, 20)
+{ }
+
+pcf2110_device::pcf2110_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pcf2100_device(mconfig, PCF2110, tag, owner, clock, 2, 32)
+{ }
+
+pcf2111_device::pcf2111_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pcf2100_device(mconfig, PCF2111, tag, owner, clock, 2, 32)
+{ }
+
+pcf2112_device::pcf2112_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pcf2100_device(mconfig, PCF2112, tag, owner, clock, 1, 32)
+{ }
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pcf2100_device::device_start()
+{
+ // timer
+ m_lcd_timer = timer_alloc(FUNC(pcf2100_device::update_output_latches), this);
+ attotime period = attotime::from_hz(clock());
+ m_lcd_timer->adjust(period, 0, period);
+
+ // zerofill
+ m_shift = 0;
+ m_count = 0;
+ m_bpout = 0;
+ std::fill_n(m_latch, std::size(m_latch), 0);
+ m_clb = 0;
+ m_data = 0;
+ m_dlen = 0;
+
+ // register for savestates
+ save_item(NAME(m_shift));
+ save_item(NAME(m_count));
+ save_item(NAME(m_bpout));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_clb));
+ save_item(NAME(m_data));
+ save_item(NAME(m_dlen));
+}
+
+
+//-------------------------------------------------
+// handlers
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(pcf2100_device::update_output_latches)
+{
+ // transfer latches to output
+ m_write_segs(m_bpout, m_latch[m_bpout]);
+ m_bpout = (m_bpout + 1) % m_bpmax;
+}
+
+void pcf2100_device::clb_w(int state)
+{
+ state = (state) ? 1 : 0;
+ bool rise = state && !m_clb;
+ m_clb = state;
+
+ if (!rise)
+ return;
+
+ if (m_dlen)
+ {
+ // before shifting data, test leading 0 at start
+ if ((m_data && m_count == 0) || m_count > (m_smax + 2))
+ return;
+
+ m_shift |= u64(m_data) << m_count;
+ m_count++;
+ }
+ else
+ {
+ if (m_count == (m_smax + 2))
+ {
+ // transfer to latches
+ int dest = BIT(m_shift, m_smax + 1) ? 0 : 1;
+ u64 mask = (u64(1) << m_smax) - 1;
+ m_latch[dest] = m_shift >> 1 & mask;
+ }
+
+ m_shift = 0;
+ m_count = 0;
+ }
+}