summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2024-09-21 14:33:46 +0200
committer hap <happppp@users.noreply.github.com>2024-09-21 14:34:14 +0200
commitf2015ac3a5e304e73b3f0768626cd13c5d746aba (patch)
treecd2cac61e4e4b60129d1053b4135c6bbf5c8002e /src
parent1174af0fe887f585faaa0cf77c19eda8982c1b51 (diff)
hmcs400: add nvram
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.cpp86
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.h18
-rw-r--r--src/devices/cpu/hmcs400/hmcs400op.cpp4
-rw-r--r--src/mame/cxg/royal.cpp37
-rw-r--r--src/mame/saitek/gk2000.cpp4
5 files changed, 137 insertions, 12 deletions
diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp
index ced9ac4d7f5..01e5ace61dd 100644
--- a/src/devices/cpu/hmcs400/hmcs400.cpp
+++ b/src/devices/cpu/hmcs400/hmcs400.cpp
@@ -71,8 +71,12 @@ DEFINE_DEVICE_TYPE(HD614089, hd614089_device, "hd614089", "Hitachi HD614089") //
hmcs400_cpu_device::hmcs400_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size) :
cpu_device(mconfig, type, tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
m_program_config("program", ENDIANNESS_LITTLE, 16, 14, -1, address_map_constructor(FUNC(hmcs400_cpu_device::program_map), this)),
m_data_config("data", ENDIANNESS_LITTLE, 8, 10, 0, address_map_constructor(FUNC(hmcs400_cpu_device::data_map), this)),
+ m_ram(*this, "ram%u", 0U),
+ m_nvram_defval(0),
+ m_nvram_battery(true),
m_rom_size(rom_size),
m_ram_size(ram_size),
m_has_div(false),
@@ -80,8 +84,12 @@ hmcs400_cpu_device::hmcs400_cpu_device(const machine_config &mconfig, device_typ
m_read_r(*this, 0),
m_write_r(*this),
m_read_d(*this, 0),
- m_write_d(*this)
-{ }
+ m_write_d(*this),
+ m_stop_cb(*this)
+{
+ // disable nvram by default (set to true if MCU is battery-backed when in stop mode)
+ nvram_enable_backup(false);
+}
hmcs400_cpu_device::~hmcs400_cpu_device() { }
@@ -205,6 +213,7 @@ void hmcs400_cpu_device::device_start()
m_timer_b_low = 0;
// register for savestates
+ save_item(NAME(m_nvram_battery));
save_item(NAME(m_pc));
save_item(NAME(m_prev_pc));
save_item(NAME(m_sp));
@@ -266,6 +275,7 @@ void hmcs400_cpu_device::device_reset()
m_st = 1;
m_standby = false;
m_stop = false;
+ m_stop_cb(0);
// clear peripherals
m_irq_flags = 0xaaa8; // IM=1, IF=0, IE=0
@@ -327,8 +337,8 @@ void hmcs400_cpu_device::data_map(address_map &map)
map(0x00a, 0x00a).rw(FUNC(hmcs400_cpu_device::tcbl_r), FUNC(hmcs400_cpu_device::tlrl_w));
map(0x00b, 0x00b).rw(FUNC(hmcs400_cpu_device::tcbu_r), FUNC(hmcs400_cpu_device::tlru_w));
- map(0x020, 0x020 + m_ram_size - 1).ram();
- map(0x3c0, 0x3ff).ram();
+ map(0x020, 0x020 + m_ram_size - 1).ram().share(m_ram[0]);
+ map(0x3c0, 0x3ff).ram().share(m_ram[1]); // stack
}
device_memory_interface::space_config_vector hmcs400_cpu_device::memory_space_config() const
@@ -341,6 +351,74 @@ device_memory_interface::space_config_vector hmcs400_cpu_device::memory_space_co
//-------------------------------------------------
+// nvram
+//-------------------------------------------------
+
+bool hmcs400_cpu_device::nvram_write(util::write_stream &file)
+{
+ // if it's currently not battery-backed, don't save at all
+ if (!m_nvram_battery)
+ return true;
+
+ std::error_condition err;
+ size_t actual;
+
+ // main RAM and stack area
+ for (auto & ram : m_ram)
+ {
+ std::tie(err, actual) = write(file, &ram[0], ram.bytes());
+ if (err)
+ return false;
+ }
+
+ return true;
+}
+
+bool hmcs400_cpu_device::nvram_read(util::read_stream &file)
+{
+ std::error_condition err;
+ size_t actual;
+
+ // main RAM and stack area
+ for (auto & ram : m_ram)
+ {
+ std::tie(err, actual) = read(file, &ram[0], ram.bytes());
+ if (err || (ram.bytes() != actual))
+ return false;
+ }
+
+ return true;
+}
+
+void hmcs400_cpu_device::nvram_default()
+{
+ if (!nvram_backup_enabled())
+ return;
+
+ // default nvram from mytag:nvram region if it exists
+ memory_region *region = memregion("nvram");
+ if (region != nullptr)
+ {
+ const u32 total = m_ram[0].bytes() + m_ram[1].bytes();
+ if (region->bytes() != total)
+ fatalerror("%s: Wrong region size (expected 0x%x, found 0x%x)", region->name(), total, region->bytes());
+
+ u32 offset = 0;
+ for (auto & ram : m_ram)
+ {
+ std::copy_n(&region->as_u8(offset), ram.bytes(), &ram[0]);
+ offset += ram.bytes();
+ }
+ }
+ else
+ {
+ for (auto & ram : m_ram)
+ std::fill_n(&ram[0], ram.bytes(), m_nvram_defval);
+ }
+}
+
+
+//-------------------------------------------------
// i/o ports
//-------------------------------------------------
diff --git a/src/devices/cpu/hmcs400/hmcs400.h b/src/devices/cpu/hmcs400/hmcs400.h
index e3776cb39fd..6b26b38227a 100644
--- a/src/devices/cpu/hmcs400/hmcs400.h
+++ b/src/devices/cpu/hmcs400/hmcs400.h
@@ -63,7 +63,7 @@ enum
*/
-class hmcs400_cpu_device : public cpu_device
+class hmcs400_cpu_device : public cpu_device, public device_nvram_interface
{
public:
virtual ~hmcs400_cpu_device();
@@ -82,6 +82,12 @@ public:
// valid options: 4, 8, 16, default to 8
auto &set_divider(u8 div) { assert(m_has_div); m_divider = div; return *this; }
+ // nvram
+ void nvram_set_battery(int state) { m_nvram_battery = bool(state); } // default is 1 (nvram_enable_backup needs to be true)
+ void nvram_set_default_value(u8 val) { m_nvram_defval = val & 0xf; } // default is 0
+ auto stop_cb() { return m_stop_cb.bind(); } // notifier (not an output pin)
+ int stop_mode() { return m_stop ? 1 : 0; }
+
protected:
// construction
hmcs400_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size);
@@ -90,6 +96,11 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+
// device_execute_interface implementation
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + m_divider - 1) / m_divider; }
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * m_divider); }
@@ -114,6 +125,10 @@ protected:
address_space *m_program;
address_space *m_data;
+ required_shared_ptr_array<u8, 2> m_ram;
+ u8 m_nvram_defval;
+ bool m_nvram_battery; // keeps internal RAM intact after soft power-off
+
int m_icount;
int m_state_count;
@@ -161,6 +176,7 @@ protected:
devcb_write8::array<11> m_write_r;
devcb_read16 m_read_d;
devcb_write16 m_write_d;
+ devcb_write_line m_stop_cb;
// misc internal helpers
u8 ram_r(u8 mem_mask = 0xf);
diff --git a/src/devices/cpu/hmcs400/hmcs400op.cpp b/src/devices/cpu/hmcs400/hmcs400op.cpp
index 19cecc44b6a..ec7643f9193 100644
--- a/src/devices/cpu/hmcs400/hmcs400op.cpp
+++ b/src/devices/cpu/hmcs400/hmcs400op.cpp
@@ -683,6 +683,10 @@ void hmcs400_cpu_device::op_stop()
{
// STOP: Stop Mode
m_stop = true;
+
if (m_icount > 0)
m_icount = 0;
+
+ // all I/O pins go high-impedance
+ m_stop_cb(1);
}
diff --git a/src/mame/cxg/royal.cpp b/src/mame/cxg/royal.cpp
index 27570ebda5a..0c7ff7a6457 100644
--- a/src/mame/cxg/royal.cpp
+++ b/src/mame/cxg/royal.cpp
@@ -5,11 +5,12 @@
CXG Sphinx Royal family
-NOTE: Turn the power switch off before exiting MAME, otherwise NVRAM won't save
-properly. Only turn power off when it's the user's turn to move.
+NOTE: Turn the power switch (or button in supra's case) off before exiting MAME,
+otherwise NVRAM won't save properly. And only turn the power off when it's the
+user's turn to move, this is warned about in the manual.
TODO:
-- actually add nvram (needs to be added to hmcs400)
+- if/when MAME supports an exit callback, hook up power-off switch/button to that
Hardware notes:
- HD614042S, 4MHz XTAL
@@ -72,6 +73,7 @@ public:
void supra(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(granada_change_cpu_freq);
+ DECLARE_INPUT_CHANGED_MEMBER(supra_on_button);
protected:
virtual void machine_start() override;
@@ -92,6 +94,8 @@ private:
u8 m_lcd_select = 0;
// I/O handlers
+ void stop_mode(int state);
+
void update_lcd();
template<int N> void lcd_segs_w(u8 data);
void lcd_com_w(u8 data);
@@ -125,6 +129,26 @@ INPUT_CHANGED_MEMBER(royal_state::granada_change_cpu_freq)
I/O
*******************************************************************************/
+// power
+
+void royal_state::stop_mode(int state)
+{
+ // clear display
+ if (state)
+ {
+ m_lcd_pwm->clear();
+ m_led_pwm->clear();
+ }
+}
+
+INPUT_CHANGED_MEMBER(royal_state::supra_on_button)
+{
+ // stop mode check actually comes from D3 high-impedance state
+ if (newval && m_maincpu->stop_mode())
+ m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
+}
+
+
// LCD
void royal_state::update_lcd()
@@ -252,7 +276,7 @@ static INPUT_PORTS_START( supra )
PORT_INCLUDE( royal )
PORT_START("RESET")
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_POWER_ON)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_POWER_ON) PORT_CHANGED_MEMBER(DEVICE_SELF, royal_state, supra_on_button, 0)
INPUT_PORTS_END
@@ -265,6 +289,9 @@ void royal_state::royal(machine_config &config)
{
// basic machine hardware
HD614042(config, m_maincpu, 4_MHz_XTAL);
+ m_maincpu->nvram_enable_backup(true);
+ m_maincpu->stop_cb().set(m_maincpu, FUNC(hmcs400_cpu_device::nvram_set_battery));
+ m_maincpu->stop_cb().append(FUNC(royal_state::stop_mode));
m_maincpu->write_r<0>().set(FUNC(royal_state::lcd_segs_w<0>));
m_maincpu->read_r<1>().set(FUNC(royal_state::board_r<0>));
m_maincpu->read_r<2>().set(FUNC(royal_state::board_r<1>));
@@ -280,7 +307,7 @@ void royal_state::royal(machine_config &config)
SENSORBOARD(config, m_board).set_type(sensorboard_device::BUTTONS);
m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess));
m_board->set_delay(attotime::from_msec(150));
- //m_board->set_nvram_enable(true);
+ m_board->set_nvram_enable(true);
// video hardware
PWM_DISPLAY(config, m_lcd_pwm).set_size(8, 8);
diff --git a/src/mame/saitek/gk2000.cpp b/src/mame/saitek/gk2000.cpp
index e707b6bce4a..2a829ab3e6e 100644
--- a/src/mame/saitek/gk2000.cpp
+++ b/src/mame/saitek/gk2000.cpp
@@ -154,13 +154,13 @@ private:
u8 m_lcd_com = 0;
// I/O handlers
+ void standby(int state);
+
void lcd_pwm_w(offs_t offset, u8 data);
void update_lcd();
template <int N> void lcd_segs_w(u8 data);
void lcd_com_w(u8 data);
- void standby(int state);
-
void p2_w(u8 data);
u8 p4_r();
void p5_w(u8 data);