Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

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