You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1358 lines
48 KiB
1358 lines
48 KiB
//==========================================================================;
|
|
//
|
|
// Decoder - Main decoder implementation
|
|
//
|
|
// $Date: 21 Aug 1998 21:46:26 $
|
|
// $Revision: 1.1 $
|
|
// $Author: Tashjian $
|
|
//
|
|
// $Copyright: (c) 1997 - 1998 ATI Technologies Inc. All Rights Reserved. $
|
|
//
|
|
//==========================================================================;
|
|
|
|
#include "mytypes.h"
|
|
#include "Scaler.h"
|
|
#include "decoder.h"
|
|
#include "dcdrvals.h"
|
|
|
|
#include "capmain.h"
|
|
|
|
#define CON_vs_BRI // HW does contrast incorrectly, try to adjust in SW
|
|
|
|
|
|
//===========================================================================
|
|
// Bt848 Decoder Class Implementation
|
|
//===========================================================================
|
|
|
|
#define REGALIGNMENT 1
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Constructor
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Decoder::Decoder(PDEVICE_PARMS pDeviceParms) :
|
|
// init register min, max, default
|
|
m_regHue(HueMin, HueMax, HueDef),
|
|
m_regSaturationNTSC(SatMinNTSC, SatMaxNTSC, SatDefNTSC),
|
|
m_regSaturationSECAM(SatMinSECAM, SatMaxSECAM, SatDefSECAM),
|
|
m_regContrast(ConMin, ConMax, ConDef),
|
|
m_regBrightness(BrtMin, BrtMax, BrtDef),
|
|
m_param(ParamMin, ParamMax, ParamDef),
|
|
|
|
decRegSTATUS (((0x00 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldHLOC(decRegSTATUS, 6, 1, RW) ,
|
|
decFieldNUML(decRegSTATUS, 4, 1, RW) ,
|
|
decFieldCSEL(decRegSTATUS, 3, 1, RW) ,
|
|
decFieldSTATUS_RES(decRegSTATUS, 2, 1, RW) ,
|
|
decFieldLOF(decRegSTATUS, 1, 1, RW) ,
|
|
decFieldCOF(decRegSTATUS, 0, 1, RW) ,
|
|
decRegIFORM (((0x01 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldHACTIVE(decRegIFORM, 7, 1, RW) ,
|
|
decFieldMUXSEL(decRegIFORM, 5, 2, RW) ,
|
|
decFieldXTSEL(decRegIFORM, 3, 2, RW) ,
|
|
decFieldFORMAT(decRegIFORM, 0, 3, RW) ,
|
|
decRegTDEC (((0x02 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldDEC_FIELD(decRegTDEC, 7, 1, RW) ,
|
|
decFieldDEC_FIELDALIGN(decRegTDEC, 6, 1, RW) ,
|
|
decFieldDEC_RAT(decRegTDEC, 0, 6, RW) ,
|
|
decRegBRIGHT (((0x0A + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegMISCCONTROL (((0x0B + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldLNOTCH(decRegMISCCONTROL, 7, 1, RW) ,
|
|
decFieldCOMP(decRegMISCCONTROL, 6, 1, RW) ,
|
|
decFieldLDEC(decRegMISCCONTROL, 5, 1, RW) ,
|
|
decFieldMISCCONTROL_RES(decRegMISCCONTROL, 3, 1, RW) ,
|
|
decFieldCON_MSB(decRegMISCCONTROL, 2, 1, RW) ,
|
|
decFieldSAT_U_MSB(decRegMISCCONTROL, 1, 1, RW) ,
|
|
decFieldSAT_V_MSB(decRegMISCCONTROL, 0, 1, RW) ,
|
|
decRegCONTRAST_LO (((0x0C + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegSAT_U_LO (((0x0D + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegSAT_V_LO (((0x0E + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegHUE (((0x0F + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegSCLOOP (((0x10 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldCAGC(decRegSCLOOP, 6, 1, RW) ,
|
|
decFieldCKILL(decRegSCLOOP, 5, 1, RW) ,
|
|
decRegWC_UP(((0x11 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegOFORM (((0x12 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldVBI_FRAME(decRegOFORM, 4, 1, RW) ,
|
|
decFieldCODE(decRegOFORM, 3, 1, RW) ,
|
|
decFieldLEN(decRegOFORM, 2, 1, RW) ,
|
|
decRegVSCALE_HI (((0x13 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldYCOMB(decRegVSCALE_HI, 7, 1, RW) ,
|
|
decFieldCOMB(decRegVSCALE_HI, 6, 1, RW) ,
|
|
decFieldINT(decRegVSCALE_HI, 5, 1, RW) ,
|
|
decRegTEST (((0x15 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegVPOLE (((0x16 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldOUT_EN (decRegVPOLE, 7, 1, RW),
|
|
decFieldDVALID (decRegVPOLE, 6, 1, RW),
|
|
decFieldVACTIVE (decRegVPOLE, 5, 1, RW),
|
|
decFieldCBFLAG (decRegVPOLE, 4, 1, RW),
|
|
decFieldFIELD (decRegVPOLE, 3, 1, RW),
|
|
decFieldACTIVE (decRegVPOLE, 2, 1, RW),
|
|
decFieldHRESET (decRegVPOLE, 1, 1, RW),
|
|
decFieldVRESET (decRegVPOLE, 0, 1, RW),
|
|
decRegADELAY (((0x18 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegBDELAY (((0x19 + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegADC (((0x1A + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldCLK_SLEEP(decRegADC, 3, 1, RW) ,
|
|
decFieldC_SLEEP(decRegADC, 1, 1, RW) ,
|
|
decFieldCRUSH(decRegADC, 0, 1, RW),
|
|
decRegVTC (((0x1B + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decFieldHSFMT(decRegVTC, 7, 1, RW) ,
|
|
decRegWC_DN(((0x1E + 0) * REGALIGNMENT) + 0, RW, pDeviceParms) ,
|
|
decRegSRESET (((0x1F + 0) * REGALIGNMENT) + 0, RW, pDeviceParms),
|
|
decRegODD_MISCCONTROL (((0x0B + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
|
|
decFieldODD_LNOTCH(decRegODD_MISCCONTROL, 7, 1, RW) ,
|
|
decFieldODD_COMP(decRegODD_MISCCONTROL, 6, 1, RW) ,
|
|
decFieldODD_LDEC(decRegODD_MISCCONTROL, 5, 1, RW) ,
|
|
decFieldODD_CBSENSE(decRegODD_MISCCONTROL, 4, 1, RW) ,
|
|
decFieldODD_MISCCONTROL_RES(decRegODD_MISCCONTROL, 3, 1, RW) ,
|
|
decFieldODD_CON_MSB(decRegODD_MISCCONTROL, 2, 1, RW) ,
|
|
decFieldODD_SAT_U_MSB(decRegODD_MISCCONTROL, 1, 1, RW) ,
|
|
decFieldODD_SAT_V_MSB(decRegODD_MISCCONTROL, 0, 1, RW) ,
|
|
decRegODD_SCLOOP (((0x10 + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
|
|
decFieldODD_CAGC(decRegODD_SCLOOP, 6, 1, RW) ,
|
|
decFieldODD_CKILL(decRegODD_SCLOOP, 5, 1, RW) ,
|
|
decFieldODD_HFILT(decRegODD_SCLOOP, 3, 2, RW) ,
|
|
decRegODD_VSCALE_HI (((0x13 + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
|
|
decFieldODD_YCOMB(decRegODD_VSCALE_HI, 7, 1, RW) ,
|
|
decFieldODD_COMB(decRegODD_VSCALE_HI, 6, 1, RW) ,
|
|
decFieldODD_INT(decRegODD_VSCALE_HI, 5, 1, RW) ,
|
|
decRegODD_VTC (((0x1B + -0x03) * REGALIGNMENT) + 0x8C, RW, pDeviceParms) ,
|
|
decFieldODD_HSFMT(decRegODD_VTC, 7, 1, RW)
|
|
{
|
|
if(!(pDeviceParms->chipRev < 4))
|
|
{
|
|
// need to set this to 0x4F
|
|
decRegWC_UP = 0x4F;
|
|
// and this one to 0x7F to make sure CRUSH bit works for not plain vanila BT829
|
|
decRegWC_DN = 0x7F;
|
|
}
|
|
|
|
// HACTIVE should always be 0
|
|
decFieldHACTIVE = 0;
|
|
|
|
decFieldHSFMT = 0;
|
|
|
|
// The following lines were commented out in an attempt to
|
|
// have a picture which closely matches what an ordinary TV would
|
|
// show. However, it should be noted that Brooktree recommended to
|
|
// comment out only the 'SetLowColorAutoRemoval' line. Probably the
|
|
// best solution of all would be to somehow expose these options
|
|
// to the application.
|
|
|
|
// Instead of using default values, set some registers fields to optimum values
|
|
/*
|
|
SetLumaDecimation(TRUE);
|
|
SetChromaAGC(TRUE);
|
|
SetLowColorAutoRemoval(FALSE);
|
|
SetAdaptiveAGC(FALSE);
|
|
*/
|
|
|
|
// for contrast adjustment purpose
|
|
regBright = 0x00; // brightness register value before adjustment
|
|
regContrast = 0xD8; // contrast register value before adjustment
|
|
m_supportedVideoStandards = KS_AnalogVideo_NTSC_M |
|
|
KS_AnalogVideo_NTSC_M_J |
|
|
KS_AnalogVideo_PAL_B |
|
|
KS_AnalogVideo_PAL_D |
|
|
KS_AnalogVideo_PAL_G |
|
|
KS_AnalogVideo_PAL_H |
|
|
KS_AnalogVideo_PAL_I |
|
|
KS_AnalogVideo_PAL_M |
|
|
KS_AnalogVideo_PAL_N; //Paul: what BT 829 can support (from L829A_A functional Description)
|
|
|
|
if(!(pDeviceParms->chipRev < 4))
|
|
m_supportedVideoStandards |= KS_AnalogVideo_SECAM_B |
|
|
KS_AnalogVideo_SECAM_D |
|
|
KS_AnalogVideo_SECAM_G |
|
|
KS_AnalogVideo_SECAM_H |
|
|
KS_AnalogVideo_SECAM_K |
|
|
KS_AnalogVideo_SECAM_K1 |
|
|
KS_AnalogVideo_SECAM_L |
|
|
KS_AnalogVideo_SECAM_L1;
|
|
|
|
m_supportedVideoStandards &= pDeviceParms->ulVideoInStandardsSupportedByCrystal; //Paul: AND with whatever supported by the onboard crystal
|
|
|
|
// jaybo
|
|
// loop until we find a supported TV standard, and use that to init
|
|
UINT k;
|
|
for (k = 1; k; k += k) {
|
|
if (k & m_supportedVideoStandards) {
|
|
SetVideoDecoderStandard(k);
|
|
break;
|
|
}
|
|
}
|
|
// end jaybo
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Destructor
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Decoder::~Decoder()
|
|
{
|
|
}
|
|
|
|
|
|
void Decoder::GetVideoDecoderCaps(PKSPROPERTY_VIDEODECODER_CAPS_S pS)
|
|
{
|
|
pS->StandardsSupported = m_supportedVideoStandards;
|
|
|
|
pS->Capabilities = KS_VIDEODECODER_FLAGS_CAN_DISABLE_OUTPUT |
|
|
KS_VIDEODECODER_FLAGS_CAN_INDICATE_LOCKED ;
|
|
|
|
// How long (ms) til locked indicator is valid.
|
|
// 31 line periods * 63.5uS per line.
|
|
pS->SettlingTime = 2;
|
|
|
|
// Not sure about this
|
|
// HSync per VSync
|
|
pS->HSyncPerVSync = 6;
|
|
}
|
|
|
|
void Decoder::GetVideoDecoderStatus(PKSPROPERTY_VIDEODECODER_STATUS_S pS)
|
|
{
|
|
pS->NumberOfLines = Is525LinesVideo() ? 525 : 625;
|
|
pS->SignalLocked = decFieldHLOC == 1;
|
|
}
|
|
|
|
DWORD Decoder::GetVideoDecoderStandard()
|
|
{
|
|
return m_videoStandard; //Paul
|
|
}
|
|
|
|
BOOL Decoder::SetVideoDecoderStandard(DWORD standard)
|
|
{
|
|
if (m_supportedVideoStandards & standard) //Paul: standard must be a supported standard
|
|
{
|
|
m_videoStandard = standard;
|
|
|
|
switch ( m_videoStandard )
|
|
{
|
|
case KS_AnalogVideo_NTSC_M:
|
|
Decoder::SetVideoFormat(VFormat_NTSC);
|
|
break;
|
|
case KS_AnalogVideo_NTSC_M_J:
|
|
Decoder::SetVideoFormat(VFormat_NTSC_J);
|
|
break;
|
|
case KS_AnalogVideo_PAL_B:
|
|
case KS_AnalogVideo_PAL_D:
|
|
case KS_AnalogVideo_PAL_G:
|
|
case KS_AnalogVideo_PAL_H:
|
|
case KS_AnalogVideo_PAL_I:
|
|
Decoder::SetVideoFormat(VFormat_PAL_BDGHI); // PAL_BDGHI covers most areas
|
|
break;
|
|
case KS_AnalogVideo_PAL_M:
|
|
Decoder::SetVideoFormat(VFormat_PAL_M);
|
|
break;
|
|
case KS_AnalogVideo_PAL_N:
|
|
Decoder::SetVideoFormat(VFormat_PAL_N_COMB);
|
|
break;
|
|
default: //Paul: SECAM
|
|
Decoder::SetVideoFormat(VFormat_SECAM);
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
//===== Device Status register ==============================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::Is525LinesVideo()
|
|
// Purpose: Check to see if we are dealing with 525 lines video signal
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE if 525 lines detected; else FALSE (assume 625 lines)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::Is525LinesVideo()
|
|
{
|
|
return (BOOL) (decFieldNUML == 0); //525
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsCrystal0Selected()
|
|
// Purpose: Reflect whether XTAL0 or XTAL1 is selected
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE if XTAL0 selected; else FALSE (XTAL1 selected)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsCrystal0Selected()
|
|
{
|
|
return (BOOL) (decFieldCSEL == 0);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsLumaOverflow()
|
|
// Purpose: Indicates if luma ADC overflow
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE if luma ADC overflow; else FALSE
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsLumaOverflow()
|
|
{
|
|
return (BOOL) (decFieldLOF == 1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::ResetLumaOverflow()
|
|
// Purpose: Reset luma ADC overflow bit
|
|
// Input: None
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::ResetLumaOverflow()
|
|
{
|
|
decFieldLOF = 0; // write to it will reset the bit
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsChromaOverflow()
|
|
// Purpose: Indicates if chroma ADC overflow
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE if chroma ADC overflow; else FALSE
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsChromaOverflow()
|
|
{
|
|
return (BOOL) (decFieldCOF == 1);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::ResetChromaOverflow()
|
|
// Purpose: Reset chroma ADC overflow bit
|
|
// Input: None
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::ResetChromaOverflow()
|
|
{
|
|
decFieldCOF = 0; // write to it will reset the bit
|
|
}
|
|
|
|
|
|
//===== Input Format register ===============================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetVideoInput(Connector source)
|
|
// Purpose: Select which connector as input
|
|
// Input: Connector source - SVideo, Tuner, Composite
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetVideoInput(Connector source)
|
|
{
|
|
if ((source != ConSVideo) &&
|
|
(source != ConTuner) &&
|
|
(source != ConComposite))
|
|
return Fail;
|
|
|
|
decFieldMUXSEL = (ULONG)source + 1;
|
|
|
|
// set to composite or Y/C component video depends on video source
|
|
SetCompositeVideo((source == ConSVideo) ? FALSE : TRUE);
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: Connector Decoder::GetVideoInput()
|
|
// Purpose: Get which connector is input
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Video source - SVideo, Tuner, Composite
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Connector Decoder::GetVideoInput()
|
|
{
|
|
return ((Connector)(decFieldMUXSEL-1));
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetCrystal(Crystal crystalNo)
|
|
// Purpose: Select which crystal as input
|
|
// Input: Crystal crystalNo:
|
|
// XT0 - Crystal_XT0
|
|
// XT1 - Crystal_XT1
|
|
// Auto select - Crystal_AutoSelect
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetCrystal(Crystal crystalNo)
|
|
{
|
|
if ((crystalNo < Crystal_XT0) || (crystalNo > Crystal_AutoSelect))
|
|
return Fail;
|
|
|
|
decFieldXTSEL = crystalNo;
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetCrystal()
|
|
// Purpose: Get which crystal is input
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Crystal Number:
|
|
// XT0 - Crystal_XT0
|
|
// XT1 - Crystal_XT1
|
|
// Auto select - Crystal_AutoSelect
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetCrystal()
|
|
{
|
|
return ((int)decFieldXTSEL);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetVideoFormat(VideoFormat format)
|
|
// Purpose: Set video format
|
|
// Input: Video format -
|
|
// Auto format: VFormat_AutoDetect
|
|
// NTSC (M): VFormat_NTSC
|
|
// NTSC Japan: VFormat_NTSC_J
|
|
// PAL (B, D, G, H, I): VFormat_PAL_BDGHI
|
|
// PAL (M): VFormat_PAL_M
|
|
// PAL(N): VFormat_PAL_N
|
|
// SECAM: VFormat_SECAM
|
|
// PAN(N Combo) VFormat_PAL_N_COMB
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
// Notes: Available video formats are: NTSC, PAL(B, D, G, H, I), PAL(M),
|
|
// PAL(N), SECAM
|
|
// This function also sets the AGCDelay (ADELAY) and BrustDelay
|
|
// (BDELAY) registers
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetVideoFormat(VideoFormat format)
|
|
{
|
|
if ((format < VFormat_AutoDetect) ||
|
|
(format > VFormat_PAL_N_COMB))
|
|
return Fail;
|
|
|
|
switch (format)
|
|
{
|
|
case VFormat_PAL_M:
|
|
case VFormat_NTSC:
|
|
case VFormat_NTSC_J:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x68;
|
|
decRegBDELAY = 0x5D;
|
|
SetChromaComb(TRUE); // enable chroma comb
|
|
SelectCrystal('N'); // select NTSC crystal
|
|
break;
|
|
|
|
case VFormat_PAL_BDGHI:
|
|
case VFormat_PAL_N:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x7F;
|
|
decRegBDELAY = 0x72;
|
|
SetChromaComb(TRUE); // enable chroma comb
|
|
SelectCrystal('P'); // select PAL crystal
|
|
break;
|
|
|
|
case VFormat_PAL_N_COMB:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x7F;
|
|
decRegBDELAY = 0x72;
|
|
SetChromaComb(TRUE); // enable chroma comb
|
|
SelectCrystal('N'); // select NTSC crystal
|
|
break;
|
|
|
|
case VFormat_SECAM:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x7F;
|
|
decRegBDELAY = 0xA0;
|
|
SetChromaComb(FALSE); // disable chroma comb
|
|
SelectCrystal('P'); // select PAL crystal
|
|
break;
|
|
|
|
default: // VFormat_AutoDetect
|
|
// auto format detect by examining the number of lines
|
|
if (Decoder::Is525LinesVideo()) // lines == 525 -> NTSC
|
|
Decoder::SetVideoFormat(VFormat_NTSC);
|
|
else // lines == 625 -> PAL/SECAM
|
|
Decoder::SetVideoFormat(VFormat_PAL_BDGHI); // PAL_BDGHI covers most areas
|
|
}
|
|
|
|
SetSaturation(m_satParam);
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetVideoFormat()
|
|
// Purpose: Obtain video format
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Video format
|
|
// Auto format: VFormat_AutoDetect
|
|
// NTSC (M): VFormat_NTSC
|
|
// PAL (B, D, G, H, I): VFormat_PAL_BDGHI
|
|
// PAL (M): VFormat_PAL_M
|
|
// PAL(N): VFormat_PAL_N
|
|
// SECAM: VFormat_SECAM
|
|
// PAN(N Combo) VFormat_PAL_N_COMB
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetVideoFormat()
|
|
{
|
|
BYTE bFormat = (BYTE)decFieldFORMAT;
|
|
if (!bFormat) // autodetection enabled
|
|
return Is525LinesVideo() ? VFormat_NTSC : VFormat_SECAM;
|
|
else
|
|
return bFormat;
|
|
}
|
|
|
|
|
|
//===== Temporal Decimation register ========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetRate(BOOL fields, VidField even, int rate)
|
|
// Purpose: Set frames or fields rate
|
|
// Input: BOOL fields - TRUE for fields, FALSE for frames
|
|
// VidField even - TRUE to start decimation with even field, FALSE odd
|
|
// int rate - decimation rate: frames (1-50/60); fields(1-25/30)
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetRate(BOOL fields, VidField vf, int rate)
|
|
{
|
|
int nMax;
|
|
if (Is525LinesVideo() == TRUE)
|
|
nMax = 30; // NTSC
|
|
else
|
|
nMax = 25; // PAL/SECAM
|
|
|
|
// if setting frame rate, double the max value
|
|
if (fields == FALSE)
|
|
nMax *= 2;
|
|
|
|
if (rate < 0 || rate > nMax)
|
|
return Fail;
|
|
|
|
decFieldDEC_FIELD = (fields == FALSE) ? Off : On;
|
|
decFieldDEC_FIELDALIGN = (vf == VF_Even) ? On : Off;
|
|
int nDrop = (BYTE) nMax - rate;
|
|
decFieldDEC_RAT = (BYTE) (fields == FALSE) ? nDrop : nDrop * 2;
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
//===== Brightness Control register =========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetBrightness(int param)
|
|
// Purpose: Set video brightness
|
|
// Input: int param - parameter value (0-255; default 128)
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
// Note: See IsAdjustContrast() for detailed description of the contrast
|
|
// adjustment calculation
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetBrightness(int param)
|
|
{
|
|
if(m_param.OutOfRange(param))
|
|
return Fail;
|
|
|
|
// perform mapping to our range
|
|
int mapped;
|
|
if (Mapping(param, m_param, &mapped, m_regBrightness) == Fail)
|
|
return Fail;
|
|
|
|
m_briParam = (WORD)param;
|
|
|
|
// calculate brightness value
|
|
int value = (128 * mapped) / m_regBrightness.Max() ;
|
|
|
|
// need to limit the value to 0x7F (+50%) because 0x80 is -50%!
|
|
if ((mapped > 0) && (value == 0x80))
|
|
value = 0x7F;
|
|
|
|
// perform adjustment of brightness register if adjustment is needed
|
|
if (IsAdjustContrast())
|
|
{
|
|
regBright = value; // brightness value before adjustment
|
|
|
|
long A = (long)regBright * (long)0xD8;
|
|
long B = 64 * ((long)0xD8 - (long)regContrast);
|
|
long temp = 0x00;
|
|
if (regContrast != 0) // already limit contrast > zero; just in case here
|
|
temp = ((A + B) / (long)regContrast);
|
|
temp = (temp < -128) ? -128 : ((temp > 127) ? 127 : temp);
|
|
value = (BYTE)temp;
|
|
|
|
}
|
|
|
|
decRegBRIGHT = (BYTE)value;
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetBrightness()
|
|
// Purpose: Obtain brightness value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Brightness parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetBrightness()
|
|
{
|
|
return m_briParam;
|
|
}
|
|
|
|
|
|
//===== Miscellaneous Control register (E_CONTROL, O_CONTROL) ===============
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetLumaNotchFilter(BOOL mode)
|
|
// Purpose: Enable/Disable luma notch filter
|
|
// Input: BOOL mode - TRUE = Enable; FALSE = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetLumaNotchFilter(BOOL mode)
|
|
{
|
|
decFieldLNOTCH = (mode == FALSE) ? On : Off; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsLumaNotchFilter()
|
|
// Purpose: Check if luma notch filter is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = Enable; FALSE = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsLumaNotchFilter()
|
|
{
|
|
return (decFieldLNOTCH == Off) ? TRUE : FALSE; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetCompositeVideo(BOOL mode)
|
|
// Purpose: Select composite or Y/C component video
|
|
// Input: BOOL mode - TRUE = Composite; FALSE = Y/C Component
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetCompositeVideo(BOOL mode)
|
|
{
|
|
if (mode == TRUE)
|
|
{
|
|
// composite video
|
|
decFieldCOMP = Off;
|
|
Decoder::SetChromaADC(FALSE); // disable chroma ADC
|
|
Decoder::SetLumaNotchFilter(TRUE); // enable luma notch filter
|
|
}
|
|
else
|
|
{
|
|
// Y/C Component video
|
|
decFieldCOMP = On;
|
|
Decoder::SetChromaADC(TRUE); // enable chroma ADC
|
|
Decoder::SetLumaNotchFilter(FALSE); // disable luma notch filter
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetLumaDecimation(BOOL mode)
|
|
// Purpose: Enable/Disable luma decimation filter
|
|
// Input: BOOL mode - TRUE = Enable; FALSE = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetLumaDecimation(BOOL mode)
|
|
{
|
|
// value of 0 turns the decimation on
|
|
decFieldLDEC = (mode == TRUE) ? 0 : 1;
|
|
}
|
|
|
|
|
|
//===== Luma Gain register (CON_MSB, CONTRAST_LO) ===========================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetContrast(int param)
|
|
// Purpose: Set video contrast
|
|
// Input: int param - parameter value (0-255; default 128)
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
// Note: See IsAdjustContrast() for detailed description of the contrast
|
|
// adjustment calculation
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetContrast(int param)
|
|
{
|
|
if(m_param.OutOfRange(param))
|
|
return Fail;
|
|
|
|
BOOL adjustContrast = IsAdjustContrast(); // is contrast need to be adjusted
|
|
|
|
// if adjust contrast is needed, make sure contrast reg value != 0
|
|
if (adjustContrast)
|
|
m_regContrast = CRegInfo(1, ConMax, ConDef);
|
|
|
|
// perform mapping to our range
|
|
int mapped;
|
|
if (Mapping(param, m_param, &mapped, m_regContrast) == Fail)
|
|
return Fail;
|
|
|
|
m_conParam = (WORD)param;
|
|
|
|
// calculate contrast
|
|
DWORD value = (DWORD)0x1FF * (DWORD)mapped;
|
|
value /= (DWORD)m_regContrast.Max();
|
|
if (value > 0x1FF)
|
|
value = 0x1FF;
|
|
|
|
// contrast is set by a 9 bit value; set LSB first
|
|
decRegCONTRAST_LO = value;
|
|
|
|
// now set the Miscellaneous Control Register CON_V_MSB to the 9th bit value
|
|
decFieldCON_MSB = ((value & 0x0100) ? On : Off);
|
|
|
|
// perform adjustment of brightness register if adjustment is needed
|
|
if (adjustContrast)
|
|
{
|
|
regContrast = (WORD)value; // contrast value
|
|
|
|
long A = (long)regBright * (long)0xD8;
|
|
long B = 64 * ((long)0xD8 - (long)regContrast);
|
|
long temp = 0x00;
|
|
if (regContrast != 0) // already limit contrast > zero; just in case here
|
|
temp = ((A + B) / (long)regContrast);
|
|
temp = (temp < -128) ? -128 : ((temp > 127) ? 127 : temp);
|
|
decRegBRIGHT = (BYTE)temp;
|
|
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetContrast()
|
|
// Purpose: Obtain contrast value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Contrast parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetContrast()
|
|
{
|
|
return m_conParam;
|
|
}
|
|
|
|
|
|
//===== Chroma Gain register (SAT_U_MSB, SAT_V_MSB, SAT_U_LO, SAT_V_LO) =====
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetSaturation(int param)
|
|
// Purpose: Set color saturation by modifying U and V values
|
|
// Input: int param - parameter value (0-255; default 128)
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetSaturation(int param)
|
|
{
|
|
if(m_param.OutOfRange(param))
|
|
return Fail;
|
|
|
|
// color saturation is controlled by two nine bit values:
|
|
// ChromaU & ChromaV
|
|
// To maintain normal color balance, the ratio between the 2 register
|
|
// values should be kept at the power-up default ratio
|
|
|
|
// Note that U & V values for NTSC and PAL are the same, SECAM is different
|
|
|
|
WORD nominalNTSC_U = 0xFE; // nominal value (i.e. 100%) for NTSC/PAL
|
|
WORD nominalNTSC_V = 0xB4;
|
|
WORD nominalSECAM_U = 0x87; // nominal value (i.e. 100%) for SECAM
|
|
WORD nominalSECAM_V = 0x85;
|
|
|
|
CRegInfo regSat; // selected saturation register; NTSC/PAL or SECAM
|
|
WORD nominal_U, nominal_V; // selected nominal U and V value; NTSC/PAL or SECAM
|
|
|
|
// select U & V values of either NTSC/PAL or SECAM to be used for calculation
|
|
if (GetVideoFormat() == VFormat_SECAM)
|
|
{
|
|
nominal_U = nominalSECAM_U;
|
|
nominal_V = nominalSECAM_V;
|
|
regSat = m_regSaturationSECAM;
|
|
}
|
|
else
|
|
{
|
|
nominal_U = nominalNTSC_U;
|
|
nominal_V = nominalNTSC_V;
|
|
regSat = m_regSaturationNTSC;
|
|
}
|
|
|
|
// perform mapping to our range
|
|
int mapped;
|
|
if (Mapping(param, m_param, &mapped, regSat) == Fail)
|
|
return Fail;
|
|
|
|
m_satParam = (WORD)param;
|
|
|
|
WORD max_nominal = max(nominal_U, nominal_V);
|
|
|
|
// calculate U and V values
|
|
WORD Uvalue = (WORD) ((DWORD)mapped * (DWORD)nominal_U / (DWORD)max_nominal);
|
|
WORD Vvalue = (WORD) ((DWORD)mapped * (DWORD)nominal_V / (DWORD)max_nominal);
|
|
|
|
// set U
|
|
decRegSAT_U_LO = Uvalue;
|
|
|
|
// now set the Miscellaneous Control Register SAT_U_MSB to the 9th bit value
|
|
decFieldSAT_U_MSB = ((Uvalue & 0x0100) ? On : Off);
|
|
|
|
// set V
|
|
decRegSAT_V_LO = Vvalue;
|
|
|
|
// now set the Miscellaneous Control Register SAT_V_MSB to the 9th bit value
|
|
decFieldSAT_V_MSB = ((Vvalue & 0x0100) ? On : Off);
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetSaturation()
|
|
// Purpose: Obtain saturation value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Saturation parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetSaturation()
|
|
{
|
|
return m_satParam;
|
|
}
|
|
|
|
|
|
//===== Hue Control register (HUE) ==========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetHue(int param)
|
|
// Purpose: Set video hue
|
|
// Input: int param - parameter value (0-255; default 128)
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetHue(int param)
|
|
{
|
|
if(m_param.OutOfRange(param))
|
|
return Fail;
|
|
|
|
// perform mapping to our range
|
|
int mapped;
|
|
if (Mapping(param, m_param, &mapped, m_regHue) == Fail)
|
|
return Fail;
|
|
|
|
m_hueParam = (WORD)param;
|
|
|
|
int value = (-128 * mapped) / m_regHue.Max();
|
|
|
|
if (value > 127)
|
|
value = 127;
|
|
else if (value < -128)
|
|
value = -128;
|
|
|
|
decRegHUE = value;
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetHue()
|
|
// Purpose: Obtain hue value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Hue parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetHue()
|
|
{
|
|
return m_hueParam;
|
|
}
|
|
|
|
|
|
//===== SC Loop Control register (E_SCLOOP, O_SCLOOP) =======================
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetChromaAGC(BOOL mode)
|
|
// Purpose: Enable/Disable Chroma AGC compensation
|
|
// Input: BOOL mode - TRUE = Enable, FALSE = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetChromaAGC(BOOL mode)
|
|
{
|
|
decFieldCAGC = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsChromaAGC()
|
|
// Purpose: Check if Chroma AGC compensation is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = Enable, FALSE = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsChromaAGC()
|
|
{
|
|
return (decFieldCAGC == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetLowColorAutoRemoval(BOOL mode)
|
|
// Purpose: Enable/Disable low color detection and removal
|
|
// Input: BOOL mode - TRUE = Enable, FALSE = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetLowColorAutoRemoval(BOOL mode)
|
|
{
|
|
decFieldCKILL = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
|
|
//===== Output Format register (OFORM) ======================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetVBIFrameMode(BOOL mode)
|
|
// Purpose: Enable/Disable VBI frame output mode
|
|
// Input: BOOL mode - TRUE = Enable, FALSE = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetVBIFrameMode(BOOL mode)
|
|
{
|
|
decFieldVBI_FRAME = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsVBIFrameMode()
|
|
// Purpose: Check if VBI frame output mode is enabled
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = Enable, FALSE = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsVBIFrameMode()
|
|
{
|
|
return (decFieldVBI_FRAME == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetCodeInsertionEnabled(BOOL mode)
|
|
// Purpose:
|
|
// Input: BOOL mode - TRUE = Disabled, FALSE = Enabled
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetCodeInsertionEnabled(BOOL mode)
|
|
{
|
|
decFieldCODE = (mode == TRUE) ? On : Off;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsCodeInsertionEnabled()
|
|
// Purpose: Check if code insertion in data stream is enabled
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = enabled, FALSE = disabled
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsCodeInsertionEnabled()
|
|
{
|
|
return (decFieldCODE == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::Set16BitDataStream(BOOL mode)
|
|
// Purpose: 8 or 16 bit data stream
|
|
// Input: BOOL mode - TRUE = 16, FALSE = 8
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::Set16BitDataStream(BOOL mode)
|
|
{
|
|
decFieldLEN = (mode == TRUE) ? On : Off;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::Is16BitDatastream()
|
|
// Purpose: Check if 16 bit data stream
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = 16, FALSE = 8
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::Is16BitDataStream()
|
|
{
|
|
return (decFieldLEN == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
//===== Vertical Scaling register (E_VSCALE_HI, O_VSCALE_HI) ================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetChromaComb(BOOL mode)
|
|
// Purpose: Enable/Disable chroma comb
|
|
// Input: BOOL mode - TRUE = Enable, FALSE = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetChromaComb(BOOL mode)
|
|
{
|
|
decFieldCOMB = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsChromaComb()
|
|
// Purpose: Check if chroma comb is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = Enable, FALSE = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsChromaComb()
|
|
{
|
|
return (decFieldCOMB == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetInterlaced(BOOL mode)
|
|
// Purpose: Enable/Disable Interlace
|
|
// Input: BOOL mode - TRUE = Interlaced
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetInterlaced(BOOL mode)
|
|
{
|
|
decFieldINT = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsInterlaced()
|
|
// Purpose: Check if interlaced or non-interlaced
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = Interlaced
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsInterlaced()
|
|
{
|
|
return (decFieldINT == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
//===== VPOLE register ==================================================
|
|
|
|
BOOL Decoder::IsOutputEnabled ()
|
|
{
|
|
return (decFieldOUT_EN == m_outputEnablePolarity);
|
|
}
|
|
|
|
void Decoder::SetOutputEnabled (BOOL mode)
|
|
{
|
|
decFieldOUT_EN = (mode == TRUE) ? m_outputEnablePolarity : !m_outputEnablePolarity;
|
|
}
|
|
|
|
BOOL Decoder::IsHighOdd ()
|
|
{
|
|
return (decFieldFIELD == 0); // 0 enabled; 1 even
|
|
}
|
|
|
|
void Decoder::SetHighOdd (BOOL mode)
|
|
{
|
|
decFieldFIELD = (mode == TRUE) ? 0 : 1; // 0 enabled; 1 even
|
|
}
|
|
|
|
//===== ADC Interface register (ADC) =========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::PowerDown(BOOL mode)
|
|
// Purpose: Select normal or shut down clock operation
|
|
// Input: BOOL mode - TRUE = shut down, FALSE = normal operation
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::PowerDown(BOOL mode)
|
|
{
|
|
decFieldCLK_SLEEP = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsPowerDown()
|
|
// Purpose: Check if clock operation has been shut down
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = shut down, FALSE = normal operation
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsPowerDown()
|
|
{
|
|
return (decFieldCLK_SLEEP == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetChromaADC(BOOL mode)
|
|
// Purpose: Select normal or sleep C ADC operation
|
|
// Input: BOOL mode - TRUE = normal, FALSE = sleep
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetChromaADC(BOOL mode)
|
|
{
|
|
decFieldC_SLEEP = (mode == FALSE) ? On : Off; // reverse
|
|
}
|
|
|
|
|
|
/*^^////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetAdaptiveAGC(BOOL mode)
|
|
// Purpose: Set adaptive or non-adaptive AGC operation
|
|
// Input: BOOL mode - TRUE = Adaptive, FALSE = Non-adaptive
|
|
// Output: None
|
|
// Return: None
|
|
*////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetAdaptiveAGC(BOOL mode)
|
|
{
|
|
decFieldCRUSH = (mode == FALSE) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsAdaptiveAGC()
|
|
// Purpose: Check if adaptive or non-adaptive AGC operation is selected
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = Adaptive, FALSE = Non-adaptive
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsAdaptiveAGC()
|
|
{
|
|
return (decFieldCRUSH == On) ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
//===== Software Reset register (SRESET) ====================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SoftwareReset()
|
|
// Purpose: Perform software reset; all registers set to default values
|
|
// Input: None
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SoftwareReset()
|
|
{
|
|
decRegSRESET = 0x00; // write any value will do
|
|
}
|
|
|
|
|
|
//===== Test Control register (TEST) ========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::AdjustInertialDampener(BOOL mode)
|
|
// Purpose: for factory diagnostics only
|
|
// Input: TRUE or FALSE
|
|
// Output: None
|
|
// Return: None
|
|
// NOTE: For factory diagnostics only!!!!!!!
|
|
// John Welch's dirty little secret
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::AdjustInertialDampener(BOOL mode)
|
|
{
|
|
#pragma message ("FOR TEST DIAGNOSTICS ONLY! ")
|
|
decRegTEST = (mode == FALSE) ? 0x00 : 0x01;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SelectCrystal(char useCrystal)
|
|
// Purpose: Select correct crystal for NTSC or PAL
|
|
// Input: char useCrystal - 'N' for NTSC; 'P' for PAL
|
|
// Output: None
|
|
// Return: None
|
|
// NOTE: Assume at most 2 crystals installed in hardware. i.e. 1 for NTSC
|
|
// and the other for PAL/SECAM.
|
|
// If there is only 1 crystal exists (which must be crystal XT0),
|
|
// do nothing since it is already selected.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SelectCrystal(char useCrystal)
|
|
{
|
|
#pragma message("do something about registry")
|
|
/*
|
|
// locate crystal information in the registry
|
|
// the keys to look for in registry are:
|
|
// 1. Bt848\NumXTAL - number of crystal installed
|
|
// possible values are "1" or "2"
|
|
// 2. Bt848\XT0 - what crystal type is for crystal 0
|
|
// possible values are "NTSC", "PAL"
|
|
// There is another key exist which may be useful in the future:
|
|
// Bt848\XT1 - what crystal type is for crystal 1
|
|
// possible values are "NTSC", "PAL", and "NONE"
|
|
|
|
VRegistryKey vkey(PRK_CLASSES_ROOT, "Bt848");
|
|
|
|
// make sure the key exists
|
|
if (vkey.lastError() == ERROR_SUCCESS)
|
|
{
|
|
char * numCrystalKey = "NumXTAL";
|
|
char nCrystal[5];
|
|
DWORD nCrystalLen = 2; // need only first char; '1' or '2'
|
|
|
|
// get number of crystal exists
|
|
if (vkey.getSubkeyValue(numCrystalKey, nCrystal, (DWORD *)&nCrystalLen))
|
|
{
|
|
// if there is only 1 crystal, no other crystal to change to
|
|
if (nCrystal[0] == '2')
|
|
{
|
|
char * crystalTypeKey = "XT0"; // crystal 0 type
|
|
char crystalType[10];
|
|
DWORD crystalTypeLen = 6; // need only first char: 'N' or 'P'
|
|
|
|
// get the crystal 0 information
|
|
if (vkey.getSubkeyValue(crystalTypeKey, crystalType, (DWORD *)&crystalTypeLen))
|
|
// compare with what we want to use
|
|
if ((IsCrystal0Selected() && (crystalType[0] != useCrystal)) ||
|
|
(!IsCrystal0Selected() && (crystalType[0] == useCrystal)))
|
|
// need to change crystal
|
|
SetCrystal(IsCrystal0Selected() ? Crystal_XT1 : Crystal_XT0);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::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.Default() - fromRange.Min())
|
|
// ------------------------------------------------ + fromRange.Min()
|
|
// toRange.Default() - toRange.Min()
|
|
//
|
|
// For fromRange.Default() < fromValue <= fromRange.Max():
|
|
//
|
|
// (fromValue - fromRange.Default()) (toRange.Max() - toRange.Default())
|
|
// --------------------------------------------------------------------- + toRange.Default()
|
|
// toRange.Max() - toRange.Default()
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::Mapping(int fromValue, CRegInfo fromRange,
|
|
int * toValue, CRegInfo toRange)
|
|
{
|
|
// calculate intermediate values
|
|
DWORD a = toRange.Default() - toRange.Min();
|
|
DWORD b = fromRange.Default() - fromRange.Min();
|
|
DWORD c = toRange.Max() - toRange.Default();
|
|
DWORD d = fromRange.Max() - fromRange.Default();
|
|
|
|
// prevent divide by zero
|
|
if ((b == 0) || (d == 0))
|
|
return (Fail);
|
|
|
|
// perform mapping
|
|
if (fromValue <= fromRange.Default())
|
|
*toValue = (int) (DWORD)fromValue * a / b + (DWORD)toRange.Min();
|
|
else
|
|
*toValue = (int) ((DWORD)fromValue - (DWORD)fromRange.Default()) * c / d
|
|
+ (DWORD)toRange.Default();
|
|
|
|
return (Success);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BOOL Decoder::IsAdjustContrast()
|
|
// Purpose: Check registry key whether adjust contrast is needed
|
|
// Input: None
|
|
// Output: None
|
|
// Return: TRUE = adjust contrast, FALSE = don't adjust contrast
|
|
// Note: If adjust contrast is turn on, brightness register value will be
|
|
// adjusted such that it remains a constant after the calculation
|
|
// performed by the hardware.
|
|
//
|
|
// The formula is:
|
|
// To keep brightness constant (i.e. not affect by changing contrast)
|
|
// set brightness to B/(C/C0)
|
|
// where B is value of brightness before adjustment
|
|
// C is contrast value
|
|
// C0 is nominal contrast value (0xD8)
|
|
//
|
|
// To adjust the contrast level such that it is at the middle of
|
|
// black and white: set brightness to (B * C0 + 64 * (C0 - C))/C
|
|
// (this is what Intel wants)
|
|
//
|
|
// Currently there is still limitation of how much adjustment
|
|
// can be performed. For example, if brightness is already high,
|
|
// (i.e. brightness reg value close to 0x7F), lowering contrast
|
|
// until a certain level will have no adjustment effect on brightness.
|
|
// In fact, it would even bring down brightness to darkness.
|
|
//
|
|
// Example 1: if brightness is at nominal value (0x00), contrast can
|
|
// only go down to 0x47 (brightness adjustment is already
|
|
// at max of 0x7F) before it starts affecting brightness
|
|
// which takes it darkness.
|
|
// Example 2: if brightness is at nominal value (0x00), contrast can
|
|
// go all the way up with brightness adjusted correctly.
|
|
// However, the max adjustment used is only 0xDC and
|
|
// the max adjustment we can use is 0x&F.
|
|
// Example 3: if brightness is at max (0x7F), lowering contrast
|
|
// cannot be compensated by adjusting brightness anymore.
|
|
// The result is gradually taking brightness to darkness.
|
|
// Example 4: if brightness is at min (0x80), lowering contrast has
|
|
// no visual effect. Bringing contrast to max is using
|
|
// 0xA5 in brightness for compensation.
|
|
//
|
|
// One last note, the center is defined as the middle of the
|
|
// gamma adjusted luminance level. Changing it to use the middle of
|
|
// the linear (RGB) luminance level is possible.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL Decoder::IsAdjustContrast()
|
|
{
|
|
return FALSE;
|
|
/*
|
|
// locate adjust contrast information in the registry
|
|
// the key to look for in registry is:
|
|
// Bt848\AdjustContrast - 0 = don't adjust contrast
|
|
// 1 = adjust contrast
|
|
|
|
VRegistryKey vkey(PRK_CLASSES_ROOT, "Bt848");
|
|
|
|
// make sure the key exists
|
|
if (vkey.lastError() == ERROR_SUCCESS)
|
|
{
|
|
char * adjustContrastKey = "AdjustContrast";
|
|
char key[3];
|
|
DWORD keyLen = 2; // need only first char; '0' or '1'
|
|
|
|
// get the registry value and check it, if exist
|
|
if ((vkey.getSubkeyValue(adjustContrastKey, key, (DWORD *)&keyLen)) &&
|
|
(key[0] == '1'))
|
|
return (TRUE);
|
|
}
|
|
return (FALSE);
|
|
*/
|
|
}
|
|
|
|
|