Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackRfPhyMcr20a.cpp Source File

NanostackRfPhyMcr20a.cpp

00001 /*
00002  * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_INTERRUPTIN && defined(MBED_CONF_RTOS_PRESENT)
00018 
00019 #include "NanostackRfPhyMcr20a.h"
00020 #include "ns_types.h"
00021 #include "platform/arm_hal_interrupt.h"
00022 #include "nanostack/platform/arm_hal_phy.h"
00023 #include <string.h>
00024 #include "rtos.h"
00025 #include "mbed_interface.h"
00026 #include "platform/mbed_error.h"
00027 
00028 using namespace mbed;
00029 using namespace rtos;
00030 
00031 /* Freescale headers which are for C files */
00032 extern "C" {
00033 #include "MCR20Drv.h "
00034 #include "MCR20Reg.h"
00035 #include "MCR20Overwrites.h "
00036 }
00037 
00038 
00039 #define RF_BUFFER_SIZE 128
00040 
00041 /*Radio RX and TX state definitions*/
00042 #define RFF_ON 0x01
00043 #define RFF_RX 0x02
00044 #define RFF_TX 0x04
00045 #define RFF_CCA 0x08
00046 
00047 #define RF_MODE_NORMAL  0
00048 #define RF_MODE_SNIFFER 1
00049 
00050 #define RF_CCA_THRESHOLD 75 /* -75 dBm */
00051 
00052 #define RF_TX_POWER_MAX 0
00053 
00054 /* PHY constants in symbols */
00055 #define gPhyWarmUpTime_c       9
00056 #define gPhySHRDuration_c     10
00057 #define gPhySymbolsPerOctet_c  2
00058 #define gPhyAckWaitDuration_c 54
00059 
00060 #define gCcaED_c               0
00061 #define gCcaCCA_MODE1_c        1
00062 
00063 #define gXcvrRunState_d       gXcvrPwrAutodoze_c
00064 #if !defined(TARGET_KW24D)
00065 #define gXcvrLowPowerState_d  gXcvrPwrHibernate_c
00066 #else
00067 #define gXcvrLowPowerState_d  gXcvrPwrAutodoze_c
00068 #endif
00069 
00070 namespace {
00071 
00072 /* MCR20A XCVR states */
00073 typedef enum xcvrState_tag {
00074     gIdle_c,
00075     gRX_c,
00076     gTX_c,
00077     gCCA_c,
00078     gTR_c,
00079     gCCCA_c,
00080 } xcvrState_t;
00081 
00082 /* MCR20A XCVR low power states */
00083 typedef enum xcvrPwrMode_tag {
00084     gXcvrPwrIdle_c,
00085     gXcvrPwrAutodoze_c,
00086     gXcvrPwrDoze_c,
00087     gXcvrPwrHibernate_c
00088 } xcvrPwrMode_t;
00089 
00090 
00091 /*RF Part Type*/
00092 typedef enum {
00093     FREESCALE_UNKNOW_DEV = 0,
00094     FREESCALE_MCR20A
00095 } rf_trx_part_e;
00096 
00097 /*Atmel RF states*/
00098 typedef enum {
00099     NOP = 0x00,
00100     BUSY_RX = 0x01,
00101     RF_TX_START = 0x02,
00102     FORCE_TRX_OFF = 0x03,
00103     FORCE_PLL_ON = 0x04,
00104     RX_ON = 0x06,
00105     TRX_OFF = 0x08,
00106     PLL_ON = 0x09,
00107     BUSY_RX_AACK = 0x11,
00108     SLEEP = 0x0F,
00109     RX_AACK_ON = 0x16,
00110     TX_ARET_ON = 0x19
00111 } rf_trx_states_t;
00112 
00113 } // anonymous namespace
00114 
00115 /*RF receive buffer*/
00116 static uint8_t rf_buffer[RF_BUFFER_SIZE];
00117 
00118 /* TX info */
00119 static uint8_t  radio_tx_power = 0x17; /* 0 dBm */
00120 static uint8_t  mac_tx_handle = 0;
00121 static uint8_t  need_ack = 0;
00122 static uint16_t tx_len = 0;
00123 
00124 /* RF driver data */
00125 static xcvrState_t mPhySeqState;
00126 static xcvrPwrMode_t mPwrState;
00127 static phy_device_driver_s device_driver;
00128 static uint8_t mStatusAndControlRegs[8];
00129 static uint8_t rf_rnd = 0;
00130 static int8_t  rf_radio_driver_id = -1;
00131 static uint8_t MAC_address[8];
00132 
00133 /* Driver instance handle and hardware */
00134 static NanostackRfPhyMcr20a *rf = NULL;
00135 static SPI *spi = NULL;
00136 static DigitalOut *cs = NULL;
00137 static DigitalOut *rst = NULL;
00138 static InterruptIn *irq = NULL;
00139 static DigitalIn *irq_pin = NULL;
00140 static Thread *irq_thread = NULL;
00141 
00142 /* Channel info */                 /* 2405    2410    2415    2420    2425    2430    2435    2440    2445    2450    2455    2460    2465    2470    2475    2480 */
00143 static const uint8_t  pll_int[16] =  {0x0B,   0x0B,   0x0B,   0x0B,   0x0B,   0x0B,   0x0C,   0x0C,   0x0C,   0x0C,   0x0C,   0x0C,   0x0D,   0x0D,   0x0D,   0x0D};
00144 static const uint16_t pll_frac[16] = {0x2800, 0x5000, 0x7800, 0xA000, 0xC800, 0xF000, 0x1800, 0x4000, 0x6800, 0x9000, 0xB800, 0xE000, 0x0800, 0x3000, 0x5800, 0x8000};
00145 
00146 /* Channel configurations for 2.4 */
00147 static const phy_rf_channel_configuration_s phy_24ghz = {.channel_0_center_frequency = 2405000000U, .channel_spacing = 5000000U, .datarate = 250000U, .number_of_channels = 16U, .modulation = M_OQPSK};
00148 
00149 static const phy_device_channel_page_s phy_channel_pages[] = {
00150     { CHANNEL_PAGE_0, &phy_24ghz},
00151     { CHANNEL_PAGE_0, NULL}
00152 };
00153 
00154 
00155 static rf_trx_part_e rf_radio_type_read(void);
00156 
00157 MBED_UNUSED static void rf_ack_wait_timer_start(uint16_t slots);
00158 MBED_UNUSED static void rf_ack_wait_timer_stop(void);
00159 MBED_UNUSED static void rf_handle_cca_ed_done(void);
00160 MBED_UNUSED static void rf_handle_tx_end(void);
00161 MBED_UNUSED static void rf_handle_rx_end(void);
00162 MBED_UNUSED static void rf_on(void);
00163 MBED_UNUSED static void rf_receive(void);
00164 MBED_UNUSED static void rf_poll_trx_state_change(rf_trx_states_t trx_state);
00165 MBED_UNUSED static void rf_init(void);
00166 MBED_UNUSED static void rf_set_mac_address(const uint8_t *ptr);
00167 MBED_UNUSED static int8_t rf_device_register(void);
00168 MBED_UNUSED static void rf_device_unregister(void);
00169 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);
00170 MBED_UNUSED static void rf_cca_abort(void);
00171 MBED_UNUSED static void rf_read_mac_address(uint8_t *ptr);
00172 MBED_UNUSED static int8_t rf_read_random(void);
00173 MBED_UNUSED static void rf_calibration_cb(void);
00174 MBED_UNUSED static void rf_init_phy_mode(void);
00175 MBED_UNUSED static void rf_ack_wait_timer_interrupt(void);
00176 MBED_UNUSED static void rf_calibration_timer_interrupt(void);
00177 MBED_UNUSED static void rf_calibration_timer_start(uint32_t slots);
00178 MBED_UNUSED static void rf_cca_timer_interrupt(void);
00179 MBED_UNUSED static void rf_cca_timer_start(uint32_t slots);
00180 MBED_UNUSED static uint16_t rf_get_phy_mtu_size(void);
00181 MBED_UNUSED static uint8_t rf_scale_lqi(int8_t rssi);
00182 
00183 /**
00184  *  RF output power write
00185  *
00186  * \brief TX power has to be set before network start.
00187  *
00188  * \param power
00189  *              See datasheet for TX power settings
00190  *
00191  * \return 0, Supported Value
00192  * \return -1, Not Supported Value
00193  */
00194 MBED_UNUSED static int8_t rf_tx_power_set(uint8_t power);
00195 MBED_UNUSED static uint8_t rf_tx_power_get(void);
00196 MBED_UNUSED static int8_t rf_enable_antenna_diversity(void);
00197 
00198 /* Private functions */
00199 MBED_UNUSED static void    rf_abort(void);
00200 MBED_UNUSED static void    rf_promiscuous(uint8_t mode);
00201 MBED_UNUSED static void    rf_get_timestamp(uint32_t *pRetClk);
00202 MBED_UNUSED static void    rf_set_timeout(uint32_t *pEndTime);
00203 MBED_UNUSED static void    rf_set_power_state(xcvrPwrMode_t newState);
00204 MBED_UNUSED static uint8_t rf_if_read_rnd(void);
00205 MBED_UNUSED static uint8_t rf_convert_LQI(uint8_t hwLqi);
00206 MBED_UNUSED static uint8_t rf_get_channel_energy(void);
00207 MBED_UNUSED static uint8_t rf_convert_energy_level(uint8_t energyLevel);
00208 MBED_UNUSED static int8_t  rf_convert_LQI_to_RSSI(uint8_t lqi);
00209 MBED_UNUSED static int8_t  rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
00210 MBED_UNUSED static int8_t  rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr);
00211 MBED_UNUSED static int8_t  rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr);
00212 static void PHY_InterruptThread(void);
00213 static void handle_interrupt(void);
00214 
00215 
00216 /*
00217  * \brief Read connected radio part.
00218  *
00219  * This function only return valid information when rf_init() is called
00220  *
00221  * \return
00222  */
00223 static rf_trx_part_e rf_radio_type_read(void)
00224 {
00225     return FREESCALE_MCR20A;
00226 }
00227 
00228 /*
00229  * \brief Function initialises and registers the RF driver.
00230  *
00231  * \param none
00232  *
00233  * \return rf_radio_driver_id Driver ID given by NET library
00234  */
00235 static int8_t rf_device_register(void)
00236 {
00237     rf_trx_part_e radio_type;
00238 
00239     rf_init();
00240 
00241 
00242 
00243     radio_type = rf_radio_type_read();
00244     if (radio_type == FREESCALE_MCR20A) {
00245         /*Set pointer to MAC address*/
00246         device_driver.PHY_MAC = MAC_address;
00247         device_driver.driver_description = (char *)"FREESCALE_MAC";
00248 
00249         //Create setup Used Radio chips
00250         /*Type of RF PHY is SubGHz*/
00251         device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
00252 
00253         device_driver.phy_channel_pages = phy_channel_pages;
00254         /*Maximum size of payload is 127*/
00255         device_driver.phy_MTU = 127;
00256         /*No header in PHY*/
00257         device_driver.phy_header_length = 0;
00258         /*No tail in PHY*/
00259         device_driver.phy_tail_length = 0;
00260         /*Set address write function*/
00261         device_driver.address_write = &rf_address_write;
00262         /*Set RF extension function*/
00263         device_driver.extension = &rf_extension;
00264         /*Set RF state control function*/
00265         device_driver.state_control = &rf_interface_state_control;
00266         /*Set transmit function*/
00267         device_driver.tx = &rf_start_cca;
00268         /*Upper layer callbacks init to NULL*/
00269         device_driver.phy_rx_cb = NULL;
00270         device_driver.phy_tx_done_cb = NULL;
00271         /*Virtual upper data callback init to NULL*/
00272         device_driver.arm_net_virtual_rx_cb = NULL;
00273         device_driver.arm_net_virtual_tx_cb = NULL;
00274 
00275         /*Register device driver*/
00276         rf_radio_driver_id = arm_net_phy_register(&device_driver);
00277     }
00278 
00279     return rf_radio_driver_id;
00280 }
00281 
00282 /*
00283  * \brief Function unregisters the RF driver.
00284  *
00285  * \param none
00286  *
00287  * \return none
00288  */
00289 static void rf_device_unregister(void)
00290 {
00291     arm_net_phy_unregister(rf_radio_driver_id);
00292 }
00293 
00294 /*
00295  * \brief Function returns the generated 8-bit random value for seeding Pseudo-random generator.
00296  *
00297  * \param none
00298  *
00299  * \return random value
00300  */
00301 static int8_t rf_read_random(void)
00302 {
00303     return rf_rnd;
00304 }
00305 
00306 /*
00307  * \brief Function is a call back for ACK wait timeout.
00308  *
00309  * \param none
00310  *
00311  * \return none
00312  */
00313 static void rf_ack_wait_timer_interrupt(void)
00314 {
00315     /* The packet was transmitted successfully, but no ACK was received */
00316     if (device_driver.phy_tx_done_cb) {
00317         device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
00318     }
00319     rf_receive();
00320 }
00321 
00322 /*
00323  * \brief Function is a call back for calibration interval timer.
00324  *
00325  * \param none
00326  *
00327  * \return none
00328  */
00329 static void rf_calibration_timer_interrupt(void)
00330 {
00331 }
00332 
00333 /*
00334  * \brief Function is a call back for cca interval timer.
00335  *
00336  * \param none
00337  *
00338  * \return none
00339  */
00340 static void rf_cca_timer_interrupt(void)
00341 {
00342     /* CCA time-out handled by Hardware */
00343 }
00344 
00345 
00346 /*
00347  * \brief Function starts the ACK wait time-out.
00348  *
00349  * \param slots The ACK wait time-out in [symbols]
00350  *
00351  * \return none
00352  */
00353 static void rf_ack_wait_timer_start(uint16_t time)
00354 {
00355     uint32_t timeout;
00356 
00357     rf_get_timestamp(&timeout);
00358     timeout += time;
00359     rf_set_timeout(&timeout);
00360 }
00361 
00362 /*
00363  * \brief Function starts the calibration interval.
00364  *
00365  * \param slots Given slots, resolution 50us
00366  *
00367  * \return none
00368  */
00369 static void rf_calibration_timer_start(uint32_t slots)
00370 {
00371     (void)slots;
00372 }
00373 
00374 /*
00375  * \brief Function starts the CCA timout.
00376  *
00377  * \param slots Given slots, resolution 50us
00378  *
00379  * \return none
00380  */
00381 static void rf_cca_timer_start(uint32_t slots)
00382 {
00383     (void)slots;
00384 }
00385 
00386 /*
00387  * \brief Function stops the ACK wait timeout.
00388  *
00389  * \param none
00390  *
00391  * \return none
00392  */
00393 static void rf_ack_wait_timer_stop(void)
00394 {
00395 }
00396 
00397 /*
00398  * \brief Function reads the MAC address array.
00399  *
00400  * \param ptr Pointer to read array
00401  *
00402  * \return none
00403  */
00404 static void rf_read_mac_address(uint8_t *ptr)
00405 {
00406     memcpy(ptr, MAC_address, 8);
00407 }
00408 
00409 /*
00410  * \brief Function sets the MAC address array.
00411  *
00412  * \param ptr Pointer to given MAC address array
00413  *
00414  * \return none
00415  */
00416 static void rf_set_mac_address(const uint8_t *ptr)
00417 {
00418     memcpy(MAC_address, ptr, 8);
00419 }
00420 
00421 static uint16_t rf_get_phy_mtu_size(void)
00422 {
00423     return device_driver.phy_MTU;
00424 }
00425 
00426 /*
00427  * \brief Function writes 16-bit address in RF address filter.
00428  *
00429  * \param short_address Given short address
00430  *
00431  * \return none
00432  */
00433 static void rf_set_short_adr(uint8_t *short_address)
00434 {
00435     /* Write one register at a time to be accessible from hibernate mode */
00436     MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_MSB, short_address[0]);
00437     MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_LSB, short_address[1]);
00438 }
00439 
00440 /*
00441  * \brief Function writes PAN Id in RF PAN Id filter.
00442  *
00443  * \param pan_id Given PAN Id
00444  *
00445  * \return none
00446  */
00447 static void rf_set_pan_id(uint8_t *pan_id)
00448 {
00449     /* Write one register at a time to be accessible from hibernate mode */
00450     MCR20Drv_IndirectAccessSPIWrite(MACPANID0_MSB, pan_id[0]);
00451     MCR20Drv_IndirectAccessSPIWrite(MACPANID0_LSB, pan_id[1]);
00452 }
00453 
00454 /*
00455  * \brief Function writes 64-bit address in RF address filter.
00456  *
00457  * \param address Given 64-bit address
00458  *
00459  * \return none
00460  */
00461 static void rf_set_address(uint8_t *address)
00462 {
00463     /* Write one register at a time to be accessible from hibernate mode */
00464     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_0,  address[7]);
00465     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_8,  address[6]);
00466     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_16, address[5]);
00467     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_24, address[4]);
00468     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_32, address[3]);
00469     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_40, address[2]);
00470     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_48, address[1]);
00471     MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_56, address[0]);
00472 }
00473 
00474 /*
00475  * \brief Function sets the RF channel.
00476  *
00477  * \param ch New channel
00478  *
00479  * \return none
00480  */
00481 static void rf_channel_set(uint8_t channel)
00482 {
00483     MCR20Drv_DirectAccessSPIWrite(PLL_INT0, pll_int[channel - 11]);
00484     MCR20Drv_DirectAccessSPIMultiByteWrite(PLL_FRAC0_LSB, (uint8_t *) &pll_frac[channel - 11], 2);
00485 }
00486 
00487 
00488 /*
00489  * \brief Function initialises the radio driver and resets the radio.
00490  *
00491  * \param none
00492  *
00493  * \return none
00494  */
00495 static void rf_init(void)
00496 {
00497     uint32_t index;
00498     mPhySeqState = gIdle_c;
00499     mPwrState = gXcvrPwrIdle_c;
00500     /*Reset RF module*/
00501     MCR20Drv_RESET();
00502     /* Initialize the transceiver SPI driver */
00503     MCR20Drv_Init();
00504     /* Disable Tristate on MISO for SPI reads */
00505     MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, 0x02);
00506     /* Set XCVR clock output settings */
00507 #if !defined(TARGET_KW24D)
00508     MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d);
00509 #endif
00510     /* Set default XCVR power state */
00511     rf_set_power_state(gXcvrRunState_d);
00512 
00513     /* PHY_CTRL1 default HW settings  + AUTOACK enabled */
00514     mStatusAndControlRegs[PHY_CTRL1] = cPHY_CTRL1_AUTOACK;
00515     /* PHY_CTRL2 : mask all PP interrupts */
00516     mStatusAndControlRegs[PHY_CTRL2] = cPHY_CTRL2_CRC_MSK | \
00517                                        cPHY_CTRL2_PLL_UNLOCK_MSK | \
00518                                        /*cPHY_CTRL2_FILTERFAIL_MSK | */ \
00519                                        cPHY_CTRL2_RX_WMRK_MSK | \
00520                                        cPHY_CTRL2_CCAMSK | \
00521                                        cPHY_CTRL2_RXMSK | \
00522                                        cPHY_CTRL2_TXMSK | \
00523                                        cPHY_CTRL2_SEQMSK;
00524     /* PHY_CTRL3 : enable timer 3 and disable remaining interrupts */
00525     mStatusAndControlRegs[PHY_CTRL3] = cPHY_CTRL3_ASM_MSK    | \
00526                                        cPHY_CTRL3_PB_ERR_MSK | \
00527                                        cPHY_CTRL3_WAKE_MSK   | \
00528                                        cPHY_CTRL3_TMR3CMP_EN;
00529     /* PHY_CTRL4 unmask global TRX interrupts, enable 16 bit mode for TC2 - TC2 prime EN */
00530     mStatusAndControlRegs[PHY_CTRL4] = cPHY_CTRL4_TC2PRIME_EN | (gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c);
00531     /* Clear all PP IRQ bits to avoid unexpected interrupts immediately after initialization */
00532     mStatusAndControlRegs[IRQSTS1] = cIRQSTS1_PLL_UNLOCK_IRQ | \
00533                                      cIRQSTS1_FILTERFAIL_IRQ | \
00534                                      cIRQSTS1_RXWTRMRKIRQ | \
00535                                      cIRQSTS1_CCAIRQ | \
00536                                      cIRQSTS1_RXIRQ | \
00537                                      cIRQSTS1_TXIRQ | \
00538                                      cIRQSTS1_SEQIRQ;
00539 
00540     mStatusAndControlRegs[IRQSTS2] = cIRQSTS2_ASM_IRQ | cIRQSTS2_PB_ERR_IRQ | cIRQSTS2_WAKE_IRQ;
00541     /* Mask and clear all TMR IRQs */
00542     mStatusAndControlRegs[IRQSTS3] = cIRQSTS3_TMR4MSK | cIRQSTS3_TMR3MSK | cIRQSTS3_TMR2MSK | cIRQSTS3_TMR1MSK | \
00543                                      cIRQSTS3_TMR4IRQ | cIRQSTS3_TMR3IRQ | cIRQSTS3_TMR2IRQ | cIRQSTS3_TMR1IRQ;
00544     /* Write settings to XCVR */
00545     MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 5);
00546     /* Clear all interrupts */
00547     MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, &mStatusAndControlRegs[IRQSTS1], 3);
00548 
00549     /*  RX_FRAME_FILTER. Accept FrameVersion 0 and 1 packets, reject all others */
00550     MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, (cRX_FRAME_FLT_FRM_VER | \
00551                                                       cRX_FRAME_FLT_BEACON_FT | \
00552                                                       cRX_FRAME_FLT_DATA_FT | \
00553                                                       cRX_FRAME_FLT_CMD_FT));
00554     /* Direct register overwrites */
00555     for (index = 0; index < sizeof(overwrites_direct) / sizeof(overwrites_t); index++) {
00556         MCR20Drv_DirectAccessSPIWrite(overwrites_direct[index].address, overwrites_direct[index].data);
00557     }
00558     /* Indirect register overwrites */
00559     for (index = 0; index < sizeof(overwrites_indirect) / sizeof(overwrites_t); index++) {
00560         MCR20Drv_IndirectAccessSPIWrite(overwrites_indirect[index].address, overwrites_indirect[index].data);
00561     }
00562 
00563     /* Set the CCA energy threshold value */
00564     MCR20Drv_IndirectAccessSPIWrite(CCA1_THRESH, RF_CCA_THRESHOLD);
00565     /* Set prescaller to obtain 1 symbol (16us) timebase */
00566     MCR20Drv_IndirectAccessSPIWrite(TMR_PRESCALE, 0x05);
00567 
00568     MCR20Drv_IRQ_Enable();
00569 
00570     /*Read random variable. This will be used when seeding pseudo-random generator*/
00571     rf_rnd = rf_if_read_rnd();
00572     /*Write initial eui64*/
00573     rf_set_address(MAC_address);
00574     /*set default channel to 11*/
00575     rf_channel_set(11);
00576     /*Start receiver*/
00577     rf_receive();
00578 }
00579 
00580 /**
00581  * \brief Function gets called when MAC is setting radio off.
00582  *
00583  * \param none
00584  *
00585  * \return none
00586  */
00587 static void rf_off(void)
00588 {
00589     /* Abort any ongoing sequences */
00590     rf_abort();
00591     /* Set XCVR in a low power state */
00592     rf_set_power_state(gXcvrLowPowerState_d);
00593 }
00594 
00595 /*
00596  * \brief Function polls the RF state until it has changed to desired state.
00597  *
00598  * \param trx_state RF state
00599  *
00600  * \return none
00601  */
00602 static void rf_poll_trx_state_change(rf_trx_states_t trx_state)
00603 {
00604     (void)trx_state;
00605 }
00606 
00607 /*
00608  * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO.
00609  *
00610  * \param data_ptr Pointer to TX data
00611  * \param data_length Length of the TX data
00612  * \param tx_handle Handle to transmission
00613  * \return 0 Success
00614  * \return -1 Busy
00615  */
00616 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol)
00617 {
00618     uint8_t ccaMode;
00619 
00620     /* Parameter validation */
00621     if (!data_ptr || (data_length > 125) || (PHY_LAYER_PAYLOAD != data_protocol)) {
00622         return -1;
00623     }
00624 
00625     if (mPhySeqState == gRX_c) {
00626         uint8_t phyReg = MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F;
00627         /* Check for an Rx in progress. */
00628         if ((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16)) {
00629             if (device_driver.phy_tx_done_cb) {
00630                 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
00631             }
00632             return -1;
00633         }
00634         rf_abort();
00635     }
00636 
00637     /*Check if transmitter is busy*/
00638     if (mPhySeqState != gIdle_c) {
00639         /*Return busy*/
00640         return -1;
00641     }
00642 
00643     /*Store TX handle*/
00644     mac_tx_handle = tx_handle;
00645     /*Check if transmitted data needs to be acked*/
00646     need_ack = (*data_ptr & 0x20) == 0x20;
00647 
00648     /* Set XCVR power state in run mode */
00649     rf_set_power_state(gXcvrRunState_d);
00650     /* Load data into XCVR */
00651     tx_len = data_length + 2;
00652     MCR20Drv_PB_SPIBurstWrite(data_ptr - 1, data_length + 1);
00653     MCR20Drv_PB_SPIByteWrite(0, tx_len);
00654 
00655     /* Set CCA mode 1 */
00656     ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE;
00657     if (ccaMode != gCcaCCA_MODE1_c) {
00658         mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c);
00659         mStatusAndControlRegs[PHY_CTRL4] |= gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c;
00660         MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]);
00661     }
00662 
00663     /* Read XCVR registers */
00664     mStatusAndControlRegs[0] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[1], 4);
00665     mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
00666     mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c;
00667     mPhySeqState = gCCA_c;
00668 
00669     /* Ensure that no spurious interrupts are raised */
00670     mStatusAndControlRegs[IRQSTS3] &= 0xF0; /* do not change other IRQ status */
00671     mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ);
00672     MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
00673 
00674     /* Write XCVR settings */
00675     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
00676 
00677     /* Unmask SEQ interrupt */
00678     mStatusAndControlRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
00679     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]);
00680 
00681     /*Return success*/
00682     return 0;
00683 }
00684 
00685 /*
00686  * \brief Function aborts CCA process.
00687  *
00688  * \param none
00689  *
00690  * \return none
00691  */
00692 static void rf_cca_abort(void)
00693 {
00694     rf_abort();
00695 }
00696 
00697 /*
00698  * \brief Function starts the transmission of the frame. Called from ISR context!
00699  *
00700  * \param none
00701  *
00702  * \return none
00703  */
00704 static void rf_start_tx(void)
00705 {
00706     /* Perform TxRxAck sequence if required by phyTxMode */
00707     if (need_ack) {
00708         mStatusAndControlRegs[PHY_CTRL1] |= cPHY_CTRL1_RXACKRQD;
00709         mPhySeqState = gTR_c;
00710     } else {
00711         mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_RXACKRQD);
00712         mPhySeqState = gTX_c;
00713     }
00714 
00715     mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
00716     mStatusAndControlRegs[PHY_CTRL1] |= mPhySeqState;
00717 
00718     /* Unmask SEQ interrupt */
00719     mStatusAndControlRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
00720 
00721     /* Start the sequence immediately */
00722     MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 2);
00723 
00724     if (need_ack) {
00725         rf_ack_wait_timer_start(gPhyWarmUpTime_c + gPhySHRDuration_c + tx_len * gPhySymbolsPerOctet_c + gPhyAckWaitDuration_c);
00726     }
00727 }
00728 
00729 /*
00730  * \brief Function sets the RF in RX state. Called from ISR context!
00731  *
00732  * \param none
00733  *
00734  * \return none
00735  */
00736 static void rf_receive(void)
00737 {
00738     uint8_t phyRegs[5];
00739 
00740     /* RX can start only from Idle state */
00741     if (mPhySeqState != gIdle_c) {
00742         return;
00743     }
00744 
00745     /* Set XCVR power state in run mode */
00746     rf_set_power_state(gXcvrRunState_d);
00747     /* read XVCR settings */
00748     phyRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &phyRegs[IRQSTS2], 4);
00749     /* unmask SEQ interrupt */
00750     phyRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
00751     /* set XcvrSeq to RX */
00752     phyRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
00753     phyRegs[PHY_CTRL1] |=  gRX_c;
00754     mPhySeqState = gRX_c;
00755     /* Ensure that no spurious interrupts are raised */
00756     phyRegs[IRQSTS3] &= 0xF0; /* do not change other IRQ status */
00757     phyRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ;
00758     /* sync settings with XCVR */
00759     MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, phyRegs, 5);
00760 }
00761 
00762 /*
00763  * \brief Function calibrates the radio.
00764  *
00765  * \param none
00766  *
00767  * \return none
00768  */
00769 static void rf_calibration_cb(void)
00770 {
00771 }
00772 
00773 /*
00774  * \brief Function sets RF_ON flag when radio is powered.
00775  *
00776  * \param none
00777  *
00778  * \return none
00779  */
00780 static void rf_on(void)
00781 {
00782 }
00783 
00784 /*
00785  * \brief Function is a call back for RX end interrupt.
00786  *
00787  * \param none
00788  *
00789  * \return none
00790  */
00791 static void rf_handle_rx_end(void)
00792 {
00793     uint8_t rf_lqi = MCR20Drv_DirectAccessSPIRead(LQI_VALUE);
00794     int8_t rf_rssi = 0;
00795     uint8_t len = mStatusAndControlRegs[RX_FRM_LEN] - 2;
00796 
00797 
00798     /*Start receiver*/
00799     rf_receive();
00800 
00801     /*Check the length is valid*/
00802     if (len > 1 && len < RF_BUFFER_SIZE) {
00803         rf_lqi  = rf_convert_LQI(rf_lqi);
00804         rf_rssi = rf_convert_LQI_to_RSSI(rf_lqi);
00805         /*gcararu: Scale LQI using received RSSI, to match the LQI reported by the ATMEL radio */
00806         rf_lqi  = rf_scale_lqi(rf_rssi);
00807 
00808         /*Read received packet*/
00809         MCR20Drv_PB_SPIBurstRead(rf_buffer, len);
00810         if (device_driver.phy_rx_cb) {
00811             device_driver.phy_rx_cb(rf_buffer, len, rf_lqi, rf_rssi, rf_radio_driver_id);
00812         }
00813     }
00814 }
00815 
00816 /*
00817  * \brief Function is called when MAC is shutting down the radio.
00818  *
00819  * \param none
00820  *
00821  * \return none
00822  */
00823 static void rf_shutdown(void)
00824 {
00825     /*Call RF OFF*/
00826     rf_off();
00827 }
00828 
00829 /*
00830  * \brief Function is a call back for TX end interrupt.
00831  *
00832  * \param none
00833  *
00834  * \return none
00835  */
00836 static void rf_handle_tx_end(void)
00837 {
00838     uint8_t rx_frame_pending = mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_RX_FRM_PEND;
00839 
00840     /*Start receiver*/
00841     rf_receive();
00842 
00843     if (!device_driver.phy_tx_done_cb) {
00844         return;
00845     }
00846 
00847     /*Call PHY TX Done API*/
00848     if (need_ack) {
00849         if (rx_frame_pending) {
00850             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE_PENDING, 1, 1);
00851         } else {
00852             // arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
00853             device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1);
00854         }
00855     } else {
00856         device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
00857     }
00858 }
00859 
00860 /*
00861  * \brief Function is a call back for CCA ED done interrupt.
00862  *
00863  * \param none
00864  *
00865  * \return none
00866  */
00867 static void rf_handle_cca_ed_done(void)
00868 {
00869     /*Check the result of CCA process*/
00870     if (!(mStatusAndControlRegs[IRQSTS2] & cIRQSTS2_CCA)) {
00871         rf_start_tx();
00872     } else if (device_driver.phy_tx_done_cb) {
00873         /*Send CCA fail notification*/
00874         device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
00875     }
00876 }
00877 
00878 /*
00879  * \brief Function sets the TX power variable.
00880  *
00881  * \param power TX power setting
00882  *
00883  * \return 0 Success
00884  * \return -1 Fail
00885  */
00886 static int8_t rf_tx_power_set(uint8_t power)
00887 {
00888     /* gcapraru: Map MCR20A Tx power levels over ATMEL values */
00889     static uint8_t pwrLevelMapping[16] = {25, 25, 25, 24, 24, 24, 23, 23, 22, 22, 21, 20, 19, 18, 17, 14};
00890 
00891     if (power > 15) {
00892         return -1;
00893     }
00894 
00895     radio_tx_power = power;
00896     MCR20Drv_DirectAccessSPIWrite(PA_PWR, pwrLevelMapping[power]);
00897     return 0;
00898 }
00899 
00900 /*
00901  * \brief Function returns the TX power variable.
00902  *
00903  * \param none
00904  *
00905  * \return radio_tx_power TX power variable
00906  */
00907 static uint8_t rf_tx_power_get(void)
00908 {
00909     return radio_tx_power;
00910 }
00911 
00912 /*
00913  * \brief Function enables the usage of Antenna diversity.
00914  *
00915  * \param none
00916  *
00917  * \return 0 Success
00918  */
00919 static int8_t rf_enable_antenna_diversity(void)
00920 {
00921     uint8_t phyReg;
00922 
00923     phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_AGC_CTRL);
00924     phyReg |= cANT_AGC_CTRL_FAD_EN_Mask_c;
00925     MCR20Drv_IndirectAccessSPIWrite(ANT_AGC_CTRL, phyReg);
00926 
00927     phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_PAD_CTRL);
00928     phyReg |= 0x02;
00929     MCR20Drv_IndirectAccessSPIWrite(ANT_PAD_CTRL, phyReg);
00930 
00931     return 0;
00932 }
00933 
00934 /*
00935  * \brief Function gives the control of RF states to MAC.
00936  *
00937  * \param new_state RF state
00938  * \param rf_channel RF channel
00939  *
00940  * \return 0 Success
00941  */
00942 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
00943 {
00944     int8_t ret_val = 0;
00945     switch (new_state) {
00946         /*Reset PHY driver and set to idle*/
00947         case PHY_INTERFACE_RESET:
00948             break;
00949         /*Disable PHY Interface driver*/
00950         case PHY_INTERFACE_DOWN:
00951             rf_shutdown();
00952             break;
00953         /*Enable PHY Interface driver*/
00954         case PHY_INTERFACE_UP:
00955             rf_channel_set(rf_channel);
00956             rf_receive();
00957             break;
00958         /*Enable wireless interface ED scan mode*/
00959         case PHY_INTERFACE_RX_ENERGY_STATE:
00960             rf_abort();
00961             rf_channel_set(rf_channel);
00962             break;
00963         case PHY_INTERFACE_SNIFFER_STATE:             /**< Enable Sniffer state */
00964             rf_promiscuous(1);
00965             rf_channel_set(rf_channel);
00966             rf_receive();
00967             break;
00968     }
00969     return ret_val;
00970 }
00971 
00972 /*
00973  * \brief Function controls the ACK pending, channel setting and energy detection.
00974  *
00975  * \param extension_type Type of control
00976  * \param data_ptr Data from NET library
00977  *
00978  * \return 0 Success
00979  */
00980 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
00981 {
00982     switch (extension_type) {
00983         /*Control MAC pending bit for Indirect data transmission*/
00984         case PHY_EXTENSION_CTRL_PENDING_BIT: {
00985             uint8_t reg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
00986 
00987             if (*data_ptr) {
00988                 reg |= cSRC_CTRL_ACK_FRM_PND;
00989             } else {
00990                 reg &= ~cSRC_CTRL_ACK_FRM_PND;
00991             }
00992 
00993             MCR20Drv_DirectAccessSPIWrite(SRC_CTRL, reg);
00994             break;
00995 
00996         }
00997         /*Return frame Auto Ack frame pending status*/
00998         case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS: {
00999             uint8_t reg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
01000             if (reg & cSRC_CTRL_ACK_FRM_PND) {
01001                 *data_ptr = 1;
01002             } else {
01003                 *data_ptr  = 0;
01004             }
01005             break;
01006         }
01007         /*Read energy on the channel*/
01008         case PHY_EXTENSION_READ_CHANNEL_ENERGY:
01009             *data_ptr = rf_get_channel_energy();
01010             break;
01011         default:
01012             break;
01013     }
01014     return 0;
01015 }
01016 
01017 /*
01018  * \brief Function sets the addresses to RF address filters.
01019  *
01020  * \param address_type Type of address
01021  * \param address_ptr Pointer to given address
01022  *
01023  * \return 0 Success
01024  */
01025 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
01026 {
01027     int8_t ret_val = 0;
01028     switch (address_type) {
01029         /*Set 48-bit address*/
01030         case PHY_MAC_48BIT:
01031             break;
01032         /*Set 64-bit address*/
01033         case PHY_MAC_64BIT:
01034             rf_set_address(address_ptr);
01035             break;
01036         /*Set 16-bit address*/
01037         case PHY_MAC_16BIT:
01038             rf_set_short_adr(address_ptr);
01039             break;
01040         /*Set PAN Id*/
01041         case PHY_MAC_PANID:
01042             rf_set_pan_id(address_ptr);
01043             break;
01044     }
01045     return ret_val;
01046 }
01047 
01048 /*
01049  * \brief Function initialises the ACK wait time and returns the used PHY mode.
01050  *
01051  * \param none
01052  *
01053  * \return tmp Used PHY mode
01054  */
01055 static void rf_init_phy_mode(void)
01056 {
01057 }
01058 
01059 /*
01060  * \brief Function is a RF interrupt vector. End of frame in RX and TX are handled here as well as CCA process interrupt.
01061  *
01062  * \param none
01063  *
01064  * \return none
01065  */
01066 static void PHY_InterruptHandler(void)
01067 {
01068     MCR20Drv_IRQ_Disable();
01069     irq_thread->flags_set(1);
01070 }
01071 
01072 static void PHY_InterruptThread(void)
01073 {
01074     for (;;) {
01075         ThisThread::flags_wait_all(1);
01076         handle_interrupt();
01077         MCR20Drv_IRQ_Enable();
01078     }
01079 }
01080 
01081 static void handle_interrupt(void)
01082 {
01083     uint8_t xcvseqCopy;
01084 
01085     /* Read transceiver interrupt status and control registers */
01086     mStatusAndControlRegs[IRQSTS1] =
01087         MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 7);
01088 
01089     xcvseqCopy = mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ;
01090 
01091     /* Flter Fail IRQ */
01092     if ((mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_FILTERFAIL_IRQ) &&
01093             !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_FILTERFAIL_MSK)) {
01094         if (xcvseqCopy == gRX_c) {
01095             /* Abort current SEQ */
01096             mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
01097             MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
01098             /* Wait for Sequence Idle */
01099             while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
01100             /* Clear IRQ flags: */
01101             MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ);
01102             /* Restart Rx asap */
01103             mStatusAndControlRegs[PHY_CTRL1] |= gRX_c;
01104             MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
01105         }
01106     }
01107 
01108     /* TMR3 IRQ: ACK wait time-out */
01109     if ((mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3IRQ) &&
01110             !(mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3MSK)) {
01111         /* Disable TMR3 IRQ */
01112         mStatusAndControlRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK;
01113 
01114         if (xcvseqCopy == gTR_c) {
01115             /* Set XCVR to Idle */
01116             mPhySeqState = gIdle_c;
01117             mStatusAndControlRegs[PHY_CTRL1] &=  ~(cPHY_CTRL1_XCVSEQ);
01118             /* Mask interrupts */
01119             mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK;
01120             /* Sync settings with XCVR */
01121             MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
01122 
01123             rf_ack_wait_timer_interrupt();
01124             return;
01125         }
01126     }
01127 
01128     /* Sequencer interrupt, the autosequence has completed */
01129     if ((mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_SEQIRQ) &&
01130             !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_SEQMSK)) {
01131         /* Set XCVR to Idle */
01132         mPhySeqState = gIdle_c;
01133         mStatusAndControlRegs[PHY_CTRL1] &=  ~(cPHY_CTRL1_XCVSEQ);
01134         /* Mask interrupts */
01135         mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK;
01136         /* Sync settings with XCVR */
01137         MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
01138 
01139         /* PLL unlock, the autosequence has been aborted due to PLL unlock */
01140         if (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_PLL_UNLOCK_IRQ) {
01141             if (xcvseqCopy == gRX_c) {
01142                 rf_receive();
01143             }
01144             return;
01145         }
01146 
01147         switch (xcvseqCopy) {
01148             case gTX_c:
01149             case gTR_c:
01150                 rf_handle_tx_end();
01151                 break;
01152 
01153             case gRX_c:
01154                 rf_handle_rx_end();
01155                 break;
01156 
01157             case gCCA_c:
01158                 rf_handle_cca_ed_done();
01159                 break;
01160 
01161             default:
01162                 break;
01163         }
01164 
01165         return;
01166     }
01167     /* Other IRQ. Clear XCVR interrupt flags */
01168     MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
01169 }
01170 
01171 /*
01172  * \brief Function forces the XCVR to Idle state.
01173  *
01174  * \param none
01175  *
01176  * \return none
01177  */
01178 static void rf_abort(void)
01179 {
01180     /* Mask XCVR irq */
01181     MCR20Drv_IRQ_Disable();
01182 
01183     mPhySeqState = gIdle_c;
01184 
01185     mStatusAndControlRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 5);
01186 
01187     /* Mask SEQ interrupt */
01188     mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_SEQMSK;
01189     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]);
01190 
01191     if ((mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c) {
01192         /* Abort current SEQ */
01193         mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
01194         MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
01195 
01196         /* Wait for Sequence Idle (if not already) */
01197         while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
01198         //while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
01199         mStatusAndControlRegs[IRQSTS1] |= cIRQSTS1_SEQIRQ;
01200     }
01201 
01202     /* Clear all PP IRQ bits to avoid unexpected interrupts and mask TMR3 interrupt.
01203        Do not change TMR IRQ status. */
01204     mStatusAndControlRegs[IRQSTS3] &= 0xF0;
01205     mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ);
01206     MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
01207 
01208     /* Unmask XCVR irq */
01209     MCR20Drv_IRQ_Enable();
01210 }
01211 
01212 /*
01213  * \brief Function reads a time-stamp value from XCVR [symbols]
01214  *
01215  * \param pEndTime pointer to location where time-stamp will be stored
01216  *
01217  * \return none
01218  */
01219 static void rf_get_timestamp(uint32_t *pRetClk)
01220 {
01221     if (NULL == pRetClk) {
01222         return;
01223     }
01224 
01225     platform_enter_critical();
01226 
01227     *pRetClk = 0;
01228     MCR20Drv_DirectAccessSPIMultiByteRead(EVENT_TMR_LSB, (uint8_t *) pRetClk, 3);
01229 
01230     platform_exit_critical();
01231 }
01232 
01233 /*
01234  * \brief Function set a time-out to an XCVR sequence.
01235  *
01236  * \param pEndTime pointer to the sequence time-out value [symbols]
01237  *
01238  * \return none
01239  */
01240 static void rf_set_timeout(uint32_t *pEndTime)
01241 {
01242     uint8_t phyReg;
01243 
01244     if (NULL == pEndTime) {
01245         return;
01246     }
01247 
01248     platform_enter_critical();
01249 
01250     phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
01251     phyReg &= 0xF0;                    /* do not change IRQ status */
01252     phyReg |= (cIRQSTS3_TMR3MSK);      /* mask TMR3 interrupt */
01253     MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg);
01254 
01255     MCR20Drv_DirectAccessSPIMultiByteWrite(T3CMP_LSB, (uint8_t *) pEndTime, 3);
01256 
01257     phyReg &= ~(cIRQSTS3_TMR3MSK);      /* unmask TMR3 interrupt */
01258     phyReg |= (cIRQSTS3_TMR3IRQ);       /* aknowledge TMR3 IRQ */
01259     MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg);
01260 
01261     platform_exit_critical();
01262 }
01263 
01264 /*
01265  * \brief Function reads a random number from RF.
01266  *
01267  * \param none
01268  *
01269  * \return 8-bit random number
01270  */
01271 static uint8_t rf_if_read_rnd(void)
01272 {
01273     uint8_t phyReg;
01274 
01275     MCR20Drv_IRQ_Disable();
01276     /* Check if XCVR is idle */
01277     phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
01278 
01279     if ((phyReg & cPHY_CTRL1_XCVSEQ) == gIdle_c) {
01280         /* Program a new sequence */
01281         MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyReg | gCCA_c);
01282         /* Wait for sequence to finish */
01283         while (!(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
01284         /* Clear interrupt flag */
01285         MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ);
01286     }
01287 
01288     MCR20Drv_IRQ_Enable();
01289 
01290     return MCR20Drv_IndirectAccessSPIRead(_RNG);
01291 }
01292 
01293 /*
01294  * \brief Function converts LQI into RSSI.
01295  *
01296  * \param LQI
01297  *
01298  * \return RSSI
01299  */
01300 static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi)
01301 {
01302     int32_t rssi = (50 * lqi - 16820) / 163;
01303     return (int8_t)rssi;
01304 }
01305 
01306 /*
01307  * \brief Function scale the LQI value reported by RF into a 0-255 value.
01308  *
01309  * \param hwLqi - the LQI value reported by RF
01310  *
01311  * \return scaled LQI
01312  */
01313 static uint8_t rf_convert_LQI(uint8_t hwLqi)
01314 {
01315     uint32_t tmpLQI;
01316 
01317     /* LQI Saturation Level */
01318     if (hwLqi >= 230) {
01319         return 0xFF;
01320     } else if (hwLqi <= 9) {
01321         return 0;
01322     } else {
01323         /* Rescale the LQI values from min to saturation to the 0x00 - 0xFF range */
01324         /* The LQI value mst be multiplied by ~1.1087 */
01325         /* tmpLQI =  hwLqi * 7123 ~= hwLqi * 65536 * 0.1087 = hwLqi * 2^16 * 0.1087*/
01326         tmpLQI = ((uint32_t)hwLqi * (uint32_t)7123);
01327         /* tmpLQI =  (tmpLQI / 2^16) + hwLqi */
01328         tmpLQI = (uint32_t)(tmpLQI >> 16) + (uint32_t)hwLqi;
01329 
01330         return (uint8_t)tmpLQI;
01331     }
01332 }
01333 
01334 /*
01335  * \brief Function enables/disables Rx promiscuous mode.
01336  *
01337  * \param state of XCVR promiscuous mode
01338  *
01339  * \return none
01340  */
01341 static void rf_promiscuous(uint8_t state)
01342 {
01343     uint8_t rxFrameFltReg, phyCtrl4Reg;
01344 
01345     rxFrameFltReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER);
01346     phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4);
01347 
01348     if (state) {
01349         /* FRM_VER[1:0] = b00. 00: Any FrameVersion accepted (0,1,2 & 3) */
01350         /* All frame types accepted*/
01351         phyCtrl4Reg   |= cPHY_CTRL4_PROMISCUOUS;
01352         rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
01353         rxFrameFltReg |= (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
01354     } else {
01355         phyCtrl4Reg   &= ~cPHY_CTRL4_PROMISCUOUS;
01356         /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others */
01357         /* Beacon, Data and MAC command frame types accepted */
01358         rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
01359         rxFrameFltReg |= (0x03 << cRX_FRAME_FLT_FRM_VER_Shift_c);
01360         rxFrameFltReg &= ~(cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
01361     }
01362 
01363     MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, rxFrameFltReg);
01364     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, phyCtrl4Reg);
01365 }
01366 
01367 /*
01368  * \brief Function used to switch XCVR power state.
01369  *
01370  * \param state The XCVR power mode
01371  *
01372  * \return none
01373  */
01374 static void rf_set_power_state(xcvrPwrMode_t newState)
01375 {
01376     uint8_t pwrMode;
01377     uint8_t xtalState;
01378 
01379     if (mPwrState == newState) {
01380         return;
01381     }
01382 
01383     /* Read power settings from RF */
01384     pwrMode = MCR20Drv_DirectAccessSPIRead(PWR_MODES);
01385     xtalState = pwrMode & cPWR_MODES_XTALEN;
01386 
01387     switch (newState) {
01388         case gXcvrPwrIdle_c:
01389             pwrMode &= ~(cPWR_MODES_AUTODOZE);
01390             pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE);
01391             break;
01392         case gXcvrPwrAutodoze_c:
01393             pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
01394             break;
01395         case gXcvrPwrDoze_c:
01396             pwrMode &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
01397             pwrMode |= cPWR_MODES_XTALEN;
01398             break;
01399         case gXcvrPwrHibernate_c:
01400             pwrMode &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
01401             break;
01402         default:
01403             return;
01404     }
01405 
01406     mPwrState = newState;
01407     MCR20Drv_DirectAccessSPIWrite(PWR_MODES, pwrMode);
01408 
01409     if (!xtalState && (pwrMode & cPWR_MODES_XTALEN)) {
01410         /* wait for crystal oscillator to complet its warmup */
01411         while ((MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY) != cPWR_MODES_XTAL_READY);
01412         /* wait for radio wakeup from hibernate interrupt */
01413         while ((MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS)) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS));
01414 
01415         MCR20Drv_DirectAccessSPIWrite(IRQSTS2, cIRQSTS2_WAKE_IRQ);
01416     }
01417 }
01418 
01419 /*
01420  * \brief Function reads the energy level on the preselected channel.
01421  *
01422  * \return energy level
01423  */
01424 static uint8_t rf_get_channel_energy(void)
01425 {
01426     uint8_t ccaMode;
01427 
01428     MCR20Drv_IRQ_Disable();
01429     /* RX can start only from Idle state */
01430     if (mPhySeqState != gIdle_c) {
01431         MCR20Drv_IRQ_Enable();
01432         return 0;
01433     }
01434 
01435     /* Set XCVR power state in run mode */
01436     rf_set_power_state(gXcvrRunState_d);
01437 
01438     /* Switch to ED mode */
01439     ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE;
01440     if (ccaMode != gCcaED_c) {
01441         mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c);
01442         mStatusAndControlRegs[PHY_CTRL4] |= gCcaED_c << cPHY_CTRL4_CCATYPE_Shift_c;
01443         MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]);
01444     }
01445 
01446     /* Start ED sequence */
01447     mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c;
01448     MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ);
01449     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
01450     /* Wait for sequence to finish */
01451     while (!(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
01452     /* Set XCVR to Idle */
01453     mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
01454     MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
01455     MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ);
01456 
01457     MCR20Drv_IRQ_Enable();
01458 
01459     return rf_convert_energy_level(MCR20Drv_DirectAccessSPIRead(CCA1_ED_FNL));
01460 }
01461 
01462 /*
01463  * \brief Function converts the energy level from dBm to a 0-255 value.
01464  *
01465  * \param energyLevel in dBm
01466  *
01467  * \return energy level (0-255)
01468  */
01469 static uint8_t rf_convert_energy_level(uint8_t energyLevel)
01470 {
01471     if (energyLevel >= 90) {
01472         /* ED value is below minimum. Return 0x00. */
01473         energyLevel = 0x00;
01474     } else if (energyLevel <= 26) {
01475         /* ED value is above maximum. Return 0xFF. */
01476         energyLevel = 0xFF;
01477     } else {
01478         /* Energy level (-90 dBm to -26 dBm ) --> varies form 0 to 64 */
01479         energyLevel = (90 - energyLevel);
01480         /* Rescale the energy level values to the 0x00-0xff range (0 to 64 translates in 0 to 255) */
01481         /* energyLevel * 3.9844 ~= 4 */
01482         /* Multiply with 4=2^2 by shifting left.
01483         The multiplication will not overflow beacause energyLevel has values between 0 and 63 */
01484         energyLevel <<= 2;
01485     }
01486 
01487     return energyLevel;
01488 }
01489 
01490 static uint8_t rf_scale_lqi(int8_t rssi)
01491 {
01492     uint8_t scaled_lqi;
01493     /*Worst case sensitivity*/
01494     const int8_t rf_sensitivity = -98;
01495 
01496     /*rssi < RF sensitivity*/
01497     if (rssi < rf_sensitivity) {
01498         scaled_lqi = 0;
01499     }
01500     /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/
01501     /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/
01502     else if (rssi < (rf_sensitivity + 10)) {
01503         scaled_lqi = 31;
01504     }
01505     /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/
01506     /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/
01507     else if (rssi < (rf_sensitivity + 20)) {
01508         scaled_lqi = 207;
01509     }
01510     /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/
01511     /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/
01512     else if (rssi < (rf_sensitivity + 30)) {
01513         scaled_lqi = 255;
01514     }
01515     /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/
01516     /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/
01517     else if (rssi < (rf_sensitivity + 40)) {
01518         scaled_lqi = 255;
01519     }
01520     /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/
01521     /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/
01522     else if (rssi < (rf_sensitivity + 50)) {
01523         scaled_lqi = 255;
01524     }
01525     /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/
01526     /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/
01527     else if (rssi < (rf_sensitivity + 60)) {
01528         scaled_lqi = 255;
01529     }
01530     /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/
01531     /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/
01532     else if (rssi < (rf_sensitivity + 70)) {
01533         scaled_lqi = 255;
01534     }
01535     /*rssi > RF saturation*/
01536     else if (rssi > (rf_sensitivity + 80)) {
01537         scaled_lqi = 111;
01538     }
01539     /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/
01540     /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/
01541     else {
01542         scaled_lqi = 255;
01543     }
01544 
01545     return scaled_lqi;
01546 }
01547 
01548 
01549 /*****************************************************************************/
01550 /*              Layer porting to the Freescale driver                        */
01551 /*****************************************************************************/
01552 extern "C" void xcvr_spi_init(uint32_t instance)
01553 {
01554     (void)instance;
01555 }
01556 
01557 extern "C" void RF_IRQ_Init(void)
01558 {
01559     MBED_ASSERT(irq != NULL);
01560     irq->mode(PullUp);
01561     irq->fall(&PHY_InterruptHandler);
01562 }
01563 
01564 extern "C" void RF_IRQ_Enable(void)
01565 {
01566     MBED_ASSERT(irq != NULL);
01567     irq->enable_irq();
01568 }
01569 
01570 extern "C" void RF_IRQ_Disable(void)
01571 {
01572     MBED_ASSERT(irq != NULL);
01573     irq->disable_irq();
01574 }
01575 
01576 extern "C" uint8_t RF_isIRQ_Pending(void)
01577 {
01578     MBED_ASSERT(rf != NULL);
01579     return !irq_pin->read();
01580 }
01581 
01582 extern "C" void RF_RST_Set(int state)
01583 {
01584     MBED_ASSERT(rst != NULL);
01585     *rst = state;
01586 }
01587 
01588 extern "C" void gXcvrAssertCS_d(void)
01589 {
01590     MBED_ASSERT(cs != NULL);
01591     *cs = 0;
01592 }
01593 
01594 extern "C" void gXcvrDeassertCS_d(void)
01595 {
01596     MBED_ASSERT(cs != NULL);
01597     *cs = 1;
01598 }
01599 
01600 extern "C" void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq)
01601 {
01602     MBED_ASSERT(spi != NULL);
01603     (void)instance;
01604     spi->frequency(freq);
01605 }
01606 
01607 extern "C" void xcvr_spi_transfer(uint32_t instance,
01608                                   uint8_t *sendBuffer,
01609                                   uint8_t *receiveBuffer,
01610                                   size_t transferByteCount)
01611 {
01612     MBED_ASSERT(spi != NULL);
01613     (void)instance;
01614     volatile uint8_t dummy;
01615 
01616     if (!transferByteCount) {
01617         return;
01618     }
01619 
01620     if (!sendBuffer && !receiveBuffer) {
01621         return;
01622     }
01623 
01624     while (transferByteCount--) {
01625         if (sendBuffer) {
01626             dummy = *sendBuffer;
01627             sendBuffer++;
01628         } else {
01629             dummy = 0xFF;
01630         }
01631 
01632         dummy = spi->write(dummy);
01633 
01634         if (receiveBuffer) {
01635             *receiveBuffer = dummy;
01636             receiveBuffer++;
01637         }
01638     }
01639 }
01640 
01641 /*****************************************************************************/
01642 /*****************************************************************************/
01643 
01644 static void rf_if_lock(void)
01645 {
01646     platform_enter_critical();
01647 }
01648 
01649 static void rf_if_unlock(void)
01650 {
01651     platform_exit_critical();
01652 }
01653 
01654 NanostackRfPhyMcr20a::NanostackRfPhyMcr20a(PinName spi_mosi, PinName spi_miso,
01655                                            PinName spi_sclk, PinName spi_cs,  PinName spi_rst, PinName spi_irq)
01656     : _spi(spi_mosi, spi_miso, spi_sclk), _rf_cs(spi_cs), _rf_rst(spi_rst, 1),
01657       _rf_irq(spi_irq), _rf_irq_pin(spi_irq),
01658       _irq_thread(osPriorityRealtime, 1024)
01659 {
01660     char mac48[6];
01661     mbed_mac_address(mac48);
01662 
01663     MAC_address[0] = mac48[0];
01664     MAC_address[1] = mac48[1];
01665     MAC_address[2] = mac48[2];
01666     MAC_address[3] = 0xFF;
01667     MAC_address[4] = 0xFF;
01668     MAC_address[5] = mac48[3];
01669     MAC_address[6] = mac48[4];
01670     MAC_address[7] = mac48[5];
01671 }
01672 
01673 NanostackRfPhyMcr20a::~NanostackRfPhyMcr20a()
01674 {
01675     // Do nothing
01676 }
01677 
01678 int8_t NanostackRfPhyMcr20a::rf_register()
01679 {
01680 
01681     rf_if_lock();
01682 
01683     if (rf != NULL) {
01684         rf_if_unlock();
01685         error("Multiple registrations of NanostackRfPhyMcr20a not supported");
01686         return -1;
01687     }
01688 
01689     _irq_thread.start(mbed::callback(PHY_InterruptThread));
01690 
01691     _pins_set();
01692     int8_t radio_id = rf_device_register();
01693     if (radio_id < 0) {
01694         _pins_clear();
01695         rf = NULL;
01696     }
01697 
01698     rf_if_unlock();
01699     return radio_id;
01700 }
01701 
01702 void NanostackRfPhyMcr20a::rf_unregister()
01703 {
01704     rf_if_lock();
01705 
01706     if (rf != this) {
01707         rf_if_unlock();
01708         return;
01709     }
01710 
01711     rf_device_unregister();
01712     rf = NULL;
01713     _pins_clear();
01714 
01715     rf_if_unlock();
01716 }
01717 
01718 void NanostackRfPhyMcr20a::get_mac_address(uint8_t *mac)
01719 {
01720     rf_if_lock();
01721 
01722     memcpy((void *)mac, (void *)MAC_address, sizeof(MAC_address));
01723 
01724     rf_if_unlock();
01725 }
01726 
01727 void NanostackRfPhyMcr20a::set_mac_address(uint8_t *mac)
01728 {
01729     rf_if_lock();
01730 
01731     if (NULL != rf) {
01732         error("NanostackRfPhyAtmel cannot change mac address when running");
01733         rf_if_unlock();
01734         return;
01735     }
01736     memcpy((void *)MAC_address, (void *)mac, sizeof(MAC_address));
01737 
01738     rf_if_unlock();
01739 }
01740 
01741 void NanostackRfPhyMcr20a::_pins_set()
01742 {
01743     spi = &_spi;
01744     cs = &_rf_cs;
01745     rst = &_rf_rst;
01746     irq = &_rf_irq;
01747     irq_pin = &_rf_irq_pin;
01748     irq_thread = &_irq_thread;
01749 }
01750 
01751 void NanostackRfPhyMcr20a::_pins_clear()
01752 {
01753     spi = NULL;
01754     cs = NULL;
01755     rst = NULL;
01756     irq = NULL;
01757     irq_pin = NULL;
01758     irq_thread = NULL;
01759 }
01760 
01761 #if MBED_CONF_MCR20A_PROVIDE_DEFAULT || TARGET_KW24D
01762 
01763 NanostackRfPhy &NanostackRfPhy::get_default_instance()
01764 {
01765     static NanostackRfPhyMcr20a rf_phy(MCR20A_SPI_MOSI, MCR20A_SPI_MISO, MCR20A_SPI_SCLK, MCR20A_SPI_CS, MCR20A_SPI_RST, MCR20A_SPI_IRQ);
01766     return rf_phy;
01767 }
01768 
01769 #endif // MBED_CONF_MCR20A_PROVIDE_DEFAULT
01770 
01771 #endif // MBED_CONF_NANOSTACK_CONFIGURATION