// license:BSD-3-Clause // copyright-holders:Aaron Giles /*************************************************************************** er2055.c GI 64 word x 8 bit electrically alterable read-only memory. Atari often called this part "137161-001" on their technical manuals, but their schematics usually called it by its proper ER-2055 name. ***************************************************************************/ #include "emu.h" #include "machine/er2055.h" #include "logmacro.h" //************************************************************************** // GLOBAL VARIABLES //************************************************************************** // device type definition DEFINE_DEVICE_TYPE(ER2055, er2055_device, "er2055", "ER2055 EAROM (64x8)") //************************************************************************** // LIVE DEVICE //************************************************************************** //------------------------------------------------- // er2055_device - constructor //------------------------------------------------- er2055_device::er2055_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, ER2055, tag, owner, clock), device_nvram_interface(mconfig, *this), m_default_data(*this, DEVICE_SELF, SIZE_DATA), m_control_state(0), m_address(0), m_data(0) { } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void er2055_device::device_start() { save_item(NAME(m_control_state)); save_item(NAME(m_address)); save_item(NAME(m_data)); m_rom_data = std::make_unique(SIZE_DATA); save_pointer(NAME(m_rom_data), SIZE_DATA); m_control_state = 0; } //------------------------------------------------- // nvram_default - called to initialize NVRAM to // its default state //------------------------------------------------- void er2055_device::nvram_default() { // default to all-0xff std::fill_n(&m_rom_data[0], SIZE_DATA, 0xff); // populate from a memory region if present if (m_default_data.found()) std::copy_n(&m_default_data[0], SIZE_DATA, &m_rom_data[0]); } //------------------------------------------------- // nvram_read - called to read NVRAM from the // .nv file //------------------------------------------------- void er2055_device::nvram_read(emu_file &file) { file.read(&m_rom_data[0], SIZE_DATA); } //------------------------------------------------- // nvram_write - called to write NVRAM to the // .nv file //------------------------------------------------- void er2055_device::nvram_write(emu_file &file) { file.write(&m_rom_data[0], SIZE_DATA); } //************************************************************************** // I/O OPERATIONS //************************************************************************** //------------------------------------------------- // set_control - set the control lines; these // must be done simultaneously because the chip // reacts to various combinations //------------------------------------------------- void er2055_device::set_control(uint8_t cs1, uint8_t cs2, uint8_t c1, uint8_t c2) { // create a new composite control state uint8_t oldstate = m_control_state; m_control_state = oldstate & CK; m_control_state |= (c1 != 0) ? C1 : 0; m_control_state |= (c2 != 0) ? C2 : 0; m_control_state |= (cs1 != 0) ? CS1 : 0; m_control_state |= (cs2 != 0) ? CS2 : 0; // if not selected, or if change from previous, we're done if ((m_control_state & (CS1 | CS2)) != (CS1 | CS2) || m_control_state == oldstate) return; update_state(); } //------------------------------------------------- // update_state - update internal state following // a transition on clock, control or chip select // lines based on what mode we're in //------------------------------------------------- void er2055_device::update_state() { switch (m_control_state & (C1 | C2)) { // write mode; erasing is required, so we perform an AND against previous // data to simulate incorrect behavior if erasing was not done case 0: m_rom_data[m_address] &= m_data; LOG("Write %02X = %02X\n", m_address, m_data); break; // erase mode case C2: m_rom_data[m_address] = 0xff; LOG("Erase %02X\n", m_address); break; } } //------------------------------------------------- // set_clk - set the CLK line, pulses on which // are required for every read operation and for // successive write or erase operations //------------------------------------------------- WRITE_LINE_MEMBER(er2055_device::set_clk) { uint8_t oldstate = m_control_state; if (state) m_control_state |= CK; else m_control_state &= ~CK; // updates occur on falling edge when chip is selected if ((m_control_state & (CS1 | CS2)) == (CS1 | CS2) && (m_control_state != oldstate) && !state) { // read mode (C2 is "Don't Care") if ((m_control_state & C1) == C1) { m_data = m_rom_data[m_address]; LOG("Read %02X = %02X\n", m_address, m_data); } update_state(); } }