⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ltddc.c

📁 此代码为WCE5.0下显示器的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        DDC2_I2C_DELAY();
        if (DDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
        {
            DALDEBUG((DALDBG_DETAIL, "DDC2_I2CStart: SCL didn't take"));
            break;
        }
        DDC2_I2CWriteDataLine(hGDO, hDDL, 0);           // Set SDA low
        DDC2_I2C_DELAY();
        DDC2_I2CWriteClockLine(hGDO, hDDL, 0);          // Set SCL low
        DDC2_I2C_DELAY();
        return TRUE;
    }

    DALDEBUG((DALDBG_DETAIL, "DDC2_I2CStart: Failed"));
    return FALSE;
}   // DDC2_I2CStart()

BOOLEAN
DDC2_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.
    //

    DDC2_I2CWriteDataLine(hGDO, hDDL, 0);               // Set SDA low
    DDC2_I2C_DELAY();
    DDC2_I2CWriteClockLine(hGDO, hDDL, 1);              // Set SCL high
    DDC2_I2C_DELAY();
    if (DDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
    {
        DALDEBUG((DALDBG_DETAIL, "DDC2_I2CStop: SCL didn't take"));
        return FALSE;
    }
    DDC2_I2CWriteDataLine(hGDO, hDDL, 1);               // Set SDA high
    DDC2_I2C_DELAY();
    if (DDC2_I2CReadDataLine(hGDO, hDDL) == FALSE)
    {
        DALDEBUG((DALDBG_DETAIL, "DDC2_I2CI2CStop: SDA didn't take"));
        return FALSE;
    }

    return TRUE;
}   // DDC2_I2CStop()

BOOLEAN
DDC2_I2CWrite(
    HGDO hGDO,
    HDDL hDDL,
    LPUCHAR lpucBuffer,
    ULONG ulLength
    )
//
// 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.
//
{
    ULONG ulCount;

    DALASSERT(NULL != hDDL, "hDDL is NULL!");
    DALASSERT(NULL != lpucBuffer, "lpucBuffer is NULL!");

    if (DDC2_I2CStart(hGDO, hDDL) == FALSE)
        return FALSE;

    for (ulCount = 0; ulCount < ulLength; ulCount++)
    {
        if (DDC2_I2CWriteByte(hGDO, hDDL, lpucBuffer[ulCount]) == FALSE)
        {
            DDC2_I2CStop(hGDO, hDDL);
            return FALSE;
        }
    }

    if (DDC2_I2CStop(hGDO, hDDL) == FALSE)
        return FALSE;

    return TRUE;
}   // DDC2_I2CWrite()

BOOLEAN
DDC2_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.
        //

        DDC2_I2CWriteDataLine(hGDO, hDDL, (UCHAR)((ucByte >> lShift) & 0x01));  // Set SDA
        DDC2_I2C_DELAY();

        //
        // After each data bit we must send high->low SCL pulse.
        //

        DDC2_I2CWriteClockLine(hGDO, hDDL, 1);              // Set SCL high
        DDC2_I2C_DELAY();
        if (DDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
        {
            DALDEBUG((DALDBG_DETAIL, "DDC2_I2CWriteByte: SCL didn't take"));
            return FALSE;
        }
        DDC2_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.
    //

    DDC2_I2CWriteDataLine(hGDO, hDDL, 1);                   // Set SDA high
    DDC2_I2C_DELAY();
    DDC2_I2CWriteClockLine(hGDO, hDDL, 1);                  // Set SCL high
    DDC2_I2C_DELAY();
    if (DDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
    {
        DALDEBUG((DALDBG_DETAIL, "DDC2_I2CWriteByte: SCL didn't take - ACK failed"));
        return FALSE;
    }
    bAck = DDC2_I2CReadDataLine(hGDO, hDDL);                // Read ACK bit
    DDC2_I2CWriteClockLine(hGDO, hDDL, 0);                  // Set SCL low
    DDC2_I2C_DELAY();

    if (TRUE == bAck)                                               // NAK from the monitor
    {
        DALDEBUG((DALDBG_DETAIL, "DDC2_I2CWriteByte: NAK received"));
        return FALSE;
    }

    return TRUE;
}   // DDC2_I2CWriteByte()

BOOLEAN
DDC2_I2CRead(
    HGDO hGDO,
    HDDL hDDL,
    LPUCHAR lpucBuffer,
    ULONG ulLength
    )
//
// 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 (DDC2_I2CStart(hGDO, hDDL) == FALSE)
        return FALSE;

    //
    // Tell the monitor that we want to listen to it.
    //

    if (DDC2_I2CWriteByte(hGDO, hDDL, DDC2_I2C_MONITOR_ADDRESS_READ) == FALSE)
    {
        DDC2_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 (DDC2_I2CReadByte(hGDO, hDDL, lpucBuffer + ulCount, FALSE) == FALSE)  // Last byte
            {
                DDC2_I2CStop(hGDO, hDDL);
                return FALSE;
            }
        }
        else
        {
            if (DDC2_I2CReadByte(hGDO, hDDL, lpucBuffer + ulCount, TRUE) == FALSE)
            {
                DDC2_I2CStop(hGDO, hDDL);
                return FALSE;
            }
        }
    }

    if (DDC2_I2CStop(hGDO, hDDL) == FALSE)
        return FALSE;

    return TRUE;
}   // DDC2_I2CRead()

BOOLEAN
DDC2_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--)
    {
        DDC2_I2CWriteClockLine(hGDO, hDDL, 1);                  // Set SCL high
        DDC2_I2C_DELAY();
        if (DDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
        {
            DALDEBUG((DALDBG_DETAIL, "DDC2_I2CReadByte: SCL didn't take"));
            return FALSE;
        }
        *lpucByte |= DDC2_I2CReadDataLine(hGDO, hDDL) << lShift; // Read SDA
        DDC2_I2CWriteClockLine(hGDO, hDDL, 0);                  // Set SCL low
        DDC2_I2C_DELAY();
    }

    //
    // Send the acknowledge bit. SDA low = ACK, SDA high = NAK.
    //

    if (TRUE == bMore)
        DDC2_I2CWriteDataLine(hGDO, hDDL, 0);                   // Set SDA low - ACK
    else
        DDC2_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.
    //

    DDC2_I2CWriteClockLine(hGDO, hDDL, 1);                      // Set SCL high
    DDC2_I2C_DELAY();
    if (DDC2_I2CWaitForClockLineHigh(hGDO, hDDL) == FALSE)
    {
        DALDEBUG((DALDBG_DETAIL, "DDC2_I2CReadByte: SCL didn't take - ACK failed"));
        return FALSE;
    }
    DDC2_I2CWriteClockLine(hGDO, hDDL, 0);                      // Set SCL low
    DDC2_I2C_DELAY();
    DDC2_I2CWriteDataLine(hGDO, hDDL, 1);                       // Set SDA high
    DDC2_I2C_DELAY();

    return TRUE;
}   // DDC2_I2CReadByte()

BOOLEAN
DDC2_I2CWaitForClockLineHigh(
    HGDO hGDO,
    HDDL hDDL
    )
//
// DESCRIPTION:
//  Waits till SCL goes high (SCL low period can be stretched by slow monitors).
//
// PARAMETERS:
//  hDDL        Points to per-adapter device extension.
//
// RETURN VALUE:
//  TRUE        OK - SCL high.
//  FALSE       SCL didn't take.
//
{
    ULONG ulCount;

    DALASSERT(NULL != hDDL, "hDDL is NULL!");

    for (ulCount = 0; ulCount < DDC2_I2C_SCL_READ_RETRIES; ulCount++)
    {
        if (DDC2_I2CReadClockLine(hGDO, hDDL) == TRUE)
            return TRUE;
        DDC2_I2C_DELAY();
    }

    return FALSE;
}   // DDC2_I2CWaitForClockLineHigh

#endif  // _WIN32_WINNT >= 0x500

//
// DDC through LT_GIO register for LT adapters:
// On LT Pro LT_GIO is hiding behind LCD_INDEX/LCD_DATA.
//
//  SCL = Pin GPIO15
//  SDA = Pin GPIO16
//
//  LT_GIO + 1: Bit 5 = SCL Read
//              Bit 6 = SDA Read
//
//  LT_GIO + 3: Bit 5 = SCL Direction, 0 = Input, 1 = Output
//              Bit 6 = SDA Direction, 0 = Input, 1 = Output
//
// NOTE:
//  For DDC communication we are the I2C master and we drive the SCL line.
//  Setting I2C line to input direction drives it high (releases it high - default).
//  Setting I2C line to output direction drives it low (pulls it to ground).
//

//
// TODO: Verify if there is no conflict between I2C/GP_IO Interface functions and DDC Helper functions.
// If there is a chance of conflict we should use VideoPortSynchronizeExecution() callback functions for
// I2C read/write.
//

VOID
DDC2_I2CWriteClockLine(
    HGDO hGDO,
    HDDL hDDL,
    UCHAR ucData
    )
//
// DESCRIPTION:
//  Sets DDC I2C clock line (SCL) low / high.
//
// PARAMETERS:
//  hDDL    Points to per-adapter device extension.
//  ucData  0 = drive SCL low, 1 = drive SCL high.
//
{
    LPGDO_RAGE_CRT hGDORageCRT;
    UCHAR          ucTemp;

    DALASSERT(NULL != hDDL, "hDDL is NULL!");

    hGDORageCRT = (LPGDO_RAGE_CRT)hGDO;

    ucData &= 0x01;     // Mask

    //sunnyvale [vichan] port by [espiritu]
    if (FAMILY_GTC == (hGDORageCRT->ulChipFamily))
    {
        //rage pro specific code
        ucTemp = (UCHAR)(MMREADUCHAR(hGDORageCRT->lpMMR, GP_IO, 3) | (0x01 << 5));
        MMWRITEUCHAR(hGDORageCRT->lpMMR, GP_IO, ucTemp, 3);
        ucTemp = (MMREADUCHAR(hGDORageCRT->lpMMR, GP_IO, 1) & ~(0x01 << 5)) | (ucData<< 5);
        MMWRITEUCHAR(hGDORageCRT->lpMMR, GP_IO, ucTemp, 1);
    }
    else    
    {
        ucData ^= 0x01;     // Invert

        //
        // Set the SCL enable line.
        //

        if( hGDORageCRT->ulChipFamily == FAMILY_LT_PRO||
            hGDORageCRT->ulChipFamily == FAMILY_RAGE_MOBILITY)
        {
            // Set LCD_DATA register to index 7 (LCD_INDEX_LT_GIO).
            MMWRITEUCHAR(hGDORageCRT->lpMMR, LCD_INDEX, LCD_INDEX_LtGio, 0);

            ucTemp = (MMREADUCHAR(hGDORageCRT->lpMMR, LCD_DATA, 3) &
                          ~(0x20))| (ucData << 5);

			MMWRITEUCHAR(hGDORageCRT->lpMMR, LCD_DATA, ucTemp, 3);
        }
        else
        {
            // EPR 35356.
            if (hGDORageCRT->bREADEDIDFROMDVI == TRUE)
            {
                //
                // Rage XL: Handle SCL through DVI connector. (Same as DFP)
                //
                // Set LCD_DATA register to index 28 (LCD_INDEX_TestIO).
                MMWRITEUCHAR(hGDORageCRT->lpMMR, LCD_INDEX, LCD_INDEX_TestIO, 0);

                //
                // Set the SCL enable line (Rage XL).
                //

                ucTemp = (MMREADUCHAR(hGDORageCRT->lpMMR, LCD_DATA, 1) &
                              ~(0x01))| ucData;
                if (ucData)
                {
                    ucTemp &= ~(0x04);
                }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -