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

📄 frame_sync.c

📁 Realtek 公司的RTD2523A芯片原厂source code,没有被修改过的。
💻 C
字号:
#define __FRAMESYNC__

#include "Header\INCLUDE.H"


/////////////////////////
// Frame-Sync Detector //
/////////////////////////
bit Frame_Sync_Detector(void)
{
    if (bPower_Status && bStable && MODE_NOSIGNAL != ucMode_Curr && MODE_NOSUPPORT != ucMode_Curr)
    {
        if (bFrameSync)
        {
            RTDRead(STATUS0_01, 1, N_INC);      // Read Status

            if (0x00 == (Data[0] & 0x03))
            {
                // No event occurred. Just return 0
                if (SOURCE_VGA != (stGUD1.INPUT_SOURCE & 0x07))     return _FALSE;

                if (0x00 == (Data[0] & 0x80))
                {
#if (TUNE_APLL)
                    if (0 == ucPE_Level)
                    {
                        RTDSetBit(DV_TOTAL_STATUS_3D, 0x7f, 0x20);      //Enable PE Max Measurement
                        Delay_Xms(1);
                        RTDRead(DV_TOTAL_STATUS_3D, 1, N_INC);          //Read PE Max
                    
                        if (0x10 < (Data[0] & 0x1f))
                        {
                            ucPE_Level = 1;
                            Adjust_I_Code();

                            if (ucI_Code & 0x80)
                                RTDSetBit(I_CODE_MB_CA, 0xdf, 0x20);    //Set the I_Code[13] to 1;
                            else
                                RTDSetBit(I_CODE_MB_CA, 0xdf, 0x00);    //Set the I_Code[13] to 0;
                        
                            ucI_Code = ucI_Code & 0x7f;
                            RTDSetByte(I_CODE_LB_C9, 0x1c | ((ucI_Code & 0x07) << 5));
                            RTDSetBit(I_CODE_MB_CA, 0xfc, 0x04 | ((ucI_Code & 0x18) >> 3));

                            RTDSetBit(DV_TOTAL_STATUS_3D, 0xdf, 0x00);  //Disable PE Max Measurement
                            RTDSetByte(DV_TOTAL_STATUS_3D, 0x40);       //Clear PE Max value
                        }
                    }
#endif
                    // No event occurred. Just return 0
                    return _FALSE;
                }
            }

            // You will reach here only when :
            // 1. Underflow / Overflow occurred.
            // 2. PLL mislock for VGA source.
            // Return 1 will cause display to reset.
            Reset_Mode();

            return _TRUE;
        }
        else
        {
            RTDRead(VDIS_CTRL_20, 1, N_INC);

            if (0 == (Data[0] & 0x08))
            {
                // You will reach here only when input format change during
                // Display_VGA_Set()/Display_DVI_Set and Set_Panel(), and
                // watch-dog change display to free-run mode.
                Reset_Mode();
                return _TRUE;
            }
        }
    }

    // No event occurred. Just return 0
    return _FALSE;
}

/////////////////////////////////////////////////////////////////////////////////
// FrameSync fine-tune routines
/////////////////////////////////////////////////////////////////////////////////

unsigned char TestSync(unsigned int offset)     // 0 - Success; Otherwise - Fail
{
    // Apply DCLK frequency setting
    RTDSetByte(DCLK_OFFSET_LSB_9A, (unsigned char)offset);
	RTDSetBit(DCLK_OFFSET_MSB_9B, 0xf0, (unsigned char)((offset >> 8) & 0x0f) | 0x20);

    Wait_For_Event(EVENT_DVS);          // Wait for Frame End

	RTDSetByte(STATUS0_01, 0x00);       // Clear Status

    Wait_For_Event(EVENT_DVS);          // Wait for Frame End
    Wait_For_Event(EVENT_DVS);          // Wait for Frame End

    RTDRead(STATUS0_01, 1, N_INC);      // Read status

    if (Data[0])
        RTDSetByte(STATUS0_01, 0x00);       // Clear Status

    // Input timing changed.
    if (Data[0] & 0x60)     return 1;

    // Save underflow/overflow information into Data[0]
    Data[0] &= 0x03;

    return 0;   // Success
}



//Returned value
// 0 : Succeed
// 1 : Fail
// 2 : Abort

unsigned char Frame_Sync(void)
{
    unsigned int    usBuffer, usDelta;
    unsigned char   ucFine, ucResult;

#if (FIX_LAST_DHT)
    unsigned int    usMax_Last_Line, usMin_Last_Line;
#endif

    //Disable the Fixed DVTOTAL & Last Line Length Fucntion
    RTDSetBit(FX_LST_LEN_H_5A, 0xef, 0x08);

    //Disable spread spectrum
    RTDSetBit(SPREAD_SPECTRUM_99, 0x0f, 0x00);
    RTDSetBit(DCLK_OFFSET_MSB_9B, 0xff, 0x20);

    //Read the DCLK offset
    RTDRead(DCLK_OFFSET_LSB_9A, 2, Y_INC);
    Data[2]     = Data[1] & 0x0f;
    Data[3]     = Data[0];
    usBuffer    = ((unsigned int*)Data)[1];

#if (VIDEO_CHIP != VDC_NONE)

    if ((SOURCE_VGA != (stGUD1.INPUT_SOURCE & 0x07)) && (SOURCE_DVI != (stGUD1.INPUT_SOURCE & 0x07)))
    {
        // Issac :
        // In order to enable full-scale spread spectrum, offset value must be within 30%~70% (1228~2866)
        while (usBuffer < (1228 + Search_Time * Offset_Step))
        {
            RTDRead(DPLL_M_D1, 2, Y_INC);
            RTDSetByte(DPLL_M_D1, Data[0] + 1);
            RTDSetByte(DPLL_N_D2, Data[1]);

            // Forster :
            // If the DCLK offset too small, then set the M_Code = M_Code + 1 and reculculate the offset
            // Original formula:
            // 24.576MHz * (M/N) * (1 - Old_Offset / 2^15) = 24.576MHz * (M+1)/N * (1 - (New_Offset /2^15))
            // => New_Offset = (2^15 + (M*Old_Offset)) / (M+1);            
            usBuffer    = (unsigned int)((unsigned long)(32768 + (unsigned long)(Data[0] + 2) * usBuffer) / (unsigned long)(Data[0] + 3));
        }
    }

#endif

// Issac :
// Offset_Step is the DCLK frequency step for searching frame-sync.
#define Offset_Step     24//32 
#define Search_Time     24//16

    // Search first satisfied DCLK setting for frame-sync

    ucResult    = 0x00;
    ucFine      = Search_Time;
    do
    {
        if (TestSync(usBuffer))  return 2;

        if (0 == Data[0])   break;

        if (Data[0] & 0x02)
            usBuffer    -= (ucResult & 0x01) ? (Offset_Step / 2) : Offset_Step;
        else
            usBuffer    += (ucResult & 0x02) ? (Offset_Step / 2) : Offset_Step;
        
        ucResult    = Data[0];
    }
    while (--ucFine);

    if (0x00 == ucFine)     return 1;

    if (0x00 == ucResult)
    {
        if (TestSync(usBuffer + Offset_Step))  return 2;
        ucResult    = Data[0] ? Data[0] : 0x01;
    }

    // Search most satisfied DCLK setting for frame-sync

    usDelta = usBuffer;
    ucFine  = 4;
    do
    {
        unsigned int usTemp = (ucResult & 0x01) ? usDelta + (Offset_Step / 2) : usDelta - (Offset_Step / 2);

        if (TestSync(usTemp))  return 2;
        if (Data[0])    break;

        usDelta = usTemp;
    }
    while (--ucFine);

    usDelta    = (usBuffer + usDelta) >> 1;

    if (TestSync(usDelta))  return 2;

    if (Data[0])    return 1;

    // Save satisfied DCLK offset for frame-sync
    usBuffer    = usDelta;

#undef Offset_Step
#undef Search_Time

#if (FIX_LAST_DHT == 0)

#if (SPREAD_SPECTRUM)

    //Enable the spread spectrum function
    RTDSetBit(SPREAD_SPECTRUM_99, 0x00, (DCLK_SPREAD_RANGE << 4));
    RTDSetBit(DCLK_OFFSET_MSB_9B, 0xff, 0x20);
    
    usDelta = usDelta + DCLK_OFFSET[DCLK_SPREAD_RANGE];

    if (TestSync(usDelta))  return 2;
	
    if (Data[0])
    {
        //Fine-tune DCLK offset 
        if (TestSync((Data[0] & 0x02) ? (usDelta - 1) : (usDelta + 1)))     return 2;

        if (Data[0] & 0x03)     return 1;   //Frame sync fail!
    }

#endif

    return 0;

#else   //If define non-zero FIX_LAST_DHT ....
 
    //Read the last line information , read back data equal to half last line length
    RTDRead(LAST_LINE_H_2C, 1, N_INC);
    usMax_Last_Line = (unsigned int)(Data[0] & 0xf8) << 2;

    RTDRead(LAST_LINE_L_26, 1, N_INC);
    usMax_Last_Line = usMax_Last_Line + (Data[0] / 8);

    //Read the last line information when frequency offset set one more step
    RTDSetByte(DCLK_OFFSET_LSB_9A, (unsigned char)(usDelta + 1));
    RTDSetBit(DCLK_OFFSET_MSB_9B, 0xf0, (unsigned char)(((usDelta + 1) >> 8) & 0x0f) | 0x20);

    Wait_For_Event(EVENT_IVS);
    Wait_For_Event(EVENT_IVS);

    RTDRead(LAST_LINE_H_2C, 1, N_INC);
    usMin_Last_Line = (unsigned int)(Data[0] & 0xf8) << 2;

    RTDRead(LAST_LINE_L_26, 1, N_INC);
    usMin_Last_Line = usMin_Last_Line + (Data[0] / 8);

    // Calculate the difference of last line when increase one offset step
    if (usMin_Last_Line < usMax_Last_Line)
        usMin_Last_Line = usMax_Last_Line - usMin_Last_Line;
    else
        usMin_Last_Line = (usDH_Total / 2) - usMin_Last_Line + usMax_Last_Line;
    
    if (FIX_LAST_DHT > usMax_Last_Line)
    {
        if ((FIX_LAST_DHT - usMax_Last_Line) > (usDH_Total / 4)) 
        {
            //Decreasing DCLK frequency to decrease last line length
            Data[0] = (unsigned int)(usMax_Last_Line + (usDH_Total / 2) - FIX_LAST_DHT) / usMin_Last_Line;
            usDelta = usDelta + Data[0];
        }
        else
        {   
            //Increasing DCLK frequency to increase last line length
            Data[0] = (unsigned int)(FIX_LAST_DHT - usMax_Last_Line) / usMin_Last_Line; 
            usDelta = usDelta - (Data[0] + 1);
        }
    }
    else
    {
        if ((usMax_Last_Line - FIX_LAST_DHT) > (usDH_Total / 4))
        {
            //Increasing DCLK frequency to increase last line length
            Data[0] = (unsigned int)(FIX_LAST_DHT + (usDH_Total / 2) - usMax_Last_Line) / usMin_Last_Line;
            usDelta = usDelta - (Data[0] + 1);
        }
        else
        {
            //Decreasing DCLK frequency to decrease last line length
            Data[0] = (usMax_Last_Line - FIX_LAST_DHT) / usMin_Last_Line; 
            usDelta = usDelta + Data[0];
        }
    }


    if (usDelta != usBuffer)
    {
        if (TestSync(usDelta))  return 2;

        if (Data[0])
        {
            // Last-line length fine-tune failed !! 
            // We cannot reach desired last-line length with safe frame-sync margin.
            // So we restore original setting and abort changing last-line length.

            usDelta = usBuffer;
            
            if (TestSync(usDelta))     return 2;
        }
        else
        {
            // Continue fine-tuning last-line length ....

            if (TestSync(usDelta + 4))  return 2;

            usDelta     = Data[0] ? usDelta - 2 : usDelta + 2;
            usBuffer    = usDelta;

            if (TestSync(usDelta))  return 2;
        }
    }

    // Read the last line information , read back data equal to half last line length
    RTDRead(LAST_LINE_H_2C, 1, N_INC);
    usMax_Last_Line = (unsigned int)(Data[0] & 0xf8) << 2;

    RTDRead(LAST_LINE_L_26, 1, N_INC);
    usMax_Last_Line = usMax_Last_Line + (Data[0] / 8);

    // Set desired last-line length
    RTDSetByte(FX_LST_LEN_L_59,(unsigned char)(usMax_Last_Line << 1));
    RTDSetBit(FX_LST_LEN_H_5A,0xe8,(unsigned char)((usMax_Last_Line >> 7) & 0x07));

    //Measure result of last 16 line of DVTotal, including the un-complete last line
    RTDRead(DV_ACT_END_34, 2, Y_INC);
    Data[2] = Data[1] & 0x07;
    Data[3] = Data[0];

    Data[4] = Data[1] >> 4;

    // Get Output_Active Height
    ((unsigned int *)Data)[1]   = ((unsigned int *)Data)[1] - DV_ACT_STA_POS;

    // Original Idea :
    // DVTotal  = Output_Active_Line * (Input_Total_Line / Input_Active_Line) 
    ((unsigned int *)Data)[0]   = (unsigned long)usVsync * ((unsigned int *)Data)[1] / usIPV_ACT_LEN;

    ((unsigned int *)Data)[1]   = (((unsigned int *)Data)[0] & 0xfff0) | Data[4];

    if (((unsigned int *)Data)[1] > (((unsigned int *)Data)[0] + 4))
        ((unsigned int *)Data)[1]   -= 0x10;
    else if (((unsigned int *)Data)[1] < (((unsigned int *)Data)[0] - 4))
        ((unsigned int *)Data)[1]   += 0x10;

    RTDSetByte(FIX_DVTOTAL_LSB_97, Data[3]);
    RTDSetByte(FIX_DVTOTAL_MSB_98, Data[2]);

    RTDSetBit(SPREAD_SPECTRUM_99, 0xfc, 0x02);  //Frequency Synthesis select N = 3
    RTDSetBit(DCLK_OFFSET_MSB_9B, 0xff, 0x20);

    // Issac :
    // In order to synthesis fixed last-line length,
    // we have to increase DCLK offset frequency by one step.
    usBuffer    = usBuffer - 1;

#if (SPREAD_SPECTRUM) 

    //Enable the spread spectrum function
    RTDSetBit(SPREAD_SPECTRUM_99, 0x0f, (DCLK_SPREAD_RANGE << 4));
    RTDSetBit(DCLK_OFFSET_MSB_9B,0xff,0x20);

    usBuffer    = usBuffer + DCLK_OFFSET[DCLK_SPREAD_RANGE];

#endif

    if (TestSync(usBuffer))     return 2;

    if (Data[0] & 0x03)
    {
        //Fine-tune DCLK offset 
        if (TestSync((Data[0] & 0x02) ? (usBuffer - 1) : (usBuffer + 1)))     return 2;

        return Data[0] ? 1 : 0;
    }
    else
    {
        // Enable the Fixed DVTOTAL & Last Line Lenghth Fucntion
        // only when everything is OK.

        
        // Issac :
        // To enable fixed last-line length function may cause OSD bouncing, 
        // so I decide to disable this function in frame-sync forever.
        // However, this function must be 1 in free-run mode

        //RTDSetBit(FX_LST_LEN_H_5A, 0xff, 0x10);
        
    }

    return 0;

#endif
}


void Adjust_I_Code(void)
{
    // Calculate the IHF in KHz
    ((unsigned int *)Data)[0] = (unsigned int)RTD_XTAL / usHsync; //Input Horizontal Frequency

    //Formula : I_Correction = CE * 2 * Fav(215634) * 100 / IHF / 2^(I_Code - 34)
    //          I_Code = 14; I_Code[13] = 0;
/*
    ucI_Code    = 14;
    Data[2]     = ((unsigned long)ucCE_Value * 43126800 / (unsigned long)((unsigned int*)Data)[0]) >> 20;
    Data[3]     = I_Correction ? I_Correction : (ucPE_Level ? (Correct_Amount - ucP_Corr) : ((ucP_Corr >> 2) + 10));
*/
    ucI_Code    = 14;
    Data[2]     = ((unsigned long)ucCE_Value * BEST_FAV_FREQ * 200 / (unsigned long)((unsigned int*)Data)[0]) >> 20;
    Data[3]     = I_Correction ? I_Correction : (ucPE_Level ? (Correct_Amount - ucP_Corr) : ((ucP_Corr >> 2) + 10));


    while(1)
    {
        if (Data[2] > Data[3])
        {
            Data[2]     = Data[2] >> 1;
            ucI_Code    = ucI_Code - 1;

            if (Data[2] <= Data[3])     break;
        }
        else
        {
            if ((Data[2] << 1) > Data[3])   break;
            
            Data[2]     = Data[2] << 1;
            ucI_Code    = ucI_Code + 1;
        }
    }

    // Judge if I_Code[13] set to 1 will more close to 155
    if ((unsigned char)((unsigned int)Data[2] * 3 / 2) <= Data[3])
    {
        ucI_Code |= 0x80;
    }
}

⌨️ 快捷键说明

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