void acia6850_device::device_reset() { int cts = devcb_call_read_line(&m_in_cts_func); int dcd = devcb_call_read_line(&m_in_dcd_func); m_status = (cts << 3) | (dcd << 2) | ACIA6850_STATUS_TDRE; m_tdr = 0; m_rdr = 0; m_tx_shift = 0; m_rx_shift = 0; m_tx_counter = 0; m_rx_counter = 0; TXD(1); m_overrun = 0; m_status_read = 0; m_brk = 0; m_rx_state = START; m_tx_state = START; m_irq = 0; devcb_call_write_line(&m_out_irq_func, 1); if (m_first_reset) { m_first_reset = 0; RTS(1); } else { RTS(m_rts); } }
READ8_DEVICE_HANDLER_TRAMPOLINE(acia6850, acia6850_data_r) { m_status &= ~(ACIA6850_STATUS_RDRF | ACIA6850_STATUS_IRQ | ACIA6850_STATUS_PE); if (m_status_read) { int dcd = devcb_call_read_line(&m_in_dcd_func); m_status_read = 0; m_status &= ~(ACIA6850_STATUS_OVRN | ACIA6850_STATUS_DCD); if (dcd) { m_status |= ACIA6850_STATUS_DCD; } } if (m_overrun == 1) { m_status |= ACIA6850_STATUS_OVRN; m_overrun = 0; } check_interrupts(); return m_rdr; }
static UINT8 control_b_r(const device_config *device) { pia6821_state *p = get_token(device); UINT8 ret; /* update CB1 & CB2 if callback exists, these in turn may update IRQ's */ if (p->in_cb1_func.read != NULL) pia6821_cb1_w(device, 0, devcb_call_read_line(&p->in_cb1_func)); else if (!p->logged_cb1_not_connected && !p->in_cb1_pushed) { logerror("PIA #%s: Error! no CB1 read handler. Three-state pin is undefined\n", device->tag); p->logged_cb1_not_connected = TRUE; } if (p->in_cb2_func.read != NULL) pia6821_cb2_w(device, 0, devcb_call_read_line(&p->in_cb2_func)); else if (!p->logged_cb2_not_connected && C2_INPUT(p->ctl_b) && !p->in_cb2_pushed) { logerror("PIA #%s: Error! No CB2 read handler. Three-state pin is undefined\n", device->tag); p->logged_cb2_not_connected = TRUE; } /* read control register */ ret = p->ctl_b; /* set the IRQ flags if we have pending IRQs */ if (p->irq_b1) ret |= PIA_IRQ1; if (p->irq_b2 && C2_INPUT(p->ctl_b)) ret |= PIA_IRQ2; LOG(("PIA #%s: control B read = %02X\n", device->tag, ret)); return ret; }
static UINT8 control_a_r(const device_config *device) { pia6821_state *p = get_token(device); UINT8 ret; /* update CA1 & CA2 if callback exists, these in turn may update IRQ's */ if (p->in_ca1_func.read != NULL) pia6821_ca1_w(device, 0, devcb_call_read_line(&p->in_ca1_func)); else if (!p->logged_ca1_not_connected && (!p->in_ca1_pushed)) { logerror("PIA #%s: Warning! No CA1 read handler. Assuming pin not connected\n", device->tag); p->logged_ca1_not_connected = TRUE; } if (p->in_ca2_func.read != NULL) pia6821_ca2_w(device, 0, devcb_call_read_line(&p->in_ca2_func)); else if ( !p->logged_ca2_not_connected && C2_INPUT(p->ctl_a) && !p->in_ca2_pushed) { logerror("PIA #%s: Warning! No CA2 read handler. Assuming pin not connected\n", device->tag); p->logged_ca2_not_connected = TRUE; } /* read control register */ ret = p->ctl_a; /* set the IRQ flags if we have pending IRQs */ if (p->irq_a1) ret |= PIA_IRQ1; if (p->irq_a2 && C2_INPUT(p->ctl_a)) ret |= PIA_IRQ2; LOG(("PIA #%s: control A read = %02X\n", device->tag, ret)); return ret; }
void acia6850_device::rx_clock_in() { int dcd = devcb_call_read_line(&m_in_dcd_func); if (dcd) { m_status |= ACIA6850_STATUS_DCD; check_interrupts(); } else if ((m_status & (ACIA6850_STATUS_DCD|ACIA6850_STATUS_IRQ)) == ACIA6850_STATUS_DCD) { m_status &= ~ACIA6850_STATUS_DCD; } m_rx_counter ++; if ( m_rx_counter > m_divide - 1) { rx_tick(); m_rx_counter = 0; } }
void acia6850_device::tx_clock_in() { int _cts = devcb_call_read_line(&m_in_cts_func); if (_cts) { m_status |= ACIA6850_STATUS_CTS; } else { m_status &= ~ACIA6850_STATUS_CTS; } m_tx_counter ++; if ( m_tx_counter > m_divide - 1) { tx_tick(); m_tx_counter = 0; } }
void acia6850_device::rx_tick() { int dcd = devcb_call_read_line(&m_in_dcd_func); if (dcd) { m_status |= ACIA6850_STATUS_DCD; check_interrupts(); } else if ((m_status & (ACIA6850_STATUS_DCD | ACIA6850_STATUS_IRQ)) == ACIA6850_STATUS_DCD) { m_status &= ~ACIA6850_STATUS_DCD; } if (m_status & ACIA6850_STATUS_DCD) { m_rx_state = START; } else { int rxd = devcb_call_read_line(&m_in_rx_func); switch (m_rx_state) { case START: { if (rxd == 0) { if (LOG) logerror("MC6850 '%s': RX START BIT\n", tag()); m_rx_shift = 0; m_rx_parity = 0; m_rx_bits = m_bits; m_rx_state = DATA; } break; } case DATA: { if (LOG) logerror("MC6850 '%s': RX DATA BIT %x\n", tag(), rxd); m_rx_shift |= rxd ? 0x80 : 0; m_rx_parity ^= rxd; if (--m_rx_bits == 0) { if (m_status & ACIA6850_STATUS_RDRF) { m_overrun = 1; check_interrupts(); } m_rx_state = m_parity == NONE ? STOP : PARITY; } else { m_rx_shift >>= 1; } break; } case PARITY: { if (LOG) logerror("MC6850 '%s': RX PARITY BIT %x\n", tag(), rxd); m_rx_parity ^= rxd; if (m_parity == EVEN) { if (m_rx_parity) { m_status |= ACIA6850_STATUS_PE; } } else { if (!m_rx_parity) { m_status |= ACIA6850_STATUS_PE; } } m_rx_state = STOP; break; } case STOP: { if (rxd == 1) { if (LOG) logerror("MC6850 '%s': RX STOP BIT\n", tag()); if (m_stopbits == 1) { m_status &= ~ACIA6850_STATUS_FE; if (!(m_status & ACIA6850_STATUS_RDRF)) { if (LOG) logerror("MC6850 '%s': RX DATA %x\n", tag(), m_rx_shift); m_rdr = m_rx_shift; m_status |= ACIA6850_STATUS_RDRF; check_interrupts(); } m_rx_state = START; } else { m_rx_state = STOP2; } } else { m_status |= ACIA6850_STATUS_FE; m_rx_state = START; } break; } case STOP2: { if (rxd == 1) { if (LOG) logerror("MC6850 '%s': RX STOP BIT\n", tag()); m_status &= ~ACIA6850_STATUS_FE; if (!(m_status & ACIA6850_STATUS_RDRF)) { if (LOG) logerror("MC6850 '%s': RX DATA %x\n", tag(), m_rx_shift); m_rdr = m_rx_shift; m_status |= ACIA6850_STATUS_RDRF; check_interrupts(); } m_rx_state = START; } else { m_status |= ACIA6850_STATUS_FE; m_rx_state = START; } break; } } } }
void acia6850_device::tx_tick() { switch (m_tx_state) { case START: { if (m_brk) { // transmit break TXD(0); } else { int _cts = devcb_call_read_line(&m_in_cts_func); if (_cts) { m_status |= ACIA6850_STATUS_CTS; } else { m_status &= ~ACIA6850_STATUS_CTS; } check_interrupts(); if (m_status & ACIA6850_STATUS_TDRE) { // transmitter idle TXD(1); } else { // transmit character if (LOG) logerror("MC6850 '%s': TX DATA %x\n", tag(), m_tdr); if (LOG) logerror("MC6850 '%s': TX START BIT\n", tag()); TXD(0); m_tx_bits = m_bits; m_tx_shift = m_tdr; m_tx_parity = 0; m_tx_state = DATA; } } break; } case DATA: { int val = m_tx_shift & 1; if (LOG) logerror("MC6850 '%s': TX DATA BIT %x\n", tag(), val); TXD(val); m_tx_parity ^= val; m_tx_shift >>= 1; if (--(m_tx_bits) == 0) { m_tx_state = (m_parity == NONE) ? STOP : PARITY; } break; } case PARITY: { int parity = 0; if (m_parity == EVEN) { parity = (m_tx_parity & 1) ? 1 : 0; } else { parity = (m_tx_parity & 1) ? 0 : 1; } TXD(parity); if (LOG) logerror("MC6850 '%s': TX PARITY BIT %x\n", tag(), parity); m_tx_state = STOP; break; } case STOP: { if (LOG) logerror("MC6850 '%s': TX STOP BIT\n", tag()); TXD(1); if (m_stopbits == 1) { m_tx_state = START; m_status |= ACIA6850_STATUS_TDRE; } else { m_tx_state = STOP2; } break; } case STOP2: { if (LOG) logerror("MC6850 '%s': TX STOP BIT\n", tag()); TXD(1); m_tx_state = START; m_status |= ACIA6850_STATUS_TDRE; break; } } }