📄 drvauto.c
字号:
if(MDrv_Auto_CheckSyncLoss()) // check no signal
return FALSE;
} // for
// initizlize
u8BestPhase2 = (u8BestPhase1 - AUTO_PHASE_STEP + 1) & 0x3f;
u8BestPhase1 = (u8BestPhase1 + AUTO_PHASE_STEP) & 0x3f;
u32MaxPhaseVal = 0;
for(u8Index = u8BestPhase2; u8Index != u8BestPhase1; u8Index = ((u8Index + 1) & 0x3f))
{
MDrv_ADC_SetADCPhase(u8Index);
MDrv_Timer_Delayms(u8VSyncTime); // delay 1 frame
u32AutoPhaseVal = MDrv_Auto_GetPhaseVal();
if(u32AutoPhaseVal > u32MaxPhaseVal) // check maximum
{
u8BestPhase2 = u8Index; // refresh best phase
u32MaxPhaseVal = u32AutoPhaseVal; // refresh maximum value
}
if(MDrv_Auto_CheckSyncLoss()) // check no signal
return FALSE;
} // for
pstModesetting->u8Phase = u8BestPhase2;
}
#endif
MDrv_ADC_SetADCPhase(pstModesetting->u8Phase);
AUTOMSG(printf("AutoPhase 0x%bx\n", pstModesetting->u8Phase);)
return TRUE;
}
//*************************************************************************
//Function name: _MDrv_Auto_GainReport
//Passing parameter:
// U8 u8Type: report AUTO_MIN_[RGB] or AUTO_MAX_[RGB]
// U8 u8DelayMS: delay how long to get the report, usually, the delay will be 1 * VSyncTime
//Return parameter:
// U8: the min/max gain report
//Description: Auto-tune R/G/B Offset of ADC.
//*************************************************************************
U8 _MDrv_Auto_GainReport(U8 u8Type, U8 u8DelayMS)
{
U8 u8Value, u8Ready;
U8 u8Bank;
u8Bank = MDrv_ReadByte( BK_SELECT_00 );
MDrv_WriteByte( BK_SELECT_00, REG_BANK_IP1F2 );
MDrv_WriteByteMask(BK_SC_IP1F2_0F_L, u8Type, _BIT2 | _BIT1 | _BIT0);
MDrv_Timer_Delayms(u8DelayMS);
// Sometimes the gain report will give a very un-reasonable value,
// So, we've to wait the IP1F2_0E[1] to be ready (=1) to get the gain report
// For safety reason, you may use this flow:
// (1) Set what to get AUTO_MIN_[RGB] or AUTO_MAX_[RGB]
// (2) wait for ready bit to be off
// (because sometimes when you change the AUTO_MIN_[RGB] or AUTO_MAX_[RGB],
// you'll get a ready immediately but the report is the old value)
// (3) wait for ready bit to be on
// (4) get the report when ready bit is on (note: see source code below)
//
// For quick response, you may get the report when ready bit is on, the report is rarely wrong if ready bit is on.
/*
// wait for ready bit to be off
while(MDrv_ReadByte(BK_SC_IP1F2_0E_L) & (0x1 << 1))
{
u8Ready = MDrv_ReadByte(BK_SC_IP1F2_0E_L);
u8Value = MDrv_ReadByte(BK_SC_IP1F2_11_L);
printf("DA:C=0x%bx,R=0x%bx,V=0x%bx\n", MDrv_ReadByte(BK_SC_IP1F2_0F_L), u8Ready, u8Value);
}
// wait for ready bit to be on
while(!(MDrv_ReadByte(BK_SC_IP1F2_0E_L) & (0x1 << 1)))
{
u8Ready = MDrv_ReadByte(BK_SC_IP1F2_0E_L);
u8Value = MDrv_ReadByte(BK_SC_IP1F2_11_L);
printf("DA:C=0x%bx,R=0x%bx,V=0x%bx\n", MDrv_ReadByte(BK_SC_IP1F2_0F_L), u8Ready, u8Value);
}
*/
while(1)
{
// It's important to read the 2 values by this order
// (1) ready bit first
// (2) report next
// and no waste time between these 2 commands
u8Ready = MDrv_ReadByte(BK_SC_IP1F2_0E_L);
u8Value = MDrv_ReadByte(BK_SC_IP1F2_11_L);
// Check if the report is reasonable here
if(u8Ready & (0x1 << 1))
{
AUTOMSG(printf("C=0x%bx,R=0x%bx,V=0x%bx,Mask=0x%bx\n", MDrv_ReadByte(BK_SC_IP1F2_0F_L), u8Ready, u8Value, BITMASK(2:0));)
break;
}
}
MDrv_WriteByte( BK_SELECT_00, u8Bank );
return u8Value;
}
//*************************************************************************
//Function name: MDrv_Auto_TuneOffset
//Passing parameter:
// U8 u8VSyncTime: VSync time
// MS_ADC_SETTING * pstADCSetting: ADC setting of Current PC mode
//Return parameter:
// BOOLEAN: Success status. (If faile, return FALSE.)
//Description: Auto-tune R/G/B Offset of ADC.
//*************************************************************************
#define AUTO_OFFSET_SW_MODE 1
BOOLEAN MDrv_Auto_TuneOffset(U8 u8VSyncTime, MS_ADC_SETTING *pstADCSetting)
{
MS_ADC_SETTING tempADCSetting;
U8 u8OffsetDelta = 0x80; // adjust step
U8 u8ATGStatus = 0; // auto gain status//ERROR FIX Prevent Tool 070522
U8 u8FlowFlag = 0x00; // underflow or overflow flag
U8 u8Bank;
tempADCSetting.u8RedGain = 0x80;
tempADCSetting.u8GreenGain = 0x80;
tempADCSetting.u8BlueGain = 0x80;
MDrv_ADC_SetGain(&tempADCSetting);
tempADCSetting.u8RedOffset = 0x80;
tempADCSetting.u8GreenOffset = 0x80;
tempADCSetting.u8BlueOffset = 0x80;
u8Bank = MDrv_ReadByte( BK_SELECT_00 );
MDrv_WriteByte( BK_SELECT_00, REG_BANK_IP1F2 );
while(1)
{
u8OffsetDelta /= 2; // next
if(u8OffsetDelta == 0x00) // check end
break;
MDrv_ADC_SetOffset(&tempADCSetting);
MDrv_Timer_Delayms(u8VSyncTime * 3); // wait stable
MDrv_Auto_WaitStatusReady(BK_SC_IP1F2_0E_L, _BIT1);
#if AUTO_OFFSET_SW_MODE
{
U8 u8ResultR,u8ResultG,u8ResultB;
u8ResultR = _MDrv_Auto_GainReport(AUTO_MIN_R, u8VSyncTime);
u8ResultG = _MDrv_Auto_GainReport(AUTO_MIN_G, u8VSyncTime);
u8ResultB = _MDrv_Auto_GainReport(AUTO_MIN_B, u8VSyncTime);
if (u8ResultR == 0x00)
u8ATGStatus |= _BIT2;
else
u8ATGStatus &= ~_BIT2;
if (u8ResultG == 0x00)
u8ATGStatus |= _BIT1;
else
u8ATGStatus &= ~_BIT1;
if (u8ResultB == 0x00)
u8ATGStatus |= _BIT0;
else
u8ATGStatus &= ~_BIT0;
}
#else
u8ATGStatus = MDrv_ReadByte(BK_SC_IP1F2_0E_H); // get auto gain status
#endif
// red
if(_bit2_(u8ATGStatus))
{
tempADCSetting.u8RedOffset += u8OffsetDelta;
u8FlowFlag |= _BIT0;
}
else
{
tempADCSetting.u8RedOffset -= u8OffsetDelta;
u8FlowFlag |= _BIT1;
}
// green
if(_bit1_(u8ATGStatus))
{
tempADCSetting.u8GreenOffset += u8OffsetDelta;
u8FlowFlag |= _BIT2;
}
else
{
tempADCSetting.u8GreenOffset -= u8OffsetDelta;
u8FlowFlag |= _BIT3;
}
// blue
if(_bit0_(u8ATGStatus))
{
tempADCSetting.u8BlueOffset += u8OffsetDelta;
u8FlowFlag |= _BIT4;
}
else
{
tempADCSetting.u8BlueOffset -= u8OffsetDelta;
u8FlowFlag |= _BIT5;
}
AUTOMSG(printf("OffATG=0x%bx,FF=0x%bx\n", u8ATGStatus, u8FlowFlag);)
} // while
// adjust offset after auto-tune
if(u8FlowFlag == 0x3f)
{
pstADCSetting->u8RedOffset = tempADCSetting.u8RedOffset;
pstADCSetting->u8GreenOffset = tempADCSetting.u8GreenOffset;
pstADCSetting->u8BlueOffset = tempADCSetting.u8BlueOffset;
}
// if calibration successed, will write new value, else, write original value
MDrv_ADC_SetOffset(pstADCSetting);
MDrv_WriteByte( BK_SELECT_00, u8Bank );
return (u8FlowFlag == 0x3F ? TRUE : FALSE);
}
//*************************************************************************
//Function name: MDrv_Auto_TuneGain
//Passing parameter:
// U8 u8VSyncTime: VSync time
// MS_ADC_SETTING * pstADCSetting: ADC setting of Current PC mode
//Return parameter:
// BOOLEAN: Success status. (If faile, return FALSE.)
//Description: Auto-tune R/G/B gain of ADC.
//*************************************************************************
#define AUTO_GAIN_SW_MODE 0
BOOLEAN MDrv_Auto_TuneGain(U8 u8VSyncTime, MS_ADC_SETTING *pstADCSetting)
{
MS_ADC_SETTING tempADCSetting;
U8 u8GainDelta = 0x80; // adjust step
U8 u8ATGStatus; // auto gain status
U8 u8FlowFlag = 0x00; // underflow or overflow flag
U8 u8Bank;
tempADCSetting.u8RedGain = 0x80;
tempADCSetting.u8GreenGain = 0x80;
tempADCSetting.u8BlueGain = 0x80;
u8Bank = MDrv_ReadByte( BK_SELECT_00 );
MDrv_WriteByte( BK_SELECT_00, REG_BANK_IP1F2 );
while (1)
{
u8GainDelta /= 2; // next
if (u8GainDelta == 0x00) // check end
break;
MDrv_ADC_SetGain(&tempADCSetting);
MDrv_Timer_Delayms(u8VSyncTime * 3); // wait stable
MDrv_Auto_WaitStatusReady(BK_SC_IP1F2_0E_L, _BIT1);
#if AUTO_GAIN_SW_MODE
{
U8 u8ResultR,u8ResultG,u8ResultB;
u8ResultR = _MDrv_Auto_GainReport(AUTO_MAX_R, u8VSyncTime);
u8ResultG = _MDrv_Auto_GainReport(AUTO_MAX_G, u8VSyncTime);
u8ResultB = _MDrv_Auto_GainReport(AUTO_MAX_B, u8VSyncTime);
if (u8ResultR == 0xFF)
u8ATGStatus |= _BIT7;
else
u8ATGStatus &= ~_BIT7;
if (u8ResultG == 0xFF)
u8ATGStatus |= _BIT6;
else
u8ATGStatus &= ~_BIT6;
if (u8ResultB == 0xFF)
u8ATGStatus |= _BIT5;
else
u8ATGStatus &= ~_BIT5;
}
#else
u8ATGStatus = MDrv_ReadByte(BK_SC_IP1F2_0E_L); // get auto gain status
#endif
// red
if (_bit7_(u8ATGStatus))
{
tempADCSetting.u8RedGain -= u8GainDelta;
u8FlowFlag |= _BIT0;
}
else
{
tempADCSetting.u8RedGain += u8GainDelta;
u8FlowFlag |= _BIT1;
}
// green
if (_bit6_(u8ATGStatus))
{
tempADCSetting.u8GreenGain -= u8GainDelta;
u8FlowFlag |= _BIT2;
}
else
{
tempADCSetting.u8GreenGain += u8GainDelta;
u8FlowFlag |= _BIT3;
}
// blue
if (_bit5_(u8ATGStatus))
{
tempADCSetting.u8BlueGain -= u8GainDelta;
u8FlowFlag |= _BIT4;
}
else
{
tempADCSetting.u8BlueGain += u8GainDelta;
u8FlowFlag |= _BIT5;
}
AUTOMSG(printf("GainATG=0x%bx,FF=0x%bx\n", u8ATGStatus, u8FlowFlag);)
} // while
// adjust gain after auto-tune
if (u8FlowFlag == 0x3f)
{
pstADCSetting->u8RedGain = tempADCSetting.u8RedGain;
pstADCSetting->u8GreenGain = tempADCSetting.u8GreenGain;
pstADCSetting->u8BlueGain = tempADCSetting.u8BlueGain;
}
// if calibration successed, will write new value, else, write original value
MDrv_ADC_SetOffset(pstADCSetting);
MDrv_WriteByte( BK_SELECT_00, u8Bank );
return (u8FlowFlag == 0x3F ? TRUE : FALSE);
}
//*************************************************************************
//Function name: MDrv_Auto_ColorYUV
//Passing parameter:
// U8 u8VSyncTime: VSync time
// MS_ADC_SETTING * pstADCSetting: ADC setting of Current YCbCr mode
//Return parameter:
// BOOLEAN: Success status. (If faile, return FALSE.)
//Description: Auto-tune Y gain of ADC.
//*************************************************************************
#if COMPONENT_AUTO_SW_MODE
BOOLEAN MDrv_Auto_ColorYUV(U8 u8VSyncTime, MS_ADC_SETTING *pstADCSetting)
{
MS_ADC_SETTING tempADCSetting;
U8 u8Bank; // bank buffer
U8 u8ATGStatus, u8Tmp, u8FlowFlag;
U8 u8ResultR,u8ResultG,u8ResultB;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -