NXP / fsl_phy_mcr20a

Fork of fsl_phy_mcr20a by Freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PhyPacketProcessor.c Source File

PhyPacketProcessor.c

Go to the documentation of this file.
00001 /*!
00002 * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003 * All rights reserved.
00004 *
00005 * \file PhyPacketProcessor.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 /************************************************************************************
00035 *************************************************************************************
00036 * Include
00037 *************************************************************************************
00038 ************************************************************************************/
00039 #include "EmbeddedTypes.h "
00040 #include "MCR20Drv.h "
00041 #include "MCR20Reg.h"
00042 #include "MCR20Overwrites.h "
00043 
00044 #include "Phy.h "
00045 #include "MpmInterface.h "
00046 
00047 #if 0
00048 #include "board.h"
00049 #include "fsl_os_abstraction.h"
00050 #include "fsl_gpio_driver.h"
00051 
00052 extern const IRQn_Type g_portIrqId[HW_PORT_INSTANCE_COUNT];
00053 #endif
00054 /************************************************************************************
00055 *************************************************************************************
00056 * Public macros
00057 *************************************************************************************
00058 ************************************************************************************/
00059 
00060 // Address mode indentifiers. Used for both network and MAC interfaces
00061 #define gPhyAddrModeNoAddr_c        (0)
00062 #define gPhyAddrModeInvalid_c       (1)
00063 #define gPhyAddrMode16BitAddr_c     (2)
00064 #define gPhyAddrMode64BitAddr_c     (3)
00065 
00066 #define PHY_MIN_RNG_DELAY 4
00067 
00068 /************************************************************************************
00069 *************************************************************************************
00070 * Private variables
00071 *************************************************************************************
00072 ************************************************************************************/
00073 
00074 const  uint8_t gPhyIdlePwrState = gPhyDefaultIdlePwrMode_c;
00075 const  uint8_t gPhyActivePwrState = gPhyDefaultActivePwrMode_c;
00076 
00077 const uint8_t gPhyIndirectQueueSize_c = 12;
00078 static uint8_t mPhyCurrentSamLvl = 12;
00079 static uint8_t mPhyPwrState = gPhyPwrIdle_c;
00080 
00081 /************************************************************************************
00082 *************************************************************************************
00083 * Public Functions
00084 *************************************************************************************
00085 ************************************************************************************/
00086 
00087 
00088 /*---------------------------------------------------------------------------
00089  * Name: PhyGetRandomNo
00090  * Description: - This function should be called only when the Radio is idle.
00091  *                The function may take a long time to run!
00092  *                It is recomended to use this function only to initializa a seed at startup!
00093  * Parameters: -
00094  * Return: -
00095  *---------------------------------------------------------------------------*/
00096 
00097 void PhyGetRandomNo(uint32_t *pRandomNo)
00098 {
00099   uint8_t i = 4, prevRN=0;
00100   uint8_t* ptr = (uint8_t *)pRandomNo;
00101   uint32_t startTime, endTime;
00102   uint8_t phyReg;
00103 
00104   MCR20Drv_IRQ_Disable();
00105   
00106   if( PhyPpGetState() )
00107   {
00108       *pRandomNo = 0;
00109       MCR20Drv_IRQ_Enable();
00110       return;   
00111   }
00112 
00113   while (i--)
00114   {
00115     PhyTimeReadClock(&startTime);
00116 
00117     // Program a new sequence
00118     phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
00119     MCR20Drv_DirectAccessSPIWrite( PHY_CTRL1, phyReg | gRX_c);
00120 
00121       // wait a variable number of symbols */
00122     do
00123       PhyTimeReadClock(&endTime);
00124     while( ((endTime - startTime) & 0x00FFFFFF) < (PHY_MIN_RNG_DELAY + (prevRN>>5)));
00125 
00126       // Abort the sequence
00127     PhyAbort();
00128 
00129       // Read new 8 bit random number
00130     prevRN = MCR20Drv_IndirectAccessSPIRead((uint8_t)_RNG);
00131     *ptr++ = prevRN;
00132   }
00133 
00134   MCR20Drv_IRQ_Enable();
00135 }
00136 
00137 
00138 /*---------------------------------------------------------------------------
00139  * Name: PhyPpSetDualPanAuto
00140  * Description: -
00141  * Parameters: -
00142  * Return: -
00143  *---------------------------------------------------------------------------*/
00144 void PhyPpSetDualPanAuto
00145 (
00146   bool_t mode
00147 )
00148 {
00149   uint8_t phyReg, phyReg2;
00150 
00151   phyReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t) DUAL_PAN_CTRL);
00152 
00153   if( mode )
00154   {
00155     phyReg2 = phyReg | (cDUAL_PAN_CTRL_DUAL_PAN_AUTO);
00156   }
00157   else
00158   {
00159     phyReg2 = phyReg & (~cDUAL_PAN_CTRL_DUAL_PAN_AUTO);
00160   }
00161 
00162   /* Write the new value only if it has changed */
00163   if (phyReg2 != phyReg)
00164     MCR20Drv_IndirectAccessSPIWrite( (uint8_t) DUAL_PAN_CTRL, phyReg2);
00165 }
00166 
00167 /*---------------------------------------------------------------------------
00168  * Name: PhyPpGetDualPanAuto
00169  * Description: -
00170  * Parameters: -
00171  * Return: -
00172  *---------------------------------------------------------------------------*/
00173 bool_t PhyPpGetDualPanAuto
00174 (
00175   void
00176 )
00177 {
00178   uint8_t phyReg = MCR20Drv_IndirectAccessSPIRead(DUAL_PAN_CTRL);
00179   return  (phyReg & cDUAL_PAN_CTRL_DUAL_PAN_AUTO) == cDUAL_PAN_CTRL_DUAL_PAN_AUTO;
00180 }
00181 
00182 /*---------------------------------------------------------------------------
00183  * Name: PhyPpSetDualPanDwell
00184  * Description: -
00185  * Parameters: -
00186  * Return: -
00187  *---------------------------------------------------------------------------*/
00188 void PhyPpSetDualPanDwell // TODO: check seq state and return phyStatus_t
00189 (
00190   uint8_t dwell
00191 )
00192 {
00193   MCR20Drv_IndirectAccessSPIWrite( (uint8_t) DUAL_PAN_DWELL, dwell);
00194 }
00195 
00196 /*---------------------------------------------------------------------------
00197  * Name: PhyPpGetDualPanDwell
00198  * Description: -
00199  * Parameters: -
00200  * Return: -
00201  *---------------------------------------------------------------------------*/
00202 uint8_t PhyPpGetDualPanDwell
00203 (
00204   void
00205 )
00206 {
00207   return MCR20Drv_IndirectAccessSPIRead( (uint8_t) DUAL_PAN_DWELL);
00208 }
00209 
00210 /*---------------------------------------------------------------------------
00211  * Name: PhyPpGetDualPanRemain
00212  * Description: -
00213  * Parameters: -
00214  * Return: - the remaining Dwell time
00215  *---------------------------------------------------------------------------*/
00216 uint8_t PhyPpGetDualPanRemain()
00217 {
00218   return (MCR20Drv_IndirectAccessSPIRead(DUAL_PAN_STS) & cDUAL_PAN_STS_DUAL_PAN_REMAIN);
00219 }
00220 
00221 /*---------------------------------------------------------------------------
00222  * Name: PhyPpSetDualPanSamLvl
00223  * Description: -
00224  * Parameters: -
00225  * Return: -
00226  *---------------------------------------------------------------------------*/
00227 void PhyPpSetDualPanSamLvl // TODO: check seq state and return phyStatus_t
00228 (
00229   uint8_t level
00230 )
00231 {
00232   uint8_t phyReg;
00233 #ifdef PHY_PARAMETERS_VALIDATION
00234   if( level > gPhyIndirectQueueSize_c )
00235     return;
00236 #endif
00237   phyReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t) DUAL_PAN_CTRL);
00238 
00239   phyReg &= ~cDUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_MSK; // clear current lvl
00240   phyReg |= level << cDUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_Shift_c; // set new lvl
00241 
00242   MCR20Drv_IndirectAccessSPIWrite( (uint8_t) DUAL_PAN_CTRL, phyReg);
00243   mPhyCurrentSamLvl = level;
00244 }
00245 
00246 /*---------------------------------------------------------------------------
00247  * Name: PhyPpGetDualPanSamLvl
00248  * Description: -
00249  * Parameters: -
00250  * Return:
00251  *---------------------------------------------------------------------------*/
00252 uint8_t PhyPpGetDualPanSamLvl()
00253 {
00254   return mPhyCurrentSamLvl;
00255 }
00256 
00257 /*---------------------------------------------------------------------------
00258  * Name: PhyPpSetDualPanActiveNwk
00259  * Description: - Select Active PAN
00260  * Parameters: -
00261  * Return: -
00262  *---------------------------------------------------------------------------*/
00263 void PhyPpSetDualPanActiveNwk // TODO: check seq state and return phyStatus_t
00264 (
00265   uint8_t nwk
00266 )
00267 {
00268   uint8_t phyReg, phyReg2;
00269 
00270   phyReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t) DUAL_PAN_CTRL);
00271 
00272   if( 0 == nwk )
00273   {
00274       phyReg2 = phyReg & (~cDUAL_PAN_CTRL_ACTIVE_NETWORK);
00275   }
00276   else
00277   {
00278       phyReg2 = phyReg | cDUAL_PAN_CTRL_ACTIVE_NETWORK;
00279   }
00280 
00281   /* Write the new value only if it has changed */
00282   if( phyReg2 != phyReg )
00283   {
00284       MCR20Drv_IndirectAccessSPIWrite( (uint8_t) DUAL_PAN_CTRL, phyReg2);
00285   }
00286 }
00287 
00288 /*---------------------------------------------------------------------------
00289  * Name: PhyPpGetDualPanActiveNwk
00290  * Description: -
00291  * Parameters: -
00292  * Return: - the Active PAN
00293  *---------------------------------------------------------------------------*/
00294 uint8_t PhyPpGetDualPanActiveNwk(void)
00295 {
00296   uint8_t phyReg;
00297 
00298   phyReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t)DUAL_PAN_CTRL );
00299 
00300   return (phyReg & cDUAL_PAN_CTRL_CURRENT_NETWORK) > 0;
00301 }
00302 
00303 /*---------------------------------------------------------------------------
00304  * Name: PhyPpGetDualPanNwkOfRxPacket
00305  * Description: -
00306  * Parameters: -
00307  * Return: - the Active PAN
00308  *---------------------------------------------------------------------------*/
00309 uint8_t PhyPpGetPanOfRxPacket(void)
00310 {
00311   uint8_t phyReg;
00312   uint8_t PanBitMask = 0;
00313 
00314   phyReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t) DUAL_PAN_STS);
00315 
00316   if( phyReg & cDUAL_PAN_STS_RECD_ON_PAN0 )
00317       PanBitMask |= (1<<0);
00318 
00319   if( phyReg & cDUAL_PAN_STS_RECD_ON_PAN1 )
00320       PanBitMask |= (1<<1);
00321 
00322   return PanBitMask;
00323 }
00324 
00325 /*---------------------------------------------------------------------------
00326  * Name: PhyPpSetPromiscuous
00327  * Description: -
00328  * Parameters: -
00329  * Return: -
00330  *---------------------------------------------------------------------------*/
00331 void PhyPpSetPromiscuous
00332 (
00333   bool_t mode
00334 )
00335 {
00336   uint8_t rxFrameFltReg, phyCtrl4Reg;
00337 
00338   rxFrameFltReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t) RX_FRAME_FILTER);
00339   phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead( (uint8_t) PHY_CTRL4);
00340 
00341   if( mode )
00342   {
00343     /* FRM_VER[1:0] = b00. 00: Any FrameVersion accepted (0,1,2 & 3) */
00344     /* All frame types accepted*/
00345     phyCtrl4Reg |= cPHY_CTRL4_PROMISCUOUS;
00346     rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
00347     rxFrameFltReg |=   (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
00348   }
00349   else
00350   {
00351     phyCtrl4Reg &= ~cPHY_CTRL4_PROMISCUOUS;
00352     /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others */
00353     /* Beacon, Data and MAC command frame types accepted */
00354     rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
00355     rxFrameFltReg |= (0x03 << cRX_FRAME_FLT_FRM_VER_Shift_c);
00356     rxFrameFltReg &= ~(cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
00357   }
00358 
00359   MCR20Drv_IndirectAccessSPIWrite( (uint8_t) RX_FRAME_FILTER, rxFrameFltReg);
00360   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL4, phyCtrl4Reg);
00361 }
00362 
00363 /*---------------------------------------------------------------------------
00364  * Name: PhySetActivePromiscuous()
00365  * Description: -
00366  * Parameters: -
00367  * Return: -
00368  *---------------------------------------------------------------------------*/
00369 void PhySetActivePromiscuous(bool_t state)
00370 {
00371     uint8_t phyCtrl4Reg;
00372     uint8_t phyFrameFilterReg;
00373 //    bool_t currentState;
00374 
00375     phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead( (uint8_t) PHY_CTRL4);
00376     phyFrameFilterReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER);
00377 
00378 //    currentState = (phyFrameFilterReg & cRX_FRAME_FLT_ACTIVE_PROMISCUOUS) ? TRUE : FALSE;
00379 //
00380 //    if( state == currentState )
00381 //        return;
00382 
00383     /* if Prom is set */
00384     if( state )
00385     {
00386         if( phyCtrl4Reg & cPHY_CTRL4_PROMISCUOUS )
00387         {
00388             /* Disable Promiscuous mode */
00389             phyCtrl4Reg &= ~(cPHY_CTRL4_PROMISCUOUS);
00390 
00391             /* Enable Active Promiscuous mode */
00392             phyFrameFilterReg |= cRX_FRAME_FLT_ACTIVE_PROMISCUOUS;
00393         }
00394     }
00395     else
00396     {
00397         if( phyFrameFilterReg & cRX_FRAME_FLT_ACTIVE_PROMISCUOUS )
00398         {
00399             /* Disable Active Promiscuous mode */
00400             phyFrameFilterReg &= ~(cRX_FRAME_FLT_ACTIVE_PROMISCUOUS);
00401 
00402             /* Enable Promiscuous mode */
00403             phyCtrl4Reg |= cPHY_CTRL4_PROMISCUOUS;
00404         }
00405     }
00406 
00407     MCR20Drv_DirectAccessSPIWrite((uint8_t) PHY_CTRL4, phyCtrl4Reg);
00408     MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, phyFrameFilterReg);
00409 }
00410 
00411 /*---------------------------------------------------------------------------
00412  * Name: PhyGetActivePromiscuous()
00413  * Description: - returns the state of ActivePromiscuous feature (Enabled/Disabled)
00414  * Parameters: -
00415  * Return: - TRUE/FALSE
00416  *---------------------------------------------------------------------------*/
00417 bool_t PhyGetActivePromiscuous( void )
00418 {
00419     uint8_t phyReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER);
00420 
00421     if( phyReg & cRX_FRAME_FLT_ACTIVE_PROMISCUOUS )
00422         return TRUE;
00423 
00424     return FALSE;
00425 }
00426 
00427 /*---------------------------------------------------------------------------
00428  * Name: PhyPpSetPanId
00429  * Description: -
00430  * Parameters: -
00431  * Return: -
00432  *---------------------------------------------------------------------------*/
00433 phyStatus_t PhyPpSetPanId
00434 (
00435   uint8_t *pPanId,
00436   uint8_t pan
00437 )
00438 {
00439 #ifdef PHY_PARAMETERS_VALIDATION
00440   if(NULL == pPanId)
00441   {
00442     return gPhyInvalidParameter_c;
00443   }
00444 #endif // PHY_PARAMETERS_VALIDATION
00445 
00446   if( 0 == pan )
00447       MCR20Drv_IndirectAccessSPIMultiByteWrite((uint8_t) MACPANID0_LSB, pPanId, 2);
00448   else
00449       MCR20Drv_IndirectAccessSPIMultiByteWrite((uint8_t) MACPANID1_LSB, pPanId, 2);
00450 
00451   return gPhySuccess_c;
00452 }
00453 
00454 
00455 /*---------------------------------------------------------------------------
00456  * Name: PhyPpSetShortAddr
00457  * Description: -
00458  * Parameters: -
00459  * Return: -
00460  *---------------------------------------------------------------------------*/
00461 phyStatus_t PhyPpSetShortAddr
00462 (
00463   uint8_t *pShortAddr,
00464   uint8_t pan
00465 )
00466 {
00467 
00468 #ifdef PHY_PARAMETERS_VALIDATION
00469   if(NULL == pShortAddr)
00470   {
00471     return gPhyInvalidParameter_c;
00472   }
00473 #endif // PHY_PARAMETERS_VALIDATION
00474 
00475   if( pan == 0 )
00476   {
00477       MCR20Drv_IndirectAccessSPIMultiByteWrite((uint8_t) MACSHORTADDRS0_LSB, pShortAddr, 2);
00478   }
00479   else
00480   {
00481       MCR20Drv_IndirectAccessSPIMultiByteWrite((uint8_t) MACSHORTADDRS1_LSB, pShortAddr, 2);
00482   }
00483 
00484   return gPhySuccess_c;
00485 }
00486 
00487 /*---------------------------------------------------------------------------
00488  * Name: PhyPpSetLongAddr
00489  * Description: -
00490  * Parameters: -
00491  * Return: -
00492  *---------------------------------------------------------------------------*/
00493 phyStatus_t PhyPpSetLongAddr
00494 (
00495   uint8_t *pLongAddr,
00496   uint8_t pan
00497 )
00498 {
00499 
00500 #ifdef PHY_PARAMETERS_VALIDATION
00501   if(NULL == pLongAddr)
00502   {
00503     return gPhyInvalidParameter_c;
00504   }
00505 #endif // PHY_PARAMETERS_VALIDATION
00506 
00507   if( 0 == pan )
00508       MCR20Drv_IndirectAccessSPIMultiByteWrite((uint8_t) MACLONGADDRS0_0, pLongAddr, 8);
00509   else
00510       MCR20Drv_IndirectAccessSPIMultiByteWrite((uint8_t) MACLONGADDRS1_0, pLongAddr, 8);
00511 
00512   return gPhySuccess_c;
00513 }
00514 
00515 
00516 /*---------------------------------------------------------------------------
00517  * Name: PhyPpSetMacRole
00518  * Description: -
00519  * Parameters: -
00520  * Return: -
00521  *---------------------------------------------------------------------------*/
00522 phyStatus_t PhyPpSetMacRole
00523 (
00524   bool_t macRole,
00525   uint8_t pan
00526 )
00527 {
00528   uint8_t phyReg;
00529 
00530   if( 0 == pan )
00531   {
00532       phyReg = MCR20Drv_DirectAccessSPIRead( (uint8_t) PHY_CTRL4);
00533 
00534       if(gMacRole_PanCoord_c == macRole)
00535       {
00536           phyReg |=  cPHY_CTRL4_PANCORDNTR0;
00537       }
00538       else
00539       {
00540           phyReg &= ~cPHY_CTRL4_PANCORDNTR0;
00541       }
00542       MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL4, phyReg);
00543   }
00544   else
00545   {
00546       phyReg = MCR20Drv_IndirectAccessSPIRead( (uint8_t) DUAL_PAN_CTRL);
00547 
00548       if(gMacRole_PanCoord_c == macRole)
00549       {
00550           phyReg |=  cDUAL_PAN_CTRL_PANCORDNTR1;
00551       }
00552       else
00553       {
00554           phyReg &= ~cDUAL_PAN_CTRL_PANCORDNTR1;
00555       }
00556       MCR20Drv_IndirectAccessSPIWrite( (uint8_t) DUAL_PAN_CTRL, phyReg);
00557   }
00558 
00559   return gPhySuccess_c;
00560 }
00561 
00562 /*---------------------------------------------------------------------------
00563  * Name: PhyPpIsTxAckDataPending
00564  * Description: -
00565  * Parameters: -
00566  * Return: -
00567  *---------------------------------------------------------------------------*/
00568 bool_t PhyPpIsTxAckDataPending
00569 (
00570 void
00571 )
00572 {
00573     uint8_t srcCtrlReg;
00574 
00575     srcCtrlReg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
00576     if( srcCtrlReg & cSRC_CTRL_SRCADDR_EN )
00577     {
00578         uint8_t irqsts2Reg;
00579 
00580         irqsts2Reg = MCR20Drv_DirectAccessSPIRead((uint8_t) IRQSTS2);
00581 
00582         if(irqsts2Reg & cIRQSTS2_SRCADDR)
00583             return TRUE;
00584         else
00585             return FALSE;
00586     }
00587     else
00588     {
00589         return ((srcCtrlReg & cSRC_CTRL_ACK_FRM_PND) == cSRC_CTRL_ACK_FRM_PND);
00590     }
00591 }
00592 
00593 /*---------------------------------------------------------------------------
00594  * Name: PhyPpIsRxAckDataPending
00595  * Description: -
00596  * Parameters: -
00597  * Return: -
00598  *---------------------------------------------------------------------------*/
00599 bool_t PhyPpIsRxAckDataPending
00600 (
00601   void
00602 )
00603 {
00604   uint8_t irqsts1Reg;
00605   irqsts1Reg = MCR20Drv_DirectAccessSPIRead((uint8_t) IRQSTS1);
00606   if(irqsts1Reg & cIRQSTS1_RX_FRM_PEND)
00607   {
00608     return TRUE;
00609   }
00610   return FALSE;
00611 }
00612 
00613 /*---------------------------------------------------------------------------
00614  * Name: PhyPpSetFpManually
00615  * Description: -
00616  * Parameters: -
00617  * Return: -
00618  *---------------------------------------------------------------------------*/
00619 void PhyPpSetFpManually
00620 (
00621   bool_t FP
00622 )
00623 {
00624     uint8_t phyReg;
00625     /* Disable the Source Address Matching feature and set FP manually */
00626     phyReg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
00627     phyReg &= ~(cSRC_CTRL_SRCADDR_EN);
00628     if(FP)
00629         phyReg |= cSRC_CTRL_ACK_FRM_PND;
00630     else
00631         phyReg &= ~(cSRC_CTRL_ACK_FRM_PND);
00632     MCR20Drv_DirectAccessSPIWrite(SRC_CTRL, phyReg);
00633 }
00634 
00635 /*---------------------------------------------------------------------------
00636  * Name: PhyPpIsPollIndication
00637  * Description: -
00638  * Parameters: -
00639  * Return: -
00640  *---------------------------------------------------------------------------*/
00641 bool_t PhyPpIsPollIndication
00642 (
00643   void
00644 )
00645 {
00646   uint8_t irqsts2Reg;
00647   irqsts2Reg = MCR20Drv_DirectAccessSPIRead((uint8_t) IRQSTS2);
00648   if(irqsts2Reg & cIRQSTS2_PI)
00649   {
00650     return TRUE;
00651   }
00652   return FALSE;
00653 }
00654 
00655 /*---------------------------------------------------------------------------
00656  * Name: PhyPpSetCcaThreshold
00657  * Description: -
00658  * Parameters: -
00659  * Return: -
00660  *---------------------------------------------------------------------------*/
00661 phyStatus_t PhyPpSetCcaThreshold(uint8_t ccaThreshold)
00662 {
00663   MCR20Drv_IndirectAccessSPIWrite((uint8_t) CCA1_THRESH, (uint8_t) ccaThreshold);
00664   return gPhySuccess_c;
00665 }
00666 
00667 /*---------------------------------------------------------------------------
00668  * Name: PhyPpSetSAMState
00669  * Description: -
00670  * Parameters: -
00671  * Return: -
00672  *---------------------------------------------------------------------------*/
00673 void PhyPpSetSAMState
00674 (
00675   bool_t state
00676 )
00677 {
00678   uint8_t phyReg, newPhyReg;
00679   /* Disable/Enables the Source Address Matching feature */
00680   phyReg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
00681   if( state )
00682     newPhyReg = phyReg | cSRC_CTRL_SRCADDR_EN;
00683   else
00684     newPhyReg = phyReg & ~(cSRC_CTRL_SRCADDR_EN);
00685 
00686   if( newPhyReg != phyReg )
00687     MCR20Drv_DirectAccessSPIWrite(SRC_CTRL, newPhyReg);
00688 }
00689 
00690 
00691 /*---------------------------------------------------------------------------
00692  * Name: PhyPlmeSetFADStateRequest
00693  * Description: -
00694  * Parameters: -
00695  * Return: -
00696  *---------------------------------------------------------------------------*/
00697 uint8_t PhyPlmeSetFADStateRequest(bool_t state)
00698 {
00699   uint8_t phyReg;
00700 
00701   phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_AGC_CTRL);
00702   state ? (phyReg |= cANT_AGC_CTRL_FAD_EN_Mask_c) : (phyReg &= (~((uint8_t)cANT_AGC_CTRL_FAD_EN_Mask_c)));
00703   MCR20Drv_IndirectAccessSPIWrite(ANT_AGC_CTRL, phyReg);
00704 
00705   phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_PAD_CTRL);
00706   state ? (phyReg |= 0x02) : (phyReg &= ~cANT_PAD_CTRL_ANTX_EN);
00707   MCR20Drv_IndirectAccessSPIWrite(ANT_PAD_CTRL, phyReg);
00708 
00709   return gPhySuccess_c;
00710 }
00711 
00712 /*---------------------------------------------------------------------------
00713  * Name: PhyPlmeSetFADThresholdRequest
00714  * Description: -
00715  * Parameters: -
00716  * Return: -
00717  *---------------------------------------------------------------------------*/
00718 uint8_t PhyPlmeSetFADThresholdRequest(uint8_t FADThreshold)
00719 {
00720   MCR20Drv_IndirectAccessSPIWrite(FAD_THR, FADThreshold);
00721   return gPhySuccess_c;
00722 }
00723 
00724 uint8_t PhyPlmeSetANTPadStateRequest(bool_t antAB_on, bool_t rxtxSwitch_on)
00725 {
00726     uint8_t phyReg;
00727 
00728     phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_PAD_CTRL);
00729     antAB_on ? (phyReg |= 0x02) : (phyReg &= ~0x02);
00730     rxtxSwitch_on ? (phyReg |= 0x01) : (phyReg &= ~0x01);
00731     MCR20Drv_IndirectAccessSPIWrite(ANT_PAD_CTRL, phyReg);
00732 
00733     return gPhySuccess_c;
00734 }
00735 
00736 uint8_t PhyPlmeSetANTPadStrengthRequest(bool_t hiStrength)
00737 {
00738     uint8_t phyReg;
00739 
00740     phyReg = MCR20Drv_IndirectAccessSPIRead(MISC_PAD_CTRL);
00741     hiStrength ? (phyReg |= cMISC_PAD_CTRL_ANTX_CURR) : (phyReg &= ~cMISC_PAD_CTRL_ANTX_CURR);
00742     MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, phyReg);
00743 
00744     return gPhySuccess_c;
00745 }
00746 
00747 uint8_t PhyPlmeSetANTPadInvertedRequest(bool_t invAntA, bool_t invAntB, bool_t invTx, bool_t invRx)
00748 {
00749     uint8_t phyReg;
00750 
00751     phyReg = MCR20Drv_IndirectAccessSPIRead(MISC_PAD_CTRL);
00752     invAntA ? (phyReg |= 0x10) : (phyReg &= ~0x10);
00753     invAntB ? (phyReg |= 0x20) : (phyReg &= ~0x20);
00754     invTx   ? (phyReg |= 0x40) : (phyReg &= ~0x40);
00755     invRx   ? (phyReg |= 0x80) : (phyReg &= ~0x80);
00756     MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, phyReg);
00757 
00758     return gPhySuccess_c;
00759 }
00760 
00761 /*---------------------------------------------------------------------------
00762  * Name: PhyPlmeSetANTXStateRequest
00763  * Description: -
00764  * Parameters: -
00765  * Return: -
00766  *---------------------------------------------------------------------------*/
00767 uint8_t PhyPlmeSetANTXStateRequest(bool_t state)
00768 {
00769   uint8_t phyReg;
00770 
00771   phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_AGC_CTRL);
00772   state ? (phyReg |= cANT_AGC_CTRL_ANTX_Mask_c) : (phyReg &= (~((uint8_t)cANT_AGC_CTRL_ANTX_Mask_c)));
00773   MCR20Drv_IndirectAccessSPIWrite(ANT_AGC_CTRL, phyReg);
00774 
00775   return gPhySuccess_c;
00776 }
00777 
00778 /*---------------------------------------------------------------------------
00779  * Name: PhyPlmeGetANTXStateRequest
00780  * Description: -
00781  * Parameters: -
00782  * Return: -
00783  *---------------------------------------------------------------------------*/
00784 uint8_t PhyPlmeGetANTXStateRequest(void)
00785 {
00786   uint8_t phyReg;
00787 
00788   phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_AGC_CTRL);
00789 
00790   return ((phyReg & cANT_AGC_CTRL_ANTX_Mask_c) == cANT_AGC_CTRL_ANTX_Mask_c);
00791 }
00792 
00793 /*---------------------------------------------------------------------------
00794  * Name: PhyPp_IndirectQueueInsert
00795  * Description: -
00796  * Parameters: -
00797  * Return: -
00798  *---------------------------------------------------------------------------*/
00799 phyStatus_t PhyPp_IndirectQueueInsert // TODO: to validate add to indirect queue parameters
00800 (
00801   uint8_t  index,
00802   uint16_t checkSum,
00803   instanceId_t instanceId
00804 )
00805 {
00806   uint16_t srcAddressCheckSum = checkSum;
00807   uint8_t  srcCtrlReg;
00808 
00809   if( index >= gPhyIndirectQueueSize_c )
00810       return gPhyInvalidParameter_c;
00811 
00812   srcCtrlReg = (uint8_t) ( (index & cSRC_CTRL_INDEX) << cSRC_CTRL_INDEX_Shift_c );
00813   MCR20Drv_DirectAccessSPIWrite( (uint8_t) SRC_CTRL, srcCtrlReg);
00814 
00815   MCR20Drv_DirectAccessSPIMultiByteWrite( (uint8_t) SRC_ADDRS_SUM_LSB, (uint8_t *) &srcAddressCheckSum, 2);
00816 
00817   srcCtrlReg |= ( cSRC_CTRL_SRCADDR_EN | cSRC_CTRL_INDEX_EN );
00818   MCR20Drv_DirectAccessSPIWrite( (uint8_t) SRC_CTRL, srcCtrlReg);
00819 
00820   return gPhySuccess_c;
00821 
00822 }
00823 
00824 
00825 /*---------------------------------------------------------------------------
00826  * Name: PhyPp_RemoveFromIndirect
00827  * Description: -
00828  * Parameters: -
00829  * Return: -
00830  *---------------------------------------------------------------------------*/
00831 phyStatus_t PhyPp_RemoveFromIndirect
00832 (
00833   uint8_t index,
00834   instanceId_t instanceId
00835 )
00836 {
00837   uint8_t srcCtrlReg;
00838 
00839   if( index >= gPhyIndirectQueueSize_c )
00840       return gPhyInvalidParameter_c;
00841 
00842   srcCtrlReg = (uint8_t)( ( (index & cSRC_CTRL_INDEX) << cSRC_CTRL_INDEX_Shift_c )
00843                          |( cSRC_CTRL_SRCADDR_EN )
00844                          |( cSRC_CTRL_INDEX_DISABLE) );
00845 
00846   MCR20Drv_DirectAccessSPIWrite( (uint8_t) SRC_CTRL, srcCtrlReg);
00847 
00848   return gPhySuccess_c;
00849 }
00850 
00851 
00852 /*---------------------------------------------------------------------------
00853  * Name: PhyPpGetState
00854  * Description: -
00855  * Parameters: -
00856  * Return: -
00857  *---------------------------------------------------------------------------*/
00858 uint8_t PhyPpGetState
00859 (
00860   void
00861 )
00862 {
00863   return (uint8_t)( MCR20Drv_DirectAccessSPIRead( (uint8_t) PHY_CTRL1) & cPHY_CTRL1_XCVSEQ );
00864 }
00865 
00866 /*! *********************************************************************************
00867 * \brief  Aborts the current sequence and force the radio to IDLE
00868 *
00869 ********************************************************************************** */
00870 void PhyAbort(void)
00871 {
00872     uint8_t phyRegs[8];
00873     volatile uint8_t currentTime = 0;
00874 
00875     ProtectFromMCR20Interrupt();
00876 
00877     phyRegs[0] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &phyRegs[1], 7);
00878 
00879     // Disable timer trigger (for scheduled XCVSEQ)
00880     if( phyRegs[PHY_CTRL1] & cPHY_CTRL1_TMRTRIGEN )
00881     {
00882         phyRegs[PHY_CTRL1] &= (uint8_t) ~(cPHY_CTRL1_TMRTRIGEN );
00883         MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyRegs[PHY_CTRL1]);
00884         
00885         // give the FSM enough time to start if it was triggered
00886         currentTime = (uint8_t) ( MCR20Drv_DirectAccessSPIRead(EVENT_TMR_LSB) + 2 );
00887         while(MCR20Drv_DirectAccessSPIRead(EVENT_TMR_LSB) != (uint8_t) (currentTime));
00888         
00889         phyRegs[PHY_CTRL1] = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
00890     }
00891 
00892     if( (phyRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c )
00893     {
00894         // Abort current SEQ
00895         phyRegs[PHY_CTRL1] &= (uint8_t) ~(cPHY_CTRL1_XCVSEQ);
00896         MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyRegs[PHY_CTRL1]);
00897         
00898         // wait for Sequence Idle (if not already)
00899         while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
00900     }
00901 
00902     // mask SEQ interrupt
00903     phyRegs[PHY_CTRL2] |= (uint8_t) (cPHY_CTRL2_SEQMSK);
00904     // stop timers
00905     phyRegs[PHY_CTRL3] &= (uint8_t) ~(cPHY_CTRL3_TMR2CMP_EN | cPHY_CTRL3_TMR3CMP_EN);
00906     phyRegs[PHY_CTRL4] &= (uint8_t) ~(cPHY_CTRL4_TC3TMOUT);
00907 
00908     MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL2, &phyRegs[PHY_CTRL2], 4);
00909 
00910     // clear all PP IRQ bits to avoid unexpected interrupts
00911     phyRegs[IRQSTS3] &= 0xF0;                     // do not change IRQ status
00912     phyRegs[IRQSTS3] |= (uint8_t) (cIRQSTS3_TMR3MSK |
00913                                    cIRQSTS3_TMR2IRQ |
00914                                    cIRQSTS3_TMR3IRQ);   // mask TMR3 interrupt
00915 
00916     MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, phyRegs, 3);
00917 
00918     PhyIsrPassRxParams(NULL);
00919 
00920     UnprotectFromMCR20Interrupt();
00921 }
00922 
00923 
00924 /*! *********************************************************************************
00925 * \brief  Initialize the 802.15.4 Radio registers
00926 *
00927 ********************************************************************************** */
00928 
00929 void PhyHwInit( void )
00930 {
00931     uint8_t index;
00932     uint8_t phyReg;
00933 
00934     /* Initialize the transceiver SPI driver */
00935     MCR20Drv_Init();
00936     /* Configure the transceiver IRQ_B port */
00937     MCR20Drv_IRQ_PortConfig();
00938     /* Initialize the SPI driver and install PHY ISR */
00939     PHY_InstallIsr();
00940 
00941     //Disable Tristate on COCO MISO for SPI reads
00942     MCR20Drv_IndirectAccessSPIWrite((uint8_t) MISC_PAD_CTRL, (uint8_t) 0x02);
00943 
00944     // PHY_CTRL4 unmask global TRX interrupts, enable 16 bit mode for TC2 - TC2 prime EN
00945     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, (uint8_t) (cPHY_CTRL4_TC2PRIME_EN | \
00946         (gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c)));
00947     
00948     // clear all PP IRQ bits to avoid unexpected interrupts immediately after init, disable all timer interrupts
00949     MCR20Drv_DirectAccessSPIWrite(IRQSTS1,   (uint8_t) (cIRQSTS1_PLL_UNLOCK_IRQ | \
00950                                                         cIRQSTS1_FILTERFAIL_IRQ | \
00951                                                         cIRQSTS1_RXWTRMRKIRQ | \
00952                                                         cIRQSTS1_CCAIRQ | \
00953                                                         cIRQSTS1_RXIRQ | \
00954                                                         cIRQSTS1_TXIRQ | \
00955                                                         cIRQSTS1_SEQIRQ));
00956     
00957     MCR20Drv_DirectAccessSPIWrite(IRQSTS2,   (uint8_t) (cIRQSTS2_ASM_IRQ | \
00958                                                         cIRQSTS2_PB_ERR_IRQ | \
00959                                                         cIRQSTS2_WAKE_IRQ));
00960     
00961     MCR20Drv_DirectAccessSPIWrite(IRQSTS3,   (uint8_t) (cIRQSTS3_TMR4MSK | \
00962                                                         cIRQSTS3_TMR3MSK | \
00963                                                         cIRQSTS3_TMR2MSK | \
00964                                                         cIRQSTS3_TMR1MSK | \
00965                                                         cIRQSTS3_TMR4IRQ | \
00966                                                         cIRQSTS3_TMR3IRQ | \
00967                                                         cIRQSTS3_TMR2IRQ | \
00968                                                         cIRQSTS3_TMR1IRQ));
00969     
00970     //  PHY_CTRL1 default HW settings  + AUTOACK enabled
00971     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, (uint8_t) (cPHY_CTRL1_AUTOACK));
00972     
00973     //  PHY_CTRL2 : disable all interrupts
00974     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, (uint8_t) (cPHY_CTRL2_CRC_MSK | \
00975                                                         cPHY_CTRL2_PLL_UNLOCK_MSK | \
00976                                                         cPHY_CTRL2_FILTERFAIL_MSK | \
00977                                                         cPHY_CTRL2_RX_WMRK_MSK | \
00978                                                         cPHY_CTRL2_CCAMSK | \
00979                                                         cPHY_CTRL2_RXMSK | \
00980                                                         cPHY_CTRL2_TXMSK | \
00981                                                         cPHY_CTRL2_SEQMSK));
00982     
00983     //  PHY_CTRL3 : disable all timers and remaining interrupts
00984     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL3, (uint8_t) (cPHY_CTRL3_ASM_MSK | \
00985                                                         cPHY_CTRL3_PB_ERR_MSK | \
00986                                                         cPHY_CTRL3_WAKE_MSK));
00987     //  SRC_CTRL
00988     MCR20Drv_DirectAccessSPIWrite(SRC_CTRL,  (uint8_t) (cSRC_CTRL_ACK_FRM_PND | \
00989                                                         (cSRC_CTRL_INDEX << cSRC_CTRL_INDEX_Shift_c)));
00990     //  RX_FRAME_FILTER
00991     //  FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others
00992     MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, (uint8_t)(cRX_FRAME_FLT_FRM_VER | \
00993                                                                cRX_FRAME_FLT_BEACON_FT | \
00994                                                                cRX_FRAME_FLT_DATA_FT | \
00995                                                                cRX_FRAME_FLT_CMD_FT ));
00996     // Direct register overwrites
00997     for (index = 0; index < sizeof(overwrites_direct)/sizeof(overwrites_t); index++)
00998         MCR20Drv_DirectAccessSPIWrite(overwrites_direct[index].address, overwrites_direct[index].data);
00999     
01000     // Indirect register overwrites
01001     for (index = 0; index < sizeof(overwrites_indirect)/sizeof(overwrites_t); index++)
01002         MCR20Drv_IndirectAccessSPIWrite(overwrites_indirect[index].address, overwrites_indirect[index].data);
01003     
01004     // Clear HW indirect queue
01005     for( index = 0; index < gPhyIndirectQueueSize_c; index++ )
01006         PhyPp_RemoveFromIndirect( index, 0 );
01007     
01008     PhyPlmeSetCurrentChannelRequest(0x0B, 0); //2405 MHz
01009 #if gMpmIncluded_d
01010     PhyPlmeSetCurrentChannelRequest(0x0B, 1); //2405 MHz
01011     
01012     // Split the HW Indirect hash table in two
01013     PhyPpSetDualPanSamLvl( gPhyIndirectQueueSize_c/2 );
01014 #else
01015     // Assign HW Indirect hash table to PAN0
01016     PhyPpSetDualPanSamLvl( gPhyIndirectQueueSize_c );
01017 #endif
01018 
01019     // set the power level to 0dBm
01020     PhyPlmeSetPwrLevelRequest(0x17);
01021     // set CCA threshold to -75 dBm
01022     PhyPpSetCcaThreshold(0x4B);
01023     // Set prescaller to obtain 1 symbol (16us) timebase
01024     MCR20Drv_IndirectAccessSPIWrite(TMR_PRESCALE, 0x05);
01025     // write default Rx watermark level
01026     MCR20Drv_IndirectAccessSPIWrite(RX_WTR_MARK, 0);
01027 
01028     //Enable the RxWatermark IRQ and FilterFail IRQ
01029     phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL2);
01030     //phyReg &= (uint8_t)~(cPHY_CTRL2_FILTERFAIL_MSK);
01031     phyReg &= (uint8_t)~(cPHY_CTRL2_RX_WMRK_MSK);
01032     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, phyReg);
01033 
01034     /* enable autodoze mode. */
01035     phyReg = MCR20Drv_DirectAccessSPIRead( (uint8_t) PWR_MODES);
01036     phyReg |= (uint8_t) cPWR_MODES_AUTODOZE;
01037     MCR20Drv_DirectAccessSPIWrite( (uint8_t) PWR_MODES, phyReg);
01038     MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d);
01039 
01040     // Clear IRQn Pending Status
01041     MCR20Drv_IRQ_Clear();
01042     //NVIC_ClearPendingIRQ(g_portIrqId[GPIO_EXTRACT_PORT(kGpioXcvrIrqPin)]);
01043     /* enable the transceiver IRQ_B interrupt request */
01044     MCR20Drv_IRQ_Enable();
01045 }
01046 
01047 /*! *********************************************************************************
01048 * \brief  Change the XCVR power state
01049 *
01050 * \param[in]  state  the new XCVR power state
01051 *
01052 * \return  phyStatus_t
01053 *
01054 * \pre Before entering hibernate/reset states, the MCG clock source must be changed
01055 *      to use an input other than the one generated by the XCVR!
01056 *
01057 * \post When XCVR is in hibernate, indirect registers cannot be accessed in burst mode
01058 *       When XCVR is in reset, all registers are inaccessible!
01059 *
01060 * \remarks Putting the XCVR into hibernate/reset will stop the generated clock signal!
01061 *
01062 ********************************************************************************** */
01063 phyStatus_t PhyPlmeSetPwrState( uint8_t state )
01064 {
01065     uint8_t phyPWR, xtalState;
01066 
01067     /* Parameter validation */
01068     if( state > gPhyPwrReset_c )
01069         return gPhyInvalidParameter_c;
01070 
01071     /* Check if the new power state = old power state */
01072     if( state == mPhyPwrState )
01073         return gPhyBusy_c;
01074 
01075     /* Check if the XCVR is in reset power mode */
01076     if( mPhyPwrState == gPhyPwrReset_c )
01077     {
01078         MCR20Drv_RST_B_Deassert();
01079         /* Wait for transceiver to deassert IRQ pin */
01080         while( MCR20Drv_IsIrqPending() );
01081         /* Wait for transceiver wakeup from POR iterrupt */
01082         while( !MCR20Drv_IsIrqPending() );
01083         /* After reset, the radio is in Idle state */
01084         mPhyPwrState = gPhyPwrIdle_c;
01085         /* Restore default radio settings */
01086         PhyHwInit();
01087     }
01088 
01089     if( state != gPhyPwrReset_c )
01090     {
01091         phyPWR = MCR20Drv_DirectAccessSPIRead( PWR_MODES );
01092         xtalState = phyPWR & cPWR_MODES_XTALEN;
01093     }
01094 
01095     switch( state )
01096     {
01097     case gPhyPwrIdle_c:
01098         phyPWR &= ~(cPWR_MODES_AUTODOZE);
01099         phyPWR |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE);
01100         break;
01101 
01102     case gPhyPwrAutodoze_c:
01103         phyPWR |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
01104         break;
01105 
01106     case gPhyPwrDoze_c:
01107         phyPWR &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
01108         phyPWR |= cPWR_MODES_XTALEN;
01109         break;
01110 
01111     case gPhyPwrHibernate_c:
01112         phyPWR &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
01113         break;
01114 
01115     case gPhyPwrReset_c:
01116         MCR20Drv_IRQ_Disable();
01117         mPhyPwrState = gPhyPwrReset_c;
01118         MCR20Drv_RST_B_Assert();
01119         return gPhySuccess_c;
01120     }
01121 
01122     mPhyPwrState = state;
01123     MCR20Drv_DirectAccessSPIWrite( PWR_MODES, phyPWR );
01124 
01125     if( !xtalState && (phyPWR & cPWR_MODES_XTALEN))
01126     {
01127         /* wait for crystal oscillator to complet its warmup */
01128         while( ( MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY ) != cPWR_MODES_XTAL_READY);
01129         /* wait for radio wakeup from hibernate interrupt */
01130         while( ( MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) );
01131 
01132         MCR20Drv_DirectAccessSPIWrite(IRQSTS2, cIRQSTS2_WAKE_IRQ);
01133     }
01134 
01135     return gPhySuccess_c;
01136 }