diff --git a/bin/History.txt b/bin/History.txt index 72ea6592..b2ba1d1d 100644 --- a/bin/History.txt +++ b/bin/History.txt @@ -9,6 +9,13 @@ https://github.com/AppleWin/AppleWin/issues/new Tom Charlesworth +1.27.3.0 - 14 Apr 2018 +---------------------- +. [Bug #308] SSC: For TCP mode, support DSR, DCD & CTS status bits. +. SSC: Now DTR must also be set to enable interrupts (in addition to the respective Tx/Rx interrupt bit). +. SSC: When reading the Status register, throttle calls to GetCommModemStatus() to a maximum of once every 8ms. + + 1.27.2.0 - 12 Apr 2018 ---------------------- . [Change #522] SSC: Support ACIA's TX Empty interrupt for both COM and TCP modes. diff --git a/resource/Applewin.rc b/resource/Applewin.rc index 3b651424..a2058600 100644 --- a/resource/Applewin.rc +++ b/resource/Applewin.rc @@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,27,2,0 - PRODUCTVERSION 1,27,2,0 + FILEVERSION 1,27,3,0 + PRODUCTVERSION 1,27,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -271,12 +271,12 @@ BEGIN VALUE "Comments", "https://github.com/AppleWin" VALUE "CompanyName", "AppleWin" VALUE "FileDescription", "Apple //e Emulator for Windows" - VALUE "FileVersion", "1, 27, 2, 0" + VALUE "FileVersion", "1, 27, 3, 0" VALUE "InternalName", "APPLEWIN" VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis" VALUE "OriginalFilename", "APPLEWIN.EXE" VALUE "ProductName", "Apple //e Emulator" - VALUE "ProductVersion", "1, 27, 2, 0" + VALUE "ProductVersion", "1, 27, 3, 0" END END BLOCK "VarFileInfo" diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp index 12a3d3d5..0964ba9a 100644 --- a/source/SerialComms.cpp +++ b/source/SerialComms.cpp @@ -439,7 +439,7 @@ BYTE __stdcall CSuperSerialCard::SSC_IOWrite(WORD PC, WORD uAddr, BYTE bWrite, B //=========================================================================== // 6551 ACIA Command Register ($C08A+s0) -// . EG. 0x09 = "no parity, enable IRQ" - b7:5(No parity), b4 (No echo), b3:1(Enable TX,RX IRQs), b0(DTR: Enable Rx/Tx) [Ref.2] +// . EG. 0x09 = "no parity, enable IRQ" [Ref.2] - b7:5(No parity), b4 (No echo), b3:1(Enable TX,RX IRQs), b0(DTR: Enable receiver and all interrupts) enum { CMD_PARITY_MASK = 3<<6, CMD_PARITY_ODD = 0<<6, // Odd parity CMD_PARITY_EVEN = 1<<6, // Even parity @@ -453,7 +453,7 @@ enum { CMD_PARITY_MASK = 3<<6, CMD_TX_IRQ_DIS_RTS_LOW = 2<<2, CMD_TX_IRQ_DIS_RTS_LOW_BRK = 3<<2, // Transmit BRK CMD_RX_IRQ_DIS = 1<<1, // 1=IRQ interrupt disabled - CMD_DTR = 1<<0, // Data Terminal Ready: 1=Enable Rx/Tx (!DTR low) + CMD_DTR = 1<<0, // Data Terminal Ready: Enable(1) or disable(0) receiver and all interrupts (!DTR low) }; BYTE __stdcall CSuperSerialCard::CommProgramReset(WORD, WORD, BYTE, BYTE, ULONG) @@ -513,7 +513,7 @@ void CSuperSerialCard::UpdateCommandReg(BYTE command) break; } - if (m_DIPSWCurrent.bInterrupts) + if (m_DIPSWCurrent.bInterrupts && m_uCommandByte & CMD_DTR) { m_bTxIrqEnabled = (m_uCommandByte & CMD_TX_MASK) == CMD_TX_IRQ_ENA_RTS_LOW; m_bRxIrqEnabled = (m_uCommandByte & CMD_RX_IRQ_DIS) == 0; @@ -630,6 +630,12 @@ BYTE __stdcall CSuperSerialCard::CommReceive(WORD, WORD, BYTE, BYTE, ULONG) if (!m_qTcpSerialBuffer.empty()) { // NB. See CommTcpSerialReceive() above, for a note explaining why there's no need for a critical section here + + // If receiver is disabled then transmitting device should not send data + // . For COM serial connection this is handled by DTR/DTS flow-control (which enables the receiver) + if ((m_uCommandByte & CMD_DTR) == 0) // Receiver disable, so prevent receiving data + return 0; + result = m_qTcpSerialBuffer.front(); m_qTcpSerialBuffer.pop_front(); @@ -639,7 +645,7 @@ BYTE __stdcall CSuperSerialCard::CommReceive(WORD, WORD, BYTE, BYTE, ULONG) m_vbRxIrqPending = true; } } - else if (m_hCommHandle != INVALID_HANDLE_VALUE) // COM + else if (m_hCommHandle != INVALID_HANDLE_VALUE) { EnterCriticalSection(&m_CriticalSection); { @@ -689,6 +695,10 @@ BYTE __stdcall CSuperSerialCard::CommTransmit(WORD, WORD, BYTE, BYTE value, ULON if (!CheckComm()) return 0; + // If transmitter is disabled then: Is data just discarded or does it get transmitted if transmitter is later enabled? + if ((m_uCommandByte & CMD_TX_MASK) == CMD_TX_IRQ_DIS_RTS_HIGH) // Transmitter disable, so just discard for now + return 0; + if (m_hCommAcceptSocket != INVALID_SOCKET) { BYTE data = value; @@ -744,11 +754,28 @@ BYTE __stdcall CSuperSerialCard::CommStatus(WORD, WORD, BYTE, BYTE, ULONG) if (!CheckComm()) return ST_DSR | ST_DCD | ST_TX_EMPTY; - DWORD modemStatus = 0; - if ((m_hCommHandle != INVALID_HANDLE_VALUE) && (m_bCfgSupportDCD || m_bCfgSupportDSR)) + static DWORD modemStatus = 0; + if (m_bCfgSupportDCD || m_bCfgSupportDSR) { - // Do this outside of the critical section (don't know how long it takes) - GetCommModemStatus(m_hCommHandle, &modemStatus); // Returns 0x30 = MS_DSR_ON|MS_CTS_ON + if (m_hCommHandle != INVALID_HANDLE_VALUE) + { + // Call GetCommModemStatus() outside of the critical section. For Win7-64: takes 1-2msecs! + static DWORD dwLastTimeGettingModemStatus = 0; + DWORD dwCurrTime = GetTickCount(); + if (dwCurrTime - dwLastTimeGettingModemStatus > 8) // Limit reading status to twice a 16.6ms video frame (arbitrary throttle limit) + { + // Only permit periodic reading, otherwise a tight 6502 polling loop can kill emulator performance! + GetCommModemStatus(m_hCommHandle, &modemStatus); // Returns 0x30 = MS_DSR_ON|MS_CTS_ON + dwLastTimeGettingModemStatus = dwCurrTime; + } + } + else if (m_hCommListenSocket != INVALID_SOCKET) + { + if (m_hCommAcceptSocket != INVALID_SOCKET) + modemStatus = MS_RLSD_ON | MS_DSR_ON | MS_CTS_ON; + else + modemStatus = 0; + } } // @@ -798,7 +825,7 @@ BYTE __stdcall CSuperSerialCard::CommStatus(WORD, WORD, BYTE, BYTE, ULONG) BYTE uStatus = IRQ | DSR - | DCD // Need 0x00 to allow ZLink to start up + | DCD // Need 0x00 (ie. DCD is active) to allow ZLink to start up | TX_EMPTY | RX_FULL; @@ -862,6 +889,10 @@ BYTE __stdcall CSuperSerialCard::CommDipSw(WORD, WORD addr, BYTE, BYTE, ULONG) if (GetCommModemStatus(m_hCommHandle, &modemStatus)) CTS = (modemStatus & MS_CTS_ON) ? 0 : 1; // CTS is true when 0 } + else if (m_hCommListenSocket != INVALID_SOCKET) + { + CTS = (m_hCommAcceptSocket != INVALID_SOCKET) ? 0 : 1; + } // SSC-54: sw = SW2_1<<7 | // b7 : SW2-1