/************************************************************************************
* Implements SetTrxStateRequest Primitive.
*
* 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
*************************************************************************************
************************************************************************************/

/************************************************************************************
*************************************************************************************
* Private prototypes
*************************************************************************************
************************************************************************************/
/************************************************************************************
*************************************************************************************
* Public type definitions
*************************************************************************************
************************************************************************************/
/************************************************************************************
*************************************************************************************
* Public memory declarations
*************************************************************************************
************************************************************************************/

/************************************************************************************
*************************************************************************************
* Private memory declarations
*************************************************************************************
************************************************************************************/
volatile bool_t mClockReadFlag;

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

void LowLevelReadClockSync(zbClock24_t *pRetClk)
{
  /* Must be called from a place protected against Abel interrupts. */
  ABEL_READ_INT(ABEL_CURR_TIME_LSB_REG,  *pRetClk); // HACK: Always clear latch if set by async call. 
  ABEL_READ_BURST_L_INT(ABEL_CURR_TIME_MSB_REG, (uint16_t*)pRetClk);
  mClockReadFlag=TRUE;
}

#pragma DISABLE_WARNING(RecursiveFunctionCall_c)
void LowLevelReadClockAsync(zbClock24_t *pRetClk)
{
  /* May be called from anywhere. But is slower than the one above*/
  mClockReadFlag=FALSE;
  ABEL_READ_BURST_L(ABEL_CURR_TIME_MSB_REG, (uint16_t*)pRetClk);

  if(mClockReadFlag)
    LowLevelReadClockAsync(pRetClk);
  mClockReadFlag=TRUE;
}
#pragma RESTORE_WARNING(RecursiveFunctionCall_c)

void InitRxFastAction(void){
    // Init RxStream function pointer
  gIsrFastAction = IrqStreamingRxFirst;  
}

void InitRxPointers(void)
{
  // Init rx buffer pointer and index
  gpPhyPacketHead = gpPhyRxData->rxData;
  gPhyMacDataRxIndex = gRxDataIndexOffset_c;  // Do this to comply with structure index. If removed, update filter index values!!!!!!

#ifdef RX_TIMING_MEASUREMENT
  gPhyMacDataRxIndex=0x15;
#endif
}



/************************************************************************************
* Restart broken Rx sequence.
*
* Interface assumptions:
*
* THIS FUNCTION MAY ONLY BE CALLED FROM THE RXSTREAM INTERRUPT OR FROM macRxFilterProcess
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   071003   JT        Created
*
************************************************************************************/
void ReStartRx(void)
{
    // Setup Rx action immediately 
  mpfPendingSetup = SetupImmediateRx; 
  SetupPendingProtected(); // Not really pending at this point, but this saves code! (clears mpfPendingSetup)
  gIsrAsyncTailFunction = DummyFastIsr;

#ifdef I_AM_A_SNIFFER
  if (gpRxDataToBeSentOnHostInterface != NULL) GREEN_LED_TOGGLE; // We have not emptied the previous packets (mainloop to slow)
  if (gpPhyRxData == &gRxDataBuffer) {
    gpPhyRxData = &gRxDataBuffer2; // Sets the pointer to the other buffer, so that we can empty the first buffer from the mainloop
    gpRxDataToBeSentOnHostInterface = &gRxDataBuffer; 
  }
  else {
    gpPhyRxData = &gRxDataBuffer; // ...and the other way around
    gpRxDataToBeSentOnHostInterface = &gRxDataBuffer2;
  }
#endif /*I_AM_A_SNIFFER*/
  
  InitRxFastAction();
  InitRxPointers();

#ifdef USE_INTERRUPT_RXEOF  // 
    // Clear Abel Status Register   
    // and handle if RxTimeouts occured just now
    // NOTE: This will only be necessary when using the EOF interrupt for Rx. 
    // NOTE: Removed when using GPIO1 polling because of known HW issue: 
    //       Reading the status register while interrupts occur eliminates the interrupt
  {
    uint16_t retReg;
    CLEAR_IRQ_STATUSREG(retReg);
    if (retReg & cTMR4_IRQ) RxTimeout();  // timeout occured just now
  }
#else
    // HACK: When Using GPIO polling it has been observed that an Rx Stream Irq has occurred in rare circumstances on CRC invalid
    // To ensure this is always cleared perform a dummy read of the data register
  DUMMY_DATA_READ;
#endif /*USE_INTERRUPT_RXEOF*/
 
  CLRTIMINGPIN_1
}


/************************************************************************************
* Set event trigger. Used for timed actions.
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   170903   TOJ,JT    Created
*
************************************************************************************/
void PhySyncSetEventTrigger(zbClock16_t startTime)
{
  startTime = startTime - gAbelWarmupTimeSym_c;
  ABEL_WRITE_INT(ABEL_TMR2_PRIME_REG, startTime); // Set new T2' timer trigger
}

/************************************************************************************
* Set event timeout. Used for timed actions.
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   170903   TOJ,JT    Created
*
************************************************************************************/
void PhySyncSetEventTimeout(zbClock24_t* pEndTime )
{
  ABEL_WRITE_BURST_L_INT(ABEL_TMR4_HI_REG, (uint16_t*)pEndTime); // Set new TC4 timeout. This will arm the timeout!
}

/************************************************************************************
* Kill event timeout
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   170903   TOJ,JT    Created
*
************************************************************************************/
void DisableEventTimeout(void)
{
    // Disabling the timer prevents future interrupts, and clears pending interrupts in Abel.
    // Both the irq level pin and reg 0x24 (bit3) are cleared
    // In case a pending timer interrupt is cleared we must remember to "ack" the irq in the MCU 
  ABEL_WRITE(ABEL_TMR4_HI_REG, 0x8000);
  HANDSHAKE_IRQ;
}

//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
// Actions executed on pending callback
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------

#if gAspJapanTelecCapability_d
// Used for TELEC callbacks
void SetupRxAntennaSwitch(void)
{
  RX_ANTENNE_ENABLED;
}
void SetupTxAntennaSwitch(void)
{
  TX_ANTENNE_ENABLED;
}
#endif


#ifndef DO_NOT_TOGGLE_SYNCH_THRESHOLD
// HACK: Set threshold to normal for Rx
void SetCorrThresholdNormal(){
  ABEL_WRITE_INT(ABEL_reg38, 0x0008); // Set correlation threshold to normal value
}

// HACK: CCA-Rx issue. Set threshold to max value for Ed and Cca to prevent correlation
void SetCorrThresholdHigh(){
  ABEL_WRITE_INT(ABEL_reg38, 0x03FF); // Set correlation threshold to high value
}
#else //DO_NOT_TOGGLE_SYNCH_THRESHOLD
void SetCorrThresholdNormal(){
}
void SetCorrThresholdHigh(){
}
#endif //DO_NOT_TOGGLE_SYNCH_THRESHOLD


// Helper function for action setup (used to save code, not used with tx due to tight critical path)
void SetupAction(uint16_t command)
{
  RxTxDisable                  // RxTxEnable = 0;
  ABEL_WRITE_INT_FAST(ABEL_CONTROL_REG, command);
  RxTxEnable                   // RxTxEnable = 1;
}

void SetupPendingTx(void)
{
  uint16_t command = cTX_STRM | cTX_SENT_MASK | SEQ_T | cTMR_TRIG_EN;
  SetupAction(command);
  TX_ANTENNE_ENABLED  
  mPhyTxRxState=cBusy_Tx;
  gIsrPendingFastAction = IrqStreamingTx; 
}

void SetupPendingRx(void)
{
  uint16_t command = cRX_RCV_ALL | cRX_STRM | cRX_RCVD_MASK | SEQ_RT | cRX_AGC | cTMR_TRIG_EN;
  SetupAction(command);
  RX_ANTENNE_ENABLED
  mPhyTxRxState=cBusy_Rx;
  gIsrPendingFastAction = IrqStreamingRxFirst; 
}

void SetupImmediateRx(void)
{
  uint16_t command = cRX_RCV_ALL | cRX_STRM | cRX_RCVD_MASK | SEQ_RT | cRX_AGC;
  SetupAction(command);
  RX_ANTENNE_ENABLED
  mPhyTxRxState=cBusy_Rx;
}

void SetupPendingTtNop(void)
{
  uint16_t command=SEQ_NOP | cTMR_TRIG_EN;
  mPhyTxRxState=cBusy_Wait;
  SetupAction(command);
  gIsrPendingFastAction = DummyFastIsr;
}

void SetupPendingNop(void)
{
  uint16_t command=SEQ_NOP;

  RX_DISABLE_LNA;
  TX_DISABLE_PA;
  mPhyTxRxState=cIdle;
  SetupAction(command);
}

void SetupPendingCca(void)
{
  uint16_t command = cCCA_MASK | cCCA_MODE0 | SEQ_C | cTMR_TRIG_EN;
  SetupAction(command);
  RX_ANTENNE_ENABLED
  mPhyTxRxState = cRxCCA;
  gIsrPendingFastAction=DoFastCcaEof;
}

void SetupPendingEd(void)
{
  uint16_t command = cCCA_MASK | cCCA_ED | SEQ_C | cTMR_TRIG_EN;
  SetupAction(command);
  RX_ANTENNE_ENABLED
  mPhyTxRxState = cRxED;
  gIsrPendingFastAction=DoFastEdEof;
}

void SetupPendingProtected(void){
  DISABLE_ALL_INTERRUPTS  
  mpfPendingSetup();
  mpfPendingSetup=NULL;
  CODE_PROFILING_CLRPIN_1
  ENABLE_ALL_INTERRUPTS
}


/************************************************************************************
* Wait request 
* Setup wait as pending action if Phy is busy. Enter wait otherwise 
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   191203   JT        Created
*
************************************************************************************/
void PhyPlmeWaitRequest(void)
{
  mpfPendingSetup = SetupPendingTtNop; 
  SetupPendingProtected();
}


/************************************************************************************
* Force Trx state in PHY layer to idle
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   010903   TOJ       Created
*   050903   JT        Features added
*   081004   JT        Separated from SetTrxStateRequest
*
************************************************************************************/
void PhyPlmeForceTrxOffRequest(void){
    mpfPendingSetup = SetupPendingNop;
    SetupPendingProtected();

    gIsrPendingFastAction=NULL;
    
      // Reset pointers and Timeout
    gIsrSuperFastAction = NULL;
    gIsrFastAction = DummyFastIsr;
    gIsrAsyncTailFunction = DummyFastIsr;
    DisableEventTimeout();
      // Clear ABEL status register... we are now IDLE!!!!!!!!
    {uint16_t retReg; CLEAR_IRQ_STATUSREG(retReg);}
}

/************************************************************************************
* Set state in PHY layer to Rx
* Setup Rx as pending action if Phy is busy. Enter Rx otherwise 
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   010903   TOJ       Created
*   050903   JT        Features added
*   081004   JT        Separated from SetTrxStateRequest
*
************************************************************************************/
void PhyPlmeRxRequest(void){
    mpfPendingSetup = SetupPendingRx;
    if (mPhyTxRxState==cIdle){  // Is Abel running, so that command must be pended?
        // Setup action immediately 
      SetupPendingProtected(); // Not really pending at this point, but this saves code! (clears mpfPendingSetup)
    }
}

/************************************************************************************
* Set state in PHY layer to Tx
* Setup Tx as pending action if Phy is busy. Enter Tx otherwise 
*
* Interface assumptions:
*
*
* Return value:
*   NONE
*
* Revision history:
*
*    Date    Author    Comments
*   ------   ------    --------
*   010903   TOJ       Created
*   050903   JT        Features added
*   081004   JT        Separated from SetTrxStateRequest
*
************************************************************************************/
void PhyPlmeTxRequest(void){
    mpfPendingSetup = SetupPendingTx;
    if (mPhyTxRxState==cIdle){  // Is Abel running, so that command must be pended?
        // Setup action immediately 
      SetupPendingProtected(); // Not really pending at this point, but this saves code! (clears mpfPendingSetup)
    }
}

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

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




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

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

/* Level 3 block comment */




// Delimiters

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

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