📄 parallelport.cpp
字号:
settings.m_Type = CParallelPortSettings::ParallelTypeSPP;
settings.m_nBaseAddress = nBaseAddress;
settings.m_ECPMode = CParallelPortSettings::ECPModeUndefined;
bSuccess = TRUE;
}
}
}
if (!bSuccess)
{
settings.m_nBaseAddress = 0;
settings.m_Type = CParallelPortSettings::ParallelTypeUndefined;
settings.m_ECPMode = CParallelPortSettings::ECPModeUndefined;
}
return bSuccess;
}
BOOL CParallelPort::GetECPPort(unsigned short nBaseAddress)
{
//If the ECP is idle and the FIFO empty,
//in the ECP's Ecp (at base address+402h),
//bit 1 (Fifo full)=0, and bit 0 (Fifo empty)=1.
//The first test is to see if these bits differ from the
//corresponding bits in the control port (at base address+2).
//If so a further test is to write 34h to the Ecr,
//then read it back. Bit 1 is read/write and bit 0 is read-only.
//If the value read is 35h, the port is an ECP.
BOOL bSuccess = FALSE;
unsigned short nEcrAddress = (unsigned short)(nBaseAddress+0x402);
int nEcrData = _inp(nEcrAddress);
//Read bits 0 and 1 and control port bit 1
int nEcrBit0 = nEcrData & 0x1;
int nEcrBit1 = (nEcrData & 0x2) >> 1;
int nControlBit1 = (ReadControl(nBaseAddress) & 0x2) >> 1;
if (nEcrBit0 == 1 && nEcrBit1 == 0)
{
//Compare control bit 1 to ECR bit 1
//Toggle the control bit if necessary
//to be sure the two registers are different.
if (nControlBit1 == 0)
{
WriteControl(nBaseAddress, 0xF);
nControlBit1 = (ReadControl(nBaseAddress) & 0x2) >> 1;
}
if (nEcrBit1 != nControlBit1)
{
int nOriginalEcrData = nEcrData;
_outp(nEcrAddress, 0x34);
if (_inp(nEcrAddress) == 0x35)
bSuccess = TRUE;
//Restore the ECR to its original value
_outp(nEcrAddress, nOriginalEcrData);
}
}
return bSuccess;
}
BOOL CParallelPort::GetEPPPort(unsigned short nBaseAddress)
{
//Write to an EPP register, then read it back.
//If the read matches the write, it's probably an EPP
BOOL bSuccess = FALSE;
//Use nEppAddressPort for testing, SPP's, ECP's and PS/2 ports
//do not have this register
unsigned short nEppAddressPort = (unsigned short) (nBaseAddress+3);
_outp(nEppAddressPort, 0x55);
//Clear the timeout bit after each EPP operation
int nTimeoutBit = GetEPPTimeoutBit(nBaseAddress);
int nRead = _inp(nEppAddressPort);
nTimeoutBit = GetEPPTimeoutBit(nBaseAddress);
if (nRead == 0x55)
{
_outp(nEppAddressPort, 0xAA);
nTimeoutBit = GetEPPTimeoutBit(nBaseAddress);
nRead = _inp(nEppAddressPort);
nTimeoutBit = GetEPPTimeoutBit(nBaseAddress);
if (nRead == 0xAA)
bSuccess = TRUE;
}
return bSuccess;
}
int CParallelPort::GetEPPTimeoutBit(unsigned short nBaseAddress)
{
//Reads and clears the EPP timeout bit (Statis port bit 0)
//Should be done after each EPP operation.
//The method for clearing the bit varies, so try 3 ways
//1. Write 1 to status port bit 0
//2. Write 0 to status port bit 1
//3. Read the status port again
int nReturn = (ReadStatus(nBaseAddress) & 0x1);
unsigned short nStatusPortAddress = (unsigned short)(nBaseAddress+1);
_outp(nStatusPortAddress, 1);
_outp(nStatusPortAddress, 0);
nReturn = (ReadStatus(nBaseAddress) & 0x1);
return nReturn;
}
BOOL CParallelPort::GetPS2Port(unsigned short nBaseAddress)
{
//First try to tristate (disable) the data outputs by
//setting bit 5 of the control port. Then write 2 values
//to the data port and read each one back. If the values
//match, the data outputs are not disabled and the port
//is not bidirectional. If the values don't match, the data
//outputs are disabled and the port is didirectional
BOOL bSuccess = FALSE;
//Set control port bit 5
WriteControl(nBaseAddress, 0x2F);
//Write the first byte and read it back
WriteData(nBaseAddress, 0x55);
//If it doesn't match, the port is bidirectional
if (ReadData(nBaseAddress) == 0x55)
{ \
WriteData(nBaseAddress, 0xAA);
//If it doesn't match, the port is bidirectional
if (ReadData(nBaseAddress) != 0xAA)
bSuccess = TRUE;
}
else
bSuccess = TRUE;
//Reset control port bit 5
WriteControl(nBaseAddress, 0xF);
return bSuccess;
}
BOOL CParallelPort::GetSPPPort(unsigned short nBaseAddress)
{
//Write two bytes and read them back. If the
//reads matches the writes, the port exists
BOOL bSuccess = FALSE;
//Be sure that control port bit 5 = 0 (Data outputs enabled)
WriteControl(nBaseAddress, 0xF);
//Perform the first write
WriteData(nBaseAddress, 0x55);
if (ReadData(nBaseAddress) == 0x55)
{
WriteData(nBaseAddress, 0xAA);
bSuccess = (ReadData(nBaseAddress) == 0xAA);
}
return bSuccess;
}
void CParallelPort::WriteControl(unsigned short nBaseAddress, int nData)
{
//The control port is at offset nBaseAddress + 2.
//Bits 0, 1 & 3 need to be inverted
_outp((unsigned short)(nBaseAddress+2), nData ^ 0xB);
}
int CParallelPort::ReadControl(unsigned short nBaseAddress)
{
//The control port is at offset nBaseAddress + 2.
//Bits 0, 1 & 3 need to be inverted
return (_inp((unsigned short)(nBaseAddress+2)) ^ 0xB);
}
void CParallelPort::WriteData(unsigned short nBaseAddress, int nData)
{
//The data port is at offset nBaseAddress.
_outp(nBaseAddress, nData);
}
int CParallelPort::ReadData(unsigned short nBaseAddress)
{
//The data port is at offset nBaseAddress.
return _inp(nBaseAddress);
}
int CParallelPort::ReadStatus(unsigned short nBaseAddress)
{
//The status port is at offset nBaseAddress + 1.
//Bit 7 need to be inverted
return (_inp((unsigned short)(nBaseAddress+1)) ^ 0x80);
}
void CParallelPort::WriteControl(int nData)
{
ASSERT(IsOpen()); //Port must be open
WriteControl(m_nBaseAddress, nData);
}
int CParallelPort::ReadControl()
{
ASSERT(IsOpen()); //Port must be open
return ReadControl(m_nBaseAddress);
}
void CParallelPort::WriteData(int nData)
{
ASSERT(IsOpen()); //Port must be open
WriteData(m_nBaseAddress, nData);
}
int CParallelPort::ReadData()
{
ASSERT(IsOpen()); //Port must be open
return ReadData(m_nBaseAddress);
}
int CParallelPort::ReadStatus()
{
ASSERT(IsOpen()); //Port must be open
return ReadStatus(m_nBaseAddress);
}
BOOL CParallelPort::ReadByteUsingNibbleMode(BYTE& byData)
{
ASSERT(IsOpen()); //Port must be open
//Read a byte of data at the status port, in 2 nibbles
//When S6 = 0, set D3 to 0
int S6;
DWORD dwStartTicks = GetTickCount();
do
{
S6 = (ReadStatus(m_nBaseAddress) & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 1);
WriteData(m_nBaseAddress, 0);
//When the peripheral responds by setting S6=1, Set D3=1
//nLowNibble then holds 4 bits of data
int nLowNibble;
do
{
nLowNibble = ReadStatus(m_nBaseAddress);
S6 = (nLowNibble & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 0);
WriteData(m_nBaseAddress, 8);
//When S6 = 0, set D3 to 0
do
{
S6 = (ReadStatus(m_nBaseAddress) & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 1);
WriteData(m_nBaseAddress, 0);
//When the peripheral responds by setting S6=1, Set D3=1
//nHighNibble then holds 4 bits of data
int nHighNibble;
do
{
nHighNibble = ReadStatus(m_nBaseAddress);
S6 = (nHighNibble & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 0);
WriteData(m_nBaseAddress, 8);
//Recombine the two nibbles back into the byte
byData = (BYTE) (((nLowNibble & 0x8) >> 3) +
((nLowNibble & 0x10) >> 3) +
((nLowNibble & 0x20) >> 3) +
((nLowNibble & 0x80) >> 4) +
((nHighNibble & 0x8) << 1) +
((nHighNibble & 0x10) << 1) +
((nHighNibble & 0x20) << 1) +
((nHighNibble & 0x80)));
return TRUE;
}
BOOL CParallelPort::WriteByteUsingNibbleMode(BYTE byData)
{
ASSERT(IsOpen()); //Port must be open
//Write a byte to the data port, in 2 nibbles.
//The remote system reads the data at its status port.
//The data bits are D0, D1, D2 and D4.
//D3 is the strobe
int nLowNibble = byData & 0x07;
nLowNibble |= (byData & 0x08) << 1;
int nHighNibble = (byData & 0x70) >> 4;
nHighNibble |= (byData & 0x80) >> 3;
//When S6=1 (not busy), write the low nibble and set D3=0.
int S6;
DWORD dwStartTicks = GetTickCount();
do
{
S6 = (ReadStatus(m_nBaseAddress) & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 0);
WriteData(m_nBaseAddress, nLowNibble);
//When the peripheral responds by setting S6=0, Set D3=1.
do
{
S6 = (ReadStatus(m_nBaseAddress) & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 1);
WriteData(m_nBaseAddress, nLowNibble | 0x8);
//When S6=1, write the high nibble and set D3=0
do
{
S6 = (ReadStatus(m_nBaseAddress) & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 0);
WriteData(m_nBaseAddress, nHighNibble);
//When the peripheral responds by setting S6=0, Set D3=1.
do
{
S6 = (ReadStatus(m_nBaseAddress) & 0x40) >> 6;
//Check the timeout has not elapsed
if ((GetTickCount() - dwStartTicks) > m_dwTimeout)
return FALSE;
}
while (S6 == 1);
WriteData(m_nBaseAddress, nHighNibble | 0x8);
return TRUE;
}
BOOL CParallelPort::ReadUsingNibbleMode(void* lpBuf, DWORD dwBytes)
{
//Validate the parameters
ASSERT(lpBuf);
//Read each byte into lpBuf
BYTE* lpByteBuf = (BYTE*) lpBuf;
for (DWORD i=0; i<dwBytes; i++)
{
if (!ReadByteUsingNibbleMode(lpByteBuf[i]))
return FALSE;
}
return TRUE;
}
BOOL CParallelPort::WriteUsingNibbleMode(const void* lpBuf, DWORD dwBytes)
{
//Validate the parameters
ASSERT(lpBuf);
//Write each byte from lpBuf
const BYTE* lpByteBuf = (const BYTE*) lpBuf;
for (DWORD i=0; i<dwBytes; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -