nec/pc9801: add RS232 port, hookup SIO irq handling

This commit is contained in:
angelosa 2024-10-30 20:01:37 +01:00
parent d244502260
commit 6be5b15b3e
7 changed files with 74 additions and 10 deletions

View File

@ -136,6 +136,9 @@ void bungo_mini5sx_state::mini5sx_config(machine_config &config)
// m_ppi_sys->in_pc_callback().set_constant(0xa0); // 0x80 cpu triple fault reset flag?
// m_ppi_sys->out_pc_callback().set(FUNC(pc98lt_state::ppi_sys_beep_portc_w));
// TODO: unverified, known to have a serial port
pc9801_serial(config);
I8255(config, m_ppi_prn, 0);
// m_ppi_prn->in_pb_callback().set_ioport("PRNB");

View File

@ -38,6 +38,9 @@ private:
u16 fake_dict_r(offs_t offset);
// just suppress for now, TBD
virtual void uart_irq_check() override {};
void bungo_palette(palette_device &palette) const;
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
};

View File

@ -356,6 +356,7 @@ Keyboard TX commands:
#include "emu.h"
#include "pc9801.h"
#include "machine/input_merger.h"
void pc98_base_state::rtc_w(uint8_t data)
@ -1657,9 +1658,25 @@ u8 pc9801_state::ppi_sys_portb_r()
return res;
}
void pc9801_state::uart_irq_check()
{
m_pic1->ir4_w(m_uart_irq_pending & m_uart_irq_mask ? 1 : 0);
}
template <unsigned N> void pc98_base_state::update_uart_irq(int state)
{
if (state)
m_uart_irq_pending |= 1 << N;
else
m_uart_irq_pending &= ~1 << N;
uart_irq_check();
}
void pc98_base_state::ppi_sys_beep_portc_w(uint8_t data)
{
m_beeper->set_state(!(data & 0x08));
m_uart_irq_mask = data & 7;
uart_irq_check();
}
void pc9801vm_state::ppi_sys_dac_portc_w(uint8_t data)
@ -1668,6 +1685,8 @@ void pc9801vm_state::ppi_sys_dac_portc_w(uint8_t data)
// TODO: some models have a finer grained volume control at I/O port 0xae8e
// (98NOTE only?)
m_dac1bit->set_output_gain(0, m_dac1bit_disable ? 0.0 : 1.0);
m_uart_irq_mask = data & 7;
uart_irq_check();
}
/*
@ -2228,6 +2247,23 @@ void pc9801vm_state::pc9801_ide(machine_config &config)
SOFTWARE_LIST(config, "cd_list").set_original("pc98_cd");
}
void pc98_base_state::pc9801_serial(machine_config &config)
{
// clocked by PIT channel 2
I8251(config, m_sio, 0);
m_sio->txd_handler().set("serial", FUNC(rs232_port_device::write_txd));
m_sio->rts_handler().set("serial", FUNC(rs232_port_device::write_rts));
m_sio->dtr_handler().set("serial", FUNC(rs232_port_device::write_dtr));
m_sio->rxrdy_handler().set([this] (int state) { update_uart_irq<0>(state); });
m_sio->txempty_handler().set([this] (int state) { update_uart_irq<1>(state); });
m_sio->txrdy_handler().set([this] (int state) { update_uart_irq<2>(state); });
rs232_port_device &rs232(RS232_PORT(config, "serial", default_rs232_devices, nullptr));
rs232.rxd_handler().set(m_sio, FUNC(i8251_device::write_rxd));
rs232.cts_handler().set(m_sio, FUNC(i8251_device::write_cts));
rs232.dsr_handler().set(m_sio, FUNC(i8251_device::write_dsr));
}
void pc9801_state::pc9801_common(machine_config &config)
{
PIT8253(config, m_pit, 0);
@ -2274,7 +2310,7 @@ void pc9801_state::pc9801_common(machine_config &config)
pc9801_mouse(config);
pc9801_cbus(config);
I8251(config, m_sio, 0);
pc9801_serial(config);
PC9801_MEMSW(config, m_memsw, 0);
@ -2292,12 +2328,12 @@ void pc9801_state::pc9801_common(machine_config &config)
m_screen->set_screen_update(FUNC(pc9801_state::screen_update));
m_screen->screen_vblank().set(FUNC(pc9801_state::vrtc_irq));
UPD7220(config, m_hgdc[0], 21.0526_MHz_XTAL / 8);
UPD7220(config, m_hgdc[0], 21.0526_MHz_XTAL / 8, "screen");
m_hgdc[0]->set_addrmap(0, &pc9801_state::upd7220_1_map);
m_hgdc[0]->set_draw_text(FUNC(pc9801_state::hgdc_draw_text));
m_hgdc[0]->vsync_wr_callback().set(m_hgdc[1], FUNC(upd7220_device::ext_sync_w));
UPD7220(config, m_hgdc[1], 21.0526_MHz_XTAL / 8);
UPD7220(config, m_hgdc[1], 21.0526_MHz_XTAL / 8, "screen");
m_hgdc[1]->set_addrmap(0, &pc9801_state::upd7220_2_map);
m_hgdc[1]->set_display_pixels(FUNC(pc9801_state::hgdc_display_pixels));

View File

@ -33,6 +33,7 @@
#include "machine/upd4991a.h"
#include "machine/upd765.h"
#include "bus/rs232/rs232.h"
#include "bus/scsi/pc9801_sasi.h"
#include "bus/scsi/scsi.h"
#include "bus/scsi/scsihd.h"
@ -71,7 +72,6 @@
#include "formats/nfd_dsk.h"
#define RTC_TAG "rtc"
#define UPD8251_TAG "upd8251"
#define SASIBUS_TAG "sasi"
#define ATTRSEL_REG 0
@ -98,6 +98,7 @@ public:
, m_ppi_sys(*this, "ppi_sys")
, m_ppi_prn(*this, "ppi_prn")
, m_beeper(*this, "beeper")
, m_sio(*this, "sio")
{
}
@ -112,13 +113,20 @@ protected:
required_device<i8255_device> m_ppi_sys;
required_device<i8255_device> m_ppi_prn;
optional_device<beep_device> m_beeper;
required_device<i8251_device> m_sio;
void rtc_w(uint8_t data);
void ppi_sys_beep_portc_w(uint8_t data);
virtual void uart_irq_check() = 0;
template <unsigned N> void update_uart_irq(int state);
void pc9801_serial(machine_config &config);
static void floppy_formats(format_registration &fr);
u8 m_sys_type = 0;
u8 m_uart_irq_mask = 0, m_uart_irq_pending = 0;
};
class pc9801_state : public pc98_base_state
@ -142,7 +150,6 @@ public:
, m_pic1(*this, "pic8259_master")
, m_pic2(*this, "pic8259_slave")
, m_memsw(*this, "memsw")
, m_sio(*this, UPD8251_TAG)
, m_sasibus(*this, SASIBUS_TAG)
, m_sasi_data_out(*this, "sasi_data_out")
, m_sasi_data_in(*this, "sasi_data_in")
@ -175,7 +182,6 @@ protected:
required_device<pic8259_device> m_pic2;
private:
required_device<pc9801_memsw_device> m_memsw;
required_device<i8251_device> m_sio;
optional_device<scsi_port_device> m_sasibus;
optional_device<output_latch_device> m_sasi_data_out;
optional_device<input_buffer_device> m_sasi_data_in;
@ -352,6 +358,10 @@ private:
void ppi_mouse_portc_w(uint8_t data);
TIMER_DEVICE_CALLBACK_MEMBER( mouse_irq_cb );
// UART SIO
protected:
virtual void uart_irq_check() override;
};
/**********************************************************

View File

@ -151,7 +151,8 @@ void pc98lt_state::lt_io(address_map &map)
map.unmap_value_high();
// map(0x0000, 0x001f) // PIC (bit 3 ON slave / master), V50 internal / <undefined>
map(0x0020, 0x002f).w(FUNC(pc98lt_state::rtc_w)).umask16(0x00ff);
map(0x0030, 0x0037).rw(m_ppi_sys, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00); //i8251 RS232c / i8255 system port
map(0x0030, 0x0037).rw(m_ppi_sys, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00);
map(0x0030, 0x0033).rw(m_sio, FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); //i8251 RS232c / i8255 system port
map(0x0040, 0x0047).rw(m_ppi_prn, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
map(0x0040, 0x0047).rw(m_keyb, FUNC(pc9801_kbd_device::rx_r), FUNC(pc9801_kbd_device::tx_w)).umask16(0xff00); //i8255 printer port / i8251 keyboard
// map(0x0070, 0x007f) // PIT, V50 internal
@ -418,6 +419,13 @@ static void pc9801_floppies(device_slot_interface &device)
// device.option_add("35hd", FLOPPY_35_HD);
}
void pc98lt_state::uart_irq_check()
{
m_maincpu->set_input_line(4, m_uart_irq_pending & m_uart_irq_mask ? ASSERT_LINE : CLEAR_LINE);
}
void pc98lt_state::lt_config(machine_config &config)
{
const XTAL xtal = XTAL(8'000'000);
@ -427,10 +435,9 @@ void pc98lt_state::lt_config(machine_config &config)
// TODO: jumps off the weeds if divided by / 4 after timer check, DMA issue?
// m_maincpu->set_tclk(xtal / 4);
m_maincpu->set_tclk(xtal / 100);
// m_maincpu->tout2_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ2);
// m_pit->out_handler<0>().set(m_pic1, FUNC(pic8259_device::ir0_w));
// m_pit->out_handler<2>().set(m_sio, FUNC(i8251_device::write_txc));
// m_pit->out_handler<2>().append(m_sio, FUNC(i8251_device::write_rxc));
m_maincpu->tout2_cb().set(m_sio, FUNC(i8251_device::write_txc));
m_maincpu->tout2_cb().append(m_sio, FUNC(i8251_device::write_rxc));
// m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
@ -444,6 +451,8 @@ void pc98lt_state::lt_config(machine_config &config)
// m_ppi_sys->in_pc_callback().set_constant(0xa0); // 0x80 cpu triple fault reset flag?
m_ppi_sys->out_pc_callback().set(FUNC(pc98lt_state::ppi_sys_beep_portc_w));
pc9801_serial(config);
I8255(config, m_ppi_prn, 0);
m_ppi_prn->in_pb_callback().set_ioport("PRNB");

View File

@ -64,6 +64,8 @@ private:
u8 m_floppy_mode = 0;
u8 m_fdc_ctrl = 0;
virtual void uart_irq_check() override;
};
class pc98ha_state : public pc98lt_state

View File

@ -44,6 +44,7 @@ void pc_hyper98_state::pc_h98_io(address_map &map)
{
pc_hyper98_state::pc9801bx2_io(map);
// ...
// map(0x4*a*, 0x4*a*) μPD72120 "AGDC"
}
// TODO: backported from pc9801_epson.cpp, needs mods