tms9914: added SR & PP FSMs, typo fixed

This commit is contained in:
fulivi 2020-04-26 18:11:46 +02:00
parent cff3741078
commit 5b2b482a52
2 changed files with 121 additions and 22 deletions

View File

@ -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:

View File

@ -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 {