SM511: added instruction clock divider (nw)

This commit is contained in:
hap 2017-05-06 22:01:08 +02:00
parent 710072f572
commit 201d49ba76
8 changed files with 52 additions and 16 deletions

View File

@ -23,15 +23,17 @@
- KB1013VK1-2/KB1013VK4-2 manual
TODO:
- finish SM500 emulation
- proper support for LFSR program counter in debugger
- callback for lcd screen as MAME bitmap (when needed)
- LCD bs pin blink mode via Y register (0.5s off, 0.5s on)
- wake up after CEND doesn't work right
- SM510 buzzer control divider bit is mask-programmable?
- SM511 undocumented/guessed opcodes:
* $01 is guessed as DIV to ACC transfer, unknown which bits
* $5d is certainly CEND
* $65 is certainly divider reset, but not sure if it behaves same as on SM510
* $6036 may be instruction timing? (16KHz vs 8KHz)
* $6036 and $6037 may be instruction timing? (16kHz and 8kHz), mnemonics unknown
*/
@ -69,7 +71,7 @@ void sm510_base_device::device_start()
m_write_segbs.resolve_safe();
m_write_segc.resolve_safe();
// zerofill
// init/zerofill
memset(m_stack, 0, sizeof(m_stack));
m_pc = 0;
m_prev_pc = 0;
@ -99,6 +101,7 @@ void sm510_base_device::device_start()
m_melody_duty_count = 0;
m_melody_duty_index = 0;
m_melody_address = 0;
m_clk_div = 2; // 16kHz
// register for savestates
save_item(NAME(m_stack));
@ -130,6 +133,7 @@ void sm510_base_device::device_start()
save_item(NAME(m_melody_duty_count));
save_item(NAME(m_melody_duty_index));
save_item(NAME(m_melody_address));
save_item(NAME(m_clk_div));
// register state for debugger
state_add(SM510_PC, "PC", m_pc).formatstr("%04X");
@ -174,7 +178,6 @@ void sm510_base_device::device_reset()
m_r = m_r_out = 0;
m_write_r(0, 0, 0xff);
m_melody_rd &= ~1;
}

View File

@ -134,8 +134,8 @@ protected:
virtual void device_reset() override;
// device_execute_interface overrides
virtual u64 execute_clocks_to_cycles(u64 clocks) const override { return (clocks + 2 - 1) / 2; } // default 2 cycles per machine cycle
virtual u64 execute_cycles_to_clocks(u64 cycles) const override { return (cycles * 2); } // "
virtual u64 execute_clocks_to_cycles(u64 clocks) const override { return (clocks + m_clk_div - 1) / m_clk_div; } // default 2 cycles per machine cycle
virtual u64 execute_cycles_to_clocks(u64 cycles) const override { return (cycles * m_clk_div); } // "
virtual u32 execute_min_cycles() const override { return 1; }
virtual u32 execute_max_cycles() const override { return 2; }
virtual u32 execute_input_lines() const override { return 1; }
@ -177,6 +177,7 @@ protected:
u8 m_r, m_r_out;
bool m_k_active;
bool m_halt;
int m_clk_div;
// lcd driver
optional_shared_ptr<u8> m_lcd_ram_a, m_lcd_ram_b, m_lcd_ram_c;
@ -295,6 +296,8 @@ protected:
virtual void op_idiv();
virtual void op_dr();
virtual void op_dta();
virtual void op_clklo();
virtual void op_clkhi();
void op_illegal();
};
@ -323,6 +326,9 @@ public:
sm511_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source);
protected:
virtual void device_post_load() override { notify_clock_changed(); }
virtual void device_reset() override;
virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override;
virtual void execute_one() override;
virtual void get_opcode_param() override;

View File

@ -25,7 +25,7 @@ enum e_mnemonics
mTB, mTC, mTAM, mTMI, mTA0, mTABL, mTIS, mTAL, mTF1, mTF4,
mRM, mSM,
mPRE, mSME, mRME, mTMEL,
mSKIP, mCEND, mIDIV, mDR, mDTA,
mSKIP, mCEND, mIDIV, mDR, mDTA, mCLKLO, mCLKHI,
// SM500-specific
mCOMCB, mRTN, mRTNS, mSSR, mTR, mTRS,
@ -52,7 +52,7 @@ static const char *const s_mnemonics[] =
"TB", "TC", "TAM", "TMI", "TA0", "TABL", "TIS", "TAL", "TF1", "TF4",
"RM", "SM",
"PRE", "SME", "RME", "TMEL",
"SKIP", "CEND", "IDIV", "DR", "DTA",
"SKIP", "CEND", "IDIV", "DR", "DTA", "CLKLO", "CLKHI",
//
"COMCB", "RTN", "RTNS", "SSR", "TR", "TRS",
@ -80,7 +80,7 @@ static const u8 s_bits[] =
0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
2, 2,
8, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
//
0, 0, 0, 4, 6, 6,
@ -110,7 +110,7 @@ static const u32 s_flags[] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
0, 0, 0, 0,
0, _OVER, 0, 0, 0,
0, _OVER, 0, 0, 0, 0, 0,
//
0, _OUT, _OUT, 0, 0, _OVER,
@ -253,7 +253,7 @@ static const u8 sm511_mnemonic[0x100] =
static const u8 sm511_extended[0x10] =
{
mRME, mSME, mTMEL, mATFC, mBDC, mATBP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 60 3
mRME, mSME, mTMEL, mATFC, mBDC, mATBP, mCLKHI,mCLKLO,0, 0, 0, 0, 0, 0, 0, 0 // 60 3
};
CPU_DISASSEMBLE(sm511)

View File

@ -444,6 +444,20 @@ void sm510_base_device::op_dta()
m_acc = m_div >> 11 & 0xf;
}
void sm510_base_device::op_clklo()
{
// CLKLO*: select 8kHz instruction clock (*unknown mnemonic)
m_clk_div = 4;
notify_clock_changed();
}
void sm510_base_device::op_clkhi()
{
// CLKHI*: select 16kHz instruction clock (*unknown mnemonic)
m_clk_div = 2;
notify_clock_changed();
}
void sm510_base_device::op_illegal()
{
logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_prev_pc);

View File

@ -58,6 +58,21 @@ sm512_device::sm512_device(const machine_config &mconfig, const char *tag, devic
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void sm511_device::device_reset()
{
sm510_base_device::device_reset();
m_melody_rd &= ~1;
m_clk_div = 4; // 8kHz
notify_clock_changed();
}
//-------------------------------------------------
// melody controller
//-------------------------------------------------
@ -179,7 +194,7 @@ void sm511_device::execute_one()
switch (m_op)
{
case 0x00: op_rot(); break;
case 0x01: op_dta(); break; // guessed
case 0x01: op_dta(); break;
case 0x02: op_sbm(); break;
case 0x03: op_atpl(); break;
case 0x08: op_add(); break;
@ -204,7 +219,7 @@ void sm511_device::execute_one()
case 0x62: op_wr(); break;
case 0x63: op_ws(); break;
case 0x64: op_incb(); break;
case 0x65: op_dr(); break; // guessed
case 0x65: op_dr(); break;
case 0x66: op_rc(); break;
case 0x67: op_sc(); break;
case 0x6c: op_decb(); break;
@ -223,6 +238,8 @@ void sm511_device::execute_one()
case 0x33: op_atfc(); break;
case 0x34: op_bdc(); break;
case 0x35: op_atbp(); break;
case 0x36: op_clkhi(); break;
case 0x37: op_clklo(); break;
default: op_illegal(); break;
}

View File

@ -150,7 +150,6 @@ static MACHINE_CONFIG_START( sc6, fidelmcs48_state )
MCFG_CPU_ADD("maincpu", I8040, XTAL_11MHz)
MCFG_CPU_PROGRAM_MAP(sc6_map)
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(fidelmcs48_state, sc6_mux_w))
MCFG_MCS48_PORT_P2_IN_CB(CONSTANT(0xff))
MCFG_MCS48_PORT_P1_IN_CB(READ8(fidelmcs48_state, sc6_input_r))
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(fidelmcs48_state, sc6_select_w))
MCFG_MCS48_PORT_T0_IN_CB(READLINE(fidelmcs48_state, sc6_input6_r))

View File

@ -1775,7 +1775,6 @@ static MACHINE_CONFIG_START( vbrc, fidelz80_state )
MCFG_QUANTUM_PERFECT_CPU("maincpu")
MCFG_CPU_ADD("mcu", I8041, XTAL_5MHz)
MCFG_MCS48_PORT_P1_IN_CB(CONSTANT(0)) // ???
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(fidelz80_state, vbrc_mcu_p1_w))
MCFG_MCS48_PORT_P2_IN_CB(READ8(fidelz80_state, vbrc_mcu_p2_r))
MCFG_MCS48_PORT_P2_OUT_CB(DEVWRITE8("i8243", i8243_device, p2_w))

View File

@ -142,8 +142,6 @@ INPUT_CHANGED_MEMBER(novagmcs48_state::octo_cpu_freq)
Machine Drivers
******************************************************************************/
// Presto/Octo
static MACHINE_CONFIG_START( presto, novagmcs48_state )
/* basic machine hardware */