mirror of
https://github.com/holub/mame
synced 2025-06-30 16:00:01 +03:00
mc6852 - implement more functionality, add byte interface. (#6931)
This commit is contained in:
parent
c6c5678815
commit
47e32437cd
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- FIFO
|
- FIFO flags
|
||||||
- receive
|
- receive
|
||||||
- transmit
|
- transmit
|
||||||
- parity
|
- parity
|
||||||
@ -56,7 +56,8 @@ mc6852_device::mc6852_device(const machine_config &mconfig, const char *tag, dev
|
|||||||
m_cts(1),
|
m_cts(1),
|
||||||
m_dcd(1),
|
m_dcd(1),
|
||||||
m_sm_dtr(0),
|
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_dcd));
|
||||||
save_item(NAME(m_sm_dtr));
|
save_item(NAME(m_sm_dtr));
|
||||||
save_item(NAME(m_tuf));
|
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 */
|
/* reset and inhibit receiver/transmitter sections */
|
||||||
m_cr[0] |= (C1_TX_RS | C1_RX_RS);
|
m_cr[0] |= (C1_TX_RS | C1_RX_RS);
|
||||||
m_cr[1] &= ~(C2_EIE | C2_PC2 | C2_PC1);
|
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 */
|
/* set receiver shift register to all 1's */
|
||||||
m_rsr = 0xff;
|
m_rsr = 0xff;
|
||||||
@ -132,6 +134,51 @@ void mc6852_device::tra_complete()
|
|||||||
// TODO
|
// 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 -
|
// rcv_complete -
|
||||||
@ -142,29 +189,113 @@ void mc6852_device::rcv_complete()
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// read -
|
// 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 mc6852_device::read(offs_t offset)
|
||||||
{
|
{
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
|
|
||||||
if (BIT(offset, 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();
|
data = m_rx_fifo.front();
|
||||||
if (!machine().side_effects_disabled())
|
if (!machine().side_effects_disabled())
|
||||||
|
{
|
||||||
m_rx_fifo.pop();
|
m_rx_fifo.pop();
|
||||||
|
int trigger = (m_cr[1] & C2_1_2_BYTE) ? 1 : 2;
|
||||||
|
if (size <= trigger)
|
||||||
|
{
|
||||||
|
m_status &= ~S_RDA;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data = m_status;
|
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;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,13 +332,40 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_data_frame(1, data_bit_count, parity, stop_bits);
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case C1_AC_C3:
|
case C1_AC_C3:
|
||||||
/* control 3 */
|
/* control 3 */
|
||||||
LOG("MC6852 Control 3 %02x\n", data);
|
LOG("MC6852 Control 3 %02x\n", data);
|
||||||
m_cr[2] = 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;
|
break;
|
||||||
|
|
||||||
case C1_AC_SYNC:
|
case C1_AC_SYNC:
|
||||||
@ -216,16 +374,28 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
|||||||
m_scr = data;
|
m_scr = data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case C1_AC_TX_FIFO:
|
case C1_AC_TX_FIFO: {
|
||||||
/* transmit data 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);
|
LOG("MC6852 Transmit FIFO %02x\n", data);
|
||||||
m_tx_fifo.push(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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG("MC6852 Control 1 %02x\n", data);
|
LOG("MC6852 Control 1 %02x\n", data);
|
||||||
@ -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_status &= ~(S_RX_OVRN | S_PE | S_DCD | S_RDA);
|
||||||
m_rsr = 0xff;
|
m_rsr = 0xff;
|
||||||
|
m_rx_fifo = std::queue<uint8_t>();
|
||||||
|
|
||||||
receive_register_reset();
|
receive_register_reset();
|
||||||
}
|
}
|
||||||
@ -250,22 +421,29 @@ void mc6852_device::write(offs_t offset, uint8_t data)
|
|||||||
/* transmitter reset */
|
/* transmitter reset */
|
||||||
if (data & C1_TX_RS)
|
if (data & C1_TX_RS)
|
||||||
{
|
{
|
||||||
/* When Tx Rs is set, it clears the transmitter
|
// When Tx Rs is set, it clears the transmitter
|
||||||
control section, Transmitter Shift Register, Tx Data FIFO
|
// control section, Transmitter Shift Register, Tx
|
||||||
Control (the Tx Data FIFO can be reloaded after one E clock
|
// Data FIFO Control (the Tx Data FIFO can be reloaded
|
||||||
pulse), the Transmitter Underflow status bit, and the CTS interrupt,
|
// after one E clock pulse), the Transmitter Underflow
|
||||||
and inhibits the TDRA status bit (in the one-sync-character
|
// status bit, and the CTS interrupt.
|
||||||
and two-sync-character modes).*/
|
|
||||||
|
|
||||||
LOG("MC6852 Transmitter Reset\n");
|
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();
|
transmit_register_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data & C1_STRIP_SYNC) LOG("MC6852 Strip Synchronization Characters\n");
|
if (data & C1_STRIP_SYNC)
|
||||||
if (data & C1_CLEAR_SYNC) LOG("MC6852 Clear Synchronization\n");
|
LOG("MC6852 Strip Synchronization Characters\n");
|
||||||
|
|
||||||
|
if (data & C1_CLEAR_SYNC)
|
||||||
|
{
|
||||||
|
LOG("MC6852 Clear Synchronization\n");
|
||||||
|
m_in_sync = 0;
|
||||||
|
}
|
||||||
|
|
||||||
m_cr[0] = data;
|
m_cr[0] = data;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,11 @@ public:
|
|||||||
DECLARE_READ_LINE_MEMBER( sm_dtr_r ) { return m_sm_dtr; }
|
DECLARE_READ_LINE_MEMBER( sm_dtr_r ) { return m_sm_dtr; }
|
||||||
DECLARE_READ_LINE_MEMBER( tuf_r ) { return m_tuf; }
|
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:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_start() override;
|
virtual void device_start() override;
|
||||||
@ -148,6 +153,7 @@ private:
|
|||||||
int m_dcd; // data carrier detect
|
int m_dcd; // data carrier detect
|
||||||
int m_sm_dtr; // sync match/data terminal ready
|
int m_sm_dtr; // sync match/data terminal ready
|
||||||
int m_tuf; // transmitter underflow
|
int m_tuf; // transmitter underflow
|
||||||
|
int m_in_sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user