modernized the RP5H01 device [Osso]

This commit is contained in:
Fabio Priuli 2013-05-30 12:50:30 +00:00
parent 8ed7d024d9
commit 963ab6495e
7 changed files with 210 additions and 268 deletions

View File

@ -3,10 +3,8 @@
RP5H01
TODO:
- convert to modern and follow the datasheet better (all dumps
presumably needs to be redone from scratch?)
2009-06 Converted to be a device
- follow the datasheet better (all dumps presumably needs to be redone
from scratch?)
***************************************************************************/
@ -14,219 +12,15 @@
#include "machine/rp5h01.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
/* these also work as the address masks */
enum {
COUNTER_MODE_6_BITS = 0x3f,
COUNTER_MODE_7_BITS = 0x7f
};
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct rp5h01_state
{
int counter;
int counter_mode; /* test pin */
int enabled; /* chip enable */
int old_reset; /* reset pin state (level-triggered) */
int old_clock; /* clock pin state (level-triggered) */
UINT8 *data;
};
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE rp5h01_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert((device->type() == RP5H01));
return (rp5h01_state *)downcast<rp5h01_device *>(device)->token();
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
rp5h01_enable_w
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER( rp5h01_enable_w )
{
rp5h01_state *rp5h01 = get_safe_token(device);
/* process the /CE signal and enable/disable the IC */
rp5h01->enabled = (data == 0) ? 1 : 0;
}
/*-------------------------------------------------
rp5h01_reset_w
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER( rp5h01_reset_w )
{
rp5h01_state *rp5h01 = get_safe_token(device);
int newstate = (data == 0) ? 0 : 1;
/* if it's not enabled, ignore */
if (!rp5h01->enabled)
return;
/* now look for a 0->1 transition */
if (rp5h01->old_reset == 0 && newstate == 1)
{
/* reset the counter */
rp5h01->counter = 0;
}
/* update the pin */
rp5h01->old_reset = newstate;
}
/*-------------------------------------------------
rp5h01_cs_w
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER( rp5h01_cs_w )
{
rp5h01_state *rp5h01 = get_safe_token(device);
/* if it's not enabled, ignore */
if (!rp5h01->enabled)
return;
if (data == 1)
{
/* reset the counter */
rp5h01->counter = 0;
}
}
/*-------------------------------------------------
rp5h01_clock_w
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER( rp5h01_clock_w )
{
rp5h01_state *rp5h01 = get_safe_token(device);
int newstate = (data == 0) ? 0 : 1;
/* if it's not enabled, ignore */
if (!rp5h01->enabled)
return;
/* now look for a 1->0 transition */
if (rp5h01->old_clock == 1 && newstate == 0)
{
/* increment the counter, and mask it with the mode */
rp5h01->counter++;
}
/* update the pin */
rp5h01->old_clock = newstate;
}
/*-------------------------------------------------
rp5h01_test_w
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER( rp5h01_test_w )
{
rp5h01_state *rp5h01 = get_safe_token(device);
/* if it's not enabled, ignore */
if (!rp5h01->enabled)
return;
/* process the test signal and change the counter mode */
rp5h01->counter_mode = (data == 0) ? COUNTER_MODE_6_BITS : COUNTER_MODE_7_BITS;
}
/*-------------------------------------------------
rp5h01_counter_r
-------------------------------------------------*/
READ8_DEVICE_HANDLER( rp5h01_counter_r )
{
rp5h01_state *rp5h01 = get_safe_token(device);
/* if it's not enabled, ignore */
if (!rp5h01->enabled)
return 0; /* ? (should be high impedance) */
/* return A5 */
return (rp5h01->counter >> 5) & 1;
}
/*-------------------------------------------------
rp5h01_data_r
-------------------------------------------------*/
READ8_DEVICE_HANDLER( rp5h01_data_r )
{
rp5h01_state *rp5h01 = get_safe_token(device);
int byte, bit;
/* if it's not enabled, ignore */
if (!rp5h01->enabled)
return 0; /* ? (should be high impedance) */
/* get the byte offset and bit offset */
byte = (rp5h01->counter & rp5h01->counter_mode) >> 3;
bit = 7 - (rp5h01->counter & 7);
/* return the data */
return (rp5h01->data[byte] >> bit) & 1;
}
/*-------------------------------------------------
DEVICE_START( rp5h01 )
-------------------------------------------------*/
static DEVICE_START( rp5h01 )
{
rp5h01_state *rp5h01 = get_safe_token(device);
assert(device->static_config() == NULL);
rp5h01->data = *device->region();
/* register for state saving */
device->save_item(NAME(rp5h01->counter));
device->save_item(NAME(rp5h01->counter_mode));
device->save_item(NAME(rp5h01->enabled));
device->save_item(NAME(rp5h01->old_reset));
device->save_item(NAME(rp5h01->old_clock));
}
/*-------------------------------------------------
DEVICE_RESET( rp5h01 )
-------------------------------------------------*/
static DEVICE_RESET( rp5h01 )
{
rp5h01_state *rp5h01 = get_safe_token(device);
rp5h01->counter = 0;
rp5h01->counter_mode = COUNTER_MODE_6_BITS;
rp5h01->enabled = 0;
rp5h01->old_reset = -1;
rp5h01->old_clock = -1;
}
//-------------------------------------------------
// 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 clock)
: device_t(mconfig, RP5H01, "RP5H01", tag, owner, clock)
{
m_token = global_alloc_clear(rp5h01_state);
}
//-------------------------------------------------
@ -245,7 +39,14 @@ void rp5h01_device::device_config_complete()
void rp5h01_device::device_start()
{
DEVICE_START_NAME( rp5h01 )(this);
m_data = *region();
/* 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));
}
//-------------------------------------------------
@ -254,5 +55,137 @@ void rp5h01_device::device_start()
void rp5h01_device::device_reset()
{
DEVICE_RESET_NAME( rp5h01 )(this);
m_counter = 0;
m_counter_mode = COUNTER_MODE_6_BITS;
m_enabled = 0;
m_old_reset = -1;
m_old_clock = -1;
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
enable_w
-------------------------------------------------*/
WRITE8_MEMBER( rp5h01_device::enable_w )
{
/* process the /CE signal and enable/disable the IC */
m_enabled = (data == 0) ? 1 : 0;
}
/*-------------------------------------------------
reset_w
-------------------------------------------------*/
WRITE8_MEMBER( rp5h01_device::reset_w )
{
int newstate = (data == 0) ? 0 : 1;
/* if it's not enabled, ignore */
if (!m_enabled)
return;
/* now look for a 0->1 transition */
if (m_old_reset == 0 && newstate == 1)
{
/* reset the counter */
m_counter = 0;
}
/* update the pin */
m_old_reset = newstate;
}
/*-------------------------------------------------
cs_w
-------------------------------------------------*/
WRITE8_MEMBER( rp5h01_device::cs_w )
{
/* if it's not enabled, ignore */
if (!m_enabled)
return;
if (data == 1)
{
/* reset the counter */
m_counter = 0;
}
}
/*-------------------------------------------------
clock_w
-------------------------------------------------*/
WRITE8_MEMBER( rp5h01_device::clock_w )
{
int newstate = (data == 0) ? 0 : 1;
/* if it's not enabled, ignore */
if (!m_enabled)
return;
/* now look for a 1->0 transition */
if (m_old_clock == 1 && newstate == 0)
{
/* increment the counter, and mask it with the mode */
m_counter++;
}
/* update the pin */
m_old_clock = newstate;
}
/*-------------------------------------------------
test_w
-------------------------------------------------*/
WRITE8_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 = (data == 0) ? COUNTER_MODE_6_BITS : COUNTER_MODE_7_BITS;
}
/*-------------------------------------------------
counter_r
-------------------------------------------------*/
READ8_MEMBER( rp5h01_device::counter_r )
{
/* if it's not enabled, ignore */
if (!m_enabled)
return 0; /* ? (should be high impedance) */
/* return A5 */
return (m_counter >> 5) & 1;
}
/*-------------------------------------------------
data_r
-------------------------------------------------*/
READ8_MEMBER( rp5h01_device::data_r )
{
int byte, bit;
/* if it's not enabled, ignore */
if (!m_enabled)
return 0; /* ? (should be high impedance) */
/* get the byte offset and bit offset */
byte = (m_counter & m_counter_mode) >> 3;
bit = 7 - (m_counter & 7);
/* return the data */
return (m_data[byte] >> bit) & 1;
}

View File

@ -8,7 +8,16 @@
#ifndef __RP5H01_H__
#define __RP5H01_H__
#include "devlegcy.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
/* these also work as the address masks */
enum {
COUNTER_MODE_6_BITS = 0x3f,
COUNTER_MODE_7_BITS = 0x7f
};
/***************************************************************************
MACROS / CONSTANTS
@ -18,10 +27,15 @@ class rp5h01_device : public device_t
{
public:
rp5h01_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~rp5h01_device() { global_free(m_token); }
DECLARE_WRITE8_MEMBER( enable_w ); /* /CE */
DECLARE_WRITE8_MEMBER( reset_w ); /* RESET */
DECLARE_WRITE8_MEMBER( cs_w ); /* CS */
DECLARE_WRITE8_MEMBER( clock_w ); /* DATA CLOCK (active low) */
DECLARE_WRITE8_MEMBER( test_w ); /* TEST */
DECLARE_READ8_MEMBER( counter_r ); /* COUNTER OUT */
DECLARE_READ8_MEMBER( data_r ); /* DATA */
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected:
// device-level overrides
virtual void device_config_complete();
@ -29,7 +43,12 @@ protected:
virtual void device_reset();
private:
// internal state
void *m_token;
int m_counter;
int m_counter_mode; /* test pin */
int m_enabled; /* chip enable */
int m_old_reset; /* reset pin state (level-triggered) */
int m_old_clock; /* clock pin state (level-triggered) */
UINT8 *m_data;
};
extern const device_type RP5H01;
@ -44,16 +63,4 @@ extern const device_type RP5H01;
* assigned to device.
*/
/***************************************************************************
PROTOTYPES
***************************************************************************/
DECLARE_WRITE8_DEVICE_HANDLER( rp5h01_enable_w ); /* /CE */
DECLARE_WRITE8_DEVICE_HANDLER( rp5h01_reset_w ); /* RESET */
DECLARE_WRITE8_DEVICE_HANDLER( rp5h01_cs_w ); /* CS */
DECLARE_WRITE8_DEVICE_HANDLER( rp5h01_clock_w ); /* DATA CLOCK (active low) */
DECLARE_WRITE8_DEVICE_HANDLER( rp5h01_test_w ); /* TEST */
DECLARE_READ8_DEVICE_HANDLER( rp5h01_counter_r ); /* COUNTER OUT */
DECLARE_READ8_DEVICE_HANDLER( rp5h01_data_r ); /* DATA */
#endif /* __RP5H01_H__ */

View File

@ -463,13 +463,13 @@ READ8_MEMBER(nss_state::nss_prot_r)
if (m_cart_sel == 0)
{
rp5h01_enable_w(m_rp5h01, space, 0, 0);
data |= ((~rp5h01_counter_r(m_rp5h01, space, 0)) << 4) & 0x10; /* D4 */
data |= ((rp5h01_data_r(m_rp5h01, space, 0)) << 3) & 0x08; /* D3 */
rp5h01_enable_w(m_rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 0);
data |= ((~m_rp5h01->counter_r(space, 0)) << 4) & 0x10; /* D4 */
data |= ((m_rp5h01->data_r(space, 0)) << 3) & 0x08; /* D3 */
m_rp5h01->enable_w(space, 0, 1);
}
else
rp5h01_enable_w(m_rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 1);
return data;
}
@ -478,14 +478,14 @@ WRITE8_MEMBER(nss_state::nss_prot_w)
{
if (m_cart_sel == 0)
{
rp5h01_enable_w(m_rp5h01, space, 0, 0);
rp5h01_test_w(m_rp5h01, space, 0, data & 0x10); /* D4 */
rp5h01_clock_w(m_rp5h01, space, 0, data & 0x08); /* D3 */
rp5h01_cs_w(m_rp5h01, space, 0, ~data & 0x01);
rp5h01_enable_w(m_rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 0);
m_rp5h01->test_w(space, 0, data & 0x10); /* D4 */
m_rp5h01->clock_w(space, 0, data & 0x08); /* D3 */
m_rp5h01->cs_w(space, 0, ~data & 0x01);
m_rp5h01->enable_w(space, 0, 1);
}
else
rp5h01_enable_w(m_rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 1);
ioport("EEPROMOUT")->write(data, 0xff);
}

View File

@ -141,7 +141,6 @@ Changes:
#include "cpu/m6502/n2a03.h"
#include "rendlay.h"
#include "video/ppu2c0x.h"
#include "machine/rp5h01.h"
#include "sound/dac.h"
#include "sound/nes_apu.h"
#include "includes/vsnes.h"

View File

@ -1,3 +1,5 @@
#include "machine/rp5h01.h"
struct chr_bank
{
int writable; // 1 for RAM, 0 for ROM
@ -9,12 +11,17 @@ class playch10_state : public driver_device
public:
playch10_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_rp5h01(*this, "rp5h01"),
m_ram_8w(*this, "ram_8w"),
m_videoram(*this, "videoram"),
m_timedata(*this, "timedata"),
m_work_ram(*this, "work_ram"),
m_maincpu(*this, "maincpu") { }
m_work_ram(*this, "work_ram")
{ }
required_device<cpu_device> m_maincpu;
optional_device<rp5h01_device> m_rp5h01;
required_shared_ptr<UINT8> m_ram_8w;
required_shared_ptr<UINT8> m_videoram;
required_shared_ptr<UINT8> m_timedata;
@ -125,7 +132,6 @@ public:
void gboard_scanline_cb( int scanline, int vblank, int blanked );
void ppu_irq(int *ppu_regs);
void mapper9_latch(offs_t offset);
required_device<cpu_device> m_maincpu;
};
/*----------- defined in video/playch10.c -----------*/

View File

@ -3,11 +3,15 @@ class vsnes_state : public driver_device
public:
vsnes_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_work_ram(*this, "work_ram"),
m_work_ram_1(*this, "work_ram_1"),
m_maincpu(*this, "maincpu"),
m_subcpu(*this, "sub") { }
m_subcpu(*this, "sub"),
m_work_ram(*this, "work_ram"),
m_work_ram_1(*this, "work_ram_1")
{ }
required_device<cpu_device> m_maincpu;
optional_device<cpu_device> m_subcpu;
required_shared_ptr<UINT8> m_work_ram;
optional_shared_ptr<UINT8> m_work_ram_1;
int m_coin;
@ -110,8 +114,6 @@ public:
void mapper4_irq( int scanline, int vblank, int blanked );
void ppu_irq_1(int *ppu_regs);
void ppu_irq_2(int *ppu_regs);
required_device<cpu_device> m_maincpu;
optional_device<cpu_device> m_subcpu;
};
/*----------- defined in video/vsnes.c -----------*/

View File

@ -1,6 +1,5 @@
#include "emu.h"
#include "video/ppu2c0x.h"
#include "machine/rp5h01.h"
#include "machine/nvram.h"
#include "includes/playch10.h"
@ -12,8 +11,6 @@
void playch10_state::machine_reset()
{
device_t *rp5h01 = machine().device("rp5h01");
/* initialize latches and flip-flops */
m_pc10_nmi_enable = m_pc10_dog_di = m_pc10_dispmask = m_pc10_sdcs = m_pc10_int_detect = 0;
@ -30,10 +27,10 @@ void playch10_state::machine_reset()
/* reset the security chip */
address_space &space = generic_space();
rp5h01_enable_w(rp5h01, space, 0, 0);
rp5h01_reset_w(rp5h01, space, 0, 0);
rp5h01_reset_w(rp5h01, space, 0, 1);
rp5h01_enable_w(rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 0);
m_rp5h01->reset_w(space, 0, 0);
m_rp5h01->reset_w(space, 0, 1);
m_rp5h01->enable_w(space, 0, 1);
pc10_set_mirroring(m_mirroring);
}
@ -158,31 +155,29 @@ WRITE8_MEMBER(playch10_state::pc10_CARTSEL_w)
READ8_MEMBER(playch10_state::pc10_prot_r)
{
device_t *rp5h01 = machine().device("rp5h01");
int data = 0xe7;
/* we only support a single cart connected at slot 0 */
if (m_cart_sel == 0)
{
rp5h01_enable_w(rp5h01, space, 0, 0);
data |= ((~rp5h01_counter_r(rp5h01, space, 0)) << 4) & 0x10; /* D4 */
data |= ((rp5h01_data_r(rp5h01, space, 0)) << 3) & 0x08; /* D3 */
rp5h01_enable_w(rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 0);
data |= ((~m_rp5h01->counter_r(space, 0)) << 4) & 0x10; /* D4 */
data |= ((m_rp5h01->data_r(space, 0)) << 3) & 0x08; /* D3 */
m_rp5h01->enable_w(space, 0, 1);
}
return data;
}
WRITE8_MEMBER(playch10_state::pc10_prot_w)
{
device_t *rp5h01 = machine().device("rp5h01");
/* we only support a single cart connected at slot 0 */
if (m_cart_sel == 0)
{
rp5h01_enable_w(rp5h01, space, 0, 0);
rp5h01_test_w(rp5h01, space, 0, data & 0x10); /* D4 */
rp5h01_clock_w(rp5h01, space, 0, data & 0x08); /* D3 */
rp5h01_reset_w(rp5h01, space, 0, ~data & 0x01); /* D0 */
rp5h01_enable_w(rp5h01, space, 0, 1);
m_rp5h01->enable_w(space, 0, 0);
m_rp5h01->test_w(space, 0, data & 0x10); /* D4 */
m_rp5h01->clock_w(space, 0, data & 0x08); /* D3 */
m_rp5h01->reset_w(space, 0, ~data & 0x01); /* D0 */
m_rp5h01->enable_w(space, 0, 1);
/* this thing gets dense at some point */
/* it wants to jump and execute an opcode at $ffff, wich */