ds1215: modernize and complete emulation

* rename previous ds1315 to earlier/original ds1215 device
* support both ds1215 and transparent access methods
* implement rtc and nvram interfaces
* support updating registers
This commit is contained in:
Patrick Mackinlay 2025-01-02 12:30:59 +07:00
parent ab34107f9f
commit 2da636bb21
17 changed files with 515 additions and 529 deletions

View File

@ -1170,13 +1170,13 @@ end
---------------------------------------------------
--
--@src/devices/machine/ds1315.h,MACHINES["DS1315"] = true
--@src/devices/machine/ds1215.h,MACHINES["DS1215"] = true
---------------------------------------------------
if (MACHINES["DS1315"]~=null) then
if (MACHINES["DS1215"]~=null) then
files {
MAME_DIR .. "src/devices/machine/ds1315.cpp",
MAME_DIR .. "src/devices/machine/ds1315.h",
MAME_DIR .. "src/devices/machine/ds1215.cpp",
MAME_DIR .. "src/devices/machine/ds1215.h",
}
end

View File

@ -33,8 +33,8 @@ void bbc_stlrtc_device::device_add_mconfig(machine_config &config)
void bbc_pmsrtc_device::device_add_mconfig(machine_config &config)
{
/* Dallas DS1216 SmartWatch RAM */
DS1315(config, m_rtc, 0);
/* Dallas DS1216 SmartWatch ROM */
DS1216E(config, m_rtc);
}
//**************************************************************************
@ -107,18 +107,10 @@ uint8_t bbc_pmsrtc_device::read(offs_t offset)
{
uint8_t data = get_rom_base()[offset & 0x1fff];
switch (offset)
{
case 0x00:
data |= m_rtc->read_0();
break;
case 0x01:
data |= m_rtc->read_1();
break;
case 0x04:
if (m_rtc->chip_enable())
data = m_rtc->read_data() & 0x01;
break;
}
if (m_rtc->ceo_r())
data = m_rtc->read(offset);
else
m_rtc->read(offset);
return data;
}

View File

@ -15,7 +15,7 @@
#include "slot.h"
#include "machine/mc146818.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
//**************************************************************************
// TYPE DEFINITIONS
@ -62,7 +62,7 @@ protected:
virtual uint8_t read(offs_t offset) override;
private:
required_device<ds1315_device> m_rtc;
required_device<ds1216e_device> m_rtc;
};
// device type definition

View File

@ -78,7 +78,6 @@
#include "meb_intrf.h"
#include "imagedev/floppy.h"
#include "machine/ds1315.h"
#include "machine/input_merger.h"
#include "machine/msm6242.h"
#include "machine/wd_fdc.h"

View File

@ -4,9 +4,6 @@
Dobbertin Smartwatch
Created: 23/2/2015
TODO: setting the time (requires the DS1315 core to be able to do this,
at the moment it just reads the current time)
*/
#include "emu.h"
@ -21,8 +18,7 @@ DEFINE_DEVICE_TYPE(CPC_SMARTWATCH, cpc_smartwatch_device, "cpc_smartwatch", "Dob
void cpc_smartwatch_device::device_add_mconfig(machine_config &config)
{
DS1315(config, m_rtc, 0);
// no pass-through (?)
DS1216E(config, m_rtc);
}
@ -63,26 +59,17 @@ void cpc_smartwatch_device::device_start()
void cpc_smartwatch_device::device_reset()
{
address_space &space = m_slot->cpu().space(AS_PROGRAM);
space.install_read_handler(0xc000,0xc001, read8sm_delegate(*this, FUNC(cpc_smartwatch_device::rtc_w)));
space.install_read_handler(0xc004,0xc004, read8smo_delegate(*this, FUNC(cpc_smartwatch_device::rtc_r)));
// FIXME: should cover the whole ROM address decode range
space.install_read_handler(0xc000,0xc004, read8sm_delegate(*this, FUNC(cpc_smartwatch_device::rtc_r)));
m_bank = membank(":bank7");
}
uint8_t cpc_smartwatch_device::rtc_w(offs_t offset)
uint8_t cpc_smartwatch_device::rtc_r(offs_t offset)
{
uint8_t* bank = (uint8_t*)m_bank->base();
if (!machine().side_effects_disabled())
{
if(offset & 1)
m_rtc->read_1();
else
m_rtc->read_0();
}
return bank[offset & 1];
}
uint8_t cpc_smartwatch_device::rtc_r()
{
uint8_t* bank = (uint8_t*)m_bank->base();
return (bank[4] & 0xfe) | (m_rtc->read_data() & 0x01);
if (m_rtc->ceo_r())
return m_rtc->read(offset);
else
m_rtc->read(offset);
return bank[offset];
}

View File

@ -15,7 +15,7 @@
#pragma once
#include "cpcexp.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
class cpc_smartwatch_device : public device_t, public device_cpc_expansion_card_interface
{
@ -23,8 +23,7 @@ public:
// construction/destruction
cpc_smartwatch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
uint8_t rtc_w(offs_t offset);
uint8_t rtc_r();
uint8_t rtc_r(offs_t offset);
protected:
// device-level overrides
@ -38,7 +37,7 @@ protected:
private:
cpc_expansion_slot_device *m_slot;
required_device<ds1315_device> m_rtc;
required_device<ds1216e_device> m_rtc;
memory_bank* m_bank;
};

View File

@ -73,17 +73,13 @@ void vme_mvme181_card_device::device_start()
m_cpu->space(AS_PROGRAM).install_read_tap(0xff820000, 0xff82001f, "rtc",
[this](offs_t offset, u32 &data, u32 mem_mask)
{
if (!m_rtc->chip_enable())
if (ACCESSING_BITS_24_31)
{
if (BIT(offset, 2))
m_rtc->read_1();
if (m_rtc->ceo_r())
data = (data & 0x00ffffffU) | u32(m_rtc->read(offset >> 2)) << 24;
else
m_rtc->read_0();
m_rtc->read(offset >> 2);
}
else if (BIT(offset, 4))
data = u32(m_rtc->read_data()) << 24;
else
m_rtc->write_data(BIT(offset, 2));
});
}
@ -102,7 +98,7 @@ void vme_mvme181_card_device::device_add_mconfig(machine_config &config)
MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x7e).set_mbus(m_cpu, AS_PROGRAM);
MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x7f).set_mbus(m_cpu, AS_PROGRAM);
DS1315(config, m_rtc, 0); // DS1216
DS1216E(config, m_rtc);
SCN2681(config, m_duart, 3.6864_MHz_XTAL); // SCC68692C1A44
m_duart->irq_cb().set(FUNC(vme_mvme181_card_device::irq_w<6>));

View File

@ -7,7 +7,7 @@
#pragma once
#include "cpu/m88000/m88000.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
#include "machine/mc68681.h"
#include "machine/mc88200.h"
@ -37,7 +37,7 @@ private:
required_device<mc88100_device> m_cpu;
required_device_array<mc88200_device, 2> m_mmu;
required_device<ds1315_device> m_rtc;
required_device<ds1216e_device> m_rtc;
required_device<scn2681_device> m_duart;
required_device_array<rs232_port_device, 2> m_serial;

View File

@ -0,0 +1,350 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* Dallas Semiconductor DS1215 Phantom Time Chip
*
* Sources:
* - Dallas Semiconductor 1992-1993 Product Data Book
* - Dallas Semiconductor DS1215 Phantom Time Chip, Copyright 1997 Dallas Semiconductor Corporation
*
* The DS1215 is an integrated circuit which can be optionally coupled with a
* CMOS static RAM. Its nonvolatile memory control functions may be enabled or
* disabled through a dedicated input line. This device does not have any
* address input lines, and is accessed using its chip enable input (/CEI),
* output enable (/OE) and write enable (/WE) inputs. Data is input or output
* on dedicated D and Q lines. DS1315 is a drop-in replacement for the DS1215,
* differing only in offering 3.3V operation and expanded temperature range.
*
* The DS1216 SmartWatch/RAM and SmartWatch/ROM devices are DIP sockets with an
* integrated quartz crystal, lithium battery and CMOS watch function. The
* internal operation of these devices is identical to the DS1215, however the
* access method varies between SmartWatch/RAM and SmartWatch/ROM device types.
* The RAM type operates identically to the DS1215, while the ROM type supports
* a "read-only" access mechanism using address lines A0 and A2.
*
* Address line A2 is treated as an active-low write enable input, while A0 is
* used for the input data bit when data is being written to the device. When
* the device is being read, data output is available on D0.
*
* TODO:
* - DS124xY variants
*/
/*
* Implementation Notes
* --------------------
* The ceo() callback and ceo_r() provide access to the active-low chip enable
* output (/CEO) signal, which may be used to enable or disable access to a RAM
* or ROM device which shares the same address decode output. /CEO is negated
* during the 64 cycles following a successful pattern recognition sequence.
*
* The ds1216e_device::read(offs_t offset) handler implements the SmartWatch/ROM
* interface, decoding the offset as described above to provide both read and
* write access to the chip. ds1215_device should be used for DS1215/DS1315 and
* DS1216 SmartWatch/RAM variants.
*
*/
#include "emu.h"
#include "ds1215.h"
#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(DS1215, ds1215_device, "ds1215", "Dallas Semiconductor DS1215 Phantom Time Chip")
DEFINE_DEVICE_TYPE(DS1216E, ds1216e_device, "ds1216e", "Dallas Semiconductor DS1216E SmartWatch/ROM")
enum mode : u8
{
MODE_IDLE,
MODE_MATCH,
MODE_DATA,
};
enum reg3_mask : u8
{
REG3_12 = 0x80, // enable 12 hour time
REG3_PM = 0x20, // AM/PM flag (1=PM)
};
enum reg4_mask : u8
{
REG4_RST = 0x10, // disable reset
REG4_OSC = 0x20, // disable oscillator
};
ds1215_device_base::ds1215_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_nvram_interface(mconfig, *this)
, device_rtc_interface(mconfig, *this)
, m_ceo(*this)
, m_timer(nullptr)
, m_mode(MODE_IDLE)
, m_count(0)
, m_reg{}
, m_ceo_state(false)
{
}
ds1215_device::ds1215_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: ds1215_device_base(mconfig, DS1215, tag, owner, clock)
{
}
ds1216e_device::ds1216e_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: ds1215_device_base(mconfig, DS1216E, tag, owner, clock)
{
}
void ds1215_device_base::device_start()
{
save_item(NAME(m_mode));
save_item(NAME(m_count));
save_item(NAME(m_reg));
save_item(NAME(m_ceo_state));
m_timer = timer_alloc(FUNC(ds1215_device::timer), this);
update_ceo();
}
void ds1215_device_base::device_reset()
{
if (!(m_reg[4] & REG4_RST))
{
m_mode = MODE_IDLE;
m_count = 0;
update_ceo();
}
m_timer->adjust(attotime::from_msec(10), 0, attotime::from_msec(10));
}
bool ds1215_device_base::nvram_read(util::read_stream &file)
{
auto const [err, actual] = util::read(file, &m_reg[0], std::size(m_reg));
return !err && (actual == std::size(m_reg));
}
bool ds1215_device_base::nvram_write(util::write_stream &file)
{
auto const [err, actual] = util::write(file, &m_reg[0], std::size(m_reg));
return !err;
}
void ds1215_device_base::nvram_default()
{
m_reg[0] = 0; // second/100 = 0
m_reg[1] = 0; // second = 0
m_reg[2] = 0; // minute = 0
m_reg[3] = 0; // 24 hour time, hour = 0
m_reg[4] = 1; // enable oscillator, enable reset, day of week = 1
m_reg[5] = 1; // day of month = 1
m_reg[6] = 1; // month = 1
m_reg[7] = 0; // year = 0
}
void ds1215_device_base::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
{
m_reg[0] = 0; // always zero second/100
m_reg[1] = convert_to_bcd(second);
m_reg[2] = convert_to_bcd(minute);
m_reg[3] &= REG3_12;
if (m_reg[3] & REG3_12)
{
// adjust for PM
if (hour > 11)
{
m_reg[3] |= REG3_PM;
hour -= 12;
}
m_reg[3] |= convert_to_bcd(hour ? hour : 12);
}
else
// 24 hour time
m_reg[3] |= convert_to_bcd(hour);
m_reg[4] = (m_reg[4] & (REG4_OSC | REG4_RST)) | convert_to_bcd(day_of_week);
m_reg[5] = convert_to_bcd(day);
m_reg[6] = convert_to_bcd(month);
m_reg[7] = convert_to_bcd(year);
}
u8 ds1215_device_base::read_bit()
{
u8 data = 0;
switch (m_mode)
{
case MODE_IDLE:
// first read starts pattern recognition
LOG("pattern recognition started\n");
m_mode = MODE_MATCH;
m_count = 0;
break;
case MODE_MATCH:
// read during match aborts sequence
LOG("pattern recognition aborted\n");
m_mode = MODE_IDLE;
m_count = 0;
break;
case MODE_DATA:
data = BIT(m_reg[m_count >> 3], m_count & 7);
if (m_count == 63)
{
LOG("data read completed\n");
m_mode = MODE_IDLE;
m_count = 0;
update_ceo();
}
else
m_count++;
break;
}
return data;
}
void ds1215_device_base::write_bit(u8 data)
{
static constexpr u8 pattern[] = { 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c };
switch (m_mode)
{
case MODE_IDLE:
break;
case MODE_MATCH:
if (BIT(pattern[m_count >> 3], m_count & 7) == (data & 1))
{
// match, check if finished
if (m_count == 63)
{
LOG("pattern recognition completed\n");
m_mode = MODE_DATA;
m_count = 0;
update_ceo();
}
else
m_count++;
}
else
{
// no match, abort sequence
LOG("pattern recognition aborted\n");
m_mode = MODE_IDLE;
m_count = 0;
}
break;
case MODE_DATA:
if (data & 1)
m_reg[m_count >> 3] |= 1U << (m_count & 7);
else
m_reg[m_count >> 3] &= ~(1U << (m_count & 7));
if (m_count == 63)
{
LOG("data write completed\n");
// clear reserved bits
m_reg[1] &= 0x7f;
m_reg[2] &= 0x7f;
m_reg[3] &= 0xbf;
m_reg[4] &= 0x37;
m_reg[5] &= 0x3f;
m_reg[6] &= 0x1f;
// retrieve date/time from registers
int const year = bcd_to_integer(m_reg[7]);
int const month = bcd_to_integer(m_reg[6]);
int const day = bcd_to_integer(m_reg[5]);
int const day_of_week = bcd_to_integer(m_reg[4] & 0x7);
int hour = bcd_to_integer(m_reg[3] & 0x3f);
int const minute = bcd_to_integer(m_reg[2]);
int const second = bcd_to_integer(m_reg[1]);
// check for 12 hour mode
if (m_reg[3] & REG3_12)
{
hour = bcd_to_integer(m_reg[3] & 0x1f);
// adjust for PM
if (m_reg[3] & REG3_PM)
hour = (hour + 12) % 24;
}
// update clock
LOG("time/date set %d-%d-%d %02d:%02d:%02d\n", year, month, day, hour, minute, second);
set_time(false, year, month, day, day_of_week, hour, minute, second);
m_mode = MODE_IDLE;
m_count = 0;
update_ceo();
}
else
m_count++;
break;
}
}
void ds1215_device_base::timer(s32 param)
{
// register 4 bit 5 disables oscillator
if (m_reg[4] & REG4_OSC)
return;
int const hundredths = bcd_to_integer(m_reg[0]);
if (hundredths < 99)
m_reg[0] = convert_to_bcd(hundredths + 1);
else
advance_seconds();
}
void ds1215_device_base::update_ceo()
{
// ceo is asserted except when in data i/o mode
bool const ceo = m_mode != MODE_DATA;
if (m_ceo_state != ceo)
{
m_ceo_state = ceo;
m_ceo(!m_ceo_state);
}
}
u8 ds1215_device::read()
{
if (!machine().side_effects_disabled())
return read_bit();
else
return 0;
}
void ds1215_device::write(u8 data)
{
write_bit(data & 1);
}
u8 ds1216e_device::read(offs_t offset)
{
if (!machine().side_effects_disabled())
{
if (BIT(offset, 2))
return read_bit();
else
write_bit(BIT(offset, 0));
return BIT(offset, 0);
}
else
return 0;
}

View File

@ -0,0 +1,77 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_MACHINE_DS1215_H
#define MAME_MACHINE_DS1215_H
#pragma once
#include "dirtc.h"
class ds1215_device_base
: public device_t
, public device_nvram_interface
, public device_rtc_interface
{
public:
auto ceo() { return m_ceo.bind(); }
bool ceo_r() { return !m_ceo_state; }
protected:
ds1215_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
// device_t implementation
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_nvram_interface implementation
virtual bool nvram_read(util::read_stream &file) override;
virtual bool nvram_write(util::write_stream &file) override;
virtual void nvram_default() override;
// device_rtc_interface implementation
virtual bool rtc_feature_y2k() const override { return false; }
virtual bool rtc_feature_leap_year() const override { return true; }
virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override;
u8 read_bit();
void write_bit(u8 data);
private:
void timer(s32 param);
void update_ceo();
devcb_write_line m_ceo;
emu_timer *m_timer;
// internal state
u8 m_mode;
u8 m_count;
u8 m_reg[8];
bool m_ceo_state;
};
class ds1215_device : public ds1215_device_base
{
public:
ds1215_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 32'768);
~ds1215_device() {}
u8 read();
void write(u8 data);
};
class ds1216e_device : public ds1215_device_base
{
public:
ds1216e_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 32'768);
~ds1216e_device() {}
u8 read(offs_t offset);
};
DECLARE_DEVICE_TYPE(DS1215, ds1215_device)
DECLARE_DEVICE_TYPE(DS1216E, ds1216e_device)
#endif // MAME_MACHINE_DS1215_H

View File

@ -1,305 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Tim Lindner, R. Belmont
/*****************************************************************************************
ds1315.cpp
Dallas Semiconductor's Phantom Time Chip DS1315.
NOTE: writes are decoded, but the host's time will always be returned when asked.
November 2017: R. Belmont added capability to emulate DS1216 and other DS121x
parts where the clock sits in the same place as a ROM. The backing callback
returns the ROM contents when the RTC is locked.
April 2015: chip enable / chip reset / phantom writes by Karl-Ludwig Deisenhofer
November 2001: implementation by Tim Lindner
HOW DOES IT WORK?
READS: pattern recognition (64 bits in correct order). When RTC finally enables
64 bits of data can be read. Chance of accidential pattern recognition is minimal.
WRITES: two different locations (bits 0 and 1) are used to transfer data to the
DS1315. 64 bit with time/date info are transmitted directly after recognition
of the magic 64 bit pattern (see read above).
**************************************************************************************/
#include "emu.h"
#include "ds1315.h"
#include "coreutil.h"
DEFINE_DEVICE_TYPE(DS1315, ds1315_device, "ds1315", "Dallas DS1315 Phantom Time Chip")
ds1315_device::ds1315_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, DS1315, tag, owner, clock),
m_backing_read(*this, 0xff),
m_mode(),
m_count(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void ds1315_device::device_start()
{
save_item(NAME(m_count));
save_item(NAME(m_mode));
save_item(NAME(m_raw_data));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void ds1315_device::device_reset()
{
chip_reset();
}
/***************************************************************************
LOCAL VARIABLES
***************************************************************************/
static const uint8_t ds1315_pattern[] =
{
1, 0, 1, 0, 0, 0, 1, 1,
0, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 0, 0, 1, 0, 1,
0, 0, 1, 1, 1, 0, 1, 0,
1, 0, 1, 0, 0, 0, 1, 1,
0, 1, 0, 1, 1, 1, 0, 0,
1, 1, 0, 0, 0, 1, 0, 1,
0, 0, 1, 1, 1, 0, 1, 0
};
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
// automated read, does all the work the real Dallas chip does
uint8_t ds1315_device::read(offs_t offset)
{
if (m_mode == DS_SEEK_MATCHING)
{
if (offset & 1)
{
read_1();
}
else
{
read_0();
}
if (offset & 4)
{
m_count = 0;
m_mode = DS_SEEK_MATCHING;
}
return m_backing_read(offset);
}
else if (m_mode == DS_CALENDAR_IO)
{
return read_data();
}
return 0xff; // shouldn't happen, but compilers don't know that
}
/*-------------------------------------------------
read_0 (actual data)
-------------------------------------------------*/
uint8_t ds1315_device::read_0()
{
if (ds1315_pattern[m_count++] == 0)
{
if (m_count == 64)
{
/* entire pattern matched */
m_count = 0;
m_mode = DS_CALENDAR_IO;
fill_raw_data();
}
return 0;
}
m_count = 0;
m_mode = DS_SEEK_MATCHING;
return 0;
}
/*-------------------------------------------------
read_1 (actual data)
-------------------------------------------------*/
uint8_t ds1315_device::read_1()
{
if (ds1315_pattern[m_count++] == 1)
{
m_count %= 64;
return 0;
}
m_count = 0;
m_mode = DS_SEEK_MATCHING;
return 0;
}
/*-------------------------------------------------
read_data
-------------------------------------------------*/
uint8_t ds1315_device::read_data()
{
uint8_t result;
if (m_mode == DS_CALENDAR_IO)
{
result = m_raw_data[m_count++];
if (m_count == 64)
{
m_mode = DS_SEEK_MATCHING;
m_count = 0;
}
return result;
}
m_count = 0;
return 0;
}
/*-------------------------------------------------
fill_raw_data
-------------------------------------------------*/
void ds1315_device::fill_raw_data()
{
/* This routine calls a standard 'C' library routine to get the current
date and time and then fill in the raw data struct.
*/
system_time systime;
int raw[8], i, j;
/* get the current date/time from the core */
machine().current_datetime(systime);
raw[0] = 0; /* tenths and hundreths of seconds are always zero */
raw[1] = dec_2_bcd(systime.local_time.second);
raw[2] = dec_2_bcd(systime.local_time.minute);
raw[3] = dec_2_bcd(systime.local_time.hour);
raw[4] = dec_2_bcd((systime.local_time.weekday != 0) ? systime.local_time.weekday : 7);
raw[5] = dec_2_bcd(systime.local_time.mday);
raw[6] = dec_2_bcd(systime.local_time.month + 1);
raw[7] = dec_2_bcd(systime.local_time.year - 1900); /* Epoch is 1900 */
/* Ok now we have the raw bcd bytes. Now we need to push them into our bit array */
for (i = 0; i < 64; i++)
{
j = i / 8;
m_raw_data[i] = (raw[j] & 0x0001);
raw[j] = raw[j] >> 1;
}
}
/*-------------------------------------------------
write_data
-------------------------------------------------*/
uint8_t ds1315_device::write_data(offs_t offset)
{
static int write_count;
if (write_count >= 64)
write_count = 0;
if (m_mode == DS_CALENDAR_IO)
{
m_raw_data[write_count++] = offset & 0x01;
if (write_count == 64)
{
write_count = 0;
m_mode = DS_SEEK_MATCHING;
m_count = 0;
input_raw_data();
}
}
return 0; // ignore
}
/*-------------------------------------------------
ds1315_input_raw_data
Routine is called when new date and time has
been written to the clock chip. Currently we
ignore setting the date and time in the clock
chip.
-------------------------------------------------*/
void ds1315_device::input_raw_data()
{
int raw[8], i, j;
raw[0] = raw[1] = raw[2] = raw[3] = raw[4] = raw[5] = raw[6] = raw[7] = 0;
uint8_t flag = 1;
for (i = 0; i < 64; i++)
{
j = i / 8;
if ((i % 8) == 0)
flag = 1;
if (m_raw_data[i] & 1)
raw[j] |= flag;
flag <<= 1;
}
raw[0] = bcd_2_dec(raw[0]); // hundreds of seconds
raw[1] = bcd_2_dec(raw[1]); // seconds (often set to zero)
raw[2] = bcd_2_dec(raw[2]); // minute
raw[3] = bcd_2_dec(raw[3]); // hour
raw[4] = bcd_2_dec(raw[4]); // weekday (10 for Friday ?!)
raw[5] = bcd_2_dec(raw[5]); // mday
raw[6] = bcd_2_dec(raw[6]); // month
raw[7] = bcd_2_dec(raw[7]); // year (two digits)
logerror("\nDS1315 RTC INPUT (WILL BE IGNORED) mm/dd/yy hh:mm:ss - %02d/%02d/%02d %02d/%02d/%02d",
raw[6], raw[5], raw[7], raw[3], raw[2], raw[1]
);
}
/*-------------------------------------------------
query and reset chip status
-------------------------------------------------*/
bool ds1315_device::chip_enable()
{
return (m_mode == DS_CALENDAR_IO);
}
// Set a defined state (important for pattern detection)
void ds1315_device::chip_reset()
{
memset(m_raw_data, 0, sizeof(m_raw_data));
m_count = 0;
m_mode = DS_SEEK_MATCHING;
}

View File

@ -1,65 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Tim Lindner
/*********************************************************************
ds1315.h
Dallas Semiconductor's Phantom Time Chip DS1315.
by tim lindner, November 2001.
*********************************************************************/
#ifndef MAME_MACHINE_DS1315_H
#define MAME_MACHINE_DS1315_H
#pragma once
class ds1315_device : public device_t
{
public:
ds1315_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
~ds1315_device() {}
auto read_backing() { return m_backing_read.bind(); }
// this handler automates the bits 0/2 stuff
uint8_t read(offs_t offset);
uint8_t read_0();
uint8_t read_1();
uint8_t read_data();
uint8_t write_data(offs_t offset);
bool chip_enable();
void chip_reset();
protected:
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
devcb_read8 m_backing_read;
enum mode_t : u8
{
DS_SEEK_MATCHING,
DS_CALENDAR_IO
};
// internal state
mode_t m_mode;
void fill_raw_data();
void input_raw_data();
int m_count;
uint8_t m_raw_data[8*8];
};
ALLOW_SAVE_TYPE(ds1315_device::mode_t);
DECLARE_DEVICE_TYPE(DS1315, ds1315_device)
#endif // MAME_MACHINE_DS1315_H

View File

@ -133,7 +133,7 @@ MIG RAM page 2 $CE02 is the speaker/slot bitfield and $CE03 is the paddle/accele
#include "cpu/z80/z80.h"
#include "imagedev/cassette.h"
#include "machine/applefdintf.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
#include "machine/iwm.h"
#include "machine/kb3600.h"
#include "machine/mos6551.h"
@ -294,7 +294,7 @@ public:
optional_device<mos6551_device> m_acia1, m_acia2;
optional_device<applefdintf_device> m_iwm;
optional_device_array<floppy_connector, 4> m_floppy;
required_device<ds1315_device> m_ds1315;
required_device<ds1216e_device> m_ds1315;
optional_device<centronics_device> m_printer_conn;
optional_device<output_latch_device> m_printer_out;
@ -387,7 +387,6 @@ public:
void ay3600_ako_w(int state);
u8 memexp_r(offs_t offset);
void memexp_w(offs_t offset, u8 data);
u8 nsc_backing_r(offs_t offset);
u8 ace500_c0bx_r(offs_t offset);
void ace500_c0bx_w(offs_t offset, u8 data);
@ -3070,10 +3069,14 @@ u8 apple2e_state::read_int_rom(int slotbias, int offset)
return m_rom_ptr[slotbias + offset];
}
return m_ds1315->read(slotbias + offset);
}
// return data from SmartWatch if /CEO is negated
if (m_ds1315->ceo_r())
return m_ds1315->read(slotbias + offset);
else
m_ds1315->read(slotbias + offset);
u8 apple2e_state::nsc_backing_r(offs_t offset) { return m_rom_ptr[offset]; }
return m_rom_ptr[slotbias + offset];
}
u8 apple2e_state::c100_r(offs_t offset) { accel_slot(1 + ((offset >> 8) & 0x7)); return read_slot_rom(1, offset); }
u8 apple2e_state::c100_int_r(offs_t offset) { accel_slot(1 + ((offset >> 8) & 0x7)); return read_int_rom(0x100, offset); }
@ -5117,7 +5120,7 @@ void apple2e_state::apple2e_common(machine_config &config, bool enhanced, bool r
SPEAKER_SOUND(config, A2_SPEAKER_TAG).add_route(ALL_OUTPUTS, "mono", 0.4);
/* DS1315 for no-slot clock */
DS1315(config, m_ds1315, 0).read_backing().set(FUNC(apple2e_state::nsc_backing_r));
DS1216E(config, m_ds1315);
/* RAM */
RAM(config, m_ram).set_default_size("64K").set_default_value(0x00);

View File

@ -350,7 +350,7 @@ W17 pulls J1 serial port pin 1 to GND when set (chassis to logical GND).
#include "machine/timer.h"
#include "machine/ram.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
#include "emupal.h"
#include "softlist.h"
#include "screen.h"
@ -492,7 +492,6 @@ public:
m_p_vol_ram(*this, "vol_ram"),
m_p_nvram(*this, "nvram"),
m_rtc(*this, "rtc"),
m_hgdc(*this, "upd7220"), // GDC
m_screen2(*this, "screen2"),
@ -519,8 +518,6 @@ protected:
uint8_t ext_ram_r(offs_t offset);
void rtc_w(offs_t offset, uint8_t data);
uint8_t read_video_ram_r(offs_t offset);
void video_interrupt(int state);
@ -650,8 +647,6 @@ protected:
required_shared_ptr<uint8_t> m_p_vol_ram;
required_shared_ptr<uint8_t> m_p_nvram;
optional_device<ds1315_device> m_rtc;
required_device<upd7220_device> m_hgdc; // GDC
required_device<screen_device> m_screen2;
required_device<palette_device> m_palette2;
@ -753,7 +748,8 @@ class rainbow_modela_state : public rainbow_base_state
{
public:
rainbow_modela_state(const machine_config &mconfig, device_type type, const char *tag) :
rainbow_base_state(mconfig, type, tag)
rainbow_base_state(mconfig, type, tag),
m_rtc(*this, "rtc")
{
}
@ -767,15 +763,19 @@ private:
void ext_ram_w(offs_t offset, uint8_t data);
uint8_t rtc_r(offs_t offset);
void rtc_w(offs_t offset, uint8_t data);
void irq_hi_w(int state);
uint8_t system_parameter_r();
required_device<ds1215_device> m_rtc;
};
class rainbow_modelb_state : public rainbow_base_state
{
public:
rainbow_modelb_state(const machine_config &mconfig, device_type type, const char *tag) :
rainbow_base_state(mconfig, type, tag)
rainbow_base_state(mconfig, type, tag),
m_rtc(*this, "rtc")
{
}
@ -791,6 +791,8 @@ private:
uint8_t rtc_r(offs_t offset);
void irq_hi_w(int state);
uint8_t system_parameter_r();
required_device<ds1216e_device> m_rtc;
};
// It * should be * OK to RESET the SCROLL_BUFFER and the COLOR_MAP (at least with WELL WRITTEN programs)
@ -1180,8 +1182,6 @@ void rainbow_base_state::machine_reset()
m_crtc->MHFU(MHFU_RESET_and_DISABLE);
m_rtc->chip_reset(); // * Reset RTC to a defined state *
// *********** HARD DISK CONTROLLERS...
address_space &io = m_i8088->space(AS_IO);
if (m_inp5->read() == 0x01) // ...PRESENT?
@ -1528,27 +1528,20 @@ void rainbow_modelb_state::ext_ram_w(offs_t offset, uint8_t data)
// Requires a short program from the Suitable Solutions ClikClok distribution disk (CLIKA.COM)
// - also needed to set time/date (*). Reads $ed000, writes ed0fe/ed0ff.
void rainbow_base_state::rtc_w(offs_t offset, uint8_t data)
void rainbow_modela_state::rtc_w(offs_t offset, uint8_t data)
{
if (m_inp11->read() == 0x01) // if enabled...
{
switch (offset)
if (m_rtc->ceo_r())
{
case 0x00: // Write to 0xED0FE
if (m_rtc->chip_enable())
m_rtc->write_data(offset & 0x01); // Transfer data to DS1315 (data = offset):
else
m_rtc->read_0(); // (RTC ACTIVATION) read magic pattern 0
break;
m_rtc->write(offset & 0x01);
case 0x01: // Write to 0xED0FF
if (m_rtc->chip_enable())
m_rtc->write_data(offset & 0x01); // Transfer data to DS1315 (data = offset):
else
m_rtc->read_1(); // (RTC ACTIVATION) read magic pattern 1
break;
return;
}
m_rtc->write(offset & 0x01);
}
m_p_vol_ram[offset] = data; // Poke value into VOL_RAM.
}
@ -1561,10 +1554,10 @@ uint8_t rainbow_modela_state::rtc_r(offs_t offset)
{
if (offset == 0x00) // read time/date from 0xED000 (ClikClok for 100-A)
{
if (m_rtc->chip_enable())
return m_rtc->read_data() & 0x01;
if (m_rtc->ceo_r())
return m_rtc->read();
else
m_rtc->chip_reset();
m_rtc->read();
}
}
@ -1575,41 +1568,10 @@ uint8_t rainbow_modelb_state::rtc_r(offs_t offset)
{
if (m_inp11->read() == 0x01) // if enabled...
{
switch (offset)
{
// Transfer data to DS1315 (data = offset):
case 0x0000: // RTC_WRITE_DATA_0 0xFC000
case 0x2000: // RTC_WRITE_DATA_0 0xFE000 (MIRROR)
case 0x0001: // RTC_WRITE_DATA_1 0xFC001
case 0x2001: // RTC_WRITE_DATA_1 0xFE001 (MIRROR)
m_rtc->write_data(offset & 0x01);
break;
// Read actual time/date from ClikClok:
case 0x0004: // 0xFC004
case 0x2004: // 0xFE004 (MIRROR)
if (m_rtc->chip_enable())
return (m_rtc->read_data() & 0x01);
[[fallthrough]]; // FIXME: really?
// (RTC ACTIVATION) read magic pattern 0
case 0x0100: // 0xFC100
case 0x2100: // 0xFE100 (MIRROR)
m_rtc->read_0();
break;
// (RTC ACTIVATION) read magic pattern 1
case 0x0101: // 0xFC101
case 0x2101: // 0xFE101 (MIRROR)
m_rtc->read_1();
break;
// RESET
case 0x0104: // 0xFC104
case 0x2104: // 0xFE104 (MIRROR)
m_rtc->chip_reset();
break;
}
if (m_rtc->ceo_r())
return m_rtc->read(offset);
else
m_rtc->read(offset);
}
uint8_t *rom = memregion("maincpu")->base();
@ -3278,8 +3240,6 @@ void rainbow_base_state::rainbow_base(machine_config &config)
HARDDISK(config, "harddisk3", "corvus_hdd");
HARDDISK(config, "harddisk4", "corvus_hdd");
DS1315(config, m_rtc, 0); // DS1315 (ClikClok for DEC-100 B) * OPTIONAL *
COM8116_003(config, m_dbrg, 24.0734_MHz_XTAL / 4); // 6.01835 MHz (nominally 6 MHz)
m_dbrg->fr_handler().set(FUNC(rainbow_base_state::dbrg_fr_w));
m_dbrg->ft_handler().set(FUNC(rainbow_base_state::dbrg_ft_w));
@ -3330,6 +3290,8 @@ void rainbow_modela_state::rainbow_modela(machine_config &config)
m_i8088->set_addrmap(AS_IO, &rainbow_modela_state::rainbow8088_io);
RAM(config, m_ram).set_default_size("64K").set_extra_options("64K,128K,192K,256K,320K,384K,448K,512K,576K,640K,704K,768K");
m_kbd8251->dtr_handler().set(FUNC(rainbow_modela_state::irq_hi_w));
DS1215(config, m_rtc); // DS1315 (ClikClok for DEC-100 B) * OPTIONAL *
}
void rainbow_modelb_state::rainbow_modelb(machine_config &config)
@ -3339,6 +3301,8 @@ void rainbow_modelb_state::rainbow_modelb(machine_config &config)
m_i8088->set_addrmap(AS_IO, &rainbow_modelb_state::rainbow8088_io);
RAM(config, m_ram).set_default_size("128K").set_extra_options("128K,192K,256K,320K,384K,448K,512K,576K,640K,704K,768K,832K,896K");
m_kbd8251->dtr_handler().set(FUNC(rainbow_modelb_state::irq_hi_w));
DS1216E(config, m_rtc); // DS1315 (ClikClok for DEC-100 B) * OPTIONAL *
}
//----------------------------------------------------------------------------------------

View File

@ -25,7 +25,7 @@
// other devices
#include "machine/aic6250.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
#include "machine/input_merger.h"
#include "machine/mc68681.h"
#include "machine/ncr5380.h"
@ -72,7 +72,7 @@ protected:
required_device<ns32381_device> m_fpu;
required_device<ns32202_device> m_icu;
required_device<ds1315_device> m_rtc;
required_device<ds1216e_device> m_rtc;
required_device<ncr5380_device> m_ncr5380;
required_device<aic6250_device> m_aic6250;
@ -115,16 +115,13 @@ void pc532_state::machine_start()
{
// install phantom rtc using memory taps
// TODO: not tested
m_cpu->space(AS_PROGRAM).install_read_tap(0x1000'0000, 0x1000'0003, "rtc_w",
m_cpu->space(AS_PROGRAM).install_read_tap(0x1000'0000, 0x1000'0007, "rtc_r",
[this](offs_t offset, u32 &data, u32 mem_mask)
{
m_rtc->write_data(offset & 1);
});
m_cpu->space(AS_PROGRAM).install_read_tap(0x1000'0004, 0x1000'0007, "rtc_r",
[this](offs_t offset, u32 &data, u32 mem_mask)
{
if (m_rtc->chip_enable())
data = m_rtc->read_data();
if (m_rtc->ceo_r())
data = m_rtc->read(offset);
else
m_rtc->read(offset);
});
}
@ -312,7 +309,7 @@ void pc532_state::pc532(machine_config &config)
m_icu->out_g<0>().set([this](int state) { m_swap.select(state); });
m_icu->out_g<7>().set([this](int state) { m_select.select(state); });
DS1315(config, m_rtc, 32.768_kHz_XTAL);
DS1216E(config, m_rtc);
NSCSI_BUS(config, "slot");
NSCSI_CONNECTOR(config, "slot:0", scsi_devices, "harddisk", false);

View File

@ -168,7 +168,7 @@ void sgi_ip4_device::device_add_mconfig(machine_config &config)
m_cpu->set_addrmap(AS_PROGRAM, &sgi_ip4_device::map);
m_cpu->in_brcond<0>().set([]() { return 1; }); // writeback complete
DS1315(config, m_rtc, 0); // DS1216?
DS1215(config, m_rtc); // DS1216B?
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // CXK5816PN-15L
@ -511,10 +511,11 @@ u8 sgi_ip4_device::nvram_r(offs_t offset)
{
if (offset == 0x7ff && !machine().side_effects_disabled())
{
if (m_rtc->chip_enable())
m_rtc->read_data();
// return SmartWatch data if /CEO is negated
if (m_rtc->ceo_r())
return m_rtc->read();
else
return m_rtc->read_data();
m_rtc->read();
}
return m_nvram[offset];
@ -522,21 +523,12 @@ u8 sgi_ip4_device::nvram_r(offs_t offset)
void sgi_ip4_device::nvram_w(offs_t offset, u8 data)
{
if (offset != 0x7ff || !m_rtc->chip_enable())
// write to NVRAM if SmartWatch /CEO is asserted
if (offset != 0x7ff || !m_rtc->ceo_r())
m_nvram[offset] = data;
if (offset == 0x7ff)
{
if (!m_rtc->chip_enable())
{
if (data)
m_rtc->read_1();
else
m_rtc->read_0();
}
else
m_rtc->write_data(data);
}
m_rtc->write(data);
}
ROM_START(ip4)

View File

@ -8,7 +8,7 @@
#include "cpu/mips/mips1.h"
#include "machine/ds1315.h"
#include "machine/ds1215.h"
#include "machine/mc68681.h"
#include "machine/pit8253.h"
#include "machine/wd33c9x.h"
@ -52,7 +52,7 @@ protected:
private:
required_device<mips1_device_base> m_cpu;
required_device<ds1315_device> m_rtc;
required_device<ds1215_device> m_rtc;
required_device<pit8254_device> m_pit;
required_device<wd33c9x_base_device> m_scsi;
required_device_array<scn2681_device, 3> m_duart;