	{
		uint8_t errors = 0;
		if (is_receive_framing_error())
			errors |= STATUS_FRAMING_ERROR;
		if (is_receive_parity_error())
			errors |= STATUS_PARITY_ERROR;
		rx_fifo_push(get_received_char(), errors);
	}
}

void duart_channel::rx_fifo_push(uint8_t data, uint8_t errors)
{
	if (rx_fifo_num == (MC68681_RX_FIFO_SIZE + 1))
	{
		logerror("68681: FIFO overflow\n");
		SR |= STATUS_OVERRUN_ERROR;
		// In case of overrun the FIFO tail entry is overwritten
		// Back rx_fifo_write_ptr up by one position
		if (rx_fifo_write_ptr)
			rx_fifo_write_ptr--;
		else
			rx_fifo_write_ptr = MC68681_RX_FIFO_SIZE;
	}

	rx_fifo[rx_fifo_write_ptr++] = data | (errors << 8);
	if (rx_fifo_write_ptr > MC68681_RX_FIFO_SIZE)
		rx_fifo_write_ptr = 0;

	if (rx_fifo_num <= MC68681_RX_FIFO_SIZE)
	{
		rx_fifo_num++;
	}

	if (rx_fifo_num == 1)
	{
		SR |= STATUS_RECEIVER_READY;
		if (!(MR1 & MODE_BLOCK_ERROR))
			SR &= ~(STATUS_RECEIVED_BREAK | STATUS_FRAMING_ERROR | STATUS_PARITY_ERROR);
		SR |= errors;
	}
	if (rx_fifo_num == MC68681_RX_FIFO_SIZE)
		SR |= STATUS_FIFO_FULL;
	update_interrupts();
}

void duart_channel::tra_complete()
{
	// The transmit shift register has just emptied.  If another character is
	// waiting in the THR, transfer it to the shift register and assert TxRDY:
	// per the datasheet the THR->shift transfer is where the TxRDY conditions
	// are re-asserted, providing "one full character time of buffering".  If the
	// THR is empty the transmitter is now idle, so set TxEMT (TxRDY is already
	// set from the previous transfer).
	//
	// Asserting TxRDY here, at the transfer -- rather than in the idle branch --
	// both prevents the transmitter from deadlocking when TxRDY would otherwise
	// fail to re-assert on a CPU-write / final-bit-time race, and preserves the
	// one-character buffering window that firmware polling or pipelining on TxRDY
	// relies on.
	if (m_tx_data_in_buffer)
	{
		transmit_register_setup(m_tx_data);
		m_bits_transmitted = 0;
		m_tx_data_in_buffer = false;
		SR |= STATUS_TRANSMITTER_READY;
		update_interrupts();
	}
	else
	{
		SR |= STATUS_TRANSMITTER_EMPTY;
		update_interrupts();
	}
}

void duart_channel::tra_callback()
{
	// don't actually send in loopback mode
	if ((MR2 & 0xc0) != 0x80)
	{
		int bit = transmit_register_get_data_bit();
		//printf("%s ch %d transmit %d\n", tag(), m_ch, bit);
		if (m_ch == 0)
		{
			m_uart->write_a_tx(bit);
		}
		else if (m_ch == 1)
		{
			m_uart->write_b_tx(bit);
		}
		else if (m_ch == 2)
		{
			m_uart->write_c_tx(bit);
		}
		else if (m_ch == 3)
		{
			m_uart->write_d_tx(bit);
		}
	}
	else
	{
		// loop back transmitted bit
		rx_w(transmit_register_get_data_bit());
	}

	// TxRDY is not set until the end of start bit time
	if (++m_bits_transmitted > 1 && !m_tx_data_in_buffer && m_tx_enabled)
	{
		SR |= STATUS_TRANSMITTER_READY;
		update_interrupts();
	}
}

void duart_channel::update_interrupts()
{
	// Handle the TxEMT and TxRDY bits based on mode
	switch (MR2 & 0xc0) // what mode are we in?
	{
