⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auto.c

📁 NT68617源程序代码集合
💻 C
📖 第 1 页 / 共 2 页
字号:
	     		Histogram |= (uint32)RdScalarReg(rP0FB);
	     		Sum += Histogram;
	     		if(Sum >= ExtraBlackPixel) break;
	    		}
	    		if(area==0){
	     			TheChannelFineTuneOk = 1;  //next channel
	     			WrScalarReg(9-(channel*3), RdScalarReg(9-(channel*3))+Offset);
	    			}
				else{
	     			WrScalarReg(9-(channel*3), RdScalarReg(9-(channel*3))+area);
	    			}
	   	}
	}
}


uint8 code MaskWin[4] = {
	0x00,		// rP02A Horizontal Mask Window Begin
	24,			// rP02B Horizontal Mask Window End
	0x00,		// rP02C Vertical Mask Window Begin
	0x00,		// rP02D Vertical Mask Window End
};

/*
********************************************************************************
* 	函 数 名: AutoTunePorc
* 	功能描述: 自动校正位置,时钟和相位, 如果画面是满屏的就进行完整的调整,如果
*			  画面是不满屏的,那么就只进行相位的调整
* 	输    入: 无
* 	返    回: 无
*	注    意: 对于客户的特殊要求,这里并没有进行处理,所以客户对特定画面或者
*			  显示模式的要求,需要根据实际需求进行调整
********************************************************************************
*/
uint8 AutoTuneProc(void)
{
	uint8 result = AUTO_CONTINUE;
	uint8 Reg06A;
	
	Flg_NonFullScreen = FALSE;
	Reg06A = RdScalarReg(rP06A);		// 该寄存器用于抖动校正控制
	WrScalarReg(rP06A, 0x00);			// 清除该寄存器原来的设置

	WrScalarBytes(rP02A, 4, MaskWin);	// 设置Mask Window
	result = AutoTunePos();
	//if (result == AUTO_FAIL) {
	//	ModePar.htotal = ModeAttr[ModePar.mode].Htotal;
	//	AdcSetPll(ModePar.htotal);
	//	AutoTuneClock();
	//	}
	//result = AutoTunePos();

	//	对不满屏画面的AUTO处理
	if (result == AUTO_FAIL) {
		if (Flg_NonFullScreen)  {
			AutoTuneClockByPhase();
			result = AutoTunePhaseFine();
			goto auto_exit;
			}
		else goto auto_exit;
		}

	//	对满屏画面的AUTO处理
	else  {
		Flg_NonFullScreen = FALSE;
		result = AutoTuneClock();
		if (result == AUTO_FAIL) goto auto_exit;
		
		result = AutoTuneClockByPhase();
		if (result == AUTO_FAIL) goto auto_exit;
		
		result = AutoTunePhaseFine();
		if (result == AUTO_FAIL) goto auto_exit;
		
		result = AutoTunePos();
		}

auto_exit:
	WrScalarReg(rP06A, Reg06A);
	if (result == AUTO_OK) {
		ModePar.hoffset = 0;
		ModePar.voffset = 0;
		}
	AdjClock(HIDE, 0);
	AdjPhase(HIDE, 0);
	AdjHpos(HIDE, 0);
	AdjVpos(HIDE, 0);
	return result;
}


/*
********************************************************************************
* 	函 数 名: AutoTunePos
* 	功能描述: 自动校正水平和垂直的位置,采用的是SCALAR自身的方法,过程也十分
*             简单明了。
* 	输    入: 无
* 	返    回: 返回调整的结果: AUTO_OK或者是AUTO_FAIL
********************************************************************************
*/
uint8 AutoTunePos(void)
{
	uint16 xdata temph,tempv;
	uint16 xdata H_Active, V_Active;
	uint16 xdata InputVactive;

	if (SyncGetIntState())  return AUTO_FAIL;

	//	设置初始的参数
	//WrScalarBytes(rP02A, 4, MaskWin);	// 设置Mask Window
	WrScalarReg(rP107, NOISE_MARGIN);	// 设置门限值
	AutoGetHmask();
	
	//	启动自动校正过程
	WrScalarReg(rP106, 0x00);
	WrScalarReg(rP106, AUTO_MASK + 0x01);

	//	等待自动校正结束
	SysTmr = 200/SYSTMR_PRIO;
	while ((RdScalarReg(rP106) & BIT_0) && SysTmr != 0)  {
		ClearWatchDog();
		if (SyncGetIntState())  {
			return AUTO_FAIL;
			}
		}

	if (SysTmr != 0)  {					// 对没有超时的情况进行处理
		V_Active = RdScalarWord(rP10C) & 0x07FF;
		H_Active = RdScalarWord(rP110) & 0x07FF;

		if (Flg_Interlace) InputVactive = DispModeHeight<<1;
		else  InputVactive = DispModeHeight;
		
		tempv = abs(InputVactive - V_Active);
		if(tempv < 5) {
			temph = abs(DispModeWidth - H_Active);
			if(temph > (DispModeWidth >> 2))  {		// Check HTotal range.
				Flg_NonFullScreen = TRUE;
				return AUTO_FAIL;
				}
			}
		else {
			Flg_NonFullScreen = TRUE;
			return AUTO_FAIL;
			}

		tempv = RdScalarWord(rP108) & 0x07FF;
		temph = RdScalarWord(rP10E) & 0x07FF;
		if(tempv < 1 || temph < 1) return AUTO_FAIL;
		if((tempv > 0xff) || (temph > (ModePar.htotal - H_Active))) {
			Flg_NonFullScreen = TRUE;
			return AUTO_FAIL;
			}
		
		else {
			if(V_Active != InputVactive) {
				if(V_Active==400 || V_Active==350) {
					tempv = tempv - (InputVactive - V_Active)/2;
					}
				}
			ModePar.hstart = temph;
			ModePar.vstart = tempv;
			SarHpos(ModePar.hstart);
			SarVpos(ModePar.vstart);
			return AUTO_OK;
			}
   	}
	return AUTO_FAIL;					// 如果超时表示自动位置调整失败
}


/*
********************************************************************************
* 	函 数 名: AutoCheckPhaseData
* 	功能描述: 按步长为4输出相位值,将所有值输出一遍。在输出的同时启动检测功能,
*             记录检测值的最大值和最小值,返回这两个值的差值,同时检验值SOD最大
*			  时的相位值记录在MaxSOD_Phase,SOD最小的相位值记录在MinSOD_Phase
* 	输    入: 无
* 	返    回: 返回最大检测值和最小检测值的差
*   注    意: 不破坏AdcPar.phase的值
********************************************************************************
*/
static uint32 AutoCheckPhaseData(void)
{
	uint32 xdata Value,MinValueTemp,MaxValueTemp;
	uint8 ADC_Phase;
	
	MaxValueTemp = 0;
	MinValueTemp = 0xFFFFFFFF;
	
	for(ADC_Phase = 0; ADC_Phase < 0x40; ADC_Phase += 4) {
		AdcSetPhase(ADC_Phase);
		WrScalarReg(rP106, AUTO_MASK + 0x02);
		SysTmr = 200/SYSTMR_PRIO;
		while((RdScalarReg(rP106) & BIT_1) && SysTmr != 0)  {
			ClearWatchDog();
			if (SyncGetIntState())  return 0;
			}

		Value = RdScalarWord(rP115);
		Value <<= 16;
		Value += RdScalarWord(rP113);
		
		if(Value < MinValueTemp) {
			MinValueTemp = Value;
			MinSOD_Phase = ADC_Phase;
			}
		if(Value > MaxValueTemp) {
			MaxValueTemp = Value;
			MaxSOD_Phase = ADC_Phase;
			}
		}
	
	Value = MaxValueTemp - MinValueTemp;
	return Value;
}


/*
********************************************************************************
* 	函 数 名: AutoTuneClock
* 	功能描述: 自动校正ADC采样时钟, 同时会影响标志Flg_NonFullScreen
* 	输    入: 无
* 	返    回: 返回调整的结果: AUTO_OK或者是AUTO_FAIL
********************************************************************************
*/
static uint8 AutoTuneClock(void)
{
	uint8 H_Difference,i,Compare;
	uint16 xdata H_Act, TempClock;

	WrScalarBytes(rP02A, 4, MaskWin);	// 设置Mask Window
	TempClock = ModePar.htotal;
	if(DispModeWidth >= TempClock)  {
		TempClock = DispModeWidth + ModePar.hstart;
		AdcSetPll(TempClock);
		}
	WrScalarWord(rP117, DispModeWidth);
	
	for(i = 0; i < 20; i++) {
		AutoGetHmask();
		WrScalarReg(rP106, AUTO_MASK + 0x01);
		SysTmr = 200/SYSTMR_PRIO;
	   	while((RdScalarReg(rP106) & 0x01) && SysTmr != 0) {
			ClearWatchDog();
			if (SyncGetIntState()) return AUTO_FAIL;
		}
		
		H_Act = RdScalarWord(rP110) & 0x0FFF;
		H_Difference = RdScalarReg(rP119);
		Compare = (H_Difference & 0xC0) >> 6;
		H_Difference &= 0x3F;

		if(Compare == 0x00)  break;
		
		if(Compare == 0x01)  {
			TempClock += H_Difference;
			//if(TempClock > 3072)  {
			if(TempClock > (DispModeWidth + (DispModeWidth>>1)))  {
				i = 0xFF;
				break;
				}
			}
		
		if(Compare > 0x01)  {
			TempClock -= H_Difference;
			if(TempClock < DispModeWidth)  {
				i = 0xFF;
				break;
				}
			}	
		AdcSetPll(TempClock);
		}
	if(i == 0xFF || i == 20)  {
		Flg_NonFullScreen = 1;
		AdcSetPll(ModePar.htotal);
		return AUTO_FAIL;
		}
	
	else  {
		ModePar.htotal = TempClock;	
//		ModePar.htotal = (TempClock + 2) & 0xFFFC;	

		AdcSetPll(ModePar.htotal);
		return AUTO_OK;
		}
}


/*
********************************************************************************
* 	函 数 名: AutoTuneClockByPhase
* 	功能描述: 在当前采样时钟的基础上(该基础时钟是通过在此之前执行的AutoTuneClock
*             所得到的),往前或者往后调整2步,通过相位校正的方式来细调当前的时钟
*             是否准确。
* 	输    入: 无
* 	返    回: 返回调整的结果: AUTO_OK或者是AUTO_FAIL
*   注    意: 判断的原则是相位检测值的差是否是最大的。
********************************************************************************
*/
static uint8 AutoTuneClockByPhase(void)
{
	uint8 k,MinTmpPh,MaxTmpPh;
	uint16 Clk;
	uint32 xdata MaxMin,Value;

	Clk = ModePar.htotal - 1;
	MaxMin = 0;
	for(k = 0; k < 3; k++) {		// find tune clock +/- 1
		AdcSetPll(Clk);
		Value = AutoCheckPhaseData();
		if(MaxMin < Value) {
			ModePar.htotal = Clk;
			MaxMin = Value;
			MinTmpPh = MinSOD_Phase;
			MaxTmpPh = MaxSOD_Phase;
			}
		Clk++;
		}
	AdcSetPll(ModePar.htotal);

	//	通过设定这个条件来判断画面是锐利的还是平滑的
	//Value = (uint32)DispModeWidth * DispModeHeight * 256;
	if (Flg_Interlace)	Value = (uint32)DispModeWidth * DispModeHeight * 128;
	else Value = (uint32)DispModeWidth * DispModeHeight * 64;

	//	画面是平滑的,因此最佳Phase应该出现在反向180度的地方,其实应该要加
	//	32才对,但是需要往前推8个点,所以是加24
	if(MaxMin < Value) {
		ModePar.phase = (MinTmpPh + 24) & 0x3F;
		PhaseSearchRange = 32;
		}

	//	画面是锐利的,因此最佳Phase应该出现在最大值的附近,往前推8个点为后面
	//	的搜寻服务
	else {
		ModePar.phase = (MaxTmpPh - 8) & 0x3F;
		PhaseSearchRange = 16;
		}
	AdcSetPhase(ModePar.phase);
	return AUTO_OK;
}


/*
********************************************************************************
* 	函 数 名: AutoTunePhaseFine
* 	功能描述: 自动校正ADC采样时钟的相位
* 	输    入: 无
* 	返    回: 返回调整的结果: AUTO_OK或者是AUTO_FAIL
*   注    意: 这个函数的使用要在一定的基础上进行,否则不能得到正确的结果
********************************************************************************
*/
static uint8 AutoTunePhaseFine(void)
{
	uint8 GoodPhase,yy, Phase;
	uint32 xdata Phase_0, Phase_1, Phase_2, Phase_Pre3, Phase_Now3, Phase_Delta;

    Phase_1 = 0x00000000;   // (i-1)
    Phase_2 = 0x00000000;   // (i-2)
    Phase_Pre3 = 0x00000000;   // (pre sum)->(delta)->(now sum)
    Phase_Delta = 0xFFFFFFFF;   // (min delta)
	
	for(yy = 0; yy < PhaseSearchRange; yy++)  {
		Phase = (ModePar.phase + yy) & 0x3F;
		AdcSetPhase(Phase);
		WrScalarReg(rP106, AUTO_MASK + 0x02);
		SysTmr = 200/SYSTMR_PRIO;
	 	while((RdScalarReg(rP106) & 0x02) && SysTmr != 0)  {
			ClearWatchDog();
			if (SyncGetIntState()) return AUTO_FAIL;
			}

		Phase_Now3 = RdScalarWord(rP115);
		Phase_Now3 <<= 16;
		Phase_Now3 += RdScalarWord(rP113);

        Phase_2 = Phase_1;  // Shift	
        Phase_1 = Phase_0;
        Phase_0 = Phase_Now3;
		Phase_Now3 = (Phase_0>>1) + (Phase_1>>1) + (Phase_2>>2); // Phase_Now3
		if(yy < 3)  Phase_Pre3  = Phase_Now3;   // Phase_Pre3 = Phase_Now3
		else  {
			if(Phase_Now3 > Phase_Pre3)  Phase_Pre3  = Phase_Now3 - Phase_Pre3;
			else  Phase_Pre3  = Phase_Pre3 - Phase_Now3;  // Phase_Pre3=delta
			if(Phase_Pre3 < Phase_Delta)  {
				GoodPhase = Phase;           
				Phase_Delta = Phase_Pre3;
				}
			Phase_Pre3  = Phase_Now3;   // Phase_Pre3 = Phase_Now3
			}     
		}

	// 这个范围是+/- 2, 具体的数值将取决于实际的PCB设计
	//ModePar.phase = (GoodPhase - 2) & 0x3F;
	ModePar.phase = (GoodPhase - 1) & 0x3F;
	AdcSetPhase(ModePar.phase);
	return AUTO_OK;
}


/*
================================================================================
=	说明: 这个函数还需要调整,因为在640 * 480的分辨率下自动调整不成功
================================================================================
*/
static void AutoGetHmask(void)
{
#if 0
	uint16 mask, hw;
	uint8 sw;
	float temp;

	WrScalarReg(rP02A, 0x10);
	sw = RdScalarReg(rP1B1);
	hw = RdScalarWord(rP19B) & 0x1FFF;
	temp = ((float)ModePar.htotal * sw * 8)/hw;
	mask = (uint8)(temp * 11/10 + 0.5);
	if (mask > 0xFF) mask = 0xFF;
	hw = ModePar.htotal - DispModeWidth - ModePar.hstart;
	if (mask > hw) mask = hw;
	WrScalarReg(rP02B, mask);
#endif
}
/*
********************************************************************************
*                                文 件 结 束                                   *
********************************************************************************
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -