summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/mos6551.c
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2013-02-06 14:34:13 +0000
committer Curt Coder <curtcoder@mail.com>2013-02-06 14:34:13 +0000
commit5f9462af076d23acb740d29529d0377da4271d5c (patch)
treef624c200e0064fadf069acc1e8a71a457aefdaeb /src/emu/machine/mos6551.c
parent5948ae089309499aea3599dba5b65ed7e816bae2 (diff)
(MESS) devcb2 conversions. (nw)
Diffstat (limited to 'src/emu/machine/mos6551.c')
-rw-r--r--src/emu/machine/mos6551.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/src/emu/machine/mos6551.c b/src/emu/machine/mos6551.c
new file mode 100644
index 00000000000..9f09ebee54b
--- /dev/null
+++ b/src/emu/machine/mos6551.c
@@ -0,0 +1,277 @@
+/**********************************************************************
+
+ MOS Technology 6551 Asynchronous Communication Interface Adapter
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "mos6551.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+const int mos6551_device::brg_divider[] = {
+ 0, 2304, 1536, 1048, 856, 768, 384, 192, 96, 64, 48, 32, 24, 16, 12, 6
+};
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+// device type definition
+const device_type MOS6551 = &device_creator<mos6551_device>;
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mos6551_device - constructor
+//-------------------------------------------------
+
+mos6551_device::mos6551_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, MOS6551, "MOS6551", tag, owner, clock),
+ device_serial_interface(mconfig, *this),
+ m_irq_handler(*this),
+ m_ctrl(0),
+ m_cmd(CMD_RIE),
+ m_st(ST_TDRE),
+ m_ext_rxc(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mos6551_device::device_start()
+{
+ m_irq_handler.resolve_safe();
+
+ transmit_register_reset();
+ receive_register_reset();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mos6551_device::device_reset()
+{
+ m_ctrl = 0;
+ m_cmd = CMD_RIE;
+
+ update_serial();
+}
+
+
+//-------------------------------------------------
+// tra_complete -
+//-------------------------------------------------
+
+void mos6551_device::tra_complete()
+{
+ if ((m_cmd & CMD_TC_MASK) == CMD_TC_TIE_RTS_LO)
+ {
+ m_st |= ST_IRQ;
+ m_irq_handler(ASSERT_LINE);
+ }
+
+ if (!(m_st & ST_TDRE))
+ {
+ transmit_register_setup(m_tdr);
+ m_st |= ST_TDRE;
+ }
+}
+
+
+//-------------------------------------------------
+// rcv_complete -
+//-------------------------------------------------
+
+void mos6551_device::rcv_complete()
+{
+ if (m_st & ST_RDRF)
+ {
+ m_st |= ST_OR;
+ }
+ else
+ {
+ m_st |= ST_RDRF;
+
+ if (!(m_cmd & CMD_RIE))
+ {
+ m_st |= ST_IRQ;
+ m_irq_handler(ASSERT_LINE);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// input_callback -
+//-------------------------------------------------
+
+void mos6551_device::input_callback(UINT8 state)
+{
+ m_input_state = state;
+}
+
+
+//-------------------------------------------------
+// update_serial -
+//-------------------------------------------------
+
+void mos6551_device::update_serial()
+{
+ int brg = m_ctrl & CTRL_BRG_MASK;
+
+ if (brg == CTRL_BRG_16X_EXTCLK)
+ {
+ set_rcv_rate(m_ext_rxc / 16);
+ set_tra_rate(m_ext_rxc / 16);
+ }
+ else
+ {
+ int baud = clock() / brg_divider[brg] / 16;
+
+ set_tra_rate(baud);
+
+ if (m_ctrl & CTRL_RXC_BRG)
+ {
+ set_rcv_rate(baud);
+ }
+ else
+ {
+ set_rcv_rate(m_ext_rxc / 16);
+ }
+
+ int num_data_bits = 8;
+ int stop_bit_count = 1;
+ int parity_code = SERIAL_PARITY_NONE;
+
+ switch (m_ctrl & CTRL_WL_MASK)
+ {
+ case CTRL_WL_8: num_data_bits = 8; break;
+ case CTRL_WL_7: num_data_bits = 7; break;
+ case CTRL_WL_6: num_data_bits = 6; break;
+ case CTRL_WL_5: num_data_bits = 5; break;
+ }
+
+ set_data_frame(num_data_bits, stop_bit_count, parity_code);
+ }
+
+ if (m_cmd & CMD_DTR)
+ m_connection_state |= SERIAL_STATE_DTR;
+ else
+ m_connection_state &= ~SERIAL_STATE_DTR;
+
+ if ((m_cmd & CMD_TC_MASK) == CMD_TC_RTS_HI)
+ m_connection_state &= ~SERIAL_STATE_RTS;
+ else
+ m_connection_state |= SERIAL_STATE_RTS;
+
+ serial_connection_out();
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( mos6551_device::read )
+{
+ UINT8 data = 0;
+
+ switch (offset & 0x03)
+ {
+ case 0:
+ if (is_receive_register_full())
+ {
+ receive_register_extract();
+ data = get_received_char();
+ }
+
+ m_st &= ~(ST_RDRF | ST_OR | ST_FE | ST_PE);
+ break;
+
+ case 1:
+ data = m_st;
+ m_st &= ~ST_IRQ;
+ m_irq_handler(CLEAR_LINE);
+ break;
+
+ case 2:
+ data = m_cmd;
+ break;
+
+ case 3:
+ data = m_ctrl;
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( mos6551_device::write )
+{
+ switch (offset & 0x03)
+ {
+ case 0:
+ m_tdr = data;
+ m_st &= ~ST_TDRE;
+
+ if (is_transmit_register_empty())
+ {
+ transmit_register_setup(m_tdr);
+ m_st |= ST_TDRE;
+ }
+ break;
+
+ case 1:
+ // programmed reset
+ m_cmd = (m_cmd & 0xe0) | CMD_RIE;
+ m_st &= ~ST_OR;
+ update_serial();
+ break;
+
+ case 2:
+ m_cmd = data;
+ update_serial();
+ break;
+
+ case 3:
+ m_ctrl = data;
+ update_serial();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// set_rxc - set external receiver clock
+//-------------------------------------------------
+
+void mos6551_device::set_rxc(int clock)
+{
+ m_ext_rxc = clock;
+}