/*
* Copyright (c) 2010 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:
*
*/


/** @file

XtiRx driver receives the data from Musti and sends it to Trace Core.

*///=========================================================================
                                      

//- Include Files  ----------------------------------------------------------

#include <rap.h>
#include <kernel/kernel.h>
#include <rap_priv.h>
#include <PowerResourceManager.h>
#include "xtirx.h"
#include "xtitx.h"
#include "XtiDebug.h"

//- Namespace ---------------------------------------------------------------


//- Using -------------------------------------------------------------------


//- External Data -----------------------------------------------------------


//- External Function Prototypes --------------------------------------------


//- Constants ---------------------------------------------------------------

const TInt   KBitsInByte                    = 8;  // the amount of bits in byte
const TInt   KBitsInDataLengthMsg           = 32; // the amount of bits in data length message
const TInt   KMaxWakeupResponceCounterValue = 20; // the maximum number of attempts to writing to TraceCore buffer
const TInt   KWakeupResponceTimerInterval   = 100000; // time interval of attempts to writing to TraceCore buffer (microseconds)
const TUint  KBitRate                       = 115200; // bit rate
const TUint8 KDefaultDfcPriority            = 3;      // Default DFC queue priority
const TInt   KInterruptId                   = TRap::EIntIdASR001_MUSTI_BUFFERFULL; // Uart interrupt line
const TInt   KPollPeriodMs                  = 2;      // time interval of checking if the Uart RX buffer has data (milliseconds)
const TInt   KIdleTimerInterval             = 500000; // time interval for idle timer (microseconds)
const TInt   KResetTimerInterval            = 800000; // time interval for idle timer (microseconds)
const TInt   KMaxPoll                       = 25;    // the maximum number of checking if the Uart RX buffer has data 
const TUint  KMaxXtiMessageLength           = 8204;    // Maximum size of XTI message send by Musti
const TUint  KClearPoll                     = 3; // Used when clearing UART buffer


/** The name of the created XTI RX thread */
_LIT( KThreadName, "XtiRxThread" );

/** DFC thread priority */
const TInt KDfcThreadPriority = 26;


//- Macros ------------------------------------------------------------------

//- Global and Local Variables ----------------------------------------------

XtiRx* XtiRx::iXtiRxPtr = NULL;

TBool HasUartRxFifoData( TAny* aPtr );

_LIT(KXTIRXDriver, "XTI RX Driver");

//- Local Function Prototypes -----------------------------------------------

//===========================================================================

//- Local Functions ---------------------------------------------------------

//===========================================================================

//- Member Functions --------------------------------------------------------
void XtiRx::GPIOwakeIsr(TAny* aPtr)
    {
    XTI_TRACE( Kern::Printf("XtiRx::GPIOwakeIsr") )
    XTI_TRACE( Kern::Printf("XtiRx::GPIOwakeIsr <<") )
    }
    
/*
-----------------------------------------------------------------------------

    XtiRx

    XtiRx
                  
    Constructor
-----------------------------------------------------------------------------
*/

XtiRx::XtiRx()
    : iDfcQueue( NULL )
    , iReceiveDataDfc( ReceiveDataDfc, this,  KDefaultDfcPriority )
    , iGPIOWakeupDfc( GPIOWakeupDfc, this, KDefaultDfcPriority )
    , iSetPowerDfc( SetPowerDfc, this, KDefaultDfcPriority )
    , iClearPowerDfc( ClearPowerDfc, this, KDefaultDfcPriority )
    , iClocksOn( EFalse )
    , iTraceCoreDfcPtr( NULL )
    , iRxBufferPtr( NULL )
    , iRxState( KRxStateIdle )
    , iReceiveBufferFree( EFalse )
    , iMessagelength( 0 )
    , iWakeupResponseCounter( 0 )
    , iClientId( 0 )
    {
    
    // Register the PRM client
    TInt r = TPowerResourceManager::RegisterClient( iClientId, KXTIRXDriver );
    __ASSERT_DEBUG(r==KErrNone,Kern::Fault("Registration with the power manager failed",r));
    }


/*
-----------------------------------------------------------------------------
    XtiRx

    ~XtiRx
    
    Destructor
-----------------------------------------------------------------------------
*/
XtiRx::~XtiRx()
    {
    iRxBufferPtr = NULL;
    iTraceCoreDfcPtr = NULL;

    // Deregister the PRM client
    TPowerResourceManager::DeRegisterClient( iClientId );    
    iDfcQueue = NULL;
    }

/*
----------------------------------------------------------------------------

    XtiRx

    Instance

    Return an instance to XtiRx interface. This method returns the
    only XtiRx instance system can have, it is not possible to create
    new instances of this class.

    Return Values:          iXtiRxPtr* An instance to XtiRx class

-----------------------------------------------------------------------------
*/
XtiRx* XtiRx::Instance( )
    {
    XTI_TRACE( Kern::Printf("XtiRx::Instance") )
    // Allow only 1 instance of XtiRx to exists at any time
    if ( iXtiRxPtr == NULL )
        {
        iXtiRxPtr = new XtiRx();
        }
    return iXtiRxPtr;
    }

/*
----------------------------------------------------------------------------

    XtiRx

    Init

    Bind Uart interrupt, configure Uart HW and start receiving the data 

    Return Values: KErrNone or error code
    
-----------------------------------------------------------------------------
*/
TInt XtiRx::Init()      
    {
    XTI_TRACE( Kern::Printf("XtiRx::Init >>") ) 
    TInt ret( KErrNone );
    SetPowerRequirements();

    XTI_TRACE( Kern::Printf("XtiRx::Init - Bind method Isr to uart interrupt 0x%x", KInterruptId) ) 
    ret = Interrupt::Bind( KInterruptId, Isr, this );
       
    if( ret == KErrNone ) 
        {                        
        ret = Configure();
        if( ret == KErrNone )
            {                           
            ret = Start();
            }         
        }
    XTI_TRACE( Kern::Printf("XtiRx::Init <<, ret= %d", ret))
    return ret;
    }

/*
----------------------------------------------------------------------------

    XtiRx

    ConfigureUart

    Configure Uart HW.
    
    Return Value: KErrNone or error code

-----------------------------------------------------------------------------
*/
TInt XtiRx::ConfigureUart() const
{
    XTI_TRACE( Kern::Printf("XtiRx::ConfigureUart >>") )
  
    TInt ret( KErrNone );
  
    XTI_TRACE( Kern::Printf("XtiRx::ConfigureUart - Disable uart interrupt 0x%x", KInterruptId) )
    ret = Interrupt::Disable( KInterruptId );
    __ASSERT_DEBUG(ret == KErrNone, Kern::Fault( ("XtiRx::ConfigureUart"), __LINE__ ));
  
    TUint32 clock_in_hz = TRap::McuppClockInHz();
  
    TUint32 baud_rate = 2304000;  // Use Musti default bit rate

  
    // Integer part of bitduration value for Rx (the bit window)
  
    TUint32 mcuClock;
    mcuClock = clock_in_hz / baud_rate;
    TUint32 rx_bitduration = (TUint32)((mcuClock - 3) / 2);
    TUint32 rx_modulo = rx_bitduration / 5;  // Use the recommended 20%
  
  
    // Fractional part: The formula is rewritten like this in order to
    // be able to use integer math:
    //
    // rx_bitduration = clock_in_hz / (2 * baud_rate) - 3/2
    //
    // Thus the fractional part of rx_bitduration can be calculated as
    //
    //      f = f1 - f2
    //
    // where
    //
    //      f1 = fractional_part_of( clock_in_hz / (2 * baud_rate) )
    //
    //      f2 = fractional_part_of( 3/2 )
    //
    // The two fractional parts are calculated as follows:
    //
    // f1 = ( clock_in_hz % (2 * baud_rate) ) * ( 2^32 / 2 * baud_rate )
    //    = ( clock_in_hz % (2 * baud_rate) ) * ( 2^31 / baud_rate )
    //
    //
    // f2 = ( 3 % 2 ) * ( 2^32 / 2 )
    //    =     1     *   2^31
    //
    TUint32 rx_fraction = (clock_in_hz % (baud_rate << 1)) * ( (TUint32)(1<<31)/baud_rate ) - (TUint32)(1<<31);
  
    XTI_TRACE( Kern::Printf( "XtiRx Rx parameters:" ));
    XTI_TRACE( Kern::Printf( "Baud             %u", baud_rate ) );
    XTI_TRACE( Kern::Printf( "Mcupp clock freq %u", clock_in_hz ) );
    XTI_TRACE( Kern::Printf( "Write registers:" ));
    XTI_TRACE( Kern::Printf( "RX-bitduration   %u", rx_bitduration) );
    XTI_TRACE( Kern::Printf( "RX-pulseduration %u", rx_bitduration) );
    XTI_TRACE( Kern::Printf( "RX-fraction      %u", rx_fraction) );
    XTI_TRACE( Kern::Printf( "RX-modulo        %u", rx_modulo) );
  
    // Configure static Rx parameters
    // Setting up ASR001
    TRap::SetRegister32(ASR001_T_V_MODE_RUN, KRapRegXTIASR001_MODE);
    TRap::SetRegister32(rx_modulo, KRapRegXTIASR001_MODULO);
    TRap::SetRegister32(ASR001_T_V_POLARITY_POSITIVE, KRapRegXTIASR001_POLARITY);
    TRap::SetRegister32(ASR001_T_V_FLOW_OFF, KRapRegXTIASR001_FLOW);
    TRap::SetRegister32(ASR001_T_V_RXSTATE_IDLE, KRapRegXTIASR001_RXSTATE);
    TRap::SetRegister32(rx_bitduration, KRapRegXTIASR001_BITDURATION); /* Bitrate = 2304000 b/s */
    TRap::SetRegister32(rx_bitduration, KRapRegXTIASR001_PULSEDURATION);
    TRap::SetRegister32(rx_fraction, KRapRegXTIASR001_FRACTION);
    // Note that only the upper bits of the written fraction will have effect
    // e.g. 0x40000000
    //TRap::SetRegister32(0x42AAAAAA, KRapRegXTIASR001_FRACTION);
    TRap::SetRegister32(0x02, KRapRegXTIASR001_THRESHOLD);
    TRap::SetRegister32(0x07, KRapRegXTIASR001_DATABITS); /* 8 Data bits */
    TRap::SetRegister32(0x00, KRapRegXTIASR001_STOPBITS); /* 1 Stop bits */
    TRap::SetRegister32(ASR001_T_V_PARITY_NONE, KRapRegXTIASR001_PARITY); /* No parity */
    TRap::SetRegister32(0x00, KRapRegXTIASR001_WATERMARK);
  
  
    XTI_TRACE( Kern::Printf("XtiRx::ConfigureUart <<") )
    return ret;
}

/*
----------------------------------------------------------------------------

    XtiRx

    Configure

    Configure HW.
    
    Return Value: KErrNone or error code

-----------------------------------------------------------------------------
*/
TInt XtiRx::Configure() const
    {
    TInt ret( KErrNone );

    XTI_TRACE( Kern::Printf("XtiRx::Configure >>") )

    // Configure UART
    ret = ConfigureUart();
    __ASSERT_DEBUG(ret == KErrNone, Kern::Fault( ("XtiRx::Configure"), __LINE__ ));

    XTI_TRACE( Kern::Printf("XtiRx::Configure <<") )
    return ret;

    }


/*
----------------------------------------------------------------------------

    XtiRx

    Isr

    Uart interrupt service routine
    
    @param   aPtr  Pointer to XtiRx object

-----------------------------------------------------------------------------
*/
void XtiRx::Isr(TAny* aPtr)
    {
    XTI_TRACE( Kern::Printf("XtiRx::Isr >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::Isr - Null pointer!"), 0 ));

    XTI_TRACE( Kern::Printf("XtiRx::Isr - Disable uart interrupt 0x%x", KInterruptId) )  
    TInt ret = Interrupt::Disable( KInterruptId );
    __ASSERT_DEBUG(ret == KErrNone, Kern::Fault( ("XtiRx::Isr"), __LINE__ ));
    
    XtiRx& self = *static_cast<XtiRx*>( aPtr );
    XTI_TRACE( Kern::Printf("XtiRx::Isr - Add ReceiveDataDfc") )     
    self.iReceiveDataDfc.Add();
    
    XTI_TRACE( Kern::Printf("XtiRx::Isr <<") )
    }


/*
----------------------------------------------------------------------------

    XtiRx

    ReceiveDataDfc

    Function called in DFC context after Uart interrupt. Reads the data
    from Uart RX FIFO and saves the data to the buffer which is defined
    XtiRx::Register function. 

    @param   aPtr  Pointer to XtiRx object    

-----------------------------------------------------------------------------
*/
void XtiRx::ReceiveDataDfc( TAny* aPtr )
    {
    XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::ReceiveDataDfc - Null pointer!"), 0 ));

    XtiRx& self = *static_cast< XtiRx* >( aPtr );
    TInt ret( KErrNone );

    XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Cancel timer") )
    self.iIdleTimer.Cancel();    
    // Start timer safety timer to clear state machine if problems
    XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Start timer safety timer to clear state machine if problems") )
    self.iIdleTimer.OneShot( KResetTimerInterval, XtiRx::ResetReceiveState, aPtr );
    
    self.SetPowerRequirements(); 
    if( self.iRxState == KRxStateIdle )
        {
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - XTI state = KRxStateIdle") )
        TInt count(0);
        // Clear Uart RX buffer
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Clear Uart RX buffer") ) 
 
        while( TRap::Register32(KRapRegXTIASR001_GAUGE) != 0 || count < KClearPoll )
            {
            TInt r = Kern::PollingWait(HasUartRxFifoData, (TAny*)&self , KPollPeriodMs, KMaxPoll);
            if( r == KErrNone  )
                {
                TRap::Register32(KRapRegXTIASR001_DATA);
                }
            count++;
            }

        // check if Trace Core has read the previous data package
        if( self.iReceiveBufferFree )
            {
            if( ret == KErrNone ) 
                {
                // Send bit rate to Musti
                XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Send bit rate to Musti") ) 
                XtiTx::SetBitRate( KBitRate );
                // Waiting for the data length message
                XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Waiting for the data length message") ) 
                self.iRxState = KRxStateWaitDataLenMsg;
                }
            }
        else
            {
            XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Buffer not free -> start timer") )
            self.iWakeupResponseTimer.OneShot( KWakeupResponceTimerInterval, XtiRx::ReceiveDataDfc, aPtr );
            self.iWakeupResponseCounter++;
            if( self.iWakeupResponseCounter == KMaxWakeupResponceCounterValue )
                {
                self.iWakeupResponseTimer.Cancel();
                ret = KErrGeneral;
                } 
            }
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Enable uart interrupt 0x%x", KInterruptId) )    
        Interrupt::Enable( KInterruptId );
        }
    else if( self.iRxState == KRxStateWaitDataLenMsg ) 
        {
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - XTI state = KRxStateWaitDataLenMsg") )
        self.iMessagelength = 0;
        // Read XTI message length. The number of bytes is sent as a 32-bit binary little-endian integer.
        TInt r( KErrNone );
        for( TInt i = 0 ; (i < KBitsInDataLengthMsg) ; i += KBitsInByte )
            {
            //TUint32 len = 0;
            r = Kern::PollingWait(HasUartRxFifoData, (TAny*)&self , KPollPeriodMs, KMaxPoll);
            if( r == KErrNone  )
                {
                //len = TRap::Register32(KRapRegXTIASR001_DATA) << i;
                self.iMessagelength += TRap::Register32(KRapRegXTIASR001_DATA) << i;
                }
            //__DEBUG_ONLY (Kern::Printf("XtiRx::ReceiveDataDfc - len = %d", len) );
            //self.iMessagelength += len;
            }
        __DEBUG_ONLY (Kern::Printf("XtiRx::ReceiveDataDfc - iMessagelength = %d", self.iMessagelength) );
        // acknowledgement to Musti
        
        if( r == KErrNone )
            {
            XtiTx::SendDataLenAckMsg();
            self.iRxState = KRxStateWaitDataMsg; 
            }
        else
            {
            self.iXtiRxPtr->iReceiveBufferFree = ETrue;
            self.iXtiRxPtr->iRxBufferPtr->Zero();  // set data length to zero
            self.iRxState = KRxStateIdle;
            }
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Enable uart interrupt 0x%x", KInterruptId) )  
        Interrupt::Enable( KInterruptId );
        }
    else
        {
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - XTI state = KRxStateWaitDataMsg") )
        ret = self.ReadData();
        if( ret == KErrNone )
            {
            // acknowledgement to Musti
            XtiTx::SendDataRxAckMsg();   
            self.iReceiveBufferFree = EFalse;
            // Cancel reset timer
            XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Cancel reset timer") )
            self.iIdleTimer.Cancel();
            // inform Trace core that the data is in the receive buffer
            self.iTraceCoreDfcPtr->Enque();
            // Start standby timer
            XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Start standby timer") ) 
            self.iRxState = KRxStateIdle;
            self.iIdleTimer.OneShot( KIdleTimerInterval, XtiRx::StandbyMode, aPtr );
            }
        XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc - Enable uart interrupt 0x%x", KInterruptId) )  
        Interrupt::Enable( KInterruptId );
        }  
    XTI_TRACE( Kern::Printf("XtiRx::ReceiveDataDfc <<") )
    }


/*
----------------------------------------------------------------------------

    XtiRx

    GPIOWakeupDfc

    Function called in DFC context after GPIO interrupt. Mux the UART PIN and
    start UART clocks
    
    @param   aPtr  Pointer to XtiRx object    

-----------------------------------------------------------------------------
*/
void XtiRx::GPIOWakeupDfc( TAny* aPtr )
{
    XTI_TRACE( Kern::Printf("XtiRx::GPIOWakeupDfc >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::GPIOWakeupDfc - Null pointer!"), 0 ));

    XtiRx& self = *static_cast< XtiRx* >( aPtr );

    self.SetPowerRequirements();
    
    XTI_TRACE( Kern::Printf("XtiRx::GPIOWakeupDfc - Enable uart interrupt 0x%x", KInterruptId) )
    TInt ret = Interrupt::Enable( KInterruptId );
    __ASSERT_DEBUG(ret == KErrNone, Kern::Fault( ("XtiRx::GPIOWakeupDfc"), __LINE__ ));   
          
    XTI_TRACE( Kern::Printf("XtiRx::GPIOWakeupDfc <<" ) )
}


/*
----------------------------------------------------------------------------

    XtiRx

    GPIODeepSleepWakeupDfc

    Function called in DFC context after GPIO interrupt in deep sleep. Mux the UART PIN and
    start UART clocks
    
    @param   aPtr  Pointer to XtiRx object    

-----------------------------------------------------------------------------
*/
void XtiRx::GPIODeepSleepWakeupDfc( TAny* aPtr )
{
    XTI_TRACE( Kern::Printf("XtiRx::GPIODeepSleepWakeupDfc >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::GPIODeepSleepWakeupDfc - Null pointer!"), 0 ));

    XtiRx& self = *static_cast< XtiRx* >( aPtr );

    XTI_TRACE( Kern::Printf("XtiRx::GPIODeepSleepWakeupDfc - Bind method Isr to uart interrupt 0x%x", KInterruptId) ) 
    TInt ret = Interrupt::Bind( KInterruptId, Isr, aPtr );

    self.SetPowerRequirements();

    self.ConfigureUart();

    XTI_TRACE( Kern::Printf("XtiRx::GPIODeepSleepWakeupDfc - Enable uart interrupt 0x%x", KInterruptId) )
    ret = Interrupt::Enable( KInterruptId );
    __ASSERT_DEBUG(ret == KErrNone, Kern::Fault( ("XtiRx::GPIODeepSleepWakeupDfc"), __LINE__ ));   
          
    XTI_TRACE( Kern::Printf("XtiRx::GPIODeepSleepWakeupDfc <<" ) )
}

/*
----------------------------------------------------------------------------

    XtiRx

    SetPowerDfc

    Call SetPowerRequirements
    
    @param   aPtr  Pointer to XtiRx object    

-----------------------------------------------------------------------------
*/
void XtiRx::SetPowerDfc( TAny* aPtr )
{
    XTI_TRACE( Kern::Printf("XtiRx::SetPowerDfc >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::SetPowerDfc - Null pointer!"), 0 ));

    XtiRx& self = *static_cast< XtiRx* >( aPtr );

    self.SetPowerRequirements();

    XTI_TRACE( Kern::Printf( "XtiRx::SetPowerDfc <<" ) )
}


/*
----------------------------------------------------------------------------

    XtiRx

    ClearPowerDfc

    Call ClearPowerRequirements
    
    @param   aPtr  Pointer to XtiRx object    

-----------------------------------------------------------------------------
*/
void XtiRx::ClearPowerDfc( TAny* aPtr )
{
    XTI_TRACE( Kern::Printf("XtiRx::ClearPowerDfc >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::ClearPowerDfc - Null pointer!"), 0 ));

    XtiRx& self = *static_cast< XtiRx* >( aPtr );

    self.ClearPowerRequirements();

    XTI_TRACE( Kern::Printf( "XtiRx::ClearPowerDfc <<" ) )
}
         
         

/*
----------------------------------------------------------------------------

    XtiRx

    ReadRxData

    Read data from Uart RX FIFO

    Return Value: KErrNone or error code
-----------------------------------------------------------------------------
*/
TInt XtiRx::ReadData()
    {
    XTI_TRACE( Kern::Printf("XtiRx::ReadData >>") )
    TInt ret( KErrNone );
    TInt error( KErrNone );
    TUint32 character( 0 );
    __ASSERT_DEBUG(iRxBufferPtr != NULL, Kern::Fault( ("XtiRx::ReadData - Null pointer!"), 0 ));
    iRxBufferPtr->Zero();  // set data length to zero

    if( iMessagelength > KMaxXtiMessageLength )
        {     
        XTI_TRACE( Kern::Printf("XtiRx::ReadData - Message is greater than the maximum size of XTI message") )
        ret = KErrGeneral;
        }                    
    else
        {
        while( iMessagelength != 0 && ret == KErrNone )
            {           
            ret = Kern::PollingWait(HasUartRxFifoData, this , KPollPeriodMs, KMaxPoll);
            if( ret == KErrNone  )
                {
                character = TRap::Register32(KRapRegXTIASR001_DATA);
                XTI_TRACE( Kern::Printf("XtiRx::ReadData - data = 0x%x",character) )
                error = character >> KBitsInByte;
                character = character & KMaxTUint8;
  
                /*Check for receive errors
                Error flags are OR'ed into the high bits of char
                */
 
                if( error & ASR001_T_V_ERROR_OVERRUN) 
                    {
                     XTI_TRACE( Kern::Printf("XtiRx::ReadData - Overrun ERROR") ) 
                    ret = KErrCommsOverrun;  
                    }
                if( error & ASR001_T_V_ERROR_PARITY)
                    {
                    XTI_TRACE( Kern::Printf("XtiRx::ReadData - Parity ERROR") ) 
                    ret = KErrCommsParity;
                    }
                if( error & ASR001_T_V_ERROR_FRAMING )
                    {
                    XTI_TRACE( Kern::Printf("XtiRx::ReadData - Framing ERROR") )
                    ret = KErrCommsFrame;
                    }

                iRxBufferPtr->Append( character );
                iMessagelength--;
                }
            }
        }

    XTI_TRACE( Kern::Printf("XtiRx::ReadData <<, ret= %d", ret) )
    return ret;
    }


/*
----------------------------------------------------------------------------

    XtiRx

    Register

    This method is used to register an user to the driver.
    
    @param   aDfc         Pointer to the DFC function which is called by the XTI driver when the data is
                          available in the receive buffer.
    
    @param   aBuf         Receive buffer 

    Return Value:         KErrNone or error code  

-----------------------------------------------------------------------------
*/
EXPORT_C TInt XtiRx::Register( TDfc* aDfc, TDes8& aBuf  )
    {
    __ASSERT_DEBUG(aDfc != NULL, Kern::Fault( ("XtiRx::Register - Null pointer!"), 0 ));
    XTI_TRACE( Kern::Printf("XtiRx::Register >>") )
    TInt ret(KErrNone);

    // Create DFC thread inside of which the operations are performed
    if( iXtiRxPtr != NULL )
        {
        ret = Kern::DfcQCreate( iXtiRxPtr->iDfcQueue, KDfcThreadPriority, &KThreadName );
        }
     else
        {
        ret = KErrGeneral;
        }
        
    if(ret == KErrNone )
        {
        iXtiRxPtr->iReceiveDataDfc.SetDfcQ( iXtiRxPtr->iDfcQueue );
        iXtiRxPtr->iGPIOWakeupDfc.SetDfcQ( iXtiRxPtr->iDfcQueue );
        iXtiRxPtr->iSetPowerDfc.SetDfcQ( iXtiRxPtr->iDfcQueue );
        iXtiRxPtr->iClearPowerDfc.SetDfcQ( iXtiRxPtr->iDfcQueue );

        ret = iXtiRxPtr->Init();
        if( ret == KErrNone )
            {
            iXtiRxPtr->iTraceCoreDfcPtr = aDfc;
            iXtiRxPtr->iRxBufferPtr = &aBuf;
            iXtiRxPtr->iReceiveBufferFree = ETrue;
            }
        }
               
    XTI_TRACE( Kern::Printf("XtiRx::Register <<, ret= %d",ret) )
    iXtiRxPtr->ClearPowerRequirements();
    return ret;
    }


/*
----------------------------------------------------------------------------

    XtiRx

    SetReceiveBufferRead

    User of the driver calls this function when the receive buffer has been read

-----------------------------------------------------------------------------
*/
EXPORT_C void XtiRx::SetReceiveBufferRead()
    {
    XTI_TRACE( Kern::Printf("XtiRx::SetReceiveBufferRead >>") )
    iXtiRxPtr->iReceiveBufferFree = ETrue;
    iXtiRxPtr->iRxBufferPtr->Zero();  // set data length to zero
    XTI_TRACE( Kern::Printf("XtiRx::SetReceiveBufferRead <<") )
    }


/*
----------------------------------------------------------------------------

    XtiRx
    
    Start
                
    Start receiving characters
    
    Return Value:         KErrNone or error code

-----------------------------------------------------------------------------
*/

TInt XtiRx::Start() const 
    {   
    XTI_TRACE( Kern::Printf( "XtiRx::Start >>") )
    TInt ret(KErrNone);

    // Clear Uart RX buffer
     XTI_TRACE( Kern::Printf( "XtiRx::Start - Clear Uart RX buffer") )   
    while(  TRap::Register32(KRapRegXTIASR001_GAUGE) )
        { 
         TRap::Register32(KRapRegXTIASR001_DATA);
        }
        
    if( ret == KErrNone )    
        {
        // Enable Uart interrupt 
        XTI_TRACE( Kern::Printf( "XtiRx::Start - Enable uart interrupt  0x%x", KInterruptId) )
        ret = Interrupt::Enable( KInterruptId );
        }
    XTI_TRACE( Kern::Printf( "XtiRx::Start <<, ret= %d",ret) )
    return ret;
    }
    

/*
----------------------------------------------------------------------------

    XtiRx
    
    SetPowerRequirements
                
    Set power requirements
    
-----------------------------------------------------------------------------
*/
void XtiRx::SetPowerRequirements() 
    {   
    XTI_TRACE( Kern::Printf( "XtiRx::SetPowerRequirements >>") )
    
    if( iClocksOn == EFalse )
        {
        // Request to enable a clock resource
        XTI_TRACE( Kern::Printf( "XtiRx::SetPowerRequirements - Request to enable a clock resource") )        
      
        iClocksOn = ETrue;
        }
    XTI_TRACE( Kern::Printf( "XtiRx::SetPowerRequirements <<" ) )
    }


/*
----------------------------------------------------------------------------

    XtiRx
    
    ClearPowerRequirements
                
    Clear power requirements
    
-----------------------------------------------------------------------------
*/
void XtiRx::ClearPowerRequirements() 
    {   
    XTI_TRACE( Kern::Printf( "XtiRx::ClearPowerRequirements >>") )
    
    if( iClocksOn )
        {
        iClocksOn = EFalse;
        }
    XTI_TRACE( Kern::Printf( "XtiRx::ClearPowerRequirements <<" ) )
    }


/*
----------------------------------------------------------------------------

    XtiRx
    
    StandbyMode
                
    Set the driver to standby mode
    
-----------------------------------------------------------------------------
*/
void XtiRx::StandbyMode( TAny* aPtr ) 
    {
    XTI_TRACE( Kern::Printf( "XtiRx::StandbyMode >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::StandbyMode - Null pointer!"), 0 ));
    XtiRx& self = *static_cast< XtiRx* >( aPtr );
    XTI_TRACE( Kern::Printf( "XtiRx::StandbyMode - Enque ClearPowerDfc") )    
    self.iClearPowerDfc.Enque();
    self.iRxState = KRxStateIdle;
    XTI_TRACE( Kern::Printf( "XtiRx::StandbyMode <<" ) )
    }    
    

/*
----------------------------------------------------------------------------

    XtiRx
    
    ResetReceiveState
                
    Reset receiver state machine.
    
-----------------------------------------------------------------------------
*/
void XtiRx::ResetReceiveState( TAny* aPtr ) 
    {
    XTI_TRACE( Kern::Printf( "XtiRx::ResetReceiveState >>") )
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::ResetReceiveState - Null pointer!"), 0 ));
    XtiRx& self = *static_cast< XtiRx* >( aPtr );
    self.iXtiRxPtr->iReceiveBufferFree = ETrue;
    self.iXtiRxPtr->iRxBufferPtr->Zero();  // set data length to zero
    XTI_TRACE( Kern::Printf( "XtiRx::ResetReceiveState - Enque ClearPowerDfc") )    
    self.iClearPowerDfc.Enque();
    self.iRxState = KRxStateIdle;
    XTI_TRACE( Kern::Printf( "XtiRx::ResetReceiveState <<" ) )
    }   
    
    
    
    
//===========================================================================

//- Global Functions --------------------------------------------------------
                  
/*
----------------------------------------------------------------------------

    HasUartRxFifoData
                
    Check if there is data in the Uart RX FiFo. 
        
    @param   aPtr  Pointer to XtiRx object 

    Return Values: ETrue ot EFalse

-----------------------------------------------------------------------------
*/
TBool HasUartRxFifoData( TAny* aPtr  )
  {
    __ASSERT_DEBUG(aPtr != NULL, Kern::Fault( ("XtiRx::HasUartRxFifoData - Null pointer!"), 0 ));
    TBool ret( ETrue );
  
    if( TRap::Register32(KRapRegXTIASR001_GAUGE) == 0 )
        {
        XTI_TRACE( Kern::Printf("XtiRx::HasUartRxFifoData - No data in RX FIFO") )
        ret = EFalse;
        }
        
    return ret;
  }


//---------------------------------------------------------------------------
/**
    The entry point for a standard extension. Creates Xti extension.

    @return KErrNone, if successful
*/
DECLARE_STANDARD_EXTENSION()
    {
    TInt ret( KErrNoMemory );
    XtiRx* xtirx = XtiRx::Instance();
    if ( xtirx != NULL )
        {
        ret = KErrNone;
        }
    return ret;
    }                 

//- Namespace ---------------------------------------------------------------

// End of File
