ins8250: Add hack to reset transmitter when baud rate is changed

(nw) This is needed to make the VT102 printer loopback test pass because ins8250_uart_device does not fully emulate the baud rate generator as the independent block it really is, but relies on the all-purpose, somewhat faulty device_serial_interface implementation.
This commit is contained in:
AJR 2018-03-11 22:07:55 -04:00
parent cc98642d5c
commit a8d7ce5fc6
3 changed files with 30 additions and 6 deletions

View File

@ -225,6 +225,17 @@ void ins8250_uart_device::clear_int(int flag)
update_interrupt();
}
// Baud rate generator is reset after writing to either byte of divisor latch
void ins8250_uart_device::update_baud_rate()
{
set_rate(clock(), m_regs.dl * 16);
// FIXME: Baud rate generator should not affect transmitter or receiver, but device_serial_interface resets them regardless.
// If the transmitter is still running at this time and we don't flush it, the shift register will never be emptied!
if (!(m_regs.lsr & INS8250_LSR_TSRE))
tra_complete();
}
WRITE8_MEMBER( ins8250_uart_device::ins8250_w )
{
int tmp;
@ -235,7 +246,7 @@ WRITE8_MEMBER( ins8250_uart_device::ins8250_w )
if (m_regs.lcr & INS8250_LCR_DLAB)
{
m_regs.dl = (m_regs.dl & 0xff00) | data;
set_rate(clock(), m_regs.dl*16);
update_baud_rate();
}
else
{
@ -252,7 +263,7 @@ WRITE8_MEMBER( ins8250_uart_device::ins8250_w )
if (m_regs.lcr & INS8250_LCR_DLAB)
{
m_regs.dl = (m_regs.dl & 0xff) | (data << 8);
set_rate(clock(), m_regs.dl*16);
update_baud_rate();
}
else
{

View File

@ -59,6 +59,8 @@ protected:
void trigger_int(int flag);
void clear_int(int flag);
void update_baud_rate();
const dev_type m_device_type;
struct {
uint8_t thr; /* 0 -W transmitter holding register */

View File

@ -53,7 +53,7 @@ public:
m_nvr(*this, "nvr"),
m_rstbuf(*this, "rstbuf"),
m_rs232(*this, RS232_TAG),
m_printer_uart(*this, "printer_uart"),
m_printer_uart(*this, "printuart"),
m_p_ram(*this, "p_ram")
{
}
@ -246,6 +246,17 @@ void vt100_state::machine_start()
m_kbduart->write_swe(0);
m_pusart->write_cts(0);
if (m_printer_uart.found())
{
auto *printer_port = subdevice<rs232_port_device>("printer");
printer_port->write_dtr(0);
printer_port->write_rts(0);
m_printer_uart->cts_w(0);
m_printer_uart->dcd_w(0);
m_printer_uart->ri_w(0);
}
}
void vt100_state::machine_reset()
@ -422,13 +433,13 @@ MACHINE_CONFIG_START(vt100_state::vt102)
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_IO_MAP(vt102_io)
MCFG_DEVICE_ADD("printer_uart", INS8250, XTAL(24'073'400) / 16)
MCFG_DEVICE_ADD("printuart", INS8250, XTAL(24'073'400) / 16)
MCFG_INS8250_OUT_TX_CB(DEVWRITELINE("printer", rs232_port_device, write_txd))
MCFG_INS8250_OUT_INT_CB(INPUTLINE("maincpu", I8085_RST75_LINE)) // 8085 pin 7, mislabeled RST 5.5 on schematics
MCFG_RS232_PORT_ADD("printer", default_rs232_devices, nullptr)
MCFG_RS232_RXD_HANDLER(DEVWRITELINE("printer_uart", ins8250_device, rx_w))
MCFG_RS232_DSR_HANDLER(DEVWRITELINE("printer_uart", ins8250_device, dsr_w))
MCFG_RS232_RXD_HANDLER(DEVWRITELINE("printuart", ins8250_device, rx_w))
MCFG_RS232_DSR_HANDLER(DEVWRITELINE("printuart", ins8250_device, dsr_w))
MACHINE_CONFIG_END
/* VT1xx models: