Version of easy-connect with the u-blox cellular platforms C027 and C030 added.

Dependents:   HelloMQTT

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