Added support for the WNC M14A2A Cellular LTE Data Module.
Dependencies: WNC14A2AInterface
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 }
Generated on Tue Jul 12 2022 19:09:04 by 1.7.2