summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sm510/sm510base.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sm510/sm510base.h')
-rw-r--r--src/devices/cpu/sm510/sm510base.h251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/devices/cpu/sm510/sm510base.h b/src/devices/cpu/sm510/sm510base.h
new file mode 100644
index 00000000000..1e3aa5c9795
--- /dev/null
+++ b/src/devices/cpu/sm510/sm510base.h
@@ -0,0 +1,251 @@
+// 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 active K input can wake up the CPU,
+// driver is required to use set_input_line(SM510_EXT_WAKEUP_LINE, state)
+#define SM510_EXT_WAKEUP_LINE 0
+
+// 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:
+ // 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/8-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(); }
+
+ // 4/8-bit S strobe output port
+ auto write_s() { return m_write_s.bind(); }
+
+ // 1/2-bit R (buzzer/melody) output port
+ // may also be called F(frequency?) or SO(sound out)
+ // SM590 has 4 R ports, don't use this one, see sm590.h
+ 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/SM530: H1/2 as a0, O group as a1-a4, O data as d0-d3
+ auto write_segs() { return m_write_segs.bind(); }
+
+protected:
+ // 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);
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface implementation
+ 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 1; }
+ virtual void execute_set_input(int line, int state) override;
+ virtual void execute_run() override;
+
+ // device_memory_interface implementation
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual void execute_one() = 0;
+ virtual bool op_argument() { return false; }
+
+ virtual void reset_vector() { do_branch(3, 7, 0); }
+ virtual void wakeup_vector() { do_branch(1, 0, 0); } // after halt
+
+ address_space_config m_program_config;
+ address_space_config m_data_config;
+ address_space *m_program;
+ address_space *m_data;
+
+ int m_prgwidth;
+ int m_datawidth;
+ int m_prgmask;
+ int m_datamask;
+ int m_pagemask;
+
+ int m_icount;
+ int m_state_count;
+
+ 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
+
+ u8 m_acc;
+ u8 m_bl;
+ u8 m_bm;
+ u8 m_bmask;
+ u8 m_c;
+ bool m_skip;
+ u8 m_w;
+ u8 m_r;
+ u8 m_r_out;
+ int m_r_mask_option;
+ bool m_ext_wakeup;
+ 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;
+ u8 m_gamma;
+
+ virtual void init_divider();
+ virtual 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_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_dta();
+ virtual void op_clklo();
+ virtual void op_clkhi();
+
+ void op_illegal();
+};
+
+#endif // MAME_CPU_SM510_SM510BASE_H