/************************************************************************************
* End of frames are handled here. Called from TxDone and RxDone interrupts in Abel.
*
* Author(s):
*   Thomas O. Jensen, Jesper Thomsen
*
* (c) Copyright 2004, Freescale, Inc.  All rights reserved.
*
* Freescale Confidential Proprietary
* Digianswer Confidential
*
* No part of this document must be reproduced in any form - including copied,
* transcribed, printed or by any electronic means - without specific written
* permission from Freescale.
*
* Last Inspected:
* Last Tested:
************************************************************************************/

#include "DigiType.h"
#include "Phy.h"
#include "PhyMacMsg.h"
#include "MacPhy.h"

/************************************************************************************
*************************************************************************************
* Private macros
*************************************************************************************
************************************************************************************/
#if !(defined(USE_INTERRUPT_RXEOF) && defined(USE_INTERRUPT_TXEOF) )
#define POLL_UNTIL_IDLE {while(IsAbelActive());}
#endif 

#ifdef USE_INTERRUPT_TXEOF
#define DELAY_5US 
#else
#define DELAY_5US { {uint8_t i=10; do {} while(--i);}  }
#endif

/************************************************************************************
*************************************************************************************
* Private prototypes
*************************************************************************************
************************************************************************************/
bool_t PhyCheckAddrMode(uint8_t addrMode);
void (*gIsrSuperFastAction)(void);
/************************************************************************************
*************************************************************************************
* Private type definitions
*************************************************************************************
************************************************************************************/

/************************************************************************************
*************************************************************************************
* Public memory declarations
*************************************************************************************
************************************************************************************/
extern bool_t gPanIdConflict;


#ifdef I_AM_A_SNIFFER
extern rxPacket_t gRxDataBuffer;
rxPacket_t gRxDataBuffer2;
rxPacket_t * gpRxDataToBeSentOnHostInterface  = NULL;  
uint8_t SnifferPacketCounter = 0;
#endif I_AM_A_SNIFFER

/************************************************************************************
*************************************************************************************
* Private memory declarations
*************************************************************************************
************************************************************************************/

/************************************************************************************
*************************************************************************************
* Public functions
*************************************************************************************
************************************************************************************/

/************************************************************************************
*************************************************************************************
* Private functions
*************************************************************************************
************************************************************************************/

/************************************************************************************
* Fast Eof interrupt routine for Ed.
*
* Interface assumptions:
*   Fast action setup
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   061003   TOJ       Created 
*   041004   JT        Separated from CCA  
*
************************************************************************************/
void DoFastEdEof(void)
{
  uint8_t energyLevel;

  RX_DISABLE_LNA;
  CODE_PROFILING_SETPIN_0;
  mPhyTxRxState=cIdle;
  gIsrFastAction = DummyFastIsr;

  energyLevel=GetEnergyLevel();

  PhyPlmeEdConfirm(energyLevel);
  gIsrMask = ~cCCA_IRQ;
}

/************************************************************************************
* Fast Eof interrupt routine for CCA
*
* Interface assumptions:
*   Fast action setup
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   061003   TOJ       Created 
*   041004   JT        Separated from ED  
*
************************************************************************************/
void DoFastCcaEof(void)
{
  RX_DISABLE_LNA;
  mPhyTxRxState=cIdle;

  if (IsAbelCcaBusy()){
    mpfPendingSetup = NULL; // Prevent Tx action setup when channel busy
    CODE_PROFILING_SETPIN_0;
  }
  if (mpfPendingSetup) {
    SetupPendingProtected();
  }

  gIsrFastAction = DummyFastIsr;
  PhyPlmeCcaConfirm(IsAbelCcaBusy());  // Pass message 
  gIsrMask = ~cCCA_IRQ;
}



/************************************************************************************
* In order to speed up EOF generation, it is possible to poll Abel GPIO's. This
* busy-waiting scheme is only suggested if timing does not allow use of interrupt!
*
* After calling this function, the TxEof routine is automatically exectuted
* (transparent to the system whether from poll or interrupt).
*
* Interface assumptions:
*   Fast action setup
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   061003   TOJ       Created 
*
************************************************************************************/
void DoFastTxEof(void)
{
  TX_DISABLE_PA;  
    // Enter here on expected EOF
    // Assert if not in tx state
  if (mPhyTxRxState != cBusy_Tx) return;  // EOF assumed to be generated due to action abort by sequential action
    // Set state to idle
  mPhyTxRxState=cIdle;
  gIsrFastAction = DummyFastIsr;

  if (mpfPendingSetup) {
    SetupPendingProtected();
  }
  else{
    CODE_PROFILING_SETPIN_0;
    if(IsCurrentActionAutoRx()){
      mpfPendingSetup = SetupImmediateRx; // Fall back to Rx if in Auto Rx mode
      SetupPendingProtected();
    }
  }

    // Send Data.confirm to MAC
  PhyPdDataConfirm();
  gIsrMask = ~cTX_DONE;
}


/************************************************************************************
* In order to speed up EOF generation, it is possible to poll Abel GPIO's. This
* busy-waiting scheme is only suggested if timing does not allow use of interrupt!
*
* These two functions serve as the fast actions on Eof. The functions are called 
* according to the status of the crc. (Set up in super fast action).
* In the busy wait scenario these functions are called directly from the polling routine. 
*
* Interface assumptions:
*   Fast action 
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   061003   TOJ       Created 
*   170204   JT        Updated 
*
************************************************************************************/
void DoFastRxEofCrcValid(void)
{
  gIsrAsyncTailFunction = DummyFastIsr;
  gIsrFastAction = DummyFastIsr;

  if(IsCurrentActionAutoRx()){
    gIsrMask = ~(cRX_DONE);
  }
  else {
    DisableEventTimeout();
    gIsrMask = ~(cRX_DONE | cTMR4_IRQ);
  }
  ConvertLinkQuality();
  PhyPdDataIndication();
}


void DoFastRxEofCrcInvalid(void)
{
  RestartRxOrTimeout();                               // Handle CRC failure the same way as when aborting Rx in Filter
  gIsrMask = ~(cRX_DONE | cTMR2_IRQ | cRX_RCVD_IRQ);  // cRX_RCVD_IRQ added in case function called from RxStreamIsr
}



#ifdef USE_INTERRUPT_RXEOF
/************************************************************************************
* In order to speed up EOF generation, it is possible to poll Abel GPIO's. This
* busy-waiting scheme is only suggested if timing does not allow use of interrupt!
*
* Since the Eof on Rx is delayed we need to setup a pending action ASAP in the Eof 
* interrupt. So this super-fast action is called. An interruptable fast action is 
* setup depending on the crc status.  
*
* Interface assumptions:
*   Superfast action setup with interrupts disabled.
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   240204   JT       Created 
*
************************************************************************************/
#ifndef I_AM_A_SNIFFER
void DoSuperFastRxEof(void)
{
  RX_DISABLE_LNA;
  if(IsAbelCrcOk()){
    if (gBeaconWithBadSrcDetected) {
      gBeaconWithBadSrcDetected = FALSE;
      if (gpPhyRxData->rxData[gpPhyRxData->headerLength + 1] & 0x40) { // chech PAN coordinator bit in beacon superframe spec. (bit 14)
        gPanIdConflict= TRUE;
        gIsrFastAction = DoFastRxEofCrcInvalid;
        return;
      }
    }
    if (mpfPendingSetup) {
      mpfPendingSetup();  // Does not disable or enable interrupts, which is desired here 
      mpfPendingSetup=NULL;
    }
    else{
      CODE_PROFILING_SETPIN_0;
      mPhyTxRxState = cIdle;
      if(IsCurrentActionAutoRx()){
        // Fall back to Rx if in Auto Rx mode
        mpfPendingSetup = SetupImmediateRx;
        mpfPendingSetup();  // Does not disable or enable interrupts, which is desired here 
        mpfPendingSetup=NULL;
      }
    }
    gIsrFastAction = DoFastRxEofCrcValid;
  }
  else{
    gIsrFastAction = DoFastRxEofCrcInvalid;
  }
}

#else
void DoSuperFastRxEof(void)
{
  RX_DISABLE_LNA;
  if(IsAbelCrcOk()){
     gpPhyRxData->timeStampMCU |= 0x80; // Set bit7 in this element if CRC is ok
   }
  else {
     gpPhyRxData->timeStampMCU &= ~0x80; // Clear bit7 in this element if CRC failed
  }
  gIsrFastAction = DoFastRxEofCrcInvalid;
}
#endif I_AM_A_SNIFFER

/************************************************************************************
* Tail function when using Eof interrupt
* Polls for packet completion and initialises super-fast action to occur at first 
* coming interrupt (assumed eof interrupt).
*
* Interface assumptions:
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   240204   JT       Created 
*
************************************************************************************/
void PollForRx(void)
{
  EXIT_IF_RXINDEX_NOT_REACHED((uint8_t)(gpPhyRxData->frameLength-2));
  gIsrAsyncTailFunction = DummyFastIsr;
  gIsrSuperFastAction=DoSuperFastRxEof;
}

#else /* USE_INTERRUPT_RXEOF */
/************************************************************************************
* Tail polling function when NOT using Eof interrupt
* Polls for packet completion using GPIO and sets up pending actions
*
* Interface assumptions:
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   240204   JT       Created 
*
************************************************************************************/
#ifndef I_AM_A_SNIFFER
void PollForRx(void)
{
  EXIT_IF_RXINDEX_NOT_REACHED((uint8_t)gpPhyRxData->frameLength-2);

  POLL_UNTIL_IDLE;

  RX_DISABLE_LNA;
  DISABLE_ALL_INTERRUPTS; // ensure nothing influences the delay after polling is done
  // Short delay (5 us) inserted to ensure Abel Sequencer stable writing Abel Ctrl register. Prevents GPIO1 held low through Tx.
  DELAY_5US // Empty Macro if using TxEOF irq
    
  if(IsAbelCrcOk()){
    if (gBeaconWithBadSrcDetected) {
      gBeaconWithBadSrcDetected = FALSE;
      if (gpPhyRxData->rxData[gpPhyRxData->headerLength + 1] & 0x40) { // chech PAN coordinator bit in beacon superframe spec. (bit 14)
        gPanIdConflict= TRUE;
        ENABLE_ALL_INTERRUPTS; 
        DoFastRxEofCrcInvalid();
        return;
      }
    }
    
    if (mpfPendingSetup) {
      SetupPendingProtected(); // disables and enables all interrupts
    }
    else{
      CODE_PROFILING_SETPIN_0;
      ENABLE_ALL_INTERRUPTS; 
      mPhyTxRxState = cIdle;
      if(IsCurrentActionAutoRx()){
        // Fall back to Rx if in Auto Rx mode
        mpfPendingSetup = SetupImmediateRx;
        SetupPendingProtected(); // disables and enables all interrupts
      }
    }
    DoFastRxEofCrcValid();
  }
  else{
    ENABLE_ALL_INTERRUPTS; 
    DoFastRxEofCrcInvalid();
  }
}

#else I_AM_A_SNIFFER
void PollForRx(void)
{
  EXIT_IF_RXINDEX_NOT_REACHED((uint8_t)gpPhyRxData->frameLength-2);

  POLL_UNTIL_IDLE;
  
  RX_DISABLE_LNA;
  DISABLE_ALL_INTERRUPTS; // ensure nothing influences the delay after polling is done
  // Short delay (5 us) inserted to ensure Abel Sequencer stable writing Abel Ctrl register. Prevents GPIO1 held low through Tx.
  DELAY_5US // Empty Macro if using TxEOF irq
  if(IsAbelCrcOk()){
    gpPhyRxData->timeStampMCU |= 0x80; // Set bit7 in this element if CRC is ok
  }
  else {
    gpPhyRxData->timeStampMCU &= ~0x80; // Clear bit7 in this element if CRC failed
  }
  ENABLE_ALL_INTERRUPTS; 
  DoFastRxEofCrcInvalid();
}
#endif I_AM_A_SNIFFER
#endif /* USE_INTERRUPT_RXEOF */


#ifndef USE_INTERRUPT_TXEOF
/************************************************************************************
* Tail polling function when NOT using Eof interrupt
* Polls for packet completion using GPIO and sets up pending actions
*
* Interface assumptions:
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   240204   JT       Created 
*
************************************************************************************/
void PollForTx(void)
{
  gIsrAsyncTailFunction = DummyFastIsr;
  POLL_UNTIL_IDLE;
  DoFastTxEof();
}
#endif /* USE_INTERRUPT_TXEOF */

#ifndef ALLOW_TX_ABORT_ON_TIMEOUT
/************************************************************************************
* Helper function for aborting Phy action upon timeout
*
* Interface assumptions:
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   190205   JT        Created 
*
************************************************************************************/
void PhyAbortAndSendTimeoutInd(void){
  PhyPlmeForceTrxOffRequest();
  PhyPlmeRxTimeoutIndication();
}
#endif // ALLOW_TX_ABORT_ON_TIMEOUT

/************************************************************************************
* If Timeout occurs, generate event to MAC layer
*
* Interface assumptions:
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   061003   TOJ       Created 
*
************************************************************************************/
void RxTimeout(void)
{
  RX_DISABLE_LNA;
  CODE_PROFILING_SETPIN_0;
    // We have received a timeout on a phy (Rx) action. On TMR4 (timeout) received, the PHY is forced idle
#ifndef ALLOW_TX_ABORT_ON_TIMEOUT
   if (mPhyTxRxState == cBusy_Tx) {
     gIsrFastAction = PhyAbortAndSendTimeoutInd;   // HACK: Timeout in TxAck must only abort Tx synchronously 
   }
   else{
     PhyAbortAndSendTimeoutInd();
   }
#else //ALLOW_TX_ABORT_ON_TIMEOUT
  PhyPlmeForceTrxOffRequest();
  PhyPlmeRxTimeoutIndication();
#endif //ALLOW_TX_ABORT_ON_TIMEOUT
}


/************************************************************************************
* If TMR2 expires, then it is a TC2' interrupt. If exiting doze mode, the TC2
* timer interrupt is also used, but the vector must point to ExitDoze.
*
* Sanity check: If TC2' occurs, and no action has been setup, then it is assumed that
* we are out of sync.
*
* Interface assumptions:
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   061003   TOJ       Created 
*
************************************************************************************/
void IsrTx2prime(void)
{
  CODE_PROFILING_CLRPIN_0

    // If gIsrPendingFastAction is NULL, TC2' expired, before new command was programmed
  if (NULL==gIsrPendingFastAction){
    PhyPlmeSyncLossIndication();
    return;
  }

  gIsrFastAction=gIsrPendingFastAction;
  gIsrPendingFastAction=NULL; // Clear pending setup

  PhyPlmeB2BIndication(); // Indicate that new TC2' is ready for setup
  if (gIsrFastAction==IrqStreamingRxFirst)
    InitRxPointers();
}

/************************************************************************************
*************************************************************************************
* Module debug stuff
*************************************************************************************
************************************************************************************/




/************************************************************************************
*************************************************************************************
* Level 1 block comment
*************************************************************************************
************************************************************************************/

//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
// Level 2 block comment
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------

/* Level 3 block comment */




// Delimiters

/***********************************************************************************/

//-----------------------------------------------------------------------------------
