// license:BSD-3-Clause // copyright-holders:Nicola Salmoria /*************************************************************************** RP5H01 - Ricoh 64x1bit(+8bit) PROM with 6/7-bit counter In reality, PROM data is 72bits (64 + 8bit 'dummy'). In 7-bit counter mode, from 64 to 127 (%1000000 to %1111111), the dummy bits are read repeatedly, with a mask of %1010111. For example if the 8 dummy bits are $7c, bits 64 to 127 are read as $7c $7c $00 $00 $7c $7c $00 $00. To simplify this, our emulation expects 'overdumps', 128bits total. TODO: - not sure if the polarity of our PROM dumps (playch10) is correct, same goes for the bit order (note: does not require new dumps) ***************************************************************************/ #include "emu.h" #include "machine/rp5h01.h" // this is the contents of an unprogrammed PROM uint8_t const rp5h01_device::s_initial_data[0x10] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 }; //------------------------------------------------- // rp5h01_device - constructor //------------------------------------------------- DEFINE_DEVICE_TYPE(RP5H01, rp5h01_device, "rp5h01", "RP5H01 6/7-bit Counter") rp5h01_device::rp5h01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, RP5H01, tag, owner, clock) , m_data(nullptr) , m_rom(*this, DEVICE_SELF, 0x10) { } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void rp5h01_device::device_start() { if (m_rom.found()) m_data = m_rom; else m_data = s_initial_data; /* register for state saving */ save_item(NAME(m_counter)); save_item(NAME(m_counter_mode)); save_item(NAME(m_enabled)); save_item(NAME(m_old_reset)); save_item(NAME(m_old_clock)); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void rp5h01_device::device_reset() { m_counter = 0; m_counter_mode = COUNTER_MODE_6_BITS; m_enabled = 0; m_old_reset = 0; m_old_clock = 0; } /*************************************************************************** IMPLEMENTATION ***************************************************************************/ /*------------------------------------------------- enable_w -------------------------------------------------*/ WRITE_LINE_MEMBER( rp5h01_device::enable_w ) { /* process the /CE signal and enable/disable the IC */ m_enabled = state ? 0 : 1; } /*------------------------------------------------- reset_w -------------------------------------------------*/ WRITE_LINE_MEMBER( rp5h01_device::reset_w ) { /* if it's not enabled, ignore */ if (!m_enabled) return; /* now look for a 0->1 transition */ if (!m_old_reset && state) { /* reset the counter */ m_counter = 0; } /* update the pin */ m_old_reset = state; } /*------------------------------------------------- cs_w -------------------------------------------------*/ WRITE_LINE_MEMBER( rp5h01_device::cs_w ) { /* if it's not enabled, ignore */ if (!m_enabled) return; if (state) { /* reset the counter */ m_counter = 0; } } /*------------------------------------------------- clock_w -------------------------------------------------*/ WRITE_LINE_MEMBER( rp5h01_device::clock_w ) { /* if it's not enabled, ignore */ if (!m_enabled) return; /* now look for a 1->0 transition */ if (m_old_clock && !state) { /* increment the counter, and mask it with the mode */ m_counter++; } /* update the pin */ m_old_clock = state; } /*------------------------------------------------- test_w -------------------------------------------------*/ WRITE_LINE_MEMBER( rp5h01_device::test_w ) { /* if it's not enabled, ignore */ if (!m_enabled) return; /* process the test signal and change the counter mode */ m_counter_mode = (state) ? COUNTER_MODE_7_BITS : COUNTER_MODE_6_BITS; } /*------------------------------------------------- counter_r -------------------------------------------------*/ READ_LINE_MEMBER( rp5h01_device::counter_r ) { /* if it's not enabled, ignore */ if (!m_enabled) return 1; /* high impedance */ /* return A5 */ return (m_counter >> 5) & 1; } /*------------------------------------------------- data_r -------------------------------------------------*/ READ_LINE_MEMBER( rp5h01_device::data_r ) { /* if it's not enabled, ignore */ if (!m_enabled) return 1; /* high impedance */ /* get the byte offset and bit offset */ int byte = (m_counter & m_counter_mode) >> 3; int bit = 7 - (m_counter & 7); /* return the data */ return (m_data[byte] >> bit) & 1; }