diff options
| author | 2024-09-21 14:33:46 +0200 | |
|---|---|---|
| committer | 2024-09-21 14:34:14 +0200 | |
| commit | f2015ac3a5e304e73b3f0768626cd13c5d746aba (patch) | |
| tree | cd2cac61e4e4b60129d1053b4135c6bbf5c8002e /src | |
| parent | 1174af0fe887f585faaa0cf77c19eda8982c1b51 (diff) | |
hmcs400: add nvram
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/cpu/hmcs400/hmcs400.cpp | 86 | ||||
| -rw-r--r-- | src/devices/cpu/hmcs400/hmcs400.h | 18 | ||||
| -rw-r--r-- | src/devices/cpu/hmcs400/hmcs400op.cpp | 4 | ||||
| -rw-r--r-- | src/mame/cxg/royal.cpp | 37 | ||||
| -rw-r--r-- | src/mame/saitek/gk2000.cpp | 4 |
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(®ion->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); |
