📄 auto.c
字号:
/*
********************************************************************************
*
* LCD控制程序
*
* 这是一个自动调整处理模块
*
* 文件名 : AUTO.C
* 设计者 : Terry
********************************************************************************
* 功 能 描 述
*
* 完成自动调整处理,该自动调整包括:
* 时钟,时钟相位,水平位置,垂直位置
********************************************************************************
*/
#include "global.h"
#include "scalar.h"
#define NOISE_MARGIN 0x30 // 自动位置校正时, 非黑像素的门限值
#define AUTO_MASK 0x40 // 0x40表示Mask Windows Enable, 否则为0x00
uint8 xdata MinSOD_Phase;
uint8 xdata MaxSOD_Phase;
uint8 xdata PhaseSearchRange;
static uint8 AutoTuneAdcGain(void);
static uint8 AutoTuneAdcClamp(void);
static void AutoFineTuneAdcOffset(void);
static uint8 AutoTuneTextModePos(void);
static void AutoTuneHPos(void);
static uint8 AutoTuneClock(void);
static uint8 AutoTunePhaseByClock(void);
static uint8 AutoTuneClockByPhase(void);
static uint32 AutoCheckPhaseData(void);
static uint8 AutoTunePhaseFine(void);
static uint8 AutoCheckClock(void);
static void AutoGetHmask(void);
ADCPAR code AutoAdcPar = {
0xFF,
0x80,
0xFF,
0x80,
0xFF,
0x80,
};
// 这是一种通过测量RGB的最大和最小值来校正ADC增益和偏压的方法
/*
********************************************************************************
* 函 数 名: AutoTuneAdc
* 功能描述: 自动校正三路ADC的增益和钳位
* 输 入: 无
* 返 回: 调整的结果: AUTO_OK或者是AUTO_FAIL
* 说 明: 原理还没有搞清楚
********************************************************************************
*/
uint8 AutoTuneAdc(void)
{
uint8 Reg06A, Reg1BC;
// 关闭Jitter功能
Reg06A = RdScalarReg(rP06A);
Reg1BC = RdScalarReg(rP1BC);
WrScalarReg(rP06A, 0x00);
WrScalarReg(rP1BC, 0x00);
/*
================================================================================
= 下面被屏蔽掉的两句是用于调试的,可以观察AUTO COLOR的效果,比较好的结果是,
= 左侧应该是一条白线
================================================================================
*/
//WrScalarReg(rP1C7, 0x18); //for debug only
//WrScalarReg(rP1C8, 0x03); //for debug only
if(AutoTuneAdcClamp() == AUTO_FAIL) {
WrScalarReg(rP06A, Reg06A);
AdcSetClamp(0, AdcPar.clampR);
AdcSetClamp(1, AdcPar.clampG);
AdcSetClamp(2, AdcPar.clampB);
WrScalarReg(rP1BC, Reg1BC);
WrScalarReg(rP06A, Reg06A);
return AUTO_FAIL;
}
AutoFineTuneAdcOffset();
AdcPar.clampR = RdScalarReg(rP003);
AdcPar.clampG = RdScalarReg(rP006);
AdcPar.clampB = RdScalarReg(rP009);
if (AutoTuneAdcGain() == AUTO_FAIL) {
WrScalarReg(rP06A, Reg06A);
AdcSetGain(0, AdcPar.gainR);
AdcSetGain(1, AdcPar.gainG);
AdcSetGain(2, AdcPar.gainB);
WrScalarReg(rP1BC, Reg1BC);
WrScalarReg(rP06A, Reg06A);
return AUTO_FAIL;
}
AdcPar.gainR = RdScalarReg(rP001);
AdcPar.gainG = RdScalarReg(rP004);
AdcPar.gainB = RdScalarReg(rP007);
WrScalarReg(rP06A, Reg06A);
WrScalarReg(rP1BC, Reg1BC);
return AUTO_OK;
}
#if 0
/*
********************************************************************************
* 函 数 名: AutoTuneAdc
* 功能描述: 自动校正三路ADC的增益和钳位
* 输 入: 无
* 返 回: 无
********************************************************************************
*/
static uint8 AutoTuneAdcGain(void)
{
#define MinIndex 0
#define MidIndex 1
#define MaxIndex 2
#define Cal_Gain_Loop 8
#define FinalOffset 4
uint8 RGB_Gain[3][3],CompareBuf[3],DataBuf,i,j;
bit Is_Compare_ok;
CompareBuf[0] = AdcPar.gainR;
CompareBuf[1] = AdcPar.gainG;
CompareBuf[2] = AdcPar.gainB;
Is_Compare_ok = 0;
while(!Is_Compare_ok){
Is_Compare_ok = 1;
RGB_Gain[MinIndex][0] = 0x00;
RGB_Gain[MinIndex][1] = 0x00;
RGB_Gain[MinIndex][2] = 0x00;
RGB_Gain[MaxIndex][0] = 0xFF;
RGB_Gain[MaxIndex][1] = 0xFF;
RGB_Gain[MaxIndex][2] = 0xFF;
RGB_Gain[MidIndex][0] = 0x7F;
RGB_Gain[MidIndex][1] = 0x7F;
RGB_Gain[MidIndex][2] = 0x7F;
AdcSetGain(COLOR_R, RGB_Gain[MidIndex][COLOR_R]);
AdcSetGain(COLOR_G, RGB_Gain[MidIndex][COLOR_G]);
AdcSetGain(COLOR_B, RGB_Gain[MidIndex][COLOR_B]);
for(i = 0; i < Cal_Gain_Loop; i++){
WrScalarReg(rP106, 0x2E);
SysTmr = 5;
while((RdScalarReg(rP106) & BIT_1) && SysTmr != 0){
ClearWatchDog();
if (SyncGetIntState()) return AUTO_FAIL;
}
for(j = 0; j < 3; j++){
DataBuf = RdScalarReg((rP113 + j));
if(DataBuf < 254){
RGB_Gain[MaxIndex][j]=RGB_Gain[MidIndex][j];
RGB_Gain[MidIndex][j]=((uint16)RGB_Gain[MidIndex][j]+RGB_Gain[MinIndex][j])/2;
}
else if(DataBuf == 0xFF){
RGB_Gain[MinIndex][j]=RGB_Gain[MidIndex][j];
RGB_Gain[MidIndex][j]=((uint16)RGB_Gain[MaxIndex][j]+RGB_Gain[MidIndex][j])/2;
}
}
AdcSetGain(COLOR_R, RGB_Gain[MidIndex][COLOR_R]);
AdcSetGain(COLOR_G, RGB_Gain[MidIndex][COLOR_G]);
AdcSetGain(COLOR_B, RGB_Gain[MidIndex][COLOR_B]);
}
for(i = 0; i < 3; i++){ //compare data
if(abs(RGB_Gain[MidIndex][i]-CompareBuf[i])>5){
CompareBuf[i]=RGB_Gain[MidIndex][i];
Is_Compare_ok=0;
}
}
}
AdcSetGain(COLOR_R, RGB_Gain[MidIndex][COLOR_R] - FinalOffset);
AdcSetGain(COLOR_G, RGB_Gain[MidIndex][COLOR_G] - FinalOffset);
AdcSetGain(COLOR_B, RGB_Gain[MidIndex][COLOR_B] - FinalOffset);
return AUTO_OK;
}
#endif
//#if 0
/*
********************************************************************************
* 函 数 名: AutoTuneAdc
* 功能描述: 自动校正三路ADC的增益
* 输 入: 无
* 返 回: 无
********************************************************************************
*/
static uint8 AutoTuneAdcGain(void)
{
#define MinIndex 0
#define MidIndex 1
#define MaxIndex 2
uint8 RGB_Gain[3][3], OutData[3];
uint8 i, Color;
RGB_Gain[MinIndex][0] = 0x00;
RGB_Gain[MinIndex][1] = 0x00;
RGB_Gain[MinIndex][2] = 0x00;
RGB_Gain[MaxIndex][0] = 0xFF;
RGB_Gain[MaxIndex][1] = 0xFF;
RGB_Gain[MaxIndex][2] = 0xFF;
RGB_Gain[MidIndex][0] = 0x7F;
RGB_Gain[MidIndex][1] = 0x7F;
RGB_Gain[MidIndex][2] = 0x7F;
AdcSetGain(COLOR_R, RGB_Gain[MidIndex][COLOR_R]);
AdcSetGain(COLOR_G, RGB_Gain[MidIndex][COLOR_G]);
AdcSetGain(COLOR_B, RGB_Gain[MidIndex][COLOR_B]);
for (i = 0; i < 20; i++) {
WrScalarReg(rP106, 0x2E);
SysTmr = 200/SYSTMR_PRIO;
while((RdScalarReg(rP106) & BIT_1) && SysTmr != 0) {
ClearWatchDog();
if (SyncGetIntState()) return FALSE;
}
for (Color = 0; Color < 3; Color++) {
OutData[Color] = RdScalarReg(rP113 + Color);
if (OutData[Color] == 255) {
RGB_Gain[MinIndex][Color] = RGB_Gain[MidIndex][Color];
RGB_Gain[MidIndex][Color] = ((uint16)RGB_Gain[MinIndex][Color] + RGB_Gain[MaxIndex][Color]) / 2;
AdcSetGain(Color, RGB_Gain[MidIndex][Color]);
}
else if (OutData[Color] < 245) {
RGB_Gain[MaxIndex][Color] = RGB_Gain[MidIndex][Color];
RGB_Gain[MidIndex][Color] = ((uint16)RGB_Gain[MinIndex][Color] + RGB_Gain[MaxIndex][Color]) / 2;
AdcSetGain(Color, RGB_Gain[MidIndex][Color]);
}
else continue;
}
if (OutData[0] >= 245 && OutData[1] >= 245 && OutData[2] >= 245) break;
}
if (i >= 20) return FALSE;
if (OutData[0] < 200 || OutData[1] < 200 || OutData[2] < 200) return FALSE;
//AdcSetGain(COLOR_R, RGB_Gain[MidIndex][COLOR_R]);
//AdcSetGain(COLOR_G, RGB_Gain[MidIndex][COLOR_G]);
//AdcSetGain(COLOR_B, RGB_Gain[MidIndex][COLOR_B]);
for (i = 0; i < 64; i++) {
WrScalarReg(rP106, 0x2E);
SysTmr = 200/SYSTMR_PRIO;
while((RdScalarReg(rP106) & BIT_1) && SysTmr != 0) {
ClearWatchDog();
if (SyncGetIntState()) return FALSE;
}
for (Color = 0; Color < 3; Color++) {
OutData[Color] = RdScalarReg(rP113 + Color);
if (OutData[Color] < 255) {
RGB_Gain[MidIndex][Color]--;
AdcSetGain(Color, RGB_Gain[MidIndex][Color]);
}
}
if (OutData[0] == 255 && OutData[1] == 255 && OutData[2] == 255) break;
//if (OutData[0] >= 254 && OutData[1] >= 254 && OutData[2] >= 254) break;
}
if (i >= 64) return FALSE;
else return TRUE;
}
//#endif
/*
********************************************************************************
* 函 数 名: AutoTuneAdcClamp
* 功能描述: 自动校正ADC的钳位
* 输 入: 无
* 返 回: 无
********************************************************************************
*/
static uint8 AutoTuneAdcClamp(void)
{
uint8 RGB_Offset[3][3],DataBuf,i,j,AutoWay;
bit Is_Compare_ok;
#define MinIndex 0
#define MidIndex 1
#define MaxIndex 2
#define Cal_Offset_Loop 8
#define AutoWayByMask 0x4a
#define AutoWayByCapture 0x2a
Is_Compare_ok = 0;
AutoWay = AutoWayByMask;
WrScalarRegBit(rP020, 0x00, 0x10);
if (ModePar.hstart > 0x10) i = ModePar.hstart - 0x10;
else i = 0;
WrScalarReg(rP02A, i);
i = ModePar.htotal - ModePar.hstart - 10;
WrScalarReg(rP02B, i);
while(!Is_Compare_ok){
Is_Compare_ok=1;
RGB_Offset[MinIndex][0] = 0x00;
RGB_Offset[MinIndex][1] = 0x00;
RGB_Offset[MinIndex][2] = 0x00;
RGB_Offset[MaxIndex][0] = 0xFF;
RGB_Offset[MaxIndex][1] = 0xFF;
RGB_Offset[MaxIndex][2] = 0xFF;
RGB_Offset[MidIndex][0] = 0x7F;
RGB_Offset[MidIndex][1] = 0x7F;
RGB_Offset[MidIndex][2] = 0x7F;
AdcSetClamp(COLOR_R, RGB_Offset[MidIndex][COLOR_R]);
AdcSetClamp(COLOR_G, RGB_Offset[MidIndex][COLOR_G]);
AdcSetClamp(COLOR_B, RGB_Offset[MidIndex][COLOR_B]);
for(i = 0; i < Cal_Offset_Loop; i++) {
ClearWatchDog();
WrScalarReg(rP106, AutoWay);
SysTmr = 100/SYSTMR_PRIO;
while((RdScalarReg(rP106) & BIT_1) && SysTmr != 0){
ClearWatchDog();
if (SyncGetIntState()) return AUTO_FAIL;
}
for(j = 0; j < 3; j++){
DataBuf = RdScalarReg(rP113 + j);
if(DataBuf > 1){
RGB_Offset[MinIndex][j]=RGB_Offset[MidIndex][j]; //update min
RGB_Offset[MidIndex][j]=((uint16)RGB_Offset[MaxIndex][j]+RGB_Offset[MidIndex][j])/2;
}else if(DataBuf==0){
RGB_Offset[MaxIndex][j]=RGB_Offset[MidIndex][j];
RGB_Offset[MidIndex][j]=((uint16)RGB_Offset[MidIndex][j]+RGB_Offset[MinIndex][j])/2;
}
}
AdcSetClamp(COLOR_R, RGB_Offset[MidIndex][COLOR_R]);
AdcSetClamp(COLOR_G, RGB_Offset[MidIndex][COLOR_G]);
AdcSetClamp(COLOR_B, RGB_Offset[MidIndex][COLOR_B]);
}
if(RGB_Offset[MidIndex][1] < 0x10){
//if(RGB_Offset[MidIndex][1] < 0x08){
AutoWay = AutoWayByCapture;
Is_Compare_ok = 0;
}
};
return AUTO_OK;
}
/*
********************************************************************************
* 函 数 名: AutoFineTuneAdcOffset
* 功能描述: 通过Novatek新的测量方法来调整钳位,这是通过柱状图的方式来进行
* 调整处理
* 输 入: 无
* 返 回: 无
********************************************************************************
*/
void AutoFineTuneAdcOffset(void)
{
#define AutoGaugeWinV_OddBegin 0x0E6
#define AutoGaugeWinV_EvenBegin 0x0E8
#define AutoGaugeWinV_Length 0x0EA
#define AutoGaugeWinH_Begin 0x0EC
#define AutoGaugeWinH_Length 0x0EE
#define Offset 4
#define ShiftLines 10
#define ShiftPixel 25
uint8 channel,area,ShiftLineBuf,ShiftPixelBuf;
uint16 xdata H_Start,H_Act,V_Start,V_Act;
uint32 xdata ExtraBlackPixel,Histogram,Sum;
bit TheChannelFineTuneOk;
V_Act = RdScalarWord(rP032) & 0x07FF;
H_Act = RdScalarWord(rP036) & 0x0FFF;
V_Start = RdScalarWord(rP02E) & 0x7FF;
if(V_Start < ShiftLines ) ShiftLineBuf = V_Start;
else ShiftLineBuf = ShiftLines;
H_Start = RdScalarWord(rP034) & 0x0FFF; //H begin
if(H_Start < ShiftPixel) ShiftPixelBuf = H_Start;
else ShiftPixelBuf = ShiftPixel;
if(ShiftPixelBuf > 7 && ShiftLineBuf > 2)
ExtraBlackPixel = ((ShiftLineBuf-2) * H_Act) + ((ShiftPixelBuf-7)* V_Act);
else
ExtraBlackPixel = (ShiftLineBuf * H_Act) + (ShiftPixelBuf* V_Act);
WrScalarWord(AutoGaugeWinV_OddBegin,(RdScalarWord(rP02E)&0x7FF) -ShiftLineBuf);
WrScalarWord(AutoGaugeWinV_EvenBegin,(RdScalarWord(rP030)&0x7FF)-ShiftLineBuf);
WrScalarWord(AutoGaugeWinV_Length,(RdScalarWord(rP032)&0x7FF));
WrScalarWord(AutoGaugeWinH_Begin,(RdScalarWord(rP034) & 0x0FFF)-ShiftPixelBuf);
WrScalarWord(AutoGaugeWinH_Length,(RdScalarWord(rP036)& 0x0FFF));
WrScalarWord(rP0F7, 0x01); // Gauge Control1 by windows
WrScalarReg(rP0FA, 0x00);
for(channel = 0; channel < 3; channel++){ //00-->B,01-->G,10-->R
TheChannelFineTuneOk = 0;
while(TheChannelFineTuneOk==0){
WrScalarReg(rP0F8, 0x00);
WrScalarReg(rP0F8, BIT_7 | (channel<<3));
SysTmr = 100/SYSTMR_PRIO;
Sum = 0;
while((RdScalarReg(rP0F8) & BIT_7) && SysTmr);
for(area = 0; area < 8; area++) {
WrScalarReg(rP0F9, area);
Histogram = RdScalarWord(rP0FC);
Histogram <<= 8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -