Added support for the WNC M14A2A Cellular LTE Data Module.

Dependencies:   WNC14A2AInterface

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