// 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
//-------------------------------------------------
const device_type RP5H01 = device_creator<rp5h01_device>;
rp5h01_device::rp5h01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, RP5H01, "RP5H01 6/7-bit Counter", tag, owner, clock, "rp5h01", __FILE__)
, 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;
}