Jim Flynn / Mbed OS wifi_Example

Dependencies:   X_NUCLEO_IKS01A2 mbed-http

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