/*
 * Copyright (c) 2008,2009 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description:
 * Implementation of CEdidParserBase class.
 *
 */

#include "trace.h"
#include "edidparserbase.h"
#include "cea861edidparser.h"
#include "traceediddata.h"

// ---------------------------------------------------------------------------
// CEdidParserBase::CEdidParserBase
// ---------------------------------------------------------------------------
//
CEdidParserBase::CEdidParserBase() :
    iNumberOfExtensionBlocks( 0 )
    {
    FUNC_LOG;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::ConstructL
// ---------------------------------------------------------------------------
//
void CEdidParserBase::ConstructL( const TDesC8& aBinaryData )
    {
    FUNC_LOG;

    //Check if it is EDID data
    if( !IsEdidData( aBinaryData ) )
        {
        // Not EDID data
        User::Leave( KErrNotSupported );
        }

    iRawData = HBufC8::NewL( aBinaryData.Length() );
    TPtr8 rawPtr = iRawData->Des();
    rawPtr.Copy( aBinaryData );

    // Make a copy of base EDID data
    Mem::Copy( &iBaseEdidData, rawPtr.Ptr(), KEdidParserSizeOfEdidBlock );
    
    TRACE_EDID_DATA( *this );
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::NewL
// ---------------------------------------------------------------------------
//
EXPORT_C CEdidParserBase* CEdidParserBase::NewL( const TDesC8& aBinaryData )
    {
    FUNC_LOG;

    CEdidParserBase* self = CEdidParserBase::NewLC( aBinaryData );
    CleanupStack::Pop( self );

    return self;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::NewLC
// ---------------------------------------------------------------------------
//
EXPORT_C CEdidParserBase* CEdidParserBase::NewLC( const TDesC8& aBinaryData )
    {
    FUNC_LOG;

    CEdidParserBase* self = new ( ELeave ) CEdidParserBase();
    CleanupStack::PushL( self );
    self->ConstructL( aBinaryData );

    return self;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::CEdidParserBase
// ---------------------------------------------------------------------------
//
CEdidParserBase::~CEdidParserBase()
    {
    FUNC_LOG;

    delete iRawData;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::IsEdidData
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CEdidParserBase::IsEdidData( const TDesC8& aBinaryData )
    {
    FUNC_LOG;
    INFO_1( "TBool CEdidParserBase::IsEdidData: aBinaryData length: %d", aBinaryData.Length() );

    TBool edidData = EFalse;

    // Check the length
    if( aBinaryData.Length() >= KEdidParserSizeOfEdidBlock )
        {
        for( int ii = 0; ii < KEdidParserSizeOfEdidHeader; ii++ )
            {
            if( aBinaryData[ii] != KBaseEdidHeader[ii] )
                {
                    // Not a valid EDID header
                ERROR_1( KErrArgument, "TBool CEdidParserBase::IsEdidData: Not a valid EDID header: %d", ii );
                return EFalse;
                }
            }
        edidData = ETrue;
        }

    return edidData;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetManufacturerCode
// ---------------------------------------------------------------------------
//
EXPORT_C void CEdidParserBase::GetManufacturerCode( TDes& aCode )
    {
    FUNC_LOG;

    if( aCode.Length() < KEdidParserManufacturerCodeLength )
        {
        //return;
        }

    TUint16 data = iBaseEdidData.iVendorProductInfo.iManufacturerCode;

    // Manufacturer codes are also called the ISA (Industry Standard Architecture)
    // Plug and Play Device Identifier (PNPID). They are based on 5 bit compressed
    // ASCII codes
    // bits 14-10: first letter (01h='A', 02h='B',..)
    // bits 9-5: second letter
    // bits 4-0: third letter

    // Convert to big endian
    data = ( ( data >> 8 ) & 0xff ) + ( ( data << 8 ) & 0xff00 );

    // Get ASCII codes
    TChar asciicode;
    asciicode = ( ( data >> 10 ) & 0x1f ) + 'A' - 1;
    aCode.Append( asciicode );
    asciicode = ( ( data >> 5 ) & 0x1f ) + 'A' - 1;
    aCode.Append( asciicode );
    asciicode = ( data & 0x1f ) + 'A' - 1;
    aCode.Append( asciicode );
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetProductId
// ---------------------------------------------------------------------------
//
EXPORT_C void CEdidParserBase::GetProductId( TDes& aCode )
    {
    FUNC_LOG;

    aCode.AppendFormat( _L( "%04x" ), iBaseEdidData.iVendorProductInfo.iProductId );
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetManufactureWeek
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetManufactureWeek()
    {
    FUNC_LOG;

    return iBaseEdidData.iVendorProductInfo.iWeek;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetManufactureYear
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetManufactureYear()
    {
    FUNC_LOG;

    // Year of manufacture stored in EDID data is "Year of Manufacture - 1990"
    return ( iBaseEdidData.iVendorProductInfo.iYear + KEdidBaseYear );
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetVersion
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetVersion()
    {
    FUNC_LOG;

    return iBaseEdidData.iVersion;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetRevision
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetRevision()
    {
    FUNC_LOG;

    return iBaseEdidData.iRevision;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetVideoInputDefinition
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetVideoInputDefinition()
    {
    FUNC_LOG;

    // Analog if bit 7 is 0. Digital if bit 7 is 1
    return ( ( iBaseEdidData.iVideoInputDefinition & KBit7 ) == KBit7 ? 1 : 0 );
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetHorizontalScreenSize
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetHorizontalScreenSize()
    {
    FUNC_LOG;

    return iBaseEdidData.iScreenSize.iHorizontal;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetVerticalScreenSize
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetVerticalScreenSize()
    {
    FUNC_LOG;

    return iBaseEdidData.iScreenSize.iVertical;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetAspectRatioLandscape
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetAspectRatioLandscape()
    {
	FUNC_LOG;
	
    // TEdidAspectRatio contains same values as TEdidScreenSize
    // Horizontal = Landscape 
    return iBaseEdidData.iScreenSize.iHorizontal;
    }


// ---------------------------------------------------------------------------
// CEdidParserBase::GetAspectRatioPortrait
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetAspectRatioPortrait()
    {
	FUNC_LOG;
	
    // TEdidAspectRatio contains same values as TEdidScreenSize
    // Vertical = Portrait 
    return iBaseEdidData.iScreenSize.iVertical;
    }


// ---------------------------------------------------------------------------
// CEdidParserBase::IsAspectRationUsed
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CEdidParserBase::IsAspectRatioUsed()
    {
    FUNC_LOG;

    // If byte 15h != 00h then byte 16h = Vertical Screen Size in cm.     (Range is 1 cm -> 255 cm)
    // If byte 15h == 00h then byte 16h = Aspect Ratio (Portrait)         (Range is 0.28 : 1 AR -> 0.99 : 1 AR)
    //
    // If byte 16h != 00h then byte 15h = Horizontal Screen Size in cm.   (Range is 1 cm -> 255 cm)
    // If byte 16h == 00h then byte 15h = Aspect Ratio (Landscape)        (Range is 1 : 1 AR -> 3.54 : 1 AR)

    if( ( iBaseEdidData.iScreenSize.iHorizontal == 0 )
        || ( iBaseEdidData.iScreenSize.iVertical == 0 ) )
        {
        return ETrue;
        }

    return EFalse;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::DisplayTransferCharacteristics
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::DisplayTransferCharacteristics()
    {
    FUNC_LOG;

    // Stored Value = (GAMMA x 100) – 100
    return iBaseEdidData.iDisplayTransferCharasteristics;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesRedX
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesRedX()
    {
    FUNC_LOG;

    // Address 19h bits 7&6 are RedX bits 1&0
    // Address 1Bh = RedX bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[2]; //1Bh
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit7 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit6 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesRedY
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesRedY()
    {
    FUNC_LOG;

    // Address 19h bits 5&4 are RedY bits 1&0
    // Address 1Ch = RedY bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[3]; //1Ch
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit5 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit4 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesGreenX
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesGreenX()
    {
    FUNC_LOG;

    // Address 19h bits 3&2 are GreenX bits 1&0
    // Address 1Dh = GreenX bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[4]; //1Dh
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit3 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit2 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesGreenY
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesGreenY()
    {
    FUNC_LOG;

    // Address 19h bits 1&0 are GreenY bits 1&0
    // Address 1Eh = GreenY bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[5]; //1Dh
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit1 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[0] & KBit0 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesBlueX
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesBlueX()
    {
    FUNC_LOG;

    // Address 1Ah bits 7&6 are BlueX bits 1&0
    // Address 1Fh = BlueX bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[6]; //1Fh
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit7 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit6 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesBlueY
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesBlueY()
    {
    FUNC_LOG;

    // Address 1Ah bits 5&4 are BlueY bits 1&0
    // Address 20h = BlueY bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[7]; //20h
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit5 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit4 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesWhiteX
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesWhiteX()
    {
    FUNC_LOG;

    // Address 1Ah bits 3&2 are WhiteX bits 1&0
    // Address 21h = WhiteX bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[8]; //21h
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit3 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit2 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetColorCoordinatesWhiteY
// ---------------------------------------------------------------------------
//
EXPORT_C TUint16 CEdidParserBase::GetColorCoordinatesWhiteY()
    {
    FUNC_LOG;

    // Address 1Ah bits 3&2 are WhiteX bits 1&0
    // Address 22h = WhiteX bits 9 to 2
    TUint16 ret = iBaseEdidData.iColorCharasteristics[9]; //22h
    ret = ret << 2;
    TUint8 add = 0;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit1 )
        {
        add++;
        }
    add = add << 1;
    if( iBaseEdidData.iColorCharasteristics[1] & KBit0 )
        {
        add++;
        }
    ret += add;
    return ret;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetEstablishedTimings1
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetEstablishedTimings1()
    {
    FUNC_LOG;

    //Bit - Established Timing I
    // 7     720 x 400  @ 70Hz
    // 6     720 x 400  @ 88Hz
    // 5     640 x 480  @ 60Hz
    // 4     640 x 480  @ 67Hz
    // 3     640 x 480  @ 72Hz
    // 2     640 x 480  @ 75Hz
    // 1     800 x 600  @ 56Hz
    // 0     800 x 600  @ 60Hz
    return iBaseEdidData.iEstablishedTimings[0];
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetEstablishedTimings2
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetEstablishedTimings2()
    {
    FUNC_LOG;

    //Bit - Established Timing I
    // 7     800 x 600    @ 72Hz
    // 6     800 x 600    @ 75Hz
    // 5     832 x 624    @ 75Hz
    // 4     1024 x 768   @ 87Hz
    // 3     1024 x 768   @ 60Hz
    // 2     1024 x 768   @ 70Hz
    // 1     1024 x 768   @ 75Hz
    // 0     1280 x 1024  @ 75Hz
    return iBaseEdidData.iEstablishedTimings[1];
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetManufacturerTimings
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetManufacturerTimings()
    {
    FUNC_LOG;

    //Bit - Manufacturer Timing
    // 7     1152 x 870   @ 75Hz
    // 6-0   Reserved for Manufacturer Specified Timings
    return iBaseEdidData.iEstablishedTimings[2];
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetManufacturerTimings
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetStandardTimings( TInt aIndex )
    {
    FUNC_LOG;
    
    TUint8 byte = 0;
    if( aIndex >= 0 && aIndex < 15 )
        {
        byte = iBaseEdidData.iStdTimingIdentifications[aIndex];
        }
    
    return byte;
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetDescriptorBlock
// ----------------------------------------------------------------------------
//
EXPORT_C TEdidDescriptorBlock CEdidParserBase::GetDescriptorBlock( TUint8 aDescriptorBlockNumber ) const
    {
    FUNC_LOG;

    TEdidDescriptorBlock descBlock;

    descBlock.iPixelClock = GetPixelClock( aDescriptorBlockNumber );

    descBlock.iHorizontalAddressableVideoPixels
        = GetHorizontalAddressableVideo( aDescriptorBlockNumber );

    descBlock.iHorizontalBlanking
        = GetHorizontalBlanking( aDescriptorBlockNumber );

    descBlock.iVerticalAddressableVideoPixels
        = GetVerticalAddressableVideo( aDescriptorBlockNumber );
    
    descBlock.iVerticalBlanking
            = GetVerticalBlanking( aDescriptorBlockNumber );
    
    descBlock.iHorizontalFrontPorch
        = GetHorizontalFrontPorch( aDescriptorBlockNumber );

    descBlock.iHorizontalSyncPulse
        = GetHorizontalSyncPulseWidth( aDescriptorBlockNumber );

    descBlock.iVerticalFrontPorch
        = GetVerticalFrontPorch( aDescriptorBlockNumber );

    descBlock.iVerticalSyncPulse
        = GetVerticalSyncPulseWidth( aDescriptorBlockNumber );

    descBlock.iHorizontalAddressableImageSize
        = GetHorizontalAddressableImageSize( aDescriptorBlockNumber );

    descBlock.iVerticalAddressableImageSize
        = GetVerticalAddressableImageSize( aDescriptorBlockNumber );

    descBlock.iHorizontalBorder
        = GetHorizontalBorderSize( aDescriptorBlockNumber );

    descBlock.iVerticalBorder = GetVerticalBorderSize( aDescriptorBlockNumber );

    descBlock.iInterlacedVideo = GetVideoIsInterlaced( aDescriptorBlockNumber );

    descBlock.iStereoSupport = GetStereoViewingSupport( aDescriptorBlockNumber );

    descBlock.iSyncs = GetSyncSignalDefinitions( aDescriptorBlockNumber );

    return descBlock;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetNumberOfExtensions
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetNumberOfExtensions()
    {
    FUNC_LOG;

    // If Block Maps are used then 254 is the maximum value of number of
    // extension blocks. If Block Maps are not used then 255 is the maximum
    // value of number of extension blocks
    return iBaseEdidData.iExtensionNumber;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetExtension
// ---------------------------------------------------------------------------
//
EXPORT_C TInt CEdidParserBase::ReadExtension( TInt aNumber )
    {
    FUNC_LOG;

    // |-----Base block-----|----Ext1----|---Ext2---|---.....|
    //                            ^           ^
    //                           Extension numbers (1,2,..)
    TInt err = KErrNone;
    if( aNumber <= GetNumberOfExtensions() )
        {
        // Make a copy of extension data. Call ReadExtensionL() with different
        // extension number to read other extension
        TPtr8 rawPtr = iRawData->Des();
        Mem::Copy( &iExtensionData, rawPtr.Ptr() + ( aNumber
            * KEdidParserSizeOfEdidBlock ), KEdidParserSizeOfEdidBlock );
        }
    else
        {
        // Invalid extension number. Return with KErrNotSupported
        err = KErrNotSupported;
        }

    return err;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetExtensionType
// ---------------------------------------------------------------------------
//
EXPORT_C TEdidExtensionTagCode CEdidParserBase::GetExtensionType( TInt aNumber )
    {
    FUNC_LOG;

    TEdidExtensionTagCode tag( EUnknownExt );
    TInt err = ReadExtension( aNumber );
    if( err == KErrNone )
        {
        switch( iExtensionData[0] )
            {
            case 0x02:
                tag = ECea861Ext;
                break;
            case 0x10:
                tag = EVTBExt;
                break;
            case 0x20:
                tag = EEDID20;
                break;
            case 0x40:
                tag = EDIExt;
                break;
            case 0x50:
                tag = ELSExt;
                break;
            case 0x60:
                tag = EDPVLExt;
                break;
            default:
                // tag is EUnknownExt
                break;
            }
        }

    return tag;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::CreateCea861ExtensionParserL
// ---------------------------------------------------------------------------
//
EXPORT_C CCea861EdidParser* CEdidParserBase::CreateCea861ExtensionParserL( TInt aNumber )
    {
    FUNC_LOG;

    CCea861EdidParser* parser = NULL;
    TInt ext = GetExtensionType( aNumber );
    switch( ext )
        {
        case ECea861Ext:
            {
            // CEA 861 extension
            parser = CCea861EdidParser::NewL( iExtensionData );
            break;
            }
        default:
            {
            // Not supported
            break;
            }
        }

    // Extension is not supported. Return NULL
    return parser;
    }

// ---------------------------------------------------------------------------
// CEdidParserBase::GetChecksum
// ---------------------------------------------------------------------------
//
EXPORT_C TUint8 CEdidParserBase::GetChecksum()
    {
    FUNC_LOG;

    // The Checksum Byte contains a value such that a checksum of the entire
    // 128 byte base EDID equals 00h
    return iBaseEdidData.iChecksum;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetPixelClock
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetPixelClock( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    // Stored Value = Pixel clock ÷ 10,000
    // LSB stored in byte 0 and MSB stored in byte 1
    // 0, 1 2 Range: 10 kHz to 655.35 MHz in 10 kHz steps
    // (00 00)h Reserved: Do not use for Detailed Timing Descriptor

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[0];
        word2 = iBaseEdidData.iTimingDescriptor[1];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[0];
        word2 = iBaseEdidData.iSecondTimingDescriptor[1];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[0];
        word2 = iBaseEdidData.iMonitorDescriptor[1];
        }
    else
        {
        //ERROR
        return 0;
        }

    // xxxx xxxx 1010 1010
    TUint16 pixelClock = word2;
    // 1010 1010 xxxx xxxx shifted to left (MSB)
    pixelClock = pixelClock << 8;
    // 1010 1010 0101 0101 add the LSB
    pixelClock += word1;

    return pixelClock;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetHorizontalAddressableVideo
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetHorizontalAddressableVideo( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[4];
        word2 = iBaseEdidData.iTimingDescriptor[2];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[4];
        word2 = iBaseEdidData.iSecondTimingDescriptor[2];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[4];
        word2 = iBaseEdidData.iMonitorDescriptor[2];
        }
    else
        {
        //ERROR
        return 0;
        }

    // 12bits long, defined in 8 bits of byte 2 and
    // upper nibble of byte 4 (4bits), range 0-4095
    TUint16 horAddrVideo = 0;

    // Nullify the 4 lsb
    // ---- ---- xxxx yyyy >> 4  = ---- ---- ---- xxxx
    horAddrVideo = word1 >> 4;
    // return back to original position (4)+4
    // ---- ---- ---- xxxx << 4  = ---- xxxx 0000 0000
    horAddrVideo = horAddrVideo << ( 4 + 4 );
    // ---- xxxx zzzz zzzz = correct values for the 12-bit-long var
    horAddrVideo += word2;

    return horAddrVideo;
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetHorizontalBlanking
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetHorizontalBlanking( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[4];
        word2 = iBaseEdidData.iTimingDescriptor[3];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[4];
        word2 = iBaseEdidData.iSecondTimingDescriptor[3];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[4];
        word2 = iBaseEdidData.iMonitorDescriptor[3];
        }
    else
        {
        //ERROR
        return 0;
        }

    TUint16 horBlanking = 0;

    // nullify the 4 msb
    //      ---- ---- xxxx yyyy << 12 = yyyy ---- ---- ----
    horBlanking = word1 << 12;
    // nullify the 4 msb
    // yyyy ---- ---- ---- >> 4  = ---- yyyy ---- ----
    horBlanking = horBlanking >> 4;
    // ---- yyyy zzzz zzzz = correct values for the 12-bit-long var
    horBlanking += word2;

    return horBlanking;
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetVerticalAddressableVideo
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetVerticalAddressableVideo( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[7];
        word2 = iBaseEdidData.iTimingDescriptor[5];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[7];
        word2 = iBaseEdidData.iSecondTimingDescriptor[5];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[7];
        word2 = iBaseEdidData.iMonitorDescriptor[5];
        }
    else
        {
        //ERROR
        return 0;
        }

    //Upper nibble of byte 7 and the 8 bits of byte 5)
    //Range is 0 lines to 4095 lines
    TUint16 vertAddrVideo = 0;
    vertAddrVideo = word1 >> 4;
    vertAddrVideo = vertAddrVideo << ( 4 + 4 );
    vertAddrVideo += word2;

    return vertAddrVideo;
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetVerticalBlanking
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetVerticalBlanking( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[7];
        word2 = iBaseEdidData.iTimingDescriptor[6];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[7];
        word2 = iBaseEdidData.iSecondTimingDescriptor[6];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[7];
        word2 = iBaseEdidData.iMonitorDescriptor[6];
        }
    else
        {
        //ERROR
        return 0;
        }

    // 12bits long, defined in 8 bits of byte 2 and
    // upper nibble of byte 4 (4bits), range 0-4095
    TUint16 vertBlanking = 0;

    // nullify the 4 msb
    // ---- ---- xxxx yyyy << 12 = yyyy ---- ---- ----
    vertBlanking = word1 << 12;
    // nullify the 4 msb
    // yyyy ---- ---- ---- >> 4  = 0000 yyyy ---- ----
    vertBlanking = vertBlanking >> 4;
    // ---- yyyy zzzz zzzz = correct values for the 12-bit-long var
    vertBlanking += word2;

    return vertBlanking;
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetHorizontalFrontPorch
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetHorizontalFrontPorch( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[6];
        word2 = iBaseEdidData.iTimingDescriptor[8];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[6];
        word2 = iBaseEdidData.iSecondTimingDescriptor[8];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[6];
        word2 = iBaseEdidData.iMonitorDescriptor[8];
        }
    else
        {
        //ERROR
        return 0;
        }

    // Horizontal Front Porch in Pixels (from blanking start to start of sync)
    // is represented by a 10 bit number (Bits 7 & 6 of byte 11 and the 8 bits of byte 8)
    // Range is 0 pixels to 1023 pixels.

    TUint16 horFrontPorch = 0;

    TUint8 bit67 = word1;
    // bits 6 and 7 remain
    bit67 = ( bit67 & KBit7 ) | ( bit67 & KBit6 );

    horFrontPorch = bit67 << 2;
    horFrontPorch += word2;

    return horFrontPorch;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetHorizontalSyncPulseWidth
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetHorizontalSyncPulseWidth( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    //Horizontal Sync Pulse Width in Pixels (from the end of the front porch to the start of the back
    //porch) is represented by a 10 bit number (Bits 5 & 4 of byte 11 and the 8 bits of byte 9) - Range
    //is 0 pixels to 1023 pixels.

    TUint8 word1;
    TUint8 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[11];
        word2 = iBaseEdidData.iTimingDescriptor[9];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[11];
        word2 = iBaseEdidData.iSecondTimingDescriptor[9];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[11];
        word2 = iBaseEdidData.iMonitorDescriptor[9];
        }
    else
        {
        //ERROR
        return 0;
        }

    TUint16 horSyncPulseWidth = word1;

    // only bits 5 and 4 remain: xx00 xxxx
    horSyncPulseWidth = ( horSyncPulseWidth & KBit5 ) | ( horSyncPulseWidth
        & KBit4 );

    // xx00 xxxx -> xx00 xxxx xxxx
    horSyncPulseWidth = horSyncPulseWidth << 4;

    // xx00 xxxx xxxx -> 00 0000 0000
    horSyncPulseWidth += word2;

    return horSyncPulseWidth;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetVerticalFrontPorch
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetVerticalFrontPorch( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    // Vertical Front Porch in Lines (from blanking start to start of sync) is represented by a 6 bit
    // number (Bits 3 & 2 of byte 11 and the upper nibble of byte 10) - Range is 0 lines to 63 lines.

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[11];
        word2 = iBaseEdidData.iTimingDescriptor[10];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[11];
        word2 = iBaseEdidData.iSecondTimingDescriptor[10];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[11];
        word2 = iBaseEdidData.iMonitorDescriptor[10];
        }
    else
        {
        //ERROR
        return 0;
        }

    TUint16 vertFrontPorch = 0;
    TUint8 bit23 = word1;

    // bits 2 and 3 remain  0000 xx00
    bit23 = ( bit23 & KBit3 ) | ( bit23 & KBit2 );

    // 00xx 0000
    vertFrontPorch = bit23 << 2;

    // only the upper nibble
    // 00xx yyyy
    vertFrontPorch += ( word2 >> 4 );

    return vertFrontPorch;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetVerticalSyncPulseWidth
// ----------------------------------------------------------------------------
//
TUint8 CEdidParserBase::GetVerticalSyncPulseWidth( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    // Vertical Sync Pulse Width in Lines (from the end of the front porch to the start of the back
    // porch) is represented by a 6 bit number (Bits 1 & 0 of byte 11 and the lower nibble of byte 10 -
    // Range is 0 lines to 63 lines.

    TUint8 word1;
    TUint8 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[10];
        word2 = iBaseEdidData.iTimingDescriptor[11];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[10];
        word2 = iBaseEdidData.iSecondTimingDescriptor[11];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[10];
        word2 = iBaseEdidData.iMonitorDescriptor[11];
        }
    else
        {
        //ERROR
        return 0;
        }

    // Vertical Sync Pulse Width in Lines (from the end of the front porch to the start of the back
    // porch) is represented by a 6 bit number (Bits 1 & 0 of byte 11 and the lower nibble of byte 10 -
    // Range is 0 lines to 63 lines.
    TUint8 vertSyncPulse = 0;

    // bits 1 and 0 remain   0000 00xx
    word2 = ( word2 & KBit1 ) | ( word2 & KBit0 );

    // 00xx 0000
    vertSyncPulse = word2 << 4;
    // only the lower nibble, %16 removes the upper nibble
    word1 = word1 % 16;
    // 00xx yyyy
    vertSyncPulse += word1;

    return vertSyncPulse;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetHorizontalAddressableImageSize
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetHorizontalAddressableImageSize( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[14];
        word2 = iBaseEdidData.iTimingDescriptor[12];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[14];
        word2 = iBaseEdidData.iSecondTimingDescriptor[12];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[14];
        word2 = iBaseEdidData.iMonitorDescriptor[12];
        }
    else
        {
        //ERROR
        return 0;
        }

    //Horizontal Addressable Video Image Size in mm is represented by a 12 bit number (Upper
    //nibble of byte 14 and the 8 bits of byte 12) - Range is 0 mm to 4095 mm.

    TUint16 hais = word1 >> 4; // first nullify 4 lsb
    hais = hais << ( 4 + 4 ); // and then move back the first 4 and then again 4
    hais += word2;

    return hais;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetVerticalAddressableImageSize
// ----------------------------------------------------------------------------
//
TUint16 CEdidParserBase::GetVerticalAddressableImageSize( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    TUint16 word2;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[14];
        word2 = iBaseEdidData.iTimingDescriptor[13];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[14];
        word2 = iBaseEdidData.iSecondTimingDescriptor[13];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[14];
        word2 = iBaseEdidData.iMonitorDescriptor[13];
        }
    else
        {
        //ERROR
        return 0;
        }

    //Vertical Addressable Video Image Size in mm is represented by a 12 bit number (Lower nibble
    //of byte 14 and the 8 bits of byte 13) - Range is 0 mm to 4095 mm.

    TUint16 vais = word1;
    vais = vais << 12; // first nullify 4 msb and then move back 1 nibble
    vais = vais >> 4;
    vais += word2;

    return vais;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetHorizontalBorderSize
// ----------------------------------------------------------------------------
//
TUint8 CEdidParserBase::GetHorizontalBorderSize( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[15];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[15];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[15];
        }
    else
        {
        //ERROR
        return 0;
        }

    //Right Horizontal Border or Left Horizontal Border in Pixels is represented by
    // an 8 bit number (the 8 bits of byte 15) - Range is 0 pixels to 255 pixels.

    // the same value is used for (left and right) / (top and bottom)
    return word1;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetVerticalBorderSize
// ----------------------------------------------------------------------------
//
TUint8 CEdidParserBase::GetVerticalBorderSize( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[16];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[16];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[16];
        }
    else
        {
        //ERROR
        return 0;
        }

    //Top Vertical Border or Bottom Vertical Border in Lines is represented by an 8 bit number (the
    //8 bits of byte 16) - Range is 0 lines to 255 lines.
    return word1;
    }

// ----------------------------------------------------------------------------
// CEdidParserBase::GetVideoIsInterlaced
// ----------------------------------------------------------------------------
//
TBool CEdidParserBase::GetVideoIsInterlaced( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;
    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[17];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[17];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[17];
        }
    else
        {
        //ERROR
        return EFalse;
        }

    // byte 17
    // Bytes Bit Definitions Detailed Timing Definitions
    // 7 6 5 4 3 2 1 0 Signal Interface Type:
    // 0 _ _ _ _ _ _ _ Non-Interlaced (1 frame = 1 field)
    // 1 _ _ _ _ _ _ _ Interlaced (1 frame = 2 fields)

    return KBit7 & word1;
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetStereoViewingSupport
// ----------------------------------------------------------------------------
//
TEdidStereoViewingSupport CEdidParserBase::GetStereoViewingSupport( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    TUint16 word1;

    if( aDataBlockNumber == 1 )
        {
        word1 = iBaseEdidData.iTimingDescriptor[17];
        }
    else if( aDataBlockNumber == 2 )
        {
        word1 = iBaseEdidData.iSecondTimingDescriptor[17];
        }
    else if( aDataBlockNumber == 3 )
        {
        word1 = iBaseEdidData.iMonitorDescriptor[17];
        }
    else
        {
        //ERROR
        return EUnknownStereoViewingSupport;
        }

    //Bytes Bit Definitions Detailed Timing Definitions
    //_ 6 5 _ _ _ _ 0 Stereo Viewing Support:
    //  0 0 _ _ _ _ x Normal Display – No Stereo. The value of bit 0 is "don't care"
    //  0 1 _ _ _ _ 0 Field sequential stereo, right image when stereo sync signal = 1
    //  1 0 _ _ _ _ 0 Field sequential stereo, left image when stereo sync signal = 1
    //  0 1 _ _ _ _ 1 2-way interleaved stereo, right image on even lines
    //  1 0 _ _ _ _ 1 2-way interleaved stereo, left image on even lines
    //  1 1 _ _ _ _ 0 4-way interleaved stereo
    //  1 1 _ _ _ _ 1 Side-by-Side interleaved stereo
    TUint8 bit17 = word1;
    if( !( ( KBit6 & bit17 ) | ( KBit5 & bit17 ) ) ) //  0 0 _ _ _ _ x Normal Display – No Stereo.
        { //                The value of bit 0 is "don't care"
        return ENormalDisplay;
        }
    else if( !( KBit6 & bit17 ) && ( KBit5 & bit17 ) && !( KBit0 & bit17 ) ) //  0 1 _ _ _ _ 0 Field sequential stereo,
        { //                right image when stereo sync signal=1
        return EFieldSequentialStereoRightWhenStereoSyncSignal1;
        }
    else if( ( KBit6 & bit17 ) && !( KBit5 & bit17 ) && !( KBit0 & bit17 ) ) //  1 0 _ _ _ _ 0 Field sequential stereo,
        { //                left image when stereo sync signal=1
        return EFieldSequentialStereoLeftWhenStereoSyncSignal1;
        }
    else if( !( KBit6 & bit17 ) && ( KBit5 & bit17 ) && ( KBit0 & bit17 ) ) //  0 1 _ _ _ _ 1 2-way interleaved stereo,
        { //                right image on even lines
        return ETwoWayInterleavedStereoRightImageOnEvenLines;
        }
    else if( ( KBit6 & bit17 ) && !( KBit5 & bit17 ) && ( KBit0 & bit17 ) ) //  1 0 _ _ _ _ 1 2-way interleaved stereo,
        { //                left image on even lines
        return ETwoWayInterleavedStereoLeftImageOnEvenLines;
        }
    else if( ( KBit6 & bit17 ) && ( KBit5 & bit17 ) && !( KBit0 & bit17 ) ) //  1 1 _ _ _ _ 0 4-way interleaved stereo
        {
        return EFourWayInterleaverStereo;
        }
    else if( ( KBit6 & bit17 ) && ( KBit5 & bit17 ) && ( KBit0 & bit17 ) ) //  1 1 _ _ _ _ 1 Side-by-Side interleaved stereo
        {
        return ESideBySideInterleavedStere;
        }
    else
        {
        // ERROR
        return EUnknownStereoViewingSupport;
        }

    // Unreachable
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetSyncSignalDefinitions
// ----------------------------------------------------------------------------
//
TEdidSyncSignalDefinitions CEdidParserBase::GetSyncSignalDefinitions( TUint8 aDataBlockNumber ) const
    {
    FUNC_LOG;

    // byte 17
    // 4 3 2 1 _ Analog Sync Signal Definitions:
    //------------------------------------------
    // 0 0 _ _ _ Analog Composite Sync:
    // 0 1 _ _ _ Bipolar Analog Composite Sync:

    TUint8 byte17 = 0;
    if( aDataBlockNumber == 1 )
        {
        byte17 = iBaseEdidData.iTimingDescriptor[17];
        }
    else if( aDataBlockNumber == 2 )
        {
        byte17 = iBaseEdidData.iSecondTimingDescriptor[17];
        }
    else if( aDataBlockNumber == 3 )
        {
        byte17 = iBaseEdidData.iMonitorDescriptor[17];
        }
    else
        {
        // ERROR
        return EUnknownSignalDefinition;
        }

    if( !( KBit4 & byte17 ) ) // if bit4 == 0 then this is analog display
        {
        return GetAnalogSyncSignalDefinitions( byte17 );
        }
    else
        {
        return GetDigitalSyncSignalDefinitions( byte17 );
        }
    // unreachable
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetAnalogSyncSignalDefinitions
// ----------------------------------------------------------------------------
//
TEdidSyncSignalDefinitions CEdidParserBase::GetAnalogSyncSignalDefinitions( const TUint aByte17 )
    {
    FUNC_LOG;

    // byte 17
    // 4 3 2 1 _ Analog Sync Signal Definitions:
    //------------------------------------------
    // 0 0 _ _ _ Analog Composite Sync:
    // 0 1 _ _ _ Bipolar Analog Composite Sync:
    // 0 _ 0 _ _ ---------- Without Serrations;
    // 0 _ 1 _ _ ---------- With Serrations (H-sync during V-sync);
    // 0 _ _ 0 _ -------------------- Sync On Green Signal only
    // 0 _ _ 1 _ -------------------- Sync On all three (RGB) video signals

    TBool ACS = !( KBit3 & aByte17 ); // if true -> bipolar analog composite sync
    TBool serrations = KBit2 & aByte17;
    TBool syncOnGreen = !( KBit1 & aByte17 );

    if( ACS )
        {
        if( !serrations )
            {
            if( syncOnGreen )
                {
                return EAnalogCompositeSyncWithoutSerrationsSyncSyncOnGreenSignalOnly;
                }
            else
                {
                return EAnalogCompositeSyncWithoutSerrationsSyncOnAllThreeVideoSignals;
                }
            }
        else
            {
            if( syncOnGreen )
                {
                return EAnalogCompositeSyncWithoutSerrationsSyncSyncOnGreenSignalOnly;
                }
            else
                {
                return EAnalogCompositeSyncWithoutSerrationsSyncOnAllThreeVideoSignals;
                }
            }
        }
    else
        {
        if( !serrations )
            {
            if( syncOnGreen )
                {
                return EAnalogBipolarAnalogCompositeSyncWithoutSerrationsSyncSyncOnGreenSignalOnly;
                }
            else
                {
                return EAnalogBipolarAnalogCompositeSyncWithoutSerrationsSyncOnAllThreeVideoSignals;
                }
            }
        else
            {
            if( syncOnGreen )
                {
                return EAnalogBipolarAnalogCompositeSyncWithSerrationsSyncSyncOnGreenSignalOnly;
                }
            else
                {
                return EAnalogBipolarAnalogCompositeSyncWithSerrationsSyncOnAllThreeVideoSignals;
                }
            }
        }
    // unreachable
    }

// ----------------------------------------------------------------------------
// CBaseEdid::GetDigitalSyncSignalDefinitions
// ----------------------------------------------------------------------------
//
TEdidSyncSignalDefinitions CEdidParserBase::GetDigitalSyncSignalDefinitions( const TUint aByte17 )
    {
    FUNC_LOG;

    //        4 3 2 1 0 bit
    //        --------------
    //        1 0 _ _ _ Digital Composite Sync:
    //        1 0 0 _ _ ---------- Without Serrations;
    //        1 0 1 _ _ ---------- With Serrations (H-sync during V-sync);
    //        1 1 _ _ _ Digital Separate Sync:
    //        1 1 0 _ _ ---------- Vertical Sync is Negative;
    //        1 1 1 _ _ ---------- Vertical Sync is Positive;
    //        1 _ _ 0 _ -------------------- Horizontal Sync is Negative (outside of V-sync)
    //        1 _ _ 1 _ -------------------- Horizontal Sync is Positive (outside of V-sync)
    TBool digComp = ( KBit3 & aByte17 ); // ETrue == digital separate sync
    TBool bit2 = KBit2 & aByte17;

    if( !digComp ) // digital composite sync
        {
        if( !bit2 ) // without serrations
            {
            return EDigitalCompositeSyncWithoutSerrations;
            }
        else // with serrations
            {
            return EDigitalCompositeSyncWithSerrations;
            }
        } // endif  digital composite sync
    else //        digital separate sync
        {
        TBool bit1 = KBit1 & aByte17;

        if( !bit2 ) // vertical = neg
            {
            if( !bit1 )
                { // vertical = neg, horizontal = neg
                return EDigitalSeparateSyncVerticalSyncIsNegativeHorizontalSyncIsNegative;
                }
            else
                { // vertical = neg, horizontal = pos
                return EDigitalSeparateSyncVerticalSyncIsNegativeHorizontalSyncIsPositive;
                }
            }
        else // vertical = pos
            {
            if( !bit1 )
                { // vertical = pos, horizontal = neg
                return EDigitalSeparateSyncVerticalSyncIsPositiveHorizontalSyncIsNegative;
                }
            else
                { // vertical = pos, horizontal = pos
                return EDigitalSeparateSyncVerticalSyncIsPositiveHorizontalSyncIsPositive;
                }
            }
        }
    // unreachable
    }

// End of file
