(nw) fp1100: improved handshaking between cpus

upd7801: fixed problem with first INTF2 being ignored.
This commit is contained in:
Robbbert 2019-10-17 23:39:44 +11:00
parent db318046c4
commit 17d174d812
2 changed files with 81 additions and 39 deletions

View File

@ -2005,19 +2005,19 @@ void upd7801_device::execute_set_input(int irqline, int state)
/* Check if the ES bit is set then check for rising edge, otherwise falling edge */
if ( MKL & 0x20 )
{
if ( m_int2 == CLEAR_LINE && state == ASSERT_LINE )
if ( m_int2 != CLEAR_LINE && state == ASSERT_LINE )
{
IRR |= INTF2;
}
}
else
{
if ( m_int2 == ASSERT_LINE && state == CLEAR_LINE )
if ( m_int2 != ASSERT_LINE && state == CLEAR_LINE )
{
IRR |= INTF2;
}
}
m_int2 = state;
m_int2 = !state;
break;
}
}

View File

@ -23,10 +23,7 @@
The keyboard is a separate unit. It contains a beeper.
TODO:
- irq sources and communications; subcpu never enables its interrupts.
- unimplemented instruction PER triggered (can be ignored)
- Most of this code is guesswork, because although schematics exist,
they are too blurry to read.
- Display can be interlaced or non-interlaced. Interlaced not emulated.
- Cassette Load is quite complex, using 6 pins of the sub-cpu. Not done.
- subcpu is supposed to be in WAIT except in horizontal blanking period.
@ -100,10 +97,11 @@ private:
void io_map(address_map &map);
void main_map(address_map &map);
void sub_map(address_map &map);
void handle_int_to_main();
uint8_t m_irq_mask;
uint8_t m_main_latch;
uint8_t m_sub_latch;
uint8_t m_latch_main_to_sub;
uint8_t m_latch_sub_to_main;
uint8_t m_slot_num;
uint8_t m_kbd_row;
uint8_t m_col_border;
@ -111,6 +109,8 @@ private:
uint8_t m_col_display;
uint8_t m_centronics_busy;
uint8_t m_cass_data[4];
bool m_main_irq_status;
bool m_sub_irq_status;
bool m_cassbit;
bool m_cassold;
@ -183,27 +183,40 @@ WRITE8_MEMBER( fp1100_state::main_bank_w )
m_slot_num = (m_slot_num & 3) | ((data & 1) << 2); //??
}
// tell sub that latch has a byte
WRITE8_MEMBER( fp1100_state::irq_mask_w )
{
machine().scheduler().synchronize(); // force resync
m_irq_mask = data;
if (BIT(data, 7))
handle_int_to_main();
if (BIT(data, 7) && !m_sub_irq_status)
{
m_subcpu->set_input_line(UPD7810_INTF2, ASSERT_LINE);
LOG("%s: Sub IRQ asserted\n",machine().describe_context());
m_sub_irq_status = true;
}
else
if (!BIT(data, 7) && m_sub_irq_status)
{
m_subcpu->set_input_line(UPD7810_INTF2, CLEAR_LINE);
LOG("%s: Sub IRQ cleared\n",machine().describe_context());
m_sub_irq_status = false;
}
LOG("%s: IRQmask=%X\n",machine().describe_context(),data);
}
// send byte from main to latch
WRITE8_MEMBER( fp1100_state::main_to_sub_w )
{
m_sub_latch = data;
LOG("%s: From main:%X\n",machine().describe_context(),data);
// m_subcpu->set_input_line(UPD7810_INTF2, ASSERT_LINE);
m_latch_main_to_sub = data;
}
READ8_MEMBER( fp1100_state::sub_to_main_r )
{
m_maincpu->set_input_line(0, CLEAR_LINE);
LOG("%s: To main:%X\n",machine().describe_context(),m_main_latch);
return m_main_latch;
LOG("%s: To main:%X\n",machine().describe_context(),m_latch_sub_to_main);
return m_latch_sub_to_main;
}
WRITE8_MEMBER( fp1100_state::slot_bank_w )
@ -237,16 +250,15 @@ void fp1100_state::io_map(address_map &map)
READ8_MEMBER( fp1100_state::main_to_sub_r )
{
m_subcpu->set_input_line(UPD7810_INTF2, CLEAR_LINE);
LOG("%s: To sub:%X\n",machine().describe_context(),m_sub_latch);
return m_sub_latch;
LOG("%s: To sub:%X\n",machine().describe_context(),m_latch_main_to_sub);
return m_latch_main_to_sub;
}
// send byte from sub to latch
WRITE8_MEMBER( fp1100_state::sub_to_main_w )
{
m_main_latch = data;
m_latch_sub_to_main = data;
LOG("%s: From sub:%X\n",machine().describe_context(),data);
//m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xf0); // Z80
}
/*
@ -278,7 +290,7 @@ d6,7 - not used
*/
WRITE8_MEMBER( fp1100_state::kbd_row_w )
{
m_kbd_row = data & 15;
m_kbd_row = data;
m_beep->set_state(BIT(data, 4));
}
@ -290,7 +302,7 @@ void fp1100_state::sub_map(address_map &map)
map(0xe001, 0xe001).mirror(0x3fe).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xe400, 0xe7ff).portr("DSW").w(FUNC(fp1100_state::kbd_row_w));
map(0xe800, 0xebff).rw(FUNC(fp1100_state::main_to_sub_r), FUNC(fp1100_state::sub_to_main_w));
//map(0xec00, 0xefff) "Acknowledge of INT0" is coded in but isn't currently executed
map(0xec00, 0xefff).lw8("reset0", [this] (u8 data) { m_subcpu->set_input_line(UPD7810_INTF0, CLEAR_LINE); });
map(0xf000, 0xf3ff).w(FUNC(fp1100_state::colour_control_w));
map(0xf400, 0xff7f).rom().region("sub_ipl", 0x2400);
}
@ -314,9 +326,13 @@ WRITE8_MEMBER( fp1100_state::porta_w )
READ8_MEMBER( fp1100_state::portb_r )
{
uint8_t data = m_keyboard[m_kbd_row]->read() ^ 0xff;
//m_subcpu->set_input_line(UPD7810_INTF0, BIT(data, 7) ? HOLD_LINE : CLEAR_LINE);
return data;
u8 data = m_keyboard[m_kbd_row & 15]->read() ^ 0xff;
LOG("%s: PortB:%X:%X\n",machine().describe_context(),m_kbd_row,data);
//m_subcpu->set_input_line(UPD7810_INTF0, BIT(data, 7) ? ASSERT_LINE : CLEAR_LINE);
if (BIT(m_kbd_row, 5))
return data;
else
return 0;
}
/*
@ -339,20 +355,42 @@ d6 - Centronics strobe
WRITE8_MEMBER( fp1100_state::portc_w )
{
u8 bits = data ^ m_upd7801.portc;
m_upd7801.portc = data;
if (BIT(bits, 3))
if (BIT(m_irq_mask, 4))
if (!BIT(data, 3))
{
m_maincpu->set_input_line_and_vector(0, ASSERT_LINE, 0xf0); // Z80
LOG("%s: PortC:%X\n",machine().describe_context(),data);
}
{
LOG("%s: PortC:%X\n",machine().describe_context(),data);
handle_int_to_main();
}
if (BIT(bits, 5))
m_cass->change_state(BIT(data, 5) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
if (BIT(bits, 6))
m_centronics->write_strobe(BIT(data, 6));
m_upd7801.portc = data;
}
// HOLD_LINE used because the interrupt is set and cleared by successive instructions, too fast for the maincpu to notice
void fp1100_state::handle_int_to_main()
{
// IRQ is on if bit 4 of mask AND bit 3 portC
if (BIT(m_upd7801.portc, 3) && BIT(m_irq_mask, 4))
{
if (!m_main_irq_status)
{
m_maincpu->set_input_line(0, HOLD_LINE);
LOG("%s: Main IRQ asserted\n",machine().describe_context());
// m_main_irq_status = true;
}
}
else
{
if (m_main_irq_status)
{
// m_maincpu->set_input_line(0, CLEAR_LINE);
// LOG("%s: Main IRQ cleared\n",machine().describe_context());
m_main_irq_status = false;
}
}
}
/* Input ports */
static INPUT_PORTS_START( fp1100 )
@ -361,8 +399,9 @@ static INPUT_PORTS_START( fp1100 )
PORT_START("KEY.1")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break")
PORT_BIT(0x70, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_NAME("Caps")
PORT_BIT(0x60, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_NAME("Kanji") // guess, it's in Japanese
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_NAME("Caps")
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_NAME("Graph")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Ctrl")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1)
@ -478,13 +517,13 @@ static INPUT_PORTS_START( fp1100 )
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_NAME(":") PORT_CHAR(':') PORT_CHAR('*')
PORT_START("KEY.13")
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED) // Capslock LED on
PORT_START("KEY.14")
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED) // Kanji LED on
PORT_START("KEY.15")
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED) // LEDs off
PORT_START("DSW")
PORT_DIPNAME( 0x01, 0x01, "Text width" ) PORT_DIPLOCATION("SW1:1")
@ -595,6 +634,8 @@ INTERRUPT_GEN_MEMBER( fp1100_state::vblank_irq )
void fp1100_state::machine_reset()
{
m_main_irq_status = false;
m_sub_irq_status = false;
int i;
uint8_t slot_type;
const uint8_t id_type[4] = { 0xff, 0x00, 0x01, 0x04};
@ -610,8 +651,8 @@ void fp1100_state::machine_reset()
membank("bankw0")->set_entry(0); // always write to ram
m_irq_mask = 0;
m_main_latch = 0;
m_sub_latch = 0;
m_latch_sub_to_main = 0;
m_latch_main_to_sub = 0;
m_slot_num = 0;
m_kbd_row = 0;
m_col_border = 0;
@ -620,6 +661,7 @@ void fp1100_state::machine_reset()
m_upd7801.porta = 0;
m_upd7801.portb = 0;
m_upd7801.portc = 0;
m_maincpu->set_input_line_vector(0, 0xF0);
}
void fp1100_state::init_fp1100()