📄 auto.c
字号:
/****************************************************************************
+----------------------------------------------------------------------+
| Copyright Trumpion Microelectronics Inc. 1999 |
| Trumpion Microelectronics Inc. reserves the right to change products |
| or specifications without notice. |
+----------------------------------------------------------------------+
Project : LCD monitor
Version : 0.94
File Name : auto.c
Functions : auto and white-balance function implement
Revision :
1999-05-18 OriginalTeam First Created
2000-07-17 Bill Tseng Modified for Zurac-II
2000-07-21 Bill Tseng Add auto_phase_adjust2, using Mline to do coarse
phase adjust then use ASOD to fine tune
2000-08-22 Bill Tseng Change white_balance() , using Freeze-Line for
ADC offset adjust
****************************************************************************/
//=========================================================================
// include files =
//=========================================================================
#include "lib\extent.h"
#include "lib\wreg516.h"
#include "lib\declare.h"
#include "lib\global.h"
#include "lib\modedata.h"
#include "lib\initial.h"
#include "lib\ttfc.h"
#include "lib\adc.h"
#include <intrins.h>
#define GOOD_AUTO 1 /* 1:good auto or 0:original auto */
#define SMOOTH_PHASE 2 /* 1:smooth phase or 0:highest phase */
#define FINETUNE_PHASE 1 /* 1:fine tune phase or 0:normal tune phase */
// condition compile definition
#ifndef ADC_CHIP
#define ADI_9884 0
#define FMS_9884 1
#define FMS_9874 2
#define ADI_9883 3
#define ADI_9887 4
#define SCL_9884 5
#define TMI_9884 6
#define SG_9884 7
#define ADC_CHIP ADI_9884
#endif
#define MIN_THRESHOLD 0x40
#ifndef SWAP_RED_BLUE /* for R and B channel swap */
#define SWAP_RED_BLUE 0
#endif
#ifndef ZURAC_ADDRESS
#define ZURAC_ADDRESS 0xF0
#endif
#ifndef TDA8752_ADDR
#define TDA8752_ADDR 0x98
#endif
#ifndef AD9884_ADDR
#define AD9884_ADDR 0x98
#endif
#ifndef AD9887_ADDR
#define AD9887_ADDR 0x98
#endif
// constant and default value
#define max_threhold 0x80
#define min_threhold 0x1F
#define M_line 100
#define X_line 100
#define MISCTRL_value 0x03
// Zurac register definition
#define ZRC_MISCTR0 0x0A
#define ZRC_MISCTR1 0x0B
#define ZRC_STATUS1 0x0D
#define ZRC_IH_ASTART 0x10
#define ZRC_IH_AWIDTH 0x12
#define ZRC_IH_TOTAL 0x14
#define ZRC_IV_ASTART 0x16
#define ZRC_IV_AWIDTH 0x18
#define ZRC_IV_TOTAL 0x1A
#define ZRC_IH_PULW 0x1C
#define ZRC_PH_AWIDTH 0x32
#define ZRC_SPH_EMU 0x60
#define ZRC_SIH_EMU 0x62
#define ZRC_AWVSTART 0x20
#define ZRC_AWVEND 0x22
#define ZRC_AWHSTART 0x24
#define ZRC_AWHEND 0x26
#define ZRC_ASUM 0x28
#define ZRC_ASOD 0x2C
#define ZRC_ABDSUM 0x74
#define ZRC_SODCTR 0x77
#define ZRC_SODMASK 0x78
#define ZRC_ARGB_MAX 0x80
#define ZRC_ARGB_MIN 0x81
#define ZRC_AFZLADDR 0x82
#define ZRC_AFZHSTART 0x84
#define ZRC_AFZREAD 0x86
#define ZRC_AMLNUM 0x88
#define ZRC_AVSTART 0x8A
#define ZRC_AVEND 0x8C
#define ZRC_AMLHSTA 0x8E
#define ZRC_AMLHEND 0x90
#define ZRC_AMLHSTAR 0x92
#define ZRC_AMLHENDR 0x95
#define ZRC_AXLNUM 0x98
#define ZRC_AXPNUM0 0x9A
#define ZRC_AXP0R 0xA0
#define ZRC_AH_START 0xAA
#define ZRC_AML_OVERFLOW 0xAC
#define ZRC_CONTRAST 0xB0
#define ZRC_BRIGHTNESS 0xB1
// T8752 register definition
#define TDA_OFFSETR 0
#define TDA_COARSER 1
#define TDA_FINER 2
#define TDA_OFFSETG 3
#define TDA_COARSEG 4
#define TDA_FINEG 5
#define TDA_OFFSETB 6
#define TDA_COARSEB 7
#define TDA_FINEB 8
#define TDA_CONTROL 9
#define TDA_VCO_R 10
#define TDA_DIVIDER 11
#define TDA_PHASEA 12
#define TDA_PHASEB 13
// define scale factor index for H and V
#define Hn 0 // H numerial for H scaler factor
#define Hd 1 // H denumerial for H scaler factor
#define Vn 2 // V numerial for V scaler factor
#define Vd 3 // V denumerial for V scaler factor
// function definition
Bool autofunction(Bool);
Bool white_balance();
void auto_zurac_preset();
Bool auto_clock_adjust();
Bool auto_phase_adjust();
void auto_set_hvpos();
Word auto_coarse_phase();
Word auto_get_width();
Long auto_get_asod(void);
void auto_get_zurac(Byte,Byte);
void auto_zurac_restore();
void auto_adc_restore();
void auto_adc_preset();
void auto_adc_clockphase();
void auto_adc_phase(Byte);
void auto_clock_change();
void auto_short_delay(Byte);
void auto_min_threshold(Byte);
void auto_set_mline(Word);
void auto_set_fline(Word);
void auto_set_asod();
//tonny void auto_set_asum();
Bool auto_wait_mline(Word);
Bool auto_wait_fline();
Bool auto_free_fline();
Bool auto_wait_asod();
//tonny Word auto_abs_word(Word);
Bool fg_auto_mode;
Byte IDATA autoBval;
/***************************************************************************
Function : autofunction
Purpose : auto adjust Clock,Phase,Hposition,Vposition
Input : Bool auto_flag not used (for compatible)
Output : Word ClockValue ADC clock value
Byte PhaseValue ADC phase value
Word HorPositionValue horizontal position value
Word VerPositionValue vertical position value
External :
Return : Bool True(sucess)/False(fail)
***************************************************************************/
Bool autofunction(Bool auto_flag)
{
Word IDATA clock;
Byte IDATA phase;
Bool fgResult;
fg_auto_mode = auto_flag;
phase = PhaseValue; // save original PhaseValue
clock = ClockValue; // save Original ClockValue
auto_adc_preset();
auto_zurac_preset();
ClockValue = autoInfo[ModeCounter].clock_def;
auto_clock_change();
auto_adc_clockphase();
fgResult = auto_clock_adjust();
if( !fgResult )
{
ClockValue = clock;
PhaseValue = phase;
auto_adc_restore();
auto_zurac_restore();
if( ModeCounter!=DosModeTable[0][0] && ModeCounter!=DosModeTable[0][1] )
return FALSE;
}
fgResult = auto_phase_adjust();
if( !fgResult )
{
ClockValue = clock;
PhaseValue = phase;
auto_adc_restore();
auto_zurac_restore();
return FALSE;
}
auto_set_hvpos();
if( isVGAabsent() )
{
ClockValue = clock;
PhaseValue = phase;
auto_adc_restore();
auto_zurac_restore();
return FALSE;
}
auto_adc_restore();
auto_zurac_restore();
return TRUE;
}
/***************************************************************************
Function : auto_zurac_preset
Purpose : preset auto adjust registers default value
Input :
Output :
External : Byte TruBuf[] i2c i/o buffer
Byte SlvAdr i2c slave address
Byte ByteCnt i2c i/o byte count
Return :
***************************************************************************/
void auto_zurac_preset()
{
Word gcwval;
gcwval = autoInfo[ModeCounter].sync_width +
autoInfo[ModeCounter].back_porch/8;
// set the start search point
SlvAdr = ZURAC_ADDRESS;
ByteCnt = 3;
TrmBuf[0] = ZRC_AH_START;
TrmBuf[1] = LOBYTE( gcwval );
TrmBuf[2] = HIBYTE( gcwval );
SendData();
gcwval = autoInfo[ModeCounter].width_def;
SlvAdr = ZURAC_ADDRESS;
ByteCnt = 3;
TrmBuf[0] = ZRC_IH_AWIDTH;
TrmBuf[1] = LOBYTE( gcwval );
TrmBuf[2] = HIBYTE( gcwval );
SendData();
SlvAdr = ZURAC_ADDRESS;
ByteCnt = 2;
TrmBuf[0] = 0x06;
TrmBuf[1] = 0x00;
SendData();
SlvAdr = ZURAC_ADDRESS;
ByteCnt = 2;
TrmBuf[0] = 0xA9;
TrmBuf[1] = 0x06;
SendData();
return;
}
/***************************************************************************
Function : auto_clock_adjust
Purpose : adjust clock value
Input :
Output : Word ClockValue ADC clock value(also for scaler)
External : Byte TruBuf[] i2c i/o buffer
Byte ModeCounter VGA mode index
Return : Bool True(success)/False(fail)
***************************************************************************/
Bool auto_clock_adjust()
{
Byte i,k;
Word hlen,clk1;
//tonny Long IDATA bestSOD,curSOD;
Long IDATA bestSOD;
clk1 = autoInfo[ModeCounter].clock_def;
#if (GOOD_AUTO==0)
for(i=0; i<3; i++)
{
if( isVGAabsent() ) return FALSE;
auto_adc_clockphase();
auto_clock_change();
for(k=0; k<3; k++) /* give it 3 times to verify h,v length */
{
hlen = auto_coarse_phase();
ClockValue = (Word)(((long)ClockValue * (long)autoInfo[ModeCounter].width_def) / hlen);
ClockValue = ClockValue & 0xFFFC;
if( (ClockValue>=(clk1+180)) || (ClockValue<=(clk1-180)) )
{
if( ModeCounter==DosModeTable[0][0] ) /* 720x400/70Hz, DOS screen */
break;
else
ClockValue = clk1;
}
else
{
break;
}
}
if( k==3 ) continue;
if( hlen>autoInfo[ModeCounter].width_def )
ClockValue -= 4;
else if( hlen<autoInfo[ModeCounter].width_def )
ClockValue += 4;
break;
}
#else
for(i=0; i<3; i++)
{
if( isVGAabsent() ) return FALSE;
auto_adc_clockphase();
auto_clock_change();
hlen = auto_coarse_phase();
ClockValue = (Word)(((long)ClockValue * (long)autoInfo[ModeCounter].width_def) / hlen);
ClockValue = ClockValue & 0xFFFC;
if( (ClockValue>=(clk1+180)) || (ClockValue<=(clk1-180)) )
{
if( ModeCounter==DosModeTable[0][0] ) /* 720x400/70Hz, DOS screen */
break;
else
ClockValue = clk1;
}
else
{
if( hlen>autoInfo[ModeCounter].width_def )
ClockValue -= 4;
else if( hlen<autoInfo[ModeCounter].width_def )
ClockValue += 4;
break;
}
}
#endif
if( i==3 ) return FALSE;
if( ModeCounter==DosModeTable[0][0] ) /* 720x400/70Hz, DOS screen */
{
ClockValue = autoInfo[ModeCounter].clock_def;
bestSOD = auto_get_asod();
autoBval = PhaseValue;
}
else /* normal auto function */
{
for(i=k=0; i<5; i++)
{
if( isVGAabsent() ) return FALSE;
auto_adc_clockphase();
auto_clock_change();
hlen = auto_coarse_phase();
if( hlen==autoInfo[ModeCounter].width_def )
{
clk1 = ClockValue;
autoBval = PhaseValue;
break;
}
else if( hlen > autoInfo[ModeCounter].width_def )
{
if( k==2 )
{
#if 1
if( hlen==(autoInfo[ModeCounter].width_def+1) )
clk1 = ClockValue;
else
clk1 = ClockValue - 4;
#else
clk1 = ClockValue-4;
#endif
autoBval = PhaseValue;
break;
}
else
{
ClockValue -= 4;
k = 1;
}
}
else /* hlen < autoInfo[ModeCounter].width_def */
{
if( k==1 )
{
clk1 = ClockValue;
autoBval = PhaseValue;
break;
}
else
{
ClockValue += 4;
k = 2;
}
}
} /* of for(i=0;..) */
ClockValue = clk1;
}
if( isVGAabsent() ) return FALSE;
auto_clock_change();
auto_adc_clockphase();
return TRUE;
}
/***************************************************************************
Function : auto_phase_adjust
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -