mirror of
https://github.com/holub/mame
synced 2025-06-05 20:33:45 +03:00
mc6852 - implement more functionality, add byte interface. (#6931)
This commit is contained in:
parent
c6c5678815
commit
47e32437cd
@ -10,7 +10,7 @@
|
||||
|
||||
TODO:
|
||||
|
||||
- FIFO
|
||||
- FIFO flags
|
||||
- receive
|
||||
- transmit
|
||||
- parity
|
||||
@ -56,7 +56,8 @@ mc6852_device::mc6852_device(const machine_config &mconfig, const char *tag, dev
|
||||
m_cts(1),
|
||||
m_dcd(1),
|
||||
m_sm_dtr(0),
|
||||
m_tuf(0)
|
||||
m_tuf(0),
|
||||
m_in_sync(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -88,6 +89,7 @@ void mc6852_device::device_start()
|
||||
save_item(NAME(m_dcd));
|
||||
save_item(NAME(m_sm_dtr));
|
||||
save_item(NAME(m_tuf));
|
||||
save_item(NAME(m_in_sync));
|
||||
}
|
||||
|
||||
|
||||
@ -106,7 +108,7 @@ void mc6852_device::device_reset()
|
||||
/* reset and inhibit receiver/transmitter sections */
|
||||
m_cr[0] |= (C1_TX_RS | C1_RX_RS);
|
||||
m_cr[1] &= ~(C2_EIE | C2_PC2 | C2_PC1);
|
||||
m_status &= ~S_TDRA;
|
||||
m_status |= S_TDRA;
|
||||
|
||||
/* set receiver shift register to all 1's */
|
||||
m_rsr = 0xff;
|
||||
@ -132,6 +134,51 @@ void mc6852_device::tra_complete()
|
||||
// TODO
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// receive_byte -
|
||||
//-------------------------------------------------
|
||||
void mc6852_device::receive_byte(uint8_t data)
|
||||
{
|
||||
// Ignore if the receiver is in reset or sync is not enabled
|
||||
if (m_cr[0] & (C1_RX_RS | C1_CLEAR_SYNC))
|
||||
return;
|
||||
|
||||
// Handle sync detection
|
||||
if (!m_in_sync)
|
||||
{
|
||||
// TODO also handle two sync codes.
|
||||
if (data == m_scr)
|
||||
{
|
||||
m_in_sync = 1;
|
||||
// TODO handle the various SM responses
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_cr[0] & C1_STRIP_SYNC) && (data == m_scr))
|
||||
return;
|
||||
|
||||
int size = m_rx_fifo.size();
|
||||
|
||||
if (size < 3)
|
||||
{
|
||||
m_rx_fifo.push(data);
|
||||
size++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Overrun.
|
||||
// TODO this should override the last data pushed
|
||||
m_status |= S_RX_OVRN;
|
||||
}
|
||||
|
||||
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
|
||||
|
||||
if (size >= trigger)
|
||||
{
|
||||
m_status |= S_RDA;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rcv_complete -
|
||||
@ -142,32 +189,116 @@ void mc6852_device::rcv_complete()
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read -
|
||||
//-------------------------------------------------
|
||||
|
||||
// TODO each RX fifo element needs an associated PE status flag, and reading
|
||||
// the status register should return the PE for the last element of the fifo.
|
||||
|
||||
// TODO RX overrun should be cleared by reading the status register followed
|
||||
// by reading the RX fifo.
|
||||
|
||||
uint8_t mc6852_device::read(offs_t offset)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
if (BIT(offset, 0))
|
||||
{
|
||||
if (m_rx_fifo.size() > 0)
|
||||
int size = m_rx_fifo.size();
|
||||
if (size > 0)
|
||||
{
|
||||
data = m_rx_fifo.front();
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
m_rx_fifo.pop();
|
||||
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
|
||||
if (size <= trigger)
|
||||
{
|
||||
m_status &= ~S_RDA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = m_status;
|
||||
|
||||
// TS reset inhibits the TDRA status bit (in the
|
||||
// one-sync-character and two-sync-character modes) The
|
||||
// m_status S_TDRA bit is allowed to reflect the actual fifo
|
||||
// availability, masking it here on a read of the status, so
|
||||
// that the TDRA status bit is simply unmasked here when the
|
||||
// TX is taken out of reset.
|
||||
if (m_cr[0] & C1_TX_RS)
|
||||
{
|
||||
data &= ~S_TDRA;
|
||||
}
|
||||
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
// TODO this might not be quite right, the datasheet
|
||||
// states that the RX overrun flag is cleared by
|
||||
// reading the status, and the RX data fifo?
|
||||
m_status &= S_RX_OVRN;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// tx_start -
|
||||
//-------------------------------------------------
|
||||
|
||||
// The corresponds in time to just before the first bit of the next word is
|
||||
// transmitted by this device. At this time the TX shift register is loaded
|
||||
// the TUF line may be asserted if there is a TX FIFO underflow.
|
||||
uint8_t mc6852_device::get_tx_byte(int *tuf)
|
||||
{
|
||||
if (m_cr[0] & C1_TX_RS)
|
||||
{
|
||||
// FIFO is not popped when the TX is reset, but may be loaded
|
||||
// so that it is pre-loaded when the reset is cleared. But
|
||||
// will is send a sync code if that is enabled, of just ones?
|
||||
*tuf = 0;
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
int size = m_tx_fifo.size();
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
// TX underflow
|
||||
if (m_cr[1] & C2_TX_SYNC)
|
||||
{
|
||||
m_status |= S_TUF;
|
||||
// TODO should the TUF callback be called, TUF is to
|
||||
// be pulsed.
|
||||
*tuf = 1;
|
||||
return m_scr;
|
||||
}
|
||||
|
||||
*tuf = 0;
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
uint8_t data = m_tx_fifo.front();
|
||||
m_tx_fifo.pop();
|
||||
size--;
|
||||
|
||||
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
|
||||
int available = 3 - size;
|
||||
|
||||
if (available >= trigger)
|
||||
{
|
||||
m_status |= S_TDRA;
|
||||
}
|
||||
|
||||
*tuf = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write -
|
||||
@ -201,13 +332,40 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
||||
}
|
||||
|
||||
set_data_frame(1, data_bit_count, parity, stop_bits);
|
||||
}
|
||||
|
||||
// The fifo trigger levels may have changed, so update
|
||||
// the status bits.
|
||||
|
||||
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
|
||||
|
||||
if (m_rx_fifo.size() >= trigger)
|
||||
m_status |= S_RDA;
|
||||
else
|
||||
m_status &= ~S_RDA;
|
||||
|
||||
int tx_fifo_available = 3 - m_tx_fifo.size();
|
||||
if (tx_fifo_available >= trigger)
|
||||
m_status |= S_TDRA;
|
||||
else
|
||||
m_status &= ~S_TDRA;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case C1_AC_C3:
|
||||
/* control 3 */
|
||||
LOG("MC6852 Control 3 %02x\n", data);
|
||||
m_cr[2] = data;
|
||||
if (m_cr[2] & C3_CTUF)
|
||||
{
|
||||
m_cr[2] &= ~C3_CTUF;
|
||||
m_status &= ~S_TUF;
|
||||
}
|
||||
if (m_cr[2] & C3_CTS)
|
||||
{
|
||||
m_cr[2] &= ~C3_CTS;
|
||||
m_status &= ~S_CTS;
|
||||
}
|
||||
break;
|
||||
|
||||
case C1_AC_SYNC:
|
||||
@ -216,14 +374,26 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
||||
m_scr = data;
|
||||
break;
|
||||
|
||||
case C1_AC_TX_FIFO:
|
||||
case C1_AC_TX_FIFO: {
|
||||
/* transmit data FIFO */
|
||||
if (m_tx_fifo.size() < 3)
|
||||
int available = 3 - m_tx_fifo.size();
|
||||
if (available > 0)
|
||||
{
|
||||
LOG("MC6852 Transmit FIFO %02x\n", data);
|
||||
m_tx_fifo.push(data);
|
||||
available--;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("MC6852 Transmit FIFO OVERFLOW %02x\n", data);
|
||||
}
|
||||
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
|
||||
if (available < trigger)
|
||||
{
|
||||
m_status &= ~S_TDRA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -243,6 +413,7 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
||||
|
||||
m_status &= ~(S_RX_OVRN | S_PE | S_DCD | S_RDA);
|
||||
m_rsr = 0xff;
|
||||
m_rx_fifo = std::queue<uint8_t>();
|
||||
|
||||
receive_register_reset();
|
||||
}
|
||||
@ -250,22 +421,29 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
||||
/* transmitter reset */
|
||||
if (data & C1_TX_RS)
|
||||
{
|
||||
/* When Tx Rs is set, it clears the transmitter
|
||||
control section, Transmitter Shift Register, Tx Data FIFO
|
||||
Control (the Tx Data FIFO can be reloaded after one E clock
|
||||
pulse), the Transmitter Underflow status bit, and the CTS interrupt,
|
||||
and inhibits the TDRA status bit (in the one-sync-character
|
||||
and two-sync-character modes).*/
|
||||
// When Tx Rs is set, it clears the transmitter
|
||||
// control section, Transmitter Shift Register, Tx
|
||||
// Data FIFO Control (the Tx Data FIFO can be reloaded
|
||||
// after one E clock pulse), the Transmitter Underflow
|
||||
// status bit, and the CTS interrupt.
|
||||
|
||||
LOG("MC6852 Transmitter Reset\n");
|
||||
|
||||
m_status &= ~(S_TUF | S_CTS | S_TDRA);
|
||||
m_status &= ~(S_TUF | S_CTS);
|
||||
m_status |= S_TDRA;
|
||||
m_tx_fifo = std::queue<uint8_t>();
|
||||
|
||||
transmit_register_reset();
|
||||
}
|
||||
|
||||
if (data & C1_STRIP_SYNC) LOG("MC6852 Strip Synchronization Characters\n");
|
||||
if (data & C1_CLEAR_SYNC) LOG("MC6852 Clear Synchronization\n");
|
||||
if (data & C1_STRIP_SYNC)
|
||||
LOG("MC6852 Strip Synchronization Characters\n");
|
||||
|
||||
if (data & C1_CLEAR_SYNC)
|
||||
{
|
||||
LOG("MC6852 Clear Synchronization\n");
|
||||
m_in_sync = 0;
|
||||
}
|
||||
|
||||
m_cr[0] = data;
|
||||
}
|
||||
|
@ -64,6 +64,11 @@ public:
|
||||
DECLARE_READ_LINE_MEMBER( sm_dtr_r ) { return m_sm_dtr; }
|
||||
DECLARE_READ_LINE_MEMBER( tuf_r ) { return m_tuf; }
|
||||
|
||||
// These are to allow integration of this driver with code
|
||||
// controlling floppy disks.
|
||||
void receive_byte(uint8_t data);
|
||||
uint8_t get_tx_byte(int *tuf);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
@ -148,6 +153,7 @@ private:
|
||||
int m_dcd; // data carrier detect
|
||||
int m_sm_dtr; // sync match/data terminal ready
|
||||
int m_tuf; // transmitter underflow
|
||||
int m_in_sync;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user