mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
sm510: fix wakeup after CEND, reorganize files a bit
This commit is contained in:
parent
9a72f4594d
commit
a44de917e1
@ -2223,20 +2223,23 @@ end
|
||||
if CPUS["SM510"] then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm510base.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm510base.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm510.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm510.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm510op.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm510core.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm511core.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm530.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm530op.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm530core.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm511.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm511.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm500.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm500.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm500op.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm500core.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm5acore.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm5a.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm5a.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm530.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm530.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm530op.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm590.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm590.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm590op.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm590core.cpp",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
Rockwell PPS-4/1 MCU cores
|
||||
|
||||
Don't include this file, include the specific device header instead,
|
||||
for example mm76.h
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAME_CPU_PPS41_PPS41BASE_H
|
||||
|
@ -147,17 +147,6 @@ void sm500_device::clock_melody()
|
||||
// execute
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm500_device::get_opcode_param()
|
||||
{
|
||||
// LBL and prefix opcodes are 2 bytes
|
||||
if (m_op == 0x5e || m_op == 0x5f)
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void sm500_device::execute_one()
|
||||
{
|
||||
switch (m_op & 0xf0)
|
||||
@ -248,3 +237,9 @@ void sm500_device::execute_one()
|
||||
|
||||
} // big switch
|
||||
}
|
||||
|
||||
bool sm500_device::op_argument()
|
||||
{
|
||||
// LBL and prefix opcodes are 2 bytes
|
||||
return m_op == 0x5e || m_op == 0x5f;
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sm510.h"
|
||||
#include "sm510base.h"
|
||||
|
||||
|
||||
// pinout reference
|
||||
@ -38,31 +38,6 @@ O36 48 | * | 13 K2
|
||||
|
||||
1 2 3 4 5 6 7 8 9 10 11 12
|
||||
O26 O16 R4 R3 R2 R1 GND _T bt al ACL K1 note: bt = beta symbol, al = alpha symbol
|
||||
|
||||
|
||||
OS2 OS3 OS4 K4 K3 K2 K1 GND al bt ACL _R1 _Tp NC NC note: on SM5L, pin 31=V1, 32=V2, 33=NC
|
||||
45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
|
||||
____________________________________________________________
|
||||
| |
|
||||
OS1 46 | | 30 H1
|
||||
O41 47 | | 29 H2
|
||||
O31 48 | | 28 Vm
|
||||
O21 49 | | 27 Vdd
|
||||
O11 50 | | 26 _R2
|
||||
O42 51 | | 25 _R3
|
||||
O32 52 | SM5A | 24 _R4
|
||||
O22 53 | SM5L | 23 OSCin
|
||||
O12 54 | | 22 OSCout
|
||||
O43 55 | | 21 _T2
|
||||
O33 56 | | 20 _T1
|
||||
O23 57 | | 19 O18
|
||||
O13 58 | | 18 O28
|
||||
O44 59 | | 17 O38
|
||||
O34 60 | * | 16 O48
|
||||
|____________________________________________________________/
|
||||
|
||||
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
O24 O14 O45 O35 O25 O15 O46 GND O36 O26 O16 O47 O37 O27 O17
|
||||
*/
|
||||
|
||||
class sm500_device : public sm510_base_device
|
||||
@ -80,7 +55,7 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void execute_one() override;
|
||||
virtual void get_opcode_param() override;
|
||||
virtual bool op_argument() override;
|
||||
virtual void clock_melody() override;
|
||||
|
||||
virtual void reset_vector() override { do_branch(0, 0xf, 0); }
|
||||
@ -137,38 +112,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class sm5a_device : public sm500_device
|
||||
{
|
||||
public:
|
||||
sm5a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
|
||||
protected:
|
||||
sm5a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int o_pins, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
|
||||
|
||||
void program_1_8k(address_map &map);
|
||||
void data_5x13x4(address_map &map);
|
||||
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void execute_one() override;
|
||||
virtual int get_trs_field() override { return 1; }
|
||||
};
|
||||
|
||||
class sm5l_device : public sm5a_device
|
||||
{
|
||||
public:
|
||||
sm5l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
};
|
||||
|
||||
class kb1013vk12_device : public sm5a_device
|
||||
{
|
||||
public:
|
||||
kb1013vk12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(SM500, sm500_device)
|
||||
DECLARE_DEVICE_TYPE(SM5A, sm5a_device)
|
||||
DECLARE_DEVICE_TYPE(SM5L, sm5l_device)
|
||||
DECLARE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device)
|
||||
|
||||
#endif // MAME_CPU_SM510_SM500_H
|
||||
|
@ -4,9 +4,6 @@
|
||||
|
||||
Sharp SM510 MCU core implementation
|
||||
|
||||
TODO:
|
||||
- X
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -49,7 +46,6 @@ std::unique_ptr<util::disasm_interface> sm510_device::create_disassembler()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// buzzer controller
|
||||
//-------------------------------------------------
|
||||
@ -80,22 +76,10 @@ void sm510_device::clock_melody()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm510_device::get_opcode_param()
|
||||
{
|
||||
// LBL, TL, TML opcodes are 2 bytes
|
||||
if (m_op == 0x5f || (m_op & 0xf0) == 0x70)
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void sm510_device::execute_one()
|
||||
{
|
||||
switch (m_op & 0xf0)
|
||||
@ -174,3 +158,9 @@ void sm510_device::execute_one()
|
||||
// BM high bit is only valid for 1 step
|
||||
m_sbm = (m_op == 0x02);
|
||||
}
|
||||
|
||||
bool sm510_device::op_argument()
|
||||
{
|
||||
// LBL, TL, TML opcodes are 2 bytes
|
||||
return m_op == 0x5f || (m_op & 0xf0) == 0x70;
|
||||
}
|
@ -11,22 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// I/O ports setup
|
||||
|
||||
// when in halt state, any K input going High can wake up the CPU,
|
||||
// driver is required to use set_input_line(SM510_INPUT_LINE_K, state)
|
||||
#define SM510_INPUT_LINE_K 0
|
||||
|
||||
// ACL input pin
|
||||
#define SM510_INPUT_LINE_ACL INPUT_LINE_RESET
|
||||
|
||||
enum
|
||||
{
|
||||
SM510_PORT_SEGA = 0x00,
|
||||
SM510_PORT_SEGB = 0x04,
|
||||
SM510_PORT_SEGBS = 0x08,
|
||||
SM510_PORT_SEGC = 0x0c
|
||||
};
|
||||
#include "sm510base.h"
|
||||
|
||||
|
||||
// pinout reference
|
||||
@ -59,232 +44,6 @@ S8 60 | * | 16 b16
|
||||
BA OSCout Vdd
|
||||
*/
|
||||
|
||||
class sm510_base_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sm510_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program)
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
|
||||
, m_prgwidth(prgwidth)
|
||||
, m_datawidth(datawidth)
|
||||
, m_stack_levels(stack_levels)
|
||||
, m_r_mask_option(RMASK_DIRECT)
|
||||
, m_lcd_ram_a(*this, "lcd_ram_a"), m_lcd_ram_b(*this, "lcd_ram_b"), m_lcd_ram_c(*this, "lcd_ram_c")
|
||||
, m_write_segs(*this)
|
||||
, m_melody_rom(*this, "melody")
|
||||
, m_read_k(*this)
|
||||
, m_read_ba(*this), m_read_b(*this)
|
||||
, m_write_s(*this)
|
||||
, m_write_r(*this)
|
||||
{ }
|
||||
|
||||
// For SM510, SM500, SM5A, R port output is selected with a mask option,
|
||||
// either from the divider or direct contol. Documented options are:
|
||||
// SM510/SM5A: direct control, 2(4096Hz meant for alarm sound)
|
||||
// SM500: 14, 11, 3 (divider f1, f4, f12)
|
||||
void set_r_mask_option(int bit) { m_r_mask_option = bit; }
|
||||
static constexpr int RMASK_DIRECT = -1;
|
||||
|
||||
// 4-bit K input port (pull-down)
|
||||
auto read_k() { return m_read_k.bind(); }
|
||||
|
||||
// 1-bit BA(aka alpha) input pin (pull-up)
|
||||
auto read_ba() { return m_read_ba.bind(); }
|
||||
|
||||
// 1-bit B(beta) input pin (pull-up)
|
||||
auto read_b() { return m_read_b.bind(); }
|
||||
|
||||
// 8-bit S strobe output port
|
||||
auto write_s() { return m_write_s.bind(); }
|
||||
|
||||
// 1/2/4-bit R (buzzer/melody) output port
|
||||
auto write_r() { return m_write_r.bind(); }
|
||||
|
||||
// LCD segment outputs, SM51X: H1-4 as offset(low), a/b/c 1-16 as data d0-d15,
|
||||
// bs output is same as above, but only up to 2 bits used.
|
||||
// SM500/SM5A: H1/2 as a0, O group as a1-a4, O data as d0-d3
|
||||
auto write_segs() { return m_write_segs.bind(); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept 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 noexcept override { return (cycles * m_clk_div); } // "
|
||||
virtual u32 execute_min_cycles() const noexcept override { return 1; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 2; }
|
||||
virtual u32 execute_input_lines() const noexcept override { return 1; }
|
||||
virtual void execute_set_input(int line, int state) override;
|
||||
virtual void execute_run() override;
|
||||
virtual void execute_one() { } // -> child class
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_data_config;
|
||||
address_space *m_program;
|
||||
address_space *m_data;
|
||||
|
||||
virtual void reset_vector() { do_branch(3, 7, 0); }
|
||||
virtual void wakeup_vector() { do_branch(1, 0, 0); } // after halt
|
||||
|
||||
int m_prgwidth;
|
||||
int m_datawidth;
|
||||
int m_prgmask;
|
||||
int m_datamask;
|
||||
|
||||
u16 m_pc, m_prev_pc;
|
||||
u16 m_op, m_prev_op;
|
||||
u8 m_param;
|
||||
int m_stack_levels;
|
||||
u16 m_stack[4]; // max 4
|
||||
int m_icount;
|
||||
|
||||
u8 m_acc;
|
||||
u8 m_bl;
|
||||
u8 m_bm;
|
||||
bool m_sbm;
|
||||
bool m_sbl;
|
||||
u8 m_c;
|
||||
bool m_skip;
|
||||
u8 m_w;
|
||||
u8 m_r, m_r_out;
|
||||
int m_r_mask_option;
|
||||
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;
|
||||
devcb_write16 m_write_segs;
|
||||
emu_timer *m_lcd_timer;
|
||||
u8 m_l, m_x;
|
||||
u8 m_y;
|
||||
u8 m_bp;
|
||||
bool m_bc;
|
||||
|
||||
u16 get_lcd_row(int column, u8* ram);
|
||||
virtual void lcd_update();
|
||||
TIMER_CALLBACK_MEMBER(lcd_timer_cb);
|
||||
virtual void init_lcd_driver();
|
||||
|
||||
// melody controller
|
||||
optional_region_ptr<u8> m_melody_rom;
|
||||
u8 m_melody_rd;
|
||||
u8 m_melody_step_count;
|
||||
u8 m_melody_duty_count;
|
||||
u8 m_melody_duty_index;
|
||||
u8 m_melody_address;
|
||||
|
||||
virtual void clock_melody() { }
|
||||
virtual void init_melody() { }
|
||||
|
||||
// interrupt/divider
|
||||
emu_timer *m_div_timer;
|
||||
u16 m_div;
|
||||
bool m_1s;
|
||||
|
||||
virtual bool wake_me_up();
|
||||
virtual void init_divider();
|
||||
TIMER_CALLBACK_MEMBER(div_timer_cb);
|
||||
|
||||
// other i/o handlers
|
||||
devcb_read8 m_read_k;
|
||||
devcb_read_line m_read_ba;
|
||||
devcb_read_line m_read_b;
|
||||
devcb_write8 m_write_s;
|
||||
devcb_write8 m_write_r;
|
||||
|
||||
// misc internal helpers
|
||||
virtual void increment_pc();
|
||||
virtual void get_opcode_param() { }
|
||||
virtual void update_w_latch() { }
|
||||
|
||||
virtual u8 ram_r();
|
||||
virtual void ram_w(u8 data);
|
||||
void pop_stack();
|
||||
void push_stack();
|
||||
virtual void do_branch(u8 pu, u8 pm, u8 pl);
|
||||
u8 bitmask(u16 param);
|
||||
|
||||
// opcode handlers
|
||||
virtual void op_lb();
|
||||
virtual void op_lbl();
|
||||
virtual void op_sbl();
|
||||
virtual void op_sbm();
|
||||
virtual void op_exbla();
|
||||
virtual void op_incb();
|
||||
virtual void op_decb();
|
||||
|
||||
virtual void op_atpl();
|
||||
virtual void op_rtn0();
|
||||
virtual void op_rtn1();
|
||||
virtual void op_tl();
|
||||
virtual void op_tml();
|
||||
virtual void op_tm();
|
||||
virtual void op_t();
|
||||
|
||||
virtual void op_exc();
|
||||
virtual void op_bdc();
|
||||
virtual void op_exci();
|
||||
virtual void op_excd();
|
||||
virtual void op_lda();
|
||||
virtual void op_lax();
|
||||
virtual void op_ptw();
|
||||
virtual void op_wr();
|
||||
virtual void op_ws();
|
||||
|
||||
virtual void op_kta();
|
||||
virtual void op_atbp();
|
||||
virtual void op_atx();
|
||||
virtual void op_atl();
|
||||
virtual void op_atfc();
|
||||
virtual void op_atr();
|
||||
|
||||
virtual void op_add();
|
||||
virtual void op_add11();
|
||||
virtual void op_adx();
|
||||
virtual void op_coma();
|
||||
virtual void op_rot();
|
||||
virtual void op_rc();
|
||||
virtual void op_sc();
|
||||
|
||||
virtual void op_tb();
|
||||
virtual void op_tc();
|
||||
virtual void op_tam();
|
||||
virtual void op_tmi();
|
||||
virtual void op_ta0();
|
||||
virtual void op_tabl();
|
||||
virtual void op_tis();
|
||||
virtual void op_tal();
|
||||
virtual void op_tf1();
|
||||
virtual void op_tf4();
|
||||
|
||||
virtual void op_rm();
|
||||
virtual void op_sm();
|
||||
|
||||
virtual void op_pre();
|
||||
virtual void op_sme();
|
||||
virtual void op_rme();
|
||||
virtual void op_tmel();
|
||||
|
||||
virtual void op_skip();
|
||||
virtual void op_cend();
|
||||
virtual void op_idiv();
|
||||
virtual void op_dr();
|
||||
virtual void op_dta();
|
||||
virtual void op_clklo();
|
||||
virtual void op_clkhi();
|
||||
|
||||
void op_illegal();
|
||||
};
|
||||
|
||||
|
||||
class sm510_device : public sm510_base_device
|
||||
{
|
||||
public:
|
||||
@ -296,7 +55,7 @@ protected:
|
||||
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void execute_one() override;
|
||||
virtual void get_opcode_param() override;
|
||||
virtual bool op_argument() override;
|
||||
|
||||
virtual void update_w_latch() override { m_write_s(m_w); } // W is connected directly to S
|
||||
|
||||
@ -304,41 +63,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class sm511_device : public sm510_base_device
|
||||
{
|
||||
public:
|
||||
sm511_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
|
||||
protected:
|
||||
sm511_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
|
||||
|
||||
void program_4k(address_map &map);
|
||||
void data_96_32x4(address_map &map);
|
||||
|
||||
virtual void device_post_load() override { notify_clock_changed(); }
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void execute_one() override;
|
||||
virtual void get_opcode_param() override;
|
||||
|
||||
virtual void clock_melody() override;
|
||||
virtual void init_melody() override;
|
||||
};
|
||||
|
||||
class sm512_device : public sm511_device
|
||||
{
|
||||
public:
|
||||
sm512_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
|
||||
protected:
|
||||
void data_80_48x4(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(SM510, sm510_device)
|
||||
DECLARE_DEVICE_TYPE(SM511, sm511_device)
|
||||
DECLARE_DEVICE_TYPE(SM512, sm512_device)
|
||||
|
||||
#endif // MAME_CPU_SM510_SM510_H
|
||||
|
@ -13,16 +13,10 @@
|
||||
Default external frequency of these is 32.768kHz, forwarding a clockrate in the
|
||||
MAME machine config is optional. Newer revisions can have an internal oscillator.
|
||||
|
||||
TODO:
|
||||
- source organiziation between files is a mess
|
||||
- wake up after CEND doesn't work right
|
||||
|
||||
for more, see the *core.cpp file notes
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sm510.h"
|
||||
#include "sm510base.h"
|
||||
#include "debugger.h"
|
||||
|
||||
|
||||
@ -38,6 +32,8 @@ enum
|
||||
|
||||
void sm510_base_device::device_start()
|
||||
{
|
||||
assert(SM510_INPUT_LINE_K1 == 0);
|
||||
|
||||
m_program = &space(AS_PROGRAM);
|
||||
m_data = &space(AS_DATA);
|
||||
m_prgmask = (1 << m_prgwidth) - 1;
|
||||
@ -52,7 +48,7 @@ void sm510_base_device::device_start()
|
||||
m_write_segs.resolve_safe();
|
||||
|
||||
// init/zerofill
|
||||
memset(m_stack, 0, sizeof(m_stack));
|
||||
std::fill_n(m_stack, std::size(m_stack), 0);
|
||||
m_pc = 0;
|
||||
m_prev_pc = 0;
|
||||
m_op = 0;
|
||||
@ -70,7 +66,9 @@ void sm510_base_device::device_start()
|
||||
m_r_out = 0;
|
||||
m_div = 0;
|
||||
m_1s = false;
|
||||
m_k_active = false;
|
||||
m_1s_rise = false;
|
||||
m_k_rise = false;
|
||||
std::fill_n(m_k_input, std::size(m_k_input), 0);
|
||||
m_l = 0;
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
@ -103,7 +101,9 @@ void sm510_base_device::device_start()
|
||||
save_item(NAME(m_r_out));
|
||||
save_item(NAME(m_div));
|
||||
save_item(NAME(m_1s));
|
||||
save_item(NAME(m_k_active));
|
||||
save_item(NAME(m_1s_rise));
|
||||
save_item(NAME(m_k_rise));
|
||||
save_item(NAME(m_k_input));
|
||||
save_item(NAME(m_l));
|
||||
save_item(NAME(m_x));
|
||||
save_item(NAME(m_y));
|
||||
@ -138,6 +138,13 @@ void sm510_base_device::device_start()
|
||||
init_melody();
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector sm510_base_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(AS_PROGRAM, &m_program_config),
|
||||
std::make_pair(AS_DATA, &m_data_config)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -165,7 +172,6 @@ void sm510_base_device::device_reset()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// lcd driver
|
||||
//-------------------------------------------------
|
||||
@ -183,14 +189,6 @@ inline u16 sm510_base_device::get_lcd_row(int column, u8* ram)
|
||||
return rowdata;
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector sm510_base_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(AS_PROGRAM, &m_program_config),
|
||||
std::make_pair(AS_DATA, &m_data_config)
|
||||
};
|
||||
}
|
||||
|
||||
void sm510_base_device::lcd_update()
|
||||
{
|
||||
// 4 columns
|
||||
@ -222,44 +220,20 @@ void sm510_base_device::init_lcd_driver()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// interrupt/divider
|
||||
// divider
|
||||
//-------------------------------------------------
|
||||
|
||||
bool sm510_base_device::wake_me_up()
|
||||
{
|
||||
// in halt mode, wake up after 1S signal or K input
|
||||
if (m_k_active || m_1s)
|
||||
{
|
||||
// note: official doc warns that Bl/Bm and the stack are undefined
|
||||
// after waking up, but we leave it unchanged
|
||||
m_halt = false;
|
||||
wakeup_vector();
|
||||
|
||||
standard_irq_callback(0);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void sm510_base_device::execute_set_input(int line, int state)
|
||||
{
|
||||
if (line != SM510_INPUT_LINE_K)
|
||||
return;
|
||||
|
||||
// set K input lines active state
|
||||
m_k_active = (state != 0);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb)
|
||||
{
|
||||
m_div = (m_div + 1) & 0x7fff;
|
||||
|
||||
// 1S signal on overflow(falling edge of F1)
|
||||
if (m_div == 0)
|
||||
{
|
||||
m_1s_rise = !m_1s;
|
||||
m_1s = true;
|
||||
}
|
||||
|
||||
clock_melody();
|
||||
}
|
||||
@ -271,6 +245,33 @@ void sm510_base_device::init_divider()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// interrupt
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm510_base_device::execute_set_input(int line, int state)
|
||||
{
|
||||
if (!valid_wakeup_line(line))
|
||||
return;
|
||||
|
||||
// rising edge of any K input
|
||||
if (state && !m_k_input[line])
|
||||
m_k_rise = true;
|
||||
|
||||
m_k_input[line] = state;
|
||||
}
|
||||
|
||||
void sm510_base_device::do_interrupt()
|
||||
{
|
||||
// note: official doc warns that Bl/Bm and the stack are undefined
|
||||
// after waking up, but we leave it unchanged
|
||||
m_icount--;
|
||||
m_halt = false;
|
||||
wakeup_vector();
|
||||
|
||||
standard_irq_callback(0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute
|
||||
@ -286,17 +287,29 @@ void sm510_base_device::increment_pc()
|
||||
|
||||
void sm510_base_device::execute_run()
|
||||
{
|
||||
bool _1s_prev = m_1s_rise;
|
||||
|
||||
while (m_icount > 0)
|
||||
{
|
||||
m_icount--;
|
||||
// in halt mode, wake up after 1S signal or K input
|
||||
bool wakeup = m_k_rise || m_1s_rise;
|
||||
m_k_rise = false;
|
||||
m_1s_rise = false;
|
||||
|
||||
if (m_halt && !wake_me_up())
|
||||
if (m_halt)
|
||||
{
|
||||
// got nothing to do
|
||||
m_icount = 0;
|
||||
return;
|
||||
if (!wakeup)
|
||||
{
|
||||
// got nothing to do
|
||||
m_icount = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
do_interrupt();
|
||||
}
|
||||
|
||||
m_icount--;
|
||||
|
||||
// remember previous state
|
||||
m_prev_op = m_op;
|
||||
m_prev_pc = m_pc;
|
||||
@ -306,7 +319,14 @@ void sm510_base_device::execute_run()
|
||||
debugger_instruction_hook(m_pc);
|
||||
m_op = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
get_opcode_param();
|
||||
|
||||
// 2-byte opcodes
|
||||
if (op_argument())
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
|
||||
// handle opcode if it's not skipped
|
||||
if (m_skip)
|
||||
@ -316,5 +336,10 @@ void sm510_base_device::execute_run()
|
||||
}
|
||||
else
|
||||
execute_one();
|
||||
|
||||
// if CEND triggered at the same time as 1S signal, make sure it still wakes up
|
||||
if (m_halt)
|
||||
m_1s_rise = _1s_prev;
|
||||
_1s_prev = false;
|
||||
}
|
||||
}
|
||||
|
274
src/devices/cpu/sm510/sm510base.h
Normal file
274
src/devices/cpu/sm510/sm510base.h
Normal file
@ -0,0 +1,274 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Sharp SM510 MCU family - base/shared
|
||||
|
||||
Don't include this file, include the specific device header instead,
|
||||
for example sm510.h
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAME_CPU_SM510_SM510BASE_H
|
||||
#define MAME_CPU_SM510_SM510BASE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
// I/O ports setup
|
||||
|
||||
// when in halt state, any K input going high can wake up the CPU,
|
||||
// driver is required to use set_input_line(SM510_INPUT_LINE_K1/K2/K3/K4, state)
|
||||
enum
|
||||
{
|
||||
SM510_INPUT_LINE_K1 = 0,
|
||||
SM510_INPUT_LINE_K2,
|
||||
SM510_INPUT_LINE_K3,
|
||||
SM510_INPUT_LINE_K4
|
||||
};
|
||||
|
||||
// ACL input pin
|
||||
#define SM510_INPUT_LINE_ACL INPUT_LINE_RESET
|
||||
|
||||
// LCD commons
|
||||
enum
|
||||
{
|
||||
SM510_PORT_SEGA = 0x00,
|
||||
SM510_PORT_SEGB = 0x04,
|
||||
SM510_PORT_SEGBS = 0x08,
|
||||
SM510_PORT_SEGC = 0x0c
|
||||
};
|
||||
|
||||
|
||||
class sm510_base_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sm510_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program)
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
|
||||
, m_prgwidth(prgwidth)
|
||||
, m_datawidth(datawidth)
|
||||
, m_stack_levels(stack_levels)
|
||||
, m_r_mask_option(RMASK_DIRECT)
|
||||
, m_lcd_ram_a(*this, "lcd_ram_a"), m_lcd_ram_b(*this, "lcd_ram_b"), m_lcd_ram_c(*this, "lcd_ram_c")
|
||||
, m_write_segs(*this)
|
||||
, m_melody_rom(*this, "melody")
|
||||
, m_read_k(*this)
|
||||
, m_read_ba(*this), m_read_b(*this)
|
||||
, m_write_s(*this)
|
||||
, m_write_r(*this)
|
||||
{ }
|
||||
|
||||
// For SM510, SM500, SM5A, R port output is selected with a mask option,
|
||||
// either from the divider or direct contol. Documented options are:
|
||||
// SM510/SM5A: direct control, 2(4096Hz meant for alarm sound)
|
||||
// SM500: 14, 11, 3 (divider f1, f4, f12)
|
||||
void set_r_mask_option(int bit) { m_r_mask_option = bit; }
|
||||
static constexpr int RMASK_DIRECT = -1;
|
||||
|
||||
// 4-bit K input port (pull-down)
|
||||
auto read_k() { return m_read_k.bind(); }
|
||||
|
||||
// 1-bit BA(aka alpha) input pin (pull-up)
|
||||
auto read_ba() { return m_read_ba.bind(); }
|
||||
|
||||
// 1-bit B(beta) input pin (pull-up)
|
||||
auto read_b() { return m_read_b.bind(); }
|
||||
|
||||
// 8-bit S strobe output port
|
||||
auto write_s() { return m_write_s.bind(); }
|
||||
|
||||
// 1/2/4-bit R (buzzer/melody) output port
|
||||
auto write_r() { return m_write_r.bind(); }
|
||||
|
||||
// LCD segment outputs, SM51X: H1-4 as offset(low), a/b/c 1-16 as data d0-d15,
|
||||
// bs output is same as above, but only up to 2 bits used.
|
||||
// SM500/SM5A: H1/2 as a0, O group as a1-a4, O data as d0-d3
|
||||
auto write_segs() { return m_write_segs.bind(); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept 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 noexcept override { return (cycles * m_clk_div); } // "
|
||||
virtual u32 execute_min_cycles() const noexcept override { return 1; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 3+1; }
|
||||
virtual u32 execute_input_lines() const noexcept override { return 4; }
|
||||
virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return valid_wakeup_line(inputnum); }
|
||||
virtual void execute_set_input(int line, int state) override;
|
||||
virtual void execute_run() override;
|
||||
|
||||
virtual void execute_one() { } // -> child class
|
||||
virtual bool op_argument() { return false; }
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_data_config;
|
||||
address_space *m_program;
|
||||
address_space *m_data;
|
||||
|
||||
virtual void reset_vector() { do_branch(3, 7, 0); }
|
||||
virtual void wakeup_vector() { do_branch(1, 0, 0); } // after halt
|
||||
virtual bool valid_wakeup_line(int line) const { return (line >= 0 && line < 4); }
|
||||
|
||||
int m_prgwidth;
|
||||
int m_datawidth;
|
||||
int m_prgmask;
|
||||
int m_datamask;
|
||||
|
||||
u16 m_pc, m_prev_pc;
|
||||
u16 m_op, m_prev_op;
|
||||
u8 m_param;
|
||||
int m_stack_levels;
|
||||
u16 m_stack[4]; // max 4
|
||||
int m_icount;
|
||||
|
||||
u8 m_acc;
|
||||
u8 m_bl;
|
||||
u8 m_bm;
|
||||
bool m_sbm;
|
||||
bool m_sbl;
|
||||
u8 m_c;
|
||||
bool m_skip;
|
||||
u8 m_w;
|
||||
u8 m_r;
|
||||
u8 m_r_out;
|
||||
int m_r_mask_option;
|
||||
int m_k_input[4];
|
||||
bool m_k_rise;
|
||||
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;
|
||||
devcb_write16 m_write_segs;
|
||||
emu_timer *m_lcd_timer;
|
||||
u8 m_l;
|
||||
u8 m_x;
|
||||
u8 m_y;
|
||||
u8 m_bp;
|
||||
bool m_bc;
|
||||
|
||||
u16 get_lcd_row(int column, u8* ram);
|
||||
virtual void lcd_update();
|
||||
TIMER_CALLBACK_MEMBER(lcd_timer_cb);
|
||||
virtual void init_lcd_driver();
|
||||
|
||||
// melody controller
|
||||
optional_region_ptr<u8> m_melody_rom;
|
||||
u8 m_melody_rd;
|
||||
u8 m_melody_step_count;
|
||||
u8 m_melody_duty_count;
|
||||
u8 m_melody_duty_index;
|
||||
u8 m_melody_address;
|
||||
|
||||
virtual void clock_melody() { }
|
||||
virtual void init_melody() { }
|
||||
|
||||
// divider
|
||||
emu_timer *m_div_timer;
|
||||
u16 m_div;
|
||||
bool m_1s;
|
||||
bool m_1s_rise;
|
||||
|
||||
virtual void init_divider();
|
||||
TIMER_CALLBACK_MEMBER(div_timer_cb);
|
||||
|
||||
// other i/o handlers
|
||||
devcb_read8 m_read_k;
|
||||
devcb_read_line m_read_ba;
|
||||
devcb_read_line m_read_b;
|
||||
devcb_write8 m_write_s;
|
||||
devcb_write8 m_write_r;
|
||||
|
||||
// misc internal helpers
|
||||
virtual void increment_pc();
|
||||
virtual void update_w_latch() { }
|
||||
void do_interrupt();
|
||||
|
||||
virtual u8 ram_r();
|
||||
virtual void ram_w(u8 data);
|
||||
void pop_stack();
|
||||
void push_stack();
|
||||
virtual void do_branch(u8 pu, u8 pm, u8 pl);
|
||||
u8 bitmask(u16 param);
|
||||
|
||||
// opcode handlers
|
||||
virtual void op_lb();
|
||||
virtual void op_lbl();
|
||||
virtual void op_sbl();
|
||||
virtual void op_sbm();
|
||||
virtual void op_exbla();
|
||||
virtual void op_incb();
|
||||
virtual void op_decb();
|
||||
|
||||
virtual void op_atpl();
|
||||
virtual void op_rtn0();
|
||||
virtual void op_rtn1();
|
||||
virtual void op_tl();
|
||||
virtual void op_tml();
|
||||
virtual void op_tm();
|
||||
virtual void op_t();
|
||||
|
||||
virtual void op_exc();
|
||||
virtual void op_bdc();
|
||||
virtual void op_exci();
|
||||
virtual void op_excd();
|
||||
virtual void op_lda();
|
||||
virtual void op_lax();
|
||||
virtual void op_ptw();
|
||||
virtual void op_wr();
|
||||
virtual void op_ws();
|
||||
|
||||
virtual void op_kta();
|
||||
virtual void op_atbp();
|
||||
virtual void op_atx();
|
||||
virtual void op_atl();
|
||||
virtual void op_atfc();
|
||||
virtual void op_atr();
|
||||
|
||||
virtual void op_add();
|
||||
virtual void op_add11();
|
||||
virtual void op_adx();
|
||||
virtual void op_coma();
|
||||
virtual void op_rot();
|
||||
virtual void op_rc();
|
||||
virtual void op_sc();
|
||||
|
||||
virtual void op_tb();
|
||||
virtual void op_tc();
|
||||
virtual void op_tam();
|
||||
virtual void op_tmi();
|
||||
virtual void op_ta0();
|
||||
virtual void op_tabl();
|
||||
virtual void op_tis();
|
||||
virtual void op_tal();
|
||||
virtual void op_tf1();
|
||||
virtual void op_tf4();
|
||||
|
||||
virtual void op_rm();
|
||||
virtual void op_sm();
|
||||
|
||||
virtual void op_pre();
|
||||
virtual void op_sme();
|
||||
virtual void op_rme();
|
||||
virtual void op_tmel();
|
||||
|
||||
virtual void op_skip();
|
||||
virtual void op_cend();
|
||||
virtual void op_idiv();
|
||||
virtual void op_dr();
|
||||
virtual void op_dta();
|
||||
virtual void op_clklo();
|
||||
virtual void op_clkhi();
|
||||
|
||||
void op_illegal();
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_SM510_SM510BASE_H
|
@ -154,4 +154,4 @@ private:
|
||||
static const u8 sm590_mnemonic[0x100];
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // MAME_CPU_SM510_SM510D_H
|
||||
|
@ -4,7 +4,7 @@
|
||||
// SM510 shared opcode handlers
|
||||
|
||||
#include "emu.h"
|
||||
#include "sm510.h"
|
||||
#include "sm510base.h"
|
||||
|
||||
|
||||
// internal helpers
|
||||
@ -52,7 +52,6 @@ u8 sm510_base_device::bitmask(u16 param)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// instruction set
|
||||
|
||||
// RAM address instructions
|
||||
@ -154,7 +153,6 @@ void sm510_base_device::op_tm()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Data transfer instructions
|
||||
|
||||
void sm510_base_device::op_exc()
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sm510.h"
|
||||
#include "sm511.h"
|
||||
#include "sm510d.h"
|
||||
#include "debugger.h"
|
||||
|
||||
@ -67,7 +67,6 @@ sm512_device::sm512_device(const machine_config &mconfig, const char *tag, devic
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
@ -82,7 +81,6 @@ void sm511_device::device_reset()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// melody controller
|
||||
//-------------------------------------------------
|
||||
@ -158,22 +156,10 @@ void sm511_device::init_melody()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm511_device::get_opcode_param()
|
||||
{
|
||||
// LBL, PRE, TL, TML and prefix opcodes are 2 bytes
|
||||
if ((m_op >= 0x5f && m_op <= 0x61) || (m_op & 0xf0) == 0x70 || (m_op & 0xfc) == 0x68)
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void sm511_device::execute_one()
|
||||
{
|
||||
switch (m_op & 0xf0)
|
||||
@ -267,3 +253,9 @@ void sm511_device::execute_one()
|
||||
// BM high bit is only valid for 1 step
|
||||
m_sbm = (m_op == 0x02);
|
||||
}
|
||||
|
||||
bool sm511_device::op_argument()
|
||||
{
|
||||
// LBL, PRE, TL, TML and prefix opcodes are 2 bytes
|
||||
return (m_op >= 0x5f && m_op <= 0x61) || (m_op & 0xf0) == 0x70 || (m_op & 0xfc) == 0x68;
|
||||
}
|
62
src/devices/cpu/sm510/sm511.h
Normal file
62
src/devices/cpu/sm510/sm511.h
Normal file
@ -0,0 +1,62 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Sharp SM511 MCU family cores
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAME_CPU_SM510_SM511_H
|
||||
#define MAME_CPU_SM510_SM511_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sm510base.h"
|
||||
|
||||
|
||||
// pinout reference
|
||||
|
||||
/*
|
||||
|
||||
SM511: identical to SM510 (see sm510.h)
|
||||
|
||||
SM512: can't be bothered to draw one here, it's 80 pins QFP, a lot of LCD segment pins
|
||||
|
||||
*/
|
||||
|
||||
class sm511_device : public sm510_base_device
|
||||
{
|
||||
public:
|
||||
sm511_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
|
||||
protected:
|
||||
sm511_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
|
||||
|
||||
void program_4k(address_map &map);
|
||||
void data_96_32x4(address_map &map);
|
||||
|
||||
virtual void device_post_load() override { notify_clock_changed(); }
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void execute_one() override;
|
||||
virtual bool op_argument() override;
|
||||
|
||||
virtual void clock_melody() override;
|
||||
virtual void init_melody() override;
|
||||
};
|
||||
|
||||
class sm512_device : public sm511_device
|
||||
{
|
||||
public:
|
||||
sm512_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
|
||||
protected:
|
||||
void data_80_48x4(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(SM511, sm511_device)
|
||||
DECLARE_DEVICE_TYPE(SM512, sm512_device)
|
||||
|
||||
#endif // MAME_CPU_SM510_SM511_H
|
@ -55,7 +55,6 @@ sm531_device::sm531_device(const machine_config &mconfig, const char *tag, devic
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
@ -67,7 +66,6 @@ void sm530_device::device_start()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
@ -79,22 +77,10 @@ void sm530_device::device_reset()
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm530_device::get_opcode_param()
|
||||
{
|
||||
// LBL, PRE, TL opcodes are 2 bytes
|
||||
if (m_op == 0x6b || m_op == 0x78 || ((m_op & 0xf8) == 0x60))
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void sm530_device::execute_one()
|
||||
{
|
||||
switch (m_op & 0xf0)
|
||||
@ -174,3 +160,9 @@ void sm530_device::execute_one()
|
||||
m_sbl = (m_op == 0x73);
|
||||
m_sbm = (m_op == 0x72);
|
||||
}
|
||||
|
||||
bool sm530_device::op_argument()
|
||||
{
|
||||
// LBL, PRE, TL opcodes are 2 bytes
|
||||
return m_op == 0x6b || m_op == 0x78 || ((m_op & 0xf8) == 0x60);
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sm510.h"
|
||||
#include "sm511.h"
|
||||
|
||||
|
||||
class sm530_device : public sm511_device
|
||||
@ -32,7 +32,7 @@ protected:
|
||||
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 3 - 1) / 3; } // 3 cycles per machine cycle
|
||||
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 3); } // "
|
||||
virtual void execute_one() override;
|
||||
virtual void get_opcode_param() override;
|
||||
virtual bool op_argument() override;
|
||||
|
||||
using sm510_base_device::do_branch;
|
||||
virtual void do_branch(u8 pu, u8 pl); // does not have Pm
|
||||
@ -58,7 +58,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(SM530, sm530_device)
|
||||
DECLARE_DEVICE_TYPE(SM531, sm531_device)
|
||||
|
||||
|
@ -16,7 +16,6 @@ void sm530_device::do_branch(u8 pu, u8 pl)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// instruction set
|
||||
|
||||
// RAM address instructions
|
||||
|
@ -61,6 +61,7 @@ std::unique_ptr<util::disasm_interface> sm590_device::create_disassembler()
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm590_device::device_reset()
|
||||
{
|
||||
// ACL
|
||||
@ -76,27 +77,11 @@ void sm590_device::device_reset()
|
||||
//m_write_r(0); // TODO: are the four ports zeroed on reset?
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// wake from suspend mode
|
||||
//-------------------------------------------------
|
||||
bool sm590_device::wake_me_up()
|
||||
{
|
||||
// in halt mode, wake up after R2.2 goes high
|
||||
if (m_rports[2]&0x4)
|
||||
{
|
||||
m_halt = false;
|
||||
do_branch(0, 1, 0); // field 0, page 1, step 0
|
||||
|
||||
standard_irq_callback(0);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute
|
||||
//-------------------------------------------------
|
||||
|
||||
void sm590_device::increment_pc()
|
||||
{
|
||||
// PL(program counter low 7 bits) is a simple LFSR: newbit = (bit0==bit1)
|
||||
@ -105,17 +90,6 @@ void sm590_device::increment_pc()
|
||||
m_pc = feed | (m_pc >> 1 & 0x3f) | (m_pc & ~0x7f);
|
||||
}
|
||||
|
||||
void sm590_device::get_opcode_param()
|
||||
{
|
||||
// TL, TLS(TML) opcodes are 2 bytes
|
||||
if ((m_op & 0xf8) == 0x78)
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void sm590_device::execute_one()
|
||||
{
|
||||
switch (m_op & 0xf0) // opcodes with 4 bit params
|
||||
@ -184,3 +158,9 @@ void sm590_device::execute_one()
|
||||
|
||||
} // big switch
|
||||
}
|
||||
|
||||
bool sm590_device::op_argument()
|
||||
{
|
||||
// TL, TLS(TML) opcodes are 2 bytes
|
||||
return (m_op & 0xf8) == 0x78;
|
||||
}
|
@ -9,12 +9,13 @@
|
||||
#ifndef MAME_CPU_SM510_SM590_H
|
||||
#define MAME_CPU_SM510_SM590_H
|
||||
|
||||
#include "sm510.h"
|
||||
#include "sm510base.h"
|
||||
|
||||
|
||||
// I/O ports setup
|
||||
|
||||
// ..
|
||||
// It does not have K pins, but can wake up after halt on R2.2
|
||||
#define SM590_INPUT_LINE_R22 SM510_INPUT_LINE_K3
|
||||
|
||||
|
||||
// pinout reference
|
||||
@ -89,7 +90,6 @@ R3.3/CL2 => |_|6 15|_| <> R1.3
|
||||
GND -- |_|10 11|_| <> R1.0
|
||||
|____________|
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class sm590_device : public sm510_base_device
|
||||
@ -105,17 +105,17 @@ protected:
|
||||
|
||||
virtual void device_reset() override;
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual bool wake_me_up() override;
|
||||
virtual void init_divider() override { }
|
||||
virtual void init_lcd_driver() override { }
|
||||
virtual void init_melody() override { }
|
||||
virtual void increment_pc() override;
|
||||
virtual void execute_one() override;
|
||||
virtual void get_opcode_param() override;
|
||||
virtual bool op_argument() override;
|
||||
virtual void do_branch(u8 pu, u8 pm, u8 pl) override;
|
||||
|
||||
virtual void reset_vector() override { do_branch(0, 0, 0); }
|
||||
virtual void wakeup_vector() override { do_branch(0, 1, 0); }
|
||||
virtual bool valid_wakeup_line(int line) const override { return (line == SM590_INPUT_LINE_R22); }
|
||||
|
||||
// opcode handlers
|
||||
// 00-3f
|
||||
|
@ -15,6 +15,7 @@ void sm590_device::do_branch(u8 pu, u8 pm, u8 pl)
|
||||
m_pc = (((u16)pu << 9 & 0x200) | ((u16)pm << 7 & 0x180) | (pl & 0x07f)) & m_prgmask;
|
||||
}
|
||||
|
||||
|
||||
// instruction set
|
||||
|
||||
void sm590_device::op_adx()
|
||||
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sm500.h"
|
||||
#include "sm5a.h"
|
||||
#include "sm510d.h"
|
||||
#include "debugger.h"
|
||||
|
79
src/devices/cpu/sm510/sm5a.h
Normal file
79
src/devices/cpu/sm510/sm5a.h
Normal file
@ -0,0 +1,79 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap
|
||||
/*
|
||||
|
||||
Sharp SM5A MCU family cores
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAME_CPU_SM510_SM5A_H
|
||||
#define MAME_CPU_SM510_SM5A_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sm500.h"
|
||||
|
||||
|
||||
// pinout reference
|
||||
|
||||
/*
|
||||
|
||||
OS2 OS3 OS4 K4 K3 K2 K1 GND al bt ACL _R1 _Tp NC NC note: on SM5L, pin 31=V1, 32=V2, 33=NC
|
||||
45 44 43 42 41 40 39 38 37 36 35 34 33 32 31
|
||||
____________________________________________________________
|
||||
| |
|
||||
OS1 46 | | 30 H1
|
||||
O41 47 | | 29 H2
|
||||
O31 48 | | 28 Vm
|
||||
O21 49 | | 27 Vdd
|
||||
O11 50 | | 26 _R2
|
||||
O42 51 | | 25 _R3
|
||||
O32 52 | SM5A | 24 _R4
|
||||
O22 53 | SM5L | 23 OSCin
|
||||
O12 54 | | 22 OSCout
|
||||
O43 55 | | 21 _T2
|
||||
O33 56 | | 20 _T1
|
||||
O23 57 | | 19 O18
|
||||
O13 58 | | 18 O28
|
||||
O44 59 | | 17 O38
|
||||
O34 60 | * | 16 O48
|
||||
|____________________________________________________________/
|
||||
|
||||
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
O24 O14 O45 O35 O25 O15 O46 GND O36 O26 O16 O47 O37 O27 O17
|
||||
*/
|
||||
|
||||
class sm5a_device : public sm500_device
|
||||
{
|
||||
public:
|
||||
sm5a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
|
||||
protected:
|
||||
sm5a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int o_pins, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
|
||||
|
||||
void program_1_8k(address_map &map);
|
||||
void data_5x13x4(address_map &map);
|
||||
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual void execute_one() override;
|
||||
virtual int get_trs_field() override { return 1; }
|
||||
};
|
||||
|
||||
class sm5l_device : public sm5a_device
|
||||
{
|
||||
public:
|
||||
sm5l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
};
|
||||
|
||||
class kb1013vk12_device : public sm5a_device
|
||||
{
|
||||
public:
|
||||
kb1013vk12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768);
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(SM5A, sm5a_device)
|
||||
DECLARE_DEVICE_TYPE(SM5L, sm5l_device)
|
||||
DECLARE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device)
|
||||
|
||||
#endif // MAME_CPU_SM510_SM5A_H
|
@ -277,9 +277,6 @@ void hh_sm510_state::sm500_lcd_segment_w(offs_t offset, u16 data)
|
||||
|
||||
// generic input handlers - usually S output is input mux, and K input for buttons
|
||||
|
||||
#define PORT_CHANGED_CB(x) \
|
||||
PORT_CHANGED_MEMBER(DEVICE_SELF, hh_sm510_state, x, 0)
|
||||
|
||||
u8 hh_sm510_state::read_inputs(int columns, int fixed)
|
||||
{
|
||||
u8 ret = 0;
|
||||
@ -298,7 +295,9 @@ u8 hh_sm510_state::read_inputs(int columns, int fixed)
|
||||
void hh_sm510_state::update_k_line()
|
||||
{
|
||||
// this is necessary because the MCU can wake up on K input activity
|
||||
m_maincpu->set_input_line(SM510_INPUT_LINE_K, input_r() ? ASSERT_LINE : CLEAR_LINE);
|
||||
u8 input = input_r();
|
||||
for (int i = 0; i < 4; i++)
|
||||
m_maincpu->set_input_line(i, BIT(input, i) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(hh_sm510_state::input_changed)
|
||||
|
@ -40,6 +40,9 @@
|
||||
// internal artwork
|
||||
#include "rzone.lh"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class rzone_state : public hh_sm510_state
|
||||
{
|
||||
public:
|
||||
@ -53,6 +56,9 @@ public:
|
||||
void rztoshden(machine_config &config);
|
||||
void rzindy500(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
|
||||
private:
|
||||
output_finder<> m_led_out;
|
||||
required_device<timer_device> m_led_off;
|
||||
@ -75,8 +81,6 @@ private:
|
||||
void t2_update_audio();
|
||||
void t2_write_r(u8 data);
|
||||
void t2_write_s(u8 data);
|
||||
|
||||
virtual void machine_start() override;
|
||||
};
|
||||
|
||||
|
||||
@ -102,9 +106,7 @@ void rzone_state::machine_start()
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
I/O
|
||||
|
||||
I/O
|
||||
***************************************************************************/
|
||||
|
||||
// console
|
||||
@ -214,47 +216,43 @@ void rzone_state::t2_write_s(u8 data)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Inputs
|
||||
|
||||
Inputs
|
||||
***************************************************************************/
|
||||
|
||||
static INPUT_PORTS_START( rzone )
|
||||
PORT_START("IN.0")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_POWER_ON ) PORT_CHANGED_MEMBER(DEVICE_SELF, hh_sm510_state, input_changed, 0)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON1 ) // A
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) // B
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_BUTTON3 ) // C
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 ) // D
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_VOLUME_DOWN ) PORT_NAME("Sound")
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_SELECT )
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_POWER_OFF )
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Pause")
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_START )
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_POWER_ON ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_CB(input_changed) // A
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_CB(input_changed) // B
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_CB(input_changed) // C
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_CB(input_changed) // D
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_VOLUME_DOWN ) PORT_CHANGED_CB(input_changed) PORT_NAME("Sound")
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_POWER_OFF ) PORT_CHANGED_CB(input_changed)
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_CB(input_changed) PORT_NAME("Pause")
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_START ) PORT_CHANGED_CB(input_changed)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Machine Config
|
||||
|
||||
Machine Configs
|
||||
***************************************************************************/
|
||||
|
||||
void rzone_state::rzbatfor(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
// basic machine hardware
|
||||
SM512(config, m_maincpu); // no external XTAL
|
||||
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
||||
m_maincpu->read_k().set(FUNC(rzone_state::input_r));
|
||||
m_maincpu->write_s().set(FUNC(rzone_state::t2_write_s));
|
||||
m_maincpu->write_r().set(FUNC(rzone_state::t2_write_r));
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_size(1368, 1080);
|
||||
@ -263,14 +261,14 @@ void rzone_state::rzbatfor(machine_config &config)
|
||||
TIMER(config, m_led_off).configure_generic(FUNC(rzone_state::led_off_callback));
|
||||
config.set_default_layout(layout_rzone);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||
}
|
||||
|
||||
void rzone_state::rztoshden(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
// basic machine hardware
|
||||
SM510(config, m_maincpu);
|
||||
m_maincpu->set_r_mask_option(sm510_base_device::RMASK_DIRECT);
|
||||
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
||||
@ -278,7 +276,7 @@ void rzone_state::rztoshden(machine_config &config)
|
||||
m_maincpu->write_s().set(FUNC(rzone_state::t1_write_s));
|
||||
m_maincpu->write_r().set(FUNC(rzone_state::t1_write_r));
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_size(1392, 1080);
|
||||
@ -287,14 +285,14 @@ void rzone_state::rztoshden(machine_config &config)
|
||||
TIMER(config, m_led_off).configure_generic(FUNC(rzone_state::led_off_callback));
|
||||
config.set_default_layout(layout_rzone);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||
}
|
||||
|
||||
void rzone_state::rzindy500(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
// basic machine hardware
|
||||
SM510(config, m_maincpu); // no external XTAL
|
||||
m_maincpu->set_r_mask_option(sm510_base_device::RMASK_DIRECT); // confirmed
|
||||
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
||||
@ -302,7 +300,7 @@ void rzone_state::rzindy500(machine_config &config)
|
||||
m_maincpu->write_s().set(FUNC(rzone_state::t1_write_s));
|
||||
m_maincpu->write_r().set(FUNC(rzone_state::t1_write_r));
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_size(1425, 1080);
|
||||
@ -311,7 +309,7 @@ void rzone_state::rzindy500(machine_config &config)
|
||||
TIMER(config, m_led_off).configure_generic(FUNC(rzone_state::led_off_callback));
|
||||
config.set_default_layout(layout_rzone);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||
}
|
||||
@ -319,9 +317,7 @@ void rzone_state::rzindy500(machine_config &config)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Game driver(s)
|
||||
|
||||
ROM Definitions
|
||||
***************************************************************************/
|
||||
|
||||
ROM_START( rzbatfor )
|
||||
@ -351,6 +347,13 @@ ROM_START( rzindy500 )
|
||||
ROM_LOAD( "rzindy500.svg", 0, 533411, CRC(cfc85677) SHA1(014b9123d81fba1488b4a22a6b6fd0c09e22c1ea) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Drivers
|
||||
***************************************************************************/
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
|
||||
CONS( 1995, rzbatfor, 0, 0, rzbatfor, rzone, rzone_state, empty_init, "Tiger Electronics", "R-Zone: Batman Forever", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -9,10 +9,18 @@
|
||||
#ifndef MAME_INCLUDES_HH_SM510_H
|
||||
#define MAME_INCLUDES_HH_SM510_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpu/sm510/sm510.h"
|
||||
#include "cpu/sm510/sm511.h"
|
||||
#include "cpu/sm510/sm5a.h"
|
||||
#include "sound/spkrdev.h"
|
||||
|
||||
|
||||
#define PORT_CHANGED_CB(x) \
|
||||
PORT_CHANGED_MEMBER(DEVICE_SELF, hh_sm510_state, x, 0)
|
||||
|
||||
|
||||
class hh_sm510_state : public driver_device
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user