📄 tw88.c
字号:
#ifdef DEBUG
dPrintf("\r\n SetPHP : %04x----------", (WORD)php); // test only
#endif
// TW8804 write LSByte first
val = ReadDecoder(0xb6);
val &= 0xf0; //0xf8; cut D
val |= (BYTE)(php>>8);
WriteDecoder(0xb6, val);
WriteDecoder(0xb2, php); // A9, AD = Panel Hsync Cycle
}
#endif //#if defined SUPPORT_PC || defined SUPPORT_DTV
/////////////////////////////////////////////////////////////////////////////
// Mapping( int fromValue, CRegInfo fromRange,
// int * toValue, CRegInfo toRange )
// Purpose: Map a value in certain range to a value in another range
// Input: int fromValue - value to be mapped from
// CRegInfo fromRange - range of value mapping from
// CRegInfo toRange - range of value mapping to
// Output: int * toValue - mapped value
// Return: Fail if error in parameter, else Success
// Comment: No range checking is performed here. Assume parameters are in
// valid ranges.
// The mapping function does not assume default is always the mid
// point of the whole range. It only assumes default values of the
// two ranges correspond to each other.
//
// The mapping formula is:
//
// For fromRange.Min() <= fromValue <= fromRange.Default():
//
// (fromValue -fromRange.Min())* (toRange.Default() - toRange.Min())
// -------------------------------------------------------------------- + toRange.Min()
// fromRange.Default() - fromRange.Min()
//
// For fromRange.Default() < fromValue <= fromRange.Max():
//
// (fromValue - fromRange.Default()) * (toRange.Max() - toRange.Default())
// --------------------------------------------------------------------- + toRange.Default()
// fromRange.Max() - fromRange.Default()
////
////////////////////////////////////////////////////////////////////////////
BYTE Mapping1( int fromValue, CODE_P struct RegisterInfo *fromRange,
int * toValue, CODE_P struct RegisterInfo *toRange ){
// calculate intermediate values
int a;
int b;
// perform mapping
if ( fromValue <= fromRange->Default ) {
a = toRange->Default - toRange->Min;
b = fromRange->Default - fromRange->Min;
// prevent divide by zero
if( b==0 ) return (FALSE);
*toValue = (int) ( (DWORD)fromValue- (DWORD)fromRange->Min ) * a / b
+(DWORD)toRange->Min;
}
else {
a = toRange->Max - toRange->Default;
b = fromRange->Max - fromRange->Default;
// prevent divide by zero
if( b==0 ) return (FALSE);
*toValue = (int) ( (DWORD)fromValue - (DWORD)fromRange->Default ) * a / b
+ (DWORD)toRange->Default;
}
#ifdef DEBUG_OSD
dPrintf("\r\n++(Mapping1)%d(%d-%d-%d)", (WORD)fromValue, (WORD)fromRange->Min, (WORD)fromRange->Default, (WORD)fromRange->Max );
dPrintf("->%d(%d-%d)", (WORD)*toValue, (WORD)toRange->Min, (WORD)toRange->Max);
#endif
return ( TRUE );
}
#ifndef KEILC
#ifdef SUPPORT_PC
BYTE Mapping2( int fromValue, IDATA_P struct RegisterInfo *fromRange,
int * toValue, CODE_P struct RegisterInfo *toRange ){
// calculate intermediate values
int a;
int b;
// perform mapping
if ( fromValue <= fromRange->Default ) {
a = toRange->Default - toRange->Min;
b = fromRange->Default - fromRange->Min;
// prevent divide by zero
if( b==0 ) return (FALSE);
*toValue = (int) ( (DWORD)fromValue- (DWORD)fromRange->Min ) * a / b
+(DWORD)toRange->Min;
}
else {
a = toRange->Max - toRange->Default;
b = fromRange->Max - fromRange->Default;
// prevent divide by zero
if( b==0 ) return (FALSE);
*toValue = (int) ( (DWORD)fromValue - (DWORD)fromRange->Default ) * a / b
+ (DWORD)toRange->Default;
}
#ifdef DEBUG_OSD
dPrintf("\r\n++(Mapping2)%d(%d-%d-%d)", (WORD)fromValue, (WORD)fromRange->Min, (WORD)fromRange->Default,
(WORD)fromRange->Max );
dPrintf("->%d(%d-%d)", (WORD)*toValue, (WORD)toRange->Min, (WORD)toRange->Max);
#endif
return ( TRUE );
}
#endif
BYTE Mapping3( int fromValue, CODE_P struct RegisterInfo *fromRange,
int * toValue, IDATA_P struct RegisterInfo *toRange ){
// calculate intermediate values
int a;
int b;
// perform mapping
if ( fromValue <= fromRange->Default ) {
a = toRange->Default - toRange->Min;
b = fromRange->Default - fromRange->Min;
// prevent divide by zero
if( b==0 ) return (FALSE);
*toValue = (int) ( (DWORD)fromValue- (DWORD)fromRange->Min ) * a / b
+(DWORD)toRange->Min;
}
else {
a = toRange->Max - toRange->Default;
b = fromRange->Max - fromRange->Default;
// prevent divide by zero
if( b==0 ) return (FALSE);
*toValue = (int) ( (DWORD)fromValue - (DWORD)fromRange->Default ) * a / b
+ (DWORD)toRange->Default;
}
#ifdef DEBUG_OSD
dPrintf("\r\n++(Mapping3)%d(%d-%d-%d)", (WORD)fromValue, (WORD)fromRange->Min, (WORD)fromRange->Default,
(WORD)fromRange->Max );
dPrintf("->%d(%d-%d)", (WORD)*toValue, (WORD)toRange->Min, (WORD)toRange->Max);
#endif
return ( TRUE );
}
#endif
//Hans
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
void ResetStatusRegs(void)
{
ClearEnDet();
WriteTW88(STATUS0, 0xff); // clear status
WriteTW88(STATUS1, 0xff); // clear status
SetEnDet();
}
#endif
//Hans
BYTE FindDecodeSettingIndex(cMode)
{
BYTE i;
for (i=0;i<4;i++)
{
if (cMode == cModeIndex[i])
break;
}
if (i > 3) i = 0; // default 480i
return i;
}
//Hans
void SetDecodeWindow(BYTE cIndex)
{
BYTE cTemp;
#ifdef DEBUG_DECODER
dPrintf("\r\n++(SetDecodeWindow)decode setting index:%02x", (BYTE)cIndex);
#endif
cTemp = (BYTE)((DecoderFormat[cIndex].VDelay & 0x300) >> 2); // bit6-bit7 of reg 0x007
cTemp |= (BYTE)((DecoderFormat[cIndex].VActive & 0x300) >> 4); // bit4-bit5 of reg 0x007
cTemp |= (BYTE)((DecoderFormat[cIndex].HDelay & 0x300) >> 6); // bit2-bit3 of reg 0x007
cTemp |= (BYTE)((DecoderFormat[cIndex].HActive & 0x300) >> 8); // bit0-bit1 of reg 0x007
WriteTW88(0xff, 0x00); // page 0
WriteDecoder(0x1C, 0x0f); // Disable the shadow registers.
WriteDecoder(0x07, cTemp);
WriteDecoder(0x08, (BYTE)(DecoderFormat[cIndex].VDelay & 0xff)); // vdelay
WriteDecoder(0x09, (BYTE)(DecoderFormat[cIndex].VActive & 0xff)); // vactive
WriteDecoder(0x0A, (BYTE)(DecoderFormat[cIndex].HDelay & 0xff)); // hdelay
WriteDecoder(0x0B, (BYTE)(DecoderFormat[cIndex].HActive & 0xff)); // hactive
}
// Hans
void InputSetup(void)
{
BYTE cTemp;
BYTE cReg38=0x80; // Input from Decoder path
BYTE cReg42, cReg44;
#ifdef DEBUG
dPrintf("\r\n InputSetup ==========");
#endif
AudioOff();
PanelMute(TRUE);
WriteTW88(0xff, 0); // page 0
switch(InputSelection)
{
#ifdef SUPPORT_SVIDEO
case SVIDEO:
break;
#endif
#ifdef SUPPORT_COMPONENT
case COMPONENT:
break;
#endif
#ifdef SUPPORT_PC
case PC:
cReg38 = 0; // change Anti Aliasing filter path to RGB
AutoPHPCalDisable();
break;
#endif
#ifdef SUPPORT_DTV
case DTV:
cReg42 |= 0x80; //Enable field detection for Digital input port
AutoPHPCalDisable();
break;
#endif
#ifdef SUPPORT_TV
case TV:
GetFirstChannel();
break;
#endif
case COMPOSITE:
default:
InputSelection = COMPOSITE; // default to composite source
break;
}
cReg42 = InputMatrix[InputSelection].cDataOrder;
cReg44 = InputMatrix[InputSelection].cDataFormat | InputMatrix[InputSelection].cInputRoute;
cTemp = 0x40; // Input crystal clock frequency is 27MHz.
cTemp |= InputMatrix[InputSelection].cIFSEL;
cTemp |= (InputMatrix[InputSelection].cYSEL & 0x03) << 2;
cTemp |= (InputMatrix[InputSelection].cCSEL & 0x02) << 6; // bit7 of reg002
cTemp |= (InputMatrix[InputSelection].cCSEL & 0x01) << 1; // bit1 of reg002
cTemp |= InputMatrix[InputSelection].cVSEL & 0x01;
WriteDecoder(INFORM, cTemp);
cTemp = 0;
cTemp |= ((InputMatrix[InputSelection].cYSEL == 0xF0) ? 0x04 : 0);
cTemp |= ((InputMatrix[InputSelection].cCSEL == 0xF0) ? 0x02 : 0);
cTemp |= ((InputMatrix[InputSelection].cVSEL == 0xF0) ? 0x01 : 0);
WriteDecoder(ACNTL, cTemp);
#ifdef SUPPORT_TV
if (InputSelection == TV)
WriteDecoder(0x18, 0x47);// IF compensation leve is 6dB
else
#endif
WriteDecoder(0x18, 0x44);// IF compensation leve is 0dB
WriteDecoder(0x38, cReg38 | 0x0E); // disable anti-alising filter.
if (InputMatrix[InputSelection].cInputRoute == IS_DECODER) // route through decoder
{
SetDecodeWindow(FindDecodeSettingIndex(EE_YPbPr_480I)); // default NTSC settings
WriteTW88(SHARPNESS, 0x21); // CTI = 2 // SHARP = 1
// WriteDecoder(V_CONTROL2, 0x15); // Set CC line number of Even Field
// WriteDecoder(CC_ODDLINE, 0x15); // Set CC line number of Odd Field
}
WriteTW88(0x5c, 0x06); // change error tolerance and enable V/HSYNC change/loss detection
WriteTW88(0x40, 0x00);
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
if ((InputSelection == PC) || (InputSelection == DTV))
WriteTW88(0x41, 0x00);
else
#endif
WriteTW88(0x41, 0x20); //Select Explicit DE ( Data Enable also called HA for Horizontal Active);
WriteTW88(0x42, cReg42);
WriteTW88(0x43, 0x00); // "0x20" 8mA // reserved // HLIU 2008-02-28
WriteTW88(0x44, cReg44);
WriteTW88(0x45, 0x3b);
WriteTW88( 0x5c, (ReadTW88(0x5c) & 0x0f) | 0x30 ); // Noise Mask: 3
WriteTW88( 0x5d, (ReadTW88(0x5d) & 0x0f) | 0x30 ); // active detect threshold: 3
// config black white stretch
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
if ((InputSelection == PC) || (InputSelection == DTV))
WriteTW88(0x7C, (BYTE)(ReadTW88(0x7C) & 0xFE)); // Disable black white stretch.
else
#endif
WriteTW88(0x7C, 0x1D); // Enable black white stretch.
ADCDefaultsSet();
SaveInputSelectionEE(InputSelection); // HHY 1.31
ExtAudio();
}
void MeasureSetup(void)
{
#ifdef DEBUG
dPrintf("\r\n MeasureSetup ==========");
#endif
#if defined(SUPPORT_PC) || defined(SUPPORT_DTV)
//------- Assume the PC_XGA input, 60Hz Refresh -----------------
SetMeasureWindowH(1, 1400); // default window to 1400
SetMeasureWindowV(1, 1200); //1200
#endif
WriteTW88( 0xff, 0x00); // page 0
if (IsDecoderSource())
{
SetAutoDetectStd();
WriteDecoder(CSTATUS, 0xff); // clear CSTATUS
}
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
ResetStatusRegs();
#endif
WriteTW88(ACNTL, (BYTE)(ReadTW88(0x06) | 0x80)); // Software Reset
}
// Hans
BYTE SourceConfigAndDisplay(void)
{
BYTE cTemp;
WORD wTemp;
WORD hstart, vstart, width, height;
#ifndef WIDE_SCREEN
DWORD scale;
#endif
#ifdef DEBUG
dPrintf("\r\n SourceConfigAndDisplay ==========");
#endif
WriteTW88(0xff, 0); // page 0
// make sure syncs were detected
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
if ((InputSelection == PC) || (InputSelection == DTV))
{
if (( ReadTW88(STATUS0) & 0x01 ) == 0) { // no sync input
#ifdef DEBUG_PC
Puts("\r\nSourceConfigAndDisplay (pc/dtv) ========== sync loss");
#endif
return FALSE;
}
}
else
#else
if (IsNoInput()) // no decoder input
{
#ifdef SUPPORT_TV
if (InputSelection != TV)
#endif
{
#ifdef DEBUG_PC
Puts("\r\nSourceConfigAndDisplay (decoder source)========== sync loss");
#endif
return FALSE;
}
}
#endif
#ifdef SUPPORT_COMPONENT
if (InputSelection == COMPONENT)
{
cTemp = ReadDecoder(0x02);
cTemp &= 0xCF; // clear IFSEL
if ((PcMode == EE_YPbPr_480I) ||(PcMode == EE_YPbPr_576I))
{
cTemp |= D_COMPONENT_I; // IFSEL xx10xxxx (Interlace input)
}
else
{
cTemp |= D_COMPONENT_P; // IFSEL xx11xxxx (Progressive input)
}
WriteDecoder(0x02, cTemp);
}
#endif
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
if (InputSelection == PC)
{
if (IsModeSaved(PcMode))
GetPCDataEE(PcMode);
else
DoMeasurement();
GetInitPanelAttribute1(); // Set Panel Brightness / Contrast
// disable peaking and sharpness
WriteTW88( 0x77, 0 );
WriteTW88( 0x78, 0 );
}
else
#endif
{
hstart = PCMDATA[PcMode].Hstart;
vstart = PCMDATA[PcMode].Vstart;
width = PCMDATA[PcMode].HAN;
height = PCMDATA[PcMode].VAN;
if (IsDecoderSource())
{
cTemp = FindDecodeSettingIndex(PcMode);
SetDecodeWindow(cTemp);
width = DecoderFormat[cTemp].ScaleWidth; // scalewidth = HSCALE * panel.hative / 65536;
height = DecoderFormat[cTemp].ScaleHeight;// scaleheight = VSCALE * panel.vative / 65536;
}
SetHactiveStart(hstart);
wTemp = hstart + width + hstart;
SetHactiveEnd(wTemp);
SetVactiveStart(vstart);
wTemp = vstart + height + 1;
SetVactiveLen(wTemp);
#ifdef WIDE_SCREEN
Set4WideScreen(GetWideModeEE());
#else
// scaler config
scale = width; // scale = (65536 * hactive + panel.hative / 2) / panel.hative
scale *= 0x10000L;
scale += PanelData.HActive / 2;
scale /= PanelData.HActive;
XScale2(scale);
#ifdef DEBUG
dPrintf("\r\nH scale: %xh - %xh", (WORD)(scale>>8), (WORD)(scale & 0xff));
#endif
scale = height; // scale = (65536 * vactive + panel.vative / 2) / panel.vative
scale *= 0x10000L;
scale += PanelData.VActive / 2;
scale /= PanelData.VActive;
YScale2(scale);
#ifdef DEBUG
dPrintf("\r\nV scale: %xh - %xh", (WORD)(scale>>8), (WORD)(scale & 0xff));
#endif
#endif
SetVideoMode( GetVideoModeEE());
ConfigPanel(); // restore panel settings
}
PanelMute(0);
AudioOn();
WriteTW88( 0xff, 0 );
#if (defined SUPPORT_PC) || (defined SUPPORT_DTV)
ResetStatusRegs();
#endif
ClearOSDInfo();
DisplayInput();
return TRUE;
}
// hans
void InitCCFL(void)
{
BYTE cPage;
cPage = ReadTW88(0xff); // save page
WriteTW88(0xff, 0x01); // page 1
WriteTW88(0xb1, 0x30);
WriteTW88(0x30, 0xF3);
WriteTW88(0x31, 0xAD);
WriteTW88(0x32, 0x04);
WriteTW88(0x33, 0x80);
WriteTW88(0x34, 0x84);
WriteTW88(0x35, 0x00);
WriteTW88(0x36, 0x20);
WriteTW88(0x30, 0xf1);
WriteTW88(0xff, cPage); // restore page num.
}
// Hans
extern CODE BYTE cTCON_Init[];
void ConfigTCON(void)
{
#ifndef TICONLESS
I2CDeviceInitialize(cTCON_Init);
#endif
}
// Hans
void ConfigPanel(void)
{
BYTE page, val;
#ifdef DEBUG
dPrintf("\r\n ConfigPanel --------------"); // test only
#endif
page = ReadTW88(0xff);
WriteTW88(0xff, 0);
#ifndef TICONLESS
// GPIO1/GPIO2 control
WriteTW88(0x4e, 0x66); // select TCON RD_UD signal for pin output; select TCON CD_LR signal for pin output
#endif
WriteTW88(0xb0, PanelData.OutputFlags); // DE and FPCLK is high,others are low.
#ifdef SAMSUNG_LTP700WV
WriteTW88(0xb1, 0x84); // enable TCON and FPCLK delay is 5
#else
WriteTW88(0xb1, 0x80); // enable TCON
#endif
val = ReadTW88(0xb6);
val &= 0xf0; // clear bit0-bit3
val |= (BYTE)((PanelData.HPeriod & 0xf00)>>8);
val &= 0x8f; // clear bit4-bit6
val |= (BYTE) ((PanelData.HActive & 0x700)>>4);
WriteTW88(0xb6, val);
WriteTW88(0xb2, (PanelData.HPeriod & 0xff));
WriteTW88(0xb3, PanelData.HSync);
WriteTW88(0xb4, PanelData.HBackporch);
WriteTW88(0xb5, (PanelData.HActive & 0xff));
val = ReadTW88(0xbb);
val &= 0xf8; // clear bit0-bit2
val |= (BYTE)(PanelData.VPeriod>>8) & 0x07;
val &= 0x8f; // clear bit4-bit6
val |= (BYTE) ((PanelData.VActive & 0x700)>>4);
WriteTW88( 0xbb, val);
WriteTW88(0xb7, (PanelData.VPeriod & 0xff));
WriteTW88(0xb8, PanelData.VSync);
WriteTW88(0xb9, PanelData.VBackporch);
WriteTW88(0xba, (PanelData.VActive & 0xff));
#ifdef WQVGA
WriteTW88(0xbc, 0x00); // analog RGB ouput
#else
WriteTW88(0xbc, 0x21); // 6bit output format
#endif
WriteTW88(0xbd, 0x08); // Output Vsync delay from Input Vsync
WriteTW88(0xbe, 0xc2);
// DAC settings for analog panel
WriteTW88(0xf6, 0x1f); // DAC R channel gain
WriteTW88(0xf7, 0x1f); // DAC G channel gain
WriteTW88(0xf8, 0x1f); // DAC B channel gain
ChangeInternPLL(PanelData.DClock * 1000000L); // 0xf9,0xfa,0xfb and 0xfe of page 0
WriteTW88(0xfc, 0x40);
WriteTW88(0xfd, 0x30);
WriteTW88(0xff, page);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -