📄 lcdddc.c
字号:
if (LCDDDC2_I2CWrite(lpDdcQueryContext->hGDO,
lpDdcQueryContext->hDDL,
ucEdidWriteAddress) == FALSE)
{
ucEdidWriteAddress = DDC2_I2C_MONITOR_ADDRESS_WRITE0;
lpDdcQueryContext->ulLength = 21; // EPR 35356, EPR 36724
if (LCDDDC2_I2CWrite(lpDdcQueryContext->hGDO,
lpDdcQueryContext->hDDL,
ucEdidWriteAddress) == FALSE)
{
//
// Restore I2C_CNTL_0 and I2C_CNTL_1 for "use software I2C".
//
LCD_DDC2_Restore_SOFTWARE_I2C(lpDdcQueryContext->hGDO);
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_QueryCallback: Can't write (110398) - DDC2 not supported"));
return FALSE;
}
}
}
// EPR 35356
// Read EDID from the monitor.
//
ZEROMEMORY(lpDdcQueryContext->lpucQueryBuffer,lpDdcQueryContext->ulLength);
if (LCDDDC2_I2CRead(lpDdcQueryContext->hGDO,
lpDdcQueryContext->hDDL,
lpDdcQueryContext->lpucQueryBuffer,
lpDdcQueryContext->ulLength,
ucEdidWriteAddress) == FALSE)
{
//
// Restore I2C_CNTL_0 and I2C_CNTL_1 for "use software I2C".
//
LCD_DDC2_Restore_SOFTWARE_I2C(lpDdcQueryContext->hGDO);
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_QueryCallback: Can't read - DDC2 not supported"));
return FALSE;
}
//
// Restore I2C_CNTL_0 and I2C_CNTL_1 for "use software I2C".
//
LCD_DDC2_Restore_SOFTWARE_I2C(lpDdcQueryContext->hGDO);
return TRUE;
} // LCDDETQueryCallback()
BOOLEAN
LCDDDC2_I2CStart(
HGDO hGDO,
HDDL hDDL
)
//
// DESCRIPTION:
// Starts I2C communication.
//
// PARAMETERS:
// hDDL Points to per-adapter device extension.
//
// RETURN VALUE:
// TRUE OK.
// FALSE Failed.
//
{
ULONG ulRetry;
DALASSERT(NULL != hDDL, "hDDL is NULL!");
//
// The I2C communications start signal is a SDA high->low while the SCL is high.
//
for (ulRetry = 0; ulRetry <= DDC2_I2C_START_RETRIES; ulRetry++)
{
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 1); // Set SDA high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CReadDataLine(hGDO, hDDL) == FALSE) // SDA didn't take - retry
continue;
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 1); // Set SCL high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CStart: SCL didn't take"));
break;
}
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 0); // Set SDA low
DDC2_I2C_DELAY();
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 0); // Set SCL low
DDC2_I2C_DELAY();
return TRUE;
}
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CStart: Failed"));
return FALSE;
} // LCDDDC2_I2CStart()
BOOLEAN
LCDDDC2_I2CStop(
HGDO hGDO,
HDDL hDDL
)
//
// DESCRIPTION:
// Stops I2C communication.
//
// PARAMETERS:
// hDDL Points to per-adapter device extension.
//
// RETURN VALUE:
// TRUE OK.
// FALSE Failed.
//
{
DALASSERT(hDDL != NULL, "hDDL is NULL!");
//
// The I2C communications stop signal is a SDA low->high while the SCL is high.
//
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 0); // Set SDA low
DDC2_I2C_DELAY();
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 1); // Set SCL high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CStop: SCL didn't take"));
return FALSE;
}
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 1); // Set SDA high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CReadDataLine(hGDO, hDDL) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CStop: SDA didn't take"));
return FALSE;
}
return TRUE;
} // LCDDDC2_I2CStop()
BOOLEAN
LCDDDC2_I2CWrite(
HGDO hGDO,
HDDL hDDL,
UCHAR ucEdidWriteByte
)
//
// DESCRIPTION:
// Writes data to the DDC2 monitor.
//
// PARAMETERS:
// hDDL Points to per-adapter device extension.
// lpucBuffer Points to data to be written.
// ulLength Number of bytes to write.
//
// RETURN VALUE:
// TRUE Write OK.
// FALSE Write failed.
//
{
DALASSERT(NULL != hDDL, "hDDL is NULL!");
if (LCDDDC2_I2CStart(hGDO, hDDL) == FALSE)
return FALSE;
//
// Write Edid write address.
//
if (LCDDDC2_I2CWriteByte(hGDO, hDDL, ucEdidWriteByte) == FALSE)
{
LCDDDC2_I2CStop(hGDO, hDDL);
return FALSE;
}
//
// Write out start address.
//
if (LCDDDC2_I2CWriteByte(hGDO, hDDL, 0) == FALSE)
{
LCDDDC2_I2CStop(hGDO, hDDL);
return FALSE;
}
if (LCDDDC2_I2CStop(hGDO, hDDL) == FALSE)
return FALSE;
return TRUE;
} // LCDDDC2_I2CWrite()
BOOLEAN
LCDDDC2_I2CWriteByte(
HGDO hGDO,
HDDL hDDL,
UCHAR ucByte
)
//
// DESCRIPTION:
// Sends byte over I2C channel.
//
// PARAMETERS:
// hDDL Points to per-adapter device extension.
// ucByte Byte to write.
//
// RETURN VALUE:
// TRUE Write OK.
// FALSE Write failed.
//
{
LONG lShift;
BOOLEAN bAck;
DALASSERT(NULL != hDDL, "hDDL is NULL!");
//
// Bits are transmitted serially starting with the MSB.
//
for (lShift = 7; lShift >= 0; lShift--)
{
//
// Transmitt data bit.
//
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, (UCHAR)((ucByte >> lShift) & 0x01)); // Set SDA
DDC2_I2C_DELAY();
//
// After each data bit we must send high->low SCL pulse.
//
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 1); // Set SCL high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "DDC2_I2CWriteByte: SCL didn't take"));
return FALSE;
}
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 0); // Set SCL low
DDC2_I2C_DELAY();
}
//
// The monitor sends ACK by preventing the SDA from going high after the clock pulse we use
// to send our last data bit. If the SDA goes high after this bit, it is a NAK from the monitor.
//
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 1); // Set SDA high
DDC2_I2C_DELAY();
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 1); // Set SCL high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CWriteByte: SCL didn't take - ACK failed"));
return FALSE;
}
bAck = LCDDDC2_I2CReadDataLine(hGDO, hDDL); // Read ACK bit
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 0); // Set SCL low
DDC2_I2C_DELAY();
if (TRUE == bAck) // NAK from the monitor
{
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CWriteByte: NAK received"));
return FALSE;
}
return TRUE;
} // LCDDDC2_I2CWriteByte()
BOOLEAN
LCDDDC2_I2CRead(
HGDO hGDO,
HDDL hDDL,
LPUCHAR lpucBuffer,
ULONG ulLength,
UCHAR ucEdidWriteByte
)
//
// DESCRIPTION:
// Reads data from the DDC2 monitor.
//
// PARAMETERS:
// hDDL Points to per-adapter device extension.
// lpucBuffer Points to storage for data.
// ulLength Number of bytes to read.
//
// RETURN VALUE:
// TRUE Read OK.
// FALSE Read failed.
//
{
ULONG ulCount;
DALASSERT(NULL != hDDL, "hDDL is NULL!");
DALASSERT(NULL != lpucBuffer, "lpucBuffer is NULL!");
if (LCDDDC2_I2CStart(hGDO, hDDL) == FALSE)
return FALSE;
//
// Convert Edid Write Address to Edid Read Address.
//
ucEdidWriteByte |= 0x01;
//
// Tell the monitor that we want to listen to it.
//
if (LCDDDC2_I2CWriteByte(hGDO, hDDL, ucEdidWriteByte) == FALSE)
{
LCDDDC2_I2CStop(hGDO, hDDL);
return FALSE;
}
//
// On all but the last byte, we must send an ACK in order to ensure that the sending device will
// send subsequent data bytes. On the last byte, we must send a NAK so that it will shut up.
//
for (ulCount = 0; ulCount < ulLength; ulCount++)
{
if (ulLength - 1 == ulCount)
{
if (LCDDDC2_I2CReadByte(hGDO, hDDL, lpucBuffer + ulCount, FALSE) == FALSE) // Last byte
{
LCDDDC2_I2CStop(hGDO, hDDL);
return FALSE;
}
}
else
{
if (LCDDDC2_I2CReadByte(hGDO, hDDL, lpucBuffer + ulCount, TRUE) == FALSE)
{
LCDDDC2_I2CStop(hGDO, hDDL);
return FALSE;
}
}
}
if (LCDDDC2_I2CStop(hGDO, hDDL) == FALSE)
return FALSE;
return TRUE;
} // LCDDDC2_I2CRead()
BOOLEAN
LCDDDC2_I2CReadByte(
HGDO hGDO,
HDDL hDDL,
LPUCHAR lpucByte,
BOOLEAN bMore
)
//
// DESCRIPTION:
// Receives byte over I2C channel.
//
// PARAMETERS:
// hDDL Points to per-adapter device extension.
// lpucByte Points to storage for read byte.
// bMore TRUE if we want to continue reading, FALSE otherwise.
//
// RETURN VALUE:
// TRUE Read OK - received byte in lpucByte.
// FALSE Read failed.
//
// NOTE:
// We don't have to relaese SDA high (input) before read. Before first bit is read
// we always write address byte -- write releases SDA high on exit. For each subsequent
// byte we're also OK since we release SDA high on exit from this routine.
//
{
LONG lShift;
DALASSERT(NULL != hDDL, "hDDL is NULL!");
DALASSERT(NULL != lpucByte, "lpucByte is NULL!");
*lpucByte = 0;
//
// The data bits are read from MSB to LSB. A data bit is read while the SCL is high.
//
for (lShift = 7; lShift >= 0; lShift--)
{
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 1); // Set SCL high
DDC2_I2C_DELAY();
if (LCDDDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
{
DALDEBUG((DALDBG_DETAIL, "LCDDDC2_I2CReadByte: SCL didn't take"));
return FALSE;
}
*lpucByte |= LCDDDC2_I2CReadDataLine(hGDO, hDDL) << lShift; // Read SDA
LCDDDC2_I2CWriteClockLine(hGDO, hDDL, 0); // Set SCL low
DDC2_I2C_DELAY();
}
//
// Send the acknowledge bit. SDA low = ACK, SDA high = NAK.
//
if (TRUE == bMore)
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 0); // Set SDA low - ACK
else
LCDDDC2_I2CWriteDataLine(hGDO, hDDL, 1); // Set SDA high - NAK
DDC2_I2C_DELAY();
//
// Send a SCL high->low pulse, then release the SDA by setting it high.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -