mirror of
https://github.com/holub/mame
synced 2025-07-02 00:29:37 +03:00
added lcd driver
This commit is contained in:
parent
72db110754
commit
ad25e3afcf
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- proper support for LFSR program counter in debugger
|
- proper support for LFSR program counter in debugger
|
||||||
|
- callback for lcd screen as MAME bitmap (when needed)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -36,9 +37,6 @@ void sm510_base_device::device_start()
|
|||||||
m_prgmask = (1 << m_prgwidth) - 1;
|
m_prgmask = (1 << m_prgwidth) - 1;
|
||||||
m_datamask = (1 << m_datawidth) - 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
|
// resolve callbacks
|
||||||
m_read_k.resolve_safe(0);
|
m_read_k.resolve_safe(0);
|
||||||
m_read_ba.resolve_safe(1);
|
m_read_ba.resolve_safe(1);
|
||||||
@ -46,6 +44,10 @@ void sm510_base_device::device_start()
|
|||||||
m_write_s.resolve_safe();
|
m_write_s.resolve_safe();
|
||||||
m_write_r.resolve_safe();
|
m_write_r.resolve_safe();
|
||||||
|
|
||||||
|
m_write_sega.resolve_safe();
|
||||||
|
m_write_segb.resolve_safe();
|
||||||
|
m_write_segc.resolve_safe();
|
||||||
|
|
||||||
// zerofill
|
// zerofill
|
||||||
memset(m_stack, 0, sizeof(m_stack));
|
memset(m_stack, 0, sizeof(m_stack));
|
||||||
m_pc = 0;
|
m_pc = 0;
|
||||||
@ -59,7 +61,7 @@ void sm510_base_device::device_start()
|
|||||||
m_c = 0;
|
m_c = 0;
|
||||||
m_skip = false;
|
m_skip = false;
|
||||||
m_w = 0;
|
m_w = 0;
|
||||||
// m_div = 0;
|
m_div = 0;
|
||||||
m_1s = false;
|
m_1s = false;
|
||||||
m_k_active = false;
|
m_k_active = false;
|
||||||
m_bp = false;
|
m_bp = false;
|
||||||
@ -98,6 +100,9 @@ void sm510_base_device::device_start()
|
|||||||
state_add(STATE_GENFLAGS, "GENFLAGS", m_c).formatstr("%1s").noshow();
|
state_add(STATE_GENFLAGS, "GENFLAGS", m_c).formatstr("%1s").noshow();
|
||||||
|
|
||||||
m_icountptr = &m_icount;
|
m_icountptr = &m_icount;
|
||||||
|
|
||||||
|
init_divider();
|
||||||
|
init_lcd_driver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,6 +129,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
|
// interrupt/timer
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -175,6 +219,12 @@ void sm510_base_device::reset_divider()
|
|||||||
m_div_timer->adjust(attotime::from_ticks(0x800, unscaled_clock()));
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
// 4-bit K input port (pull-down)
|
// 4-bit K input port (pull-down)
|
||||||
#define MCFG_SM510_READ_K_CB(_devcb) \
|
#define MCFG_SM510_READ_K_CB(_devcb) \
|
||||||
sm510_base_device::set_read_k_callback(*device, DEVCB_##_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)
|
// 1-bit BA input pin (pull-up)
|
||||||
#define MCFG_SM510_READ_BA_CB(_devcb) \
|
#define MCFG_SM510_READ_BA_CB(_devcb) \
|
||||||
@ -34,9 +37,20 @@
|
|||||||
#define MCFG_SM510_WRITE_R_CB(_devcb) \
|
#define MCFG_SM510_WRITE_R_CB(_devcb) \
|
||||||
sm510_base_device::set_write_r_callback(*device, DEVCB_##_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,
|
// LCD segment outputs: H1-4 as offset(low), a/b/c 1-16 as data d0-d15
|
||||||
// driver is required to use execute_set_input(SM510_INPUT_LINE_K, state)
|
#define MCFG_SM510_WRITE_SEGA_CB(_devcb) \
|
||||||
#define SM510_INPUT_LINE_K 0
|
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
|
// pinout reference
|
||||||
@ -53,13 +67,13 @@ public:
|
|||||||
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
|
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program)
|
, m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program)
|
||||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
|
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
|
||||||
, m_lcd_ram(*this, "lcd_ram")
|
|
||||||
, m_prgwidth(prgwidth)
|
, m_prgwidth(prgwidth)
|
||||||
, m_datawidth(datawidth)
|
, m_datawidth(datawidth)
|
||||||
, m_stack_levels(stack_levels)
|
, 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_k(*this)
|
||||||
, m_read_ba(*this)
|
, m_read_ba(*this), m_read_b(*this)
|
||||||
, m_read_b(*this)
|
|
||||||
, m_write_s(*this)
|
, m_write_s(*this)
|
||||||
, m_write_r(*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_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_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:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_start();
|
virtual void device_start();
|
||||||
@ -97,7 +115,6 @@ protected:
|
|||||||
address_space_config m_data_config;
|
address_space_config m_data_config;
|
||||||
address_space *m_program;
|
address_space *m_program;
|
||||||
address_space *m_data;
|
address_space *m_data;
|
||||||
required_shared_ptr<UINT8> m_lcd_ram;
|
|
||||||
|
|
||||||
int m_prgwidth;
|
int m_prgwidth;
|
||||||
int m_datawidth;
|
int m_datawidth;
|
||||||
@ -110,7 +127,6 @@ protected:
|
|||||||
int m_stack_levels;
|
int m_stack_levels;
|
||||||
UINT16 m_stack[2];
|
UINT16 m_stack[2];
|
||||||
int m_icount;
|
int m_icount;
|
||||||
emu_timer *m_div_timer;
|
|
||||||
|
|
||||||
UINT8 m_acc;
|
UINT8 m_acc;
|
||||||
UINT8 m_bl;
|
UINT8 m_bl;
|
||||||
@ -118,14 +134,31 @@ protected:
|
|||||||
UINT8 m_c;
|
UINT8 m_c;
|
||||||
bool m_skip;
|
bool m_skip;
|
||||||
UINT8 m_w;
|
UINT8 m_w;
|
||||||
UINT16 m_div;
|
|
||||||
bool m_1s;
|
|
||||||
bool m_k_active;
|
bool m_k_active;
|
||||||
bool m_bp;
|
|
||||||
bool m_bc;
|
|
||||||
bool m_halt;
|
bool m_halt;
|
||||||
|
|
||||||
// i/o handlers
|
// 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;
|
||||||
|
|
||||||
|
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_read8 m_read_k;
|
||||||
devcb_read_line m_read_ba;
|
devcb_read_line m_read_ba;
|
||||||
devcb_read_line m_read_b;
|
devcb_read_line m_read_b;
|
||||||
@ -134,9 +167,6 @@ protected:
|
|||||||
|
|
||||||
// misc internal helpers
|
// misc internal helpers
|
||||||
void increment_pc();
|
void increment_pc();
|
||||||
TIMER_CALLBACK_MEMBER(div_timer_cb);
|
|
||||||
void wake_me_up();
|
|
||||||
virtual void reset_divider();
|
|
||||||
virtual void get_opcode_param() { } // -> child class
|
virtual void get_opcode_param() { } // -> child class
|
||||||
|
|
||||||
UINT8 ram_r();
|
UINT8 ram_r();
|
||||||
|
@ -24,7 +24,8 @@ ADDRESS_MAP_END
|
|||||||
|
|
||||||
static ADDRESS_MAP_START(data_96_32x4, AS_DATA, 8, sm510_base_device)
|
static ADDRESS_MAP_START(data_96_32x4, AS_DATA, 8, sm510_base_device)
|
||||||
AM_RANGE(0x00, 0x5f) AM_RAM
|
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
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,12 +22,15 @@ ADDRESS_MAP_END
|
|||||||
|
|
||||||
static ADDRESS_MAP_START(data_96_32x4, AS_DATA, 8, sm510_base_device)
|
static ADDRESS_MAP_START(data_96_32x4, AS_DATA, 8, sm510_base_device)
|
||||||
AM_RANGE(0x00, 0x5f) AM_RAM
|
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
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
static ADDRESS_MAP_START(data_80_48x4, AS_DATA, 8, sm510_base_device)
|
static ADDRESS_MAP_START(data_80_48x4, AS_DATA, 8, sm510_base_device)
|
||||||
AM_RANGE(0x00, 0x4f) AM_RAM
|
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
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user