📄 framesync.c
字号:
//----------------------------------------------------------------------------------------------------
// ID Code : FrameSync.c No.0000
// Update Note :
//
//----------------------------------------------------------------------------------------------------
#define __FRAMESYNC__
#include "Core\Header\Include.h"
//--------------------------------------------------
// 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] & 0x83) == 0))
{
return _FALSE;
}
else
{
if((_GET_INPUT_SOURCE() == _SOURCE_YPBPR)||
(_GET_INPUT_SOURCE() == _SOURCE_VGA))
{
if(pData[0]&0x80)
return _FALSE;
}
if(pData[0]&0x80)
;//DebugPrintf("\n FS Detect(Adc pll) %c",0x20);
if(pData[0]&0x02)
;//DebugPrintf("\n FS Detect(overflow) %c",0x20);
if(pData[0]&0x01)
;//DebugPrintf("\n FS Detect(underflow) %c",0x20);
CLR_MODESTABLE();
CLR_FRAMESYNCSTATUS();
// Software reset for scaler
//CScalerSetBit(_HOST_CTRL_01, ~_BIT0, _BIT0);
//CTimerDelayXms(20);
//CScalerSetBit(_HOST_CTRL_01, ~_BIT0, 0x00);
//CScalerInitial();
return _TRUE;
}
/*frank if((pData[0] & 0x03) == 0)
{
if((pData[0] & 0x80) == 0)
{
return _FALSE;
}
}*/
}
return _FALSE;
/*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_NONE)
if(CFrameSyncTestSync(*pDelta))
return _FALSE;
else
return _TRUE;
#endif
#if(_LAST_LINE_FINETUNE == _LAST_LINE_METHOD_0)
// Formula: Tne DEN End to DEN Start Length must be (1280*N)
// Samsung's Panels.
WORD dvtotal;
DWORD dclktotal = 0;
// CScalerSetDataPortByte(_DISP_ACCESS_PORT_2A, _DISP_NEW_DV_CTRL_22, 0x00);
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 + (DWORD)stDisplayInfo.DHTotal * (dvtotal + 1 - stDisplayInfo.DVHeight);
//dvtotal = dclktotal / 1280;
//dvtotal = dclktotal - ((DWORD)dvtotal * 1280);
//*pDelta = (dvtotal > (1280 - 128)) ? (*pDelta + 3) : ((dvtotal < 128) ? (*pDelta - 3) : *pDelta);
dvtotal = dclktotal / Panel[ucPanelSelect]->DHWidth;
dvtotal = dclktotal - ((DWORD)dvtotal * Panel[ucPanelSelect]->DHWidth);
*pDelta = (dvtotal > (Panel[ucPanelSelect]->DHWidth - 128)) ? (*pDelta + 3) : ((dvtotal < 128) ? (*pDelta - 3) : *pDelta);
// CScalerSetDataPortByte(_DISP_ACCESS_PORT_2A, _DISP_NEW_DV_CTRL_22, 0xa0);
return _TRUE;
#endif
#if(_LAST_LINE_FINETUNE == _LAST_LINE_METHOD_1)
// Formula: Tne DEN End to DEN Start Length must be (4096*N + 128)
// CPT's Panels.
WORD dvtotal;
DWORD dclktotal = 0;
CScalerSetDataPortByte(_DISP_ACCESS_PORT_2A, _DISP_NEW_DV_CTRL_22, 0x00);
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 + (DWORD)stDisplayInfo.DHTotal * (dvtotal + 1 - stDisplayInfo.DVHeight) - 128;
dvtotal = dclktotal / 4096;
dvtotal = dclktotal - ((DWORD)dvtotal * 4096);
*pDelta = (dvtotal > (4096 - 128)) ? (*pDelta + 3) : ((dvtotal < 128) ? (*pDelta - 3) : *pDelta);
#if(_NEW_DV_CTRL_ENABLE)
CScalerSetDataPortByte(_DISP_ACCESS_PORT_2A, _DISP_NEW_DV_CTRL_22, 0xa0);
#endif
return _TRUE;
#endif
#if(_LAST_LINE_FINETUNE == _LAST_LINE_METHOD_2)
#if 1//eric 0706
// Formula: Fixed to target last line pixels
DWORD dclktotal;
DWORD dclktarget;
WORD dvtotal;
WORD lastlinepixels;
SWORD offsetnew;
// Turn off new timing method
CScalerSetDataPortByte(_DISP_ACCESS_PORT_2A, _DISP_NEW_DV_CTRL_22, 0x00);
// Measure DVTotal
CScalerSetByte(_LAST_LINE_H_44, 0x80);
if(CFrameSyncTestSync(*pDelta))
return _FALSE;
CScalerRead(_LAST_LINE_H_44, 2, pData, _AUTOINC);
dvtotal = ((WORD)(pData[0] & 0x0f) << 8) | pData[1];
// Measure last line clock numbers
CScalerSetByte(_LAST_LINE_H_44, 0x00);
if(CFrameSyncTestSync(*pDelta)) return _FALSE;
CScalerRead(_LAST_LINE_H_44, 2, pData, _AUTOINC);
lastlinepixels = ((WORD)(pData[0] & 0x0f) << 8) | pData[1];
// Calculate total display clock numbers in a frame
dclktotal = (DWORD)stDisplayInfo.DHTotal * dvtotal + lastlinepixels;
// Calculate mininum path of target clock numbers
if(lastlinepixels > _LAST_LINE_TARGET){
if((lastlinepixels - _LAST_LINE_TARGET) > (stDisplayInfo.DHTotal / 2))
dclktarget = (DWORD)stDisplayInfo.DHTotal * (dvtotal + 1) + _LAST_LINE_TARGET; // +
else
dclktarget = (DWORD)stDisplayInfo.DHTotal * (dvtotal) + _LAST_LINE_TARGET; // -
}
else{
if((_LAST_LINE_TARGET - lastlinepixels) > (stDisplayInfo.DHTotal / 2))
dclktarget = (DWORD)stDisplayInfo.DHTotal * (dvtotal - 1) + _LAST_LINE_TARGET; // -
else
dclktarget = (DWORD)stDisplayInfo.DHTotal * (dvtotal) + _LAST_LINE_TARGET; // +
}
// Calculate and apply new offset
offsetnew = (((SDWORD)dclktotal - (SDWORD)dclktarget) * ((SDWORD)32768 - (SDWORD)*pDelta)) * 2 / (SDWORD)dclktotal;
offsetnew = (offsetnew / 2) + ((offsetnew > 0) ? (offsetnew & 0x01) : -(offsetnew & 0x01));
offsetnew = offsetnew + *pDelta;
if(CFrameSyncTestSync(offsetnew))
return _FALSE;
// Check underflow/overflow. If failed, try another side.
if(pData[0]){
if(pData[0] & 0x02)
dclktarget = dclktarget + stDisplayInfo.DHTotal;
else
dclktarget = dclktarget - stDisplayInfo.DHTotal;
offsetnew = (((SDWORD)dclktotal - (SDWORD)dclktarget) * ((SDWORD)32768 - (SDWORD)*pDelta)) * 2 / (SDWORD)dclktotal;
offsetnew = (offsetnew / 2) + ((offsetnew > 0) ? (offsetnew & 0x01) : -(offsetnew & 0x01));
offsetnew = offsetnew + *pDelta;
if(CFrameSyncTestSync(offsetnew)) return _FALSE;
}
*pDelta = offsetnew;
return _TRUE;
#else
// Formula: Last line limit.
CScalerSetByte(_DISP_NEW_DV_CTRL_22, 0x00);
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];
*pDelta = (dclktotal > 1280) ? (*pDelta + 3) : ((dclktotal > 640) ? (*pDelta - 3) : *pDelta);
return _TRUE;
#endif
#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)
{
DWORD aclkcnt = 0;
DWORD offset;
BYTE mcode, div;
CScalerSetBit(_SYNC_SELECT_47, ~(_BIT1 | _BIT0), 0x00); // Measure input active region by xtal clk
//Enable active region measure Ken
CScalerSetBit(_STABLE_PERIOD_H_50, ~_BIT4, _BIT4);
CAdjustSyncProcessorMeasureStart();
if(CTimerPollingEventProc(60, CMiscModeMeasurePollingEvent))
{
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 = ((DWORD *)pData)[0];
CScalerSetBit(_MEAS_HS_PERIOD_H_52, ~(_BIT7 | _BIT5), 0x00);
CScalerPageSelect(_PAGE1);
CScalerRead(_P1_DPLL_M_BF, 1, &mcode, _NON_AUTOINC);
mcode += 2;
CScalerRead(_P1_DPLL_N_C0, 1, &div, _NON_AUTOINC);
div = 0x01 << ((div & 0x30) >> 4); //divider value
offset = (DWORD)32768 * div * 2 * _DPLL_N_CODE * stDisplayInfo.DHTotal / aclkcnt * stDisplayInfo.DVHeight / mcode;
offset = 32768 - offset;
//CScalerSetBit(_SYNC_SELECT_47, ~(_BIT1 | _BIT0), _BIT1);
}
else
{
offset = 0xffff;
}
CScalerSetBit(_STABLE_PERIOD_H_50, ~_BIT4, 0x00);
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
//CTimerWaitForEvent(_EVENT_DVS); //V400 modify for Interlace mode
CTimerWaitForEvent(_EVENT_IVS); // Wait for Frame End
CTimerWaitForEvent(_EVENT_IVS); // Wait for Frame End
CTimerWaitForEvent(_EVENT_IVS); // Wait for Frame End
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;
// Read the DCLK offset
CScalerPageSelect(_PAGE1);
CScalerRead(_P1_DCLK_FINE_TUNE_OFFSET_MSB_C4, 2, pData, _AUTOINC);
buffer = (((WORD)pData[0] & 0x0f) << 8) | pData[1];
// Disable the Fixed DVTOTAL & Last Line Length Fucntion
CScalerSetBit(_P1_EVEN_FIXED_LAST_LINE_CTRL_CA, ~_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;
}
//DebugPrintf("\nresult = 0x%x", result);
if(result == 0) // Fast search fail, do iteration search
{
// Apply Dclk frequency setting
CAdjustDclkOffset(buffer);
// 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; // underflow
else
buffer += (result & 0x02) ? (_OFFSET_STEP / 2) : _OFFSET_STEP; // overflow
result = pData[0]; // 穦纗
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -