NXP / fsl_phy_mcr20a

Fork of fsl_phy_mcr20a by Freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PhyStateMachine.c Source File

PhyStateMachine.c

Go to the documentation of this file.
00001 /*!
00002 * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003 * All rights reserved.
00004 *
00005 * \file PhyStateMachine.c
00006 *
00007 * Redistribution and use in source and binary forms, with or without modification,
00008 * are permitted provided that the following conditions are met:
00009 *
00010 * o Redistributions of source code must retain the above copyright notice, this list
00011 *   of conditions and the following disclaimer.
00012 *
00013 * o Redistributions in binary form must reproduce the above copyright notice, this
00014 *   list of conditions and the following disclaimer in the documentation and/or
00015 *   other materials provided with the distribution.
00016 *
00017 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
00018 *   contributors may be used to endorse or promote products derived from this
00019 *   software without specific prior written permission.
00020 *
00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00022 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00025 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00028 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031 */
00032 
00033 
00034 #ifdef gSrcTask_d
00035 #undef gSrcTask_d
00036 #endif
00037 
00038 #define gSrcTask_d PHY
00039 
00040 
00041 /************************************************************************************
00042 *************************************************************************************
00043 * Include
00044 *************************************************************************************
00045 ************************************************************************************/
00046 #include "EmbeddedTypes.h "
00047 
00048 //#include "fsl_os_abstraction.h"
00049 
00050 #include "PhyInterface.h "
00051 #include "Phy.h "
00052 
00053 
00054 #include "MemManager.h "
00055 #include "FunctionLib.h "
00056 #if 0
00057 #include "Messaging.h"
00058 #include "Panic.h"
00059 #endif
00060 
00061 #include "MCR20Drv.h "
00062 #include "MCR20Reg.h"
00063 
00064 #include "AspInterface.h"
00065 #include "MpmInterface.h "
00066 
00067 /************************************************************************************
00068 *************************************************************************************
00069 * Public macros
00070 *************************************************************************************
00071 ************************************************************************************/
00072 #define mPhyMaxIdleRxDuration_c      (0xF00000) /* [sym] */
00073 
00074 #define ProtectFromXcvrInterrupt()   ProtectFromMCR20Interrupt()
00075 #define UnprotectFromXcvrInterrupt() UnprotectFromMCR20Interrupt()
00076 
00077 /************************************************************************************
00078 *************************************************************************************
00079 * Private type definitions
00080 *************************************************************************************
00081 ************************************************************************************/
00082 
00083 /************************************************************************************
00084 *************************************************************************************
00085 * Private prototypes
00086 *************************************************************************************
00087 ************************************************************************************/
00088 static void Phy24Task(Phy_PhyLocalStruct_t *pPhyData);
00089 
00090 static phyStatus_t Phy_HandlePdDataReq( Phy_PhyLocalStruct_t *pPhyData, macToPdDataMessage_t * pMsg );
00091 
00092 static void Phy_EnterIdle( Phy_PhyLocalStruct_t *pPhyData );
00093 
00094 static void PLME_SendMessage(Phy_PhyLocalStruct_t *pPhyData, phyMessageId_t msgType);
00095 
00096 static void PD_SendMessage(Phy_PhyLocalStruct_t *pPhyData, phyMessageId_t msgType);
00097 
00098 
00099 static void MSG_InitQueue(macPhyInputQueue_t * pMacPhyQueue);
00100 static void MSG_Queue(macPhyInputQueue_t * pMacPhyQueue, void * pMsgIn);
00101 static void MSG_QueueHead(macPhyInputQueue_t * pMacPhyQueue, void * pMsgIn);
00102 static bool_t MSG_Pending(macPhyInputQueue_t * pMacPhyQueue);
00103 static void * MSG_DeQueue(macPhyInputQueue_t * pMacPhyQueue);
00104 
00105 /************************************************************************************
00106 *************************************************************************************
00107 * Private memory declarations
00108 *************************************************************************************
00109 ************************************************************************************/
00110 Phy_PhyLocalStruct_t phyLocal[gPhyInstancesCnt_c];
00111 extern volatile uint32_t mPhySeqTimeout;
00112 
00113 /************************************************************************************
00114 *************************************************************************************
00115 * Public functions
00116 *************************************************************************************
00117 ************************************************************************************/
00118 
00119 /*! *********************************************************************************
00120 * \brief  This function creates the PHY task
00121 *
00122 ********************************************************************************** */
00123 void Phy_Init(void)
00124 {
00125     uint32_t i;
00126 
00127     PhyHwInit();
00128     ASP_Init( 0, gAspInterfaceId );
00129     MPM_Init();
00130 
00131     for( i=0; i<gPhyInstancesCnt_c; i++ )
00132     {
00133         phyLocal[i].flags = gPhyFlagDeferTx_c;
00134         phyLocal[i].rxParams.pRxData = NULL;
00135 
00136         /* Prepare input queues.*/
00137         MSG_InitQueue( &phyLocal[i].macPhyInputQueue );
00138     }
00139 
00140     PhyIsrPassRxParams( NULL );
00141     PhyPlmeSetPwrState( gPhyDefaultIdlePwrMode_c );
00142 }
00143 
00144 /*! *********************************************************************************
00145 * \brief  This function binds a MAC instance to a PHY instance
00146 *
00147 * \param[in]  instanceId The instance of the MAC
00148 *
00149 * \return  The instance of the PHY.
00150 *
00151 ********************************************************************************** */
00152 instanceId_t BindToPHY( instanceId_t macInstance )
00153 {
00154     return 0;
00155 }
00156 
00157 /*! *********************************************************************************
00158 * \brief  This function registers the MAC PD and PLME SAP handlers
00159 *
00160 * \param[in]  pPD_MAC_SapHandler   Pointer to the MAC PD handler function
00161 * \param[in]  pPLME_MAC_SapHandler Pointer to the MAC PLME handler function
00162 * \param[in]  instanceId           The instance of the PHY
00163 *
00164 * \return  The status of the operation.
00165 *
00166 ********************************************************************************** */
00167 void Phy_RegisterSapHandlers( PD_MAC_SapHandler_t pPD_MAC_SapHandler,
00168                               PLME_MAC_SapHandler_t pPLME_MAC_SapHandler,
00169                               instanceId_t instanceId )
00170 {
00171     phyLocal[instanceId].PD_MAC_SapHandler = pPD_MAC_SapHandler;
00172     phyLocal[instanceId].PLME_MAC_SapHandler = pPLME_MAC_SapHandler;
00173 }
00174 
00175 /*! *********************************************************************************
00176 * \brief  This function represents the PHY's task
00177 *
00178 * \param[in]  taskParam The instance of the PHY
00179 *
00180 ********************************************************************************** */
00181 static void Phy24Task(Phy_PhyLocalStruct_t *pPhyStruct)
00182 {
00183     uint8_t state;
00184     phyMessageHeader_t * pMsgIn;
00185     phyStatus_t status = gPhySuccess_c;
00186 
00187     ProtectFromXcvrInterrupt();
00188     state = PhyGetSeqState();
00189 
00190     /* Handling messages from upper layer */
00191     while( MSG_Pending(&pPhyStruct->macPhyInputQueue) )
00192     {
00193         /* PHY doesn't free dynamic alocated messages! */
00194         pMsgIn = MSG_DeQueue( &pPhyStruct->macPhyInputQueue );
00195         pPhyStruct->currentMacInstance = pMsgIn->macInstance;
00196 
00197         if( gRX_c == state )
00198         {
00199             if( (pPhyStruct->flags & gPhyFlagDeferTx_c) && (pMsgIn->msgType == gPdDataReq_c) )
00200             {
00201                 macToPdDataMessage_t *pPD = (macToPdDataMessage_t*)pMsgIn;
00202                 uint8_t phyReg = MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F;
00203                 /* Check for an Rx in progress, and if the packet can be defered.
00204                    Packet cannot be defered */
00205                 if( (pPD->msgData.dataReq.CCABeforeTx != gPhyNoCCABeforeTx_c) &&
00206                     (pPD->msgData.dataReq.startTime == gPhySeqStartAsap_c) &&
00207                     (pPD->msgData.dataReq.slottedTx == gPhyUnslottedMode_c) &&
00208                     (phyReg <= 0x06 || phyReg == 0x15 || phyReg == 0x16) )
00209                 {
00210                     MSG_QueueHead( &pPhyStruct->macPhyInputQueue, pMsgIn );
00211                     UnprotectFromXcvrInterrupt();
00212                     return;
00213                 }
00214             }
00215 
00216 //            if( pPhyStruct->flags & gPhyFlagIdleRx_c )
00217             {
00218                 PhyPlmeForceTrxOffRequest();
00219                 state = gIdle_c;
00220                 pPhyStruct->flags &= ~(gPhyFlagIdleRx_c);
00221             }
00222         }
00223 
00224         if( gIdle_c != state )
00225         {
00226             /* try again later */
00227             MSG_QueueHead( &pPhyStruct->macPhyInputQueue, pMsgIn );
00228             UnprotectFromXcvrInterrupt();
00229             return;
00230         }
00231 
00232 #if gMpmIncluded_d
00233         if( status == gPhySuccess_c )
00234         {
00235             status = MPM_PrepareForTx( pMsgIn->macInstance );
00236         }
00237 #endif
00238 
00239         if( status == gPhySuccess_c )
00240         {
00241             pPhyStruct->flags &= ~(gPhyFlagIdleRx_c);
00242 
00243             switch( pMsgIn->msgType )
00244             {
00245             case gPdDataReq_c:
00246                 status = Phy_HandlePdDataReq( pPhyStruct, (macToPdDataMessage_t *)pMsgIn );
00247                 break;
00248             case gPlmeCcaReq_c:
00249                 status = PhyPlmeCcaEdRequest(gPhyCCAMode1_c, gPhyContCcaDisabled);
00250                 break;
00251             case gPlmeEdReq_c:
00252                 status = PhyPlmeCcaEdRequest(gPhyEnergyDetectMode_c, gPhyContCcaDisabled);
00253                 break;
00254             default:
00255                 status = gPhyInvalidPrimitive_c;
00256             }
00257         }
00258 
00259         /* Check status */
00260         if( gPhySuccess_c == status )
00261         {
00262             UnprotectFromXcvrInterrupt();
00263             return;
00264         }
00265         else
00266         {
00267             switch( pMsgIn->msgType )
00268             {
00269             case gPdDataReq_c:
00270                 if( ((macToPdDataMessage_t*)pMsgIn)->msgData.dataReq.CCABeforeTx == gPhyNoCCABeforeTx_c )
00271                 {
00272                     PD_SendMessage(pPhyStruct, gPdDataCnf_c);
00273                     break;
00274                 }
00275                 /* Fallthorough */
00276             case gPlmeCcaReq_c:
00277                 pPhyStruct->channelParams.channelStatus = gPhyChannelBusy_c;
00278                 PLME_SendMessage(pPhyStruct, gPlmeCcaCnf_c);
00279                 break;
00280             case gPlmeEdReq_c:
00281                 pPhyStruct->channelParams.energyLeveldB = 0;
00282                 PLME_SendMessage(pPhyStruct, gPlmeEdCnf_c);
00283                 break;
00284             default:
00285                 PLME_SendMessage(pPhyStruct, gPlmeTimeoutInd_c);
00286             }
00287         }
00288     }/* while( MSG_Pending(&pPhyStruct->macPhyInputQueue) ) */
00289 
00290     UnprotectFromXcvrInterrupt();
00291 
00292     /* Check if PHY can enter Idle state */
00293     if( gIdle_c == state )
00294     {
00295         Phy_EnterIdle( pPhyStruct );
00296     }
00297 }
00298 
00299 /*! *********************************************************************************
00300 * \brief  This is the PD SAP message handler
00301 *
00302 * \param[in]  pMsg Pointer to the PD request message
00303 * \param[in]  instanceId The instance of the PHY
00304 *
00305 * \return  The status of the operation.
00306 *
00307 ********************************************************************************** */
00308 phyStatus_t MAC_PD_SapHandler(macToPdDataMessage_t *pMsg, instanceId_t phyInstance)
00309 {
00310     phyStatus_t result = gPhySuccess_c;
00311     uint8_t baseIndex = 0;
00312 
00313     if( NULL == pMsg )
00314     {
00315         return gPhyInvalidParameter_c;
00316     }
00317 
00318 #if gMpmIncluded_d
00319     if( pMsg->msgType == gPdIndQueueInsertReq_c || pMsg->msgType == gPdIndQueueRemoveReq_c )
00320     {
00321         baseIndex = MPM_GetRegSet( MPM_GetPanIndex( pMsg->macInstance ) ) *
00322                    (gPhyIndirectQueueSize_c/gMpmPhyPanRegSets_c);
00323     }
00324 #endif
00325 
00326     switch( pMsg->msgType )
00327     {
00328     case gPdIndQueueInsertReq_c:
00329         result = PhyPp_IndirectQueueInsert(baseIndex + pMsg->msgData.indQueueInsertReq.index,
00330                                            pMsg->msgData.indQueueInsertReq.checksum,
00331                                            phyInstance);
00332         break;
00333 
00334     case gPdIndQueueRemoveReq_c:
00335         result = PhyPp_RemoveFromIndirect(baseIndex + pMsg->msgData.indQueueRemoveReq.index,
00336                                           phyInstance);
00337         break;
00338 
00339     case gPdDataReq_c:
00340         MSG_Queue(&phyLocal[phyInstance].macPhyInputQueue, pMsg);
00341         Phy24Task( &phyLocal[phyInstance] );
00342         break;
00343 
00344     default:
00345         result = gPhyInvalidPrimitive_c;
00346     }
00347 
00348     return result;
00349 }
00350 
00351 /*! *********************************************************************************
00352 * \brief  This is the PLME SAP message handler
00353 *
00354 * \param[in]  pMsg Pointer to the PLME request message
00355 * \param[in]  instanceId The instance of the PHY
00356 *
00357 * \return  phyStatus_t The status of the operation.
00358 *
00359 ********************************************************************************** */
00360 phyStatus_t MAC_PLME_SapHandler(macToPlmeMessage_t * pMsg, instanceId_t phyInstance)
00361 {
00362     Phy_PhyLocalStruct_t *pPhyStruct = &phyLocal[phyInstance];
00363     uint8_t phyRegSet = 0;
00364 #if gMpmIncluded_d
00365     phyStatus_t result;
00366     int32_t panIdx = MPM_GetPanIndex( pMsg->macInstance );
00367 
00368     phyRegSet = MPM_GetRegSet( panIdx );
00369 #endif
00370 
00371     if( NULL == pMsg )
00372     {
00373         return gPhyInvalidParameter_c;
00374     }
00375 
00376     switch( pMsg->msgType )
00377     {
00378     case gPlmeEdReq_c:
00379     case gPlmeCcaReq_c:
00380         MSG_Queue(&phyLocal[phyInstance].macPhyInputQueue, pMsg);
00381         Phy24Task( &phyLocal[phyInstance] );
00382         break;
00383 
00384     case gPlmeSetReq_c:
00385 #if gMpmIncluded_d
00386         result = MPM_SetPIB(pMsg->msgData.setReq.PibAttribute,
00387                             &pMsg->msgData.setReq.PibAttributeValue,
00388                             panIdx );
00389         if( !MPM_isPanActive(panIdx) )
00390         {
00391             return result;
00392         }
00393 #endif
00394         return PhyPlmeSetPIBRequest(pMsg->msgData.setReq.PibAttribute, pMsg->msgData.setReq.PibAttributeValue, phyRegSet, phyInstance);
00395 
00396     case gPlmeGetReq_c:
00397 #if gMpmIncluded_d
00398         if( gPhySuccess_c == MPM_GetPIB(pMsg->msgData.getReq.PibAttribute, pMsg->msgData.getReq.pPibAttributeValue, panIdx) )
00399         {
00400             break;
00401         }
00402 #endif
00403         return PhyPlmeGetPIBRequest( pMsg->msgData.getReq.PibAttribute, pMsg->msgData.getReq.pPibAttributeValue, phyRegSet, phyInstance);
00404 
00405     case gPlmeSetTRxStateReq_c:
00406         if(gPhySetRxOn_c == pMsg->msgData.setTRxStateReq.state)
00407         {
00408             if( PhyIsIdleRx(phyInstance) )
00409             {
00410                 PhyPlmeForceTrxOffRequest();
00411             }
00412             else if( gIdle_c != PhyGetSeqState() )
00413             {
00414                 return gPhyBusy_c;
00415             }
00416 #if gMpmIncluded_d
00417             /* If another PAN has the RxOnWhenIdle PIB set, enable the DualPan Auto mode */
00418             if( gPhySuccess_c != MPM_PrepareForRx( pMsg->macInstance ) )
00419                 return gPhyBusy_c;
00420 #endif
00421             pPhyStruct->flags &= ~(gPhyFlagIdleRx_c);
00422             Phy_SetSequenceTiming(pMsg->msgData.setTRxStateReq.startTime,
00423                                   pMsg->msgData.setTRxStateReq.rxDuration);
00424 
00425             return PhyPlmeRxRequest(pMsg->msgData.setTRxStateReq.slottedMode, (phyRxParams_t *) &pPhyStruct->rxParams);
00426         }
00427         else if (gPhyForceTRxOff_c == pMsg->msgData.setTRxStateReq.state)
00428         {
00429 #if gMpmIncluded_d
00430             if( !MPM_isPanActive(panIdx) )
00431                 return gPhySuccess_c;
00432 #endif
00433             pPhyStruct->flags &= ~(gPhyFlagIdleRx_c);
00434             PhyPlmeForceTrxOffRequest();
00435         }
00436         break;
00437 
00438     default:
00439         return gPhyInvalidPrimitive_c;
00440     }
00441 
00442     return gPhySuccess_c;
00443 }
00444 
00445 /*! *********************************************************************************
00446 * \brief  This function programs a new TX sequence
00447 *
00448 * \param[in]  pMsg Pointer to the PD request message
00449 * \param[in]  pPhyData pointer to PHY data
00450 *
00451 * \return  The status of the operation.
00452 *
00453 ********************************************************************************** */
00454 static phyStatus_t Phy_HandlePdDataReq( Phy_PhyLocalStruct_t *pPhyData, macToPdDataMessage_t * pMsg )
00455 {
00456   phyStatus_t status = gPhySuccess_c;
00457   uint32_t time;
00458 
00459   if( NULL == pMsg->msgData.dataReq.pPsdu )
00460   {
00461     return gPhyInvalidParameter_c;
00462   }
00463 
00464   ProtectFromXcvrInterrupt();
00465 
00466   if( pMsg->msgData.dataReq.startTime != gPhySeqStartAsap_c )
00467   {
00468       PhyTimeSetEventTrigger( (uint16_t) pMsg->msgData.dataReq.startTime );
00469   }
00470 
00471   status = PhyPdDataRequest(&pMsg->msgData.dataReq , &pPhyData->rxParams, &pPhyData->txParams);
00472 
00473   if( pMsg->msgData.dataReq.txDuration != gPhySeqStartAsap_c )
00474   {
00475       OSA_EnterCritical(kCriticalDisableInt);
00476       PhyTimeReadClock( &time );
00477       time += pMsg->msgData.dataReq.txDuration;
00478       /* Compensate PHY overhead, including WU time */
00479       time += 54;
00480       PhyTimeSetEventTimeout( &time );
00481       OSA_ExitCritical(kCriticalDisableInt);
00482   }
00483 
00484   UnprotectFromXcvrInterrupt();
00485 
00486   if( gPhySuccess_c != status )
00487   {
00488     PhyTimeDisableEventTrigger();
00489     PhyTimeDisableEventTimeout();
00490   }
00491 
00492   return status;
00493 }
00494 
00495 /*! *********************************************************************************
00496 * \brief  This function sets the start time and the timeout value for a sequence.
00497 *
00498 * \param[in]  startTime The absolute start time for the sequence.
00499 *             If startTime is gPhySeqStartAsap_c, the start timer is disabled.
00500 * \param[in]  seqDuration The duration of the sequence.
00501 *             If seqDuration is 0xFFFFFFFF, the timeout is disabled.
00502 *
00503 ********************************************************************************** */
00504 void Phy_SetSequenceTiming(uint32_t startTime, uint32_t seqDuration)
00505 {
00506     uint32_t endTime;
00507 
00508     OSA_EnterCritical(kCriticalDisableInt);
00509 
00510     if( gPhySeqStartAsap_c == startTime )
00511     {
00512         PhyTimeReadClock( &endTime );
00513     }
00514     else
00515     {
00516         PhyTimeSetEventTrigger( (uint16_t) startTime );
00517         endTime = startTime & gPhyTimeMask_c;
00518     }
00519 
00520     if( 0xFFFFFFFF != seqDuration )
00521     {
00522         endTime += seqDuration;
00523         endTime = endTime & gPhyTimeMask_c;
00524 
00525         PhyTimeSetEventTimeout( &(endTime) );
00526     }
00527 
00528     OSA_ExitCritical(kCriticalDisableInt);
00529 }
00530 
00531 /*! *********************************************************************************
00532 * \brief  This function starts the IdleRX if the PhyRxOnWhenIdle PIB is set
00533 *
00534 * \param[in]  pPhyData pointer to PHY data
00535 *
00536 ********************************************************************************** */
00537 void Phy_EnterIdle( Phy_PhyLocalStruct_t *pPhyData )
00538 {
00539     if( (pPhyData->flags & gPhyFlagRxOnWhenIdle_c)
00540 #if gMpmIncluded_d
00541        /* Prepare the Active PAN/PANs */
00542        && (gPhySuccess_c == MPM_PrepareForRx(gInvalidInstanceId_c))
00543 #endif
00544       )
00545     {
00546         pPhyData->flags |= gPhyFlagIdleRx_c;
00547         Phy_SetSequenceTiming( gPhySeqStartAsap_c, mPhyMaxIdleRxDuration_c );
00548         (void)PhyPlmeRxRequest( gPhyUnslottedMode_c, (phyRxParams_t*)&pPhyData->rxParams );
00549     }
00550     else
00551     {
00552         pPhyData->flags &= ~(gPhyFlagIdleRx_c);
00553     }
00554 }
00555 
00556 /*! *********************************************************************************
00557 * \brief  This function sets the value of the maxFrameWaitTime PIB
00558 *
00559 * \param[in]  instanceId The instance of the PHY
00560 * \param[in]  time The maxFrameWaitTime value
00561 *
00562 ********************************************************************************** */
00563 void PhyPlmeSetFrameWaitTime( uint32_t time, instanceId_t instanceId )
00564 {
00565     phyLocal[instanceId].maxFrameWaitTime = time;
00566 }
00567 
00568 /*! *********************************************************************************
00569 * \brief  This function sets the state of the PhyRxOnWhenIdle PIB
00570 *
00571 * \param[in]  instanceId The instance of the PHY
00572 * \param[in]  state The PhyRxOnWhenIdle value
00573 *
00574 ********************************************************************************** */
00575 void PhyPlmeSetRxOnWhenIdle( bool_t state, instanceId_t instanceId )
00576 {
00577     uint8_t radioState = PhyGetSeqState();
00578 #if gMpmIncluded_d
00579     /* Check if at least one PAN has RxOnWhenIdle set */
00580     if( FALSE == state )
00581     {
00582         uint32_t i;
00583 
00584         for( i=0; i<gMpmMaxPANs_c; i++ )
00585         {
00586             MPM_GetPIB( gPhyPibRxOnWhenIdle, &state, i );
00587             if( state )
00588                 break;
00589         }
00590     }
00591 #endif
00592     if( state )
00593     {
00594         phyLocal[instanceId].flags |= gPhyFlagRxOnWhenIdle_c;
00595         if( radioState == gIdle_c)
00596         {
00597             Phy_EnterIdle( &phyLocal[instanceId] );
00598         }
00599 #if gMpmIncluded_d
00600         else if( (radioState == gRX_c) && (phyLocal[instanceId].flags & gPhyFlagIdleRx_c) )
00601         {
00602             PhyPlmeForceTrxOffRequest();
00603             Phy_EnterIdle( &phyLocal[instanceId] );
00604         }
00605 #endif
00606     }
00607     else
00608     {
00609         phyLocal[instanceId].flags &= ~gPhyFlagRxOnWhenIdle_c;
00610         if( (radioState == gRX_c) && (phyLocal[instanceId].flags & gPhyFlagIdleRx_c) )
00611         {
00612             PhyPlmeForceTrxOffRequest();
00613             phyLocal[instanceId].flags &= ~gPhyFlagIdleRx_c;
00614         }
00615     }
00616 }
00617 
00618 /*! *********************************************************************************
00619 * \brief  This function starts the IdleRX if the PhyRxOnWhenIdle PIB is set
00620 *
00621 * \param[in]  instanceId The instance of the PHY
00622 *
00623 ********************************************************************************** */
00624 bool_t PhyIsIdleRx( instanceId_t instanceId )
00625 {
00626     if( (phyLocal[instanceId].flags & gPhyFlagIdleRx_c) && (gRX_c == PhyGetSeqState()))
00627         return TRUE;
00628 
00629     return FALSE;
00630 }
00631 
00632 /*! *********************************************************************************
00633 * \brief  This function signals the PHY task that a TX operation completed successfully.
00634 *         If the received ACK has FP=1, then the radio will enter RX state for
00635 *         maxFrameWaitTime duration.
00636 *
00637 * \param[in]  instanceId The instance of the PHY
00638 * \param[in]  framePending The value of the framePending bit for the received ACK
00639 *
00640 ********************************************************************************** */
00641 void Radio_Phy_PdDataConfirm(instanceId_t instanceId, bool_t framePending)
00642 {
00643     PhyTimeDisableEventTimeout();
00644 
00645     if( framePending )
00646     {
00647         phyLocal[instanceId].flags |= gPhyFlagFramePending_c;
00648         if( phyLocal[instanceId].maxFrameWaitTime > 0 )
00649         {
00650             /* Restart Rx asap if an ACK with FP=1 is received */
00651             phyLocal[instanceId].flags &= ~(gPhyFlagIdleRx_c);
00652             Phy_SetSequenceTiming( gPhySeqStartAsap_c, phyLocal[instanceId].maxFrameWaitTime );
00653             PhyPlmeRxRequest( gPhyUnslottedMode_c, (phyRxParams_t *) &phyLocal[instanceId].rxParams );
00654         }
00655     }
00656     else
00657     {
00658         phyLocal[instanceId].flags &= ~gPhyFlagFramePending_c;
00659     }
00660 
00661     PD_SendMessage(&phyLocal[instanceId], gPdDataCnf_c);
00662     Phy24Task(&phyLocal[instanceId]);
00663 }
00664 
00665 /*! *********************************************************************************
00666 * \brief  This function signals the PHY task that new data has been received
00667 *
00668 * \param[in]  instanceId The instance of the PHY
00669 *
00670 ********************************************************************************** */
00671 void Radio_Phy_PdDataIndication(instanceId_t instanceId)
00672 {
00673     PhyTimeDisableEventTimeout();
00674 
00675     PD_SendMessage(&phyLocal[instanceId], gPdDataInd_c);
00676     Phy24Task(&phyLocal[instanceId]);
00677 }
00678 
00679 /*! *********************************************************************************
00680 * \brief  This function signals the PHY task that timer1 compare match occured
00681 *
00682 * \param[in]  instanceId The instance of the PHY
00683 *
00684 ********************************************************************************** */
00685 void Radio_Phy_TimeWaitTimeoutIndication(instanceId_t instanceId)
00686 {
00687     PhyTime_ISR();
00688 }
00689 
00690 /*! *********************************************************************************
00691 * \brief  This function signals the PHY task that a CCA sequence has finished
00692 *
00693 * \param[in]  instanceId The instance of the PHY
00694 * \param[in]  phyChannelStatus The status of the channel: Idle/Busy
00695 *
00696 * \return  None.
00697 *
00698 ********************************************************************************** */
00699 void Radio_Phy_PlmeCcaConfirm(phyStatus_t phyChannelStatus, instanceId_t instanceId)
00700 {
00701     PhyTimeDisableEventTimeout();
00702 
00703     phyLocal[instanceId].channelParams.channelStatus = phyChannelStatus;
00704 
00705     PLME_SendMessage(&phyLocal[instanceId], gPlmeCcaCnf_c);
00706     Phy24Task(&phyLocal[instanceId]);
00707 }
00708 
00709 /*! *********************************************************************************
00710 * \brief  This function signals the PHY task that a ED sequence has finished
00711 *
00712 * \param[in]  instanceId The instance of the PHY
00713 * \param[in]  energyLevel The enetgy level on the channel.
00714 * \param[in]  energyLeveldB The energy level in DB
00715 *
00716 ********************************************************************************** */
00717 void Radio_Phy_PlmeEdConfirm(uint8_t energyLeveldB, instanceId_t instanceId)
00718 {
00719     PhyTimeDisableEventTimeout();
00720 
00721     phyLocal[instanceId].channelParams.energyLeveldB = energyLeveldB;
00722 
00723     PLME_SendMessage(&phyLocal[instanceId], gPlmeEdCnf_c);
00724     Phy24Task(&phyLocal[instanceId]);
00725 }
00726 
00727 /*! *********************************************************************************
00728 * \brief  This function signals the PHY task that the programmed sequence has timed out
00729 *         The Radio is forced to Idle.
00730 *
00731 * \param[in]  instanceId The instance of the PHY
00732 *
00733 ********************************************************************************** */
00734 void Radio_Phy_TimeRxTimeoutIndication(instanceId_t instanceId)
00735 {
00736     if( !(phyLocal[instanceId].flags & gPhyFlagIdleRx_c) )
00737         PLME_SendMessage(&phyLocal[instanceId], gPlmeTimeoutInd_c);
00738 
00739     Phy24Task(&phyLocal[instanceId]);
00740 }
00741 
00742 /*! *********************************************************************************
00743 * \brief  This function signals the PHY task that the programmed sequence has started
00744 *
00745 * \param[in]  instanceId The instance of the PHY
00746 *
00747 * \return  None.
00748 *
00749 ********************************************************************************** */
00750 void Radio_Phy_TimeStartEventIndication(instanceId_t instanceId)
00751 {
00752 #ifdef MAC_PHY_DEBUG
00753     PLME_SendMessage(&phyLocal[instanceId], gPlme_StartEventInd_c);
00754     Phy24Task(&phyLocal[instanceId]);
00755 #endif
00756 }
00757 
00758 /*! *********************************************************************************
00759 * \brief  This function signals the PHY task that a SFD was detected.
00760 *         Also, if there is not enough time to receive the entire packet, the
00761 *         RX timeout will be extended.
00762 *
00763 * \param[in]  instanceId The instance of the PHY
00764 * \param[in]  frameLen the length of the PSDU
00765 *
00766 ********************************************************************************** */
00767 void Radio_Phy_PlmeRxSfdDetect(instanceId_t instanceId, uint32_t frameLen)
00768 {
00769     if( phyLocal[instanceId].flags & gPhyFlagDeferTx_c )
00770     {
00771         uint32_t currentTime;
00772         uint32_t time;
00773 
00774         OSA_EnterCritical(kCriticalDisableInt);
00775 
00776         //Read currentTime and Timeout values [sym]
00777         PhyTimeReadClock(&currentTime);
00778 
00779         frameLen = frameLen * 2 + 12 + 22 + 2; //Convert to symbols and add IFS and ACK duration
00780 
00781         if( mPhySeqTimeout > currentTime )
00782         {
00783             time = mPhySeqTimeout - currentTime;
00784         }
00785         else
00786         {
00787             time = (gPhyTimeMask_c - currentTime + mPhySeqTimeout) & gPhyTimeMask_c;
00788         }
00789 
00790         if( time > 4 )
00791         {
00792             mPhySeqTimeout = (currentTime + frameLen) & gPhyTimeMask_c;
00793             MCR20Drv_DirectAccessSPIMultiByteWrite( T3CMP_LSB, (uint8_t *)&mPhySeqTimeout, 3);
00794         }
00795 
00796         OSA_ExitCritical(kCriticalDisableInt);
00797     }
00798 
00799 #ifdef MAC_PHY_DEBUG
00800     PLME_SendMessage(&phyLocal[instanceId], gPlme_RxSfdDetectInd_c);
00801     Phy24Task(&phyLocal[instanceId]);
00802 #endif
00803 }
00804 
00805 /*! *********************************************************************************
00806 * \brief  This function signals the PHY task that a Sync Loss occured (PLL unlock)
00807 *         The Radio is forced to Idle.
00808 *
00809 * \param[in]  instanceId The instance of the PHY
00810 *
00811 ********************************************************************************** */
00812 void Radio_Phy_PlmeSyncLossIndication(instanceId_t instanceId)
00813 {
00814     PhyPlmeForceTrxOffRequest();
00815 #ifdef MAC_PHY_DEBUG
00816     PLME_SendMessage(&phyLocal[instanceId], gPlme_SyncLossInd_c);
00817 #endif
00818     Radio_Phy_TimeRxTimeoutIndication(instanceId);
00819 }
00820 
00821 /*! *********************************************************************************
00822 * \brief  This function signals the PHY task that a Filter Fail occured
00823 *
00824 * \param[in]  instanceId The instance of the PHY
00825 *
00826 ********************************************************************************** */
00827 void Radio_Phy_PlmeFilterFailRx(instanceId_t instanceId)
00828 {
00829 #ifdef MAC_PHY_DEBUG
00830     PLME_SendMessage(&phyLocal[instanceId], gPlme_FilterFailInd_c);
00831     Phy24Task(&phyLocal[instanceId]);
00832 #endif
00833 }
00834 
00835 /*! *********************************************************************************
00836 * \brief  This function signals the PHY task that an unexpected Transceiver Reset
00837 *          occured and force the TRX to Off
00838 *
00839 * \param[in]  instanceId The instance of the PHY
00840 *
00841 ********************************************************************************** */
00842 void Radio_Phy_UnexpectedTransceiverReset(instanceId_t instanceId)
00843 {
00844     PhyPlmeForceTrxOffRequest();
00845 #ifdef MAC_PHY_DEBUG
00846     PLME_SendMessage(&phyLocal[instanceId], gPlme_UnexpectedRadioResetInd_c);
00847 #endif
00848     Radio_Phy_TimeRxTimeoutIndication(instanceId);
00849 }
00850 
00851 /*! *********************************************************************************
00852 * \brief  Senf a PLME message to upper layer
00853 *
00854 * \param[in]  instanceId The instance of the PHY
00855 * \param[in]  msgType    The type of message to be sent
00856 *
00857 ********************************************************************************** */
00858 static void PLME_SendMessage(Phy_PhyLocalStruct_t *pPhyStruct, phyMessageId_t msgType)
00859 {
00860     plmeToMacMessage_t * pMsg = MEM_BufferAlloc(sizeof(plmeToMacMessage_t));
00861 
00862     if(NULL == pMsg)
00863     {
00864         //panic(0,(uint32_t)PLME_SendMessage,0,msgType);
00865         return;
00866     }
00867 
00868     pMsg->msgType = msgType;
00869 
00870     switch(msgType)
00871     {
00872     case gPlmeCcaCnf_c:
00873         pMsg->msgData.ccaCnf.status = pPhyStruct->channelParams.channelStatus;
00874         break;
00875 
00876     case gPlmeEdCnf_c:
00877         pMsg->msgData.edCnf.status        = gPhySuccess_c;
00878         pMsg->msgData.edCnf.energyLeveldB = pPhyStruct->channelParams.energyLeveldB;
00879         pMsg->msgData.edCnf.energyLevel   = Phy_GetEnergyLevel(pPhyStruct->channelParams.energyLeveldB);
00880         break;
00881 
00882     default:
00883         /* No aditional info needs to be filled */
00884         break;
00885     }
00886 
00887     pPhyStruct->PLME_MAC_SapHandler(pMsg, pPhyStruct->currentMacInstance);
00888 }
00889 
00890 /*! *********************************************************************************
00891 * \brief  Senf a PD message to upper layer
00892 *
00893 * \param[in]  instanceId The instance of the PHY
00894 * \param[in]  msgType    The type of message to be sent
00895 *
00896 ********************************************************************************** */
00897 static void PD_SendMessage(Phy_PhyLocalStruct_t *pPhyStruct, phyMessageId_t msgType)
00898 {
00899     pdDataToMacMessage_t *pMsg;
00900 
00901     if( msgType == gPdDataInd_c )
00902     {
00903         uint32_t temp;
00904         uint16_t len = pPhyStruct->rxParams.psduLength - 2; //Excluding FCS (2 bytes);
00905 
00906         pMsg = pPhyStruct->rxParams.pRxData;
00907         pPhyStruct->rxParams.pRxData = NULL;
00908 
00909 #if !gUsePBTransferThereshold_d
00910         MCR20Drv_PB_SPIBurstRead( (uint8_t *)(pMsg->msgData.dataInd.pPsdu), len );
00911 #endif
00912 
00913         pMsg->msgType                         = gPdDataInd_c;
00914         pMsg->msgData.dataInd.ppduLinkQuality = pPhyStruct->rxParams.linkQuality;
00915         pMsg->msgData.dataInd.psduLength      = len;
00916 
00917         pMsg->msgData.dataInd.timeStamp       = PhyTime_GetTimestamp();      //current timestamp (64bit)
00918         temp = (uint32_t)(pMsg->msgData.dataInd.timeStamp & gPhyTimeMask_c); //convert to 24bit
00919         pMsg->msgData.dataInd.timeStamp -= (temp - pPhyStruct->rxParams.timeStamp) & gPhyTimeMask_c;
00920 #if !(gMpmIncluded_d)
00921         pPhyStruct->PD_MAC_SapHandler(pMsg, pPhyStruct->currentMacInstance);
00922 #else
00923         {
00924             uint32_t i, bitMask = PhyPpGetPanOfRxPacket();
00925 
00926             for( i=0; i<gMpmPhyPanRegSets_c; i++ )
00927             {
00928                 if( bitMask & (1 << i) )
00929                 {
00930                     bitMask &= ~(1 << i);
00931                     pPhyStruct->currentMacInstance = MPM_GetMacInstanceFromRegSet(i);
00932 
00933                     /* If the packet passed filtering on muliple PANs, send a copy to each one */
00934                     if( bitMask )
00935                     {
00936                         pdDataToMacMessage_t *pDataIndCopy;
00937 
00938                         pDataIndCopy = MEM_BufferAlloc(sizeof(pdDataToMacMessage_t) + len);
00939                         
00940                         if( pDataIndCopy )
00941                         {
00942                             FLib_MemCpy(pDataIndCopy, pMsg, sizeof(pdDataToMacMessage_t) + len);
00943                             pPhyStruct->PD_MAC_SapHandler(pDataIndCopy, pPhyStruct->currentMacInstance);
00944                         }
00945                     }
00946                     else
00947                     {
00948                         pPhyStruct->PD_MAC_SapHandler(pMsg, pPhyStruct->currentMacInstance);
00949                         break;
00950                     }
00951                 }
00952             }
00953         }
00954 #endif
00955     }
00956     else
00957     {
00958         pMsg = MEM_BufferAlloc( sizeof(pdDataToMacMessage_t) );
00959 
00960         if(NULL == pMsg)
00961         {
00962             //panic(0,(uint32_t)PD_SendMessage,0,gPdDataCnf_c);
00963             return;
00964         }
00965 
00966         pMsg->msgType = gPdDataCnf_c;
00967 
00968         if( pPhyStruct->flags & gPhyFlagFramePending_c )
00969         {
00970             pPhyStruct->flags &= ~(gPhyFlagFramePending_c);
00971             pMsg->msgData.dataCnf.status = gPhyFramePending_c;
00972         }
00973         else
00974         {
00975             pMsg->msgData.dataCnf.status = gPhySuccess_c;
00976         }
00977 
00978         pPhyStruct->PD_MAC_SapHandler(pMsg, pPhyStruct->currentMacInstance);
00979     }
00980 }
00981 
00982 void MSG_InitQueue(macPhyInputQueue_t * pMacPhyQueue)
00983 {
00984     pMacPhyQueue->msgInIdx = 0;
00985     FLib_MemSet(&pMacPhyQueue->pMsgIn[0], 0x00, gPhyMsgQueueMax_c * sizeof(void*));
00986 }
00987 
00988 /* Check if a message is pending in a queue. Returns */
00989 /* TRUE if any pending messages, and FALSE otherwise. */
00990 bool_t MSG_Pending(macPhyInputQueue_t * pMacPhyQueue)
00991 {
00992     return (pMacPhyQueue->msgInIdx > 0);
00993 }
00994 
00995 /* Get a message from a queue. Returns NULL if no messages in queue. */
00996 void * MSG_DeQueue(macPhyInputQueue_t * pMacPhyQueue)
00997 {
00998     phyMessageHeader_t * pMsgIn = NULL;
00999     uint32_t i = 0;
01000 
01001     if(MSG_Pending(pMacPhyQueue))
01002     {
01003         pMsgIn = pMacPhyQueue->pMsgIn[0];
01004 
01005         while(i < pMacPhyQueue->msgInIdx)
01006         {
01007             pMacPhyQueue->pMsgIn[i] = pMacPhyQueue->pMsgIn[i+1];
01008             i++;
01009         }
01010 
01011         pMacPhyQueue->msgInIdx--;
01012         pMacPhyQueue->pMsgIn[pMacPhyQueue->msgInIdx] = NULL;
01013     }
01014     
01015     return pMsgIn;
01016 }
01017 
01018 
01019 void MSG_Queue(macPhyInputQueue_t * pMacPhyQueue, void * pMsgIn)
01020 {
01021     if(pMacPhyQueue->msgInIdx < gPhyMsgQueueMax_c)
01022     {
01023         pMacPhyQueue->pMsgIn[pMacPhyQueue->msgInIdx] = pMsgIn;
01024         pMacPhyQueue->msgInIdx++;
01025     }
01026 }
01027 
01028 void MSG_QueueHead(macPhyInputQueue_t * pMacPhyQueue, void * pMsgIn)
01029 {
01030     uint32_t i = gPhyMsgQueueMax_c - 1;
01031     
01032     if(pMacPhyQueue->msgInIdx < gPhyMsgQueueMax_c)
01033     {
01034         while(i > 0)
01035         {
01036             pMacPhyQueue->pMsgIn[i] = pMacPhyQueue->pMsgIn[i-1];
01037             i--;
01038         }
01039         pMacPhyQueue->pMsgIn[0] = pMsgIn;
01040         pMacPhyQueue->msgInIdx++;
01041     }
01042 }
01043 
01044