Add DS1994 device (#5054)

Add DS1994 device
amaticmg driver: added ds1994 device, modified prom load, added ds1994 to romload
This commit is contained in:
grullosgo 2019-05-14 17:07:02 -03:00 committed by R. Belmont
parent bbb32eb832
commit aff42a9969
5 changed files with 976 additions and 5 deletions

View File

@ -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

View File

@ -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

View 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(&current_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". .
*/

View 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

View File

@ -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
/*