From 2da636bb214ee65c339b385ffc3be275d06ff76e Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 2 Jan 2025 12:30:59 +0700 Subject: 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 --- scripts/src/machine.lua | 8 +- src/devices/bus/bbc/rom/rtc.cpp | 22 +-- src/devices/bus/bbc/rom/rtc.h | 4 +- src/devices/bus/coco/coco_fdc.cpp | 1 - src/devices/bus/cpc/smartwatch.cpp | 31 +--- src/devices/bus/cpc/smartwatch.h | 7 +- src/devices/bus/vme/mvme181.cpp | 14 +- src/devices/bus/vme/mvme181.h | 4 +- src/devices/machine/ds1215.cpp | 350 +++++++++++++++++++++++++++++++++++++ src/devices/machine/ds1215.h | 77 ++++++++ src/devices/machine/ds1315.cpp | 305 -------------------------------- src/devices/machine/ds1315.h | 65 ------- src/mame/apple/apple2e.cpp | 17 +- src/mame/dec/rainbow.cpp | 92 +++------- src/mame/homebrew/pc532.cpp | 19 +- src/mame/sgi/ip4.cpp | 24 +-- src/mame/sgi/ip4.h | 4 +- 17 files changed, 515 insertions(+), 529 deletions(-) create mode 100644 src/devices/machine/ds1215.cpp create mode 100644 src/devices/machine/ds1215.h delete mode 100644 src/devices/machine/ds1315.cpp delete mode 100644 src/devices/machine/ds1315.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 3cc9b40227b..5172bcc4381 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -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 diff --git a/src/devices/bus/bbc/rom/rtc.cpp b/src/devices/bus/bbc/rom/rtc.cpp index 436783f3641..e2c34beb20d 100644 --- a/src/devices/bus/bbc/rom/rtc.cpp +++ b/src/devices/bus/bbc/rom/rtc.cpp @@ -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; } diff --git a/src/devices/bus/bbc/rom/rtc.h b/src/devices/bus/bbc/rom/rtc.h index 7849e69545d..d975fed41ce 100644 --- a/src/devices/bus/bbc/rom/rtc.h +++ b/src/devices/bus/bbc/rom/rtc.h @@ -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 m_rtc; + required_device m_rtc; }; // device type definition diff --git a/src/devices/bus/coco/coco_fdc.cpp b/src/devices/bus/coco/coco_fdc.cpp index 0b4ec90d2cb..dfd68864f18 100644 --- a/src/devices/bus/coco/coco_fdc.cpp +++ b/src/devices/bus/coco/coco_fdc.cpp @@ -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" diff --git a/src/devices/bus/cpc/smartwatch.cpp b/src/devices/bus/cpc/smartwatch.cpp index a58b30f2c0a..4b2aa04cd10 100644 --- a/src/devices/bus/cpc/smartwatch.cpp +++ b/src/devices/bus/cpc/smartwatch.cpp @@ -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* 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 cpc_smartwatch_device::rtc_r(offs_t offset) { 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]; } diff --git a/src/devices/bus/cpc/smartwatch.h b/src/devices/bus/cpc/smartwatch.h index 2e682643b32..3c9959f6590 100644 --- a/src/devices/bus/cpc/smartwatch.h +++ b/src/devices/bus/cpc/smartwatch.h @@ -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 m_rtc; + required_device m_rtc; memory_bank* m_bank; }; diff --git a/src/devices/bus/vme/mvme181.cpp b/src/devices/bus/vme/mvme181.cpp index 55d5d601035..ef098c64d46 100644 --- a/src/devices/bus/vme/mvme181.cpp +++ b/src/devices/bus/vme/mvme181.cpp @@ -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>)); diff --git a/src/devices/bus/vme/mvme181.h b/src/devices/bus/vme/mvme181.h index aaa4acf954e..ccdf1cc4ede 100644 --- a/src/devices/bus/vme/mvme181.h +++ b/src/devices/bus/vme/mvme181.h @@ -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 m_cpu; required_device_array m_mmu; - required_device m_rtc; + required_device m_rtc; required_device m_duart; required_device_array m_serial; diff --git a/src/devices/machine/ds1215.cpp b/src/devices/machine/ds1215.cpp new file mode 100644 index 00000000000..9d1a8b1ec0b --- /dev/null +++ b/src/devices/machine/ds1215.cpp @@ -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; +} diff --git a/src/devices/machine/ds1215.h b/src/devices/machine/ds1215.h new file mode 100644 index 00000000000..ceab96f7201 --- /dev/null +++ b/src/devices/machine/ds1215.h @@ -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 diff --git a/src/devices/machine/ds1315.cpp b/src/devices/machine/ds1315.cpp deleted file mode 100644 index 812f39dffba..00000000000 --- a/src/devices/machine/ds1315.cpp +++ /dev/null @@ -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; -} diff --git a/src/devices/machine/ds1315.h b/src/devices/machine/ds1315.h deleted file mode 100644 index f42152c19a7..00000000000 --- a/src/devices/machine/ds1315.h +++ /dev/null @@ -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 diff --git a/src/mame/apple/apple2e.cpp b/src/mame/apple/apple2e.cpp index 30845cdfaaf..ab478991093 100644 --- a/src/mame/apple/apple2e.cpp +++ b/src/mame/apple/apple2e.cpp @@ -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 m_acia1, m_acia2; optional_device m_iwm; optional_device_array m_floppy; - required_device m_ds1315; + required_device m_ds1315; optional_device m_printer_conn; optional_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); diff --git a/src/mame/dec/rainbow.cpp b/src/mame/dec/rainbow.cpp index cce1a9af14e..2a5bedd48a6 100644 --- a/src/mame/dec/rainbow.cpp +++ b/src/mame/dec/rainbow.cpp @@ -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 m_p_vol_ram; required_shared_ptr m_p_nvram; - optional_device m_rtc; - required_device m_hgdc; // GDC required_device m_screen2; required_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 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 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 * } //---------------------------------------------------------------------------------------- diff --git a/src/mame/homebrew/pc532.cpp b/src/mame/homebrew/pc532.cpp index cef4b338a6c..19c169b7cb1 100644 --- a/src/mame/homebrew/pc532.cpp +++ b/src/mame/homebrew/pc532.cpp @@ -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 m_fpu; required_device m_icu; - required_device m_rtc; + required_device m_rtc; required_device m_ncr5380; required_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); diff --git a/src/mame/sgi/ip4.cpp b/src/mame/sgi/ip4.cpp index fe7f4bec944..6f1e7a996f0 100644 --- a/src/mame/sgi/ip4.cpp +++ b/src/mame/sgi/ip4.cpp @@ -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) diff --git a/src/mame/sgi/ip4.h b/src/mame/sgi/ip4.h index 0f20770b441..88c0b2a0b1d 100644 --- a/src/mame/sgi/ip4.h +++ b/src/mame/sgi/ip4.h @@ -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 m_cpu; - required_device m_rtc; + required_device m_rtc; required_device m_pit; required_device m_scsi; required_device_array m_duart; -- cgit v1.2.3