mirror of
https://github.com/holub/mame
synced 2025-05-20 12:48:53 +03:00
(MESS) Modernized the at45dbxx device (nw)
This commit is contained in:
parent
b26d2ae6d5
commit
78987d2e6e
@ -12,13 +12,6 @@
|
||||
|
||||
#include "at45dbxx.h"
|
||||
|
||||
enum
|
||||
{
|
||||
TYPE_AT45DB041,
|
||||
TYPE_AT45DB081,
|
||||
TYPE_AT45DB161
|
||||
};
|
||||
|
||||
#define LOG_LEVEL 1
|
||||
#define _logerror(level,x) do { if (LOG_LEVEL > level) logerror x; } while (0)
|
||||
|
||||
@ -32,458 +25,351 @@ enum
|
||||
#define FLASH_MODE_SO 2 // output
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
struct AT45DBXX_PINS
|
||||
{
|
||||
int cs; // chip select
|
||||
int sck; // serial clock
|
||||
int si; // serial input
|
||||
int so; // serial output
|
||||
int wp; // write protect
|
||||
int reset; // reset
|
||||
int busy; // busy
|
||||
};
|
||||
|
||||
struct AT45DBXX_CMD
|
||||
{
|
||||
UINT8 data[8], size;
|
||||
};
|
||||
|
||||
struct AT45DBXX_IO
|
||||
{
|
||||
UINT8 *data;
|
||||
UINT32 size, pos;
|
||||
};
|
||||
|
||||
struct at45dbxx_t
|
||||
{
|
||||
UINT8 *data;
|
||||
UINT32 size;
|
||||
UINT32 pages, page_size;
|
||||
UINT8 mode, status, devid, *buffer1, *buffer2;
|
||||
AT45DBXX_PINS pin;
|
||||
UINT8 si_byte, si_bits, so_byte, so_bits;
|
||||
AT45DBXX_CMD cmd;
|
||||
AT45DBXX_IO io;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
INLINE at45dbxx_t *get_token(device_t *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == AT45DB041 || device->type() == AT45DB081 || device->type() == AT45DB161);
|
||||
|
||||
return (at45dbxx_t *) downcast<at45db041_device *>(device)->token();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
IMPLEMENTATION
|
||||
***************************************************************************/
|
||||
|
||||
static void common_start(device_t *device, int device_type)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
|
||||
_logerror( 0, ("at45dbxx_init (%d)\n", device_type));
|
||||
memset(flash, 0, sizeof(at45dbxx_t));
|
||||
switch (device_type)
|
||||
{
|
||||
case TYPE_AT45DB041 : flash->pages = 2048; flash->page_size = 264; flash->devid = 0x18; break;
|
||||
case TYPE_AT45DB081 : flash->pages = 4096; flash->page_size = 264; flash->devid = 0x20; break;
|
||||
case TYPE_AT45DB161 : flash->pages = 4096; flash->page_size = 528; flash->devid = 0x28; break;
|
||||
}
|
||||
flash->size = flash->pages * flash->page_size;
|
||||
flash->data = auto_alloc_array(device->machine(), UINT8, flash->size);
|
||||
flash->buffer1 = auto_alloc_array(device->machine(), UINT8, flash->page_size);
|
||||
flash->buffer2 = auto_alloc_array(device->machine(), UINT8, flash->page_size);
|
||||
|
||||
// data
|
||||
state_save_register_item_pointer(device->machine(), "at45dbxx", device->tag(), 0, flash->data, flash->size);
|
||||
// pins
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.cs);
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.sck);
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.si);
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.so);
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.wp);
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.reset);
|
||||
state_save_register_item(device->machine(), "at45dbxx", device->tag(), 0, flash->pin.busy);
|
||||
}
|
||||
|
||||
static DEVICE_START( at45db041 )
|
||||
{
|
||||
common_start(device, TYPE_AT45DB041);
|
||||
}
|
||||
|
||||
static DEVICE_START( at45db081 )
|
||||
{
|
||||
common_start(device, TYPE_AT45DB081);
|
||||
}
|
||||
|
||||
static DEVICE_START( at45db161 )
|
||||
{
|
||||
common_start(device, TYPE_AT45DB161);
|
||||
}
|
||||
|
||||
static DEVICE_RESET( at45dbxx )
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
_logerror( 1, ("at45dbxx_reset\n"));
|
||||
// mode
|
||||
flash->mode = FLASH_MODE_SI;
|
||||
// command
|
||||
memset( &flash->cmd.data[0], 0, sizeof( flash->cmd.data));
|
||||
flash->cmd.size = 0;
|
||||
// input/output
|
||||
flash->io.data = NULL;
|
||||
flash->io.size = 0;
|
||||
flash->io.pos = 0;
|
||||
// pins
|
||||
flash->pin.cs = 0;
|
||||
flash->pin.sck = 0;
|
||||
flash->pin.si = 0;
|
||||
flash->pin.so = 0;
|
||||
flash->pin.wp = 0;
|
||||
flash->pin.reset = 0;
|
||||
flash->pin.busy = 0;
|
||||
// output
|
||||
flash->so_byte = 0;
|
||||
flash->so_bits = 0;
|
||||
// input
|
||||
flash->si_byte = 0;
|
||||
flash->si_bits = 0;
|
||||
}
|
||||
|
||||
static UINT8 at45dbxx_read_byte( device_t *device)
|
||||
{
|
||||
UINT8 data;
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
// check mode
|
||||
if ((flash->mode != FLASH_MODE_SO) || (!flash->io.data)) return 0;
|
||||
// read byte
|
||||
data = flash->io.data[flash->io.pos++];
|
||||
_logerror( 2, ("at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, flash->io.pos, flash->io.size));
|
||||
if (flash->io.pos == flash->io.size) flash->io.pos = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
static void flash_set_io( device_t *device, UINT8* data, UINT32 size, UINT32 pos)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
flash->io.data = data;
|
||||
flash->io.size = size;
|
||||
flash->io.pos = pos;
|
||||
}
|
||||
|
||||
static UINT32 flash_get_page_addr( device_t *device)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
switch (flash->devid)
|
||||
{
|
||||
case 0x18 : return ((flash->cmd.data[1] & 0x0F) << 7) | ((flash->cmd.data[2] & 0xFE) >> 1);
|
||||
case 0x20 : return ((flash->cmd.data[1] & 0x1F) << 7) | ((flash->cmd.data[2] & 0xFE) >> 1);
|
||||
case 0x28 : return ((flash->cmd.data[1] & 0x3F) << 6) | ((flash->cmd.data[2] & 0xFC) >> 2);
|
||||
default : return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 flash_get_byte_addr( device_t *device)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
switch (flash->devid)
|
||||
{
|
||||
case 0x18 : // fall-through
|
||||
case 0x20 : return ((flash->cmd.data[2] & 0x01) << 8) | ((flash->cmd.data[3] & 0xFF) >> 0);
|
||||
case 0x28 : return ((flash->cmd.data[2] & 0x03) << 8) | ((flash->cmd.data[3] & 0xFF) >> 0);
|
||||
default : return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void at45dbxx_write_byte(device_t *device, UINT8 data)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
// check mode
|
||||
if (flash->mode != FLASH_MODE_SI) return;
|
||||
// process byte
|
||||
if (flash->cmd.size < 8)
|
||||
{
|
||||
UINT8 opcode;
|
||||
_logerror( 2, ("at45dbxx_write_byte (%02X)\n", data));
|
||||
// add to command buffer
|
||||
flash->cmd.data[flash->cmd.size++] = data;
|
||||
// check opcode
|
||||
opcode = flash->cmd.data[0];
|
||||
switch (opcode)
|
||||
{
|
||||
// status register read
|
||||
case FLASH_CMD_57 :
|
||||
{
|
||||
// 8 bits command
|
||||
if (flash->cmd.size == 1)
|
||||
{
|
||||
_logerror( 1, ("at45dbxx opcode %02X - status register read\n", opcode));
|
||||
flash->status = (flash->status & 0xC7) | flash->devid; // 80 = busy / 40 = compare fail
|
||||
flash_set_io( device, &flash->status, 1, 0);
|
||||
flash->mode = FLASH_MODE_SO;
|
||||
flash->cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// main memory page to buffer 1 compare
|
||||
case FLASH_CMD_60 :
|
||||
{
|
||||
// 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care
|
||||
if (flash->cmd.size == 4)
|
||||
{
|
||||
UINT32 page;
|
||||
UINT8 comp;
|
||||
page = flash_get_page_addr(device);
|
||||
_logerror( 1, ("at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page));
|
||||
comp = memcmp( flash->data + page * flash->page_size, flash->buffer1, flash->page_size) == 0 ? 0 : 1;
|
||||
if (comp) flash->status |= 0x40; else flash->status &= ~0x40;
|
||||
_logerror( 1, ("at45dbxx page compare %s\n", comp ? "failure" : "success"));
|
||||
flash->mode = FLASH_MODE_SI;
|
||||
flash->cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// main memory page read
|
||||
case FLASH_CMD_52 :
|
||||
{
|
||||
// 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care
|
||||
if (flash->cmd.size == 8)
|
||||
{
|
||||
UINT32 page, byte;
|
||||
page = flash_get_page_addr(device);
|
||||
byte = flash_get_byte_addr(device);
|
||||
_logerror( 1, ("at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte));
|
||||
flash_set_io( device, flash->data + page * flash->page_size, flash->page_size, byte);
|
||||
flash->mode = FLASH_MODE_SO;
|
||||
flash->cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// main memory page program through buffer 1
|
||||
case FLASH_CMD_82 :
|
||||
{
|
||||
// 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address
|
||||
if (flash->cmd.size == 4)
|
||||
{
|
||||
UINT32 page, byte;
|
||||
page = flash_get_page_addr(device);
|
||||
byte = flash_get_byte_addr(device);
|
||||
_logerror( 1, ("at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte));
|
||||
flash_set_io( device, flash->buffer1, flash->page_size, byte);
|
||||
memset( flash->buffer1, 0xFF, flash->page_size);
|
||||
flash->mode = FLASH_MODE_SI;
|
||||
flash->cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// other
|
||||
default :
|
||||
{
|
||||
_logerror( 1, ("at45dbxx opcode %02X - unknown\n", opcode));
|
||||
flash->cmd.data[0] = 0;
|
||||
flash->cmd.size = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logerror( 2, ("at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, flash->io.pos + 1, flash->io.size));
|
||||
// store byte
|
||||
flash->io.data[flash->io.pos] = data;
|
||||
flash->io.pos++;
|
||||
if (flash->io.pos == flash->io.size) flash->io.pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int at45dbxx_pin_so( device_t *device)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
if (flash->pin.cs == 0) return 0;
|
||||
return flash->pin.so;
|
||||
}
|
||||
|
||||
void at45dbxx_pin_si(device_t *device, int data)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
if (flash->pin.cs == 0) return;
|
||||
flash->pin.si = data;
|
||||
}
|
||||
|
||||
void at45dbxx_pin_cs(device_t *device, int data)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
// check if changed
|
||||
if (flash->pin.cs == data) return;
|
||||
// cs low-to-high
|
||||
if (data != 0)
|
||||
{
|
||||
// complete program command
|
||||
if ((flash->cmd.size >= 4) && (flash->cmd.data[0] == FLASH_CMD_82))
|
||||
{
|
||||
UINT32 page, byte;
|
||||
page = flash_get_page_addr(device);
|
||||
byte = flash_get_byte_addr(device);
|
||||
_logerror( 1, ("at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte));
|
||||
memcpy( flash->data + page * flash->page_size, flash->buffer1, flash->page_size);
|
||||
}
|
||||
// reset
|
||||
DEVICE_RESET_CALL( at45dbxx );
|
||||
}
|
||||
// save cs
|
||||
flash->pin.cs = data;
|
||||
}
|
||||
|
||||
void at45dbxx_pin_sck(device_t *device, int data)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
// check if changed
|
||||
if (flash->pin.sck == data) return;
|
||||
// sck high-to-low
|
||||
if (data == 0)
|
||||
{
|
||||
// output (part 1)
|
||||
if (flash->so_bits == 8)
|
||||
{
|
||||
flash->so_bits = 0;
|
||||
flash->so_byte = at45dbxx_read_byte(device);
|
||||
}
|
||||
// input
|
||||
if (flash->pin.si) flash->si_byte = flash->si_byte | (1 << flash->si_bits);
|
||||
flash->si_bits++;
|
||||
if (flash->si_bits == 8)
|
||||
{
|
||||
flash->si_bits = 0;
|
||||
at45dbxx_write_byte( device, flash->si_byte);
|
||||
flash->si_byte = 0;
|
||||
}
|
||||
// output (part 2)
|
||||
flash->pin.so = (flash->so_byte >> flash->so_bits) & 1;
|
||||
flash->so_bits++;
|
||||
}
|
||||
// save sck
|
||||
flash->pin.sck = data;
|
||||
}
|
||||
|
||||
void at45dbxx_load(device_t *device, emu_file *file)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
_logerror( 0, ("at45dbxx_load (%p)\n", file));
|
||||
file->read(flash->data, flash->size);
|
||||
}
|
||||
|
||||
void at45dbxx_save(device_t *device, emu_file *file)
|
||||
{
|
||||
at45dbxx_t *flash = get_token(device);
|
||||
_logerror( 0, ("at45dbxx_save (%p)\n", file));
|
||||
file->write(flash->data, flash->size);
|
||||
}
|
||||
|
||||
#ifdef UNUSED_FUNCTION
|
||||
NVRAM_HANDLER( at45dbxx )
|
||||
{
|
||||
_logerror( 0, ("nvram_handler_at45dbxx (%p/%d)\n", file, read_or_write));
|
||||
if (read_or_write)
|
||||
{
|
||||
at45dbxx_save( file);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
at45dbxx_load( file);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( flash->data, 0xFF, flash->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
// device type definition
|
||||
const device_type AT45DB041 = &device_creator<at45db041_device>;
|
||||
const device_type AT45DB081 = &device_creator<at45db081_device>;
|
||||
const device_type AT45DB161 = &device_creator<at45db161_device>;
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// at45db041_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
at45db041_device::at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, AT45DB041, "AT45DB041", tag, owner, clock)
|
||||
: device_t(mconfig, AT45DB041, "AT45DB041", tag, owner, clock),
|
||||
device_nvram_interface(mconfig, *this)
|
||||
{
|
||||
m_token = global_alloc_clear(at45dbxx_t);
|
||||
}
|
||||
|
||||
|
||||
at45db041_device::at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, type, name, tag, owner, clock)
|
||||
{
|
||||
m_token = global_alloc_clear(at45dbxx_t);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void at45db041_device::device_config_complete()
|
||||
: device_t(mconfig, type, name, tag, owner, clock),
|
||||
device_nvram_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
at45db081_device::at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: at45db041_device(mconfig, AT45DB081, "AT45DB081", tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
at45db161_device::at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: at45db041_device(mconfig, AT45DB161, "AT45DB161", tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void at45db041_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( at45db041 )(this);
|
||||
m_size = num_pages() * page_size();
|
||||
m_data = auto_alloc_array(machine(), UINT8, m_size);
|
||||
m_buffer1 = auto_alloc_array(machine(), UINT8, page_size());
|
||||
m_buffer2 = auto_alloc_array(machine(), UINT8, page_size());
|
||||
|
||||
// data
|
||||
save_pointer(NAME(m_data), m_size);
|
||||
// pins
|
||||
save_item(NAME(m_pin.cs));
|
||||
save_item(NAME(m_pin.sck));
|
||||
save_item(NAME(m_pin.si));
|
||||
save_item(NAME(m_pin.so));
|
||||
save_item(NAME(m_pin.wp));
|
||||
save_item(NAME(m_pin.reset));
|
||||
save_item(NAME(m_pin.busy));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void at45db041_device::device_reset()
|
||||
{
|
||||
DEVICE_RESET_NAME( at45dbxx )(this);
|
||||
_logerror( 1, ("at45dbxx_reset\n"));
|
||||
// mode
|
||||
m_mode = FLASH_MODE_SI;
|
||||
// command
|
||||
memset(&m_cmd.data[0], 0, sizeof(m_cmd.data));
|
||||
m_cmd.size = 0;
|
||||
// input/output
|
||||
m_io.data = NULL;
|
||||
m_io.size = 0;
|
||||
m_io.pos = 0;
|
||||
// pins
|
||||
m_pin.cs = 0;
|
||||
m_pin.sck = 0;
|
||||
m_pin.si = 0;
|
||||
m_pin.so = 0;
|
||||
m_pin.wp = 0;
|
||||
m_pin.reset = 0;
|
||||
m_pin.busy = 0;
|
||||
// output
|
||||
m_so_byte = 0;
|
||||
m_so_bits = 0;
|
||||
// input
|
||||
m_si_byte = 0;
|
||||
m_si_bits = 0;
|
||||
}
|
||||
|
||||
|
||||
const device_type AT45DB081 = &device_creator<at45db081_device>;
|
||||
//-------------------------------------------------
|
||||
// nvram_default - called to initialize NVRAM to
|
||||
// its default state
|
||||
//-------------------------------------------------
|
||||
|
||||
at45db081_device::at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: at45db041_device(mconfig, AT45DB081, "AT45DB081", tag, owner, clock)
|
||||
void at45db041_device::nvram_default()
|
||||
{
|
||||
memset(m_data, 0xff, m_size);
|
||||
|
||||
if (region() != NULL)
|
||||
{
|
||||
UINT32 bytes = region()->bytes();
|
||||
if (bytes > m_size)
|
||||
bytes = m_size;
|
||||
|
||||
memcpy(m_data, region()->base(), bytes);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
// nvram_read - called to read NVRAM from the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void at45db081_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( at45db081 )(this);
|
||||
}
|
||||
|
||||
|
||||
const device_type AT45DB161 = &device_creator<at45db161_device>;
|
||||
|
||||
at45db161_device::at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: at45db041_device(mconfig, AT45DB161, "AT45DB161", tag, owner, clock)
|
||||
void at45db041_device::nvram_read(emu_file &file)
|
||||
{
|
||||
file.read(m_data, m_size);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
// nvram_write - called to write NVRAM to the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void at45db161_device::device_start()
|
||||
void at45db041_device::nvram_write(emu_file &file)
|
||||
{
|
||||
DEVICE_START_NAME( at45db161 )(this);
|
||||
file.write(m_data, m_size);
|
||||
}
|
||||
|
||||
UINT8 at45db041_device::read_byte()
|
||||
{
|
||||
UINT8 data;
|
||||
// check mode
|
||||
if ((m_mode != FLASH_MODE_SO) || (!m_io.data)) return 0;
|
||||
// read byte
|
||||
data = m_io.data[m_io.pos++];
|
||||
_logerror( 2, ("at45dbxx_read_byte (%02X) (%03d/%03d)\n", data, m_io.pos, m_io.size));
|
||||
if (m_io.pos == m_io.size) m_io.pos = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
void at45db041_device::flash_set_io(UINT8* data, UINT32 size, UINT32 pos)
|
||||
{
|
||||
m_io.data = data;
|
||||
m_io.size = size;
|
||||
m_io.pos = pos;
|
||||
}
|
||||
|
||||
UINT32 at45db041_device::flash_get_page_addr()
|
||||
{
|
||||
return ((m_cmd.data[1] & 0x0F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1);
|
||||
}
|
||||
|
||||
UINT32 at45db041_device::flash_get_byte_addr()
|
||||
{
|
||||
return ((m_cmd.data[2] & 0x01) << 8) | ((m_cmd.data[3] & 0xFF) >> 0);
|
||||
}
|
||||
|
||||
UINT32 at45db081_device::flash_get_page_addr()
|
||||
{
|
||||
return ((m_cmd.data[1] & 0x1F) << 7) | ((m_cmd.data[2] & 0xFE) >> 1);
|
||||
}
|
||||
|
||||
UINT32 at45db161_device::flash_get_page_addr()
|
||||
{
|
||||
return ((m_cmd.data[1] & 0x3F) << 6) | ((m_cmd.data[2] & 0xFC) >> 2);
|
||||
}
|
||||
|
||||
UINT32 at45db161_device::flash_get_byte_addr()
|
||||
{
|
||||
return ((m_cmd.data[2] & 0x03) << 8) | ((m_cmd.data[3] & 0xFF) >> 0);
|
||||
}
|
||||
|
||||
void at45db041_device::write_byte(UINT8 data)
|
||||
{
|
||||
// check mode
|
||||
if (m_mode != FLASH_MODE_SI) return;
|
||||
// process byte
|
||||
if (m_cmd.size < 8)
|
||||
{
|
||||
UINT8 opcode;
|
||||
_logerror( 2, ("at45dbxx_write_byte (%02X)\n", data));
|
||||
// add to command buffer
|
||||
m_cmd.data[m_cmd.size++] = data;
|
||||
// check opcode
|
||||
opcode = m_cmd.data[0];
|
||||
switch (opcode)
|
||||
{
|
||||
// status register read
|
||||
case FLASH_CMD_57 :
|
||||
{
|
||||
// 8 bits command
|
||||
if (m_cmd.size == 1)
|
||||
{
|
||||
_logerror( 1, ("at45dbxx opcode %02X - status register read\n", opcode));
|
||||
m_status = (m_status & 0xC7) | device_id(); // 80 = busy / 40 = compare fail
|
||||
flash_set_io(&m_status, 1, 0);
|
||||
m_mode = FLASH_MODE_SO;
|
||||
m_cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// main memory page to buffer 1 compare
|
||||
case FLASH_CMD_60 :
|
||||
{
|
||||
// 8 bits command + 4 bits reserved + 11 bits page address + 9 bits don't care
|
||||
if (m_cmd.size == 4)
|
||||
{
|
||||
UINT32 page;
|
||||
UINT8 comp;
|
||||
page = flash_get_page_addr();
|
||||
_logerror( 1, ("at45dbxx opcode %02X - main memory page to buffer 1 compare [%04X]\n", opcode, page));
|
||||
comp = memcmp( m_data + page * page_size(), m_buffer1, page_size()) == 0 ? 0 : 1;
|
||||
if (comp) m_status |= 0x40; else m_status &= ~0x40;
|
||||
_logerror( 1, ("at45dbxx page compare %s\n", comp ? "failure" : "success"));
|
||||
m_mode = FLASH_MODE_SI;
|
||||
m_cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// main memory page read
|
||||
case FLASH_CMD_52 :
|
||||
{
|
||||
// 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address + 32 bits don't care
|
||||
if (m_cmd.size == 8)
|
||||
{
|
||||
UINT32 page, byte;
|
||||
page = flash_get_page_addr();
|
||||
byte = flash_get_byte_addr();
|
||||
_logerror( 1, ("at45dbxx opcode %02X - main memory page read [%04X/%04X]\n", opcode, page, byte));
|
||||
flash_set_io(m_data + page * page_size(), page_size(), byte);
|
||||
m_mode = FLASH_MODE_SO;
|
||||
m_cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// main memory page program through buffer 1
|
||||
case FLASH_CMD_82 :
|
||||
{
|
||||
// 8 bits command + 4 bits reserved + 11 bits page address + 9 bits buffer address
|
||||
if (m_cmd.size == 4)
|
||||
{
|
||||
UINT32 page, byte;
|
||||
page = flash_get_page_addr();
|
||||
byte = flash_get_byte_addr();
|
||||
_logerror( 1, ("at45dbxx opcode %02X - main memory page program through buffer 1 [%04X/%04X]\n",opcode, page, byte));
|
||||
flash_set_io(m_buffer1, page_size(), byte);
|
||||
memset( m_buffer1, 0xFF, page_size());
|
||||
m_mode = FLASH_MODE_SI;
|
||||
m_cmd.size = 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// other
|
||||
default :
|
||||
{
|
||||
_logerror( 1, ("at45dbxx opcode %02X - unknown\n", opcode));
|
||||
m_cmd.data[0] = 0;
|
||||
m_cmd.size = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logerror( 2, ("at45dbxx_write_byte (%02X) (%03d/%03d)\n", data, m_io.pos + 1, m_io.size));
|
||||
// store byte
|
||||
m_io.data[m_io.pos] = data;
|
||||
m_io.pos++;
|
||||
if (m_io.pos == m_io.size) m_io.pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(at45db041_device::so_r)
|
||||
{
|
||||
if (m_pin.cs == 0) return 0;
|
||||
return m_pin.so;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(at45db041_device::si_w)
|
||||
{
|
||||
if (m_pin.cs == 0) return;
|
||||
m_pin.si = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(at45db041_device::cs_w)
|
||||
{
|
||||
// check if changed
|
||||
if (m_pin.cs == state) return;
|
||||
// cs low-to-high
|
||||
if (state != 0)
|
||||
{
|
||||
// complete program command
|
||||
if ((m_cmd.size >= 4) && (m_cmd.data[0] == FLASH_CMD_82))
|
||||
{
|
||||
UINT32 page, byte;
|
||||
page = flash_get_page_addr();
|
||||
byte = flash_get_byte_addr();
|
||||
_logerror( 1, ("at45dbxx - program data stored in buffer 1 into selected page in main memory [%04X/%04X]\n", page, byte));
|
||||
memcpy( m_data + page * page_size(), m_buffer1, page_size());
|
||||
}
|
||||
// reset
|
||||
at45db041_device::device_reset();
|
||||
}
|
||||
// save cs
|
||||
m_pin.cs = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(at45db041_device::sck_w)
|
||||
{
|
||||
// check if changed
|
||||
if (m_pin.sck == state) return;
|
||||
// sck high-to-low
|
||||
if (state == 0)
|
||||
{
|
||||
// output (part 1)
|
||||
if (m_so_bits == 8)
|
||||
{
|
||||
m_so_bits = 0;
|
||||
m_so_byte = read_byte();
|
||||
}
|
||||
// input
|
||||
if (m_pin.si) m_si_byte = m_si_byte | (1 << m_si_bits);
|
||||
m_si_bits++;
|
||||
if (m_si_bits == 8)
|
||||
{
|
||||
m_si_bits = 0;
|
||||
write_byte(m_si_byte);
|
||||
m_si_byte = 0;
|
||||
}
|
||||
// output (part 2)
|
||||
m_pin.so = (m_so_byte >> m_so_bits) & 1;
|
||||
m_so_bits++;
|
||||
}
|
||||
// save sck
|
||||
m_pin.sck = state;
|
||||
}
|
||||
|
@ -16,77 +16,127 @@
|
||||
#include "emu.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
|
||||
class at45db041_device : public device_t
|
||||
{
|
||||
public:
|
||||
at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
~at45db041_device() { global_free(m_token); }
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
private:
|
||||
// internal state
|
||||
void *m_token;
|
||||
};
|
||||
|
||||
extern const device_type AT45DB041;
|
||||
|
||||
//**************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_AT45DB041_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, AT45DB041, 0)
|
||||
class at45db081_device : public at45db041_device
|
||||
{
|
||||
public:
|
||||
at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
};
|
||||
|
||||
extern const device_type AT45DB081;
|
||||
|
||||
|
||||
#define MCFG_AT45DB081_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, AT45DB081, 0)
|
||||
class at45db161_device : public at45db041_device
|
||||
{
|
||||
public:
|
||||
at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
};
|
||||
|
||||
extern const device_type AT45DB161;
|
||||
|
||||
|
||||
#define MCFG_AT45DB161_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, AT45DB161, 0)
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
// pins
|
||||
void at45dbxx_pin_cs(device_t *device, int data);
|
||||
void at45dbxx_pin_sck(device_t *device, int data);
|
||||
void at45dbxx_pin_si(device_t *device, int data);
|
||||
int at45dbxx_pin_so(device_t *device);
|
||||
|
||||
// load/save
|
||||
void at45dbxx_load(device_t *device, emu_file *file);
|
||||
void at45dbxx_save(device_t *device, emu_file *file);
|
||||
// ======================> at45db041_device
|
||||
|
||||
// non-volatile ram handler
|
||||
//NVRAM_HANDLER( at45dbxx );
|
||||
class at45db041_device : public device_t,
|
||||
public device_nvram_interface
|
||||
{
|
||||
public:
|
||||
at45db041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
at45db041_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(cs_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(sck_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(si_w);
|
||||
DECLARE_READ_LINE_MEMBER(so_r);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_nvram_interface overrides
|
||||
virtual void nvram_default();
|
||||
virtual void nvram_read(emu_file &file);
|
||||
virtual void nvram_write(emu_file &file);
|
||||
|
||||
protected:
|
||||
virtual int num_pages() const { return 2048; }
|
||||
virtual int page_size() const { return 264; }
|
||||
virtual UINT8 device_id() const { return 0x18; }
|
||||
|
||||
UINT8 read_byte();
|
||||
void flash_set_io(UINT8* data, UINT32 size, UINT32 pos);
|
||||
virtual UINT32 flash_get_page_addr();
|
||||
virtual UINT32 flash_get_byte_addr();
|
||||
void write_byte(UINT8 data);
|
||||
|
||||
// internal state
|
||||
UINT8 * m_data;
|
||||
UINT32 m_size;
|
||||
UINT8 m_mode;
|
||||
UINT8 m_status;
|
||||
UINT8 * m_buffer1;
|
||||
UINT8 * m_buffer2;
|
||||
UINT8 m_si_byte;
|
||||
UINT8 m_si_bits;
|
||||
UINT8 m_so_byte;
|
||||
UINT8 m_so_bits;
|
||||
|
||||
struct AT45DBXX_PINS
|
||||
{
|
||||
int cs; // chip select
|
||||
int sck; // serial clock
|
||||
int si; // serial input
|
||||
int so; // serial output
|
||||
int wp; // write protect
|
||||
int reset; // reset
|
||||
int busy; // busy
|
||||
} m_pin;
|
||||
|
||||
struct AT45DBXX_IO
|
||||
{
|
||||
UINT8 *data;
|
||||
UINT32 size;
|
||||
UINT32 pos;
|
||||
} m_io;
|
||||
|
||||
struct AT45DBXX_CMD
|
||||
{
|
||||
UINT8 data[8];
|
||||
UINT8 size;
|
||||
} m_cmd;
|
||||
};
|
||||
|
||||
// ======================> at45db081_device
|
||||
|
||||
class at45db081_device : public at45db041_device
|
||||
{
|
||||
public:
|
||||
at45db081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
protected:
|
||||
virtual int num_pages() const { return 4096; }
|
||||
virtual int page_size() const { return 264; }
|
||||
virtual UINT8 device_id() const { return 0x20; }
|
||||
|
||||
virtual UINT32 flash_get_page_addr();
|
||||
};
|
||||
|
||||
// ======================> at45db161_device
|
||||
|
||||
class at45db161_device : public at45db041_device
|
||||
{
|
||||
public:
|
||||
at45db161_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
protected:
|
||||
virtual int num_pages() const { return 4096; }
|
||||
virtual int page_size() const { return 528; }
|
||||
virtual UINT8 device_id() const { return 0x28; }
|
||||
|
||||
virtual UINT32 flash_get_page_addr();
|
||||
virtual UINT32 flash_get_byte_addr();
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type AT45DB041;
|
||||
extern const device_type AT45DB081;
|
||||
extern const device_type AT45DB161;
|
||||
|
||||
#endif
|
||||
|
@ -104,18 +104,6 @@ static int nvram_system_save( running_machine &machine, const char *name, nvram_
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void cybiko_at45dbxx_load(running_machine &machine, emu_file *file)
|
||||
{
|
||||
device_t *device = machine.device("flash1");
|
||||
at45dbxx_load(device, file);
|
||||
}
|
||||
|
||||
static void cybiko_at45dbxx_save(running_machine &machine, emu_file *file)
|
||||
{
|
||||
device_t *device = machine.device("flash1");
|
||||
at45dbxx_save(device, file);
|
||||
}
|
||||
|
||||
static void cybiko_sst39vfx_load(running_machine &machine, emu_file *file)
|
||||
{
|
||||
device_t *device = machine.device("flash2");
|
||||
@ -165,8 +153,6 @@ static void cybiko_ramdisk_save(running_machine &machine, emu_file *file)
|
||||
void cybiko_state::machine_start()
|
||||
{
|
||||
_logerror( 0, ("machine_start_cybikov1\n"));
|
||||
// serial dataflash
|
||||
nvram_system_load( machine(), "flash1", cybiko_at45dbxx_load, 1);
|
||||
// serial port
|
||||
cybiko_rs232_init(machine());
|
||||
// other
|
||||
@ -178,8 +164,6 @@ MACHINE_START_MEMBER(cybiko_state,cybikov2)
|
||||
device_t *flash2 = machine().device("flash2");
|
||||
|
||||
_logerror( 0, ("machine_start_cybikov2\n"));
|
||||
// serial dataflash
|
||||
nvram_system_load( machine(), "flash1", cybiko_at45dbxx_load, 1);
|
||||
// multi-purpose flash
|
||||
nvram_system_load( machine(), "flash2", cybiko_sst39vfx_load, 1);
|
||||
machine().root_device().membank( "bank2" )->set_base( sst39vfx_get_base(flash2));
|
||||
@ -233,8 +217,6 @@ MACHINE_RESET_MEMBER(cybiko_state,cybikoxt)
|
||||
void cybiko_state::machine_stop_cybikov1()
|
||||
{
|
||||
_logerror( 0, ("machine_stop_cybikov1\n"));
|
||||
// serial dataflash
|
||||
nvram_system_save( machine(), "flash1", cybiko_at45dbxx_save);
|
||||
// serial port
|
||||
cybiko_rs232_exit();
|
||||
}
|
||||
@ -242,8 +224,6 @@ void cybiko_state::machine_stop_cybikov1()
|
||||
void cybiko_state::machine_stop_cybikov2()
|
||||
{
|
||||
_logerror( 0, ("machine_stop_cybikov2\n"));
|
||||
// serial dataflash
|
||||
nvram_system_save( machine(), "flash1", cybiko_at45dbxx_save);
|
||||
// multi-purpose flash
|
||||
nvram_system_save( machine(), "flash2", cybiko_sst39vfx_save);
|
||||
// serial port
|
||||
@ -402,7 +382,7 @@ READ8_MEMBER( cybiko_state::cybikov1_io_reg_r )
|
||||
// serial dataflash
|
||||
case H8S_IO_PORT3 :
|
||||
{
|
||||
if (at45dbxx_pin_so(m_flash1))
|
||||
if (m_flash1->so_r())
|
||||
data |= H8S_P3_RXD1;
|
||||
}
|
||||
break;
|
||||
@ -448,7 +428,7 @@ READ8_MEMBER( cybiko_state::cybikov2_io_reg_r )
|
||||
// serial dataflash
|
||||
case H8S_IO_PORT3 :
|
||||
{
|
||||
if (at45dbxx_pin_so(m_flash1))
|
||||
if (m_flash1->so_r())
|
||||
data |= H8S_P3_RXD1;
|
||||
}
|
||||
break;
|
||||
@ -530,9 +510,9 @@ WRITE8_MEMBER( cybiko_state::cybikov1_io_reg_w )
|
||||
// serial dataflash
|
||||
case H8S_IO_P3DR :
|
||||
{
|
||||
at45dbxx_pin_cs (m_flash1, (data & H8S_P3_SCK0) ? 0 : 1);
|
||||
at45dbxx_pin_si (m_flash1, (data & H8S_P3_TXD1) ? 1 : 0);
|
||||
at45dbxx_pin_sck(m_flash1, (data & H8S_P3_SCK1) ? 1 : 0);
|
||||
m_flash1->cs_w ((data & H8S_P3_SCK0) ? 0 : 1);
|
||||
m_flash1->si_w ((data & H8S_P3_TXD1) ? 1 : 0);
|
||||
m_flash1->sck_w((data & H8S_P3_SCK1) ? 1 : 0);
|
||||
}
|
||||
break;
|
||||
// rs232
|
||||
@ -571,9 +551,9 @@ WRITE8_MEMBER( cybiko_state::cybikov2_io_reg_w )
|
||||
// serial dataflash
|
||||
case H8S_IO_P3DR :
|
||||
{
|
||||
at45dbxx_pin_cs (m_flash1, (data & H8S_P3_SCK0) ? 0 : 1);
|
||||
at45dbxx_pin_si (m_flash1, (data & H8S_P3_TXD1) ? 1 : 0);
|
||||
at45dbxx_pin_sck(m_flash1, (data & H8S_P3_SCK1) ? 1 : 0);
|
||||
m_flash1->cs_w ((data & H8S_P3_SCK0) ? 0 : 1);
|
||||
m_flash1->si_w ((data & H8S_P3_TXD1) ? 1 : 0);
|
||||
m_flash1->sck_w((data & H8S_P3_SCK1) ? 1 : 0);
|
||||
}
|
||||
break;
|
||||
// rs232
|
||||
|
Loading…
Reference in New Issue
Block a user