summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2015-07-09 16:18:50 +0200
committer hap <happppp@users.noreply.github.com>2015-07-09 16:18:50 +0200
commitad25e3afcf50097366d40b38fc9bea3ea5408433 (patch)
tree8e12653b2a80ddf8ad498b9158c5fb09f64219f4 /src
parent72db110754846df1531e599b8ead000fe311513a (diff)
added lcd driver
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/sm510/sm510.c58
-rw-r--r--src/emu/cpu/sm510/sm510.h60
-rw-r--r--src/emu/cpu/sm510/sm510core.c3
-rw-r--r--src/emu/cpu/sm510/sm511core.c7
4 files changed, 106 insertions, 22 deletions
diff --git a/src/emu/cpu/sm510/sm510.c b/src/emu/cpu/sm510/sm510.c
index 7f0fe7900f2..c2c282b373f 100644
--- a/src/emu/cpu/sm510/sm510.c
+++ b/src/emu/cpu/sm510/sm510.c
@@ -12,6 +12,7 @@
TODO:
- proper support for LFSR program counter in debugger
+ - callback for lcd screen as MAME bitmap (when needed)
*/
@@ -36,9 +37,6 @@ void sm510_base_device::device_start()
m_prgmask = (1 << m_prgwidth) - 1;
m_datamask = (1 << m_datawidth) - 1;
- m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this));
- reset_divider();
-
// resolve callbacks
m_read_k.resolve_safe(0);
m_read_ba.resolve_safe(1);
@@ -46,6 +44,10 @@ void sm510_base_device::device_start()
m_write_s.resolve_safe();
m_write_r.resolve_safe();
+ m_write_sega.resolve_safe();
+ m_write_segb.resolve_safe();
+ m_write_segc.resolve_safe();
+
// zerofill
memset(m_stack, 0, sizeof(m_stack));
m_pc = 0;
@@ -59,7 +61,7 @@ void sm510_base_device::device_start()
m_c = 0;
m_skip = false;
m_w = 0;
-// m_div = 0;
+ m_div = 0;
m_1s = false;
m_k_active = false;
m_bp = false;
@@ -98,6 +100,9 @@ void sm510_base_device::device_start()
state_add(STATE_GENFLAGS, "GENFLAGS", m_c).formatstr("%1s").noshow();
m_icountptr = &m_icount;
+
+ init_divider();
+ init_lcd_driver();
}
@@ -125,6 +130,45 @@ void sm510_base_device::device_reset()
//-------------------------------------------------
+// lcd driver
+//-------------------------------------------------
+
+inline UINT16 sm510_base_device::get_lcd_row(int column, UINT8* ram)
+{
+ // output 0 if lcd blackpate/bleeder is off, or in case row doesn't exist
+ if (ram == NULL || m_bc || !m_bp)
+ return 0;
+
+ UINT16 rowdata = 0;
+ for (int i = 0; i < 0x10; i++)
+ rowdata |= (ram[i] >> column & 1) << i;
+
+ return rowdata;
+}
+
+TIMER_CALLBACK_MEMBER(sm510_base_device::lcd_timer_cb)
+{
+ // 4 columns, 16 segments per row
+ for (int h = 0; h < 4; h++)
+ {
+ m_write_sega(h | SM510_PORT_SEGA, get_lcd_row(h, m_lcd_ram_a), 0xffff);
+ m_write_segb(h | SM510_PORT_SEGB, get_lcd_row(h, m_lcd_ram_b), 0xffff);
+ m_write_segc(h | SM510_PORT_SEGC, get_lcd_row(h, m_lcd_ram_c), 0xffff);
+ }
+
+ // schedule next timeout
+ m_lcd_timer->adjust(attotime::from_ticks(0x200, unscaled_clock()));
+}
+
+void sm510_base_device::init_lcd_driver()
+{
+ m_lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::lcd_timer_cb), this));
+ m_lcd_timer->adjust(attotime::from_ticks(0x200, unscaled_clock())); // 64hz default
+}
+
+
+
+//-------------------------------------------------
// interrupt/timer
//-------------------------------------------------
@@ -175,6 +219,12 @@ void sm510_base_device::reset_divider()
m_div_timer->adjust(attotime::from_ticks(0x800, unscaled_clock()));
}
+void sm510_base_device::init_divider()
+{
+ m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this));
+ reset_divider();
+}
+
//-------------------------------------------------
diff --git a/src/emu/cpu/sm510/sm510.h b/src/emu/cpu/sm510/sm510.h
index 30f6a837364..1428e22d823 100644
--- a/src/emu/cpu/sm510/sm510.h
+++ b/src/emu/cpu/sm510/sm510.h
@@ -17,6 +17,9 @@
// 4-bit K input port (pull-down)
#define MCFG_SM510_READ_K_CB(_devcb) \
sm510_base_device::set_read_k_callback(*device, DEVCB_##_devcb);
+// when in halt state, any K input going High can wake up the CPU,
+// driver is required to use execute_set_input(SM510_INPUT_LINE_K, state)
+#define SM510_INPUT_LINE_K 0
// 1-bit BA input pin (pull-up)
#define MCFG_SM510_READ_BA_CB(_devcb) \
@@ -34,9 +37,20 @@
#define MCFG_SM510_WRITE_R_CB(_devcb) \
sm510_base_device::set_write_r_callback(*device, DEVCB_##_devcb);
-// when in halt state, any K input going High can wake up the CPU,
-// driver is required to use execute_set_input(SM510_INPUT_LINE_K, state)
-#define SM510_INPUT_LINE_K 0
+// LCD segment outputs: H1-4 as offset(low), a/b/c 1-16 as data d0-d15
+#define MCFG_SM510_WRITE_SEGA_CB(_devcb) \
+ sm510_base_device::set_write_sega_callback(*device, DEVCB_##_devcb);
+#define MCFG_SM510_WRITE_SEGB_CB(_devcb) \
+ sm510_base_device::set_write_segb_callback(*device, DEVCB_##_devcb);
+#define MCFG_SM510_WRITE_SEGC_CB(_devcb) \
+ sm510_base_device::set_write_segc_callback(*device, DEVCB_##_devcb);
+
+enum
+{
+ SM510_PORT_SEGA = 0x10,
+ SM510_PORT_SEGB = 0x20,
+ SM510_PORT_SEGC = 0x30
+};
// pinout reference
@@ -53,13 +67,13 @@ public:
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
, m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program)
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
- , m_lcd_ram(*this, "lcd_ram")
, m_prgwidth(prgwidth)
, m_datawidth(datawidth)
, m_stack_levels(stack_levels)
+ , 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_sega(*this), m_write_segb(*this), m_write_segc(*this)
, m_read_k(*this)
- , m_read_ba(*this)
- , m_read_b(*this)
+ , m_read_ba(*this), m_read_b(*this)
, m_write_s(*this)
, m_write_r(*this)
{ }
@@ -71,6 +85,10 @@ public:
template<class _Object> static devcb_base &set_write_s_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_write_s.set_callback(object); }
template<class _Object> static devcb_base &set_write_r_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_write_r.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_sega_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_write_sega.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_segb_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_write_segb.set_callback(object); }
+ template<class _Object> static devcb_base &set_write_segc_callback(device_t &device, _Object object) { return downcast<sm510_base_device &>(device).m_write_segc.set_callback(object); }
+
protected:
// device-level overrides
virtual void device_start();
@@ -97,7 +115,6 @@ protected:
address_space_config m_data_config;
address_space *m_program;
address_space *m_data;
- required_shared_ptr<UINT8> m_lcd_ram;
int m_prgwidth;
int m_datawidth;
@@ -110,7 +127,6 @@ protected:
int m_stack_levels;
UINT16 m_stack[2];
int m_icount;
- emu_timer *m_div_timer;
UINT8 m_acc;
UINT8 m_bl;
@@ -118,14 +134,31 @@ protected:
UINT8 m_c;
bool m_skip;
UINT8 m_w;
- UINT16 m_div;
- bool m_1s;
bool m_k_active;
+ bool m_halt;
+
+ // lcd driver
+ optional_shared_ptr<UINT8> m_lcd_ram_a, m_lcd_ram_b, m_lcd_ram_c;
+ devcb_write16 m_write_sega, m_write_segb, m_write_segc;
+ emu_timer *m_lcd_timer;
bool m_bp;
bool m_bc;
- bool m_halt;
- // i/o handlers
+ UINT16 get_lcd_row(int column, UINT8* ram);
+ TIMER_CALLBACK_MEMBER(lcd_timer_cb);
+ virtual void init_lcd_driver();
+
+ // clock divider
+ emu_timer *m_div_timer;
+ UINT16 m_div;
+ bool m_1s;
+
+ TIMER_CALLBACK_MEMBER(div_timer_cb);
+ void wake_me_up();
+ virtual void reset_divider();
+ void init_divider();
+
+ // other i/o handlers
devcb_read8 m_read_k;
devcb_read_line m_read_ba;
devcb_read_line m_read_b;
@@ -134,9 +167,6 @@ protected:
// misc internal helpers
void increment_pc();
- TIMER_CALLBACK_MEMBER(div_timer_cb);
- void wake_me_up();
- virtual void reset_divider();
virtual void get_opcode_param() { } // -> child class
UINT8 ram_r();
diff --git a/src/emu/cpu/sm510/sm510core.c b/src/emu/cpu/sm510/sm510core.c
index fe25e9abdbd..0ac9d7d3caf 100644
--- a/src/emu/cpu/sm510/sm510core.c
+++ b/src/emu/cpu/sm510/sm510core.c
@@ -24,7 +24,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(data_96_32x4, AS_DATA, 8, sm510_base_device)
AM_RANGE(0x00, 0x5f) AM_RAM
- AM_RANGE(0x60, 0x7f) AM_RAM AM_SHARE("lcd_ram")
+ AM_RANGE(0x60, 0x6f) AM_RAM AM_SHARE("lcd_ram_a")
+ AM_RANGE(0x70, 0x7f) AM_RAM AM_SHARE("lcd_ram_b")
ADDRESS_MAP_END
diff --git a/src/emu/cpu/sm510/sm511core.c b/src/emu/cpu/sm510/sm511core.c
index 8905b4c3239..11f6808e5a4 100644
--- a/src/emu/cpu/sm510/sm511core.c
+++ b/src/emu/cpu/sm510/sm511core.c
@@ -22,12 +22,15 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(data_96_32x4, AS_DATA, 8, sm510_base_device)
AM_RANGE(0x00, 0x5f) AM_RAM
- AM_RANGE(0x60, 0x7f) AM_RAM AM_SHARE("lcd_ram")
+ AM_RANGE(0x60, 0x6f) AM_RAM AM_SHARE("lcd_ram_a")
+ AM_RANGE(0x70, 0x7f) AM_RAM AM_SHARE("lcd_ram_b")
ADDRESS_MAP_END
static ADDRESS_MAP_START(data_80_48x4, AS_DATA, 8, sm510_base_device)
AM_RANGE(0x00, 0x4f) AM_RAM
- AM_RANGE(0x50, 0x7f) AM_RAM AM_SHARE("lcd_ram")
+ AM_RANGE(0x50, 0x5f) AM_RAM AM_SHARE("lcd_ram_c")
+ AM_RANGE(0x60, 0x6f) AM_RAM AM_SHARE("lcd_ram_a")
+ AM_RANGE(0x70, 0x7f) AM_RAM AM_SHARE("lcd_ram_b")
ADDRESS_MAP_END