mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
m3002: New device
This commit is contained in:
parent
4f08f64bd7
commit
2d68e6dae9
@ -1761,6 +1761,18 @@ if (MACHINES["LINFLASH"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/m3002.h,MACHINES["M3002"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["M3002"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/m3002.cpp",
|
||||
MAME_DIR .. "src/devices/machine/m3002.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/m6m80011ap.h,MACHINES["M6M80011AP"] = true
|
||||
|
@ -514,6 +514,7 @@ MACHINES["LDVP931"] = true
|
||||
MACHINES["LINFLASH"] = true
|
||||
MACHINES["LPCI"] = true
|
||||
--MACHINES["LSI53C810"] = true
|
||||
--MACHINES["M3002"] = true
|
||||
--MACHINES["M68307"] = true
|
||||
--MACHINES["M68340"] = true
|
||||
MACHINES["M6M80011AP"] = true
|
||||
|
@ -536,6 +536,7 @@ MACHINES["LH5810"] = true
|
||||
MACHINES["LINFLASH"] = true
|
||||
MACHINES["LPCI"] = true
|
||||
MACHINES["LSI53C810"] = true
|
||||
MACHINES["M3002"] = true
|
||||
MACHINES["M68307"] = true
|
||||
MACHINES["M68340"] = true
|
||||
MACHINES["M6M80011AP"] = true
|
||||
|
490
src/devices/machine/m3002.cpp
Normal file
490
src/devices/machine/m3002.cpp
Normal file
@ -0,0 +1,490 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/**********************************************************************
|
||||
|
||||
EM Microelectronic-Marin (µem) M 3002 Real Time Clock
|
||||
|
||||
TODO:
|
||||
- Pulse output (256 Hz, second, minute, hour)
|
||||
- Test mode
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "m3002.h"
|
||||
|
||||
#define VERBOSE 1
|
||||
#include "logmacro.h"
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(M3002, m3002_device, "m3002", "EM M 3002 Real Time Clock")
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE CONSTRUCTION AND INITIALIZATION
|
||||
//**************************************************************************
|
||||
|
||||
ALLOW_SAVE_TYPE(m3002_device::mux_state);
|
||||
|
||||
//-------------------------------------------------
|
||||
// m3002_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
m3002_device::m3002_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, M3002, tag, owner, clock)
|
||||
, device_nvram_interface(mconfig, *this)
|
||||
, device_rtc_interface(mconfig, *this)
|
||||
, m_irq_callback(*this)
|
||||
, m_address(0)
|
||||
, m_mux_state(mux_state::INIT)
|
||||
, m_irq_active(false)
|
||||
, m_update_deferred(false)
|
||||
, m_second_timer(nullptr)
|
||||
{
|
||||
std::fill_n(&m_ram[0], 0x10, 0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_resolve_objects - resolve objects that
|
||||
// may be needed for other devices to set
|
||||
// initial conditions at start time
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::device_resolve_objects()
|
||||
{
|
||||
m_irq_callback.resolve_safe();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::device_start()
|
||||
{
|
||||
// Setup timer
|
||||
m_second_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m3002_device::second_timer), this));
|
||||
|
||||
// Save internal state
|
||||
save_item(NAME(m_ram));
|
||||
save_item(NAME(m_address));
|
||||
save_item(NAME(m_mux_state));
|
||||
save_item(NAME(m_irq_active));
|
||||
save_item(NAME(m_update_deferred));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_clock_changed - called when the
|
||||
// device clock is altered in any way
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::device_clock_changed()
|
||||
{
|
||||
attotime second = clocks_to_attotime(32768);
|
||||
m_second_timer->adjust(second, 0, second);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_read - read NVRAM from the file
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::nvram_read(emu_file &file)
|
||||
{
|
||||
file.read(&m_ram[0], 0x10);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_write - write NVRAM to the file
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::nvram_write(emu_file &file)
|
||||
{
|
||||
file.write(&m_ram[0], 0x10);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_default - initialize NVRAM to its
|
||||
// default state
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::nvram_default()
|
||||
{
|
||||
// Set watch, alarm and timer registers to minimum values
|
||||
m_ram[0x0] = m_ram[0x8] = m_ram[0xc] = 0x00;
|
||||
m_ram[0x1] = m_ram[0x9] = m_ram[0xd] = 0x00;
|
||||
m_ram[0x2] = m_ram[0xa] = m_ram[0xe] = 0x00;
|
||||
m_ram[0x3] = m_ram[0xb] = 0x01;
|
||||
m_ram[0x4] = 0x01;
|
||||
m_ram[0x5] = 0x00;
|
||||
m_ram[0x6] = 0x01;
|
||||
m_ram[0x7] = 0x01;
|
||||
|
||||
// Allow watch to operate
|
||||
m_ram[0xf] = 0x01;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rtc_clock_updated - set emulated time
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
|
||||
{
|
||||
if (!BIT(m_ram[0xf], 0))
|
||||
return;
|
||||
|
||||
m_ram[0x0] = convert_to_bcd(second);
|
||||
m_ram[0x1] = convert_to_bcd(minute);
|
||||
m_ram[0x2] = convert_to_bcd(hour);
|
||||
m_ram[0x3] = convert_to_bcd(day);
|
||||
m_ram[0x4] = convert_to_bcd(month);
|
||||
m_ram[0x5] = convert_to_bcd(year);
|
||||
m_ram[0x6] = convert_to_bcd(day_of_week);
|
||||
|
||||
unsigned day_of_year = day - 1;
|
||||
for (int n = 1; n < month; n++)
|
||||
{
|
||||
if (n == 2)
|
||||
day_of_year += (year % 4) == 0 ? 29 : 28;
|
||||
else
|
||||
day_of_year += BIT(0xa50, n) ? 30 : 31;
|
||||
}
|
||||
m_ram[0x7] = convert_to_bcd((day_of_year + 7 - day_of_week) / 7 + 1);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERNAL UPDATE CYCLES
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// internal_busy - return true if in the middle
|
||||
// of a once-per-second update
|
||||
//-------------------------------------------------
|
||||
|
||||
bool m3002_device::internal_busy() const
|
||||
{
|
||||
// Each internal update lasts between 0.73 ms and 6 ms
|
||||
return attotime_to_clocks(m_second_timer->remaining()) < 239;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// bcd_increment - increment the value of one RAM
|
||||
// location using BCD sequence
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::bcd_increment(u8 location)
|
||||
{
|
||||
if ((m_ram[location] & 0x09) != 0x09)
|
||||
m_ram[location]++;
|
||||
else
|
||||
{
|
||||
if ((m_ram[location] & 0x90) != 0x90)
|
||||
m_ram[location] = (m_ram[location] & 0xf0) + 0x10;
|
||||
else
|
||||
m_ram[location] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// max_date - return the maximum date (BCD) in
|
||||
// the current month
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 m3002_device::max_date() const
|
||||
{
|
||||
if (m_ram[4] == 0x02)
|
||||
return (m_ram[5] & 0x03) == 0x00 ? 0x29 : 0x28;
|
||||
else
|
||||
return BIT(0x20250, m_ram[4]) ? 0x30 : 0x31;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// watch_update - update watch registers
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::watch_update()
|
||||
{
|
||||
// Count seconds
|
||||
if (m_ram[0x0] != 0x59)
|
||||
{
|
||||
bcd_increment(0x0);
|
||||
return;
|
||||
}
|
||||
m_ram[0x0] = 0x00;
|
||||
|
||||
// Count minutes
|
||||
if (m_ram[0x1] != 0x59)
|
||||
{
|
||||
bcd_increment(0x1);
|
||||
return;
|
||||
}
|
||||
m_ram[0x1] = 0x00;
|
||||
|
||||
// Count hours
|
||||
if (m_ram[0x2] != 0x23)
|
||||
{
|
||||
bcd_increment(0x2);
|
||||
return;
|
||||
}
|
||||
m_ram[0x2] = 0x00;
|
||||
|
||||
// Count weekdays
|
||||
if (m_ram[0x6] != 0x07)
|
||||
bcd_increment(0x6);
|
||||
else
|
||||
{
|
||||
m_ram[0x6] = 0x01;
|
||||
|
||||
// Count weeks
|
||||
bcd_increment(0x7);
|
||||
}
|
||||
|
||||
// Count date
|
||||
if (m_ram[0x3] != max_date())
|
||||
{
|
||||
bcd_increment(0x3);
|
||||
return;
|
||||
}
|
||||
m_ram[0x3] = 0x01;
|
||||
|
||||
// Count months
|
||||
if (m_ram[0x4] != 0x12)
|
||||
{
|
||||
bcd_increment(0x4);
|
||||
return;
|
||||
}
|
||||
m_ram[0x4] = 0x01;
|
||||
m_ram[0x7] = 0x01;
|
||||
|
||||
// Count years
|
||||
bcd_increment(5);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// alarm_update - compare alarm registers against
|
||||
// watch registers
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::alarm_update()
|
||||
{
|
||||
// Compare seconds, minutes, hours, date
|
||||
for (int r = 0x0; r <= 0x3; r++)
|
||||
if (m_ram[0x8 + r] != 0xff && m_ram[0x8 + r] != m_ram[r])
|
||||
return;
|
||||
|
||||
// Alarm IRQ
|
||||
m_ram[0xf] |= 0x04;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// timer_update - update timer registers
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::timer_update()
|
||||
{
|
||||
// Count seconds
|
||||
if (m_ram[0xc] != 0x59)
|
||||
{
|
||||
bcd_increment(0xc);
|
||||
return;
|
||||
}
|
||||
m_ram[0xc] = 0x00;
|
||||
|
||||
// Count minutes
|
||||
if (m_ram[0xd] != 0x59)
|
||||
{
|
||||
bcd_increment(0xd);
|
||||
return;
|
||||
}
|
||||
m_ram[0xd] = 0x00;
|
||||
|
||||
// Count hours
|
||||
if (m_ram[0xe] != 0x23)
|
||||
{
|
||||
bcd_increment(0xe);
|
||||
return;
|
||||
}
|
||||
m_ram[0xe] = 0x00;
|
||||
|
||||
// Timer IRQ (23:59:59 -> 00:00:00)
|
||||
m_ram[0xf] |= 0x08;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// irq_update - update IRQ output
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::irq_update()
|
||||
{
|
||||
if (!m_irq_active && (m_ram[0xf] & 0x0c) != 0)
|
||||
{
|
||||
LOG("IRQ occurred\n");
|
||||
m_irq_active = true;
|
||||
m_irq_callback(ASSERT_LINE);
|
||||
}
|
||||
else if (m_irq_active && (m_ram[0xf] & 0x0c) == 0)
|
||||
{
|
||||
LOG("IRQ cleared\n");
|
||||
m_irq_active = false;
|
||||
m_irq_callback(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// update - perform one full internal update
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::update()
|
||||
{
|
||||
if (BIT(m_ram[0xf], 0))
|
||||
{
|
||||
watch_update();
|
||||
if (BIT(m_ram[0xf], 1))
|
||||
alarm_update();
|
||||
}
|
||||
|
||||
if (BIT(m_ram[0xf], 4))
|
||||
timer_update();
|
||||
|
||||
irq_update();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// second_timer - called once each second
|
||||
//-------------------------------------------------
|
||||
|
||||
TIMER_CALLBACK_MEMBER(m3002_device::second_timer)
|
||||
{
|
||||
if (m_update_deferred)
|
||||
{
|
||||
m_update_deferred = false;
|
||||
update();
|
||||
}
|
||||
else if (m_mux_state != mux_state::INIT)
|
||||
m_update_deferred = true;
|
||||
|
||||
if (!m_update_deferred)
|
||||
update();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// MICROPROCESSOR ACCESS
|
||||
//**************************************************************************
|
||||
|
||||
const char *const m3002_device::s_register_names[0x10] =
|
||||
{
|
||||
"watch seconds",
|
||||
"watch minutes",
|
||||
"watch hours",
|
||||
"watch date",
|
||||
"watch month",
|
||||
"watch year",
|
||||
"watch weekday",
|
||||
"watch week",
|
||||
"alarm seconds",
|
||||
"alarm minutes",
|
||||
"alarm hours",
|
||||
"alarm date",
|
||||
"timer seconds",
|
||||
"timer minutes",
|
||||
"timer hours",
|
||||
"status/control"
|
||||
};
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_init_state - return the multiplexer to the
|
||||
// initial state
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::set_init_state()
|
||||
{
|
||||
m_mux_state = mux_state::INIT;
|
||||
if (m_update_deferred)
|
||||
{
|
||||
m_update_deferred = false;
|
||||
update();
|
||||
}
|
||||
irq_update();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read - read data or busy status using 3-step
|
||||
// access sequence
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 m3002_device::read()
|
||||
{
|
||||
u8 data = 0x0;
|
||||
|
||||
switch (m_mux_state)
|
||||
{
|
||||
case mux_state::INIT:
|
||||
if (internal_busy())
|
||||
data = 0xf;
|
||||
break;
|
||||
|
||||
case mux_state::TENS:
|
||||
data = m_ram[m_address] >> 4;
|
||||
if (!machine().side_effects_disabled())
|
||||
m_mux_state = mux_state::UNITS;
|
||||
break;
|
||||
|
||||
case mux_state::UNITS:
|
||||
data = m_ram[m_address] & 0x0f;
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
LOG("%s: Read %02X from %s register\n", machine().describe_context(), m_ram[m_address], s_register_names[m_address]);
|
||||
set_init_state();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write - write address and/or data using 3-step
|
||||
// access sequence
|
||||
//-------------------------------------------------
|
||||
|
||||
void m3002_device::write(u8 data)
|
||||
{
|
||||
data &= 0xf;
|
||||
|
||||
switch (m_mux_state)
|
||||
{
|
||||
case mux_state::INIT:
|
||||
m_address = data;
|
||||
m_mux_state = mux_state::TENS;
|
||||
break;
|
||||
|
||||
case mux_state::TENS:
|
||||
m_ram[m_address] = (data << 4) | (m_ram[m_address] & 0x0f);
|
||||
m_mux_state = mux_state::UNITS;
|
||||
break;
|
||||
|
||||
case mux_state::UNITS:
|
||||
m_ram[m_address] = (m_ram[m_address] & 0xf0) | data;
|
||||
LOG("%s: Writing %02X to %s register\n", machine().describe_context(), m_ram[m_address], s_register_names[m_address]);
|
||||
set_init_state();
|
||||
break;
|
||||
}
|
||||
}
|
101
src/devices/machine/m3002.h
Normal file
101
src/devices/machine/m3002.h
Normal file
@ -0,0 +1,101 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/**********************************************************************
|
||||
|
||||
EM Microelectronic-Marin (µem) M 3002 Real Time Clock
|
||||
|
||||
***********************************************************************
|
||||
____ ____
|
||||
Vbb 1 |* \__/ | 16 Vdd
|
||||
XI 2 | | 15 _PULSE
|
||||
XO 3 | | 14 _BUSY
|
||||
_SYNC 4 | | 13 _IRQ
|
||||
R/_W 5 | M 3002 | 12 I/O 3
|
||||
_OE 6 | | 11 I/O 2
|
||||
_CS 7 | | 10 I/O 1
|
||||
Vss 8 |____________| 9 I/O 0
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_M3002_H
|
||||
#define MAME_MACHINE_M3002_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dirtc.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> m3002_device
|
||||
|
||||
class m3002_device : public device_t, public device_nvram_interface, public device_rtc_interface
|
||||
{
|
||||
public:
|
||||
// device type constructor
|
||||
m3002_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// 4-bit read/write handlers
|
||||
u8 read();
|
||||
void write(u8 data);
|
||||
|
||||
// status output polling
|
||||
DECLARE_READ_LINE_MEMBER(busy_r) { return internal_busy() ? 0 : 1; }
|
||||
DECLARE_READ_LINE_MEMBER(irq_r) { return m_irq_active ? 0 : 1; }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_clock_changed() override;
|
||||
|
||||
// device_nvram_interface overrides
|
||||
virtual void nvram_read(emu_file &file) override;
|
||||
virtual void nvram_write(emu_file &file) override;
|
||||
virtual void nvram_default() override;
|
||||
|
||||
// device_rtc_interface overrides
|
||||
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;
|
||||
|
||||
private:
|
||||
static const char *const s_register_names[0x10];
|
||||
|
||||
enum class mux_state : u8
|
||||
{
|
||||
INIT,
|
||||
TENS,
|
||||
UNITS
|
||||
};
|
||||
|
||||
// internal helpers
|
||||
bool internal_busy() const;
|
||||
void bcd_increment(u8 location);
|
||||
u8 max_date() const;
|
||||
void watch_update();
|
||||
void alarm_update();
|
||||
void timer_update();
|
||||
void irq_update();
|
||||
void update();
|
||||
TIMER_CALLBACK_MEMBER(second_timer);
|
||||
void set_init_state();
|
||||
|
||||
// callback objects
|
||||
devcb_write_line m_irq_callback;
|
||||
|
||||
// internal state
|
||||
u8 m_ram[16];
|
||||
u8 m_address;
|
||||
mux_state m_mux_state;
|
||||
bool m_irq_active;
|
||||
bool m_update_deferred;
|
||||
emu_timer *m_second_timer;
|
||||
};
|
||||
|
||||
// device type declaration
|
||||
DECLARE_DEVICE_TYPE(M3002, m3002_device)
|
||||
|
||||
#endif // MAME_MACHINE_M3002_H
|
@ -34,7 +34,7 @@
|
||||
#include "bus/isa/aga.h"
|
||||
#include "bus/isa/fdc.h"
|
||||
#include "machine/genpc.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/m3002.h"
|
||||
#include "machine/pckeybrd.h"
|
||||
#include "machine/ram.h"
|
||||
|
||||
@ -50,6 +50,7 @@ public:
|
||||
m_mb(*this, "mb"),
|
||||
m_keyboard(*this, "pc_keyboard"),
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_rtc(*this, "rtc"),
|
||||
m_jim_state(0),
|
||||
m_port61(0)
|
||||
{ }
|
||||
@ -65,6 +66,7 @@ private:
|
||||
required_device<pc_noppi_mb_device> m_mb;
|
||||
required_device<pc_keyboard_device> m_keyboard;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<m3002_device> m_rtc;
|
||||
|
||||
DECLARE_WRITE8_MEMBER( europc_pio_w );
|
||||
DECLARE_READ8_MEMBER( europc_pio_r );
|
||||
@ -73,26 +75,11 @@ private:
|
||||
DECLARE_READ8_MEMBER ( europc_jim_r );
|
||||
DECLARE_READ8_MEMBER ( europc_jim2_r );
|
||||
|
||||
DECLARE_READ8_MEMBER( europc_rtc_r );
|
||||
DECLARE_WRITE8_MEMBER( europc_rtc_w );
|
||||
|
||||
void europc_rtc_set_time();
|
||||
|
||||
uint8_t m_jim_data[16];
|
||||
uint8_t m_jim_state;
|
||||
isa8_aga_device::mode_t m_jim_mode;
|
||||
int m_port61; // bit 0,1 must be 0 for startup; reset?
|
||||
uint8_t m_rtc_data[0x10];
|
||||
int m_rtc_reg;
|
||||
int m_rtc_state;
|
||||
|
||||
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
emu_timer* m_rtc_timer;
|
||||
|
||||
enum
|
||||
{
|
||||
TIMER_RTC
|
||||
};
|
||||
void europc_io(address_map &map);
|
||||
void europc_map(address_map &map);
|
||||
};
|
||||
@ -208,7 +195,7 @@ WRITE8_MEMBER( europc_pc_state::europc_jim_w )
|
||||
}
|
||||
break;
|
||||
case 0xa:
|
||||
europc_rtc_w(space, 0, data);
|
||||
m_rtc->write(data);
|
||||
return;
|
||||
}
|
||||
logerror("jim write %.2x %.2x\n", offset, data);
|
||||
@ -222,7 +209,7 @@ READ8_MEMBER( europc_pc_state::europc_jim_r )
|
||||
{
|
||||
case 4: case 5: case 6: case 7: data = m_jim_data[offset]; break;
|
||||
case 0: case 1: case 2: case 3: data = 0; break;
|
||||
case 0xa: return europc_rtc_r(space, 0);
|
||||
case 0xa: return m_rtc->read();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@ -271,99 +258,6 @@ READ8_MEMBER( europc_pc_state::europc_jim2_r )
|
||||
reg 0f: 01 status ok, when not 01 written
|
||||
*/
|
||||
|
||||
void europc_pc_state::europc_rtc_set_time()
|
||||
{
|
||||
system_time systime;
|
||||
|
||||
/* get the current date/time from the core */
|
||||
machine().current_datetime(systime);
|
||||
|
||||
m_rtc_data[0] = dec_2_bcd(systime.utc_time.second);
|
||||
m_rtc_data[1] = dec_2_bcd(systime.utc_time.minute);
|
||||
m_rtc_data[2] = dec_2_bcd(systime.utc_time.hour);
|
||||
|
||||
m_rtc_data[3] = dec_2_bcd(systime.utc_time.mday);
|
||||
m_rtc_data[4] = dec_2_bcd(systime.utc_time.month + 1);
|
||||
m_rtc_data[5] = dec_2_bcd(systime.utc_time.year % 100);
|
||||
}
|
||||
|
||||
void europc_pc_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
int month, year;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case TIMER_RTC:
|
||||
m_rtc_data[0]=bcd_adjust(m_rtc_data[0]+1);
|
||||
if (m_rtc_data[0]>=0x60)
|
||||
{
|
||||
m_rtc_data[0]=0;
|
||||
m_rtc_data[1]=bcd_adjust(m_rtc_data[1]+1);
|
||||
if (m_rtc_data[1]>=0x60)
|
||||
{
|
||||
m_rtc_data[1]=0;
|
||||
m_rtc_data[2]=bcd_adjust(m_rtc_data[2]+1);
|
||||
if (m_rtc_data[2]>=0x24)
|
||||
{
|
||||
m_rtc_data[2]=0;
|
||||
m_rtc_data[3]=bcd_adjust(m_rtc_data[3]+1);
|
||||
month=bcd_2_dec(m_rtc_data[4]);
|
||||
year=bcd_2_dec(m_rtc_data[5])+2000; // save for julian_days_in_month_calculation
|
||||
if (m_rtc_data[3]> gregorian_days_in_month(month, year))
|
||||
{
|
||||
m_rtc_data[3]=1;
|
||||
m_rtc_data[4]=bcd_adjust(m_rtc_data[4]+1);
|
||||
if (m_rtc_data[4]>0x12)
|
||||
{
|
||||
m_rtc_data[4]=1;
|
||||
m_rtc_data[5]=bcd_adjust(m_rtc_data[5]+1)&0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( europc_pc_state::europc_rtc_r )
|
||||
{
|
||||
int data=0;
|
||||
switch (m_rtc_state)
|
||||
{
|
||||
case 1:
|
||||
data=(m_rtc_data[m_rtc_reg]&0xf0)>>4;
|
||||
m_rtc_state++;
|
||||
break;
|
||||
case 2:
|
||||
data=m_rtc_data[m_rtc_reg]&0xf;
|
||||
m_rtc_state=0;
|
||||
// logerror("rtc read %x %.2x\n",m_rtc_reg, m_rtc_data[m_rtc_reg]);
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( europc_pc_state::europc_rtc_w )
|
||||
{
|
||||
switch (m_rtc_state)
|
||||
{
|
||||
case 0:
|
||||
m_rtc_reg=data;
|
||||
m_rtc_state=1;
|
||||
break;
|
||||
case 1:
|
||||
m_rtc_data[m_rtc_reg]=(m_rtc_data[m_rtc_reg]&~0xf0)|((data&0xf)<<4);
|
||||
m_rtc_state++;
|
||||
break;
|
||||
case 2:
|
||||
m_rtc_data[m_rtc_reg]=(m_rtc_data[m_rtc_reg]&~0xf)|(data&0xf);
|
||||
m_rtc_state=0;
|
||||
// logerror("rtc written %x %.2x\n",m_rtc_reg, m_rtc_data[m_rtc_reg]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void europc_pc_state::init_europc()
|
||||
{
|
||||
uint8_t *rom = &memregion("bios")->base()[0];
|
||||
@ -380,17 +274,6 @@ void europc_pc_state::init_europc()
|
||||
a += rom[i];
|
||||
rom[0xffff] = 256 - a;
|
||||
}
|
||||
|
||||
memset(&m_rtc_data,0,sizeof(m_rtc_data));
|
||||
m_rtc_reg = 0;
|
||||
m_rtc_state = 0;
|
||||
m_rtc_data[0xf]=1;
|
||||
|
||||
m_rtc_timer = timer_alloc();
|
||||
m_rtc_timer->adjust(attotime::zero, 0, attotime(1,0));
|
||||
// europc_rtc_set_time();
|
||||
|
||||
subdevice<nvram_device>("nvram")->set_base(m_rtc_data, sizeof(m_rtc_data));
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( europc_pc_state::europc_pio_w )
|
||||
@ -591,7 +474,7 @@ void europc_pc_state::europc(machine_config &config)
|
||||
PC_KEYB(config, m_keyboard);
|
||||
m_keyboard->keypress().set("mb:pic8259", FUNC(pic8259_device::ir1_w));
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);;
|
||||
M3002(config, m_rtc, 32.768_kHz_XTAL);
|
||||
|
||||
/* internal ram */
|
||||
// Machine came with 512K standard, 640K via expansion card, but BIOS offers 256K as well
|
||||
|
Loading…
Reference in New Issue
Block a user