mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
added lcd driver
This commit is contained in:
parent
72db110754
commit
ad25e3afcf
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
//-------------------------------------------------
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
|
@ -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_bp;
|
||||
bool m_bc;
|
||||
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_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();
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user