SSC work:

. SSC: For TCP mode, support DSR, DCD & CTS status bits (#308).
. 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.
This commit is contained in:
tomcw 2018-04-14 21:15:41 +01:00
parent 1ed484eb01
commit 4ab5aa1e7c
3 changed files with 51 additions and 13 deletions

View File

@ -9,6 +9,13 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth 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 1.27.2.0 - 12 Apr 2018
---------------------- ----------------------
. [Change #522] SSC: Support ACIA's TX Empty interrupt for both COM and TCP modes. . [Change #522] SSC: Support ACIA's TX Empty interrupt for both COM and TCP modes.

View File

@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,27,2,0 FILEVERSION 1,27,3,0
PRODUCTVERSION 1,27,2,0 PRODUCTVERSION 1,27,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin" VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin" VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows" VALUE "FileDescription", "Apple //e Emulator for Windows"
VALUE "FileVersion", "1, 27, 2, 0" VALUE "FileVersion", "1, 27, 3, 0"
VALUE "InternalName", "APPLEWIN" VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis" VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE" VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator" VALUE "ProductName", "Apple //e Emulator"
VALUE "ProductVersion", "1, 27, 2, 0" VALUE "ProductVersion", "1, 27, 3, 0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -439,7 +439,7 @@ BYTE __stdcall CSuperSerialCard::SSC_IOWrite(WORD PC, WORD uAddr, BYTE bWrite, B
//=========================================================================== //===========================================================================
// 6551 ACIA Command Register ($C08A+s0) // 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, enum { CMD_PARITY_MASK = 3<<6,
CMD_PARITY_ODD = 0<<6, // Odd parity CMD_PARITY_ODD = 0<<6, // Odd parity
CMD_PARITY_EVEN = 1<<6, // Even 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 = 2<<2,
CMD_TX_IRQ_DIS_RTS_LOW_BRK = 3<<2, // Transmit BRK CMD_TX_IRQ_DIS_RTS_LOW_BRK = 3<<2, // Transmit BRK
CMD_RX_IRQ_DIS = 1<<1, // 1=IRQ interrupt disabled 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) BYTE __stdcall CSuperSerialCard::CommProgramReset(WORD, WORD, BYTE, BYTE, ULONG)
@ -513,7 +513,7 @@ void CSuperSerialCard::UpdateCommandReg(BYTE command)
break; 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_bTxIrqEnabled = (m_uCommandByte & CMD_TX_MASK) == CMD_TX_IRQ_ENA_RTS_LOW;
m_bRxIrqEnabled = (m_uCommandByte & CMD_RX_IRQ_DIS) == 0; 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()) if (!m_qTcpSerialBuffer.empty())
{ {
// NB. See CommTcpSerialReceive() above, for a note explaining why there's no need for a critical section here // 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(); result = m_qTcpSerialBuffer.front();
m_qTcpSerialBuffer.pop_front(); m_qTcpSerialBuffer.pop_front();
@ -639,7 +645,7 @@ BYTE __stdcall CSuperSerialCard::CommReceive(WORD, WORD, BYTE, BYTE, ULONG)
m_vbRxIrqPending = true; m_vbRxIrqPending = true;
} }
} }
else if (m_hCommHandle != INVALID_HANDLE_VALUE) // COM else if (m_hCommHandle != INVALID_HANDLE_VALUE)
{ {
EnterCriticalSection(&m_CriticalSection); EnterCriticalSection(&m_CriticalSection);
{ {
@ -689,6 +695,10 @@ BYTE __stdcall CSuperSerialCard::CommTransmit(WORD, WORD, BYTE, BYTE value, ULON
if (!CheckComm()) if (!CheckComm())
return 0; 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) if (m_hCommAcceptSocket != INVALID_SOCKET)
{ {
BYTE data = value; BYTE data = value;
@ -744,11 +754,28 @@ BYTE __stdcall CSuperSerialCard::CommStatus(WORD, WORD, BYTE, BYTE, ULONG)
if (!CheckComm()) if (!CheckComm())
return ST_DSR | ST_DCD | ST_TX_EMPTY; return ST_DSR | ST_DCD | ST_TX_EMPTY;
DWORD modemStatus = 0; static DWORD modemStatus = 0;
if ((m_hCommHandle != INVALID_HANDLE_VALUE) && (m_bCfgSupportDCD || m_bCfgSupportDSR)) if (m_bCfgSupportDCD || m_bCfgSupportDSR)
{ {
// Do this outside of the critical section (don't know how long it takes) if (m_hCommHandle != INVALID_HANDLE_VALUE)
GetCommModemStatus(m_hCommHandle, &modemStatus); // Returns 0x30 = MS_DSR_ON|MS_CTS_ON {
// 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 = BYTE uStatus =
IRQ IRQ
| DSR | 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 | TX_EMPTY
| RX_FULL; | RX_FULL;
@ -862,6 +889,10 @@ BYTE __stdcall CSuperSerialCard::CommDipSw(WORD, WORD addr, BYTE, BYTE, ULONG)
if (GetCommModemStatus(m_hCommHandle, &modemStatus)) if (GetCommModemStatus(m_hCommHandle, &modemStatus))
CTS = (modemStatus & MS_CTS_ON) ? 0 : 1; // CTS is true when 0 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: // SSC-54:
sw = SW2_1<<7 | // b7 : SW2-1 sw = SW2_1<<7 | // b7 : SW2-1