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