📄 autofunc.c
字号:
#define _AUTOFUNC_C_
#include <math.h>
#include "types.h"
#include "board.h"
#if VGA_ENABLE
#include "global.h"
#include "ms_reg.h"
#include "adjust.h"
#include "ms_rwreg.h"
#include "misc.h"
#include "DEBUG.h"
#include "power.h"
#include "AutoFunc.h"
#include "detect.h"
#include "panel.h"
#include "mstar.h"
///////////////////////////////////////////////////////////////////////////////
// <Function>: msAutoGeometry
//
// <Description>: Auto geometry for analog port.
///////////////////////////////////////////////////////////////////////////////
#define ThresholdData 0x60
#if(ENABLE_WATCH_DOG)
void Delay1ms_WatchDog( WORD wValue )
{
WatchDogClear();
while( wValue )
{
if( wValue > 500 )
{
Delay1ms(500);
wValue -= 500;
WatchDogClear();
}
else
{
Delay1ms(wValue);
wValue = 0;
}
}
WatchDogClear();
}
#endif
BOOL msAutoGeometry(AutoTuneType AutoParam)
{
BYTE ucBank; // bank buffer
BYTE ucBk0_01;
BYTE ucBk1_01;
BYTE ucVSyncTime; // VSync time
ucBank = msReadByte(BK0_00_REGBK); // store bank
// Disable DB buffer
msWriteByte( BK0_00_REGBK, REG_BANK1_ADC_ACE_MCU ); // bank 1
ucBk1_01 = msReadByte( BK1_01_DBFC);
msWriteByte( BK1_01_DBFC, 0x00 );
msWriteByte( BK0_00_REGBK, REG_BANK_SCALER ); // bank 0
ucBk0_01 = msReadByte( BK0_01_DBFC);
msWriteByte( BK0_01_DBFC, 0x00 );
msAdjustAdcGain(0x80, 0x80, 0x80);
msAdjustAdcOffset(0x90, 0x90, 0x90);
ucVSyncTime = msCalculateVSyncTime(); // get VSync time
// auto position valid data theshold
if (AutoParam & AUTO_TUNE_VALID_DATA)
if (msAutoSetValidData(ucVSyncTime+3) == FALSE) AutoParam = AUTO_TUNE_NULL;
else // fixed valid data
msWriteByte(BK0_CC_AOVDV, ThresholdData); // set valid data threshold
// auto horizontal total
if (AutoParam & AUTO_TUNE_FREQ)
if (msAutoTuneHTotal(ucVSyncTime*2) == FALSE) AutoParam = AUTO_TUNE_NULL;
// auto phase
if (AutoParam & AUTO_TUNE_PHASE)
if (msAutoTunePhase(ucVSyncTime+3) == FALSE) AutoParam = AUTO_TUNE_NULL;
// auto position
if (AutoParam & AUTO_TUNE_POSITION)
if (msAutoTunePosition(ucVSyncTime) == FALSE) AutoParam = AUTO_TUNE_NULL;
msWriteByte(BK0_00_REGBK, REG_BANK_SCALER); // select register bank scaler
msWriteByte(BK0_C8_ATGCTRL, 0x11); // enable auto gain function
// auto RGB offset
if (AutoParam & AUTO_TUNE_RGB_OFFSET)
if (msAutoTuneOffset(ucVSyncTime) == FALSE)
AutoParam= AUTO_TUNE_NULL; // auto-tune ADC offset
// auto RGB gain
if (AutoParam & AUTO_TUNE_RGB_GAIN)
if (msAutoTuneGain(ucVSyncTime) == FALSE)
AutoParam= AUTO_TUNE_NULL; // auto-tune ADC gain
msWriteByte(BK0_00_REGBK, REG_BANK_SCALER); // select register bank scaler
msWriteByte(BK0_C8_ATGCTRL, 0x00); // disable auto gain function
msWriteByte(BK0_CC_AOVDV, 0x40); // set valid data threshold
msAdjustAdcGain(g_PcSetting.AdcRedGain, g_PcSetting.AdcGreenGain, g_PcSetting.AdcBlueGain);
msAdjustAdcOffset(g_PcSetting.AdcRedOffset, g_PcSetting.AdcGreenOffset, g_PcSetting.AdcBlueOffset);
// Recover DB buffer setting
msWriteByte( BK0_01_DBFC, ucBk0_01);
msWriteByte( BK0_00_REGBK, REG_BANK1_ADC_ACE_MCU ); // bank 1
msWriteByte( BK1_01_DBFC, ucBk1_01);
msWriteByte(BK0_00_REGBK, ucBank); // recovery bank
if (AutoParam) // success
return TRUE;
else // fail
{
putstr("\r\nAuto failed");
return FALSE;
}
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: msAutoCheckSyncLoss
//
// <Description>: Check Sync loss status.
//
// <Returns> :
///////////////////////////////////////////////////////////////////////////////
BOOL msAutoCheckSyncLoss(void)
{
//#if UseINT
if (g_bInputTimingChangeFlag)
{
#ifdef AUTO_DEBUG_EN
putstr("\r\ng_bInputTimingChange=1");
printf("\r\nVt=%x",msGetVerticalTotal());
#endif
return TRUE;
}
//#endif
// check H/VSync change
if ((abs(g_wHorizontalPeriod - msGetHorizontalPeriod()) > HPeriod_Torlance) ||
(abs(g_wVerticalTotal - msGetVerticalTotal()) > VTotal_Torlance))
{
SrcFlags|= bHSyncLoss;
SrcFlags|= bVSyncLoss;
g_bInputTimingChangeFlag = 1;
#ifdef AUTO_DEBUG_EN
printf("\r\nHP=%x",msGetHorizontalPeriod());
printf("\r\nVt=%x",msGetVerticalTotal());
#endif
return TRUE;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: msAutoSetValidData
//
// <Description>: Auto set valid data value.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucVSyncTime - In - VSync time
///////////////////////////////////////////////////////////////////////////////
BOOL msAutoSetValidData(BYTE ucVSyncTime)
{
BYTE ucValidData; // valide dataa value
BYTE ucPhaseIndex; // phase index
WORD wComapreHPos; // compare horizontal position
BYTE ucBank = msReadByte( BK0_00_REGBK);
msWriteByte( BK0_00_REGBK, REG_BANK_SCALER );
for (ucValidData=0x04; ucValidData!=0x10; ucValidData++)
{
msWriteByte(BK0_CC_AOVDV, ucValidData << 4); // set valid data threshold
msAdjustAdcPhase(0x00); // set phase
Delay1ms_WatchDog(ucVSyncTime);
wComapreHPos = msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime); // horizontal position
for (ucPhaseIndex=0x01; ucPhaseIndex!=0x10; ucPhaseIndex++)
{
msAdjustAdcPhase(ucPhaseIndex * 4); // set phase
Delay1ms_WatchDog(ucVSyncTime);
if (abs(wComapreHPos - msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime)) > 3) // check lose data
break;
if (msAutoCheckSyncLoss()) // check Sync change
{
msWriteByte( BK0_00_REGBK, ucBank );
#ifdef AUTO_DEBUG_EN
putstr("\r\nmsAutoSetValidData() failed");
#endif
return FALSE;
}
} // for
if (ucPhaseIndex == 0x10)
break;
} // for
msWriteByte( BK0_00_REGBK, ucBank );
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: autoWaitStatusReady
//
// <Description>: Wait for status ready.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucRegIndex - In - Register index
// ucRegMask - In - Status mask
///////////////////////////////////////////////////////////////////////////////
void msAutoWaitStatusReady(BYTE ucRegIndex, BYTE ucRegMask)
{
WORD wDummy = 250; // loop dummy
#if ENABLE_MCU_USE_INTERNAL_CLOCK
wDummy = 1000;
#endif
while (!(msReadByte(ucRegIndex) & ucRegMask) && (wDummy--)) ;
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: autoWaitStatusReady
//
// <Description>: Wait for status ready.
//
// <Returns> : Auto position value.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucRegIndex - In - Register index
// ucVSyncTime - In - VSync time
///////////////////////////////////////////////////////////////////////////////
WORD msAutoGetPosition(BYTE ucRegIndex, BYTE ucVSyncTime)
{
WORD wComparePos, wAutoPos; // position buffer
BYTE ucDummy = 20; // loop dummy
BYTE ucCount = 0; // counter of compare alike
BYTE ucBank = msReadByte( BK0_00_REGBK);
msWriteByte( BK0_00_REGBK, REG_BANK_SCALER );
while(ucDummy--)
{
msAutoWaitStatusReady(BK0_CB_ATOCTRL, _BIT1); // auto position result ready
wAutoPos = msReadWord(ucRegIndex+1); // get auto position
if (wAutoPos == wComparePos) // match
ucCount++;
else // different
{
ucCount = 0; // reset counter
wComparePos = wAutoPos; // reset position
}
if (ucCount == 3) // match counter ok
break;
if (msAutoCheckSyncLoss()) // check no signal
{
msWriteByte( BK0_00_REGBK, ucBank );
return -1; // return fail
}
Delay1ms_WatchDog(ucVSyncTime); // wait next frame
} // while
msWriteByte( BK0_00_REGBK, ucBank );
return wAutoPos;
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: autoWaitStatusReady
//
// <Description>: Wait for status ready.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucVSyncTime - In - VSync time
///////////////////////////////////////////////////////////////////////////////
BOOL msAutoTunePosition(BYTE ucVSyncTime)
{
WORD wPosBff; // position buffer
BYTE ucBank;
#ifdef AUTO_DEBUG_EN
printf("\r\nmsAutoTunePosition(%d)", ucVSyncTime);
#endif
ucBank = msReadByte( BK0_00_REGBK);
msWriteByte( BK0_00_REGBK, REG_BANK_SCALER );
// horizotal position
wPosBff = msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime); // auto horizontal start position detected result
if (wPosBff > StandardModeWidth ) // check overflow
{
msWriteByte( BK0_00_REGBK, ucBank );
return FALSE;
}
#if 0 // todo: test!!
wPosBff -= 1; // 20051101 Antony patch for Auto-H.Position
#endif
g_ModeSetting.HStart= wPosBff;
msWriteWord(BK0_08_SPRHST_H, wPosBff);
// g_ModeSetting.DefaultHStart = wPosBff;
// vertical positoin
wPosBff = msAutoGetPosition(BK0_CE_AOVST_L, ucVSyncTime); // auto vertical start position detected result
if (wPosBff >StandardModeHeight) // check overflow
{
msWriteByte( BK0_00_REGBK, ucBank );
return FALSE;
}
g_ModeSetting.VStart= wPosBff;
if( StandardModeHeight == 350 ) // if IBM VGA 640x350 then use 640x400 resolution and move to middle of screen
wPosBff -= ((400-350)/2);
msWriteWord(BK0_06_SPRVST_H, wPosBff);
msWriteByte( BK0_00_REGBK, ucBank );
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: msAdcGetTransPos
//
// <Description>: Get trans-position.
//
// <Returns> : Trans-phase.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucVSyncTime - In - VSync time
///////////////////////////////////////////////////////////////////////////////
BYTE msAutoGetTransPos(BYTE ucVSyncTime)
{
WORD wComparePos; // compare start position
BYTE ucAdjustPhase = 0x20, ucPhaseDelta = 0x20; // phase data buffer
msAdjustAdcPhase(0x00); // intialize
wComparePos = msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime);
while (1)
{
msAdjustAdcPhase(ucAdjustPhase); // set phase
ucPhaseDelta /= 2; // next step
if (ucPhaseDelta == 0x00) // check end
break;
if (msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime) == wComparePos) // find critical phase
ucAdjustPhase += ucPhaseDelta; // right shift
else
ucAdjustPhase -= ucPhaseDelta; // left shift
if (msAutoCheckSyncLoss()) // check no signal
return -1;
} // while
return (ucAdjustPhase);
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: msAutoGetActualWidth
//
// <Description>: Get actual image width.
//
// <Returns> : Actual width.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucVSyncTime - In - VSync time
///////////////////////////////////////////////////////////////////////////////
WORD msAutoGetActualWidth(BYTE ucVSyncTime)
{
WORD wHStart; // actual horizontal start
msAdjustAdcPhase(0x00); // initialize phase value
wHStart = msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime); // horizontal start position
msAutoGetTransPos(ucVSyncTime); // seek critical phase
return ((msAutoGetPosition(BK0_D4_AOHEND_L, ucVSyncTime) - wHStart) + 1); // actual image width
}
///////////////////////////////////////////////////////////////////////////////
// <Function>: msAutoTuneHTotal
//
// <Description>: auto-tune horizontal total.
//
// <Returns> : Success status.
//
// <Parameter>: - <Flow> - <Description>
//-----------------------------------------------------------------------------
// ucVSyncTime - In - VSync time
///////////////////////////////////////////////////////////////////////////////
BOOL msAutoTuneHTotal(BYTE ucVSyncTime)
{
WORD wActualWidth; // actual width
WORD wStdWidth; // standard width
WORD wHTotalBff; // horizontal total buffer
BOOL bResult = FALSE;
msAdjustAdcPhase(0x00); // initialize phase value
wActualWidth = msAutoGetPosition(BK0_D4_AOHEND_L, ucVSyncTime) - msAutoGetPosition(BK0_D0_AOHST_L, ucVSyncTime);
// get standard display width
wStdWidth = StandardModeWidth;
if (abs(wActualWidth - wStdWidth) > (wStdWidth / 4)) // check actual width over standard
{
#ifdef AUTO_DEBUG_EN
putstr("\r\nmsAutoTuneHTotal failed-1");
#endif
return FALSE;
}
wHTotalBff = g_ModeSetting.HTotal; // intialize horizontal total buffer
if (abs(wActualWidth - wStdWidth) > 1) // check width difference
{
// calculate horizontal total
wHTotalBff = ((DWORD)g_ModeSetting.HTotal* wStdWidth) / wActualWidth;
// check over range of adjusting
if (abs(wHTotalBff - StandardModeHTotal > ADJUST_CLOCK_RANGE))
{
#ifdef AUTO_DEBUG_EN
putstr("\r\nmsAutoTuneHTotal failed-2");
printf("\r\nwHTotalBff=%d", wHTotalBff);
printf("\r\nwStdWidth=%d", wStdWidth);
printf("\r\nwActualWidth=%d", wActualWidth);
#endif
return FALSE;
}
msAdjustAdcClock(wHTotalBff); // set clock
}
// check width
wActualWidth = msAutoGetActualWidth(ucVSyncTime);
if (wActualWidth != wStdWidth) // match width
{
// adjust horizontal total
wHTotalBff = wHTotalBff + (wStdWidth - wActualWidth);
msAdjustAdcClock(wHTotalBff);
wActualWidth = msAutoGetActualWidth(ucVSyncTime);
// adjust horizontal total again
wHTotalBff = wHTotalBff + (wStdWidth - wActualWidth);
}
if (wHTotalBff & 0x01) // match width and check odd
{
msAdjustAdcClock(wHTotalBff - 1); // find decrement
wActualWidth = msAutoGetActualWidth(ucVSyncTime);
if (wActualWidth == wStdWidth) // match width
wHTotalBff--;
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -