ccompan2: remove standbytimer,

hlcd0515/mattelchess: add nvram
This commit is contained in:
hap 2023-11-09 16:21:07 +01:00
parent eb1d4f8ad7
commit 7a691be059
6 changed files with 128 additions and 62 deletions

View File

@ -22,14 +22,14 @@ DEFINE_DEVICE_TYPE(NVRAM, nvram_device, "nvram", "NVRAM")
// nvram_device - constructor
//-------------------------------------------------
nvram_device::nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NVRAM, tag, owner, clock),
device_nvram_interface(mconfig, *this),
m_region(*this, DEVICE_SELF),
m_default_value(DEFAULT_ALL_1),
m_custom_handler(*this),
m_base(nullptr),
m_length(0)
nvram_device::nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, NVRAM, tag, owner, clock),
device_nvram_interface(mconfig, *this),
m_region(*this, DEVICE_SELF),
m_default_value(DEFAULT_ALL_1),
m_custom_handler(*this),
m_base(nullptr),
m_length(0)
{
}

View File

@ -30,9 +30,13 @@ DEFINE_DEVICE_TYPE(HLCD0601, hlcd0601_device, "hlcd0601", "Hughes HLCD 0601 LCD
hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 colmax) :
device_t(mconfig, type, tag, owner, clock),
device_nvram_interface(mconfig, *this),
m_colmax(colmax),
m_write_cols(*this), m_write_data(*this)
{ }
{
// disable nvram by default
nvram_enable_backup(false);
}
hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
hlcd0515_device(mconfig, HLCD0515, tag, owner, clock, 25)
@ -56,18 +60,9 @@ hlcd0601_device::hlcd0601_device(const machine_config &mconfig, const char *tag,
// device_start - device-specific startup
//-------------------------------------------------
void hlcd0515_device::device_start()
void hlcd0515_device::internal_clear()
{
// timer
m_lcd_timer = timer_alloc(FUNC(hlcd0515_device::scan_lcd), this);
attotime period = attotime::from_hz(clock() / 2);
m_lcd_timer->adjust(period, 0, period);
// zerofill
m_cs = 0;
m_clk = 0;
m_data = 0;
m_dataout = 0;
// clear internal registers and RAM
m_count = 0;
m_control = 0;
m_blank = false;
@ -76,6 +71,21 @@ void hlcd0515_device::device_start()
m_rowsel = 0;
m_buffer = 0;
memset(m_ram, 0, sizeof(m_ram));
}
void hlcd0515_device::device_start()
{
// timer
m_lcd_timer = timer_alloc(FUNC(hlcd0515_device::scan_lcd), this);
attotime period = attotime::from_hz(clock() / 2);
m_lcd_timer->adjust(period, 0, period);
// zerofill
internal_clear();
m_cs = 0;
m_clk = 0;
m_data = 0;
m_dataout = 0;
// register for savestates
save_item(NAME(m_cs));
@ -95,7 +105,63 @@ void hlcd0515_device::device_start()
//-------------------------------------------------
// scan_lcd -
// nvram (when VDD is battery-backed, rare occurence)
//-------------------------------------------------
bool hlcd0515_device::nvram_write(util::write_stream &file)
{
size_t actual;
// misc internal registers
u8 buf[6];
buf[0] = m_count;
buf[1] = m_control;
buf[2] = m_blank ? 1 : 0;
buf[3] = m_rowmax;
buf[4] = m_rowout;
buf[5] = m_rowsel;
if (file.write(&buf, sizeof(buf), actual) || (sizeof(buf) != actual))
return false;
// shift register and RAM
if (file.write(&m_buffer, sizeof(m_buffer), actual) || (sizeof(m_buffer) != actual))
return false;
if (file.write(&m_ram, sizeof(m_ram), actual) || (sizeof(m_ram) != actual))
return false;
return true;
}
bool hlcd0515_device::nvram_read(util::read_stream &file)
{
size_t actual;
// misc internal registers
u8 buf[6];
if (file.read(&buf, sizeof(buf), actual) || (sizeof(buf) != actual))
return false;
m_count = buf[0];
m_control = buf[1];
m_blank = bool(buf[2]);
m_rowmax = buf[3] & 7;
m_rowout = buf[4] & 7;
m_rowsel = buf[5] & 7;
// shift register and RAM
if (file.read(&m_buffer, sizeof(m_buffer), actual) || (sizeof(m_buffer) != actual))
return false;
if (file.read(&m_ram, sizeof(m_ram), actual) || (sizeof(m_ram) != actual))
return false;
return true;
}
//-------------------------------------------------
// I/O handlers
//-------------------------------------------------
TIMER_CALLBACK_MEMBER(hlcd0515_device::scan_lcd)
@ -109,11 +175,6 @@ TIMER_CALLBACK_MEMBER(hlcd0515_device::scan_lcd)
}
//-------------------------------------------------
// handlers
//-------------------------------------------------
void hlcd0515_device::set_control()
{
// clock 0,1,2: row select
@ -178,7 +239,6 @@ void hlcd0515_device::clock_w(int state)
if (m_count == 4)
set_control();
}
else
clock_data(m_count - 5);

View File

@ -41,7 +41,7 @@
*/
class hlcd0515_device : public device_t
class hlcd0515_device : public device_t, public device_nvram_interface
{
public:
hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
@ -61,6 +61,12 @@ protected:
// device-level overrides
virtual void device_start() override;
// device_nvram_interface overrides
virtual void nvram_default() override { internal_clear(); }
virtual bool nvram_read(util::read_stream &file) override;
virtual bool nvram_write(util::write_stream &file) override;
void internal_clear();
TIMER_CALLBACK_MEMBER(scan_lcd);
virtual void set_control();
@ -72,7 +78,7 @@ protected:
int m_clk; // "
int m_data; // "
int m_dataout; // DATA OUT pin state
int m_count;
u8 m_count;
u8 m_control;
bool m_blank; // display blank/visible
u8 m_rowmax; // number of rows output by lcd (max 8)

View File

@ -37,9 +37,8 @@ license:CC0-1.0
</element>
<element name="text_switch" defstate="0">
<rect><color red="0.12" green="0.03" blue="0.4" /></rect>
<text string="POWER SWITCH: ON" align="1" state="0"><color red="0.4" green="0.4" blue="0.55" /></text>
<text string="POWER SWITCH: SAVE" align="1" state="1"><color red="0.4" green="0.4" blue="0.55" /></text>
<text string="SAVE: OFF" align="1" state="0"><color red="0.8" green="0.8" blue="0.8" /></text>
<text string="SAVE: ON" align="1" state="1"><color red="0.8" green="0.8" blue="0.8" /></text>
</element>
<element name="text_l0"><text string="MOVE"><color red="0.8" green="0.8" blue="0.8" /></text></element>
@ -156,7 +155,8 @@ license:CC0-1.0
<element ref="blackb"><bounds x="91" y="47" width="95" height="53" /></element>
<group ref="buttons"><bounds x="93" y="48.634" width="87.8" height="45.8" /></group>
<element ref="text_switch" inputtag="IN.3" inputmask="0x01"><bounds x="91" y="2" width="24" height="2.7" /></element>
<element ref="blackb"><bounds x="170" y="-1" width="20" height="4" /></element>
<element ref="text_switch" inputtag="IN.3" inputmask="0x01"><bounds x="171" y="0" width="13" height="2.7" /></element>
</view>
<view name="Internal Layout (Screen)">

View File

@ -5,6 +5,16 @@
Mattel Computer Chess
The chess engine is by Julio Kaplan, before he was working for SciSys/Saitek.
The power switch has a SAVE setting, this keeps the LCD chips powered on, and
the program reads the chessboard position from LCD RAM on the next boot. To save
a game in progress, make sure to press CLEAR before powering off. It does not
save the level setting.
There is no button to start a new game. The user is meant to switch power off/on.
In MAME, reset (or exit/restart) while the save switch is off.
Hardware notes:
- INS8050 CPU @ 6MHz (4KB internal ROM, 256 bytes internal RAM)
- 2*HLCD0569(also seen with 2*HLCD0601, functionally same?)
@ -16,8 +26,10 @@ assumed to be an unlicensed clone.
*******************************************************************************/
#include "emu.h"
#include "cpu/mcs48/mcs48.h"
#include "video/hlcd0515.h"
#include "screen.h"
// internal artwork
@ -39,8 +51,6 @@ public:
void mchess(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(reset_switch) { update_reset(newval); }
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
@ -52,8 +62,6 @@ private:
required_ioport_array<4> m_inputs;
output_finder<2, 8, 22> m_out_x;
void update_reset(ioport_value state);
// I/O handlers
template<int Sel> void lcd_output_w(offs_t offset, u32 data);
void input_w(u8 data);
@ -77,14 +85,12 @@ void mchess_state::machine_start()
void mchess_state::machine_reset()
{
update_reset(m_inputs[3]->read());
}
void mchess_state::update_reset(ioport_value state)
{
// battery is disconnected from CPU VCC pin when power switch is in SAVE mode
// (at reboot, the game will read the chessboard positions from LCD RAM)
m_maincpu->set_input_line(INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
// clear nvram if SAVE is off
if (~m_inputs[3]->read() & 1)
{
m_lcd[0]->nvram_reset();
m_lcd[1]->nvram_reset();
}
}
@ -96,12 +102,10 @@ void mchess_state::update_reset(ioport_value state)
template<int Sel>
void mchess_state::lcd_output_w(offs_t offset, u32 data)
{
int enabled = ~m_inputs[3]->read() & m_lcd_control & 1;
// output to x.y.z where x = chip, y = row, z = col
// up to 22 columns used
for (int i = 0; i < 22; i++)
m_out_x[Sel][offset][i] = BIT(data, i) & enabled;
m_out_x[Sel][offset][i] = BIT(data, i) & m_lcd_control;
}
void mchess_state::input_w(u8 data)
@ -181,7 +185,7 @@ static INPUT_PORTS_START( mchess )
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME("Take Back")
PORT_START("IN.3")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, mchess_state, reset_switch, 0) PORT_NAME("Save Switch")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_TOGGLE PORT_NAME("Save Switch")
INPUT_PORTS_END
@ -202,8 +206,11 @@ void mchess_state::mchess(machine_config &config)
// video hardware
HLCD0569(config, m_lcd[0], 500); // C=0.01uF
m_lcd[0]->write_cols().set(FUNC(mchess_state::lcd_output_w<0>));
m_lcd[0]->nvram_enable_backup(true);
HLCD0569(config, m_lcd[1], 500); // C=0.01uF
m_lcd[1]->write_cols().set(FUNC(mchess_state::lcd_output_w<1>));
m_lcd[1]->nvram_enable_backup(true);
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
screen.set_refresh_hz(60);

View File

@ -104,9 +104,8 @@ private:
void led_w(u8 data);
void set_cpu_freq();
TIMER_CALLBACK_MEMBER(set_pin);
TIMER_CALLBACK_MEMBER(delayed_nmi);
emu_timer *m_standbytimer;
emu_timer *m_nmitimer;
bool m_power = false;
u8 m_inp_mux = 0;
@ -114,8 +113,7 @@ private:
void ccompan2_state::machine_start()
{
m_nmitimer = timer_alloc(FUNC(ccompan2_state::set_pin), this);
m_standbytimer = timer_alloc(FUNC(ccompan2_state::set_pin), this);
m_nmitimer = timer_alloc(FUNC(ccompan2_state::delayed_nmi), this);
// register for savestates
save_item(NAME(m_power));
@ -137,12 +135,11 @@ void ccompan2_state::set_cpu_freq()
void ccompan2_state::machine_reset()
{
m_power = true;
m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
TIMER_CALLBACK_MEMBER(ccompan2_state::set_pin)
TIMER_CALLBACK_MEMBER(ccompan2_state::delayed_nmi)
{
m_maincpu->set_input_line(param, ASSERT_LINE);
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
}
INPUT_CHANGED_MEMBER(ccompan2_state::power_off)
@ -152,12 +149,8 @@ INPUT_CHANGED_MEMBER(ccompan2_state::power_off)
m_power = false;
// when power switch is set to MEMORY, it triggers an NMI after a short delay
attotime delay = attotime::from_msec(100);
m_nmitimer->adjust(delay, INPUT_LINE_NMI);
// afterwards, MCU STBY pin is asserted after a short delay
delay += attotime::from_msec(10);
m_standbytimer->adjust(delay, INPUT_LINE_RESET);
// (and shortly after that, MCU STBY is asserted)
m_nmitimer->adjust(attotime::from_msec(100));
}
}