mirror of
https://github.com/holub/mame
synced 2025-06-01 02:21:48 +03:00
68561mpcc: Detect framing and parity errors and include them in the receive FIFO; improve handling of interrupts and status register writes
mc2661: Detect framing and parity errors; allow disabling of side effects of reads
This commit is contained in:
parent
b49825bf25
commit
a67dd2df3c
@ -609,6 +609,12 @@ void mpcc_device::rcv_complete()
|
||||
data = get_received_char();
|
||||
LOGRX("%s %02x [%c]\n", FUNCNAME, isascii(data) ? data : ' ', data);
|
||||
|
||||
uint8_t errors = 0;
|
||||
if (is_receive_parity_error())
|
||||
errors |= REG_RSR_CPERR;
|
||||
if (is_receive_framing_error())
|
||||
errors |= REG_RSR_FRERR;
|
||||
|
||||
// receive_data(data);
|
||||
if (m_rx_data_fifo.full())
|
||||
{
|
||||
@ -622,7 +628,12 @@ void mpcc_device::rcv_complete()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rx_data_fifo.enqueue(data);
|
||||
if (m_rx_data_fifo.empty())
|
||||
{
|
||||
m_rsr |= errors;
|
||||
update_interrupts(INT_RX);
|
||||
}
|
||||
m_rx_data_fifo.enqueue(data | errors << 8);
|
||||
m_rsr |= REG_RSR_RDA;
|
||||
// interrupt if rx data availble is enabled
|
||||
if (m_rier & REG_RIER_RDA)
|
||||
@ -747,13 +758,14 @@ void mpcc_device::update_interrupts(int source)
|
||||
|
||||
switch(source)
|
||||
{
|
||||
case INT_TX:
|
||||
case INT_TX_TDRA:
|
||||
case INT_TX_TFC:
|
||||
case INT_TX_TUNRN:
|
||||
case INT_TX_TFERR:
|
||||
if ( m_tsr & (REG_TSR_TDRA | REG_TSR_TFC | REG_TSR_TUNRN | REG_TSR_TFERR) )
|
||||
if (m_tsr & m_tier & (REG_TSR_TDRA | REG_TSR_TFC | REG_TSR_TUNRN | REG_TSR_TFERR))
|
||||
{
|
||||
LOGINT(" - Found unserved TX interrupt %02x\n", m_tsr);
|
||||
LOGINT(" - Found unserved TX interrupt %02x\n", m_tsr & m_tier);
|
||||
m_int_state[TX_INT_PRIO] = INT_REQ; // Still TX interrupts to serve
|
||||
}
|
||||
else
|
||||
@ -761,15 +773,16 @@ void mpcc_device::update_interrupts(int source)
|
||||
m_int_state[TX_INT_PRIO] = INT_NONE; // No more TX interrupts to serve
|
||||
}
|
||||
break;
|
||||
case INT_RX:
|
||||
case INT_RX_RDA:
|
||||
case INT_RX_EOF:
|
||||
case INT_RX_CPERR:
|
||||
case INT_RX_FRERR:
|
||||
case INT_RX_ROVRN:
|
||||
case INT_RX_RAB:
|
||||
if ( m_rsr & (REG_RSR_RDA | REG_RSR_EOF | REG_RSR_CPERR | REG_RSR_FRERR | REG_RSR_ROVRN | REG_RSR_RAB))
|
||||
if (m_rsr & m_rier & (REG_RSR_RDA | REG_RSR_EOF | REG_RSR_CPERR | REG_RSR_FRERR | REG_RSR_ROVRN | REG_RSR_RAB))
|
||||
{
|
||||
LOGINT(" - Found unserved RX interrupt %02x\n", m_rsr);
|
||||
LOGINT(" - Found unserved RX interrupt %02x\n", m_rsr & m_rier);
|
||||
m_int_state[RX_INT_PRIO] = INT_REQ; // Still RX interrupts to serve
|
||||
}
|
||||
else
|
||||
@ -777,12 +790,13 @@ void mpcc_device::update_interrupts(int source)
|
||||
m_int_state[RX_INT_PRIO] = INT_NONE; // No more RX interrupts to serve
|
||||
}
|
||||
break;
|
||||
case INT_SR:
|
||||
case INT_SR_CTS:
|
||||
case INT_SR_DSR:
|
||||
case INT_SR_DCD:
|
||||
if ( m_sisr & (REG_SISR_CTST | REG_SISR_DSRT | REG_SISR_DCDT ) )
|
||||
if (m_sisr & m_sier & (REG_SISR_CTST | REG_SISR_DSRT | REG_SISR_DCDT))
|
||||
{
|
||||
LOGINT(" - Found unserved SR interrupt %02x\n", m_sisr);
|
||||
LOGINT(" - Found unserved SR interrupt %02x\n", m_sisr & m_sier);
|
||||
m_int_state[SR_INT_PRIO] = INT_REQ; // Still SR interrupts to serve
|
||||
}
|
||||
else
|
||||
@ -865,12 +879,15 @@ WRITE8_MEMBER( mpcc_device::write )
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Sync clear of error bits with readout from fifo
|
||||
// TODO: implement Idle bit
|
||||
void mpcc_device::do_rsr(uint8_t data)
|
||||
{
|
||||
LOG("%s -> %02x\n", FUNCNAME, data);
|
||||
m_rsr = data;
|
||||
// writing 1 resets status bits except for RDA which is read-only
|
||||
m_rsr &= ~data | REG_RSR_RDA;
|
||||
// status belonging to data at the head of the FIFO cannot be cleared
|
||||
if (!m_rx_data_fifo.empty())
|
||||
m_rsr |= m_rx_data_fifo.peek() >> 8;
|
||||
update_interrupts(INT_RX);
|
||||
}
|
||||
|
||||
@ -909,7 +926,7 @@ uint8_t mpcc_device::do_rdr()
|
||||
if (!m_rx_data_fifo.empty())
|
||||
{
|
||||
// load data from the FIFO
|
||||
data = m_rx_data_fifo.dequeue();
|
||||
data = m_rx_data_fifo.dequeue() & 0xff;
|
||||
|
||||
// Check if this was the last data and reset the interrupt and status register accordingly
|
||||
if (m_rx_data_fifo.empty())
|
||||
@ -917,6 +934,11 @@ uint8_t mpcc_device::do_rdr()
|
||||
m_rsr &= ~REG_RSR_RDA;
|
||||
update_interrupts(INT_RX_RDA);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rsr |= m_rx_data_fifo.peek() >> 8;
|
||||
update_interrupts(INT_RX);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -952,6 +974,7 @@ void mpcc_device::do_rier(uint8_t data)
|
||||
LOGSETUP(" - Rx INT on Frame error : %s\n", (m_rier & REG_RIER_FRERR) ? "enabled" : "disabled");
|
||||
LOGSETUP(" - Rx INT on Receiver overrun : %s\n", (m_rier & REG_RIER_ROVRN) ? "enabled" : "disabled");
|
||||
LOGSETUP(" - Rx INT on Abort/Break : %s\n", (m_rier & REG_RIER_RAB) ? "enabled" : "disabled");
|
||||
update_interrupts(INT_RX);
|
||||
}
|
||||
|
||||
uint8_t mpcc_device::do_rier()
|
||||
@ -1004,7 +1027,8 @@ void mpcc_device::do_tdr(uint8_t data)
|
||||
void mpcc_device::do_tsr(uint8_t data)
|
||||
{
|
||||
LOGINT("%s -> %02x\n", FUNCNAME, data);
|
||||
m_tsr = data;
|
||||
// writing 1 resets status bits except for TDRA which is read-only
|
||||
m_tsr &= ~data | REG_TSR_TDRA;
|
||||
update_interrupts(INT_TX);
|
||||
}
|
||||
|
||||
@ -1060,6 +1084,7 @@ void mpcc_device::do_tier(uint8_t data)
|
||||
LOGSETUP(" - Tx INT on Frame complete : %s\n", (m_tier & REG_TIER_TFC ) ? "enabled" : "disabled");
|
||||
LOGSETUP(" - Tx INT on Underrun : %s\n", (m_tier & REG_TIER_TUNRN) ? "enabled" : "disabled");
|
||||
LOGSETUP(" - Tx INT on Frame error : %s\n", (m_tier & REG_TIER_TFERR) ? "enabled" : "disabled");
|
||||
update_interrupts(INT_TX);
|
||||
}
|
||||
|
||||
uint8_t mpcc_device::do_tier()
|
||||
@ -1131,6 +1156,7 @@ void mpcc_device::do_sier(uint8_t data)
|
||||
LOGSETUP(" - Serial interface INT on CTS: %s\n", (m_sier & REG_SIER_CTS) ? "enabled" : "disabled");
|
||||
LOGSETUP(" - Serial interface INT on DSR: %s\n", (m_sier & REG_SIER_DSR) ? "enabled" : "disabled");
|
||||
LOGSETUP(" - Serial interface INT on DCD: %s\n", (m_sier & REG_SIER_DCD) ? "enabled" : "disabled");
|
||||
update_interrupts(INT_SR);
|
||||
}
|
||||
|
||||
uint8_t mpcc_device::do_sier()
|
||||
|
@ -207,7 +207,7 @@ protected:
|
||||
uint8_t m_rdr;
|
||||
uint8_t do_rdr();
|
||||
// TODO: investigate if 4 x 16 bit wide FIFO is needed for 16 bit mode
|
||||
util::fifo<uint8_t, 8> m_rx_data_fifo;
|
||||
util::fifo<uint16_t, 8> m_rx_data_fifo;
|
||||
|
||||
// RIVNR - Rx Interrupt Vector Number Register
|
||||
uint8_t m_rivnr;
|
||||
|
@ -212,6 +212,10 @@ void mc2661_device::rcv_complete()
|
||||
receive_register_extract();
|
||||
m_rhr = get_received_char();
|
||||
m_sr |= STATUS_RXRDY;
|
||||
if (is_receive_parity_error())
|
||||
m_sr |= STATUS_PE;
|
||||
if (is_receive_framing_error())
|
||||
m_sr |= STATUS_FE;
|
||||
m_write_rxrdy(ASSERT_LINE);
|
||||
}
|
||||
|
||||
@ -228,8 +232,11 @@ uint8_t mc2661_device::read(offs_t offset)
|
||||
{
|
||||
case REGISTER_HOLDING:
|
||||
data = m_rhr;
|
||||
m_sr &= ~STATUS_RXRDY;
|
||||
m_write_rxrdy(CLEAR_LINE);
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_sr &= ~STATUS_RXRDY;
|
||||
m_write_rxrdy(CLEAR_LINE);
|
||||
}
|
||||
break;
|
||||
|
||||
case REGISTER_STATUS:
|
||||
@ -239,14 +246,20 @@ uint8_t mc2661_device::read(offs_t offset)
|
||||
case REGISTER_MODE:
|
||||
data = m_mr[m_mode_index];
|
||||
|
||||
m_mode_index++;
|
||||
m_mode_index &= 0x01;
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_mode_index++;
|
||||
m_mode_index &= 0x01;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REGISTER_COMMAND:
|
||||
m_mode_index = 0;
|
||||
m_sync_index = 0;
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_mode_index = 0;
|
||||
m_sync_index = 0;
|
||||
}
|
||||
|
||||
data = m_cr;
|
||||
break;
|
||||
@ -415,7 +428,7 @@ void mc2661_device::write(offs_t offset, uint8_t data)
|
||||
}
|
||||
if (!COMMAND_RXEN)
|
||||
{
|
||||
m_sr &= ~STATUS_RXRDY;
|
||||
m_sr &= ~(STATUS_RXRDY | STATUS_FE | STATUS_OVERRUN | STATUS_PE);
|
||||
m_write_rxrdy(CLEAR_LINE);
|
||||
}
|
||||
if (COMMAND_RESET)
|
||||
|
Loading…
Reference in New Issue
Block a user