summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/devices/machine/tms9914.cpp141
-rw-r--r--src/devices/machine/tms9914.h2
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 {