mirror of
https://github.com/holub/mame
synced 2025-06-07 13:23:50 +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
|
if CPUS["SM510"] then
|
||||||
files {
|
files {
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm510base.cpp",
|
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.h",
|
||||||
|
MAME_DIR .. "src/devices/cpu/sm510/sm510.cpp",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm510op.cpp",
|
MAME_DIR .. "src/devices/cpu/sm510/sm510op.cpp",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm510core.cpp",
|
MAME_DIR .. "src/devices/cpu/sm510/sm511.h",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm511core.cpp",
|
MAME_DIR .. "src/devices/cpu/sm510/sm511.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/sm500.h",
|
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/sm500op.cpp",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm500core.cpp",
|
MAME_DIR .. "src/devices/cpu/sm510/sm5a.h",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm5acore.cpp",
|
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.h",
|
||||||
|
MAME_DIR .. "src/devices/cpu/sm510/sm590.cpp",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm590op.cpp",
|
MAME_DIR .. "src/devices/cpu/sm510/sm590op.cpp",
|
||||||
MAME_DIR .. "src/devices/cpu/sm510/sm590core.cpp",
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
Rockwell PPS-4/1 MCU cores
|
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
|
#ifndef MAME_CPU_PPS41_PPS41BASE_H
|
||||||
|
@ -147,17 +147,6 @@ void sm500_device::clock_melody()
|
|||||||
// execute
|
// 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()
|
void sm500_device::execute_one()
|
||||||
{
|
{
|
||||||
switch (m_op & 0xf0)
|
switch (m_op & 0xf0)
|
||||||
@ -248,3 +237,9 @@ void sm500_device::execute_one()
|
|||||||
|
|
||||||
} // big switch
|
} // 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
|
#pragma once
|
||||||
|
|
||||||
#include "sm510.h"
|
#include "sm510base.h"
|
||||||
|
|
||||||
|
|
||||||
// pinout reference
|
// pinout reference
|
||||||
@ -38,31 +38,6 @@ O36 48 | * | 13 K2
|
|||||||
|
|
||||||
1 2 3 4 5 6 7 8 9 10 11 12
|
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
|
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
|
class sm500_device : public sm510_base_device
|
||||||
@ -80,7 +55,7 @@ protected:
|
|||||||
virtual void device_reset() override;
|
virtual void device_reset() override;
|
||||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||||
virtual void execute_one() override;
|
virtual void execute_one() override;
|
||||||
virtual void get_opcode_param() override;
|
virtual bool op_argument() override;
|
||||||
virtual void clock_melody() override;
|
virtual void clock_melody() override;
|
||||||
|
|
||||||
virtual void reset_vector() override { do_branch(0, 0xf, 0); }
|
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(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
|
#endif // MAME_CPU_SM510_SM500_H
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
Sharp SM510 MCU core implementation
|
Sharp SM510 MCU core implementation
|
||||||
|
|
||||||
TODO:
|
|
||||||
- X
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
@ -49,7 +46,6 @@ std::unique_ptr<util::disasm_interface> sm510_device::create_disassembler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// buzzer controller
|
// buzzer controller
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -80,22 +76,10 @@ void sm510_device::clock_melody()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// execute
|
// 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()
|
void sm510_device::execute_one()
|
||||||
{
|
{
|
||||||
switch (m_op & 0xf0)
|
switch (m_op & 0xf0)
|
||||||
@ -174,3 +158,9 @@ void sm510_device::execute_one()
|
|||||||
// BM high bit is only valid for 1 step
|
// BM high bit is only valid for 1 step
|
||||||
m_sbm = (m_op == 0x02);
|
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
|
#pragma once
|
||||||
|
|
||||||
// I/O ports setup
|
#include "sm510base.h"
|
||||||
|
|
||||||
// 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
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// pinout reference
|
// pinout reference
|
||||||
@ -59,232 +44,6 @@ S8 60 | * | 16 b16
|
|||||||
BA OSCout Vdd
|
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
|
class sm510_device : public sm510_base_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -296,7 +55,7 @@ protected:
|
|||||||
|
|
||||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||||
virtual void execute_one() 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
|
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(SM510, sm510_device)
|
||||||
DECLARE_DEVICE_TYPE(SM511, sm511_device)
|
|
||||||
DECLARE_DEVICE_TYPE(SM512, sm512_device)
|
|
||||||
|
|
||||||
#endif // MAME_CPU_SM510_SM510_H
|
#endif // MAME_CPU_SM510_SM510_H
|
||||||
|
@ -13,16 +13,10 @@
|
|||||||
Default external frequency of these is 32.768kHz, forwarding a clockrate in the
|
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.
|
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 "emu.h"
|
||||||
#include "sm510.h"
|
#include "sm510base.h"
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
|
|
||||||
|
|
||||||
@ -38,6 +32,8 @@ enum
|
|||||||
|
|
||||||
void sm510_base_device::device_start()
|
void sm510_base_device::device_start()
|
||||||
{
|
{
|
||||||
|
assert(SM510_INPUT_LINE_K1 == 0);
|
||||||
|
|
||||||
m_program = &space(AS_PROGRAM);
|
m_program = &space(AS_PROGRAM);
|
||||||
m_data = &space(AS_DATA);
|
m_data = &space(AS_DATA);
|
||||||
m_prgmask = (1 << m_prgwidth) - 1;
|
m_prgmask = (1 << m_prgwidth) - 1;
|
||||||
@ -52,7 +48,7 @@ void sm510_base_device::device_start()
|
|||||||
m_write_segs.resolve_safe();
|
m_write_segs.resolve_safe();
|
||||||
|
|
||||||
// init/zerofill
|
// init/zerofill
|
||||||
memset(m_stack, 0, sizeof(m_stack));
|
std::fill_n(m_stack, std::size(m_stack), 0);
|
||||||
m_pc = 0;
|
m_pc = 0;
|
||||||
m_prev_pc = 0;
|
m_prev_pc = 0;
|
||||||
m_op = 0;
|
m_op = 0;
|
||||||
@ -70,7 +66,9 @@ void sm510_base_device::device_start()
|
|||||||
m_r_out = 0;
|
m_r_out = 0;
|
||||||
m_div = 0;
|
m_div = 0;
|
||||||
m_1s = false;
|
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_l = 0;
|
||||||
m_x = 0;
|
m_x = 0;
|
||||||
m_y = 0;
|
m_y = 0;
|
||||||
@ -103,7 +101,9 @@ void sm510_base_device::device_start()
|
|||||||
save_item(NAME(m_r_out));
|
save_item(NAME(m_r_out));
|
||||||
save_item(NAME(m_div));
|
save_item(NAME(m_div));
|
||||||
save_item(NAME(m_1s));
|
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_l));
|
||||||
save_item(NAME(m_x));
|
save_item(NAME(m_x));
|
||||||
save_item(NAME(m_y));
|
save_item(NAME(m_y));
|
||||||
@ -138,6 +138,13 @@ void sm510_base_device::device_start()
|
|||||||
init_melody();
|
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
|
// lcd driver
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -183,14 +189,6 @@ inline u16 sm510_base_device::get_lcd_row(int column, u8* ram)
|
|||||||
return rowdata;
|
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()
|
void sm510_base_device::lcd_update()
|
||||||
{
|
{
|
||||||
// 4 columns
|
// 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)
|
TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb)
|
||||||
{
|
{
|
||||||
m_div = (m_div + 1) & 0x7fff;
|
m_div = (m_div + 1) & 0x7fff;
|
||||||
|
|
||||||
// 1S signal on overflow(falling edge of F1)
|
// 1S signal on overflow(falling edge of F1)
|
||||||
if (m_div == 0)
|
if (m_div == 0)
|
||||||
|
{
|
||||||
|
m_1s_rise = !m_1s;
|
||||||
m_1s = true;
|
m_1s = true;
|
||||||
|
}
|
||||||
|
|
||||||
clock_melody();
|
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
|
// execute
|
||||||
@ -286,17 +287,29 @@ void sm510_base_device::increment_pc()
|
|||||||
|
|
||||||
void sm510_base_device::execute_run()
|
void sm510_base_device::execute_run()
|
||||||
{
|
{
|
||||||
|
bool _1s_prev = m_1s_rise;
|
||||||
|
|
||||||
while (m_icount > 0)
|
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
|
if (!wakeup)
|
||||||
m_icount = 0;
|
{
|
||||||
return;
|
// got nothing to do
|
||||||
|
m_icount = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
do_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_icount--;
|
||||||
|
|
||||||
// remember previous state
|
// remember previous state
|
||||||
m_prev_op = m_op;
|
m_prev_op = m_op;
|
||||||
m_prev_pc = m_pc;
|
m_prev_pc = m_pc;
|
||||||
@ -306,7 +319,14 @@ void sm510_base_device::execute_run()
|
|||||||
debugger_instruction_hook(m_pc);
|
debugger_instruction_hook(m_pc);
|
||||||
m_op = m_program->read_byte(m_pc);
|
m_op = m_program->read_byte(m_pc);
|
||||||
increment_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
|
// handle opcode if it's not skipped
|
||||||
if (m_skip)
|
if (m_skip)
|
||||||
@ -316,5 +336,10 @@ void sm510_base_device::execute_run()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
execute_one();
|
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];
|
static const u8 sm590_mnemonic[0x100];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // MAME_CPU_SM510_SM510D_H
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// SM510 shared opcode handlers
|
// SM510 shared opcode handlers
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "sm510.h"
|
#include "sm510base.h"
|
||||||
|
|
||||||
|
|
||||||
// internal helpers
|
// internal helpers
|
||||||
@ -52,7 +52,6 @@ u8 sm510_base_device::bitmask(u16 param)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// instruction set
|
// instruction set
|
||||||
|
|
||||||
// RAM address instructions
|
// RAM address instructions
|
||||||
@ -154,7 +153,6 @@ void sm510_base_device::op_tm()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Data transfer instructions
|
// Data transfer instructions
|
||||||
|
|
||||||
void sm510_base_device::op_exc()
|
void sm510_base_device::op_exc()
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "sm510.h"
|
#include "sm511.h"
|
||||||
#include "sm510d.h"
|
#include "sm510d.h"
|
||||||
#include "debugger.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
|
// device_reset - device-specific reset
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -82,7 +81,6 @@ void sm511_device::device_reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// melody controller
|
// melody controller
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -158,22 +156,10 @@ void sm511_device::init_melody()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// execute
|
// 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()
|
void sm511_device::execute_one()
|
||||||
{
|
{
|
||||||
switch (m_op & 0xf0)
|
switch (m_op & 0xf0)
|
||||||
@ -267,3 +253,9 @@ void sm511_device::execute_one()
|
|||||||
// BM high bit is only valid for 1 step
|
// BM high bit is only valid for 1 step
|
||||||
m_sbm = (m_op == 0x02);
|
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
|
// device_start - device-specific startup
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -67,7 +66,6 @@ void sm530_device::device_start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// device_reset - device-specific reset
|
// device_reset - device-specific reset
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -79,22 +77,10 @@ void sm530_device::device_reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// execute
|
// 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()
|
void sm530_device::execute_one()
|
||||||
{
|
{
|
||||||
switch (m_op & 0xf0)
|
switch (m_op & 0xf0)
|
||||||
@ -174,3 +160,9 @@ void sm530_device::execute_one()
|
|||||||
m_sbl = (m_op == 0x73);
|
m_sbl = (m_op == 0x73);
|
||||||
m_sbm = (m_op == 0x72);
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "sm510.h"
|
#include "sm511.h"
|
||||||
|
|
||||||
|
|
||||||
class sm530_device : public sm511_device
|
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_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 u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 3); } // "
|
||||||
virtual void execute_one() override;
|
virtual void execute_one() override;
|
||||||
virtual void get_opcode_param() override;
|
virtual bool op_argument() override;
|
||||||
|
|
||||||
using sm510_base_device::do_branch;
|
using sm510_base_device::do_branch;
|
||||||
virtual void do_branch(u8 pu, u8 pl); // does not have Pm
|
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(SM530, sm530_device)
|
||||||
DECLARE_DEVICE_TYPE(SM531, sm531_device)
|
DECLARE_DEVICE_TYPE(SM531, sm531_device)
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ void sm530_device::do_branch(u8 pu, u8 pl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// instruction set
|
// instruction set
|
||||||
|
|
||||||
// RAM address instructions
|
// RAM address instructions
|
||||||
|
@ -61,6 +61,7 @@ std::unique_ptr<util::disasm_interface> sm590_device::create_disassembler()
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// device_reset - device-specific reset
|
// device_reset - device-specific reset
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void sm590_device::device_reset()
|
void sm590_device::device_reset()
|
||||||
{
|
{
|
||||||
// ACL
|
// ACL
|
||||||
@ -76,27 +77,11 @@ void sm590_device::device_reset()
|
|||||||
//m_write_r(0); // TODO: are the four ports zeroed on 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
|
// execute
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void sm590_device::increment_pc()
|
void sm590_device::increment_pc()
|
||||||
{
|
{
|
||||||
// PL(program counter low 7 bits) is a simple LFSR: newbit = (bit0==bit1)
|
// 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);
|
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()
|
void sm590_device::execute_one()
|
||||||
{
|
{
|
||||||
switch (m_op & 0xf0) // opcodes with 4 bit params
|
switch (m_op & 0xf0) // opcodes with 4 bit params
|
||||||
@ -184,3 +158,9 @@ void sm590_device::execute_one()
|
|||||||
|
|
||||||
} // big switch
|
} // 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
|
#ifndef MAME_CPU_SM510_SM590_H
|
||||||
#define MAME_CPU_SM510_SM590_H
|
#define MAME_CPU_SM510_SM590_H
|
||||||
|
|
||||||
#include "sm510.h"
|
#include "sm510base.h"
|
||||||
|
|
||||||
|
|
||||||
// I/O ports setup
|
// 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
|
// pinout reference
|
||||||
@ -89,7 +90,6 @@ R3.3/CL2 => |_|6 15|_| <> R1.3
|
|||||||
GND -- |_|10 11|_| <> R1.0
|
GND -- |_|10 11|_| <> R1.0
|
||||||
|____________|
|
|____________|
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class sm590_device : public sm510_base_device
|
class sm590_device : public sm510_base_device
|
||||||
@ -105,17 +105,17 @@ protected:
|
|||||||
|
|
||||||
virtual void device_reset() override;
|
virtual void device_reset() override;
|
||||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() 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_divider() override { }
|
||||||
virtual void init_lcd_driver() override { }
|
virtual void init_lcd_driver() override { }
|
||||||
virtual void init_melody() override { }
|
virtual void init_melody() override { }
|
||||||
virtual void increment_pc() override;
|
virtual void increment_pc() override;
|
||||||
virtual void execute_one() 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 do_branch(u8 pu, u8 pm, u8 pl) override;
|
||||||
|
|
||||||
virtual void reset_vector() override { do_branch(0, 0, 0); }
|
virtual void reset_vector() override { do_branch(0, 0, 0); }
|
||||||
virtual void wakeup_vector() override { do_branch(0, 1, 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
|
// opcode handlers
|
||||||
// 00-3f
|
// 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;
|
m_pc = (((u16)pu << 9 & 0x200) | ((u16)pm << 7 & 0x180) | (pl & 0x07f)) & m_prgmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// instruction set
|
// instruction set
|
||||||
|
|
||||||
void sm590_device::op_adx()
|
void sm590_device::op_adx()
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "sm500.h"
|
#include "sm5a.h"
|
||||||
#include "sm510d.h"
|
#include "sm510d.h"
|
||||||
#include "debugger.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
|
// 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 hh_sm510_state::read_inputs(int columns, int fixed)
|
||||||
{
|
{
|
||||||
u8 ret = 0;
|
u8 ret = 0;
|
||||||
@ -298,7 +295,9 @@ u8 hh_sm510_state::read_inputs(int columns, int fixed)
|
|||||||
void hh_sm510_state::update_k_line()
|
void hh_sm510_state::update_k_line()
|
||||||
{
|
{
|
||||||
// this is necessary because the MCU can wake up on K input activity
|
// 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)
|
INPUT_CHANGED_MEMBER(hh_sm510_state::input_changed)
|
||||||
|
@ -40,6 +40,9 @@
|
|||||||
// internal artwork
|
// internal artwork
|
||||||
#include "rzone.lh"
|
#include "rzone.lh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
class rzone_state : public hh_sm510_state
|
class rzone_state : public hh_sm510_state
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -53,6 +56,9 @@ public:
|
|||||||
void rztoshden(machine_config &config);
|
void rztoshden(machine_config &config);
|
||||||
void rzindy500(machine_config &config);
|
void rzindy500(machine_config &config);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void machine_start() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
output_finder<> m_led_out;
|
output_finder<> m_led_out;
|
||||||
required_device<timer_device> m_led_off;
|
required_device<timer_device> m_led_off;
|
||||||
@ -75,8 +81,6 @@ private:
|
|||||||
void t2_update_audio();
|
void t2_update_audio();
|
||||||
void t2_write_r(u8 data);
|
void t2_write_r(u8 data);
|
||||||
void t2_write_s(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
|
// console
|
||||||
@ -214,47 +216,43 @@ void rzone_state::t2_write_s(u8 data)
|
|||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
Inputs
|
||||||
Inputs
|
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
static INPUT_PORTS_START( rzone )
|
static INPUT_PORTS_START( rzone )
|
||||||
PORT_START("IN.0")
|
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( 0x0001, IP_ACTIVE_HIGH, IPT_POWER_ON ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
|
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
|
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
|
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
|
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON1 ) // A
|
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_CB(input_changed) // A
|
||||||
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) // B
|
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_CB(input_changed) // B
|
||||||
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_BUTTON3 ) // C
|
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_CB(input_changed) // C
|
||||||
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 ) // D
|
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_CB(input_changed) // D
|
||||||
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_VOLUME_DOWN ) PORT_NAME("Sound")
|
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_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_POWER_OFF )
|
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_POWER_OFF ) PORT_CHANGED_CB(input_changed)
|
||||||
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Pause")
|
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_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_START ) PORT_CHANGED_CB(input_changed)
|
||||||
INPUT_PORTS_END
|
INPUT_PORTS_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
Machine Configs
|
||||||
Machine Config
|
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
void rzone_state::rzbatfor(machine_config &config)
|
void rzone_state::rzbatfor(machine_config &config)
|
||||||
{
|
{
|
||||||
/* basic machine hardware */
|
// basic machine hardware
|
||||||
SM512(config, m_maincpu); // no external XTAL
|
SM512(config, m_maincpu); // no external XTAL
|
||||||
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
||||||
m_maincpu->read_k().set(FUNC(rzone_state::input_r));
|
m_maincpu->read_k().set(FUNC(rzone_state::input_r));
|
||||||
m_maincpu->write_s().set(FUNC(rzone_state::t2_write_s));
|
m_maincpu->write_s().set(FUNC(rzone_state::t2_write_s));
|
||||||
m_maincpu->write_r().set(FUNC(rzone_state::t2_write_r));
|
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_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||||
screen.set_refresh_hz(60);
|
screen.set_refresh_hz(60);
|
||||||
screen.set_size(1368, 1080);
|
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));
|
TIMER(config, m_led_off).configure_generic(FUNC(rzone_state::led_off_callback));
|
||||||
config.set_default_layout(layout_rzone);
|
config.set_default_layout(layout_rzone);
|
||||||
|
|
||||||
/* sound hardware */
|
// sound hardware
|
||||||
SPEAKER(config, "mono").front_center();
|
SPEAKER(config, "mono").front_center();
|
||||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rzone_state::rztoshden(machine_config &config)
|
void rzone_state::rztoshden(machine_config &config)
|
||||||
{
|
{
|
||||||
/* basic machine hardware */
|
// basic machine hardware
|
||||||
SM510(config, m_maincpu);
|
SM510(config, m_maincpu);
|
||||||
m_maincpu->set_r_mask_option(sm510_base_device::RMASK_DIRECT);
|
m_maincpu->set_r_mask_option(sm510_base_device::RMASK_DIRECT);
|
||||||
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
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_s().set(FUNC(rzone_state::t1_write_s));
|
||||||
m_maincpu->write_r().set(FUNC(rzone_state::t1_write_r));
|
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_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||||
screen.set_refresh_hz(60);
|
screen.set_refresh_hz(60);
|
||||||
screen.set_size(1392, 1080);
|
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));
|
TIMER(config, m_led_off).configure_generic(FUNC(rzone_state::led_off_callback));
|
||||||
config.set_default_layout(layout_rzone);
|
config.set_default_layout(layout_rzone);
|
||||||
|
|
||||||
/* sound hardware */
|
// sound hardware
|
||||||
SPEAKER(config, "mono").front_center();
|
SPEAKER(config, "mono").front_center();
|
||||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rzone_state::rzindy500(machine_config &config)
|
void rzone_state::rzindy500(machine_config &config)
|
||||||
{
|
{
|
||||||
/* basic machine hardware */
|
// basic machine hardware
|
||||||
SM510(config, m_maincpu); // no external XTAL
|
SM510(config, m_maincpu); // no external XTAL
|
||||||
m_maincpu->set_r_mask_option(sm510_base_device::RMASK_DIRECT); // confirmed
|
m_maincpu->set_r_mask_option(sm510_base_device::RMASK_DIRECT); // confirmed
|
||||||
m_maincpu->write_segs().set(FUNC(rzone_state::sm510_lcd_segment_w));
|
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_s().set(FUNC(rzone_state::t1_write_s));
|
||||||
m_maincpu->write_r().set(FUNC(rzone_state::t1_write_r));
|
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_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG));
|
||||||
screen.set_refresh_hz(60);
|
screen.set_refresh_hz(60);
|
||||||
screen.set_size(1425, 1080);
|
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));
|
TIMER(config, m_led_off).configure_generic(FUNC(rzone_state::led_off_callback));
|
||||||
config.set_default_layout(layout_rzone);
|
config.set_default_layout(layout_rzone);
|
||||||
|
|
||||||
/* sound hardware */
|
// sound hardware
|
||||||
SPEAKER(config, "mono").front_center();
|
SPEAKER(config, "mono").front_center();
|
||||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
|
||||||
}
|
}
|
||||||
@ -319,9 +317,7 @@ void rzone_state::rzindy500(machine_config &config)
|
|||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
ROM Definitions
|
||||||
Game driver(s)
|
|
||||||
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
ROM_START( rzbatfor )
|
ROM_START( rzbatfor )
|
||||||
@ -351,6 +347,13 @@ ROM_START( rzindy500 )
|
|||||||
ROM_LOAD( "rzindy500.svg", 0, 533411, CRC(cfc85677) SHA1(014b9123d81fba1488b4a22a6b6fd0c09e22c1ea) )
|
ROM_LOAD( "rzindy500.svg", 0, 533411, CRC(cfc85677) SHA1(014b9123d81fba1488b4a22a6b6fd0c09e22c1ea) )
|
||||||
ROM_END
|
ROM_END
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
Drivers
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
|
// 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 )
|
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
|
#ifndef MAME_INCLUDES_HH_SM510_H
|
||||||
#define MAME_INCLUDES_HH_SM510_H
|
#define MAME_INCLUDES_HH_SM510_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "cpu/sm510/sm510.h"
|
#include "cpu/sm510/sm510.h"
|
||||||
|
#include "cpu/sm510/sm511.h"
|
||||||
|
#include "cpu/sm510/sm5a.h"
|
||||||
#include "sound/spkrdev.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
|
class hh_sm510_state : public driver_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user