Igor Stepura / kw41z-rf-driver Featured
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackRfPhyKw41z.cpp Source File

NanostackRfPhyKw41z.cpp

00001 /*
00002    Copyright 2017, Igor Stepura <igor.stepura@gmail.com>
00003 
00004    Inspired by mcr20a-rf-driver by Andrei Kovacs <Andrei.Kovacs@freescale.com>
00005    and NXP KW41Z 802.15.4 PHY implementation
00006 
00007    Licensed under the Apache License, Version 2.0 (the "License");
00008    you may not use this file except in compliance with the License.
00009    You may obtain a copy of the License at
00010 
00011        http://www.apache.org/licenses/LICENSE-2.0
00012 
00013    Unless required by applicable law or agreed to in writing, software
00014    distributed under the License is distributed on an "AS IS" BASIS,
00015    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016    See the License for the specific language governing permissions and
00017    limitations under the License.
00018 */
00019 
00020 #include "NanostackRfPhyKw41z.h"
00021 #include "ns_types.h"
00022 #include "platform/arm_hal_interrupt.h"
00023 #include "nanostack/platform/arm_hal_phy.h"
00024 #include <string.h>
00025 #include "rtos.h"
00026 #include "fsl_xcvr.h "
00027 #include "PhyTypes.h "
00028 
00029 /* PHY states */
00030 typedef enum {
00031   gIdle_c,
00032   gRX_c,
00033   gTX_c,
00034   gCCA_c,
00035   gTR_c,
00036   gCCCA_c,
00037 }phySeqState_t;
00038 
00039 typedef enum{
00040     gPhyPwrRun_c,
00041     gPhyPwrDSM_c,
00042 }phyPwrMode_t;
00043 
00044 /* PHY channel state */
00045 enum {
00046   gChannelIdle_c,
00047   gChannelBusy_c
00048 };
00049 
00050 enum {
00051   gMacRole_DeviceOrCoord_c,
00052   gMacRole_PanCoord_c
00053 };
00054 
00055 /* Cca types */
00056 enum {
00057   gCcaED_c,            /* energy detect - CCA bit not active, not to be used for T and CCCA sequences */
00058   gCcaCCA_MODE1_c,     /* energy detect - CCA bit ACTIVE */
00059   gCcaCCA_MODE2_c,     /* 802.15.4 compliant signal detect - CCA bit ACTIVE */
00060   gCcaCCA_MODE3_c,     /* 802.15.4 compliant signal detect and energy detect - CCA bit ACTIVE */
00061   gInvalidCcaType_c    /* illegal type */
00062 };
00063 
00064 static phyPwrMode_t mPhyPwrState = gPhyPwrRun_c;
00065 #ifndef MBED_CONF_KW41Z_RF_LONG_MAC_ADDRESS
00066 #define MBED_CONF_KW41Z_RF_LONG_MAC_ADDRESS  {1, 2, 3, 4, 5, 6, 7, 8}
00067 #endif
00068 
00069 #ifndef MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL
00070 #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL (12)
00071 #endif
00072 
00073 static uint8_t MAC_address[8] = MBED_CONF_KW41Z_RF_LONG_MAC_ADDRESS;
00074 static NanostackRfPhyKw41z *rf = NULL;
00075 
00076 #ifdef MBED_CONF_RTOS_PRESENT
00077 static Thread irq_thread(osPriorityRealtime, 1024);
00078 #endif
00079 
00080 static phy_device_driver_s device_driver;
00081 static int8_t  rf_radio_driver_id = -1;
00082 static uint8_t  mac_tx_handle = 0;
00083 
00084 static uint8_t rf_phy_channel = 0;
00085 static uint8_t  need_ack = 0;
00086 
00087 #define RF_BUFFER_SIZE 128
00088 /*RF receive buffer*/
00089 static uint8_t rf_buffer[RF_BUFFER_SIZE];
00090 
00091 /* Channel configurations for 2.4 */
00092 static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
00093 
00094 static const phy_device_channel_page_s phy_channel_pages[] = {
00095         { CHANNEL_PAGE_0, &phy_24ghz},
00096         { CHANNEL_PAGE_0, NULL}
00097 };
00098 /* Set the default power level to 0dBm */
00099 #ifndef gPhyDefaultTxPowerLevel_d
00100 #define gPhyDefaultTxPowerLevel_d     (22)
00101 #endif
00102 #define CORE_CLOCK_FREQ 47972352U
00103 #define gPhyMaxTxPowerLevel_d         (32)
00104 
00105 #define ZLL_IRQSTS_TMRMSK_MASK  (ZLL_IRQSTS_TMR1MSK_MASK | \
00106                                       ZLL_IRQSTS_TMR2MSK_MASK | \
00107                                       ZLL_IRQSTS_TMR3MSK_MASK | \
00108                                       ZLL_IRQSTS_TMR4MSK_MASK )
00109 
00110 uint8_t gPhyChannelTxPowerLimits[] = { gPhyMaxTxPowerLevel_d,   /* 11 */ \
00111                                  gPhyMaxTxPowerLevel_d,   /* 12 */ \
00112                                  gPhyMaxTxPowerLevel_d,   /* 13 */ \
00113                                  gPhyMaxTxPowerLevel_d,   /* 14 */ \
00114                                  gPhyMaxTxPowerLevel_d,   /* 15 */ \
00115                                  gPhyMaxTxPowerLevel_d,   /* 16 */ \
00116                                  gPhyMaxTxPowerLevel_d,   /* 17 */ \
00117                                  gPhyMaxTxPowerLevel_d,   /* 18 */ \
00118                                  gPhyMaxTxPowerLevel_d,   /* 19 */ \
00119                                  gPhyMaxTxPowerLevel_d,   /* 20 */ \
00120                                  gPhyMaxTxPowerLevel_d,   /* 21 */ \
00121                                  gPhyMaxTxPowerLevel_d,   /* 22 */ \
00122                                  gPhyMaxTxPowerLevel_d,   /* 23 */ \
00123                                  gPhyMaxTxPowerLevel_d,   /* 24 */ \
00124                                  gPhyMaxTxPowerLevel_d,   /* 25 */ \
00125                                  gPhyMaxTxPowerLevel_d };  /* 26 */
00126 
00127 
00128 
00129 MBED_UNUSED static void rf_init(void);
00130 MBED_UNUSED static int8_t rf_device_register(void);
00131 MBED_UNUSED static void rf_device_unregister(void);
00132 MBED_UNUSED static int8_t  rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
00133 MBED_UNUSED static int8_t  rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr);
00134 MBED_UNUSED static int8_t  rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr);
00135 MBED_UNUSED static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol );
00136 MBED_UNUSED static void    rf_abort(void);
00137 MBED_UNUSED static void    rf_promiscuous(uint8_t mode);
00138 MBED_UNUSED static void rf_receive(void);
00139 MBED_UNUSED static void rf_mac64_read(uint8_t *address);
00140 MBED_UNUSED static void    rf_set_power_state(phyPwrMode_t newState);
00141 MBED_UNUSED static void rf_handle_tx_end(uint8_t);
00142 static void rf_set_timeout(uint32_t timeout);
00143 static inline uint32_t rf_get_timestamp(void);
00144 static void rf_set_address(uint8_t *address);
00145 static uint8_t rf_detect_channel_energy(void);
00146 
00147 static inline phySeqState_t rf_get_state(void)
00148 {
00149     return (phySeqState_t)(((ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK) >> ZLL_PHY_CTRL_XCVSEQ_SHIFT));
00150 } 
00151 
00152 
00153 static void PHY_InterruptHandler(void);
00154 static void PHY_InterruptThread(void);
00155 static void handle_interrupt(uint32_t irqStatus);
00156 
00157 static void rf_if_lock(void)
00158 {
00159     platform_enter_critical();
00160 }
00161 
00162 static void rf_if_unlock(void)
00163 {
00164     platform_exit_critical();
00165 }
00166 
00167 static void rf_set_power_level( uint8_t pwrStep)
00168 {
00169     /* Do not exceed the Tx power limit for the current channel */
00170     if( pwrStep > gPhyChannelTxPowerLimits[ZLL->CHANNEL_NUM0 - 11] )
00171     {
00172         pwrStep = gPhyChannelTxPowerLimits[ZLL->CHANNEL_NUM0 - 11];
00173     }
00174     if( pwrStep > 2 )
00175     {
00176         pwrStep = (pwrStep << 1) - 2;
00177     }
00178 
00179     ZLL->PA_PWR = pwrStep;
00180 }
00181 
00182 static uint8_t rf_get_power_level(void)
00183 {
00184     uint8_t pwrStep = (uint8_t)ZLL->PA_PWR;
00185 
00186     if( pwrStep > 2 )
00187     {
00188         pwrStep = (pwrStep + 2) >> 1;
00189     }
00190     
00191     return pwrStep;
00192 }
00193 
00194 #define gPhyIrqNo_d           (Radio_1_IRQn)
00195 static void PHY_InstallIsr()
00196 {
00197     NVIC_SetVector(gPhyIrqNo_d, (uint32_t)&PHY_InterruptHandler);
00198     NVIC_ClearPendingIRQ(gPhyIrqNo_d);
00199     NVIC_EnableIRQ(gPhyIrqNo_d);    
00200 }
00201 
00202 static void rf_channel_set(uint8_t channel)
00203 {
00204     rf_phy_channel = channel;
00205 
00206     ZLL->CHANNEL_NUM0 = channel;
00207 
00208     if( rf_get_power_level() > gPhyChannelTxPowerLimits[channel - 11] )
00209     {
00210         rf_set_power_level(gPhyChannelTxPowerLimits[channel - 11]);
00211     }
00212 }
00213 
00214 static inline uint32_t rf_get_timestamp(void)
00215 {
00216     uint32_t retval = ZLL->EVENT_TMR >> ZLL_EVENT_TMR_EVENT_TMR_SHIFT;
00217 
00218     return retval;
00219 }
00220 
00221 static void rf_set_timeout(uint32_t timeout)
00222 {
00223     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK;
00224     ZLL->T3CMP = timeout & 0x00FFFFFF;
00225 
00226     uint32_t sts = ZLL->IRQSTS & ZLL_IRQSTS_TMRMSK_MASK;
00227     sts &= ~(ZLL_IRQSTS_TMR3MSK_MASK);
00228     sts |= ZLL_IRQSTS_TMR3IRQ_MASK;
00229     ZLL->IRQSTS = sts;
00230 
00231     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TMR3CMP_EN_MASK;
00232     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_TC3TMOUT_MASK;
00233 }
00234 
00235 static uint8_t rf_detect_channel_energy(void)
00236 {
00237     if (rf_get_state() !=gIdle_c)
00238     {
00239         return 0;
00240     }
00241     rf_set_power_state(gPhyPwrRun_c);
00242 
00243     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_CCATYPE_MASK;
00244     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK |
00245                      ZLL_PHY_CTRL_RXMSK_MASK  |
00246                      ZLL_PHY_CTRL_TXMSK_MASK  |
00247                      ZLL_PHY_CTRL_SEQMSK_MASK;
00248 
00249     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCATYPE(gCcaED_c);
00250 
00251     ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
00252     ZLL->PHY_CTRL |= gCCA_c;
00253 
00254     /* Busy wait. No interrupt will be raised */
00255     while (!(ZLL->IRQSTS & ZLL_IRQSTS_SEQIRQ_MASK)){}
00256     ZLL->IRQSTS = ZLL->IRQSTS;
00257     ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
00258 
00259     int8_t caa1_ed_fnl = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_CCA1_ED_FNL_MASK) >> ZLL_LQI_AND_RSSI_CCA1_ED_FNL_SHIFT;
00260 
00261     return 128 + caa1_ed_fnl;
00262 }
00263 
00264 static void rf_init(void)
00265 {
00266     uint32_t phyReg;
00267     XCVR_Init( ZIGBEE_MODE, DR_500KBPS );
00268     
00269     XCVR_SetXtalTrim(0x30);
00270     
00271     /* Enable 16 bit mode for TC2 - TC2 prime EN, disable all timers,
00272        enable AUTOACK, mask all interrupts */
00273     ZLL->PHY_CTRL = (gCcaCCA_MODE1_c << ZLL_PHY_CTRL_CCATYPE_SHIFT) |
00274                    ZLL_PHY_CTRL_TC2PRIME_EN_MASK    |
00275                    ZLL_PHY_CTRL_TSM_MSK_MASK        |
00276                    ZLL_PHY_CTRL_WAKE_MSK_MASK       |
00277                    ZLL_PHY_CTRL_CRC_MSK_MASK        |
00278                    ZLL_PHY_CTRL_PLL_UNLOCK_MSK_MASK |
00279                    ZLL_PHY_CTRL_FILTERFAIL_MSK_MASK |
00280                    ZLL_PHY_CTRL_RX_WMRK_MSK_MASK    |
00281                    ZLL_PHY_CTRL_CCAMSK_MASK         |
00282                    ZLL_PHY_CTRL_RXMSK_MASK          |
00283                    ZLL_PHY_CTRL_TXMSK_MASK          |
00284                    ZLL_PHY_CTRL_SEQMSK_MASK         |
00285                    ZLL_PHY_CTRL_AUTOACK_MASK        |
00286                    ZLL_PHY_CTRL_TRCV_MSK_MASK;
00287 
00288     /* Clear all PP IRQ bits to avoid unexpected interrupts immediately after init
00289        disable all timer interrupts */
00290     ZLL->IRQSTS = ZLL->IRQSTS;
00291 
00292     /* Enable Source Addresing Match module */
00293     ZLL->SAM_CTRL |= ZLL_SAM_CTRL_SAP0_EN_MASK;
00294 
00295     /* Clear HW indirect queue */
00296     ZLL->SAM_TABLE |= ZLL_SAM_TABLE_INVALIDATE_ALL_MASK;
00297 
00298     /*  Frame Filtering
00299         FRM_VER[7:6] = b11. Accept FrameVersion 0 and 1 packets, reject all others */
00300     ZLL->RX_FRAME_FILTER &= ~ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK;
00301     ZLL->RX_FRAME_FILTER = ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3) |
00302                            ZLL_RX_FRAME_FILTER_CMD_FT_MASK  |
00303                            ZLL_RX_FRAME_FILTER_DATA_FT_MASK |
00304                            ZLL_RX_FRAME_FILTER_BEACON_FT_MASK;
00305 
00306     /* Set prescaller to obtain 1 symbol (16us) timebase */
00307     ZLL->TMR_PRESCALE = 0x05;
00308 
00309     /* Set CCA threshold to -75 dBm */
00310     ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_CCA1_THRESH_MASK;
00311     ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_CCA1_THRESH(0xB5);
00312 
00313     /* Set the default power level */
00314     rf_set_power_level(gPhyDefaultTxPowerLevel_d);
00315 
00316     /* Adjust ACK delay to fulfill the 802.15.4 turnaround requirements */
00317     ZLL->ACKDELAY &= ~ZLL_ACKDELAY_ACKDELAY_MASK;
00318     ZLL->ACKDELAY |= ZLL_ACKDELAY_ACKDELAY(-8);
00319     
00320     /* Adjust LQI compensation */
00321     ZLL->CCA_LQI_CTRL &= ~ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP_MASK;
00322     ZLL->CCA_LQI_CTRL |= ZLL_CCA_LQI_CTRL_LQI_OFFSET_COMP(96);
00323 
00324     /* Enable the RxWatermark IRQ and FilterFail IRQ */
00325     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RX_WMRK_MSK_MASK;
00326     /* Set Rx watermark level */
00327     ZLL->RX_WTR_MARK = 0;
00328 
00329     rf_channel_set(MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL);
00330     
00331     /* DSM settings */
00332     phyReg = (RSIM->RF_OSC_CTRL & RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_MASK) >> 
00333              RSIM_RF_OSC_CTRL_BB_XTAL_READY_COUNT_SEL_SHIFT;
00334     phyReg = (1024U << phyReg) / (CORE_CLOCK_FREQ / 32768) + 1;
00335     RSIM->DSM_OSC_OFFSET = phyReg;
00336 
00337     /* Install PHY ISR */
00338     PHY_InstallIsr();
00339     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TRCV_MSK_MASK;
00340 
00341     rf_receive();    
00342 }
00343 
00344 static void rf_mac64_read(uint8_t *address)
00345 {
00346     uint64_t val = ZLL->MACLONGADDRS0_MSB;
00347     val <<= 32;
00348     val |= ZLL->MACLONGADDRS0_LSB;
00349 
00350     *((uint64_t*)address) = val;
00351 }
00352 
00353 static void rf_promiscuous(uint8_t state)
00354 {
00355     if( state )
00356     {
00357         ZLL->PHY_CTRL |= ZLL_PHY_CTRL_PROMISCUOUS_MASK;
00358         /* FRM_VER[11:8] = b1111. Any FrameVersion accepted */
00359         ZLL->RX_FRAME_FILTER |= (ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK |
00360                                  ZLL_RX_FRAME_FILTER_ACK_FT_MASK |
00361                                  ZLL_RX_FRAME_FILTER_NS_FT_MASK);
00362     }
00363     else
00364     {
00365         ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_PROMISCUOUS_MASK;
00366         /* FRM_VER[11:8] = b0011. Accept FrameVersion 0 and 1 packets, reject all others */
00367         /* Beacon, Data and MAC command frame types accepted */
00368         ZLL->RX_FRAME_FILTER &= ~(ZLL_RX_FRAME_FILTER_FRM_VER_FILTER_MASK |
00369                                  ZLL_RX_FRAME_FILTER_ACK_FT_MASK  |
00370                                  ZLL_RX_FRAME_FILTER_NS_FT_MASK   |
00371                                  ZLL_RX_FRAME_FILTER_ACTIVE_PROMISCUOUS_MASK);
00372         ZLL->RX_FRAME_FILTER |= ZLL_RX_FRAME_FILTER_FRM_VER_FILTER(3);
00373     }    
00374 }
00375 
00376 static void rf_receive(void)
00377 {
00378     uint32_t irqSts;
00379     /* RX can start only from Idle state */
00380     if( rf_get_state() != gIdle_c )
00381     {
00382         return;
00383     }
00384     rf_set_power_state(gPhyPwrRun_c);
00385 
00386     irqSts = ZLL->IRQSTS;
00387     irqSts |= ZLL_IRQSTS_TMR3MSK_MASK;
00388     ZLL->IRQSTS = irqSts;
00389 
00390     ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
00391     ZLL->PHY_CTRL |= gRX_c ;
00392     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;
00393 }
00394 
00395 static int8_t rf_device_register(void)
00396 {
00397 
00398     rf_init();
00399 
00400     /*Set pointer to MAC address*/
00401     device_driver.PHY_MAC = MAC_address;
00402     device_driver.driver_description = (char*)"NXP_KWx";
00403 
00404     //Create setup Used Radio chips
00405     /*Type of RF PHY is SubGHz*/
00406     device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
00407 
00408     device_driver.phy_channel_pages = phy_channel_pages;
00409     /*Maximum size of payload is 127*/
00410     device_driver.phy_MTU = 127;
00411     /*No header in PHY*/
00412     device_driver.phy_header_length = 0;
00413     /*No tail in PHY*/
00414     device_driver.phy_tail_length = 0;
00415     /*Set address write function*/
00416     device_driver.address_write = &rf_address_write;
00417     /*Set RF extension function*/
00418     device_driver.extension = &rf_extension;
00419     /*Set RF state control function*/
00420     device_driver.state_control = &rf_interface_state_control;
00421     /*Set transmit function*/
00422     device_driver.tx = &rf_start_cca;
00423     /*Upper layer callbacks init to NULL*/
00424     device_driver.phy_rx_cb = NULL;
00425     device_driver.phy_tx_done_cb = NULL;
00426     /*Virtual upper data callback init to NULL*/
00427     device_driver.arm_net_virtual_rx_cb = NULL;
00428     device_driver.arm_net_virtual_tx_cb = NULL;
00429 
00430     /*Register device driver*/
00431     rf_radio_driver_id = arm_net_phy_register(&device_driver);
00432 
00433     return rf_radio_driver_id;
00434 }
00435 
00436 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol )
00437 {
00438     if( rf_get_state() == gRX_c )
00439     {
00440         uint8_t phyReg = (ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK);
00441         /* Check for an Rx in progress. */
00442         if((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16))
00443         {
00444             if (device_driver.phy_tx_done_cb) {
00445                 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
00446             }
00447             return -1;
00448         }
00449         rf_abort();
00450     }    
00451     uint8_t* pPB = (uint8_t*)ZLL->PKT_BUFFER_TX;
00452     pPB[0] = data_length + 2; /* including 2 bytes of FCS */
00453     memcpy(&pPB[1], data_ptr, data_length);
00454 
00455     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCABFRTX_MASK;
00456     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_CCATYPE_MASK;
00457     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCATYPE(gCcaCCA_MODE1_c);
00458 
00459     ZLL->IRQSTS = ZLL->IRQSTS;
00460 
00461     mac_tx_handle = tx_handle;
00462     need_ack = (*data_ptr & 0x20) == 0x20;
00463 
00464     /* Set XCVR power state in run mode */
00465     rf_set_power_state(gPhyPwrRun_c);
00466 
00467     uint8_t xcvseq;    
00468     if(need_ack)
00469     {
00470         ZLL->PHY_CTRL |= ZLL_PHY_CTRL_RXACKRQD_MASK;
00471         xcvseq = gTR_c;
00472     }
00473     else
00474     {
00475         ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_RXACKRQD_MASK;
00476         xcvseq = gTX_c;        
00477 
00478         uint32_t timeout = rf_get_timestamp();
00479         timeout += ((XCVR_TSM->END_OF_SEQ & XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_MASK) >> XCVR_TSM_END_OF_SEQ_END_OF_TX_WU_SHIFT) >> 4;
00480         timeout += 50; /* Maigic numbers are the best!! */
00481 
00482         rf_set_timeout(timeout);
00483     }    
00484     ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_XCVSEQ_MASK);
00485     ZLL->PHY_CTRL |= xcvseq;
00486     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;    
00487 
00488     return 0;
00489 }
00490 
00491 static void rf_set_short_adr(uint8_t * short_address)
00492 {
00493     uint16_t value = ((uint16_t)short_address[0] << 8) | (uint16_t)short_address[1];
00494     ZLL->MACSHORTADDRS0 &= ~ZLL_MACSHORTADDRS0_MACSHORTADDRS0_MASK;
00495     ZLL->MACSHORTADDRS0 |= ZLL_MACSHORTADDRS0_MACSHORTADDRS0(value);    
00496 }
00497 
00498 static void rf_set_pan_id(uint8_t *pan_id)
00499 {
00500     uint16_t value = ((uint16_t)pan_id[0] << 8) | (uint16_t)pan_id[1];
00501     ZLL->MACSHORTADDRS0 &= ~ZLL_MACSHORTADDRS0_MACPANID0_MASK;
00502     ZLL->MACSHORTADDRS0 |= ZLL_MACSHORTADDRS0_MACPANID0(value);
00503 }
00504 
00505 #define TO_UINT32(ptr, num) do {\
00506     num = (((uint32_t)(ptr)[0] << 24) |\
00507            ((uint32_t)(ptr)[1] << 16) |\
00508            ((uint32_t)(ptr)[2] << 8) |\
00509            ((uint32_t)(ptr)[3])); \
00510 }while(0)
00511 
00512 static void rf_set_address(uint8_t *address)
00513 {
00514     uint32_t addrLo;
00515     uint32_t addrHi;    
00516 
00517     TO_UINT32(address, addrHi);
00518     TO_UINT32(address + 4, addrLo);
00519 
00520     ZLL->MACLONGADDRS0_LSB = addrLo;
00521     ZLL->MACLONGADDRS0_MSB = addrHi;    
00522 } 
00523 
00524 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
00525 {
00526     int8_t ret_val = 0;
00527     switch (address_type)
00528     {
00529         /*Set 48-bit address*/
00530         case PHY_MAC_48BIT:
00531             break;
00532             /*Set 64-bit address*/
00533         case PHY_MAC_64BIT:
00534             rf_set_address(address_ptr);
00535             break;
00536         /*Set 16-bit address*/
00537         case PHY_MAC_16BIT:
00538             rf_set_short_adr(address_ptr);
00539             break;
00540         /*Set PAN Id*/
00541         case PHY_MAC_PANID:
00542             rf_set_pan_id(address_ptr);
00543             break;
00544     }
00545     return ret_val;
00546 }
00547 
00548 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
00549 {
00550     uint32_t type = (uint32_t)extension_type;
00551     switch (type)
00552     {
00553         /*Return frame pending status*/
00554         case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
00555             *data_ptr = ((ZLL->IRQSTS & ZLL_IRQSTS_RX_FRM_PEND_MASK) >> ZLL_IRQSTS_RX_FRM_PEND_SHIFT);
00556             break;        
00557         case PHY_EXTENSION_SET_CHANNEL:
00558             rf_channel_set(*data_ptr);
00559             break;
00560         case PHY_EXTENSION_READ_CHANNEL_ENERGY:
00561             *data_ptr = rf_detect_channel_energy();
00562             break;            
00563     }    
00564     return 0;
00565 }
00566 
00567 #define mPhyDSM_GuardTime_d         (5) /* DSM_TIME ticks (32.768KHz) */
00568 static uint32_t mPhyDSMDuration = 0xFFFFF0;
00569 static void rf_set_power_state(phyPwrMode_t newState)
00570 {
00571     if( newState == mPhyPwrState )
00572     {
00573         return;
00574     }
00575     else
00576     {
00577         switch(newState)
00578         {
00579             case gPhyPwrRun_c:
00580                 /* Set XCVR in run mode if not allready */
00581                 if(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK)
00582                 {
00583                     RSIM->ZIG_WAKE = (RSIM->DSM_TIMER + mPhyDSM_GuardTime_d);
00584                     while(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK);
00585                 }
00586                 break;
00587 
00588             case gPhyPwrDSM_c:
00589                 /* Set XCVR in low power mode if not allready */
00590                 if(!(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_DEEP_SLEEP_STATUS_MASK))
00591                 {
00592                     uint32_t minTime = (RSIM->DSM_OSC_OFFSET > mPhyDSM_GuardTime_d) ? RSIM->DSM_OSC_OFFSET : mPhyDSM_GuardTime_d;
00593 
00594                     RSIM->ZIG_SLEEP = RSIM->DSM_TIMER + minTime;
00595                     RSIM->ZIG_WAKE = RSIM->DSM_TIMER + mPhyDSMDuration;
00596                     RSIM->DSM_CONTROL |= RSIM_DSM_CONTROL_ZIG_SYSCLK_REQUEST_EN_MASK |
00597                         RSIM_DSM_CONTROL_DSM_TIMER_EN_MASK | 
00598                         RSIM_DSM_CONTROL_ZIG_SYSCLK_INTERRUPT_EN_MASK;
00599                 }
00600                 break;
00601         }
00602 
00603         mPhyPwrState = newState;
00604     }
00605 }
00606 
00607 static void rf_off(void)
00608 {
00609     rf_abort();
00610     rf_set_power_state(gPhyPwrDSM_c);
00611 }
00612 
00613 static void rf_shutdown(void)
00614 {
00615     rf_off();
00616 }
00617 
00618 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
00619 {
00620     int8_t ret_val = 0;
00621     switch (new_state)
00622     {
00623         /*Reset PHY driver and set to idle*/
00624         case PHY_INTERFACE_RESET:
00625             break;
00626         /*Disable PHY Interface driver*/
00627         case PHY_INTERFACE_DOWN:
00628             rf_shutdown();
00629             break;
00630         /*Enable PHY Interface driver*/
00631         case PHY_INTERFACE_UP:
00632             rf_channel_set(rf_channel);
00633             rf_receive();
00634             break;
00635         /*Enable wireless interface ED scan mode*/
00636         case PHY_INTERFACE_RX_ENERGY_STATE:
00637             rf_abort();
00638             rf_channel_set(rf_channel);
00639             break;
00640         case PHY_INTERFACE_SNIFFER_STATE:             /**< Enable Sniffer state */
00641             rf_promiscuous(1);
00642             rf_channel_set(rf_channel);
00643             rf_receive();
00644             break;
00645     }
00646     return ret_val;
00647 }
00648 
00649 static void rf_device_unregister(void)
00650 {
00651     arm_net_phy_unregister(rf_radio_driver_id);
00652 }
00653 
00654 static void rf_abort(void)
00655 {
00656     /* Mask SEQ interrupt */
00657     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_SEQMSK_MASK;
00658     /* Disable timer trigger (for scheduled XCVSEQ) */
00659     if( ZLL->PHY_CTRL & ZLL_PHY_CTRL_TMRTRIGEN_MASK )
00660     {
00661         ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMRTRIGEN_MASK;
00662         /* give the FSM enough time to start if it was triggered */
00663         while( (XCVR_MISC->XCVR_CTRL & XCVR_CTRL_XCVR_STATUS_TSM_COUNT_MASK) == 0) {}
00664     }
00665 
00666     /* If XCVR is not idle, abort current SEQ */
00667     if( ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK )
00668     {
00669         ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
00670         /* wait for Sequence Idle (if not already) */
00671         while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
00672     }
00673 
00674     /* Stop timers */
00675     ZLL->PHY_CTRL &= ~(ZLL_PHY_CTRL_TMR2CMP_EN_MASK |
00676             ZLL_PHY_CTRL_TMR3CMP_EN_MASK |
00677             ZLL_PHY_CTRL_TC3TMOUT_MASK );
00678     ZLL->IRQSTS &= ~(ZLL_IRQSTS_TMR1IRQ_MASK | ZLL_IRQSTS_TMR4IRQ_MASK);
00679 }
00680 
00681 
00682 static volatile uint32_t gIrqStatus = 0;
00683 static void PHY_InterruptHandler(void)
00684 {
00685     gIrqStatus = ZLL->IRQSTS;
00686     ZLL->IRQSTS = gIrqStatus;
00687 #ifdef MBED_CONF_RTOS_PRESENT
00688     irq_thread.signal_set(1);
00689 #else
00690     handle_interrupt(gIrqStatus);
00691 #endif
00692 
00693 }
00694 
00695 static void PHY_InterruptThread(void)
00696 {
00697 #ifdef MBED_CONF_RTOS_PRESENT
00698     for (;;) {
00699         osEvent event = irq_thread.signal_wait(0);
00700         if (event.status != osEventSignal) {
00701             continue;
00702         }
00703         handle_interrupt(gIrqStatus);
00704 
00705     }
00706 #endif
00707 }
00708 
00709 static inline void rf_clean_seq_isr(void)
00710 {
00711     uint32_t irqStatus;
00712 
00713     /* Set the PHY sequencer back to IDLE */
00714     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
00715     /* Mask SEQ, RX, TX and CCA interrupts */
00716     ZLL->PHY_CTRL |= ZLL_PHY_CTRL_CCAMSK_MASK |
00717                      ZLL_PHY_CTRL_RXMSK_MASK  |
00718                      ZLL_PHY_CTRL_TXMSK_MASK  |
00719                      ZLL_PHY_CTRL_SEQMSK_MASK;
00720 
00721     while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
00722 
00723     irqStatus = ZLL->IRQSTS;
00724     irqStatus |= ZLL_IRQSTS_TMR3MSK_MASK;
00725     irqStatus &= ~( ZLL_IRQSTS_TMR1IRQ_MASK |
00726                     ZLL_IRQSTS_TMR2IRQ_MASK |
00727                     ZLL_IRQSTS_TMR3IRQ_MASK |
00728                     ZLL_IRQSTS_TMR4IRQ_MASK );
00729     ZLL->IRQSTS = irqStatus;
00730 }
00731 
00732 static inline uint8_t rf_convert_lqi(uint8_t rssi)
00733 {
00734     if (rssi >= 220)
00735     {
00736         rssi = 255;
00737     }
00738     else
00739     {
00740         rssi = (51 * rssi) / 44;
00741     }
00742 
00743     return rssi;
00744 }
00745 
00746 static inline int8_t rf_lqi_to_rssi(uint8_t lqi)
00747 {
00748     /* As per NXP's PHY implemenation */
00749     int32_t rssi = (36 * lqi - 9836) / 109;
00750 
00751     return (int8_t)rssi;
00752 }
00753 
00754 static void rf_handle_rx_end(void)
00755 {
00756     uint32_t irqSts;
00757 
00758     /* disable TMR3 compare */
00759     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK;
00760     /* disable autosequence stop by TC3 match */
00761     ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TC3TMOUT_MASK;
00762     /* mask TMR3 interrupt (do not change other IRQ status) */
00763     irqSts  = ZLL->IRQSTS & ZLL_IRQSTS_TMR3MSK_MASK;
00764     irqSts |= ZLL_IRQSTS_TMR3MSK_MASK;
00765     /* aknowledge TMR3 IRQ */
00766     irqSts |= ZLL_IRQSTS_TMR3IRQ_MASK;
00767     ZLL->IRQSTS = irqSts;
00768 
00769     uint8_t phyRssi = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >> ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT;
00770     uint8_t lqi = rf_convert_lqi(phyRssi);
00771     int8_t  rssi = rf_lqi_to_rssi(lqi);
00772 
00773     uint8_t psduLength = (ZLL->IRQSTS & ZLL_IRQSTS_RX_FRAME_LENGTH_MASK) >> ZLL_IRQSTS_RX_FRAME_LENGTH_SHIFT; /* Including FCS (2 bytes) */
00774     uint8_t len = psduLength - 2;
00775 
00776     rf_receive();
00777     if (psduLength > 0 )
00778     {
00779         for (uint8_t i = 0; i < len; i++)
00780         {
00781             rf_buffer[i] = ((uint8_t*)ZLL->PKT_BUFFER_RX)[i];
00782         }
00783 
00784         if (device_driver.phy_rx_cb) {
00785             device_driver.phy_rx_cb(rf_buffer, len, lqi, rssi, rf_radio_driver_id);
00786         }
00787     }
00788 
00789 }
00790 
00791 static void handle_interrupt(uint32_t irqStatus)
00792 {
00793      /* RSIM Wake-up IRQ */
00794     if(RSIM->DSM_CONTROL & RSIM_DSM_CONTROL_ZIG_SYSCLK_REQ_INT_MASK)
00795     {
00796         RSIM->DSM_CONTROL = RSIM->DSM_CONTROL;
00797         return;
00798     }
00799 
00800     /* Read current XCVRSEQ and interrup status */
00801     uint32_t xcvseqCopy = ZLL->PHY_CTRL & ZLL_PHY_CTRL_XCVSEQ_MASK;
00802 
00803     /* WAKE IRQ */
00804     if( irqStatus & ZLL_IRQSTS_WAKE_IRQ_MASK )
00805     {
00806         uint32_t timeAdjust = RSIM->ZIG_WAKE;
00807         /* Adjust the 802.15.4 EVENT_TMR */
00808         timeAdjust = (timeAdjust - RSIM->ZIG_SLEEP)/32768U * 1000000U; /* [us] */
00809         ZLL->EVENT_TMR = (timeAdjust << 4) | ZLL_EVENT_TMR_EVENT_TMR_ADD_MASK;
00810     }
00811 
00812     if( (!(ZLL->PHY_CTRL & ZLL_PHY_CTRL_SEQMSK_MASK)) && (irqStatus & ZLL_IRQSTS_SEQIRQ_MASK) )
00813     {
00814         if( irqStatus & ZLL_IRQSTS_PLL_UNLOCK_IRQ_MASK )
00815         {
00816             rf_clean_seq_isr();
00817         }
00818         /* TMR3 timeout, the autosequence has been aborted due to TMR3 timeout */
00819         else if( (irqStatus & ZLL_IRQSTS_TMR3IRQ_MASK) &&
00820             (!(irqStatus & ZLL_IRQSTS_RXIRQ_MASK)) &&
00821             (gTX_c != xcvseqCopy) )
00822         {
00823             ZLL->IRQSTS = irqStatus | ZLL_IRQSTS_TMR3MSK_MASK;
00824             ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_TMR3CMP_EN_MASK;
00825 
00826             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 1);
00827         }
00828         else
00829         {
00830             rf_clean_seq_isr();
00831             switch(xcvseqCopy)
00832             {
00833                 case gTX_c:
00834                     if( (ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCABFRTX_MASK) && (irqStatus & ZLL_IRQSTS_CCA_MASK ) )
00835                     {
00836                         device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
00837                     }
00838                     else
00839                     {
00840                         ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_XCVSEQ_MASK;
00841                         ZLL->PHY_CTRL |= (ZLL_PHY_CTRL_CCAMSK_MASK |
00842                                 ZLL_PHY_CTRL_RXMSK_MASK |
00843                                 ZLL_PHY_CTRL_TXMSK_MASK |
00844                                 ZLL_PHY_CTRL_SEQMSK_MASK);
00845                         while( ZLL->SEQ_STATE & ZLL_SEQ_STATE_SEQ_STATE_MASK ) {}
00846                         rf_handle_tx_end(0);
00847                     }
00848                     break;
00849 
00850                 case gTR_c:
00851                     if( (ZLL->PHY_CTRL & ZLL_PHY_CTRL_CCABFRTX_MASK) && (irqStatus & ZLL_IRQSTS_CCA_MASK ) )
00852                     {
00853                         device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
00854                     }
00855                     else
00856                     {
00857                         rf_handle_tx_end((irqStatus & ZLL_IRQSTS_RX_FRM_PEND_MASK) > 0);
00858 
00859                     }
00860                     break;
00861 
00862                 case gRX_c:
00863                     rf_handle_rx_end();
00864                     break;
00865                 default:
00866                     break;
00867             }
00868         }
00869     }
00870 }
00871 
00872 static void rf_handle_tx_end(uint8_t rx_frame_pending)
00873 {
00874     rf_receive();
00875 
00876     if (!device_driver.phy_tx_done_cb) {
00877         return;
00878     }
00879     if( need_ack )
00880     {
00881         if( rx_frame_pending )
00882         {
00883             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE_PENDING, 1, 1);
00884         }
00885         else
00886         {
00887             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1);
00888         }
00889     }
00890     else
00891     {
00892         device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
00893     }
00894 
00895 
00896 }
00897 
00898 NanostackRfPhyKw41z::NanostackRfPhyKw41z()
00899 {
00900 }
00901 
00902 NanostackRfPhyKw41z::~NanostackRfPhyKw41z()
00903 {
00904 }
00905 
00906 int8_t NanostackRfPhyKw41z::rf_register()
00907 {
00908 
00909     rf_if_lock();
00910 
00911     if (rf != NULL) {
00912         rf_if_unlock();
00913         error("Multiple registrations of NanostackRfPhyKw41z not supported");
00914         return -1;
00915     }
00916 
00917 #ifdef MBED_CONF_RTOS_PRESENT
00918     irq_thread.start(mbed::callback(PHY_InterruptThread));
00919 #endif
00920 
00921     int8_t radio_id = rf_device_register();
00922     if (radio_id < 0) {
00923         rf = NULL;
00924     }
00925 
00926     rf_if_unlock();
00927     return radio_id;
00928 }
00929 
00930 void NanostackRfPhyKw41z::rf_unregister()
00931 {
00932     rf_if_lock();
00933 
00934     if (rf != this) {
00935         rf_if_unlock();
00936         return;
00937     }
00938 
00939     rf_device_unregister();
00940     rf = NULL;
00941     rf_if_unlock();
00942 }
00943 
00944 
00945 void NanostackRfPhyKw41z::set_mac_address(uint8_t* mac)
00946 {
00947     rf_if_lock();
00948 
00949     if (NULL != rf) {
00950         error("NanostackRfPhyKw41z cannot change mac address when running");
00951         rf_if_unlock();
00952         return;
00953     }
00954     memcpy((void*)MAC_address, (void*)mac, sizeof(MAC_address));
00955 
00956     rf_if_unlock();
00957 }
00958 
00959 void NanostackRfPhyKw41z::get_mac_address(uint8_t *mac)
00960 {
00961     rf_if_lock();
00962 
00963     memcpy((void*)mac, (void*)MAC_address, sizeof(MAC_address));
00964 
00965     rf_if_unlock();
00966 }
00967