📄 frame_sync.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 + -