diff options
Diffstat (limited to 'src/devices/video/lc7580.cpp')
-rw-r--r-- | src/devices/video/lc7580.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/devices/video/lc7580.cpp b/src/devices/video/lc7580.cpp new file mode 100644 index 00000000000..19868db4409 --- /dev/null +++ b/src/devices/video/lc7580.cpp @@ -0,0 +1,159 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/* + +Sanyo LC7580 LCD Driver + +53 outputs (static), or 104 outputs (1/2 duty) + +TODO: +- any difference between LC7580 and LC7582? +- OSC pin (input is R/C) +- AD/DSP function + +*/ + +#include "emu.h" +#include "lc7580.h" + +#include <tuple> + + +DEFINE_DEVICE_TYPE(LC7580, lc7580_device, "lc7580", "Sanyo LC7580 LCD Driver") +DEFINE_DEVICE_TYPE(LC7582, lc7582_device, "lc7582", "Sanyo LC7582 LCD Driver") + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +lc7580_device::lc7580_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), + device_nvram_interface(mconfig, *this), + m_write_segs(*this) +{ + // disable nvram by default + nvram_enable_backup(false); +} + +lc7580_device::lc7580_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + lc7580_device(mconfig, LC7580, tag, owner, clock) +{ } + +lc7582_device::lc7582_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + lc7580_device(mconfig, LC7582, tag, owner, clock) +{ } + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void lc7580_device::device_start() +{ + // zerofill + m_data = 0; + m_ce = 0; + m_clk = 0; + m_blank = false; + m_shift = 0; + std::fill_n(m_latch, std::size(m_latch), 0); + + // register for savestates + save_item(NAME(m_data)); + save_item(NAME(m_ce)); + save_item(NAME(m_clk)); + save_item(NAME(m_blank)); + save_item(NAME(m_shift)); + save_item(NAME(m_latch)); +} + + +//------------------------------------------------- +// nvram (when VDD is battery-backed) +//------------------------------------------------- + +bool lc7580_device::nvram_write(util::write_stream &file) +{ + std::error_condition err; + size_t actual; + + std::tie(err, actual) = write(file, &m_shift, sizeof(m_shift)); + if (err) + return false; + std::tie(err, actual) = write(file, &m_latch, sizeof(m_latch)); + if (err) + return false; + + return true; +} + +bool lc7580_device::nvram_read(util::read_stream &file) +{ + std::error_condition err; + size_t actual; + + std::tie(err, actual) = read(file, &m_shift, sizeof(m_shift)); + if (err || (sizeof(m_shift) != actual)) + return false; + std::tie(err, actual) = read(file, &m_latch, sizeof(m_latch)); + if (err || (sizeof(m_latch) != actual)) + return false; + + return true; +} + + +//------------------------------------------------- +// handlers +//------------------------------------------------- + +void lc7580_device::refresh_output() +{ + if (BIT(m_latch[0], 53)) + { + // 1/2 duty + u64 segs[2] = { 0, 0 }; + + // COM1 on even bits, COM2 on uneven bits + for (int i = 0; i < 104; i++) + segs[i & 1] |= BIT(m_latch[i / 52], i % 52) << (i >> 1); + + for (int i = 0; i < 2; i++) + m_write_segs(i, m_blank ? 0 : segs[i]); + } + else + { + // 1/1 duty + m_write_segs(0, m_blank ? 0 : m_latch[0] & ((1ULL << 53) - 1)); + m_write_segs(1, 0); + } +} + +void lc7580_device::clk_w(int state) +{ + state = (state) ? 1 : 0; + + // clock shift register + if (state && !m_clk) + m_shift = m_shift >> 1 | u64(m_data) << 55; + + m_clk = state; +} + +void lc7580_device::ce_w(int state) +{ + state = (state) ? 1 : 0; + + // latch at falling edge + if (!state && m_ce) + { + // d0-d52: segment data + // d53(0): DP (drive mode select, aka duty) + // d54(0): DQ (AD/DSP function) + // d55: latch select + m_latch[BIT(m_shift, 55)] = m_shift; + refresh_output(); + } + + m_ce = state; +} |