http
Embed:
(wiki syntax)
Show/hide line numbers
NanostackRfPhyMcr20a.cpp
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "NanostackRfPhyMcr20a.h" 00017 #include "ns_types.h" 00018 #include "platform/arm_hal_interrupt.h" 00019 #include "nanostack/platform/arm_hal_phy.h" 00020 #include <string.h> 00021 #include "rtos.h" 00022 00023 /* Freescale headers which are for C files */ 00024 extern "C" { 00025 #include "MCR20Drv.h " 00026 #include "MCR20Reg.h" 00027 #include "MCR20Overwrites.h " 00028 } 00029 00030 00031 #define RF_BUFFER_SIZE 128 00032 00033 /*Radio RX and TX state definitions*/ 00034 #define RFF_ON 0x01 00035 #define RFF_RX 0x02 00036 #define RFF_TX 0x04 00037 #define RFF_CCA 0x08 00038 00039 #define RF_MODE_NORMAL 0 00040 #define RF_MODE_SNIFFER 1 00041 00042 #define RF_CCA_THRESHOLD 75 /* -75 dBm */ 00043 00044 #define RF_TX_POWER_MAX 0 00045 00046 /* PHY constants in symbols */ 00047 #define gPhyWarmUpTime_c 9 00048 #define gPhySHRDuration_c 10 00049 #define gPhySymbolsPerOctet_c 2 00050 #define gPhyAckWaitDuration_c 54 00051 00052 #define gCcaED_c 0 00053 #define gCcaCCA_MODE1_c 1 00054 00055 #define gXcvrRunState_d gXcvrPwrAutodoze_c 00056 #if !defined(TARGET_KW24D) 00057 #define gXcvrLowPowerState_d gXcvrPwrHibernate_c 00058 #else 00059 #define gXcvrLowPowerState_d gXcvrPwrAutodoze_c 00060 #endif 00061 00062 /* MCR20A XCVR states */ 00063 typedef enum xcvrState_tag{ 00064 gIdle_c, 00065 gRX_c, 00066 gTX_c, 00067 gCCA_c, 00068 gTR_c, 00069 gCCCA_c, 00070 }xcvrState_t; 00071 00072 /* MCR20A XCVR low power states */ 00073 typedef enum xcvrPwrMode_tag{ 00074 gXcvrPwrIdle_c, 00075 gXcvrPwrAutodoze_c, 00076 gXcvrPwrDoze_c, 00077 gXcvrPwrHibernate_c 00078 }xcvrPwrMode_t; 00079 00080 00081 /*RF Part Type*/ 00082 typedef enum 00083 { 00084 FREESCALE_UNKNOW_DEV = 0, 00085 FREESCALE_MCR20A 00086 }rf_trx_part_e; 00087 00088 /*Atmel RF states*/ 00089 typedef enum 00090 { 00091 NOP = 0x00, 00092 BUSY_RX = 0x01, 00093 RF_TX_START = 0x02, 00094 FORCE_TRX_OFF = 0x03, 00095 FORCE_PLL_ON = 0x04, 00096 RX_ON = 0x06, 00097 TRX_OFF = 0x08, 00098 PLL_ON = 0x09, 00099 BUSY_RX_AACK = 0x11, 00100 SLEEP = 0x0F, 00101 RX_AACK_ON = 0x16, 00102 TX_ARET_ON = 0x19 00103 }rf_trx_states_t; 00104 00105 /*RF receive buffer*/ 00106 static uint8_t rf_buffer[RF_BUFFER_SIZE]; 00107 00108 /* TX info */ 00109 static uint8_t radio_tx_power = 0x17; /* 0 dBm */ 00110 static uint8_t mac_tx_handle = 0; 00111 static uint8_t need_ack = 0; 00112 static uint16_t tx_len = 0; 00113 00114 /* RF driver data */ 00115 static xcvrState_t mPhySeqState; 00116 static xcvrPwrMode_t mPwrState; 00117 static phy_device_driver_s device_driver; 00118 static uint8_t mStatusAndControlRegs[8]; 00119 static uint8_t rf_rnd = 0; 00120 static int8_t rf_radio_driver_id = -1; 00121 static uint8_t MAC_address[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 00122 00123 /* Driver instance handle and hardware */ 00124 static NanostackRfPhyMcr20a *rf = NULL; 00125 static SPI *spi = NULL; 00126 static DigitalOut *cs = NULL; 00127 static DigitalOut *rst = NULL; 00128 static InterruptIn *irq = NULL; 00129 static DigitalIn *irq_pin = NULL; 00130 static Thread irq_thread(osPriorityRealtime, 1024); 00131 00132 /* Channel info */ /* 2405 2410 2415 2420 2425 2430 2435 2440 2445 2450 2455 2460 2465 2470 2475 2480 */ 00133 static const uint8_t pll_int[16] = {0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D}; 00134 static const uint16_t pll_frac[16] = {0x2800, 0x5000, 0x7800, 0xA000, 0xC800, 0xF000, 0x1800, 0x4000, 0x6800, 0x9000, 0xB800, 0xE000, 0x0800, 0x3000, 0x5800, 0x8000}; 00135 static uint8_t rf_phy_channel = 0; 00136 00137 /* Channel configurations for 2.4 */ 00138 static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK}; 00139 00140 static const phy_device_channel_page_s phy_channel_pages[] = { 00141 { CHANNEL_PAGE_0, &phy_24ghz}, 00142 { CHANNEL_PAGE_0, NULL} 00143 }; 00144 00145 00146 static rf_trx_part_e rf_radio_type_read(void); 00147 00148 MBED_UNUSED static void rf_ack_wait_timer_start(uint16_t slots); 00149 MBED_UNUSED static void rf_ack_wait_timer_stop(void); 00150 MBED_UNUSED static void rf_handle_cca_ed_done(void); 00151 MBED_UNUSED static void rf_handle_tx_end(void); 00152 MBED_UNUSED static void rf_handle_rx_end(void); 00153 MBED_UNUSED static void rf_on(void); 00154 MBED_UNUSED static void rf_receive(void); 00155 MBED_UNUSED static void rf_poll_trx_state_change(rf_trx_states_t trx_state); 00156 MBED_UNUSED static void rf_init(void); 00157 MBED_UNUSED static void rf_set_mac_address(const uint8_t *ptr); 00158 MBED_UNUSED static int8_t rf_device_register(void); 00159 MBED_UNUSED static void rf_device_unregister(void); 00160 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 ); 00161 MBED_UNUSED static void rf_cca_abort(void); 00162 MBED_UNUSED static void rf_read_mac_address(uint8_t *ptr); 00163 MBED_UNUSED static int8_t rf_read_random(void); 00164 MBED_UNUSED static void rf_calibration_cb(void); 00165 MBED_UNUSED static void rf_init_phy_mode(void); 00166 MBED_UNUSED static void rf_ack_wait_timer_interrupt(void); 00167 MBED_UNUSED static void rf_calibration_timer_interrupt(void); 00168 MBED_UNUSED static void rf_calibration_timer_start(uint32_t slots); 00169 MBED_UNUSED static void rf_cca_timer_interrupt(void); 00170 MBED_UNUSED static void rf_cca_timer_start(uint32_t slots); 00171 MBED_UNUSED static uint16_t rf_get_phy_mtu_size(void); 00172 MBED_UNUSED static uint8_t rf_scale_lqi(int8_t rssi); 00173 00174 /** 00175 * RF output power write 00176 * 00177 * \brief TX power has to be set before network start. 00178 * 00179 * \param power 00180 * See datasheet for TX power settings 00181 * 00182 * \return 0, Supported Value 00183 * \return -1, Not Supported Value 00184 */ 00185 MBED_UNUSED static int8_t rf_tx_power_set(uint8_t power); 00186 MBED_UNUSED static uint8_t rf_tx_power_get(void); 00187 MBED_UNUSED static int8_t rf_enable_antenna_diversity(void); 00188 00189 /* Private functions */ 00190 MBED_UNUSED static void rf_abort(void); 00191 MBED_UNUSED static void rf_promiscuous(uint8_t mode); 00192 MBED_UNUSED static void rf_get_timestamp(uint32_t *pRetClk); 00193 MBED_UNUSED static void rf_set_timeout(uint32_t *pEndTime); 00194 MBED_UNUSED static void rf_set_power_state(xcvrPwrMode_t newState); 00195 MBED_UNUSED static uint8_t rf_if_read_rnd(void); 00196 MBED_UNUSED static uint8_t rf_convert_LQI(uint8_t hwLqi); 00197 MBED_UNUSED static uint8_t rf_get_channel_energy(void); 00198 MBED_UNUSED static uint8_t rf_convert_energy_level(uint8_t energyLevel); 00199 MBED_UNUSED static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi); 00200 MBED_UNUSED static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel); 00201 MBED_UNUSED static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr); 00202 MBED_UNUSED static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr); 00203 MBED_UNUSED static void rf_mac64_read(uint8_t *address); 00204 static void PHY_InterruptThread(void); 00205 static void handle_interrupt(void); 00206 00207 00208 /* 00209 * \brief Read connected radio part. 00210 * 00211 * This function only return valid information when rf_init() is called 00212 * 00213 * \return 00214 */ 00215 static rf_trx_part_e rf_radio_type_read(void) 00216 { 00217 return FREESCALE_MCR20A; 00218 } 00219 00220 /* 00221 * \brief Function initialises and registers the RF driver. 00222 * 00223 * \param none 00224 * 00225 * \return rf_radio_driver_id Driver ID given by NET library 00226 */ 00227 static int8_t rf_device_register(void) 00228 { 00229 rf_trx_part_e radio_type; 00230 00231 rf_init(); 00232 00233 00234 00235 radio_type = rf_radio_type_read(); 00236 if(radio_type == FREESCALE_MCR20A) 00237 { 00238 /*Set pointer to MAC address*/ 00239 device_driver.PHY_MAC = MAC_address; 00240 device_driver.driver_description = (char*)"FREESCALE_MAC"; 00241 00242 //Create setup Used Radio chips 00243 /*Type of RF PHY is SubGHz*/ 00244 device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE; 00245 00246 device_driver.phy_channel_pages = phy_channel_pages; 00247 /*Maximum size of payload is 127*/ 00248 device_driver.phy_MTU = 127; 00249 /*No header in PHY*/ 00250 device_driver.phy_header_length = 0; 00251 /*No tail in PHY*/ 00252 device_driver.phy_tail_length = 0; 00253 /*Set address write function*/ 00254 device_driver.address_write = &rf_address_write; 00255 /*Set RF extension function*/ 00256 device_driver.extension = &rf_extension; 00257 /*Set RF state control function*/ 00258 device_driver.state_control = &rf_interface_state_control; 00259 /*Set transmit function*/ 00260 device_driver.tx = &rf_start_cca; 00261 /*Upper layer callbacks init to NULL*/ 00262 device_driver.phy_rx_cb = NULL; 00263 device_driver.phy_tx_done_cb = NULL; 00264 /*Virtual upper data callback init to NULL*/ 00265 device_driver.arm_net_virtual_rx_cb = NULL; 00266 device_driver.arm_net_virtual_tx_cb = NULL; 00267 00268 /*Register device driver*/ 00269 rf_radio_driver_id = arm_net_phy_register(&device_driver); 00270 } 00271 00272 return rf_radio_driver_id; 00273 } 00274 00275 /* 00276 * \brief Function unregisters the RF driver. 00277 * 00278 * \param none 00279 * 00280 * \return none 00281 */ 00282 static void rf_device_unregister(void) 00283 { 00284 arm_net_phy_unregister(rf_radio_driver_id); 00285 } 00286 00287 /* 00288 * \brief Function returns the generated 8-bit random value for seeding Pseudo-random generator. 00289 * 00290 * \param none 00291 * 00292 * \return random value 00293 */ 00294 static int8_t rf_read_random(void) 00295 { 00296 return rf_rnd; 00297 } 00298 00299 /* 00300 * \brief Function is a call back for ACK wait timeout. 00301 * 00302 * \param none 00303 * 00304 * \return none 00305 */ 00306 static void rf_ack_wait_timer_interrupt(void) 00307 { 00308 /* The packet was transmitted successfully, but no ACK was received */ 00309 if (device_driver.phy_tx_done_cb) { 00310 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1); 00311 } 00312 rf_receive(); 00313 } 00314 00315 /* 00316 * \brief Function is a call back for calibration interval timer. 00317 * 00318 * \param none 00319 * 00320 * \return none 00321 */ 00322 static void rf_calibration_timer_interrupt(void) 00323 { 00324 } 00325 00326 /* 00327 * \brief Function is a call back for cca interval timer. 00328 * 00329 * \param none 00330 * 00331 * \return none 00332 */ 00333 static void rf_cca_timer_interrupt(void) 00334 { 00335 /* CCA time-out handled by Hardware */ 00336 } 00337 00338 00339 /* 00340 * \brief Function starts the ACK wait time-out. 00341 * 00342 * \param slots The ACK wait time-out in [symbols] 00343 * 00344 * \return none 00345 */ 00346 static void rf_ack_wait_timer_start(uint16_t time) 00347 { 00348 uint32_t timeout; 00349 00350 rf_get_timestamp(&timeout); 00351 timeout += time; 00352 rf_set_timeout(&timeout); 00353 } 00354 00355 /* 00356 * \brief Function starts the calibration interval. 00357 * 00358 * \param slots Given slots, resolution 50us 00359 * 00360 * \return none 00361 */ 00362 static void rf_calibration_timer_start(uint32_t slots) 00363 { 00364 (void)slots; 00365 } 00366 00367 /* 00368 * \brief Function starts the CCA timout. 00369 * 00370 * \param slots Given slots, resolution 50us 00371 * 00372 * \return none 00373 */ 00374 static void rf_cca_timer_start(uint32_t slots) 00375 { 00376 (void)slots; 00377 } 00378 00379 /* 00380 * \brief Function stops the ACK wait timeout. 00381 * 00382 * \param none 00383 * 00384 * \return none 00385 */ 00386 static void rf_ack_wait_timer_stop(void) 00387 { 00388 } 00389 00390 /* 00391 * \brief Function reads the MAC address array. 00392 * 00393 * \param ptr Pointer to read array 00394 * 00395 * \return none 00396 */ 00397 static void rf_read_mac_address(uint8_t *ptr) 00398 { 00399 memcpy(ptr, MAC_address, 8); 00400 } 00401 00402 /* 00403 * \brief Function sets the MAC address array. 00404 * 00405 * \param ptr Pointer to given MAC address array 00406 * 00407 * \return none 00408 */ 00409 static void rf_set_mac_address(const uint8_t *ptr) 00410 { 00411 memcpy(MAC_address, ptr, 8); 00412 } 00413 00414 static uint16_t rf_get_phy_mtu_size(void) 00415 { 00416 return device_driver.phy_MTU; 00417 } 00418 00419 /* 00420 * \brief Function writes 16-bit address in RF address filter. 00421 * 00422 * \param short_address Given short address 00423 * 00424 * \return none 00425 */ 00426 static void rf_set_short_adr(uint8_t * short_address) 00427 { 00428 /* Write one register at a time to be accessible from hibernate mode */ 00429 MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_MSB, short_address[0]); 00430 MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_LSB, short_address[1]); 00431 } 00432 00433 /* 00434 * \brief Function writes PAN Id in RF PAN Id filter. 00435 * 00436 * \param pan_id Given PAN Id 00437 * 00438 * \return none 00439 */ 00440 static void rf_set_pan_id(uint8_t *pan_id) 00441 { 00442 /* Write one register at a time to be accessible from hibernate mode */ 00443 MCR20Drv_IndirectAccessSPIWrite(MACPANID0_MSB, pan_id[0]); 00444 MCR20Drv_IndirectAccessSPIWrite(MACPANID0_LSB, pan_id[1]); 00445 } 00446 00447 /* 00448 * \brief Function writes 64-bit address in RF address filter. 00449 * 00450 * \param address Given 64-bit address 00451 * 00452 * \return none 00453 */ 00454 static void rf_set_address(uint8_t *address) 00455 { 00456 /* Write one register at a time to be accessible from hibernate mode */ 00457 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_0, address[7]); 00458 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_8, address[6]); 00459 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_16, address[5]); 00460 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_24, address[4]); 00461 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_32, address[3]); 00462 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_40, address[2]); 00463 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_48, address[1]); 00464 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_56, address[0]); 00465 } 00466 00467 /* 00468 * \brief Function sets the RF channel. 00469 * 00470 * \param ch New channel 00471 * 00472 * \return none 00473 */ 00474 static void rf_channel_set(uint8_t channel) 00475 { 00476 rf_phy_channel = channel; 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 /*Read eui64*/ 00565 rf_mac64_read(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 } 01039 return 0; 01040 } 01041 01042 /* 01043 * \brief Function sets the addresses to RF address filters. 01044 * 01045 * \param address_type Type of address 01046 * \param address_ptr Pointer to given address 01047 * 01048 * \return 0 Success 01049 */ 01050 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) 01051 { 01052 int8_t ret_val = 0; 01053 switch (address_type) 01054 { 01055 /*Set 48-bit address*/ 01056 case PHY_MAC_48BIT: 01057 break; 01058 /*Set 64-bit address*/ 01059 case PHY_MAC_64BIT: 01060 rf_set_address(address_ptr); 01061 break; 01062 /*Set 16-bit address*/ 01063 case PHY_MAC_16BIT: 01064 rf_set_short_adr(address_ptr); 01065 break; 01066 /*Set PAN Id*/ 01067 case PHY_MAC_PANID: 01068 rf_set_pan_id(address_ptr); 01069 break; 01070 } 01071 return ret_val; 01072 } 01073 01074 static void rf_mac64_read(uint8_t *address) 01075 { 01076 /* Write one register at a time to be accessible from hibernate mode */ 01077 address[7] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_0); 01078 address[6] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_8); 01079 address[5] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_16); 01080 address[4] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_24); 01081 address[3] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_32); 01082 address[2] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_40); 01083 address[1] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_48); 01084 address[0] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_56); 01085 01086 } 01087 01088 /* 01089 * \brief Function initialises the ACK wait time and returns the used PHY mode. 01090 * 01091 * \param none 01092 * 01093 * \return tmp Used PHY mode 01094 */ 01095 static void rf_init_phy_mode(void) 01096 { 01097 } 01098 01099 /* 01100 * \brief Function is a RF interrupt vector. End of frame in RX and TX are handled here as well as CCA process interrupt. 01101 * 01102 * \param none 01103 * 01104 * \return none 01105 */ 01106 static void PHY_InterruptHandler(void) 01107 { 01108 /* Disable and clear transceiver(IRQ_B) interrupt */ 01109 MCR20Drv_IRQ_Disable(); 01110 irq_thread.signal_set(1); 01111 } 01112 01113 static void PHY_InterruptThread(void) 01114 { 01115 for (;;) { 01116 osEvent event = irq_thread.signal_wait(0); 01117 if (event.status != osEventSignal) { 01118 continue; 01119 } 01120 handle_interrupt(); 01121 } 01122 } 01123 01124 static void handle_interrupt(void) 01125 { 01126 uint8_t xcvseqCopy; 01127 01128 //MCR20Drv_IRQ_Clear(); 01129 01130 /* Read transceiver interrupt status and control registers */ 01131 mStatusAndControlRegs[IRQSTS1] = 01132 MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 7); 01133 01134 xcvseqCopy = mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ; 01135 01136 /* Flter Fail IRQ */ 01137 if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_FILTERFAIL_IRQ) && 01138 !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_FILTERFAIL_MSK) ) 01139 { 01140 if( xcvseqCopy == gRX_c ) 01141 { 01142 /* Abort current SEQ */ 01143 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); 01144 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); 01145 /* Wait for Sequence Idle */ 01146 while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0); 01147 /* Clear IRQ flags: */ 01148 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ); 01149 /* Restart Rx asap */ 01150 mStatusAndControlRegs[PHY_CTRL1] |= gRX_c; 01151 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); 01152 } 01153 } 01154 01155 /* TMR3 IRQ: ACK wait time-out */ 01156 if( (mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3IRQ) && 01157 !(mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3MSK) ) 01158 { 01159 /* Disable TMR3 IRQ */ 01160 mStatusAndControlRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK; 01161 01162 if( xcvseqCopy == gTR_c ) 01163 { 01164 /* Set XCVR to Idle */ 01165 mPhySeqState = gIdle_c; 01166 mStatusAndControlRegs[PHY_CTRL1] &= ~( cPHY_CTRL1_XCVSEQ ); 01167 /* Mask interrupts */ 01168 mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK; 01169 /* Sync settings with XCVR */ 01170 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5); 01171 01172 rf_ack_wait_timer_interrupt(); 01173 MCR20Drv_IRQ_Enable(); 01174 return; 01175 } 01176 } 01177 01178 /* Sequencer interrupt, the autosequence has completed */ 01179 if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_SEQIRQ) && 01180 !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_SEQMSK) ) 01181 { 01182 /* Set XCVR to Idle */ 01183 mPhySeqState = gIdle_c; 01184 mStatusAndControlRegs[PHY_CTRL1] &= ~( cPHY_CTRL1_XCVSEQ ); 01185 /* Mask interrupts */ 01186 mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK; 01187 /* Sync settings with XCVR */ 01188 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5); 01189 01190 /* PLL unlock, the autosequence has been aborted due to PLL unlock */ 01191 if( mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_PLL_UNLOCK_IRQ ) 01192 { 01193 if(xcvseqCopy == gRX_c) 01194 { 01195 rf_receive(); 01196 } 01197 MCR20Drv_IRQ_Enable(); 01198 return; 01199 } 01200 01201 switch(xcvseqCopy) 01202 { 01203 case gTX_c: 01204 case gTR_c: 01205 rf_handle_tx_end(); 01206 break; 01207 01208 case gRX_c: 01209 rf_handle_rx_end(); 01210 break; 01211 01212 case gCCA_c: 01213 rf_handle_cca_ed_done(); 01214 break; 01215 01216 default: 01217 break; 01218 } 01219 01220 MCR20Drv_IRQ_Enable(); 01221 return; 01222 } 01223 /* Other IRQ. Clear XCVR interrupt flags */ 01224 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3); 01225 MCR20Drv_IRQ_Enable(); 01226 } 01227 01228 /* 01229 * \brief Function forces the XCVR to Idle state. 01230 * 01231 * \param none 01232 * 01233 * \return none 01234 */ 01235 static void rf_abort(void) 01236 { 01237 /* Mask XCVR irq */ 01238 MCR20Drv_IRQ_Disable(); 01239 01240 mPhySeqState = gIdle_c; 01241 01242 mStatusAndControlRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 5); 01243 01244 /* Mask SEQ interrupt */ 01245 mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_SEQMSK; 01246 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]); 01247 01248 if( (mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c ) 01249 { 01250 /* Abort current SEQ */ 01251 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); 01252 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); 01253 01254 /* Wait for Sequence Idle (if not already) */ 01255 while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0); 01256 //while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ)); 01257 mStatusAndControlRegs[IRQSTS1] |= cIRQSTS1_SEQIRQ; 01258 } 01259 01260 /* Clear all PP IRQ bits to avoid unexpected interrupts and mask TMR3 interrupt. 01261 Do not change TMR IRQ status. */ 01262 mStatusAndControlRegs[IRQSTS3] &= 0xF0; 01263 mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ); 01264 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3); 01265 01266 /* Unmask XCVR irq */ 01267 MCR20Drv_IRQ_Enable(); 01268 } 01269 01270 /* 01271 * \brief Function reads a time-stamp value from XCVR [symbols] 01272 * 01273 * \param pEndTime pointer to location where time-stamp will be stored 01274 * 01275 * \return none 01276 */ 01277 static void rf_get_timestamp(uint32_t *pRetClk) 01278 { 01279 if(NULL == pRetClk) 01280 { 01281 return; 01282 } 01283 01284 platform_enter_critical(); 01285 01286 *pRetClk = 0; 01287 MCR20Drv_DirectAccessSPIMultiByteRead(EVENT_TMR_LSB, (uint8_t *) pRetClk, 3); 01288 01289 platform_exit_critical(); 01290 } 01291 01292 /* 01293 * \brief Function set a time-out to an XCVR sequence. 01294 * 01295 * \param pEndTime pointer to the sequence time-out value [symbols] 01296 * 01297 * \return none 01298 */ 01299 static void rf_set_timeout(uint32_t *pEndTime) 01300 { 01301 uint8_t phyReg; 01302 01303 if(NULL == pEndTime) 01304 { 01305 return; 01306 } 01307 01308 platform_enter_critical(); 01309 01310 phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3); 01311 phyReg &= 0xF0; /* do not change IRQ status */ 01312 phyReg |= (cIRQSTS3_TMR3MSK); /* mask TMR3 interrupt */ 01313 MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg); 01314 01315 MCR20Drv_DirectAccessSPIMultiByteWrite(T3CMP_LSB, (uint8_t *) pEndTime, 3); 01316 01317 phyReg &= ~(cIRQSTS3_TMR3MSK); /* unmask TMR3 interrupt */ 01318 phyReg |= (cIRQSTS3_TMR3IRQ); /* aknowledge TMR3 IRQ */ 01319 MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg); 01320 01321 platform_exit_critical(); 01322 } 01323 01324 /* 01325 * \brief Function reads a random number from RF. 01326 * 01327 * \param none 01328 * 01329 * \return 8-bit random number 01330 */ 01331 static uint8_t rf_if_read_rnd(void) 01332 { 01333 uint8_t phyReg; 01334 01335 MCR20Drv_IRQ_Disable(); 01336 /* Check if XCVR is idle */ 01337 phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1); 01338 01339 if( (phyReg & cPHY_CTRL1_XCVSEQ) == gIdle_c ) 01340 { 01341 /* Program a new sequence */ 01342 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyReg | gCCA_c); 01343 /* Wait for sequence to finish */ 01344 while( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ) ); 01345 /* Clear interrupt flag */ 01346 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ); 01347 } 01348 01349 MCR20Drv_IRQ_Enable(); 01350 01351 return MCR20Drv_IndirectAccessSPIRead(_RNG); 01352 } 01353 01354 /* 01355 * \brief Function converts LQI into RSSI. 01356 * 01357 * \param LQI 01358 * 01359 * \return RSSI 01360 */ 01361 static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi) 01362 { 01363 int32_t rssi = (50*lqi - 16820) / 163; 01364 return (int8_t)rssi; 01365 } 01366 01367 /* 01368 * \brief Function scale the LQI value reported by RF into a 0-255 value. 01369 * 01370 * \param hwLqi - the LQI value reported by RF 01371 * 01372 * \return scaled LQI 01373 */ 01374 static uint8_t rf_convert_LQI(uint8_t hwLqi) 01375 { 01376 uint32_t tmpLQI; 01377 01378 /* LQI Saturation Level */ 01379 if (hwLqi >= 230) 01380 { 01381 return 0xFF; 01382 } 01383 else if (hwLqi <= 9) 01384 { 01385 return 0; 01386 } 01387 else 01388 { 01389 /* Rescale the LQI values from min to saturation to the 0x00 - 0xFF range */ 01390 /* The LQI value mst be multiplied by ~1.1087 */ 01391 /* tmpLQI = hwLqi * 7123 ~= hwLqi * 65536 * 0.1087 = hwLqi * 2^16 * 0.1087*/ 01392 tmpLQI = ((uint32_t)hwLqi * (uint32_t)7123 ); 01393 /* tmpLQI = (tmpLQI / 2^16) + hwLqi */ 01394 tmpLQI = (uint32_t)(tmpLQI >> 16) + (uint32_t)hwLqi; 01395 01396 return (uint8_t)tmpLQI; 01397 } 01398 } 01399 01400 /* 01401 * \brief Function enables/disables Rx promiscuous mode. 01402 * 01403 * \param state of XCVR promiscuous mode 01404 * 01405 * \return none 01406 */ 01407 static void rf_promiscuous(uint8_t state) 01408 { 01409 uint8_t rxFrameFltReg, phyCtrl4Reg; 01410 01411 rxFrameFltReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER); 01412 phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4); 01413 01414 if( state ) 01415 { 01416 /* FRM_VER[1:0] = b00. 00: Any FrameVersion accepted (0,1,2 & 3) */ 01417 /* All frame types accepted*/ 01418 phyCtrl4Reg |= cPHY_CTRL4_PROMISCUOUS; 01419 rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER); 01420 rxFrameFltReg |= (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT); 01421 } 01422 else 01423 { 01424 phyCtrl4Reg &= ~cPHY_CTRL4_PROMISCUOUS; 01425 /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others */ 01426 /* Beacon, Data and MAC command frame types accepted */ 01427 rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER); 01428 rxFrameFltReg |= (0x03 << cRX_FRAME_FLT_FRM_VER_Shift_c); 01429 rxFrameFltReg &= ~(cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT); 01430 } 01431 01432 MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, rxFrameFltReg); 01433 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, phyCtrl4Reg); 01434 } 01435 01436 /* 01437 * \brief Function used to switch XCVR power state. 01438 * 01439 * \param state The XCVR power mode 01440 * 01441 * \return none 01442 */ 01443 static void rf_set_power_state(xcvrPwrMode_t newState) 01444 { 01445 uint8_t pwrMode; 01446 uint8_t xtalState; 01447 01448 if( mPwrState == newState ) 01449 { 01450 return; 01451 } 01452 01453 /* Read power settings from RF */ 01454 pwrMode = MCR20Drv_DirectAccessSPIRead(PWR_MODES); 01455 xtalState = pwrMode & cPWR_MODES_XTALEN; 01456 01457 switch( newState ) 01458 { 01459 case gXcvrPwrIdle_c: 01460 pwrMode &= ~(cPWR_MODES_AUTODOZE); 01461 pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE); 01462 break; 01463 case gXcvrPwrAutodoze_c: 01464 pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); 01465 break; 01466 case gXcvrPwrDoze_c: 01467 pwrMode &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); 01468 pwrMode |= cPWR_MODES_XTALEN; 01469 break; 01470 case gXcvrPwrHibernate_c: 01471 pwrMode &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE); 01472 break; 01473 default: 01474 return; 01475 } 01476 01477 mPwrState = newState; 01478 MCR20Drv_DirectAccessSPIWrite(PWR_MODES, pwrMode); 01479 01480 if( !xtalState && (pwrMode & cPWR_MODES_XTALEN)) 01481 { 01482 /* wait for crystal oscillator to complet its warmup */ 01483 while( ( MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY ) != cPWR_MODES_XTAL_READY); 01484 /* wait for radio wakeup from hibernate interrupt */ 01485 while( ( MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ); 01486 01487 MCR20Drv_DirectAccessSPIWrite(IRQSTS2, cIRQSTS2_WAKE_IRQ); 01488 } 01489 } 01490 01491 /* 01492 * \brief Function reads the energy level on the preselected channel. 01493 * 01494 * \return energy level 01495 */ 01496 static uint8_t rf_get_channel_energy(void) 01497 { 01498 uint8_t ccaMode; 01499 01500 MCR20Drv_IRQ_Disable(); 01501 /* RX can start only from Idle state */ 01502 if( mPhySeqState != gIdle_c ) 01503 { 01504 MCR20Drv_IRQ_Enable(); 01505 return 0; 01506 } 01507 01508 /* Set XCVR power state in run mode */ 01509 rf_set_power_state(gXcvrRunState_d); 01510 01511 /* Switch to ED mode */ 01512 ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE; 01513 if( ccaMode != gCcaED_c ) 01514 { 01515 mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c); 01516 mStatusAndControlRegs[PHY_CTRL4] |= gCcaED_c << cPHY_CTRL4_CCATYPE_Shift_c; 01517 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]); 01518 } 01519 01520 /* Start ED sequence */ 01521 mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c; 01522 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ); 01523 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); 01524 /* Wait for sequence to finish */ 01525 while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ)); 01526 /* Set XCVR to Idle */ 01527 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ); 01528 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]); 01529 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ); 01530 01531 MCR20Drv_IRQ_Enable(); 01532 01533 return rf_convert_energy_level(MCR20Drv_DirectAccessSPIRead(CCA1_ED_FNL)); 01534 } 01535 01536 /* 01537 * \brief Function converts the energy level from dBm to a 0-255 value. 01538 * 01539 * \param energyLevel in dBm 01540 * 01541 * \return energy level (0-255) 01542 */ 01543 static uint8_t rf_convert_energy_level(uint8_t energyLevel) 01544 { 01545 if(energyLevel >= 90) 01546 { 01547 /* ED value is below minimum. Return 0x00. */ 01548 energyLevel = 0x00; 01549 } 01550 else if(energyLevel <= 26) 01551 { 01552 /* ED value is above maximum. Return 0xFF. */ 01553 energyLevel = 0xFF; 01554 } 01555 else 01556 { 01557 /* Energy level (-90 dBm to -26 dBm ) --> varies form 0 to 64 */ 01558 energyLevel = (90 - energyLevel); 01559 /* Rescale the energy level values to the 0x00-0xff range (0 to 64 translates in 0 to 255) */ 01560 /* energyLevel * 3.9844 ~= 4 */ 01561 /* Multiply with 4=2^2 by shifting left. 01562 The multiplication will not overflow beacause energyLevel has values between 0 and 63 */ 01563 energyLevel <<= 2; 01564 } 01565 01566 return energyLevel; 01567 } 01568 01569 static uint8_t rf_scale_lqi(int8_t rssi) 01570 { 01571 uint8_t scaled_lqi; 01572 /*Worst case sensitivity*/ 01573 const int8_t rf_sensitivity = -98; 01574 01575 /*rssi < RF sensitivity*/ 01576 if(rssi < rf_sensitivity) 01577 scaled_lqi=0; 01578 /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/ 01579 /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/ 01580 else if(rssi < (rf_sensitivity + 10)) 01581 scaled_lqi=31; 01582 /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/ 01583 /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/ 01584 else if(rssi < (rf_sensitivity + 20)) 01585 scaled_lqi=207; 01586 /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/ 01587 /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/ 01588 else if(rssi < (rf_sensitivity + 30)) 01589 scaled_lqi=255; 01590 /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/ 01591 /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/ 01592 else if(rssi < (rf_sensitivity + 40)) 01593 scaled_lqi=255; 01594 /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/ 01595 /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/ 01596 else if(rssi < (rf_sensitivity + 50)) 01597 scaled_lqi=255; 01598 /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/ 01599 /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/ 01600 else if(rssi < (rf_sensitivity + 60)) 01601 scaled_lqi=255; 01602 /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/ 01603 /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/ 01604 else if(rssi < (rf_sensitivity + 70)) 01605 scaled_lqi=255; 01606 /*rssi > RF saturation*/ 01607 else if(rssi > (rf_sensitivity + 80)) 01608 scaled_lqi=111; 01609 /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/ 01610 /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/ 01611 else 01612 scaled_lqi=255; 01613 01614 return scaled_lqi; 01615 } 01616 01617 01618 /*****************************************************************************/ 01619 /* Layer porting to the Freescale driver */ 01620 /*****************************************************************************/ 01621 extern "C" void xcvr_spi_init(uint32_t instance) 01622 { 01623 (void)instance; 01624 } 01625 01626 extern "C" void RF_IRQ_Init(void) { 01627 MBED_ASSERT(irq != NULL); 01628 irq->mode(PullUp); 01629 irq->fall(&PHY_InterruptHandler); 01630 } 01631 01632 extern "C" void RF_IRQ_Enable(void) { 01633 MBED_ASSERT(irq != NULL); 01634 irq->enable_irq(); 01635 } 01636 01637 extern "C" void RF_IRQ_Disable(void) { 01638 MBED_ASSERT(irq != NULL); 01639 irq->disable_irq(); 01640 } 01641 01642 extern "C" uint8_t RF_isIRQ_Pending(void) { 01643 MBED_ASSERT(rf != NULL); 01644 return !irq_pin->read(); 01645 } 01646 01647 extern "C" void RF_RST_Set(int state) { 01648 MBED_ASSERT(rst != NULL); 01649 *rst = state; 01650 } 01651 01652 extern "C" void gXcvrAssertCS_d(void) 01653 { 01654 MBED_ASSERT(cs != NULL); 01655 *cs = 0; 01656 } 01657 01658 extern "C" void gXcvrDeassertCS_d(void) 01659 { 01660 MBED_ASSERT(cs != NULL); 01661 *cs = 1; 01662 } 01663 01664 extern "C" void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq) 01665 { 01666 MBED_ASSERT(spi != NULL); 01667 (void)instance; 01668 spi->frequency(freq); 01669 } 01670 01671 extern "C" void xcvr_spi_transfer(uint32_t instance, 01672 uint8_t * sendBuffer, 01673 uint8_t * receiveBuffer, 01674 size_t transferByteCount) 01675 { 01676 MBED_ASSERT(spi != NULL); 01677 (void)instance; 01678 volatile uint8_t dummy; 01679 01680 if( !transferByteCount ) 01681 return; 01682 01683 if( !sendBuffer && !receiveBuffer ) 01684 return; 01685 01686 while( transferByteCount-- ) 01687 { 01688 if( sendBuffer ) 01689 { 01690 dummy = *sendBuffer; 01691 sendBuffer++; 01692 } 01693 else 01694 { 01695 dummy = 0xFF; 01696 } 01697 01698 dummy = spi->write(dummy); 01699 01700 if( receiveBuffer ) 01701 { 01702 *receiveBuffer = dummy; 01703 receiveBuffer++; 01704 } 01705 } 01706 } 01707 01708 /*****************************************************************************/ 01709 /*****************************************************************************/ 01710 01711 static void rf_if_lock(void) 01712 { 01713 platform_enter_critical(); 01714 } 01715 01716 static void rf_if_unlock(void) 01717 { 01718 platform_exit_critical(); 01719 } 01720 01721 NanostackRfPhyMcr20a::NanostackRfPhyMcr20a(PinName spi_mosi, PinName spi_miso, 01722 PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_irq) 01723 : _spi(spi_mosi, spi_miso, spi_sclk), _rf_cs(spi_cs), _rf_rst(spi_rst, 1), 01724 _rf_irq(spi_irq), _rf_irq_pin(spi_irq) 01725 { 01726 // Do nothing 01727 } 01728 01729 NanostackRfPhyMcr20a::~NanostackRfPhyMcr20a() 01730 { 01731 // Do nothing 01732 } 01733 01734 int8_t NanostackRfPhyMcr20a::rf_register() 01735 { 01736 01737 rf_if_lock(); 01738 01739 if (rf != NULL) { 01740 rf_if_unlock(); 01741 error("Multiple registrations of NanostackRfPhyMcr20a not supported"); 01742 return -1; 01743 } 01744 01745 irq_thread.start(mbed::callback(PHY_InterruptThread)); 01746 01747 _pins_set(); 01748 int8_t radio_id = rf_device_register(); 01749 if (radio_id < 0) { 01750 _pins_clear(); 01751 rf = NULL; 01752 } 01753 01754 rf_if_unlock(); 01755 return radio_id; 01756 } 01757 01758 void NanostackRfPhyMcr20a::rf_unregister() 01759 { 01760 rf_if_lock(); 01761 01762 if (rf != this) { 01763 rf_if_unlock(); 01764 return; 01765 } 01766 01767 rf_device_unregister(); 01768 rf = NULL; 01769 _pins_clear(); 01770 01771 rf_if_unlock(); 01772 } 01773 01774 void NanostackRfPhyMcr20a::get_mac_address(uint8_t *mac) 01775 { 01776 rf_if_lock(); 01777 01778 memcpy((void*)mac, (void*)MAC_address, sizeof(MAC_address)); 01779 01780 rf_if_unlock(); 01781 } 01782 01783 void NanostackRfPhyMcr20a::set_mac_address(uint8_t *mac) 01784 { 01785 rf_if_lock(); 01786 01787 if (NULL != rf) { 01788 error("NanostackRfPhyAtmel cannot change mac address when running"); 01789 rf_if_unlock(); 01790 return; 01791 } 01792 memcpy((void*)MAC_address, (void*)mac, sizeof(MAC_address)); 01793 01794 rf_if_unlock(); 01795 } 01796 01797 void NanostackRfPhyMcr20a::_pins_set() 01798 { 01799 spi = &_spi; 01800 cs = &_rf_cs; 01801 rst = &_rf_rst; 01802 irq = &_rf_irq; 01803 irq_pin = &_rf_irq_pin; 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 }
Generated on Wed Jul 13 2022 01:16:06 by
1.7.2