This commit is contained in:
angelosa 2015-07-07 22:50:54 +02:00
commit c43cc5d258
3 changed files with 121 additions and 29 deletions

View file

@ -36,8 +36,13 @@ void sm510_base_device::device_start()
m_prgmask = (1 << m_prgwidth) - 1;
m_datamask = (1 << m_datawidth) - 1;
m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this));
reset_divider();
// resolve callbacks
m_read_k.resolve_safe(0);
m_read_ba.resolve_safe(1);
m_read_b.resolve_safe(1);
m_write_s.resolve_safe();
// zerofill
@ -53,9 +58,11 @@ void sm510_base_device::device_start()
m_c = 0;
m_skip = false;
m_w = 0;
m_div = 0;
m_bdc = false;
m_cend = false;
// m_div = 0;
m_1s = false;
m_bp = false;
m_bc = false;
m_halt = false;
// register for savestates
save_item(NAME(m_stack));
@ -71,8 +78,10 @@ void sm510_base_device::device_start()
save_item(NAME(m_skip));
save_item(NAME(m_w));
save_item(NAME(m_div));
save_item(NAME(m_bdc));
save_item(NAME(m_cend));
save_item(NAME(m_1s));
save_item(NAME(m_bp));
save_item(NAME(m_bc));
save_item(NAME(m_halt));
// register state for debugger
state_add(SM510_PC, "PC", m_pc).formatstr("%04X");
@ -97,11 +106,66 @@ void sm510_base_device::device_start()
void sm510_base_device::device_reset()
{
m_skip = false;
m_bdc = false;
m_cend = false;
m_halt = false;
m_op = m_prev_op = 0;
do_branch(3, 7, 0);
m_prev_pc = m_pc;
// lcd is on (Bp on, BC off)
m_bp = true;
m_bc = false;
// y=0(bs), r=0
}
//-------------------------------------------------
// interrupt/timer
//-------------------------------------------------
void sm510_base_device::wake_me_up()
{
// in halt mode, wake up after 1S signal or K input
if (m_halt)
{
m_halt = false;
do_branch(1, 0, 0);
standard_irq_callback(0);
// note: official doc warns that Bl/Bm and the stack are undefined
// after waking up, but we leave it unchanged
}
}
void sm510_base_device::execute_set_input(int line, int state)
{
if (line != 0)
return;
}
TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb)
{
// no need to increment it by 1 everytime, since only the
// highest bits are accessible
m_div = (m_div + 0x800) & 0x7fff;
// 1S signal on overflow(falling edge of f1)
if (m_div == 0)
{
m_1s = true;
wake_me_up();
}
// schedule next timeout
m_div_timer->adjust(attotime::from_ticks(0x800, unscaled_clock()));
}
void sm510_base_device::reset_divider()
{
m_div = 0;
m_div_timer->adjust(attotime::from_ticks(0x800, unscaled_clock()));
}
@ -120,6 +184,13 @@ void sm510_base_device::increment_pc()
void sm510_base_device::execute_run()
{
// nothing to do if in halt mode
if (m_halt)
{
m_icount = 0;
return;
}
while (m_icount > 0)
{
// remember previous state

View file

@ -14,10 +14,18 @@
// I/O ports setup
// 4-bit K input port
// 4-bit K input port (pull-down)
#define MCFG_SM510_READ_K_CB(_devcb) \
sm510_base_device::set_read_k_callback(*device, DEVCB_##_devcb);
// 1-bit BA input pin (pull-up)
#define MCFG_SM510_READ_BA_CB(_devcb) \
sm510_base_device::set_read_ba_callback(*device, DEVCB_##_devcb);
// 1-bit B(beta) input pin (pull-up)
#define MCFG_SM510_READ_B_CB(_devcb) \
sm510_base_device::set_read_b_callback(*device, DEVCB_##_devcb);
// 8-bit S strobe output port
#define MCFG_SM510_WRITE_S_CB(_devcb) \
sm510_base_device::set_write_s_callback(*device, DEVCB_##_devcb);
@ -43,11 +51,15 @@ public:
, m_datawidth(datawidth)
, m_stack_levels(stack_levels)
, m_read_k(*this)
, m_read_ba(*this)
, m_read_b(*this)
, m_write_s(*this)
{ }
// static configuration helpers
template<class _Object> static devcb_base &set_read_k_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_read_k.set_callback(object); }
template<class _Object> static devcb_base &set_read_ba_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_read_ba.set_callback(object); }
template<class _Object> static devcb_base &set_read_b_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_read_b.set_callback(object); }
template<class _Object> static devcb_base &set_write_s_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_write_s.set_callback(object); }
protected:
@ -61,7 +73,7 @@ protected:
virtual UINT32 execute_min_cycles() const { return 1; }
virtual UINT32 execute_max_cycles() const { return 2; }
virtual UINT32 execute_input_lines() const { return 1; }
//virtual void execute_set_input(int line, int state);
virtual void execute_set_input(int line, int state);
virtual void execute_run();
virtual void execute_one() { } // -> child class
@ -89,6 +101,7 @@ protected:
int m_stack_levels;
UINT16 m_stack[2];
int m_icount;
emu_timer *m_div_timer;
UINT8 m_acc;
UINT8 m_bl;
@ -97,15 +110,22 @@ protected:
bool m_skip;
UINT8 m_w;
UINT16 m_div;
bool m_bdc;
bool m_cend;
bool m_1s;
bool m_bp;
bool m_bc;
bool m_halt;
// i/o handlers
devcb_read16 m_read_k;
devcb_read8 m_read_k;
devcb_read_line m_read_ba;
devcb_read_line m_read_b;
devcb_write8 m_write_s;
// misc internal helpers
void increment_pc();
TIMER_CALLBACK_MEMBER(div_timer_cb);
void wake_me_up();
virtual void reset_divider();
virtual void get_opcode_param() { } // -> child class
UINT8 ram_r();

View file

@ -161,7 +161,7 @@ void sm510_base_device::op_exc()
void sm510_base_device::op_bdc()
{
// BDC: enable LCD bleeder current with C
m_bdc = (m_c != 0);
m_bc = (m_c != 0);
}
void sm510_base_device::op_exci()
@ -217,8 +217,8 @@ void sm510_base_device::op_kta()
void sm510_base_device::op_atbp()
{
// ATBP: output ACC to BP
op_illegal();
// ATBP: output ACC to BP(internal LCD backplate signal)
m_bp = ((m_acc & 1) != 0);
}
void sm510_base_device::op_atl()
@ -296,8 +296,8 @@ void sm510_base_device::op_sc()
void sm510_base_device::op_tb()
{
// TB: x
op_illegal();
// TB: skip next if B(beta) pin is set
m_skip = (m_read_b() != 0);
}
void sm510_base_device::op_tc()
@ -326,32 +326,33 @@ void sm510_base_device::op_ta0()
void sm510_base_device::op_tabl()
{
// TABL: skip next of ACC equals BL
// TABL: skip next if ACC equals BL
m_skip = (m_acc == m_bl);
}
void sm510_base_device::op_tis()
{
// TIS: x
op_illegal();
// TIS: skip next if 1S(gamma flag) is clear, reset it after
m_skip = !m_1s;
m_1s = false;
}
void sm510_base_device::op_tal()
{
// TAL: x
op_illegal();
// TAL: skip next if BA pin is set
m_skip = (m_read_ba() != 0);
}
void sm510_base_device::op_tf1()
{
// TF1: x
op_illegal();
// TF1: skip next if divider F1(d14) is set
m_skip = ((m_div & 0x4000) != 0);
}
void sm510_base_device::op_tf4()
{
// TF4: x
op_illegal();
// TF4: skip next if divider F4(d11) is set
m_skip = ((m_div & 0x0800) != 0);
}
@ -379,14 +380,14 @@ void sm510_base_device::op_skip()
void sm510_base_device::op_cend()
{
// CEND: stop clock
m_cend = true;
// CEND: stop clock (halt the cpu and go into low-power mode)
m_halt = true;
}
void sm510_base_device::op_idiv()
{
// IDIV: reset divider
m_div = 0;
reset_divider();
}
void sm510_base_device::op_illegal()