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