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 - KB1013VK1-2/KB1013VK4-2 manual
TODO: TODO:
- finish SM500 emulation
- proper support for LFSR program counter in debugger - proper support for LFSR program counter in debugger
- callback for lcd screen as MAME bitmap (when needed) - callback for lcd screen as MAME bitmap (when needed)
- LCD bs pin blink mode via Y register (0.5s off, 0.5s on) - 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? - SM510 buzzer control divider bit is mask-programmable?
- SM511 undocumented/guessed opcodes: - SM511 undocumented/guessed opcodes:
* $01 is guessed as DIV to ACC transfer, unknown which bits * $01 is guessed as DIV to ACC transfer, unknown which bits
* $5d is certainly CEND * $5d is certainly CEND
* $65 is certainly divider reset, but not sure if it behaves same as on SM510 * $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_segbs.resolve_safe();
m_write_segc.resolve_safe(); m_write_segc.resolve_safe();
// zerofill // init/zerofill
memset(m_stack, 0, sizeof(m_stack)); memset(m_stack, 0, sizeof(m_stack));
m_pc = 0; m_pc = 0;
m_prev_pc = 0; m_prev_pc = 0;
@ -99,6 +101,7 @@ void sm510_base_device::device_start()
m_melody_duty_count = 0; m_melody_duty_count = 0;
m_melody_duty_index = 0; m_melody_duty_index = 0;
m_melody_address = 0; m_melody_address = 0;
m_clk_div = 2; // 16kHz
// register for savestates // register for savestates
save_item(NAME(m_stack)); 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_count));
save_item(NAME(m_melody_duty_index)); save_item(NAME(m_melody_duty_index));
save_item(NAME(m_melody_address)); save_item(NAME(m_melody_address));
save_item(NAME(m_clk_div));
// register state for debugger // register state for debugger
state_add(SM510_PC, "PC", m_pc).formatstr("%04X"); 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_r = m_r_out = 0;
m_write_r(0, 0, 0xff); m_write_r(0, 0, 0xff);
m_melody_rd &= ~1;
} }

View File

@ -134,8 +134,8 @@ protected:
virtual void device_reset() override; virtual void device_reset() override;
// device_execute_interface overrides // 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_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 * 2); } // " 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_min_cycles() const override { return 1; }
virtual u32 execute_max_cycles() const override { return 2; } virtual u32 execute_max_cycles() const override { return 2; }
virtual u32 execute_input_lines() const override { return 1; } virtual u32 execute_input_lines() const override { return 1; }
@ -177,6 +177,7 @@ protected:
u8 m_r, m_r_out; u8 m_r, m_r_out;
bool m_k_active; bool m_k_active;
bool m_halt; bool m_halt;
int m_clk_div;
// lcd driver // lcd driver
optional_shared_ptr<u8> m_lcd_ram_a, m_lcd_ram_b, m_lcd_ram_c; 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_idiv();
virtual void op_dr(); virtual void op_dr();
virtual void op_dta(); virtual void op_dta();
virtual void op_clklo();
virtual void op_clkhi();
void op_illegal(); 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); 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: 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 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 execute_one() override;
virtual void get_opcode_param() 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, mTB, mTC, mTAM, mTMI, mTA0, mTABL, mTIS, mTAL, mTF1, mTF4,
mRM, mSM, mRM, mSM,
mPRE, mSME, mRME, mTMEL, mPRE, mSME, mRME, mTMEL,
mSKIP, mCEND, mIDIV, mDR, mDTA, mSKIP, mCEND, mIDIV, mDR, mDTA, mCLKLO, mCLKHI,
// SM500-specific // SM500-specific
mCOMCB, mRTN, mRTNS, mSSR, mTR, mTRS, 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", "TB", "TC", "TAM", "TMI", "TA0", "TABL", "TIS", "TAL", "TF1", "TF4",
"RM", "SM", "RM", "SM",
"PRE", "SME", "RME", "TMEL", "PRE", "SME", "RME", "TMEL",
"SKIP", "CEND", "IDIV", "DR", "DTA", "SKIP", "CEND", "IDIV", "DR", "DTA", "CLKLO", "CLKHI",
// //
"COMCB", "RTN", "RTNS", "SSR", "TR", "TRS", "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, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2,
8, 0, 0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// //
0, 0, 0, 4, 6, 6, 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, 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, 0, _OUT, _OUT, 0, 0, _OVER,
@ -253,7 +253,7 @@ static const u8 sm511_mnemonic[0x100] =
static const u8 sm511_extended[0x10] = 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) CPU_DISASSEMBLE(sm511)

View File

@ -444,6 +444,20 @@ void sm510_base_device::op_dta()
m_acc = m_div >> 11 & 0xf; 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() void sm510_base_device::op_illegal()
{ {
logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_prev_pc); 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 // melody controller
//------------------------------------------------- //-------------------------------------------------
@ -179,7 +194,7 @@ void sm511_device::execute_one()
switch (m_op) switch (m_op)
{ {
case 0x00: op_rot(); break; case 0x00: op_rot(); break;
case 0x01: op_dta(); break; // guessed case 0x01: op_dta(); break;
case 0x02: op_sbm(); break; case 0x02: op_sbm(); break;
case 0x03: op_atpl(); break; case 0x03: op_atpl(); break;
case 0x08: op_add(); break; case 0x08: op_add(); break;
@ -204,7 +219,7 @@ void sm511_device::execute_one()
case 0x62: op_wr(); break; case 0x62: op_wr(); break;
case 0x63: op_ws(); break; case 0x63: op_ws(); break;
case 0x64: op_incb(); break; case 0x64: op_incb(); break;
case 0x65: op_dr(); break; // guessed case 0x65: op_dr(); break;
case 0x66: op_rc(); break; case 0x66: op_rc(); break;
case 0x67: op_sc(); break; case 0x67: op_sc(); break;
case 0x6c: op_decb(); break; case 0x6c: op_decb(); break;
@ -223,6 +238,8 @@ void sm511_device::execute_one()
case 0x33: op_atfc(); break; case 0x33: op_atfc(); break;
case 0x34: op_bdc(); break; case 0x34: op_bdc(); break;
case 0x35: op_atbp(); break; case 0x35: op_atbp(); break;
case 0x36: op_clkhi(); break;
case 0x37: op_clklo(); break;
default: op_illegal(); 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_ADD("maincpu", I8040, XTAL_11MHz)
MCFG_CPU_PROGRAM_MAP(sc6_map) MCFG_CPU_PROGRAM_MAP(sc6_map)
MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(fidelmcs48_state, sc6_mux_w)) 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_IN_CB(READ8(fidelmcs48_state, sc6_input_r))
MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(fidelmcs48_state, sc6_select_w)) MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(fidelmcs48_state, sc6_select_w))
MCFG_MCS48_PORT_T0_IN_CB(READLINE(fidelmcs48_state, sc6_input6_r)) 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_QUANTUM_PERFECT_CPU("maincpu")
MCFG_CPU_ADD("mcu", I8041, XTAL_5MHz) 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_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_IN_CB(READ8(fidelz80_state, vbrc_mcu_p2_r))
MCFG_MCS48_PORT_P2_OUT_CB(DEVWRITE8("i8243", i8243_device, p2_w)) 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 Machine Drivers
******************************************************************************/ ******************************************************************************/
// Presto/Octo
static MACHINE_CONFIG_START( presto, novagmcs48_state ) static MACHINE_CONFIG_START( presto, novagmcs48_state )
/* basic machine hardware */ /* basic machine hardware */