mc68901: Improve USART behavior for polled operation

This commit is contained in:
AJR 2017-11-02 20:11:15 -04:00
parent 6a290e3eeb
commit b0ff0b7c70
4 changed files with 46 additions and 24 deletions

View File

@ -211,10 +211,6 @@ inline void mc68901_device::rx_error()
{
take_interrupt(IR_RCV_ERROR);
}
else
{
rx_buffer_full();
}
}
inline void mc68901_device::timer_count(int index)
@ -414,7 +410,7 @@ void mc68901_device::device_start()
save_item(NAME(m_transmit_buffer));
save_item(NAME(m_transmit_pending));
save_item(NAME(m_receive_buffer));
save_item(NAME(m_receive_pending));
save_item(NAME(m_overrun_pending));
save_item(NAME(m_gpio_input));
save_item(NAME(m_gpio_output));
save_item(NAME(m_rsr_read));
@ -429,7 +425,8 @@ void mc68901_device::device_start()
void mc68901_device::device_reset()
{
m_tsr = 0;
m_transmit_pending = 0;
m_transmit_pending = false;
m_overrun_pending = false;
// Avoid read-before-write
m_ipr = m_imr = 0;
@ -496,7 +493,7 @@ void mc68901_device::tra_complete()
if (m_transmit_pending)
{
transmit_register_setup(m_transmit_buffer);
m_transmit_pending = 0;
m_transmit_pending = false;
m_tsr |= TSR_BUFFER_EMPTY;
if (m_ier & IR_XMIT_BUFFER_EMPTY)
@ -524,10 +521,16 @@ void mc68901_device::tra_complete()
void mc68901_device::rcv_complete()
{
receive_register_extract();
m_receive_buffer = get_received_char();
//if (m_receive_pending) TODO: error?
m_receive_pending = 1;
if (m_rsr & RSR_BUFFER_FULL)
{
m_overrun_pending = true;
}
else
{
m_receive_buffer = get_received_char();
m_rsr |= RSR_BUFFER_FULL;
LOG("Received Character: %02x\n", m_receive_buffer);
}
rx_buffer_full();
}
@ -565,19 +568,34 @@ READ8_MEMBER( mc68901_device::read )
case REGISTER_SCR: return m_scr;
case REGISTER_UCR: return m_ucr;
case REGISTER_RSR: return m_rsr;
case REGISTER_RSR:
{
uint8_t rsr = m_rsr;
if (!machine().side_effect_disabled())
m_rsr &= ~RSR_OVERRUN_ERROR;
return rsr;
}
case REGISTER_TSR:
{
/* clear UE bit (in reality, this won't be cleared until one full clock cycle of the transmitter has passed since the bit was set) */
uint8_t tsr = m_tsr;
m_tsr &= ~TSR_UNDERRUN_ERROR;
if (!machine().side_effect_disabled())
m_tsr &= ~TSR_UNDERRUN_ERROR;
return tsr;
}
case REGISTER_UDR:
m_receive_pending = 0;
if (!machine().side_effect_disabled())
{
m_rsr &= ~RSR_BUFFER_FULL;
if (m_overrun_pending)
{
m_overrun_pending = false;
m_rsr |= RSR_OVERRUN_ERROR;
rx_error();
}
}
return m_receive_buffer;
default: return 0;
@ -966,6 +984,7 @@ void mc68901_device::register_w(offs_t offset, uint8_t data)
}
set_data_frame(start_bits, data_bit_count, parity, stop_bits);
receive_register_reset();
m_ucr = data;
}
@ -1052,22 +1071,23 @@ void mc68901_device::register_w(offs_t offset, uint8_t data)
if (m_transmit_pending && is_transmit_register_empty())
{
transmit_register_setup(m_transmit_buffer);
m_transmit_pending = 0;
m_tsr |= TSR_BUFFER_EMPTY;
m_transmit_pending = false;
}
if (!m_transmit_pending)
m_tsr |= TSR_BUFFER_EMPTY;
}
break;
case REGISTER_UDR:
LOG("MC68901 UDR %x\n", data);
m_transmit_buffer = data;
m_transmit_pending = 1;
m_transmit_pending = true;
m_tsr &= ~TSR_BUFFER_EMPTY;
if ((m_tsr & TSR_XMIT_ENABLE) && is_transmit_register_empty())
{
transmit_register_setup(m_transmit_buffer);
m_transmit_pending = 0;
m_transmit_pending = false;
m_tsr |= TSR_BUFFER_EMPTY;
}
break;

View File

@ -279,9 +279,9 @@ private:
uint8_t m_tsr; /* transmitter status register */
uint8_t m_rsr; /* receiver status register */
uint8_t m_transmit_buffer; /* USART data register */
int m_transmit_pending;
bool m_transmit_pending;
uint8_t m_receive_buffer;
int m_receive_pending;
bool m_overrun_pending;
uint8_t m_gpio_input;
uint8_t m_gpio_output;

View File

@ -213,6 +213,7 @@ WRITE_LINE_MEMBER(device_serial_interface::rx_w)
receive_register_update_bit(state);
if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED)
{
//device().logerror("Receiver is synchronized\n");
if(m_rcv_clock && !(m_rcv_rate.is_never()))
// make start delay just a bit longer to make sure we are called after the sender
m_rcv_clock->adjust(((m_rcv_rate*3)/2), 0, m_rcv_rate);
@ -266,6 +267,7 @@ void device_serial_interface::receive_register_update_bit(int bit)
else
if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED)
{
//device().logerror("Received bit %d\n", m_rcv_bit_count_received);
m_rcv_bit_count_received++;
if (!bit && (m_rcv_bit_count_received > (m_rcv_bit_count - m_df_stop_bit_count)))
@ -279,7 +281,7 @@ void device_serial_interface::receive_register_update_bit(int bit)
m_rcv_bit_count_received = 0;
m_rcv_flags &=~RECEIVE_REGISTER_SYNCHRONISED;
m_rcv_flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT;
//logerror("receive register full\n");
//device().logerror("Receive register full\n");
m_rcv_flags |= RECEIVE_REGISTER_FULL;
}
}

View File

@ -45,8 +45,8 @@ static MACHINE_CONFIG_START( tti )
MCFG_DEVICE_ADD("mfp", MC68901, 0)
MCFG_MC68901_TIMER_CLOCK(XTAL_20MHz / 2) // guess
MCFG_MC68901_RX_CLOCK(153000) // for testing
MCFG_MC68901_TX_CLOCK(153000) // for testing
MCFG_MC68901_RX_CLOCK(9600) // for testing (FIXME: actually 16x)
MCFG_MC68901_TX_CLOCK(9600) // for testing (FIXME: actually 16x)
MCFG_MC68901_OUT_SO_CB(DEVWRITELINE("rs232", rs232_port_device, write_txd))
MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, "terminal")