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); take_interrupt(IR_RCV_ERROR);
} }
else
{
rx_buffer_full();
}
} }
inline void mc68901_device::timer_count(int index) 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_buffer));
save_item(NAME(m_transmit_pending)); save_item(NAME(m_transmit_pending));
save_item(NAME(m_receive_buffer)); 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_input));
save_item(NAME(m_gpio_output)); save_item(NAME(m_gpio_output));
save_item(NAME(m_rsr_read)); save_item(NAME(m_rsr_read));
@ -429,7 +425,8 @@ void mc68901_device::device_start()
void mc68901_device::device_reset() void mc68901_device::device_reset()
{ {
m_tsr = 0; m_tsr = 0;
m_transmit_pending = 0; m_transmit_pending = false;
m_overrun_pending = false;
// Avoid read-before-write // Avoid read-before-write
m_ipr = m_imr = 0; m_ipr = m_imr = 0;
@ -496,7 +493,7 @@ void mc68901_device::tra_complete()
if (m_transmit_pending) if (m_transmit_pending)
{ {
transmit_register_setup(m_transmit_buffer); transmit_register_setup(m_transmit_buffer);
m_transmit_pending = 0; m_transmit_pending = false;
m_tsr |= TSR_BUFFER_EMPTY; m_tsr |= TSR_BUFFER_EMPTY;
if (m_ier & IR_XMIT_BUFFER_EMPTY) if (m_ier & IR_XMIT_BUFFER_EMPTY)
@ -524,10 +521,16 @@ void mc68901_device::tra_complete()
void mc68901_device::rcv_complete() void mc68901_device::rcv_complete()
{ {
receive_register_extract(); receive_register_extract();
m_receive_buffer = get_received_char(); if (m_rsr & RSR_BUFFER_FULL)
//if (m_receive_pending) TODO: error? {
m_overrun_pending = true;
m_receive_pending = 1; }
else
{
m_receive_buffer = get_received_char();
m_rsr |= RSR_BUFFER_FULL;
LOG("Received Character: %02x\n", m_receive_buffer);
}
rx_buffer_full(); rx_buffer_full();
} }
@ -565,19 +568,34 @@ READ8_MEMBER( mc68901_device::read )
case REGISTER_SCR: return m_scr; case REGISTER_SCR: return m_scr;
case REGISTER_UCR: return m_ucr; 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: 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) */ /* 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; uint8_t tsr = m_tsr;
m_tsr &= ~TSR_UNDERRUN_ERROR; if (!machine().side_effect_disabled())
m_tsr &= ~TSR_UNDERRUN_ERROR;
return tsr; return tsr;
} }
case REGISTER_UDR: 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; return m_receive_buffer;
default: return 0; 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); set_data_frame(start_bits, data_bit_count, parity, stop_bits);
receive_register_reset();
m_ucr = data; 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()) if (m_transmit_pending && is_transmit_register_empty())
{ {
transmit_register_setup(m_transmit_buffer); transmit_register_setup(m_transmit_buffer);
m_transmit_pending = 0; m_transmit_pending = false;
m_tsr |= TSR_BUFFER_EMPTY;
} }
if (!m_transmit_pending)
m_tsr |= TSR_BUFFER_EMPTY;
} }
break; break;
case REGISTER_UDR: case REGISTER_UDR:
LOG("MC68901 UDR %x\n", data); LOG("MC68901 UDR %x\n", data);
m_transmit_buffer = data; m_transmit_buffer = data;
m_transmit_pending = 1; m_transmit_pending = true;
m_tsr &= ~TSR_BUFFER_EMPTY; m_tsr &= ~TSR_BUFFER_EMPTY;
if ((m_tsr & TSR_XMIT_ENABLE) && is_transmit_register_empty()) if ((m_tsr & TSR_XMIT_ENABLE) && is_transmit_register_empty())
{ {
transmit_register_setup(m_transmit_buffer); transmit_register_setup(m_transmit_buffer);
m_transmit_pending = 0; m_transmit_pending = false;
m_tsr |= TSR_BUFFER_EMPTY; m_tsr |= TSR_BUFFER_EMPTY;
} }
break; break;

View File

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

View File

@ -213,6 +213,7 @@ WRITE_LINE_MEMBER(device_serial_interface::rx_w)
receive_register_update_bit(state); receive_register_update_bit(state);
if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) if(m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED)
{ {
//device().logerror("Receiver is synchronized\n");
if(m_rcv_clock && !(m_rcv_rate.is_never())) 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 // 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); 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 else
if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED) if (m_rcv_flags & RECEIVE_REGISTER_SYNCHRONISED)
{ {
//device().logerror("Received bit %d\n", m_rcv_bit_count_received);
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))) 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_bit_count_received = 0;
m_rcv_flags &=~RECEIVE_REGISTER_SYNCHRONISED; m_rcv_flags &=~RECEIVE_REGISTER_SYNCHRONISED;
m_rcv_flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT; 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; m_rcv_flags |= RECEIVE_REGISTER_FULL;
} }
} }

View File

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