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.
1390 lines
49 KiB
1390 lines
49 KiB
// $Header: G:/SwDev/WDM/Video/bt848/rcs/Decoder.cpp 1.5 1998/04/29 22:43:31 tomz Exp $
|
|
|
|
#include "mytypes.h"
|
|
#include "Scaler.h"
|
|
#include "decoder.h"
|
|
#include "constr.h"
|
|
#include "dcdrvals.h"
|
|
|
|
#define CON_vs_BRI // HW does contrast incorrectly, try to adjust in SW
|
|
|
|
|
|
//===========================================================================
|
|
// Bt848 Decoder Class Implementation
|
|
//===========================================================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Constructor
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Decoder::Decoder( DWORD *xtals ) :
|
|
// 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 ),
|
|
CONSTRUCT_REGISTERS
|
|
{
|
|
Xtals_ [0] = *xtals;
|
|
Xtals_ [1] = *(xtals + 1 );
|
|
|
|
// need to set this to 0x4F
|
|
decRegWC_UP = 0x4F;
|
|
// and this one to 0x7F to make sure CRUSH bit works
|
|
decRegWC_DN = 0x7F;
|
|
|
|
// HACTIVE should always be 0
|
|
decFieldHACTIVE = 0;
|
|
|
|
// HSFMT (odd and even) should always be 0
|
|
decFieldHSFMT = decFieldODD_HSFMT = 0;
|
|
|
|
// Instead of using default values, set some registers fields to optimum values
|
|
SetLumaDecimation( true );
|
|
SetChromaAGC( true );
|
|
SetLowColorAutoRemoval( true );
|
|
SetAdaptiveAGC( false );
|
|
|
|
// for contrast adjustment purpose
|
|
regBright = 0x00; // brightness register value before adjustment
|
|
regContrast = 0xD8; // contrast register value before adjustment
|
|
|
|
// Initialize these Values so we can Get the correct property values jbc 3/13/98
|
|
// Perhaps get should read the actual values set in the decoder but this is quick and works for now
|
|
// [!!!]
|
|
m_briParam = 5000; // jbc 3/13/98
|
|
m_satParam = 5000; // jbc 3/13/98
|
|
m_conParam = 5000; // jbc 3/13/98
|
|
m_hueParam = 5000; // jbc 3/13/98
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Destructor
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
Decoder::~Decoder()
|
|
{
|
|
}
|
|
|
|
|
|
//===== Device Status register ==============================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: BYTE Decoder::GetDeviceStatusReg( void )
|
|
// Purpose: Obtain device status register value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: value of status register in BYTE
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BYTE Decoder::GetDeviceStatusReg( void )
|
|
{
|
|
BYTE status = (BYTE)decRegSTATUS;
|
|
decRegSTATUS = 0x00;
|
|
return status;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsVideoPresent( void )
|
|
// Purpose: Detect if video is present
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true if video present; else false
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsVideoPresent( void )
|
|
{
|
|
return (bool) (decFieldPRES == 1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsDeviceInHLock( void )
|
|
// Purpose: Detect if device is in H-lock
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true if device in H-lock; else false
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsDeviceInHLock( void )
|
|
{
|
|
return (bool) (decFieldHLOC == 1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsEvenField( void )
|
|
// Purpose: Reflect whether an even or odd field is being decoded
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true if even field; else false
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsEvenField( void )
|
|
{
|
|
return (bool) (decFieldEVENFIELD == 1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::Is525LinesVideo( void )
|
|
// 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( void )
|
|
{
|
|
return (bool) (decFieldNUML == 0); //525
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsCrystal0Selected( void )
|
|
// Purpose: Reflect whether XTAL0 or XTAL1 is selected
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true if XTAL0 selected; else false (XTAL1 selected)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsCrystal0Selected( void )
|
|
{
|
|
return (bool) (decFieldCSEL == 0);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsLumaOverflow( void )
|
|
// Purpose: Indicates if luma ADC overflow
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true if luma ADC overflow; else false
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsLumaOverflow( void )
|
|
{
|
|
return (bool) (decFieldLOF == 1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::ResetLumaOverflow( void )
|
|
// Purpose: Reset luma ADC overflow bit
|
|
// Input: None
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::ResetLumaOverflow( void )
|
|
{
|
|
decFieldLOF = 0; // write to it will reset the bit
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsChromaOverflow( void )
|
|
// Purpose: Indicates if chroma ADC overflow
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true if chroma ADC overflow; else false
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsChromaOverflow( void )
|
|
{
|
|
return (bool) (decFieldCOF == 1);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::ResetChromaOverflow( void )
|
|
// Purpose: Reset chroma ADC overflow bit
|
|
// Input: None
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::ResetChromaOverflow( void )
|
|
{
|
|
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 = source;
|
|
|
|
// set to composite or Y/C component video depends on video source
|
|
SetCompositeVideo( ( source == ConSVideo ) ? false : true );
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetVideoInput( void )
|
|
// Purpose: Get which connector is input
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Video source - SVideo, Tuner, Composite
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetVideoInput( void )
|
|
{
|
|
return ((int)decFieldMUXSEL);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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( void )
|
|
// 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( void )
|
|
{
|
|
return ((int)decFieldXTSEL);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetVideoFormat( VideoFormat format )
|
|
// Purpose: Set video format
|
|
// Input: 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
|
|
// 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_SECAM) ||
|
|
(format == VFormat_Reserved2) )
|
|
return Fail;
|
|
|
|
switch (format)
|
|
{
|
|
case VFormat_NTSC:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x68;
|
|
decRegBDELAY = 0x5D;
|
|
SetChromaComb( true ); // enable chroma comb
|
|
SelectCrystal( NTSC_xtal ); // select NTSC crystal
|
|
break;
|
|
case VFormat_PAL_BDGHI:
|
|
case VFormat_PAL_M:
|
|
case VFormat_PAL_N:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x7F;
|
|
decRegBDELAY = 0x72;
|
|
SetChromaComb( true ); // enable chroma comb
|
|
SelectCrystal( PAL_xtal ); // select PAL crystal
|
|
break;
|
|
case VFormat_SECAM:
|
|
decFieldFORMAT = format;
|
|
decRegADELAY = 0x7F;
|
|
decRegBDELAY = 0xA0;
|
|
SetChromaComb( false ); // disable chroma comb
|
|
SelectCrystal( PAL_xtal ); // 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( void )
|
|
// 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
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetVideoFormat( void )
|
|
{
|
|
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( void )
|
|
// Purpose: Obtain brightness value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Brightness parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetBrightness( void )
|
|
{
|
|
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 = decFieldODD_LNOTCH = (mode == false) ? On : Off; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsLumaNotchFilter( void )
|
|
// Purpose: Check if luma notch filter is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable; false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsLumaNotchFilter( void )
|
|
{
|
|
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 = decFieldODD_COMP = Off;
|
|
Decoder::SetChromaADC( false ); // disable chroma ADC
|
|
Decoder::SetLumaNotchFilter( true ); // enable luma notch filter
|
|
}
|
|
else
|
|
{
|
|
// Y/C Component video
|
|
decFieldCOMP = decFieldODD_COMP = On;
|
|
Decoder::SetChromaADC( true ); // enable chroma ADC
|
|
Decoder::SetLumaNotchFilter( false ); // disable luma notch filter
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsCompositeVideo( void )
|
|
// Purpose: Check if selected composite or Y/C component video
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Composite; false = Y/C Component
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsCompositeVideo( void )
|
|
{
|
|
return (decFieldCOMP == Off) ? true : false; // reverse
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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 = decFieldODD_LDEC = (mode == true) ? 0 : 1;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsLumaDecimation( void )
|
|
// Purpose: Check if luma decimation filter is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable; false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsLumaDecimation( void )
|
|
{
|
|
return (decFieldLDEC == Off) ? true : false; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetCbFirst( bool mode )
|
|
// Purpose: Control whether the first pixel of a line is a Cb or Cr pixel
|
|
// Input: bool mode - true = Normal Cb, Cr order, false = Invert Cb, Cr order
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetCbFirst( bool mode )
|
|
{
|
|
decFieldCBSENSE = decFieldODD_CBSENSE = (mode == false) ? On : Off; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsCbFirst( void )
|
|
// Purpose: Check if the first pixel of a line is a Cb or Cr pixel
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Normal Cb, Cr order, false = Invert Cb, Cr order
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsCbFirst( void )
|
|
{
|
|
return (decFieldCBSENSE == Off) ? true : false; // reverse
|
|
}
|
|
|
|
|
|
//===== 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 = decFieldODD_CON_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( void )
|
|
// Purpose: Obtain contrast value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Contrast parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetContrast( void )
|
|
{
|
|
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 = decFieldODD_SAT_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 = decFieldODD_SAT_V_MSB = ( (Vvalue & 0x0100) ? On : Off );
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetSaturation( void )
|
|
// Purpose: Obtain saturation value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Saturation parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetSaturation( void )
|
|
{
|
|
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( void )
|
|
// Purpose: Obtain hue value
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Hue parameter (0-255)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetHue( void )
|
|
{
|
|
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 = decFieldODD_CAGC = (mode == false) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsChromaAGC( void )
|
|
// Purpose: Check if Chroma AGC compensation is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable, false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsChromaAGC( void )
|
|
{
|
|
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 = decFieldODD_CKILL = (mode == false) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsLowColorAutoRemoval( void )
|
|
// Purpose: Check if low color detection and removal is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable, false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsLowColorAutoRemoval( void )
|
|
{
|
|
return (decFieldCKILL == On) ? true : false;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetHorizontalFilter( HorizFilter hFilter )
|
|
// Purpose: Control the configuration of the optional 6-tap Horizontal Low-Pass filter
|
|
// Input: HoriFilter hFilter:
|
|
// Auto Format - HFilter_AutoFormat
|
|
// CIF - HFilter_CIF
|
|
// QCIF - HFilter_QCIF
|
|
// ICON - HFilter_ICON
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetHorizontalFilter( HorizFilter hFilter )
|
|
{
|
|
if ( (hFilter < HFilter_AutoFormat) ||
|
|
(hFilter > HFilter_ICON) )
|
|
return Fail;
|
|
|
|
decFieldHFILT = decFieldODD_HFILT = hFilter;
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetHorizontalFilter( void )
|
|
// Purpose: Get the configuration of the optional 6-tap Horizontal Low-Pass filter
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Which filter is using:
|
|
// Auto Format - HFilter_AutoFormat
|
|
// CIF - HFilter_CIF
|
|
// QCIF - HFilter_QCIF
|
|
// ICON - HFilter_ICON
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetHorizontalFilter( void )
|
|
{
|
|
return ((int)decFieldHFILT);
|
|
}
|
|
|
|
|
|
//===== Output Format register (OFORM) ======================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetFullOutputRange( bool mode )
|
|
// Purpose: Enable/Disable full output range
|
|
// Input: bool mode - true = Enable, false = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetFullOutputRange( bool mode )
|
|
{
|
|
decFieldRANGE = (mode == false) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsFullOutputRange( void )
|
|
// Purpose: Check if full output range is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable, false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsFullOutputRange( void )
|
|
{
|
|
return (decFieldRANGE == On) ? true : false;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: ErrorCode Decoder::SetLumaCoring( CoringLevel cLevel )
|
|
// Purpose: Set luminance level such that luminance signal is truncated to zero
|
|
// if below this level
|
|
// Input: CoringLevel cLevel -
|
|
// Coring_None: no coring
|
|
// Coring_8: 8
|
|
// Coring_16: 16
|
|
// Coring_32: 32
|
|
// Output: None
|
|
// Return: Fail if error in parameter, else Success
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::SetLumaCoring( CoringLevel cLevel )
|
|
{
|
|
if ( ( cLevel < Coring_None) || ( cLevel > Coring_32 ) )
|
|
return Fail;
|
|
|
|
decFieldCORE = cLevel;
|
|
return Success;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetLumaCoring( void )
|
|
// Purpose: Get luminance level such that luminance signal is truncated to zero
|
|
// if below this level
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Luma coring level -
|
|
// Coring_None: no coring
|
|
// Coring_8: 8
|
|
// Coring_16: 16
|
|
// Coring_32: 32
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetLumaCoring( void )
|
|
{
|
|
return ((int)decFieldCORE);
|
|
}
|
|
|
|
|
|
//===== 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( void )
|
|
// Purpose: Check if chroma comb is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable, false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsChromaComb( void )
|
|
{
|
|
return (decFieldCOMB == On) ? true : false;
|
|
}
|
|
|
|
//===== AGC Delay register (ADELAY) =========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetAGCDelay( BYTE value )
|
|
// Purpose: Set AGC Delay register
|
|
// Input: Value to be set to
|
|
// Output: None
|
|
// Return: None
|
|
// NOTE: This function set the AGC Delay register to the specified value.
|
|
// No calculation is involved.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetAGCDelay( BYTE value )
|
|
{
|
|
// [!!!] this was considered suspicious by someone...
|
|
//#pragma message ("IS THIS GOOD?? ")
|
|
decRegADELAY = value;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetAGCDelay( void )
|
|
// Purpose: Get AGC Delay register
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Register value
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetAGCDelay( void )
|
|
{
|
|
return ((int)decRegADELAY);
|
|
}
|
|
|
|
|
|
//===== Burst Delay register (BDELAY) =========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetBurstDelay( BYTE value )
|
|
// Purpose: Set Burst Delay register
|
|
// Input: Value to be set to
|
|
// Output: None
|
|
// Return: None
|
|
// NOTE: This function set the Burst Delay register to the specified value.
|
|
// No calculation is involved.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetBurstDelay( BYTE value )
|
|
{
|
|
// [!!!] this was considered suspicious by someone...
|
|
//#pragma message ("IS THIS GOOD?? ")
|
|
decRegBDELAY = value;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: int Decoder::GetBurstDelay( void )
|
|
// Purpose: Get Burst Delay register
|
|
// Input: None
|
|
// Output: None
|
|
// Return: Register value
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int Decoder::GetBurstDelay( void )
|
|
{
|
|
return ((int)decRegBDELAY);
|
|
}
|
|
|
|
|
|
//===== ADC Interface register (ADC) =========================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetAnalogThresholdLow( bool mode )
|
|
// Purpose: Define high/low threshold level below which SYNC signal can be detected
|
|
// Input: bool mode - true = low threshold (~75mV), false = high threshold (~125mV)
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetAnalogThresholdLow( bool mode )
|
|
{
|
|
decFieldSYNC_T = (mode == false) ? Off : On;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsAnalogThresholdLow( void )
|
|
// Purpose: Check if high or low threshold level below which SYNC signal can be detected
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = low threshold (~75mV), false = high threshold (~125mV)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsAnalogThresholdLow( void )
|
|
{
|
|
return (decFieldSYNC_T == On) ? true : false;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetAGCFunction( bool mode )
|
|
// Purpose: Enable/Disable AGC function
|
|
// Input: bool mode - true = Enable, false = Disable
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetAGCFunction( bool mode )
|
|
{
|
|
decFieldAGC_EN = (mode == false) ? On : Off; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsAGCFunction( void )
|
|
// Purpose: Check if AGC function is enable or disable
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Enable, false = Disable
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsAGCFunction( void )
|
|
{
|
|
return (decFieldAGC_EN == Off) ? true : false; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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( void )
|
|
// Purpose: Check if clock operation has been shut down
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = shut down, false = normal operation
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsPowerDown( void )
|
|
{
|
|
return (decFieldCLK_SLEEP == On) ? true : false;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SetLumaADC( bool mode )
|
|
// Purpose: Select normal or sleep Y ADC operation
|
|
// Input: bool mode - true = normal, false = sleep
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SetLumaADC( bool mode )
|
|
{
|
|
decFieldY_SLEEP = (mode == false) ? On : Off; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsLumaADC( void )
|
|
// Purpose: Check if Y ADC operation is in normal operation or sleeping
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = normal, false = sleep
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsLumaADC( void )
|
|
{
|
|
return (decFieldY_SLEEP == Off) ? true : false; // reverse
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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: bool Decoder::IsChromaADC( void )
|
|
// Purpose: Check if C ADC operation is in normal operation or sleeping
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = normal, false = sleep
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsChromaADC( void )
|
|
{
|
|
return (decFieldC_SLEEP == Off) ? true : false; // 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( void )
|
|
// Purpose: Check if adaptive or non-adaptive AGC operation is selected
|
|
// Input: None
|
|
// Output: None
|
|
// Return: true = Adaptive, false = Non-adaptive
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
bool Decoder::IsAdaptiveAGC( void )
|
|
{
|
|
return (decFieldCRUSH == On) ? true : false;
|
|
}
|
|
|
|
|
|
//===== Software Reset register (SRESET) ====================================
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: void Decoder::SoftwareReset( void )
|
|
// Purpose: Perform software reset; all registers set to default values
|
|
// Input: None
|
|
// Output: None
|
|
// Return: None
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void Decoder::SoftwareReset( void )
|
|
{
|
|
decRegSRESET = 0x00; // write any value will do
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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( int useCrystal )
|
|
{
|
|
if ( Xtals_ [0] && Xtals_ [1] ) {
|
|
|
|
// compare with what we want to use
|
|
if ( ( IsCrystal0Selected() && ( Xtals_ [0] != (DWORD) useCrystal ) ) ||
|
|
( !IsCrystal0Selected() && ( Xtals_ [0] == (DWORD) 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 * (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()
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
ErrorCode Decoder::Mapping( int fromValue, CRegInfo fromRange,
|
|
int * toValue, CRegInfo toRange )
|
|
{
|
|
// calculate intermediate values
|
|
DWORD ToLowRange = toRange.Default() - toRange.Min();
|
|
DWORD FromLowRange = fromRange.Default() - fromRange.Min();
|
|
DWORD ToHighRange = toRange.Max() - toRange.Default();
|
|
DWORD FromHighRange = fromRange.Max() - fromRange.Default();
|
|
|
|
// prevent divide by zero
|
|
if ( !FromLowRange || !FromHighRange )
|
|
return ( Fail );
|
|
|
|
// perform mapping
|
|
if ( fromValue <= fromRange.Default() )
|
|
*toValue = (int) (DWORD)fromValue * ToLowRange / FromLowRange +
|
|
(DWORD)toRange.Min();
|
|
else
|
|
*toValue = (int) ( (DWORD)fromValue - (DWORD)fromRange.Default() ) *
|
|
ToHighRange / FromHighRange + (DWORD)toRange.Default();
|
|
|
|
return ( Success );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Method: bool Decoder::IsAdjustContrast( void )
|
|
// 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( void )
|
|
{
|
|
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 );
|
|
*/
|
|
}
|
|
|
|
/* Function: SelectFlags
|
|
* Purpose: Selects video standard flags
|
|
* Input: val: DWORD - value to switch on
|
|
* flags: LONG & - flags fo here
|
|
* Output: None
|
|
*/
|
|
void SelectFlags( DWORD val, LONG &flags )
|
|
{
|
|
switch ( val ) {
|
|
case NTSC_xtal:
|
|
flags |= KS_AnalogVideo_NTSC_M;
|
|
break;
|
|
case PAL_xtal:
|
|
flags |= KS_AnalogVideo_PAL_M | KS_AnalogVideo_PAL_N |
|
|
KS_AnalogVideo_PAL_B | KS_AnalogVideo_PAL_D |
|
|
KS_AnalogVideo_PAL_H | KS_AnalogVideo_PAL_I |
|
|
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;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Method: Decoder::GetSupportedStandards
|
|
* Purpose: Returns supported standards
|
|
* Input: None
|
|
* Output: LONG: standard flags
|
|
*/
|
|
LONG Decoder::GetSupportedStandards()
|
|
{
|
|
LONG standards =0;
|
|
|
|
SelectFlags( Xtals_ [0], standards );
|
|
SelectFlags( Xtals_ [1], standards );
|
|
return standards;
|
|
}
|
|
|