diff options
-rw-r--r-- | src/devices/machine/tms9914.cpp | 141 | ||||
-rw-r--r-- | src/devices/machine/tms9914.h | 2 |
2 files changed, 121 insertions, 22 deletions
diff --git a/src/devices/machine/tms9914.cpp b/src/devices/machine/tms9914.cpp index 421bee35590..688f12b4762 100644 --- a/src/devices/machine/tms9914.cpp +++ b/src/devices/machine/tms9914.cpp @@ -7,7 +7,6 @@ Texas Instruments TMS9914(A) GPIB Controller TODO: - - A few minor FSMs only used in non-controller devices (SR,PP) - A few interface commands - A few auxiliary commands @@ -77,8 +76,8 @@ constexpr uint8_t REG_INT0_INT_MASK = 0x3f; // Mask of actual interrupt bits // Interrupt status/mask 1 constexpr unsigned REG_INT1_IFC_BIT = 0; // IFC received -constexpr unsigned REG_INT1_MA_BIT = 1; // My address received -constexpr unsigned REG_INT1_SRQ_BIT = 2; // SRQ asserted +constexpr unsigned REG_INT1_SRQ_BIT = 1; // SRQ asserted +constexpr unsigned REG_INT1_MA_BIT = 2; // My address received constexpr unsigned REG_INT1_DCAS_BIT = 3; // DCAS state active constexpr unsigned REG_INT1_APT_BIT = 4; // Address Pass-Through constexpr unsigned REG_INT1_UNC_BIT = 5; // Unrecognized command @@ -182,13 +181,8 @@ tms9914_device::tms9914_device(const machine_config &mconfig, const char *tag, d m_accrq_write_func(*this) { // Silence compiler complaints about unused variables - (void)REG_INT0_RLC_BIT; - (void)REG_INT0_SPAS_BIT; (void)REG_INT1_IFC_BIT; - (void)REG_INT1_SRQ_BIT; (void)REG_INT1_GET_BIT; - (void)REG_SERIAL_P_MASK; - (void)REG_SERIAL_P_RSV1_BIT; } // Signal inputs @@ -219,7 +213,11 @@ WRITE_LINE_MEMBER(tms9914_device::ifc_w) WRITE_LINE_MEMBER(tms9914_device::srq_w) { + bool prev_srq = get_signal(IEEE_488_SRQ); set_ext_signal(IEEE_488_SRQ , state); + if (cont_r() && !prev_srq && get_signal(IEEE_488_SRQ)) { + set_int1_bit(REG_INT1_SRQ_BIT); + } } WRITE_LINE_MEMBER(tms9914_device::atn_w) @@ -263,15 +261,17 @@ void tms9914_device::write(offs_t offset, uint8_t data) break; case REG_W_SERIAL_P: - m_reg_serial_p = data; - // TODO: update FSM? + { + uint8_t diff = m_reg_2nd_serial_p ^ data; + m_reg_2nd_serial_p = data; + if (BIT(diff , REG_SERIAL_P_RSV1_BIT)) { + update_fsm(); + } + } break; case REG_W_PARALLEL_P: m_reg_2nd_parallel_p = data; - if (!m_pp_ppas) { - m_reg_parallel_p = data; - } break; case REG_W_DO: @@ -435,6 +435,7 @@ void tms9914_device::device_start() save_item(NAME(m_reg_int1_mask)); save_item(NAME(m_reg_address)); save_item(NAME(m_reg_serial_p)); + save_item(NAME(m_reg_2nd_serial_p)); save_item(NAME(m_reg_parallel_p)); save_item(NAME(m_reg_2nd_parallel_p)); save_item(NAME(m_reg_di)); @@ -453,6 +454,7 @@ void tms9914_device::device_start() save_item(NAME(m_stdl)); save_item(NAME(m_shdw)); save_item(NAME(m_vstdl)); + save_item(NAME(m_rsvd2)); save_item(NAME(m_ah_state)); save_item(NAME(m_ah_adhs)); save_item(NAME(m_ah_anhs)); @@ -501,6 +503,7 @@ void tms9914_device::device_reset() m_accrq_line = true; // Ensure change is propagated m_reg_serial_p = 0; + m_reg_2nd_serial_p = 0; m_reg_parallel_p = 0; m_reg_2nd_parallel_p = 0; @@ -735,6 +738,10 @@ void tms9914_device::update_fsm() // BO interrupt is raised when SGNS state is entered set_int0_bit(REG_INT0_BO_BIT); } + if (prev_state == FSM_SH_STRS && m_t_state == FSM_T_SPAS && + (m_sr_state == FSM_SR_APRS1 || m_sr_state == FSM_SR_APRS2)) { + set_int0_bit(REG_INT0_SPAS_BIT); + } } // SH outputs // EOI is controlled by SH & C FSMs @@ -743,14 +750,22 @@ void tms9914_device::update_fsm() uint8_t dio_byte = 0; set_signal(IEEE_488_DAV , m_sh_state == FSM_SH_STRS); if (sh_active()) { - dio_byte = m_t_state == FSM_T_SPAS ? m_reg_serial_p : m_reg_do; + if (m_t_state == FSM_T_SPAS) { + dio_byte = m_reg_serial_p & REG_SERIAL_P_MASK; + if (m_sr_state == FSM_SR_APRS1 || m_sr_state == FSM_SR_APRS2) { + // Set RQS + BIT_SET(dio_byte , 6); + } + } else { + dio_byte = m_reg_do; + } eoi_signal = m_t_eoi_state == FSM_T_ERAS || m_t_eoi_state == FSM_T_ENAS; } // AH FSM prev_state = m_ah_state; bool ah_reset = m_swrst || - (get_signal(IEEE_488_ATN) && m_c_state != FSM_C_CIDS && m_c_state != FSM_C_CADS) || + (get_signal(IEEE_488_ATN) && cont_r()) || (!get_signal(IEEE_488_ATN) && m_l_state != FSM_L_LADS && m_l_state != FSM_L_LACS); if (ah_reset) { m_ah_state = FSM_AH_AIDS; @@ -841,6 +856,9 @@ void tms9914_device::update_fsm() if (!get_signal(IEEE_488_ATN)) { if (m_t_spms) { m_t_state = FSM_T_SPAS; + // When entering SPAS, serial poll register is copied into the + // register that is actually output (as it's double buffered) + m_reg_serial_p = m_reg_2nd_serial_p; } else { m_t_state = FSM_T_TACS; } @@ -862,7 +880,7 @@ void tms9914_device::update_fsm() if (m_t_state != prev_state) { changed = true; } - if (m_t_spms && (m_swrst || get_ifcin() || (m_c_state != FSM_C_CIDS && m_c_state != FSM_C_CADS))) { + if (m_t_spms && (m_swrst || get_ifcin() || cont_r())) { m_t_spms = false; changed = true; } @@ -899,7 +917,77 @@ void tms9914_device::update_fsm() } // No direct L outputs - // TODO: SR & PP FSMs + // PP FSM + if (!m_pp_ppas) { + // PPSS + if (!m_swrst && get_signal(IEEE_488_ATN) && get_signal(IEEE_488_EOI) && !cont_r()) { + m_pp_ppas = true; + changed = true; + // Copy m_reg_2nd_parallel_p when entering PPAS + m_reg_parallel_p = m_reg_2nd_parallel_p; + } + } else { + // PPAS + if (m_swrst || !get_signal(IEEE_488_ATN) || !get_signal(IEEE_488_EOI) || cont_r()) { + m_pp_ppas = false; + changed = true; + } + } + // PP output + if (m_pp_ppas) { + dio_byte |= m_reg_parallel_p; + } + + // SR FSM + prev_state = m_sr_state; + if (m_swrst) { + m_sr_state = FSM_SR_NPRS; + } else { + switch (m_sr_state) { + case FSM_SR_NPRS: + if (m_t_state != FSM_T_SPAS && + (BIT(m_reg_2nd_serial_p , REG_SERIAL_P_RSV1_BIT) || m_rsvd2)) { + m_sr_state = FSM_SR_SRQS; + } + break; + + case FSM_SR_SRQS: + if (m_t_state == FSM_T_SPAS) { + m_sr_state = FSM_SR_APRS1; + } else if (!BIT(m_reg_2nd_serial_p , REG_SERIAL_P_RSV1_BIT) && !m_rsvd2) { + m_sr_state = FSM_SR_NPRS; + } + break; + + case FSM_SR_APRS1: + if (m_t_state == FSM_T_SPAS && m_sh_state == FSM_SH_STRS) { + m_rsvd2 = false; + } + if (!BIT(m_reg_2nd_serial_p , REG_SERIAL_P_RSV1_BIT) && !m_rsvd2) { + m_sr_state = FSM_SR_APRS2; + } + break; + + case FSM_SR_APRS2: + if (m_t_state == FSM_T_SPAS) { + if (m_sh_state == FSM_SH_STRS) { + m_rsvd2 = false; + } + } else { + m_sr_state = FSM_SR_NPRS; + } + break; + + default: + LOG("Invalid SR state %d\n" , m_sr_state); + m_sr_state = FSM_SR_NPRS; + } + } + if (m_sr_state != prev_state) { + changed = true; + } + // SR outputs + set_signal(IEEE_488_SRQ , m_sr_state == FSM_SR_SRQS); // RL FSM if (m_rl_state != FSM_RL_LOCS && (m_swrst || !get_signal(IEEE_488_REN))) { @@ -1097,11 +1185,17 @@ void tms9914_device::if_cmd_received(uint8_t if_cmd) break; case IFCMD_SPE: - // TODO: + if (!get_ifcin() && !m_t_spms) { + m_t_spms = true; + m_ext_state_change = true; + } break; case IFCMD_SPD: - // TODO: + if (m_t_spms) { + m_t_spms = false; + m_ext_state_change = true; + } break; case IFCMD_UNL: @@ -1387,7 +1481,7 @@ void tms9914_device::do_aux_cmd(unsigned cmd , bool set_bit) break; case AUXCMD_STDL: - LOG("Unimplemented STDL cmd\n"); + LOG("Unimplemented STDL=%d cmd\n" , set_bit); break; case AUXCMD_SHDW: @@ -1401,11 +1495,14 @@ void tms9914_device::do_aux_cmd(unsigned cmd , bool set_bit) break; case AUXCMD_VSTDL: - LOG("Unimplemented VSTDL cmd\n"); + LOG("Unimplemented VSTDL=%d cmd\n" , set_bit); break; case AUXCMD_RSV2: - LOG("Unimplemented RSV2 cmd\n"); + if (set_bit != m_rsvd2) { + m_rsvd2 = set_bit; + update_fsm(); + } break; default: diff --git a/src/devices/machine/tms9914.h b/src/devices/machine/tms9914.h index 39a6c8d5632..2c766f0dfc3 100644 --- a/src/devices/machine/tms9914.h +++ b/src/devices/machine/tms9914.h @@ -117,6 +117,7 @@ private: uint8_t m_reg_int1_mask; uint8_t m_reg_address; uint8_t m_reg_serial_p; + uint8_t m_reg_2nd_serial_p; uint8_t m_reg_parallel_p; uint8_t m_reg_2nd_parallel_p; uint8_t m_reg_di; @@ -137,6 +138,7 @@ private: bool m_stdl; bool m_shdw; bool m_vstdl; + bool m_rsvd2; // AH (Acceptor Handshake) states enum { |