📄 framesync.c
字号:
//----------------------------------------------------------------------------------------------------
// ID Code : FrameSync.c No.0000
// Update Note :
//
//----------------------------------------------------------------------------------------------------
#define __FRAMESYNC__
#include "..\Header\Include.h"
//x.hu, for video frame sync counter
BYTE ucVideoSyncCnt=0;
//--------------------------------------------------
// Description : Detect frame sync status
// Input Value : None
// Output Value : Return _FALSE if frame sync is ok, _TRUE while PLL mislock, buffer underflow/overflow
//--------------------------------------------------
bit CFrameSyncDetect(void)
{
if(GET_POWERSTATUS() && GET_MODESTABLE())
{
CScalerRead(_STATUS0_02, 1, pData, _NON_AUTOINC);
if((pData[0] & 0x03) == 0)
{
if((pData[0] & 0x80) == 0)
{
return _FALSE;
}
}
}
//x.hu, for video on 5150+2013B
//don't mask this, because sometimes the image can't display correctly.
// 20050627
/*if(GET_INPUTSOURCE_TYPE() == _SOURCE_VIDEO8)
return _FALSE;
//if(GET_INPUTSOURCE_TYPE() == _SOURCE_VIDEO8) {
if (GET_INPUTPORT_TYPE(stSystemData.InputSource) == _VIDEO_AV_PORT || \
GET_INPUTPORT_TYPE(stSystemData.InputSource) == _VIDEO_AV2_PORT ) {
if (ucVideoSyncCnt++ < 10) {
return _FALSE;
}
else {
ucVideoSyncCnt = 0;
CLR_FRAMESYNCSTATUS();
return _TRUE;
}
}
*/ // x.hu, test to mask this, may be updated
CLR_FRAMESYNCSTATUS();
return _TRUE;
}
//--------------------------------------------------
// Description : Finetune last line problem
// Input Value : Dclk offset
// Output Value : Return _TRUE if there is no timing change
//--------------------------------------------------
bit CFrameSyncLastLineFinetune(WORD *pDelta)
{
#if(_LAST_LINE_FINETUNE == _LAST_LINE_METHOD_0)
WORD dvtotal;
LWORD dclktotal = 0;
CScalerSetByte(_LAST_LINE_H_44, 0x00);
if(CFrameSyncTestSync(*pDelta)) return _FALSE;
CScalerRead(_LAST_LINE_H_44, 2, pData, _AUTOINC);
dclktotal = ((WORD)(pData[0] & 0x0f) << 8) | pData[1];
CScalerSetByte(_LAST_LINE_H_44, 0x80);
CTimerDelayXms(40);
CScalerRead(_LAST_LINE_H_44, 2, pData, _AUTOINC);
dvtotal = ((WORD)(pData[0] & 0x0f) << 8) | pData[1];
dclktotal = dclktotal + (LWORD)stDisplayInfo.DHTotal * (dvtotal + 1 - stDisplayInfo.DVHeight);
dvtotal = dclktotal / 1280;
dvtotal = dclktotal - ((LWORD)dvtotal * 1280);
*pDelta = (dvtotal > (1280 - 128)) ? (*pDelta + 3) : ((dvtotal < 128) ? (*pDelta - 3) : *pDelta);
return _TRUE;
#endif
#if(_LAST_LINE_FINETUNE == _LAST_LINE_METHOD_1)
#endif
#if(_LAST_LINE_FINETUNE == _LAST_LINE_METHOD_2)
#endif
}
//--------------------------------------------------
// Description : Finetune Dclk offset for spread spectrum
// Input Value : Dclk offset
// Output Value : Return _FALSE if there is no timing change
//--------------------------------------------------
BYTE CFrameSyncSpreadSpectrumFinetune(WORD *pDelta)
{
//Enable the spread spectrum function
CAdjustSpreadSpectrumRange(_DCLK_SPREAD_RANGE);
*pDelta = *pDelta + tDCLK_OFFSET[_DCLK_SPREAD_RANGE];
if(CFrameSyncTestSync(*pDelta)) return 2;
if(pData[0])
{
//Fine-tune DCLK offset
if(CFrameSyncTestSync((pData[0] & 0x02) ? (*pDelta - 1) : (*pDelta + 1))) return 2;
if(pData[0] & 0x03) return 1; //Frame sync fail!
}
return 0;
}
//--------------------------------------------------
// Description : Calculate the suitable framesync point
// Input Value : None
// Output Value : Return Dclk offset
//--------------------------------------------------
WORD CFrameSyncFastDo(void)
{
LWORD aclkcnt = 0;
LWORD offset;
BYTE mcode, div;
CScalerSetBit(_SYNC_SELECT_47, ~(_BIT1 | _BIT0), 0x00);
CScalerSetBit(_MEAS_HS_PERIOD_H_52, ~(_BIT7 | _BIT5), (_BIT7 | _BIT5));
CTimerDelayXms(60);
CScalerSetBit(_MEAS_HS_PERIOD_H_52, ~_BIT6, _BIT6);
CScalerSetByte(_MEAS_ACTIVE_REGION_59, 0x00);
pData[0] = 0;
CScalerRead(_MEAS_ACTIVE_REGION_59, 3, &pData[1], _NON_AUTOINC);
aclkcnt = ((LWORD *)pData)[0];
CScalerSetBit(_MEAS_HS_PERIOD_H_52, ~(_BIT7 | _BIT5), 0x00);
CScalerRead(_DPLL_M_AE, 1, &mcode, _NON_AUTOINC);
mcode += 2;
CScalerRead(_DPLL_N_AF, 1, &div, _NON_AUTOINC);
div = 0x01 << ((div & 0x30) >> 4);
offset = (LWORD)32768 * div * 2 * _DPLL_N_CODE * stDisplayInfo.DHTotal / aclkcnt * stDisplayInfo.DVHeight / mcode;
offset = 32768 - offset;
CScalerSetBit(_SYNC_SELECT_47, ~(_BIT1 | _BIT0), _BIT1);
return (WORD)offset;
}
//--------------------------------------------------
// Description : Apply Dclk frequency and get the overflow/underflow information
// Input Value : Dclk offset
// Output Value : Return _FALSE if there is no timing change
//--------------------------------------------------
bit CFrameSyncTestSync(WORD usOffset)
{
CScalerSetBit(_SYNC_SELECT_47, ~_BIT0, 0x00);
CAdjustSyncProcessorMeasureStart();
// Apply Dclk frequency setting
CAdjustDclkOffset(usOffset);
CScalerSetByte(_STATUS0_02, 0x00); // Clear Status
CTimerWaitForEvent(_EVENT_DVS); // Wait for Frame End
CTimerWaitForEvent(_EVENT_DVS); // Wait for Frame End
if(CModeIsChange())
return _TRUE;
CScalerRead(_STATUS0_02, 1, pData, _NON_AUTOINC); // Read status
// Input timing changed
if (pData[0] & 0x60)
return _TRUE;
// Save underflow/overflow information into pData[0]
pData[0] &= 0x03;
return _FALSE; // Success
}
//--------------------------------------------------
// Description : Adjust Dclk offset to meet frame sync
// Input Value : None
// Output Value : Return 0 if sucess
//--------------------------------------------------
BYTE CFrameSyncDo(void)
{
WORD buffer, delta;
BYTE fine, result = 0;
// Disable the Fixed DVTOTAL & Last Line Length Fucntion
CScalerSetBit(_FIXED_LAST_LINE_CTRL_BB, ~_BIT1, 0x00);
// Disable spread spectrum
CAdjustSpreadSpectrumRange(0);
// Fast Framesync method
delta = CFrameSyncFastDo();
if(CFrameSyncTestSync(delta)) return 2;
if(pData[0] == 0)
{
result |= _BIT0;
if(CFrameSyncTestSync(delta + _OFFSET_STEP)) return 2;
if(pData[0] == 0) result |= _BIT1;
if(CFrameSyncTestSync(delta - _OFFSET_STEP)) return 2;
if(pData[0] == 0) result |= _BIT2;
if(result == (_BIT0 | _BIT1))
delta += _OFFSET_STEP / 2;
else if(result == (_BIT0 | _BIT2))
delta -= _OFFSET_STEP / 2;
}
if(result == 0) // Fast search fail, do iteration search
{
// Read the DCLK offset
CScalerRead(_DCLK_FINE_TUNE_OFFSET_MSB_B5, 2, pData, _AUTOINC);
buffer = (((WORD)pData[0] & 0x0f) << 8) | pData[1];
// Search first satisfied DCLK setting for frame-sync
result = 0x00;
fine = _SEARCH_TIME;
do
{
if(CFrameSyncTestSync(buffer)) return 2;
if(pData[0] == 0) break;
if(pData[0] & 0x02)
buffer -= (result & 0x01) ? (_OFFSET_STEP / 2) : _OFFSET_STEP;
else
buffer += (result & 0x02) ? (_OFFSET_STEP / 2) : _OFFSET_STEP;
result = pData[0];
}
while(--fine);
if(fine == 0x00) return 1;
// If default offset is OK....
if(result == 0x00)
{
if(CFrameSyncTestSync(buffer + _OFFSET_STEP)) return 2;
result = pData[0] ? pData[0] : 0x01;
}
// Search most satisfied DCLK setting for frame-sync
delta = buffer;
fine = 4;
do
{
WORD temp = (result & 0x01) ? delta + (_OFFSET_STEP / 2) : delta - (_OFFSET_STEP / 2);
if(CFrameSyncTestSync(temp)) return 2;
if(pData[0]) break;
delta = temp;
}
while(--fine);
delta = (buffer + delta) >> 1;
}
if(!CFrameSyncLastLineFinetune(&delta)) return 2;
result = CFrameSyncSpreadSpectrumFinetune(&delta);
if(result != 0) return result;
SET_FRAMESYNCSTATUS();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -