📄 modectrl.c
字号:
m_dwBuff[0] = m_dwBuff[1];
EepPrivate.cAltID = m_cBuff[0];
}
}
}
}
if (EepPrivate.cAltID == 0xff)
return FALSE;
else
return TRUE;
}
void SetModeCaptureData(uWORD wHTotal, uWORD wHsst, uCHAR cVsst, uCHAR cVCO)
{
//~ Set PLL Freq. ~//
I2CWriteByte(TW803_P0, ADC_PLLDIV_H, (cVCO&0x01)<<6);
//~ Set PLL Divider 0x16[3~0],0x15[7~0] ~//
I2CWriteByte(TW803_P0, ADC_PLLDIV_H, ((I2CReadByte(TW803_P0, ADC_PLLDIV_H)&0xF0)|((uCHAR)(wHTotal>> 8))));
I2CWriteByte(TW803_P0, ADC_PLLDIV_L, (uCHAR)(wHTotal));
//~ Set VCO and Charge Pump ~//
I2CWriteByte(TW803_P0, ADC_VCOCP, cVCO&0xFE);
//~ Set ADC Capture HSync Back Proch 0x4C, 0x4D ~//
I2CWriteByte(TW803_P0, HSST_L, (uCHAR)wHsst);
I2CWriteByte(TW803_P0, HSST_H, (uCHAR)(wHsst>>8));
//~ Set ADC Capture VSync Back Proch 0x4E, 0x4F ~//
I2CWriteByte(TW803_P0, VSST_L, (uCHAR)cVsst);
I2CWriteByte(TW803_P0, VSST_H, (uCHAR)(cVsst >> 8));
//~ Set ADC Capture HSize 0x48, 0x49 ~//
I2CWriteByte(TW803_P0, HATVC_L, (uCHAR)m_pResolutionPtr->wHRes);
I2CWriteByte(TW803_P0, HATVC_H, (uCHAR)(m_pResolutionPtr->wHRes>>8));
//~ Set ADC Capture VSize 0x4A, 0x4B ~//
I2CWriteByte(TW803_P0, VATVR_L, (uCHAR)m_pResolutionPtr->wVRes);
I2CWriteByte(TW803_P0, VATVR_H, (uCHAR)(m_pResolutionPtr->wVRes>>8));
}
void GetModeCaptureData(void)
{
if(m_bAlt)
{
m_pAltHTotalPtr = &AltHTotals[EepPrivate.cAltID];
m_cBuff[0] = m_pAltHTotalPtr->cResID;
m_pResolutionPtr = &ResolutionTable[m_cBuff[0]];
EepPrivate.wHTotal = m_pAltHTotalPtr->wHTotal;
m_wHRes = m_pResolutionPtr->wHRes;
m_wVRes = m_pResolutionPtr->wVRes;
m_cBuff[0] = m_pAltHTotalPtr->cModeFlags; //VCO & Charge Pump
}
else
{
m_pModeDescriptorPtr = &ModeTable[EepPrivate.cModeID];
m_cBuff[0] = m_pModeDescriptorPtr->cResID;
m_pResolutionPtr = &ResolutionTable[m_cBuff[0]];
EepPrivate.wHTotal = m_pModeDescriptorPtr->wHTotal;
m_wHRes = m_pResolutionPtr->wHRes;
m_wVRes = m_pResolutionPtr->wVRes;
m_cBuff[0] = m_pModeDescriptorPtr->cModeFlags2; //VCO & Charge Pump
}
/* Ruby 2005 11 01
if (m_cModeStatus & ADCHIGHRANGE)
{
EepPrivate.wHTotal /= 2;
m_wHRes /= 2;
}
if (m_cModeStatus & ADCLOWRANGE)
{
EepPrivate.wHTotal *= 2;
m_wHRes *= 2;
}
*/
if(m_bInterlaced)
{
m_wVRes /= 2;
}
}
//Only used in analog inputs
void SetupMode(void)
{
if(!m_bDigital)
{
if(I2CReadByte(TW803_P0, 0x3F)&0x10)
I2CWriteByte(TW803_P0, 0x63, 0xCF);
else
I2CWriteByte(TW803_P0, 0x63, 0x40);
}
GetModeCaptureData();
//m_cBuff[0] saved VCO&Charge Pump
SetModeCaptureData(EepPrivate.wHTotal, FIXEDHSST, FIXEDVSST, m_cBuff[0]);
}
#define MINVRES 0x0000
#define MAXVRES 0xFFFF
BOOL GetVResolution(void)
{
//How to define THRESHOLD is a question mark, need confirm later.
McWaitReady(0x04, 0x08);
//start data
m_wBuff[0] = I2CReadByte(TW803_P0, POS_TB_H);
m_wBuff[0] <<= 8;
m_wBuff[0] |= I2CReadByte(TW803_P0, POS_TB_L);
//end data
m_wBuff[1] = I2CReadByte(TW803_P0, POS_BB_H);
m_wBuff[1] <<= 8;
m_wBuff[1] |= I2CReadByte(TW803_P0, POS_BB_L);
m_wVRes = m_wBuff[1] - m_wBuff[0] + 1;
return FALSE;
//How can I know the VRes is valid or not, inputs depend on input pattern
if (m_wVRes >= MINVRES && m_wVRes <= MAXVRES)
return TRUE;
else
return FALSE;
}
void GetModeInfo(uWORD *wVTotal, uWORD *wHPeriodCount, uDWORD dwFrameCnt)
{
uWORD wTemp;
int i;
//~ Get HSync period. ~//
I2CWriteByte(TW803_P0, 0x14, I2CReadByte(TW803_P0, 0x14)&0xEF); // Disable HSo source from PLL.
I2CWriteByte(TW803_P0, 0x16, I2CReadByte(TW803_P0, 0x16)|0x04); // Set PLL divider default value.
wTemp=0;
for(i=0; i<30; i++)
{
twdDelay1(10);
*wHPeriodCount = I2CReadByte(TW803_P0, HS_PERIOD_H);
*wHPeriodCount <<= 8;
*wHPeriodCount += I2CReadByte(TW803_P0, HS_PERIOD_L);
if((wTemp&0xFF00)==((*wHPeriodCount)&0xFF00))
break;
else
wTemp = *wHPeriodCount;
}
wTemp = dwFrameCnt * 32 * 10 / (*wHPeriodCount);
if(wTemp % 10 >= 9)
m_wBuff[0] = wTemp/10 + 1;
else
m_wBuff[0] = wTemp/10;
*wVTotal = m_wBuff[0];
I2CWriteByte(TW803_P0, 0x14, I2CReadByte(TW803_P0, 0x14)|(~0xEF)); // Enable HSo source from PLL.
}
// ================================================================
// McPolDetect Kevin Hsu. Mar. 2th, 2006
// ================================================================
// Description: Detect VSyn and HSyn polarity.
// Output: VGA sync. type.
// ---------------------------------------------------------------
uCHAR McPolDetect(void)
{
I2CWriteByte(TW803_P0, 0x10, I2CReadByte(TW803_P0, 0x10)|0x10);
m_cBuff[0] = I2CReadByte(TW803_P0, 0x10)>>6;
return m_cBuff[0]&0x03;
}
BOOL McWaitReady(uCHAR cEnableBit, uCHAR cReadyBit)
{
I2CWriteByte(TW803_P0, 0x50, I2CReadByte(TW803_P0, 0x50)|cEnableBit);
m_cBuff[0] = 0xFF;
while(m_cBuff[0]--)
{
twdDelay(1);
if(I2CReadByte(TW803_P0, 0x50)&cReadyBit)
break;
}
//Disable Enable bit for next sync coming in
I2CWriteByte(TW803_P0, 0x50, I2CReadByte(TW803_P0, 0x50)&~(cEnableBit|cReadyBit));
if(m_cBuff[0]) return TRUE;
else return FALSE;
}
// ================================================================
// GetInputVSyncXclkCnt Kevin Hsu. Mar. 7th, 2006
// ================================================================
// Description: Get VSync. period
// Output: dwVSyncCount : VSync period.
// ---------------------------------------------------------------
uDWORD GetInputVSyncXclkCnt(void)
{
uDWORD dwVSyncCount;
I2CWriteByte(TW803_P0, 0x14, I2CReadByte(TW803_P0, 0x14)&0xEF); // Disable HSo source from PLL.
m_dwBuff[0] = 0;
m_cBuff[1]=20;
RECHECK:
twdDelay(100);
m_cBuff[1]--;
m_cBuff[0] = I2CReadByte(TW803_P0, 0x50);
I2CWriteByte(TW803_P0, 0x50, m_cBuff[0] | 0x10); //Enable VSYNC counter
m_cBuff[0] = 100;
while(m_cBuff[0]--)
{
twdDelay(1);
if ((I2CReadByte(TW803_P0, 0x50)&0x20)) //V sync counter is done exit
break;
}
m_cBuff[0] = I2CReadByte(TW803_P0, 0x50);
m_cBuff[0] &= 0xCF; //Disable Auto Position
I2CWriteByte(TW803_P0, 0x50, m_cBuff[0]);
dwVSyncCount = I2CReadByte(TW803_P0, 0x53);
dwVSyncCount <<= 8;
dwVSyncCount |= I2CReadByte(TW803_P0, 0x52);
dwVSyncCount <<= 8;
dwVSyncCount |= I2CReadByte(TW803_P0, 0x51);
if((m_dwBuff[0]&0xFFFF00)!=(dwVSyncCount&0xFFFF00))
{
m_dwBuff[0] = dwVSyncCount;
if(m_cBuff[1])
goto RECHECK;
}
I2CWriteByte(TW803_P0, 0x14, I2CReadByte(TW803_P0, 0x14)|(~0xEF)); // Enable HSo source from PLL.
return dwVSyncCount;
}
void VGAScaling(void)
{
float x;
m_wBuff[0] = I2CReadByte(TW803_P0, 0x59);
m_wBuff[0] <<= 8;
m_wBuff[0] |= I2CReadByte(TW803_P0, 0x58);
switch(m_cDspPllSwitch)
{
case DSPPLL_100:x=DNDIV_100;break;
case DSPPLL_108:x=DNDIV_108;break;
case DSPPLL_120:x=DNDIV_120;break;
case DSPPLL_136:x=DNDIV_136;break;
case DSPPLL_140:x=DNDIV_140;break;
default:x=DNDIV_108;break;
}
if((float)EepPrivate.wHTotal*32/ m_wBuff[0]>x)
I2CWriteByte(TW803_P0, 0x70, I2CReadByte(TW803_P0, 0x70)|DCLKI_IS_FASTER); //Input clk faster, enable this bit
else
I2CWriteByte(TW803_P0, 0x70, I2CReadByte(TW803_P0,0x70)&~DCLKI_IS_FASTER); //Input clk slower, disable this bit
//Horizontal
m_wBuff[0] = (float)m_wHRes/VGAState.HDispSize * 0x2000;
I2CWriteByte(TW803_P0, SC_HOR_H1, (uCHAR)m_wBuff[0]);
I2CWriteByte(TW803_P0, SC_HOR_H2, (uCHAR)(m_wBuff[0]>>8));
//Vertical
if(!(m_cModeStatus & VSYNCOVERRANGE))
{
m_wBuff[0] = (float)m_wVRes/(VGAState.VDispSize) * 0x2000;
}
else
{
m_wBuff[0] = (float)m_wVRes/(VGAState.VDispSize) * 0x2000;
}
I2CWriteByte(TW803_P0, SC_VER_V1, (uCHAR)m_wBuff[0]);
I2CWriteByte(TW803_P0, SC_VER_V2, (uCHAR)(m_wBuff[0]>>8));
I2CWriteByte(TW803_P0, 0xDC, (uCHAR)VGAState.HDispSize);
I2CWriteByte(TW803_P0, 0xDD, (uCHAR)(VGAState.HDispSize>>8));
I2CWriteByte(TW803_P0, 0xDE, (uCHAR)VGAState.VDispSize);
I2CWriteByte(TW803_P0, 0xDF, (uCHAR)(VGAState.VDispSize>>8));
}
void VGASetPll(void)
{
switch(m_pModeDescriptorPtr->cModeFlags0 & DSPPLL_MASK)
{
case bDSPPLL_100:m_cDspPllSwitch=DSPPLL_100;break;
case bDSPPLL_108:m_cDspPllSwitch=DSPPLL_108;break;
case bDSPPLL_120:m_cDspPllSwitch=DSPPLL_120;break;
case bDSPPLL_136:m_cDspPllSwitch=DSPPLL_136;break;
case bDSPPLL_140:m_cDspPllSwitch=DSPPLL_140;break;
default:m_cDspPllSwitch=DSPPLL_108;break;
}
switch(m_cDspPllSwitch)
{
case DSPPLL_100:I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_100);break;
case DSPPLL_108:I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_108);break;
case DSPPLL_120:I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_120);break;
case DSPPLL_136:I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_136);break;
case DSPPLL_140:I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_140);break;
default: I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_108);break;
}
I2CWriteByte(TW803_P0, PLLDIV_I,DIDIV);
I2CWriteByte(TW803_P0, PLLDIV_O,0x10|DODIV);
/* m_cDspPllSwitch=DSPPLL_140;
I2CWriteByte(TW803_P0, PLLDIV_F,DFDIV_140);
I2CWriteByte(TW803_P0, PLLDIV_I,DIDIV);
I2CWriteByte(TW803_P0, PLLDIV_O,0x10|DODIV); */
}
// ================================================================
// VGACalOPTiming Kevin Hsu. Mar. 15th, 2006
// ================================================================
// Description: Calculate output timming.
// Output: None.
// ---------------------------------------------------------------
#define LB_WIDTH 1280 // For T103
void VGACalOPTiming(void)
{
uWORD wDVTotal, wDHTotal, wDVBILK, wTemp;
float Temp, DNDIV_40_Temp;
//~ Calculate PH_TOT and PV_TOT ~//
m_wBuff[0] = I2CReadByte(TW803_P0, 0x59);
m_wBuff[0] <<= 8;
m_wBuff[0] |= I2CReadByte(TW803_P0, 0x58);
m_wBuff[0] /= 32;
m_dwBuff[0] = I2CReadByte(TW803_P0, 0x53);
m_dwBuff[0] <<= 8;
m_dwBuff[0] |= I2CReadByte(TW803_P0, 0x52);
m_dwBuff[0] <<= 8;
m_dwBuff[0] |= I2CReadByte(TW803_P0, 0x51);
DNDIV_40_Temp = ((float)(I2CReadByte(TW803_P0, PLLDIV_F)+2)/(DIDIV+2)/DRDIV);
Temp = (27000000.0/m_dwBuff[0])*m_pModeDescriptorPtr->wHTotal*m_pModeDescriptorPtr->wVTotal;
if(Temp>(DNDIV_40_Temp*27000000.0))
I2CWriteByte(TW803_P0, 0x70, I2CReadByte(TW803_P0, 0x70)|0x20);
else
I2CWriteByte(TW803_P0, 0x70, I2CReadByte(TW803_P0, 0x70)&0xDF);
wDHTotal=(float)m_wBuff[0]*m_wVRes*DNDIV_40_Temp/VGAState.VDispSize;
wDVTotal=((DNDIV_40_Temp*(float)XCLK)/(float)(((float)(XCLK)/m_pModeDescriptorPtr->dwVFrameCount)*wDHTotal));
twdDelay(100);
m_dwBuff[1]=I2CReadByte(TW803_P0, 0x83);
m_dwBuff[1] <<= 8;
m_dwBuff[1]=I2CReadByte(TW803_P0, 0x82);
m_dwBuff[1] <<= 8;
m_dwBuff[1] |= I2CReadByte(TW803_P0, 0x81);
wDVBILK=m_dwBuff[1];
//~ Calculate back porch "DWHS" ~//
wTemp = ((wDHTotal - DWHSZ - DISP_DFLT_HSWIDTH)>>1);
I2CWriteByte(TW803_P0, 0xB0, wTemp);
I2CWriteByte(TW803_P0, 0xB1, wTemp>>8);//Horizontal back porch
I2CWriteByte(TW803_P0, 0xB2, DISP_DFLT_VDS);
I2CWriteByte(TW803_P0, 0xB3, DISP_DFLT_VDS>>8);//Vertical back porch
I2CWriteByte(TW803_P0, 0xB4,(uCHAR)(DWHSZ));
I2CWriteByte(TW803_P0, 0xB5,(uCHAR)(DWHSZ>>8));//Horizontal width
I2CWriteByte(TW803_P0, 0xB6,(uCHAR)(DWVSZ));
I2CWriteByte(TW803_P0, 0xB7,(uCHAR)(DWVSZ>>8));//Vertical height
I2CWriteByte(TW803_P0, 0xB8,(uCHAR) wDHTotal);
I2CWriteByte(TW803_P0, 0xB9,(uCHAR)(wDHTotal>>8));//Htotal
I2CWriteByte(TW803_P0, 0xBA,(uCHAR) wDVTotal);
I2CWriteByte(TW803_P0, 0xBB,(uCHAR)(wDVTotal>>8));//Vtotal
I2CWriteByte(TW803_P0, 0xBC,(uCHAR) DISP_DFLT_HSWIDTH);
I2CWriteByte(TW803_P0, 0xBD,(uCHAR)(DISP_DFLT_HSWIDTH>>8));//HSYNC Width
I2CWriteByte(TW803_P0, 0xBE,(uCHAR) DISP_DFLT_VSWIDTH);
I2CWriteByte(TW803_P0, 0xBF,(uCHAR)(DISP_DFLT_VSWIDTH>>8));//VSYNC Width
//~ Calculate line buffer ~//
if(H_Size>m_wHRes) // HSize in LB
m_wBuff[1] = m_wHRes;
else
m_wBuff[1] = H_Size;
if(LB_WIDTH >= (m_wBuff[1]<<1)) //PREFILL Size
Temp = 4.0;
else
{
Temp = 2.45 - ((float)(m_wVRes)/V_Size)/2.0;
if(LB_WIDTH>=m_wBuff[1])
Temp += (LB_WIDTH-m_wBuff[1])/m_wBuff[1];
else
Temp += 0;
}
m_wBuff[1] = ((Temp-(int)(Temp))*m_wHRes/EepPrivate.wHTotal + (int)(Temp))*m_wBuff[0]; // T_PerFill
m_wBuff[2] = ((DISP_DFLT_VSWIDTH+DISP_DFLT_VDS+I2CReadByte(TW803_P0, 0xDA))*wDHTotal + DISP_DFLT_HSWIDTH + wTemp + I2CReadByte(TW803_P0, 0xD8))/DNDIV_40_Temp; //VBo_Xclk
m_dwBuff[1] =I2CReadByte(TW803_P0, 0x53);
m_dwBuff[1] <<= 8;
m_dwBuff[1] |=I2CReadByte(TW803_P0, 0x52);
m_dwBuff[1] <<= 8;
m_dwBuff[1] |= I2CReadByte(TW803_P0, 0x51);
Temp = ((m_dwBuff[1]+1)*DNDIV_40_Temp * m_wVRes)/((m_dwBuff[1]/m_wBuff[0]) *VGAState.VDispSize); // Ideal PH_TOT
m_wBuff[0] = (Temp - (float)wDHTotal)*VGAState.VDispSize/DNDIV_40_Temp/2;
//~ VSDLY_XCLK = T_PreFill + VBi_XClk + (End_LB_Short/2) - VBo_Xclk ~//
m_dwBuff[0] = m_wBuff[1] + wDVBILK +m_wBuff[0];
wTemp = m_dwBuff[0]-m_wBuff[2];
I2CWriteByte(TW803_P0, 0x84, wTemp);
I2CWriteByte(TW803_P0, 0x85, wTemp>>8);//line buffer delay XClk
m_dwBuff[0]=(wDVTotal-m_wVRes-DWVSST-DISP_DFLT_VSWIDTH)*wDHTotal;
m_dwBuff[1]=wTemp*DNDIV_40_Temp;
if(m_dwBuff[0]<m_dwBuff[1])
I2CWriteByte(TW803_P0, 0x70, I2CReadByte(TW803_P0, 0x70)|0x20);
else
I2CWriteByte(TW803_P0, 0x70, I2CReadByte(TW803_P0, 0x70)&0xDF);
}
BOOL SyncChangDect()
{
//~ Detect V/H Sync changed. ~//
if(I2CReadByte(TW803_P0, 0x32)&0x0C)
{
ClosePanel(0x10,0xFF,0x40);
if(!SrcAnalogProcess())
{
I2CWriteByte(TW803_P0, 0x32, 0x0F);
return FALSE;
}
OpenPanel();
I2CWriteByte(TW803_P0, 0x32, 0x0C);
return TRUE;
}
//~ Detect if V/H Sync lost. ~//
if((I2CReadByte(TW803_P0, 0x32)&0x03)==0x03)
{
ClosePanel(0x10,0xFF,0x40);
I2CWriteByte(TW803_P0, 0x32, 0x0F);
return FALSE;
}
return TRUE;
}
BOOL SrcAnalogProcess(void)
{
Sync_Mode_Detect();
if(!ModeDetect()) return FALSE;
SetupMode();
VGASetPll();
AutoPositionAdj(0xF0);
VGAState.HDispSize = H_Size;
VGAState.VDispSize = V_Size;
VGAState.fHDispSize = H_Size;
VGAState.fVDispSize = V_Size;
VGAState.AdjHATV = m_wHRes;
VGAState.AdjVATV = m_wVRes;
VGACalOPTiming();
VGAScaling();
OpenPanel();
I2CWriteByte(TW803_P0, INT_STATUS, 0x3f);
I2CWriteByte(TW803_P0, 0xE2, 0x11);
AutoPhaseAdj();
if(!(m_cModeStatus&(DOSMODE|NORMALMODE))) //(OVERRANGE |SYNCERROR))
{
return FALSE;
}
I2CWriteByte(TW803_P0, INT_STATUS, 0x3f);
I2CWriteByte(TW803_P0, 0xE2, 0x11);
VGAState.PositionH = I2CReadByte(TW803_P0, 0x45);
VGAState.ADCVBaPorch = I2CReadByte(TW803_P0, VSST_L)|(I2CReadByte(TW803_P0, VSST_H)<<8);
VGAState.ADCHBaPorch = I2CReadByte(TW803_P0, HSST_L)|(I2CReadByte(TW803_P0, HSST_H)<<8);
VGAState.HATV = I2CReadByte(TW803_P0, HATVC_L)|(I2CReadByte(TW803_P0, HATVC_H)<<8);
VGAState.VATV = I2CReadByte(TW803_P0, VATVR_L)|(I2CReadByte(TW803_P0, VATVR_H)<<8);
return TRUE;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -