mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
Add DS1994 device (#5054)
Add DS1994 device amaticmg driver: added ds1994 device, modified prom load, added ds1994 to romload
This commit is contained in:
parent
bbb32eb832
commit
aff42a9969
@ -935,6 +935,18 @@ if (MACHINES["DS1386"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/ds1994.h,MACHINES["DS1994"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["DS1994"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/ds1994.cpp",
|
||||
MAME_DIR .. "src/devices/machine/ds1994.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/ds2401.h,MACHINES["DS2401"] = true
|
||||
|
@ -438,6 +438,7 @@ MACHINES["DS1205"] = true
|
||||
MACHINES["DS1302"] = true
|
||||
--MACHINES["DS1315"] = true
|
||||
--MACHINES["DS1386"] = true
|
||||
MACHINES["DS1994"] = true
|
||||
MACHINES["DS2401"] = true
|
||||
MACHINES["DS2404"] = true
|
||||
MACHINES["DS75160A"] = true
|
||||
|
798
src/devices/machine/ds1994.cpp
Normal file
798
src/devices/machine/ds1994.cpp
Normal file
@ -0,0 +1,798 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles, smf, Grull Osgo
|
||||
/*
|
||||
* DS1994
|
||||
*
|
||||
* Dallas Semiconductor
|
||||
* 1-Wire Protocol
|
||||
* RTC + BACKUP RAM
|
||||
*
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/ds1994.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define VERBOSE_LEVEL 0
|
||||
|
||||
inline void ds1994_device::verboselog(int n_level, const char *s_fmt, ...)
|
||||
{
|
||||
if ( VERBOSE_LEVEL >= n_level )
|
||||
{
|
||||
va_list v;
|
||||
char buf[32768];
|
||||
va_start(v, s_fmt);
|
||||
vsprintf(buf, s_fmt, v);
|
||||
va_end(v);
|
||||
logerror("ds1994 %s %s: %s", tag(), machine().describe_context(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(DS1994, ds1994_device, "ds1994", "DS1994 RTC + BACKUP RAM")
|
||||
|
||||
ds1994_device::ds1994_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, DS1994, tag, owner, clock), device_nvram_interface(mconfig, *this)
|
||||
, m_timer_main(nullptr)
|
||||
, m_timer_reset(nullptr)
|
||||
, m_timer_clock(nullptr)
|
||||
, m_ref_year(0)
|
||||
, m_ref_month(0)
|
||||
, m_ref_day(0)
|
||||
, m_address(0)
|
||||
, m_offset(0)
|
||||
, m_a1(0)
|
||||
, m_a2(0)
|
||||
, m_bit(0)
|
||||
, m_shift(0)
|
||||
, m_byte(0)
|
||||
, m_rx(false)
|
||||
, m_tx(false)
|
||||
, m_state_ptr(0)
|
||||
{
|
||||
memset(m_ram, 0, sizeof(m_ram));
|
||||
}
|
||||
|
||||
void ds1994_device::device_start()
|
||||
{
|
||||
// Reference time setup
|
||||
struct tm ref_tm;
|
||||
|
||||
memset(&ref_tm, 0, sizeof(ref_tm));
|
||||
ref_tm.tm_year = m_ref_year - 1900;
|
||||
ref_tm.tm_mon = m_ref_month - 1;
|
||||
ref_tm.tm_mday = m_ref_day;
|
||||
|
||||
time_t ref_time = mktime(&ref_tm);
|
||||
|
||||
time_t current_time;
|
||||
time(¤t_time);
|
||||
current_time -= ref_time;
|
||||
|
||||
m_rtc[0] = 0x0;
|
||||
m_rtc[1] = (current_time >> 0) & 0xff;
|
||||
m_rtc[2] = (current_time >> 8) & 0xff;
|
||||
m_rtc[3] = (current_time >> 16) & 0xff;
|
||||
m_rtc[4] = (current_time >> 24) & 0xff;
|
||||
|
||||
// 1-wire timmings
|
||||
t_samp = attotime::from_usec(30);
|
||||
t_rdv = attotime::from_usec(30);
|
||||
t_rstl = attotime::from_usec(480);
|
||||
t_pdh = attotime::from_usec(30);
|
||||
t_pdl = attotime::from_usec(120);
|
||||
|
||||
// 1-wire states
|
||||
m_rx = true;
|
||||
m_tx = true;
|
||||
|
||||
// 1-Wire related
|
||||
save_item(NAME(m_bit));
|
||||
save_item(NAME(m_byte));
|
||||
save_item(NAME(m_shift));
|
||||
save_item(NAME(m_rx));
|
||||
save_item(NAME(m_tx));
|
||||
|
||||
// ds1994 specific
|
||||
save_item(NAME(m_rom));
|
||||
save_item(NAME(m_sram));
|
||||
save_item(NAME(m_ram));
|
||||
save_item(NAME(m_rtc));
|
||||
save_item(NAME(m_address));
|
||||
save_item(NAME(m_a1));
|
||||
save_item(NAME(m_a2));
|
||||
save_item(NAME(m_offset));
|
||||
|
||||
// state machine
|
||||
save_item(NAME(m_state));
|
||||
save_item(NAME(m_state_ptr));
|
||||
for (auto & elem : m_state)
|
||||
elem = STATE_IDLE;
|
||||
|
||||
// timers
|
||||
m_timer_main = timer_alloc(TIMER_MAIN);
|
||||
m_timer_reset = timer_alloc(TIMER_RESET);
|
||||
m_timer_clock = timer_alloc(TIMER_CLOCK);
|
||||
|
||||
m_timer_clock->adjust(attotime::from_hz(256), 0, attotime::from_hz(256));
|
||||
}
|
||||
|
||||
void ds1994_device::device_reset()
|
||||
{
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_shift = 0;
|
||||
m_rx = true;
|
||||
m_tx = true;
|
||||
m_state_ptr = 0;
|
||||
m_state[m_state_ptr] = STATE_IDLE;
|
||||
|
||||
memory_region *region = memregion(DEVICE_SELF);
|
||||
if (region != nullptr)
|
||||
{
|
||||
if (region->bytes() == ROM_SIZE+SPD_SIZE+DATA_SIZE+RTC_SIZE+REGS_SIZE)
|
||||
{
|
||||
memcpy(m_rom, region->base(), ROM_SIZE);
|
||||
memcpy(m_ram , region->base() + ROM_SIZE, SPD_SIZE);
|
||||
memcpy(m_sram, region->base() + ROM_SIZE+SPD_SIZE, DATA_SIZE);
|
||||
memcpy(m_rtc , region->base() + ROM_SIZE+SPD_SIZE+DATA_SIZE, RTC_SIZE);
|
||||
memcpy(m_regs, region->base() + ROM_SIZE+SPD_SIZE+DATA_SIZE+RTC_SIZE, REGS_SIZE);
|
||||
return;
|
||||
}
|
||||
verboselog(0, "ds1994 %s: Wrong region length for data, expected 0x%x, got 0x%x\n", tag(), ROM_SIZE+SPD_SIZE+DATA_SIZE+RTC_SIZE+REGS_SIZE, region->bytes());
|
||||
}
|
||||
else
|
||||
{
|
||||
verboselog(0, "ds1994 %s: Warning, no id provided, answer will be all zeroes.\n", tag());
|
||||
memset(m_rom, 0, ROM_SIZE);
|
||||
memset(m_ram, 0, SPD_SIZE);
|
||||
memset(m_sram, 0, DATA_SIZE);
|
||||
memset(m_rtc, 0, RTC_SIZE);
|
||||
memset(m_regs, 0, REGS_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* */
|
||||
/* 1-wire protocol - Tx/Rx Bit Routines */
|
||||
/* */
|
||||
/********************************************/
|
||||
|
||||
bool ds1994_device::one_wire_tx_bit(uint8_t value)
|
||||
{
|
||||
if (!m_bit)
|
||||
{
|
||||
m_shift = value;
|
||||
verboselog(1, "one_wire_tx_bit: Byte to send %02x\n", m_shift);
|
||||
}
|
||||
m_tx = m_shift & 1;
|
||||
m_shift >>= 1;
|
||||
verboselog(1, "one_wire_tx_bit: State %d\n", m_tx);
|
||||
m_bit++;
|
||||
if (m_bit == 8) return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ds1994_device::one_wire_rx_bit(void)
|
||||
{
|
||||
m_shift >>= 1;
|
||||
if (m_rx)
|
||||
{
|
||||
m_shift |= 0x80;
|
||||
}
|
||||
verboselog(1, "one_wire_rx_bit: State %d\n", m_rx);
|
||||
m_bit++;
|
||||
if (m_bit == 8)
|
||||
{
|
||||
verboselog(1, "one_wire_rx_bit: Byte Received %02x\n", m_shift);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* */
|
||||
/* Internal states - Rom Commands */
|
||||
/* */
|
||||
/********************************************/
|
||||
|
||||
void ds1994_device::ds1994_rom_cmd(void)
|
||||
{
|
||||
verboselog(2, "timer_main state_rom_command\n");
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
switch (m_shift)
|
||||
{
|
||||
case ROMCMD_READROM:
|
||||
verboselog(1, "timer_main rom_cmd readrom\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_state[0] = STATE_READROM;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
case ROMCMD_SKIPROM:
|
||||
verboselog(1, "timer_main rom_cmd skiprom\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_state[0] = STATE_COMMAND;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
case ROMCMD_MATCHROM:
|
||||
verboselog(1, "timer_main rom_cmd matchrom\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_state[0] = STATE_MATCHROM;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
case ROMCMD_SEARCHROM:
|
||||
case ROMCMD_SEARCHINT:
|
||||
verboselog(0, "timer_main rom_command not implemented %02x\n", m_shift);
|
||||
m_state[m_state_ptr] = STATE_COMMAND;
|
||||
default:
|
||||
verboselog(0, "timer_main rom_command not found %02x\n", m_shift);
|
||||
m_state[m_state_ptr] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* */
|
||||
/* Internal states - DS1994 Commands */
|
||||
/* */
|
||||
/********************************************/
|
||||
|
||||
void ds1994_device::ds1994_cmd(void)
|
||||
{
|
||||
verboselog(2, "timer_main state_command\n");
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
switch (m_shift)
|
||||
{
|
||||
case COMMAND_READ_MEMORY:
|
||||
verboselog(1, "timer_main cmd read_memory\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_state[0] = STATE_ADDRESS1;
|
||||
m_state[1] = STATE_ADDRESS2;
|
||||
m_state[2] = STATE_INIT_COMMAND;
|
||||
m_state[3] = STATE_READ_MEMORY;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
case COMMAND_WRITE_SCRATCHPAD:
|
||||
verboselog(1, "timer_main cmd write_scratchpad\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_offs_ro = false;
|
||||
m_state[0] = STATE_ADDRESS1;
|
||||
m_state[1] = STATE_ADDRESS2;
|
||||
m_state[2] = STATE_INIT_COMMAND;
|
||||
m_state[3] = STATE_WRITE_SCRATCHPAD;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
case COMMAND_READ_SCRATCHPAD:
|
||||
verboselog(1, "timer_main cmd read_scratchpad\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_state[0] = STATE_TXADDRESS1;
|
||||
m_state[1] = STATE_TXADDRESS2;
|
||||
m_state[2] = STATE_TXOFFSET;
|
||||
m_state[3] = STATE_INIT_COMMAND;
|
||||
m_state[4] = STATE_READ_SCRATCHPAD;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
case COMMAND_COPY_SCRATCHPAD:
|
||||
verboselog(1, "timer_main cmd copy_scratchpad\n");
|
||||
m_bit = 0;
|
||||
m_byte = 0;
|
||||
m_offs_ro = true;
|
||||
m_auth = true;
|
||||
m_state[0] = STATE_ADDRESS1;
|
||||
m_state[1] = STATE_ADDRESS2;
|
||||
m_state[2] = STATE_OFFSET;
|
||||
m_state[3] = STATE_INIT_COMMAND;
|
||||
m_state[4] = STATE_COPY_SCRATCHPAD;
|
||||
m_state_ptr = 0;
|
||||
break;
|
||||
default:
|
||||
verboselog(0, "timer_main command not handled %02x\n", m_shift);
|
||||
m_state[m_state_ptr] = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* */
|
||||
/* Internal Routines - Memory R/W */
|
||||
/* */
|
||||
/********************************************/
|
||||
|
||||
uint8_t ds1994_device::ds1994_readmem()
|
||||
{
|
||||
if (m_address < 0x200)
|
||||
{
|
||||
return m_sram[m_address];
|
||||
}
|
||||
else
|
||||
if (m_address >= 0x202 && m_address <= 0x206)
|
||||
{
|
||||
return m_rtc[m_address - 0x202];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ds1994_device::ds1994_writemem(uint8_t value) {
|
||||
if (m_address < 0x200)
|
||||
{
|
||||
m_sram[m_address] = value;
|
||||
}
|
||||
else
|
||||
if (m_address >= 0x202 && m_address <= 0x206)
|
||||
{
|
||||
m_rtc[m_address - 0x202] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************/
|
||||
/* */
|
||||
/* Internal states - Timer controlled Events */
|
||||
/* */
|
||||
/*************************************************/
|
||||
|
||||
void ds1994_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_CLOCK:
|
||||
for (auto & elem : m_rtc)
|
||||
{
|
||||
elem++;
|
||||
if (elem != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIMER_RESET:
|
||||
verboselog(1, "timer_reset\n");
|
||||
m_state[m_state_ptr] = STATE_RESET;
|
||||
m_timer_reset->adjust(attotime::never);
|
||||
break;
|
||||
case TIMER_MAIN:
|
||||
switch (m_state[m_state_ptr])
|
||||
{
|
||||
case STATE_RESET1:
|
||||
verboselog(2, "timer_main state_reset1 %d\n", m_rx);
|
||||
m_tx = false;
|
||||
m_state[m_state_ptr] = STATE_RESET2;
|
||||
m_timer_main->adjust(t_pdl);
|
||||
break;
|
||||
case STATE_RESET2:
|
||||
verboselog(2, "timer_main state_reset2 %d\n", m_rx);
|
||||
m_tx = true;
|
||||
m_bit = 0;
|
||||
m_shift = 0;
|
||||
m_state[m_state_ptr] = STATE_ROMCMD;
|
||||
break;
|
||||
case STATE_ROMCMD:
|
||||
ds1994_rom_cmd();
|
||||
break;
|
||||
case STATE_COMMAND:
|
||||
ds1994_cmd();
|
||||
break;
|
||||
case STATE_MATCHROM:
|
||||
verboselog(2, "timer_main state_matchrom - Data to match: <- %d\n", m_rx);
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
if (m_rom[7- m_byte] == m_shift)
|
||||
{
|
||||
m_byte++;
|
||||
m_bit = 0;
|
||||
verboselog(2, "timer_main state_matchrom: datamatch %x - byte=%d\n", m_shift, m_byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state[m_state_ptr] = STATE_IDLE;
|
||||
verboselog(1, "timer_main state_matchrom: no match rx=%x <> mem=%x - byte:%d\n", m_shift, m_rom[7 - m_byte], m_byte);
|
||||
}
|
||||
}
|
||||
if (m_byte == ROM_SIZE)
|
||||
{
|
||||
verboselog(2, "timer_main matchrom finished\n");
|
||||
m_state[m_state_ptr] = STATE_COMMAND;
|
||||
}
|
||||
break;
|
||||
case STATE_ADDRESS1:
|
||||
verboselog(2, "timer_main state_address1\n");
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
m_bit = 0;
|
||||
if (m_offs_ro)
|
||||
{
|
||||
if (m_a1 != m_shift) m_auth = false;
|
||||
verboselog(1, "timer_main state_address1 - TA1=%02x - Auth_Code 1=%02x\n", m_a1, m_shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_a1 = m_shift & 0xff;
|
||||
verboselog(2, "timer_main state_address1 - Address1=%02x\n", m_a1);
|
||||
}
|
||||
m_state_ptr++;
|
||||
}
|
||||
break;
|
||||
case STATE_ADDRESS2:
|
||||
verboselog(2, "timer_main state_address2\n");
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
m_bit = 0;
|
||||
if (m_offs_ro)
|
||||
{
|
||||
if ( m_a2 != m_shift ) m_auth = false;
|
||||
verboselog(1, "timer_main state_address1 - TA2=%02x - Auth_Code 2=%02x\n", m_a1, m_shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_a2 = m_shift & 0xff;
|
||||
verboselog(2, "timer_main state_address2 - Address2=%02x\n", m_a2);
|
||||
}
|
||||
m_state_ptr++;
|
||||
}
|
||||
break;
|
||||
case STATE_OFFSET:
|
||||
verboselog(2, "timer_main state_offset\n");
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
m_bit = 0;
|
||||
if (m_offs_ro)
|
||||
{
|
||||
if (m_a2 != m_shift) m_auth = false;
|
||||
verboselog(1, "timer_main state_address1 - OFS_ES=%02x - Auth_Code 3=%02x\n", m_offset, m_shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_offset = m_shift & 0x1f;
|
||||
verboselog(2, "timer_main state_address2 - Offset=%02x\n", m_offset);
|
||||
}
|
||||
m_state_ptr++;
|
||||
}
|
||||
break;
|
||||
case STATE_WRITE_SCRATCHPAD:
|
||||
verboselog(2, "timer_main state_write_scratchpad\n");
|
||||
if (one_wire_rx_bit())
|
||||
{
|
||||
m_bit = 0;
|
||||
m_ram[m_offset & 0x1f] = m_shift & 0xff;
|
||||
m_offset++;
|
||||
}
|
||||
verboselog(2, "timer_main state_write_scratchpad %d Offs=%02x\n", m_rx, m_offset);
|
||||
break;
|
||||
case STATE_READROM:
|
||||
m_tx = true;
|
||||
if (m_byte == ROM_SIZE)
|
||||
{
|
||||
verboselog(1, "timer_main readrom finished\n");
|
||||
m_state[m_state_ptr] = STATE_COMMAND;
|
||||
}
|
||||
else
|
||||
verboselog(2, "timer_main readrom window closed\n");
|
||||
break;
|
||||
case STATE_TXADDRESS1:
|
||||
m_tx = true;
|
||||
if (m_byte == 1)
|
||||
{
|
||||
verboselog(1, "timer_main txaddress1 finished m_byte=%d\n", m_byte);
|
||||
m_byte = 0;
|
||||
m_state_ptr++;
|
||||
}
|
||||
else
|
||||
verboselog(2, "timer_main txaddress1 window closed\n");
|
||||
break;
|
||||
case STATE_TXADDRESS2:
|
||||
m_tx = true;
|
||||
if (m_byte == 1)
|
||||
{
|
||||
verboselog(1, "timer_main txaddress2 finished m_byte=%d\n", m_byte);
|
||||
m_byte = 0;
|
||||
m_state_ptr++;
|
||||
}
|
||||
else
|
||||
verboselog(2, "timer_main txaddress2 window closed\n");
|
||||
break;
|
||||
case STATE_TXOFFSET:
|
||||
m_tx = true;
|
||||
if (m_byte == 1)
|
||||
{
|
||||
verboselog(1, "timer_main txoffset finished - m_byte=%d\n", m_byte);
|
||||
m_byte = 0;
|
||||
m_state_ptr++;
|
||||
}
|
||||
else
|
||||
verboselog(2, "timer_main txoffset window closed\n");
|
||||
break;
|
||||
case STATE_READ_MEMORY:
|
||||
verboselog(2, "timer_main state_readmemory\n");
|
||||
break;
|
||||
case STATE_COPY_SCRATCHPAD:
|
||||
verboselog(2, "timer_main state_copy_scratchpad\n");
|
||||
break;
|
||||
case STATE_READ_SCRATCHPAD:
|
||||
verboselog(2, "timer_main state_read_scratchpad\n");
|
||||
break;
|
||||
default:
|
||||
verboselog(0, "timer_main state not handled: %d\n", m_state[m_state_ptr]);
|
||||
break;
|
||||
}
|
||||
if (m_state[m_state_ptr] == STATE_INIT_COMMAND)
|
||||
{
|
||||
switch (m_state[m_state_ptr + 1])
|
||||
{
|
||||
case STATE_IDLE:
|
||||
case STATE_COMMAND:
|
||||
case STATE_ADDRESS1:
|
||||
case STATE_ADDRESS2:
|
||||
case STATE_OFFSET:
|
||||
break;
|
||||
case STATE_READ_MEMORY:
|
||||
verboselog(2, "timer_main (init_cmd) -> state_read_memory - set address\n");
|
||||
m_address = (m_a2 << 8) | m_a1;
|
||||
break;
|
||||
case STATE_WRITE_SCRATCHPAD:
|
||||
verboselog(2, "timer_main (init_cmd) -> state_write_scratchpad - set address\n");
|
||||
m_offs_ro = false;
|
||||
m_offset = 0;
|
||||
break;
|
||||
case STATE_READ_SCRATCHPAD:
|
||||
verboselog(2, "timer_main (init_cmd) -> state_read_scratchpad - set address\n");
|
||||
m_address = 0;
|
||||
break;
|
||||
case STATE_COPY_SCRATCHPAD:
|
||||
verboselog(2, "timer_main (init_cmd) -> state_copy_scratchpad - do copy\n");
|
||||
if (m_auth)
|
||||
{
|
||||
m_address = (m_a2 << 8) | m_a1;
|
||||
for (int i = 0; i <= m_offset; i++)
|
||||
{
|
||||
ds1994_writemem(m_ram[i]);
|
||||
m_address++;
|
||||
}
|
||||
}
|
||||
else
|
||||
verboselog(1, "timer_main (init_cmd) -> state_copy_scratchpad - Auth-Rejected\n");
|
||||
break;
|
||||
}
|
||||
m_state_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************/
|
||||
/* */
|
||||
/* Write Handler */
|
||||
/* */
|
||||
/*********************/
|
||||
|
||||
WRITE_LINE_MEMBER(ds1994_device::write)
|
||||
{
|
||||
verboselog(1, "write(%d)\n", state);
|
||||
if (!state && m_rx)
|
||||
{
|
||||
switch (m_state[m_state_ptr])
|
||||
{
|
||||
case STATE_IDLE:
|
||||
case STATE_INIT_COMMAND:
|
||||
break;
|
||||
case STATE_ROMCMD:
|
||||
verboselog(2, "state_romcommand\n");
|
||||
m_timer_main->adjust(t_samp);
|
||||
break;
|
||||
case STATE_COMMAND:
|
||||
verboselog(2, "state_command\n");
|
||||
m_timer_main->adjust(t_samp);
|
||||
break;
|
||||
case STATE_ADDRESS1:
|
||||
verboselog(2, "state_address1\n");
|
||||
m_timer_main->adjust(t_samp);
|
||||
break;
|
||||
case STATE_ADDRESS2:
|
||||
verboselog(2, "state_address2\n");
|
||||
m_timer_main->adjust(t_samp);
|
||||
break;
|
||||
case STATE_OFFSET:
|
||||
verboselog(2, "state_offset\n");
|
||||
m_timer_main->adjust(t_samp);
|
||||
break;
|
||||
case STATE_TXADDRESS1:
|
||||
verboselog(2, "state_txaddress1\n");
|
||||
if (one_wire_tx_bit(m_a1))
|
||||
{
|
||||
m_bit = 0;
|
||||
m_byte++;
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_TXADDRESS2:
|
||||
verboselog(2, "state_txaddress2\n");
|
||||
if (one_wire_tx_bit(m_a2))
|
||||
{
|
||||
m_bit = 0;
|
||||
m_byte++;
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_TXOFFSET:
|
||||
verboselog(2, "state_txoffset\n");
|
||||
if (one_wire_tx_bit(m_offset))
|
||||
{
|
||||
m_bit = 0;
|
||||
m_byte++;
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_READROM:
|
||||
verboselog(2, "state_readrom\n");
|
||||
if (one_wire_tx_bit(m_rom[7 - m_byte]))
|
||||
{
|
||||
m_bit = 0;
|
||||
m_byte++;
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_READ_MEMORY:
|
||||
verboselog(2, "state_read_memory\n");
|
||||
if (one_wire_tx_bit(ds1994_readmem()))
|
||||
{
|
||||
m_bit = 0;
|
||||
if ( m_address < DATA_SIZE+RTC_SIZE+REGS_SIZE ) m_address++;
|
||||
else
|
||||
m_tx = true;
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_MATCHROM:
|
||||
verboselog(2, "state_matchrom\n");
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_COPY_SCRATCHPAD:
|
||||
if ( m_auth )
|
||||
{
|
||||
verboselog(2, "state_copy_scratchpad Auth_Code Match: %d\n", m_tx);
|
||||
m_tx = true;
|
||||
m_auth = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tx = false;
|
||||
verboselog(1, "state_copy_scratchpad Auth_Code No Match: %d\n", m_tx);
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
case STATE_WRITE_SCRATCHPAD:
|
||||
verboselog(2, "state_write_scratchpad\n");
|
||||
m_timer_main->adjust(t_samp);
|
||||
break;
|
||||
case STATE_READ_SCRATCHPAD:
|
||||
verboselog(2, "state_read_scratchpad\n");
|
||||
if (one_wire_tx_bit(m_ram[m_address]))
|
||||
{
|
||||
m_bit = 0;
|
||||
if ( m_address <= m_offset ) m_address++;
|
||||
else
|
||||
m_tx = true;
|
||||
}
|
||||
m_timer_main->adjust(t_rdv);
|
||||
break;
|
||||
default:
|
||||
verboselog(0, "state not handled: %d\n", m_state[m_state_ptr]);
|
||||
break;
|
||||
}
|
||||
m_timer_reset->adjust(t_rstl);
|
||||
}
|
||||
else if (state && !m_rx)
|
||||
{
|
||||
switch (m_state[m_state_ptr])
|
||||
{
|
||||
case STATE_RESET:
|
||||
m_state[m_state_ptr] = STATE_RESET1;
|
||||
m_timer_main->adjust(t_pdh);
|
||||
break;
|
||||
}
|
||||
m_timer_reset->adjust(attotime::never);
|
||||
}
|
||||
m_rx = state;
|
||||
}
|
||||
|
||||
/*********************/
|
||||
/* */
|
||||
/* Read Handler */
|
||||
/* */
|
||||
/*********************/
|
||||
|
||||
READ_LINE_MEMBER(ds1994_device::read)
|
||||
{
|
||||
verboselog(2, "read %d\n", m_tx && m_rx);
|
||||
return m_tx && m_rx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_default - called to initialize NVRAM to
|
||||
// its default state
|
||||
//-------------------------------------------------
|
||||
|
||||
void ds1994_device::nvram_default()
|
||||
{
|
||||
memset(m_rom, 0, ROM_SIZE);
|
||||
memset(m_ram, 0, SPD_SIZE);
|
||||
memset(m_sram, 0, DATA_SIZE);
|
||||
memset(m_rtc, 0, RTC_SIZE);
|
||||
memset(m_regs, 0, REGS_SIZE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_read - called to read NVRAM from the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void ds1994_device::nvram_read(emu_file &file)
|
||||
{
|
||||
file.read(m_rom, ROM_SIZE);
|
||||
file.read(m_ram, SPD_SIZE);
|
||||
file.read(m_sram, DATA_SIZE);
|
||||
file.read(m_rtc, RTC_SIZE);
|
||||
file.read(m_regs, REGS_SIZE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_write - called to write NVRAM to the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void ds1994_device::nvram_write(emu_file &file)
|
||||
{
|
||||
file.write(m_rom, ROM_SIZE);
|
||||
file.write(m_ram, SPD_SIZE);
|
||||
file.write(m_sram, DATA_SIZE);
|
||||
file.write(m_rtc, RTC_SIZE);
|
||||
file.write(m_regs, REGS_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
app74.pdf
|
||||
|
||||
Under normal circumstances an ibutton will sample the line 30us after the falling edge of the start condition.
|
||||
The internal time base of ibutton may deviate from its nominal value. The allowed tollerance band ranges from 15us to 60us.
|
||||
This means that the actual slave sampling may occur anywhere from 15 and 60us after the start condition, which is a ratio of 1 to 4.
|
||||
During this time frame the voltage on the data line must stay below Vilmax or above Vihmin.
|
||||
|
||||
In the 1-Wire system, the logical values 1 and 0 are represented by certain voltages in special waveforms.
|
||||
The waveforms needed to write commands or data to ibuttons are called write-1 and write-0 time slots.
|
||||
The duration of a low pulse to write a 1 must be shorter than 15us.
|
||||
To write a 0, the duration of the low pulse must be at least 60us to cope with worst-case conditions.
|
||||
|
||||
The duration of the active part of a time slot can be extended beyond 60us.
|
||||
The maximum extension is limited by the fact that a low pulse of a duration of at least eight active time slots ( 480us ) is defined as a Reset Pulse.
|
||||
Allowing the same worst-case tolerance ratio, a low pulse of 120us might be sufficient for a reset.
|
||||
This limits the extension of the active part of a time slot to a maximum of 120us to prevent misinterpretation with reset.
|
||||
|
||||
Commands and data are sent to ibuttons by combining write-0 and write-1 time slots.
|
||||
To read data, the master has to generate read-data time slots to define the start condition of each bit.
|
||||
The read-data time slots looks essentially the same as a write-1 time slot from the masters point of view.
|
||||
Starting at the high-to-low transition, the ibuttons sends 1 bit of its addressed contents.
|
||||
If the data bit is a 1, the ibutton leaves the pulse unchanged.
|
||||
If the data bit is a 0, the ibutton will pull the data line low for 15us.
|
||||
In this time frame data is valid for reading by the master.
|
||||
The duration of the low pulse sent by the master should be a minimum of 1us with a maximum value as short as possible to maximize the master sampling window.
|
||||
|
||||
The Reset Pulse provides a clear starting condition that supersedes any time slot synchronisation.
|
||||
It is defined as single low pulse of minimum duration of eight time slots or 480us followed by a Reset-high time tRSTH of another 480us.
|
||||
After a Reset Pulse has been sent, the ibutton will wait for the time tPDH and then generate a Pulse-Presence Pulse of duration tPDL.
|
||||
No other communication on the 1-Wire bus is allowed during tRSTH.
|
||||
|
||||
There are 1,000 microseconds in a millisecond, and 1,000 milliseconds in a second.
|
||||
Thus, there are 1,000,000 microseconds in a second. Why is it "usec"?
|
||||
The "u" is supposed to look like the Greek letter Mu that we use for "micro". .
|
||||
*/
|
134
src/devices/machine/ds1994.h
Normal file
134
src/devices/machine/ds1994.h
Normal file
@ -0,0 +1,134 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles, smf, Grull Osgo
|
||||
/*
|
||||
* DS1994
|
||||
*
|
||||
* Dallas Semiconductor
|
||||
* 1-Wire Protocol
|
||||
* RTC + BACKUP RAM
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MAME_MACHINE_DS1994_H
|
||||
#define MAME_MACHINE_DS1994_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class ds1994_device : public device_t, public device_nvram_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
ds1994_device(const machine_config &mconfig, const char *tag, device_t *owner)
|
||||
: ds1994_device(mconfig, tag, owner, uint32_t(0))
|
||||
{
|
||||
}
|
||||
|
||||
ds1994_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// inline configuration helpers
|
||||
void ref_year(uint32_t year) { m_ref_year = year; }
|
||||
void ref_month(uint8_t month) { m_ref_month = month; }
|
||||
void ref_day(uint8_t day) { m_ref_day = day; }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(write);
|
||||
DECLARE_READ_LINE_MEMBER(read);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
// device_nvram_interface overrides
|
||||
virtual void nvram_default() override;
|
||||
virtual void nvram_read(emu_file &file) override;
|
||||
virtual void nvram_write(emu_file &file) override;
|
||||
|
||||
private:
|
||||
enum {
|
||||
ROM_SIZE = 8,
|
||||
DATA_SIZE = 0x202,
|
||||
SPD_SIZE = 0x20,
|
||||
RTC_SIZE = 0x05,
|
||||
REGS_SIZE = 0x19,
|
||||
// Rom Commands
|
||||
ROMCMD_READROM = 0x33,
|
||||
ROMCMD_MATCHROM = 0x55,
|
||||
ROMCMD_SEARCHROM = 0xf0,
|
||||
ROMCMD_SEARCHINT = 0xec,
|
||||
ROMCMD_SKIPROM = 0xcc,
|
||||
// Memory Commands
|
||||
COMMAND_READ_MEMORY = 0xf0,
|
||||
COMMAND_WRITE_SCRATCHPAD = 0x0f,
|
||||
COMMAND_READ_SCRATCHPAD = 0xaa,
|
||||
COMMAND_COPY_SCRATCHPAD = 0x55
|
||||
};
|
||||
|
||||
enum {
|
||||
TIMER_MAIN,
|
||||
TIMER_RESET,
|
||||
TIMER_CLOCK
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_IDLE,
|
||||
STATE_RESET,
|
||||
STATE_RESET1,
|
||||
STATE_RESET2,
|
||||
STATE_ROMCMD,
|
||||
STATE_READROM,
|
||||
STATE_SKIPROM,
|
||||
STATE_MATCHROM,
|
||||
STATE_COMMAND,
|
||||
STATE_ADDRESS1,
|
||||
STATE_ADDRESS2,
|
||||
STATE_OFFSET,
|
||||
STATE_TXADDRESS1,
|
||||
STATE_TXADDRESS2,
|
||||
STATE_TXOFFSET,
|
||||
STATE_INIT_COMMAND,
|
||||
STATE_READ_MEMORY,
|
||||
STATE_WRITE_SCRATCHPAD,
|
||||
STATE_READ_SCRATCHPAD,
|
||||
STATE_COPY_SCRATCHPAD
|
||||
};
|
||||
|
||||
void ds1994_rom_cmd(void);
|
||||
void ds1994_cmd(void);
|
||||
bool one_wire_tx_bit(uint8_t value);
|
||||
bool one_wire_rx_bit(void);
|
||||
uint8_t ds1994_readmem();
|
||||
void ds1994_writemem(uint8_t value);
|
||||
|
||||
emu_timer *m_timer_main, *m_timer_reset, *m_timer_clock;
|
||||
|
||||
uint32_t m_ref_year;
|
||||
uint8_t m_ref_month;
|
||||
uint8_t m_ref_day;
|
||||
|
||||
uint16_t m_address;
|
||||
uint16_t m_offset;
|
||||
uint8_t m_a1;
|
||||
uint8_t m_a2;
|
||||
int m_bit, m_shift;
|
||||
uint8_t m_byte;
|
||||
bool m_rx, m_tx;
|
||||
uint8_t m_rom[ROM_SIZE];
|
||||
uint8_t m_sram[DATA_SIZE];
|
||||
uint8_t m_ram[SPD_SIZE];
|
||||
uint8_t m_rtc[RTC_SIZE];
|
||||
uint8_t m_regs[REGS_SIZE];
|
||||
int m_state[6];
|
||||
int m_state_ptr;
|
||||
bool m_auth;
|
||||
bool m_offs_ro;
|
||||
|
||||
attotime t_samp, t_rdv, t_rstl, t_pdh, t_pdl;
|
||||
|
||||
inline void verboselog(int n_level, const char *s_fmt, ...) ATTR_PRINTF(3, 4);
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(DS1994, ds1994_device)
|
||||
|
||||
#endif // MAME_MACHINE_DS1994_H
|
@ -413,6 +413,7 @@
|
||||
#include "emu.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/ds1994.h"
|
||||
#include "sound/3812intf.h"
|
||||
#include "video/mc6845.h"
|
||||
//#include "sound/dac.h"
|
||||
@ -439,6 +440,7 @@ public:
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_tch(*this, "touch_m"),
|
||||
m_lamps(*this, "lamp%u", 0U)
|
||||
{
|
||||
}
|
||||
@ -464,10 +466,14 @@ private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
optional_device<ds1994_device> m_tch;
|
||||
output_finder<7> m_lamps;
|
||||
|
||||
uint8_t m_nmi_mask;
|
||||
|
||||
DECLARE_READ8_MEMBER(epm_code_r);
|
||||
DECLARE_READ8_MEMBER(touchm_r);
|
||||
DECLARE_WRITE8_MEMBER(touchm_w);
|
||||
DECLARE_WRITE8_MEMBER(rombank_w);
|
||||
DECLARE_WRITE8_MEMBER(nmi_mask_w);
|
||||
DECLARE_WRITE8_MEMBER(unk80_w);
|
||||
@ -592,6 +598,20 @@ void amaticmg_state::amaticmg2_palette(palette_device &palette) const
|
||||
/************************************
|
||||
* Read/Write Handlers *
|
||||
************************************/
|
||||
READ8_MEMBER( amaticmg_state::epm_code_r )
|
||||
{
|
||||
return 0x65;
|
||||
}
|
||||
|
||||
READ8_MEMBER( amaticmg_state::touchm_r )
|
||||
{
|
||||
return m_tch->read() & 1;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( amaticmg_state::touchm_w )
|
||||
{
|
||||
m_tch->write(data & 1);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( amaticmg_state::rombank_w )
|
||||
{
|
||||
@ -687,9 +707,11 @@ void amaticmg_state::amaticmg2_portmap(address_map &map)
|
||||
map(0x00, 0x03).rw("ppi8255_0", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0x20, 0x23).rw("ppi8255_1", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0x40, 0x41).w("ymsnd", FUNC(ym3812_device::write));
|
||||
map(0x60, 0x60).w("crtc", FUNC(mc6845_device::address_w)); // 0e for mg_iii_vger_3.64_v_8309
|
||||
map(0x60, 0x60).w("crtc", FUNC(mc6845_device::address_w)); // 0e for mg_iii_vger_3.64_v_8309
|
||||
map(0x61, 0x61).rw("crtc", FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); // 0f for mg_iii_vger_3.64_v_8309
|
||||
map(0xc0, 0xc0).w(FUNC(amaticmg_state::rombank_w));
|
||||
map(0xe0, 0xe0).rw(FUNC(amaticmg_state::touchm_r),FUNC(amaticmg_state::touchm_w)); // Touch Memory DS1994f
|
||||
map(0xe4, 0xe4).r(FUNC(amaticmg_state::epm_code_r)); // Input(0x00E4) must give back 0x65 in case of EPM Code 8201
|
||||
map(0xe6, 0xe6).w(FUNC(amaticmg_state::nmi_mask_w));
|
||||
map(0xe8, 0xeb).rw("ppi8255_2", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
}
|
||||
@ -912,8 +934,9 @@ void amaticmg_state::amaticmg2(machine_config &config)
|
||||
m_gfxdecode->set_info(gfx_amaticmg2);
|
||||
m_palette->set_init(FUNC(amaticmg_state::amaticmg2_palette));
|
||||
m_palette->set_entries(0x10000);
|
||||
}
|
||||
|
||||
DS1994(config, "touch_m");
|
||||
}
|
||||
|
||||
void amaticmg_state::amaticmg4(machine_config &config)
|
||||
{
|
||||
@ -967,9 +990,12 @@ ROM_START( am_mg24 )
|
||||
ROM_LOAD( "multi_2.4_zg2.i18.bin", 0x080000, 0x80000, CRC(b504e1b8) SHA1(ffa17a2c212eb2fffb89b131868e69430cb41203) )
|
||||
ROM_LOAD( "multi_2.4_zg3.i33.bin", 0x000000, 0x80000, CRC(9b66bb4d) SHA1(64035d2028a9b68164c87475a1ec9754453ad572) )
|
||||
|
||||
ROM_REGION( 0x20000/*0x0400*/, "proms", 0 )
|
||||
ROM_LOAD( "n82s147a_1.bin", 0x0000, 0x0200, NO_DUMP )
|
||||
ROM_LOAD( "n82s147a_2.bin", 0x0200, 0x0200, NO_DUMP )
|
||||
ROM_REGION( 0x4000, "proms", 0 )
|
||||
ROM_LOAD( "m2061295.bin", 0x0000, 0x1c00, CRC(05f4a6af) SHA1(b14e9c80d3313fa5bf076d129a509a711d80f982) )
|
||||
ROM_LOAD( "m2080196.bin", 0x2000, 0x1c00, CRC(8cf6c3a6) SHA1(6454077c2ab94093e878cbc1c0102bbb6c4bc367) )
|
||||
|
||||
ROM_REGION( 0x0248, "touch_m", 0 )
|
||||
ROM_LOAD( "ds1994.bin", 0x0000, 0x0248, CRC(7f581301) SHA1(33b2652f053a5e09442ccaa078b5d245255bb415) )
|
||||
ROM_END
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user