f3853: Overhaul interface and replace custom interrupt generation callback with devcb3 (nw)

vidbrain.cpp: Remove old F3853 code in favor of device (nw)
This commit is contained in:
AJR 2018-08-12 23:36:26 -04:00
parent 9bc6e6f3cf
commit 210b0fa0c5
7 changed files with 83 additions and 211 deletions

View File

@ -39,9 +39,20 @@ DEFINE_DEVICE_TYPE(F3853, f3853_device, "f3853_device", "F3853 SMI")
f3853_device::f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, F3853, tag, owner, clock)
, m_int_req_callback(*this)
, m_pri_out_callback(*this)
, m_priority_line(false)
, m_external_interrupt_line(true)
{
}
void f3853_device::device_resolve_objects()
{
m_int_req_callback.resolve_safe();
m_pri_out_callback.resolve_safe(); // TODO: not implemented
m_int_daisy_chain_callback.bind_relative_to(*owner());
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -55,17 +66,14 @@ void f3853_device::device_start()
reg = reg << 1 | (BIT(reg,7) ^ BIT(reg,5) ^ BIT(reg,4) ^ BIT(reg,3) ^ 1);
}
m_interrupt_req_cb.bind_relative_to(*owner());
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(f3853_device::timer_callback),this));
save_item(NAME(m_high) );
save_item(NAME(m_low) );
save_item(NAME(m_external_enable) );
save_item(NAME(m_timer_enable) );
save_item(NAME(m_request_flipflop) );
save_item(NAME(m_priority_line) );
save_item(NAME(m_external_interrupt_line) );
save_item(NAME(m_int_vector));
save_item(NAME(m_external_enable));
save_item(NAME(m_timer_enable));
save_item(NAME(m_request_flipflop));
save_item(NAME(m_priority_line));
save_item(NAME(m_external_interrupt_line));
}
@ -75,13 +83,12 @@ void f3853_device::device_start()
void f3853_device::device_reset()
{
m_high = 0;
m_low = 0;
m_external_enable = 0;
m_timer_enable = 0;
m_request_flipflop = 0;
m_priority_line = false;
m_int_vector = 0;
m_external_enable = false;
m_timer_enable = false;
m_request_flipflop = false;
m_external_interrupt_line = true;
set_interrupt_request_line();
m_timer->enable(false);
}
@ -89,21 +96,32 @@ void f3853_device::device_reset()
void f3853_device::set_interrupt_request_line()
{
if (m_interrupt_req_cb.isnull())
return;
m_int_req_callback(m_request_flipflop && !m_priority_line ? ASSERT_LINE : CLEAR_LINE);
}
IRQ_CALLBACK_MEMBER(f3853_device::int_acknowledge)
{
if (m_external_enable && !m_priority_line && m_request_flipflop)
{
m_request_flipflop = false;
m_interrupt_req_cb(external_interrupt_vector(), true);
set_interrupt_request_line();
return external_interrupt_vector();
}
else if (m_timer_enable && !m_priority_line && m_request_flipflop)
{
m_request_flipflop = false;
m_interrupt_req_cb(timer_interrupt_vector(), true);
set_interrupt_request_line();
return timer_interrupt_vector();
}
else if (!m_int_daisy_chain_callback.isnull())
return m_int_daisy_chain_callback(device, irqline);
else
m_interrupt_req_cb(0, false);
{
// should never happen
logerror("%s: Spurious interrupt!\n", machine().describe_context());
return 0;
}
}
@ -124,19 +142,19 @@ TIMER_CALLBACK_MEMBER(f3853_device::timer_callback)
timer_start(0xfe);
}
void f3853_device::set_external_interrupt_in_line(int level)
WRITE_LINE_MEMBER(f3853_device::ext_int_w)
{
if(m_external_interrupt_line && !level && m_external_enable)
if(m_external_interrupt_line && !state && m_external_enable)
{
m_request_flipflop = true;
}
m_external_interrupt_line = level;
m_external_interrupt_line = bool(state);
set_interrupt_request_line();
}
void f3853_device::set_priority_in_line(int level)
WRITE_LINE_MEMBER(f3853_device::pri_in_w)
{
m_priority_line = level;
m_priority_line = bool(state);
set_interrupt_request_line();
}
@ -148,11 +166,11 @@ READ8_MEMBER(f3853_device::read)
switch (offset)
{
case 0:
data = m_high;
data = m_int_vector >> 8;
break;
case 1:
data = m_low;
data = m_int_vector & 0xff;
break;
case 2: // Interrupt control; not readable
@ -169,11 +187,11 @@ WRITE8_MEMBER(f3853_device::write)
switch(offset)
{
case 0:
m_high = data;
m_int_vector = (data << 8) | (m_int_vector & 0x00ff);
break;
case 1:
m_low = data;
m_int_vector = data | (m_int_vector & 0xff00);
break;
case 2: //interrupt control

View File

@ -39,65 +39,57 @@
#pragma once
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_F3853_EXT_INPUT_CB(_class, _method) \
downcast<f3853_device &>(*device).set_interrupt_req_callback(f3853_device::interrupt_req_delegate(&_class::_method, #_class "::" #_method, this));
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
#define F3853_INTERRUPT_REQ_CB(_name) void _name(uint16_t addr, int level)
// ======================> f3853_device
class f3853_device : public device_t
class f3853_device : public device_t
{
public:
typedef device_delegate<void (uint16_t addr, int level)> interrupt_req_delegate;
// construction/destruction
f3853_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <typename Object> void set_interrupt_req_callback(Object &&cb) { m_interrupt_req_cb = std::forward<Object>(cb); }
auto int_req_callback() { return m_int_req_callback.bind(); }
auto pri_out_callback() { return m_pri_out_callback.bind(); }
template<typename Object> void set_int_daisy_chain_callback(Object &&cb) { m_int_daisy_chain_callback = std::forward<Object>(cb); }
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
void set_external_interrupt_in_line(int level);
void set_priority_in_line(int level);
DECLARE_WRITE_LINE_MEMBER(ext_int_w);
DECLARE_WRITE_LINE_MEMBER(pri_in_w);
TIMER_CALLBACK_MEMBER(timer_callback);
IRQ_CALLBACK_MEMBER(int_acknowledge);
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_post_load() override { }
virtual void device_clock_changed() override { }
private:
uint16_t interrupt_vector() const { return m_low | (uint16_t(m_high) << 8); }
uint16_t timer_interrupt_vector() const { return interrupt_vector() & ~uint16_t(0x0080); }
uint16_t external_interrupt_vector() const { return interrupt_vector() | uint16_t(0x0080); }
uint16_t timer_interrupt_vector() const { return m_int_vector & ~uint16_t(0x0080); }
uint16_t external_interrupt_vector() const { return m_int_vector | uint16_t(0x0080); }
void set_interrupt_request_line();
void timer_start(uint8_t value);
interrupt_req_delegate m_interrupt_req_cb;
uint8_t m_high;
uint8_t m_low; // Bit 7 is set to 0 for timer interrupts, 1 for external interrupts
int32_t m_external_enable;
int32_t m_timer_enable;
devcb_write_line m_int_req_callback;
devcb_write_line m_pri_out_callback;
device_irq_acknowledge_delegate m_int_daisy_chain_callback;
int32_t m_request_flipflop;
uint16_t m_int_vector; // Bit 7 is set to 0 for timer interrupts, 1 for external interrupts
bool m_external_enable;
bool m_timer_enable;
int32_t m_priority_line; /* inverted level*/
int32_t m_external_interrupt_line; /* inverted level */
bool m_request_flipflop;
bool m_priority_line; /* inverted level*/
bool m_external_interrupt_line; /* inverted level */
emu_timer *m_timer;

View File

@ -45,7 +45,6 @@ private:
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
F3853_INTERRUPT_REQ_CB(f3853_interrupt);
DECLARE_WRITE_LINE_MEMBER(vblank_w);
DECLARE_READ8_MEMBER(bell_r);
@ -167,11 +166,6 @@ u32 microterm_f8_state::screen_update(screen_device &screen, bitmap_rgb32 &bitma
return 0;
}
F3853_INTERRUPT_REQ_CB(microterm_f8_state::f3853_interrupt)
{
m_maincpu->set_input_line_and_vector(F8_INPUT_LINE_INT_REQ, level ? ASSERT_LINE : CLEAR_LINE, addr);
}
WRITE_LINE_MEMBER(microterm_f8_state::vblank_w)
{
if (state)
@ -491,14 +485,15 @@ void microterm_f8_state::act5a(machine_config &config)
cpu_device &maincpu(F8(config, "maincpu", 2_MHz_XTAL));
maincpu.set_addrmap(AS_PROGRAM, &microterm_f8_state::f8_mem);
maincpu.set_addrmap(AS_IO, &microterm_f8_state::f8_io);
maincpu.set_irq_acknowledge_callback("smi", FUNC(f3853_device::int_acknowledge));
f3853_device &smi(F3853(config, "smi", 2_MHz_XTAL));
smi.set_interrupt_req_callback(f3853_device::interrupt_req_delegate(FUNC(microterm_f8_state::f3853_interrupt), this));
smi.int_req_callback().set_inputline("maincpu", F8_INPUT_LINE_INT_REQ);
AY51013(config, m_uart);
m_uart->read_si_callback().set(m_io, FUNC(rs232_port_device::rxd_r));
m_uart->write_so_callback().set("txd", FUNC(input_merger_device::in_w<0>));
m_uart->write_dav_callback().set("smi", FUNC(f3853_device::set_external_interrupt_in_line)).invert();
m_uart->write_dav_callback().set("smi", FUNC(f3853_device::ext_int_w)).invert();
m_uart->set_auto_rdav(true);
RS232_PORT(config, m_io, default_rs232_devices, nullptr);

View File

@ -64,7 +64,6 @@ private:
DECLARE_READ8_MEMBER(mk1_f8_r);
DECLARE_WRITE8_MEMBER(mk1_f8_w);
TIMER_DEVICE_CALLBACK_MEMBER(mk1_update_leds);
F3853_INTERRUPT_REQ_CB(mk1_interrupt);
void mk1_io(address_map &map);
void mk1_mem(address_map &map);
@ -185,22 +184,16 @@ void mk1_state::machine_start()
}
F3853_INTERRUPT_REQ_CB(mk1_state::mk1_interrupt)
{
m_maincpu->set_input_line_vector(F8_INPUT_LINE_INT_REQ, addr);
m_maincpu->set_input_line(F8_INPUT_LINE_INT_REQ, level ? ASSERT_LINE : CLEAR_LINE);
}
MACHINE_CONFIG_START(mk1_state::mk1)
/* basic machine hardware */
MCFG_DEVICE_ADD( "maincpu", F8, MAIN_CLOCK ) /* MK3850 */
MCFG_DEVICE_PROGRAM_MAP(mk1_mem)
MCFG_DEVICE_IO_MAP(mk1_io)
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE("f3853", f3853_device, int_acknowledge)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_DEVICE_ADD("f3853", F3853, MAIN_CLOCK)
MCFG_F3853_EXT_INPUT_CB(mk1_state, mk1_interrupt)
f3853_device &f3853(F3853(config, "f3853", MAIN_CLOCK));
f3853.int_req_callback().set_inputline("maincpu", F8_INPUT_LINE_INT_REQ);
/* video hardware */
config.set_default_layout(layout_mk1);

View File

@ -42,7 +42,6 @@ public:
private:
u8 m_io[2]; // F8 CPU I/O ports
F3853_INTERRUPT_REQ_CB(f3853_interrupt);
// Delta-1
DECLARE_WRITE8_MEMBER(delta1_io0_w);
@ -186,21 +185,16 @@ INPUT_PORTS_END
Machine Drivers
******************************************************************************/
F3853_INTERRUPT_REQ_CB(novagf8_state::f3853_interrupt)
{
m_maincpu->set_input_line_vector(F8_INPUT_LINE_INT_REQ, addr);
m_maincpu->set_input_line(F8_INPUT_LINE_INT_REQ, level ? ASSERT_LINE : CLEAR_LINE);
}
MACHINE_CONFIG_START(novagf8_state::delta1)
/* basic machine hardware */
MCFG_DEVICE_ADD("maincpu", F8, 2000000) // LC circuit, measured 2MHz
MCFG_DEVICE_PROGRAM_MAP(delta1_map)
MCFG_DEVICE_IO_MAP(delta1_io)
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE("f3853", f3853_device, int_acknowledge)
MCFG_DEVICE_ADD("f3853", F3853, 2000000)
MCFG_F3853_EXT_INPUT_CB(novagf8_state, f3853_interrupt)
f3853_device &f3853(F3853(config, "f3853", 2000000));
f3853.int_req_callback().set_inputline("maincpu", F8_INPUT_LINE_INT_REQ);
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", novagbase_state, display_decay_tick, attotime::from_msec(1))
config.set_default_layout(layout_novag_delta1);

View File

@ -158,65 +158,6 @@ WRITE8_MEMBER( vidbrain_state::sound_w )
}
//-------------------------------------------------
// interrupt_check - check interrupts
//-------------------------------------------------
void vidbrain_state::interrupt_check()
{
int interrupt = CLEAR_LINE;
switch (m_int_enable)
{
case 1:
if (m_ext_int_latch) interrupt = ASSERT_LINE;
break;
case 3:
if (m_timer_int_latch) interrupt = ASSERT_LINE;
break;
}
m_maincpu->set_input_line(F8_INPUT_LINE_INT_REQ, interrupt);
}
//-------------------------------------------------
// f3853_w - F3853 SMI write
//-------------------------------------------------
WRITE8_MEMBER( vidbrain_state::f3853_w )
{
switch (offset)
{
case 0:
// interrupt vector address high
m_vector = (data << 8) | (m_vector & 0xff);
logerror("%s: F3853 Interrupt Vector %04x\n", machine().describe_context(), m_vector);
break;
case 1:
// interrupt vector address low
m_vector = (m_vector & 0xff00) | data;
logerror("%s: F3853 Interrupt Vector %04x\n", machine().describe_context(), m_vector);
break;
case 2:
// interrupt control
m_int_enable = data & 0x03;
logerror("%s: F3853 Interrupt Control %u\n", machine().describe_context(), m_int_enable);
interrupt_check();
if (m_int_enable == 0x03) logerror("F3853 Timer not supported!\n");
break;
case 3:
// timer 8-bit polynomial counter
logerror("%s: F3853 Timer not supported!\n", machine().describe_context());
}
}
//**************************************************************************
// ADDRESS MAPS
@ -247,8 +188,7 @@ void vidbrain_state::vidbrain_io(address_map &map)
{
map(0x00, 0x00).w(FUNC(vidbrain_state::keyboard_w));
map(0x01, 0x01).rw(FUNC(vidbrain_state::keyboard_r), FUNC(vidbrain_state::sound_w));
map(0x0c, 0x0f).w(FUNC(vidbrain_state::f3853_w));
// AM_RANGE(0x0c, 0x0f) AM_DEVREADWRITE(F3853_TAG, f3853_device, read, write)
map(0x0c, 0x0f).rw(F3853_TAG, FUNC(f3853_device::read), FUNC(f3853_device::write));
}
@ -366,16 +306,6 @@ INPUT_PORTS_END
// DEVICE CONFIGURATION
//**************************************************************************
//-------------------------------------------------
// f3853 interrupt request callback
//-------------------------------------------------
F3853_INTERRUPT_REQ_CB(vidbrain_state::f3853_int_req_w)
{
m_vector = addr;
m_maincpu->set_input_line(F8_INPUT_LINE_INT_REQ, level);
}
//-------------------------------------------------
// UV201_INTERFACE( uv_intf )
//-------------------------------------------------
@ -384,8 +314,7 @@ WRITE_LINE_MEMBER( vidbrain_state::ext_int_w )
{
if (state)
{
m_ext_int_latch = state;
interrupt_check();
m_smi->ext_int_w(0);
}
}
@ -426,33 +355,6 @@ READ8_MEMBER(vidbrain_state::memory_read_byte)
// MACHINE INITIALIZATION
//**************************************************************************
//-------------------------------------------------
// IRQ_CALLBACK_MEMBER(vidbrain_int_ack)
//-------------------------------------------------
IRQ_CALLBACK_MEMBER(vidbrain_state::vidbrain_int_ack)
{
uint16_t vector = m_vector;
switch (m_int_enable)
{
case 1:
vector |= 0x80;
m_ext_int_latch = 0;
break;
case 3:
vector &= ~0x80;
m_timer_int_latch = 0;
break;
}
interrupt_check();
return vector;
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
@ -460,9 +362,7 @@ IRQ_CALLBACK_MEMBER(vidbrain_state::vidbrain_int_ack)
void vidbrain_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_uv->ext_int_w(0);
m_ext_int_latch = 1;
interrupt_check();
m_smi->ext_int_w(1);
}
@ -476,10 +376,6 @@ void vidbrain_state::machine_start()
m_timer_ne555 = timer_alloc(TIMER_JOYSTICK);
// register for state saving
save_item(NAME(m_vector));
save_item(NAME(m_int_enable));
save_item(NAME(m_ext_int_latch));
save_item(NAME(m_timer_int_latch));
save_item(NAME(m_keylatch));
save_item(NAME(m_joy_enable));
save_item(NAME(m_sound_clk));
@ -488,9 +384,6 @@ void vidbrain_state::machine_start()
void vidbrain_state::machine_reset()
{
m_int_enable = 0;
m_ext_int_latch = 0;
m_timer_int_latch = 0;
}
@ -507,7 +400,7 @@ MACHINE_CONFIG_START(vidbrain_state::vidbrain)
MCFG_DEVICE_ADD(F3850_TAG, F8, XTAL(4'000'000)/2)
MCFG_DEVICE_PROGRAM_MAP(vidbrain_mem)
MCFG_DEVICE_IO_MAP(vidbrain_io)
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DRIVER(vidbrain_state,vidbrain_int_ack)
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE(F3853_TAG, f3853_device, int_acknowledge)
// video hardware
config.set_default_layout(layout_vidbrain);
@ -528,8 +421,8 @@ MACHINE_CONFIG_START(vidbrain_state::vidbrain)
MCFG_SOUND_ROUTE(0, "dac", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE(0, "dac", -1.0, DAC_VREF_NEG_INPUT)
// devices
MCFG_DEVICE_ADD(F3853_TAG, F3853, XTAL(4'000'000)/2)
MCFG_F3853_EXT_INPUT_CB(vidbrain_state, f3853_int_req_w)
F3853(config, m_smi, XTAL(4'000'000)/2);
m_smi->int_req_callback().set_inputline(F3850_TAG, F8_INPUT_LINE_INT_REQ);
// cartridge
MCFG_VIDEOBRAIN_EXPANSION_SLOT_ADD(VIDEOBRAIN_EXPANSION_SLOT_TAG, vidbrain_expansion_cards, nullptr)

View File

@ -76,24 +76,11 @@ private:
DECLARE_WRITE8_MEMBER( keyboard_w );
DECLARE_READ8_MEMBER( keyboard_r );
DECLARE_WRITE8_MEMBER( sound_w );
DECLARE_WRITE8_MEMBER( f3853_w );
DECLARE_WRITE_LINE_MEMBER( ext_int_w );
DECLARE_WRITE_LINE_MEMBER( hblank_w );
DECLARE_READ8_MEMBER(memory_read_byte);
F3853_INTERRUPT_REQ_CB(f3853_int_req_w);
IRQ_CALLBACK_MEMBER(vidbrain_int_ack);
void interrupt_check();
// F3853 SMI state
uint16_t m_vector;
int m_int_enable;
int m_ext_int_latch;
int m_timer_int_latch;
// keyboard state
uint8_t m_keylatch;
int m_joy_enable;