Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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:14:50 by
