RTC auf true
components/802_15_4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp@2:7aab896b1a3b, 2019-03-13 (annotated)
- Committer:
- kevman
- Date:
- Wed Mar 13 11:03:24 2019 +0000
- Revision:
- 2:7aab896b1a3b
2019-03-13
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kevman | 2:7aab896b1a3b | 1 | /* |
kevman | 2:7aab896b1a3b | 2 | * Copyright (c) 2014-2015 ARM Limited. All rights reserved. |
kevman | 2:7aab896b1a3b | 3 | * SPDX-License-Identifier: Apache-2.0 |
kevman | 2:7aab896b1a3b | 4 | * Licensed under the Apache License, Version 2.0 (the License); you may |
kevman | 2:7aab896b1a3b | 5 | * not use this file except in compliance with the License. |
kevman | 2:7aab896b1a3b | 6 | * You may obtain a copy of the License at |
kevman | 2:7aab896b1a3b | 7 | * |
kevman | 2:7aab896b1a3b | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
kevman | 2:7aab896b1a3b | 9 | * |
kevman | 2:7aab896b1a3b | 10 | * Unless required by applicable law or agreed to in writing, software |
kevman | 2:7aab896b1a3b | 11 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
kevman | 2:7aab896b1a3b | 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
kevman | 2:7aab896b1a3b | 13 | * See the License for the specific language governing permissions and |
kevman | 2:7aab896b1a3b | 14 | * limitations under the License. |
kevman | 2:7aab896b1a3b | 15 | */ |
kevman | 2:7aab896b1a3b | 16 | #include <string.h> |
kevman | 2:7aab896b1a3b | 17 | |
kevman | 2:7aab896b1a3b | 18 | #if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI && DEVICE_I2C |
kevman | 2:7aab896b1a3b | 19 | |
kevman | 2:7aab896b1a3b | 20 | #include "platform/arm_hal_interrupt.h" |
kevman | 2:7aab896b1a3b | 21 | #include "nanostack/platform/arm_hal_phy.h" |
kevman | 2:7aab896b1a3b | 22 | #include "ns_types.h" |
kevman | 2:7aab896b1a3b | 23 | #include "NanostackRfPhyAtmel.h" |
kevman | 2:7aab896b1a3b | 24 | #include "randLIB.h" |
kevman | 2:7aab896b1a3b | 25 | #include "AT86RFReg.h" |
kevman | 2:7aab896b1a3b | 26 | #include "nanostack/platform/arm_hal_phy.h" |
kevman | 2:7aab896b1a3b | 27 | #include "mbed_trace.h" |
kevman | 2:7aab896b1a3b | 28 | #include "mbed_toolchain.h" |
kevman | 2:7aab896b1a3b | 29 | |
kevman | 2:7aab896b1a3b | 30 | #define TRACE_GROUP "AtRF" |
kevman | 2:7aab896b1a3b | 31 | |
kevman | 2:7aab896b1a3b | 32 | /*Worst case sensitivity*/ |
kevman | 2:7aab896b1a3b | 33 | #define RF_DEFAULT_SENSITIVITY -88 |
kevman | 2:7aab896b1a3b | 34 | /*Run calibration every 5 minutes*/ |
kevman | 2:7aab896b1a3b | 35 | #define RF_CALIBRATION_INTERVAL 6000000 |
kevman | 2:7aab896b1a3b | 36 | /*Wait ACK for 2.5ms*/ |
kevman | 2:7aab896b1a3b | 37 | #define RF_ACK_WAIT_DEFAULT_TIMEOUT 50 |
kevman | 2:7aab896b1a3b | 38 | /*Base CCA backoff (50us units) - substitutes for Inter-Frame Spacing*/ |
kevman | 2:7aab896b1a3b | 39 | #define RF_CCA_BASE_BACKOFF 13 /* 650us */ |
kevman | 2:7aab896b1a3b | 40 | /*CCA random backoff (50us units)*/ |
kevman | 2:7aab896b1a3b | 41 | #define RF_CCA_RANDOM_BACKOFF 51 /* 2550us */ |
kevman | 2:7aab896b1a3b | 42 | |
kevman | 2:7aab896b1a3b | 43 | #define RF_MTU 127 |
kevman | 2:7aab896b1a3b | 44 | |
kevman | 2:7aab896b1a3b | 45 | #define RF_PHY_MODE OQPSK_SIN_250 |
kevman | 2:7aab896b1a3b | 46 | |
kevman | 2:7aab896b1a3b | 47 | /*Radio RX and TX state definitions*/ |
kevman | 2:7aab896b1a3b | 48 | #define RFF_ON 0x01 |
kevman | 2:7aab896b1a3b | 49 | #define RFF_RX 0x02 |
kevman | 2:7aab896b1a3b | 50 | #define RFF_TX 0x04 |
kevman | 2:7aab896b1a3b | 51 | #define RFF_CCA 0x08 |
kevman | 2:7aab896b1a3b | 52 | |
kevman | 2:7aab896b1a3b | 53 | typedef enum |
kevman | 2:7aab896b1a3b | 54 | { |
kevman | 2:7aab896b1a3b | 55 | RF_MODE_NORMAL = 0, |
kevman | 2:7aab896b1a3b | 56 | RF_MODE_SNIFFER = 1, |
kevman | 2:7aab896b1a3b | 57 | RF_MODE_ED = 2 |
kevman | 2:7aab896b1a3b | 58 | }rf_mode_t; |
kevman | 2:7aab896b1a3b | 59 | |
kevman | 2:7aab896b1a3b | 60 | /*Atmel RF Part Type*/ |
kevman | 2:7aab896b1a3b | 61 | typedef enum |
kevman | 2:7aab896b1a3b | 62 | { |
kevman | 2:7aab896b1a3b | 63 | ATMEL_UNKNOW_DEV = 0, |
kevman | 2:7aab896b1a3b | 64 | ATMEL_AT86RF212, |
kevman | 2:7aab896b1a3b | 65 | ATMEL_AT86RF231, // No longer supported (doesn't give ED+status on frame read) |
kevman | 2:7aab896b1a3b | 66 | ATMEL_AT86RF233 |
kevman | 2:7aab896b1a3b | 67 | }rf_trx_part_e; |
kevman | 2:7aab896b1a3b | 68 | |
kevman | 2:7aab896b1a3b | 69 | /*Atmel RF states*/ |
kevman | 2:7aab896b1a3b | 70 | typedef enum |
kevman | 2:7aab896b1a3b | 71 | { |
kevman | 2:7aab896b1a3b | 72 | NOP = 0x00, |
kevman | 2:7aab896b1a3b | 73 | BUSY_RX = 0x01, |
kevman | 2:7aab896b1a3b | 74 | BUSY_TX = 0x02, |
kevman | 2:7aab896b1a3b | 75 | RF_TX_START = 0x02, |
kevman | 2:7aab896b1a3b | 76 | FORCE_TRX_OFF = 0x03, |
kevman | 2:7aab896b1a3b | 77 | FORCE_PLL_ON = 0x04, |
kevman | 2:7aab896b1a3b | 78 | RX_ON = 0x06, |
kevman | 2:7aab896b1a3b | 79 | TRX_OFF = 0x08, |
kevman | 2:7aab896b1a3b | 80 | PLL_ON = 0x09, |
kevman | 2:7aab896b1a3b | 81 | BUSY_RX_AACK = 0x11, |
kevman | 2:7aab896b1a3b | 82 | SLEEP = 0x0F, |
kevman | 2:7aab896b1a3b | 83 | RX_AACK_ON = 0x16, |
kevman | 2:7aab896b1a3b | 84 | TX_ARET_ON = 0x19, |
kevman | 2:7aab896b1a3b | 85 | STATE_TRANSITION_IN_PROGRESS = 0x1F |
kevman | 2:7aab896b1a3b | 86 | }rf_trx_states_t; |
kevman | 2:7aab896b1a3b | 87 | |
kevman | 2:7aab896b1a3b | 88 | static const uint8_t *rf_tx_data; // Points to Nanostack's buffer |
kevman | 2:7aab896b1a3b | 89 | static uint8_t rf_tx_length; |
kevman | 2:7aab896b1a3b | 90 | /*ACK wait duration changes depending on data rate*/ |
kevman | 2:7aab896b1a3b | 91 | static uint16_t rf_ack_wait_duration = RF_ACK_WAIT_DEFAULT_TIMEOUT; |
kevman | 2:7aab896b1a3b | 92 | |
kevman | 2:7aab896b1a3b | 93 | static int8_t rf_sensitivity = RF_DEFAULT_SENSITIVITY; |
kevman | 2:7aab896b1a3b | 94 | static rf_mode_t rf_mode = RF_MODE_NORMAL; |
kevman | 2:7aab896b1a3b | 95 | static uint8_t radio_tx_power = 0x00; // Default to +4dBm |
kevman | 2:7aab896b1a3b | 96 | static uint8_t rf_phy_channel = 12; |
kevman | 2:7aab896b1a3b | 97 | static uint8_t rf_tuned = 1; |
kevman | 2:7aab896b1a3b | 98 | static uint8_t rf_use_antenna_diversity = 0; |
kevman | 2:7aab896b1a3b | 99 | static int16_t expected_ack_sequence = -1; |
kevman | 2:7aab896b1a3b | 100 | static uint8_t rf_rx_mode = 0; |
kevman | 2:7aab896b1a3b | 101 | static uint8_t rf_flags = 0; |
kevman | 2:7aab896b1a3b | 102 | static int8_t rf_radio_driver_id = -1; |
kevman | 2:7aab896b1a3b | 103 | static phy_device_driver_s device_driver; |
kevman | 2:7aab896b1a3b | 104 | static uint8_t mac_tx_handle = 0; |
kevman | 2:7aab896b1a3b | 105 | static uint8_t xah_ctrl_1; |
kevman | 2:7aab896b1a3b | 106 | |
kevman | 2:7aab896b1a3b | 107 | /* Channel configurations for 2.4 and sub-GHz */ |
kevman | 2:7aab896b1a3b | 108 | static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK}; |
kevman | 2:7aab896b1a3b | 109 | static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 2000000U, 250000U, 11U, M_OQPSK}; |
kevman | 2:7aab896b1a3b | 110 | |
kevman | 2:7aab896b1a3b | 111 | static const phy_device_channel_page_s phy_channel_pages[] = { |
kevman | 2:7aab896b1a3b | 112 | { CHANNEL_PAGE_0, &phy_24ghz}, |
kevman | 2:7aab896b1a3b | 113 | { CHANNEL_PAGE_2, &phy_subghz}, |
kevman | 2:7aab896b1a3b | 114 | { CHANNEL_PAGE_0, NULL} |
kevman | 2:7aab896b1a3b | 115 | }; |
kevman | 2:7aab896b1a3b | 116 | |
kevman | 2:7aab896b1a3b | 117 | /** |
kevman | 2:7aab896b1a3b | 118 | * RF output power write |
kevman | 2:7aab896b1a3b | 119 | * |
kevman | 2:7aab896b1a3b | 120 | * \brief TX power has to be set before network start. |
kevman | 2:7aab896b1a3b | 121 | * |
kevman | 2:7aab896b1a3b | 122 | * \param power |
kevman | 2:7aab896b1a3b | 123 | * AT86RF233 |
kevman | 2:7aab896b1a3b | 124 | * 0 = 4 dBm |
kevman | 2:7aab896b1a3b | 125 | * 1 = 3.7 dBm |
kevman | 2:7aab896b1a3b | 126 | * 2 = 3.4 dBm |
kevman | 2:7aab896b1a3b | 127 | * 3 = 3 dBm |
kevman | 2:7aab896b1a3b | 128 | * 4 = 2.5 dBm |
kevman | 2:7aab896b1a3b | 129 | * 5 = 2 dBm |
kevman | 2:7aab896b1a3b | 130 | * 6 = 1 dBm |
kevman | 2:7aab896b1a3b | 131 | * 7 = 0 dBm |
kevman | 2:7aab896b1a3b | 132 | * 8 = -1 dBm |
kevman | 2:7aab896b1a3b | 133 | * 9 = -2 dBm |
kevman | 2:7aab896b1a3b | 134 | * 10 = -3 dBm |
kevman | 2:7aab896b1a3b | 135 | * 11 = -4 dBm |
kevman | 2:7aab896b1a3b | 136 | * 12 = -6 dBm |
kevman | 2:7aab896b1a3b | 137 | * 13 = -8 dBm |
kevman | 2:7aab896b1a3b | 138 | * 14 = -12 dBm |
kevman | 2:7aab896b1a3b | 139 | * 15 = -17 dBm |
kevman | 2:7aab896b1a3b | 140 | * |
kevman | 2:7aab896b1a3b | 141 | * AT86RF212B |
kevman | 2:7aab896b1a3b | 142 | * See datasheet for TX power settings |
kevman | 2:7aab896b1a3b | 143 | * |
kevman | 2:7aab896b1a3b | 144 | * \return 0, Supported Value |
kevman | 2:7aab896b1a3b | 145 | * \return -1, Not Supported Value |
kevman | 2:7aab896b1a3b | 146 | */ |
kevman | 2:7aab896b1a3b | 147 | static rf_trx_part_e rf_radio_type_read(void); |
kevman | 2:7aab896b1a3b | 148 | static void rf_ack_wait_timer_start(uint16_t slots); |
kevman | 2:7aab896b1a3b | 149 | static void rf_handle_cca_ed_done(uint8_t full_trx_status); |
kevman | 2:7aab896b1a3b | 150 | static void rf_handle_tx_end(rf_trx_states_t trx_status); |
kevman | 2:7aab896b1a3b | 151 | static void rf_handle_rx_end(rf_trx_states_t trx_status); |
kevman | 2:7aab896b1a3b | 152 | static void rf_on(void); |
kevman | 2:7aab896b1a3b | 153 | static void rf_give_up_on_ack(void); |
kevman | 2:7aab896b1a3b | 154 | static void rf_receive(rf_trx_states_t trx_status = STATE_TRANSITION_IN_PROGRESS); |
kevman | 2:7aab896b1a3b | 155 | static rf_trx_states_t rf_poll_trx_state_change(rf_trx_states_t trx_state); |
kevman | 2:7aab896b1a3b | 156 | static void rf_init(void); |
kevman | 2:7aab896b1a3b | 157 | static int8_t rf_device_register(const uint8_t *mac_addr); |
kevman | 2:7aab896b1a3b | 158 | static void rf_device_unregister(void); |
kevman | 2:7aab896b1a3b | 159 | static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ); |
kevman | 2:7aab896b1a3b | 160 | static void rf_cca_abort(void); |
kevman | 2:7aab896b1a3b | 161 | static void rf_calibration_cb(void); |
kevman | 2:7aab896b1a3b | 162 | static void rf_init_phy_mode(void); |
kevman | 2:7aab896b1a3b | 163 | static void rf_ack_wait_timer_interrupt(void); |
kevman | 2:7aab896b1a3b | 164 | static void rf_calibration_timer_interrupt(void); |
kevman | 2:7aab896b1a3b | 165 | static void rf_calibration_timer_start(uint32_t slots); |
kevman | 2:7aab896b1a3b | 166 | static void rf_cca_timer_interrupt(void); |
kevman | 2:7aab896b1a3b | 167 | static void rf_cca_timer_start(uint32_t slots); |
kevman | 2:7aab896b1a3b | 168 | static uint8_t rf_scale_lqi(int8_t rssi); |
kevman | 2:7aab896b1a3b | 169 | |
kevman | 2:7aab896b1a3b | 170 | static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel); |
kevman | 2:7aab896b1a3b | 171 | static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr); |
kevman | 2:7aab896b1a3b | 172 | static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr); |
kevman | 2:7aab896b1a3b | 173 | |
kevman | 2:7aab896b1a3b | 174 | static void rf_if_cca_timer_start(uint32_t slots); |
kevman | 2:7aab896b1a3b | 175 | static void rf_if_enable_promiscuous_mode(void); |
kevman | 2:7aab896b1a3b | 176 | static void rf_if_lock(void); |
kevman | 2:7aab896b1a3b | 177 | static void rf_if_unlock(void); |
kevman | 2:7aab896b1a3b | 178 | static uint8_t rf_if_read_rnd(void); |
kevman | 2:7aab896b1a3b | 179 | static void rf_if_calibration_timer_start(uint32_t slots); |
kevman | 2:7aab896b1a3b | 180 | static void rf_if_interrupt_handler(void); |
kevman | 2:7aab896b1a3b | 181 | static void rf_if_ack_wait_timer_start(uint16_t slots); |
kevman | 2:7aab896b1a3b | 182 | static void rf_if_ack_wait_timer_stop(void); |
kevman | 2:7aab896b1a3b | 183 | static void rf_if_ack_pending_ctrl(uint8_t state); |
kevman | 2:7aab896b1a3b | 184 | static void rf_if_calibration(void); |
kevman | 2:7aab896b1a3b | 185 | static uint8_t rf_if_read_register(uint8_t addr); |
kevman | 2:7aab896b1a3b | 186 | static void rf_if_set_bit(uint8_t addr, uint8_t bit, uint8_t bit_mask); |
kevman | 2:7aab896b1a3b | 187 | static void rf_if_clear_bit(uint8_t addr, uint8_t bit); |
kevman | 2:7aab896b1a3b | 188 | static void rf_if_write_register(uint8_t addr, uint8_t data); |
kevman | 2:7aab896b1a3b | 189 | static void rf_if_reset_radio(void); |
kevman | 2:7aab896b1a3b | 190 | static void rf_if_enable_ant_div(void); |
kevman | 2:7aab896b1a3b | 191 | static void rf_if_disable_ant_div(void); |
kevman | 2:7aab896b1a3b | 192 | static void rf_if_enable_slptr(void); |
kevman | 2:7aab896b1a3b | 193 | static void rf_if_disable_slptr(void); |
kevman | 2:7aab896b1a3b | 194 | static void rf_if_write_antenna_diversity_settings(void); |
kevman | 2:7aab896b1a3b | 195 | static void rf_if_write_set_tx_power_register(uint8_t value); |
kevman | 2:7aab896b1a3b | 196 | static void rf_if_write_rf_settings(void); |
kevman | 2:7aab896b1a3b | 197 | static rf_trx_states_t rf_if_read_trx_state(void); |
kevman | 2:7aab896b1a3b | 198 | static uint16_t rf_if_read_packet(uint8_t data[RF_MTU], uint8_t *lqi_out, uint8_t *ed_out, bool *crc_good); |
kevman | 2:7aab896b1a3b | 199 | static void rf_if_write_short_addr_registers(uint8_t *short_address); |
kevman | 2:7aab896b1a3b | 200 | static uint8_t rf_if_last_acked_pending(void); |
kevman | 2:7aab896b1a3b | 201 | static void rf_if_write_pan_id_registers(uint8_t *pan_id); |
kevman | 2:7aab896b1a3b | 202 | static void rf_if_write_ieee_addr_registers(uint8_t *address); |
kevman | 2:7aab896b1a3b | 203 | static void rf_if_write_frame_buffer(const uint8_t *ptr, uint8_t length); |
kevman | 2:7aab896b1a3b | 204 | static rf_trx_states_t rf_if_change_trx_state(rf_trx_states_t trx_state); |
kevman | 2:7aab896b1a3b | 205 | static void rf_if_start_cca_process(void); |
kevman | 2:7aab896b1a3b | 206 | static int8_t rf_if_scale_rssi(uint8_t ed_level); |
kevman | 2:7aab896b1a3b | 207 | static void rf_if_set_channel_register(uint8_t channel); |
kevman | 2:7aab896b1a3b | 208 | static void rf_if_enable_promiscuous_mode(void); |
kevman | 2:7aab896b1a3b | 209 | static void rf_if_disable_promiscuous_mode(void); |
kevman | 2:7aab896b1a3b | 210 | static uint8_t rf_if_read_part_num(void); |
kevman | 2:7aab896b1a3b | 211 | static void rf_if_enable_irq(void); |
kevman | 2:7aab896b1a3b | 212 | static void rf_if_disable_irq(void); |
kevman | 2:7aab896b1a3b | 213 | static void rf_if_spi_exchange_n(const void *tx, size_t tx_len, void *rx, size_t rx_len); |
kevman | 2:7aab896b1a3b | 214 | |
kevman | 2:7aab896b1a3b | 215 | static inline rf_trx_states_t rf_if_trx_status_from_full(uint8_t full_trx_status) |
kevman | 2:7aab896b1a3b | 216 | { |
kevman | 2:7aab896b1a3b | 217 | return (rf_trx_states_t) (full_trx_status & 0x1F); |
kevman | 2:7aab896b1a3b | 218 | } |
kevman | 2:7aab896b1a3b | 219 | |
kevman | 2:7aab896b1a3b | 220 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 221 | #include "mbed.h" |
kevman | 2:7aab896b1a3b | 222 | #include "rtos.h" |
kevman | 2:7aab896b1a3b | 223 | |
kevman | 2:7aab896b1a3b | 224 | static void rf_if_irq_task_process_irq(); |
kevman | 2:7aab896b1a3b | 225 | |
kevman | 2:7aab896b1a3b | 226 | #define SIG_RADIO 1 |
kevman | 2:7aab896b1a3b | 227 | #define SIG_TIMER_ACK 2 |
kevman | 2:7aab896b1a3b | 228 | #define SIG_TIMER_CAL 4 |
kevman | 2:7aab896b1a3b | 229 | #define SIG_TIMER_CCA 8 |
kevman | 2:7aab896b1a3b | 230 | |
kevman | 2:7aab896b1a3b | 231 | #define SIG_TIMERS (SIG_TIMER_ACK|SIG_TIMER_CAL|SIG_TIMER_CCA) |
kevman | 2:7aab896b1a3b | 232 | #define SIG_ALL (SIG_RADIO|SIG_TIMERS) |
kevman | 2:7aab896b1a3b | 233 | #endif |
kevman | 2:7aab896b1a3b | 234 | |
kevman | 2:7aab896b1a3b | 235 | // HW pins to RF chip |
kevman | 2:7aab896b1a3b | 236 | |
kevman | 2:7aab896b1a3b | 237 | class UnlockedSPI : public SPI { |
kevman | 2:7aab896b1a3b | 238 | public: |
kevman | 2:7aab896b1a3b | 239 | UnlockedSPI(PinName mosi, PinName miso, PinName sclk) : |
kevman | 2:7aab896b1a3b | 240 | SPI(mosi, miso, sclk) { } |
kevman | 2:7aab896b1a3b | 241 | virtual void lock() { } |
kevman | 2:7aab896b1a3b | 242 | virtual void unlock() { } |
kevman | 2:7aab896b1a3b | 243 | }; |
kevman | 2:7aab896b1a3b | 244 | |
kevman | 2:7aab896b1a3b | 245 | class RFBits { |
kevman | 2:7aab896b1a3b | 246 | public: |
kevman | 2:7aab896b1a3b | 247 | RFBits(PinName spi_mosi, PinName spi_miso, |
kevman | 2:7aab896b1a3b | 248 | PinName spi_sclk, PinName spi_cs, |
kevman | 2:7aab896b1a3b | 249 | PinName spi_rst, PinName spi_slp, PinName spi_irq); |
kevman | 2:7aab896b1a3b | 250 | UnlockedSPI spi; |
kevman | 2:7aab896b1a3b | 251 | DigitalOut CS; |
kevman | 2:7aab896b1a3b | 252 | DigitalOut RST; |
kevman | 2:7aab896b1a3b | 253 | DigitalOut SLP_TR; |
kevman | 2:7aab896b1a3b | 254 | InterruptIn IRQ; |
kevman | 2:7aab896b1a3b | 255 | Timeout ack_timer; |
kevman | 2:7aab896b1a3b | 256 | Timeout cal_timer; |
kevman | 2:7aab896b1a3b | 257 | Timeout cca_timer; |
kevman | 2:7aab896b1a3b | 258 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 259 | Thread irq_thread; |
kevman | 2:7aab896b1a3b | 260 | Mutex mutex; |
kevman | 2:7aab896b1a3b | 261 | void rf_if_irq_task(); |
kevman | 2:7aab896b1a3b | 262 | #endif |
kevman | 2:7aab896b1a3b | 263 | }; |
kevman | 2:7aab896b1a3b | 264 | |
kevman | 2:7aab896b1a3b | 265 | RFBits::RFBits(PinName spi_mosi, PinName spi_miso, |
kevman | 2:7aab896b1a3b | 266 | PinName spi_sclk, PinName spi_cs, |
kevman | 2:7aab896b1a3b | 267 | PinName spi_rst, PinName spi_slp, PinName spi_irq) |
kevman | 2:7aab896b1a3b | 268 | : spi(spi_mosi, spi_miso, spi_sclk), |
kevman | 2:7aab896b1a3b | 269 | CS(spi_cs), |
kevman | 2:7aab896b1a3b | 270 | RST(spi_rst), |
kevman | 2:7aab896b1a3b | 271 | SLP_TR(spi_slp), |
kevman | 2:7aab896b1a3b | 272 | IRQ(spi_irq) |
kevman | 2:7aab896b1a3b | 273 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 274 | ,irq_thread(osPriorityRealtime, 1024) |
kevman | 2:7aab896b1a3b | 275 | #endif |
kevman | 2:7aab896b1a3b | 276 | { |
kevman | 2:7aab896b1a3b | 277 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 278 | irq_thread.start(mbed::callback(this, &RFBits::rf_if_irq_task)); |
kevman | 2:7aab896b1a3b | 279 | #endif |
kevman | 2:7aab896b1a3b | 280 | } |
kevman | 2:7aab896b1a3b | 281 | |
kevman | 2:7aab896b1a3b | 282 | static RFBits *rf; |
kevman | 2:7aab896b1a3b | 283 | static uint8_t rf_part_num = 0; |
kevman | 2:7aab896b1a3b | 284 | /*TODO: RSSI Base value setting*/ |
kevman | 2:7aab896b1a3b | 285 | static int8_t rf_rssi_base_val = -91; |
kevman | 2:7aab896b1a3b | 286 | |
kevman | 2:7aab896b1a3b | 287 | static void rf_if_lock(void) |
kevman | 2:7aab896b1a3b | 288 | { |
kevman | 2:7aab896b1a3b | 289 | platform_enter_critical(); |
kevman | 2:7aab896b1a3b | 290 | } |
kevman | 2:7aab896b1a3b | 291 | |
kevman | 2:7aab896b1a3b | 292 | static void rf_if_unlock(void) |
kevman | 2:7aab896b1a3b | 293 | { |
kevman | 2:7aab896b1a3b | 294 | platform_exit_critical(); |
kevman | 2:7aab896b1a3b | 295 | } |
kevman | 2:7aab896b1a3b | 296 | |
kevman | 2:7aab896b1a3b | 297 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 298 | static void rf_if_cca_timer_signal(void) |
kevman | 2:7aab896b1a3b | 299 | { |
kevman | 2:7aab896b1a3b | 300 | rf->irq_thread.signal_set(SIG_TIMER_CCA); |
kevman | 2:7aab896b1a3b | 301 | } |
kevman | 2:7aab896b1a3b | 302 | |
kevman | 2:7aab896b1a3b | 303 | static void rf_if_cal_timer_signal(void) |
kevman | 2:7aab896b1a3b | 304 | { |
kevman | 2:7aab896b1a3b | 305 | rf->irq_thread.signal_set(SIG_TIMER_CAL); |
kevman | 2:7aab896b1a3b | 306 | } |
kevman | 2:7aab896b1a3b | 307 | |
kevman | 2:7aab896b1a3b | 308 | static void rf_if_ack_timer_signal(void) |
kevman | 2:7aab896b1a3b | 309 | { |
kevman | 2:7aab896b1a3b | 310 | rf->irq_thread.signal_set(SIG_TIMER_ACK); |
kevman | 2:7aab896b1a3b | 311 | } |
kevman | 2:7aab896b1a3b | 312 | #endif |
kevman | 2:7aab896b1a3b | 313 | |
kevman | 2:7aab896b1a3b | 314 | |
kevman | 2:7aab896b1a3b | 315 | /* Delay functions for RF Chip SPI access */ |
kevman | 2:7aab896b1a3b | 316 | #ifdef __CC_ARM |
kevman | 2:7aab896b1a3b | 317 | __asm static void delay_loop(uint32_t count) |
kevman | 2:7aab896b1a3b | 318 | { |
kevman | 2:7aab896b1a3b | 319 | 1 |
kevman | 2:7aab896b1a3b | 320 | SUBS a1, a1, #1 |
kevman | 2:7aab896b1a3b | 321 | BCS %BT1 |
kevman | 2:7aab896b1a3b | 322 | BX lr |
kevman | 2:7aab896b1a3b | 323 | } |
kevman | 2:7aab896b1a3b | 324 | #elif defined (__ARMCC_VERSION) /* ARMC6 */ |
kevman | 2:7aab896b1a3b | 325 | void delay_loop(uint32_t count) |
kevman | 2:7aab896b1a3b | 326 | { |
kevman | 2:7aab896b1a3b | 327 | // TODO: This needs implementation |
kevman | 2:7aab896b1a3b | 328 | while(count--) |
kevman | 2:7aab896b1a3b | 329 | ;; |
kevman | 2:7aab896b1a3b | 330 | } |
kevman | 2:7aab896b1a3b | 331 | #elif defined (__ICCARM__) |
kevman | 2:7aab896b1a3b | 332 | static void delay_loop(uint32_t count) |
kevman | 2:7aab896b1a3b | 333 | { |
kevman | 2:7aab896b1a3b | 334 | __asm volatile( |
kevman | 2:7aab896b1a3b | 335 | "loop: \n" |
kevman | 2:7aab896b1a3b | 336 | " SUBS %0, %0, #1 \n" |
kevman | 2:7aab896b1a3b | 337 | " BCS.n loop\n" |
kevman | 2:7aab896b1a3b | 338 | : "+r" (count) |
kevman | 2:7aab896b1a3b | 339 | : |
kevman | 2:7aab896b1a3b | 340 | : "cc" |
kevman | 2:7aab896b1a3b | 341 | ); |
kevman | 2:7aab896b1a3b | 342 | } |
kevman | 2:7aab896b1a3b | 343 | #else // GCC |
kevman | 2:7aab896b1a3b | 344 | static void delay_loop(uint32_t count) |
kevman | 2:7aab896b1a3b | 345 | { |
kevman | 2:7aab896b1a3b | 346 | __asm__ volatile ( |
kevman | 2:7aab896b1a3b | 347 | "%=:\n\t" |
kevman | 2:7aab896b1a3b | 348 | #if defined(__thumb__) && !defined(__thumb2__) |
kevman | 2:7aab896b1a3b | 349 | "SUB %0, #1\n\t" |
kevman | 2:7aab896b1a3b | 350 | #else |
kevman | 2:7aab896b1a3b | 351 | "SUBS %0, %0, #1\n\t" |
kevman | 2:7aab896b1a3b | 352 | #endif |
kevman | 2:7aab896b1a3b | 353 | "BCS %=b\n\t" |
kevman | 2:7aab896b1a3b | 354 | : "+l" (count) |
kevman | 2:7aab896b1a3b | 355 | : |
kevman | 2:7aab896b1a3b | 356 | : "cc" |
kevman | 2:7aab896b1a3b | 357 | ); |
kevman | 2:7aab896b1a3b | 358 | } |
kevman | 2:7aab896b1a3b | 359 | #endif |
kevman | 2:7aab896b1a3b | 360 | |
kevman | 2:7aab896b1a3b | 361 | static void delay_ns(uint32_t ns) |
kevman | 2:7aab896b1a3b | 362 | { |
kevman | 2:7aab896b1a3b | 363 | uint32_t cycles_per_us = SystemCoreClock / 1000000; |
kevman | 2:7aab896b1a3b | 364 | // Cortex-M0 takes 4 cycles per loop (SUB=1, BCS=3) |
kevman | 2:7aab896b1a3b | 365 | // Cortex-M3 and M4 takes 3 cycles per loop (SUB=1, BCS=2) |
kevman | 2:7aab896b1a3b | 366 | // Cortex-M7 - who knows? |
kevman | 2:7aab896b1a3b | 367 | // Cortex M3-M7 have "CYCCNT" - would be better than a software loop, but M0 doesn't |
kevman | 2:7aab896b1a3b | 368 | // Assume 3 cycles per loop for now - will be 33% slow on M0. No biggie, |
kevman | 2:7aab896b1a3b | 369 | // as original version of code was 300% slow on M4. |
kevman | 2:7aab896b1a3b | 370 | // [Note that this very calculation, plus call overhead, will take multiple |
kevman | 2:7aab896b1a3b | 371 | // cycles. Could well be 100ns on its own... So round down here, startup is |
kevman | 2:7aab896b1a3b | 372 | // worth at least one loop iteration.] |
kevman | 2:7aab896b1a3b | 373 | uint32_t count = (cycles_per_us * ns) / 3000; |
kevman | 2:7aab896b1a3b | 374 | |
kevman | 2:7aab896b1a3b | 375 | delay_loop(count); |
kevman | 2:7aab896b1a3b | 376 | } |
kevman | 2:7aab896b1a3b | 377 | |
kevman | 2:7aab896b1a3b | 378 | // t1 = 180ns, SEL falling edge to MISO active [SPI setup assumed slow enough to not need manual delay] |
kevman | 2:7aab896b1a3b | 379 | #define CS_SELECT() {rf->CS = 0; /* delay_ns(180); */} |
kevman | 2:7aab896b1a3b | 380 | // t9 = 250ns, last clock to SEL rising edge, t8 = 250ns, SPI idle time between consecutive access |
kevman | 2:7aab896b1a3b | 381 | #define CS_RELEASE() {delay_ns(250); rf->CS = 1; delay_ns(250);} |
kevman | 2:7aab896b1a3b | 382 | |
kevman | 2:7aab896b1a3b | 383 | /* |
kevman | 2:7aab896b1a3b | 384 | * \brief Read connected radio part. |
kevman | 2:7aab896b1a3b | 385 | * |
kevman | 2:7aab896b1a3b | 386 | * This function only return valid information when rf_init() is called |
kevman | 2:7aab896b1a3b | 387 | * |
kevman | 2:7aab896b1a3b | 388 | * \return |
kevman | 2:7aab896b1a3b | 389 | */ |
kevman | 2:7aab896b1a3b | 390 | static rf_trx_part_e rf_radio_type_read(void) |
kevman | 2:7aab896b1a3b | 391 | { |
kevman | 2:7aab896b1a3b | 392 | rf_trx_part_e ret_val = ATMEL_UNKNOW_DEV; |
kevman | 2:7aab896b1a3b | 393 | |
kevman | 2:7aab896b1a3b | 394 | switch (rf_part_num) |
kevman | 2:7aab896b1a3b | 395 | { |
kevman | 2:7aab896b1a3b | 396 | case PART_AT86RF212: |
kevman | 2:7aab896b1a3b | 397 | ret_val = ATMEL_AT86RF212; |
kevman | 2:7aab896b1a3b | 398 | break; |
kevman | 2:7aab896b1a3b | 399 | case PART_AT86RF233: |
kevman | 2:7aab896b1a3b | 400 | ret_val = ATMEL_AT86RF233; |
kevman | 2:7aab896b1a3b | 401 | break; |
kevman | 2:7aab896b1a3b | 402 | default: |
kevman | 2:7aab896b1a3b | 403 | break; |
kevman | 2:7aab896b1a3b | 404 | } |
kevman | 2:7aab896b1a3b | 405 | |
kevman | 2:7aab896b1a3b | 406 | return ret_val; |
kevman | 2:7aab896b1a3b | 407 | } |
kevman | 2:7aab896b1a3b | 408 | |
kevman | 2:7aab896b1a3b | 409 | |
kevman | 2:7aab896b1a3b | 410 | /* |
kevman | 2:7aab896b1a3b | 411 | * \brief Function starts the ACK wait timeout. |
kevman | 2:7aab896b1a3b | 412 | * |
kevman | 2:7aab896b1a3b | 413 | * \param slots Given slots, resolution 50us |
kevman | 2:7aab896b1a3b | 414 | * |
kevman | 2:7aab896b1a3b | 415 | * \return none |
kevman | 2:7aab896b1a3b | 416 | */ |
kevman | 2:7aab896b1a3b | 417 | static void rf_if_ack_wait_timer_start(uint16_t slots) |
kevman | 2:7aab896b1a3b | 418 | { |
kevman | 2:7aab896b1a3b | 419 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 420 | rf->ack_timer.attach_us(rf_if_ack_timer_signal, slots*50); |
kevman | 2:7aab896b1a3b | 421 | #else |
kevman | 2:7aab896b1a3b | 422 | rf->ack_timer.attach_us(rf_ack_wait_timer_interrupt, slots*50); |
kevman | 2:7aab896b1a3b | 423 | #endif |
kevman | 2:7aab896b1a3b | 424 | } |
kevman | 2:7aab896b1a3b | 425 | |
kevman | 2:7aab896b1a3b | 426 | /* |
kevman | 2:7aab896b1a3b | 427 | * \brief Function starts the calibration interval. |
kevman | 2:7aab896b1a3b | 428 | * |
kevman | 2:7aab896b1a3b | 429 | * \param slots Given slots, resolution 50us |
kevman | 2:7aab896b1a3b | 430 | * |
kevman | 2:7aab896b1a3b | 431 | * \return none |
kevman | 2:7aab896b1a3b | 432 | */ |
kevman | 2:7aab896b1a3b | 433 | static void rf_if_calibration_timer_start(uint32_t slots) |
kevman | 2:7aab896b1a3b | 434 | { |
kevman | 2:7aab896b1a3b | 435 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 436 | rf->cal_timer.attach_us(rf_if_cal_timer_signal, slots*50); |
kevman | 2:7aab896b1a3b | 437 | #else |
kevman | 2:7aab896b1a3b | 438 | rf->cal_timer.attach_us(rf_calibration_timer_interrupt, slots*50); |
kevman | 2:7aab896b1a3b | 439 | #endif |
kevman | 2:7aab896b1a3b | 440 | } |
kevman | 2:7aab896b1a3b | 441 | |
kevman | 2:7aab896b1a3b | 442 | /* |
kevman | 2:7aab896b1a3b | 443 | * \brief Function starts the CCA interval. |
kevman | 2:7aab896b1a3b | 444 | * |
kevman | 2:7aab896b1a3b | 445 | * \param slots Given slots, resolution 50us |
kevman | 2:7aab896b1a3b | 446 | * |
kevman | 2:7aab896b1a3b | 447 | * \return none |
kevman | 2:7aab896b1a3b | 448 | */ |
kevman | 2:7aab896b1a3b | 449 | static void rf_if_cca_timer_start(uint32_t slots) |
kevman | 2:7aab896b1a3b | 450 | { |
kevman | 2:7aab896b1a3b | 451 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 452 | rf->cca_timer.attach_us(rf_if_cca_timer_signal, slots*50); |
kevman | 2:7aab896b1a3b | 453 | #else |
kevman | 2:7aab896b1a3b | 454 | rf->cca_timer.attach_us(rf_cca_timer_interrupt, slots*50); |
kevman | 2:7aab896b1a3b | 455 | #endif |
kevman | 2:7aab896b1a3b | 456 | } |
kevman | 2:7aab896b1a3b | 457 | |
kevman | 2:7aab896b1a3b | 458 | /* |
kevman | 2:7aab896b1a3b | 459 | * \brief Function stops the CCA interval. |
kevman | 2:7aab896b1a3b | 460 | * |
kevman | 2:7aab896b1a3b | 461 | * \return none |
kevman | 2:7aab896b1a3b | 462 | */ |
kevman | 2:7aab896b1a3b | 463 | static void rf_if_cca_timer_stop(void) |
kevman | 2:7aab896b1a3b | 464 | { |
kevman | 2:7aab896b1a3b | 465 | rf->cca_timer.detach(); |
kevman | 2:7aab896b1a3b | 466 | } |
kevman | 2:7aab896b1a3b | 467 | |
kevman | 2:7aab896b1a3b | 468 | /* |
kevman | 2:7aab896b1a3b | 469 | * \brief Function stops the ACK wait timeout. |
kevman | 2:7aab896b1a3b | 470 | * |
kevman | 2:7aab896b1a3b | 471 | * \param none |
kevman | 2:7aab896b1a3b | 472 | * |
kevman | 2:7aab896b1a3b | 473 | * \return none |
kevman | 2:7aab896b1a3b | 474 | */ |
kevman | 2:7aab896b1a3b | 475 | static void rf_if_ack_wait_timer_stop(void) |
kevman | 2:7aab896b1a3b | 476 | { |
kevman | 2:7aab896b1a3b | 477 | rf->ack_timer.detach(); |
kevman | 2:7aab896b1a3b | 478 | } |
kevman | 2:7aab896b1a3b | 479 | |
kevman | 2:7aab896b1a3b | 480 | /* |
kevman | 2:7aab896b1a3b | 481 | * \brief Function sets bit(s) in given RF register. |
kevman | 2:7aab896b1a3b | 482 | * |
kevman | 2:7aab896b1a3b | 483 | * \param addr Address of the register to set |
kevman | 2:7aab896b1a3b | 484 | * \param bit Bit(s) to set |
kevman | 2:7aab896b1a3b | 485 | * \param bit_mask Masks the field inside the register |
kevman | 2:7aab896b1a3b | 486 | * |
kevman | 2:7aab896b1a3b | 487 | * \return none |
kevman | 2:7aab896b1a3b | 488 | */ |
kevman | 2:7aab896b1a3b | 489 | static void rf_if_set_bit(uint8_t addr, uint8_t bit, uint8_t bit_mask) |
kevman | 2:7aab896b1a3b | 490 | { |
kevman | 2:7aab896b1a3b | 491 | uint8_t reg = rf_if_read_register(addr); |
kevman | 2:7aab896b1a3b | 492 | reg &= ~bit_mask; |
kevman | 2:7aab896b1a3b | 493 | reg |= bit; |
kevman | 2:7aab896b1a3b | 494 | rf_if_write_register(addr, reg); |
kevman | 2:7aab896b1a3b | 495 | } |
kevman | 2:7aab896b1a3b | 496 | |
kevman | 2:7aab896b1a3b | 497 | /* |
kevman | 2:7aab896b1a3b | 498 | * \brief Function clears bit(s) in given RF register. |
kevman | 2:7aab896b1a3b | 499 | * |
kevman | 2:7aab896b1a3b | 500 | * \param addr Address of the register to clear |
kevman | 2:7aab896b1a3b | 501 | * \param bit Bit(s) to clear |
kevman | 2:7aab896b1a3b | 502 | * |
kevman | 2:7aab896b1a3b | 503 | * \return none |
kevman | 2:7aab896b1a3b | 504 | */ |
kevman | 2:7aab896b1a3b | 505 | static void rf_if_clear_bit(uint8_t addr, uint8_t bit) |
kevman | 2:7aab896b1a3b | 506 | { |
kevman | 2:7aab896b1a3b | 507 | rf_if_set_bit(addr, 0, bit); |
kevman | 2:7aab896b1a3b | 508 | } |
kevman | 2:7aab896b1a3b | 509 | |
kevman | 2:7aab896b1a3b | 510 | /* |
kevman | 2:7aab896b1a3b | 511 | * \brief Function writes register in RF. |
kevman | 2:7aab896b1a3b | 512 | * |
kevman | 2:7aab896b1a3b | 513 | * \param addr Address on the RF |
kevman | 2:7aab896b1a3b | 514 | * \param data Written data |
kevman | 2:7aab896b1a3b | 515 | * |
kevman | 2:7aab896b1a3b | 516 | * \return none |
kevman | 2:7aab896b1a3b | 517 | */ |
kevman | 2:7aab896b1a3b | 518 | static void rf_if_write_register(uint8_t addr, uint8_t data) |
kevman | 2:7aab896b1a3b | 519 | { |
kevman | 2:7aab896b1a3b | 520 | const uint8_t tx[2] = { static_cast<uint8_t>(0xC0 | addr), data }; |
kevman | 2:7aab896b1a3b | 521 | uint8_t rx[2]; |
kevman | 2:7aab896b1a3b | 522 | CS_SELECT(); |
kevman | 2:7aab896b1a3b | 523 | rf_if_spi_exchange_n(tx, 2, rx, 2); |
kevman | 2:7aab896b1a3b | 524 | CS_RELEASE(); |
kevman | 2:7aab896b1a3b | 525 | } |
kevman | 2:7aab896b1a3b | 526 | |
kevman | 2:7aab896b1a3b | 527 | /* |
kevman | 2:7aab896b1a3b | 528 | * \brief Function reads RF register, and also outputs PHY_STATUS |
kevman | 2:7aab896b1a3b | 529 | * |
kevman | 2:7aab896b1a3b | 530 | * \param addr Address on the RF |
kevman | 2:7aab896b1a3b | 531 | * \param[out] status_out Pointer to store PHY_STATUS |
kevman | 2:7aab896b1a3b | 532 | * |
kevman | 2:7aab896b1a3b | 533 | * \return Read register data |
kevman | 2:7aab896b1a3b | 534 | */ |
kevman | 2:7aab896b1a3b | 535 | static uint8_t rf_if_read_register_with_status(uint8_t addr, uint8_t *status_out) |
kevman | 2:7aab896b1a3b | 536 | { |
kevman | 2:7aab896b1a3b | 537 | const uint8_t tx[1] = { static_cast<uint8_t>(0x80 | addr) }; |
kevman | 2:7aab896b1a3b | 538 | uint8_t rx[2]; |
kevman | 2:7aab896b1a3b | 539 | CS_SELECT(); |
kevman | 2:7aab896b1a3b | 540 | rf_if_spi_exchange_n(tx, 1, rx, 2); |
kevman | 2:7aab896b1a3b | 541 | CS_RELEASE(); |
kevman | 2:7aab896b1a3b | 542 | if (status_out) { |
kevman | 2:7aab896b1a3b | 543 | *status_out = rx[0]; |
kevman | 2:7aab896b1a3b | 544 | } |
kevman | 2:7aab896b1a3b | 545 | return rx[1]; |
kevman | 2:7aab896b1a3b | 546 | } |
kevman | 2:7aab896b1a3b | 547 | |
kevman | 2:7aab896b1a3b | 548 | /* |
kevman | 2:7aab896b1a3b | 549 | * \brief Function reads RF register. |
kevman | 2:7aab896b1a3b | 550 | * |
kevman | 2:7aab896b1a3b | 551 | * \param addr Address on the RF |
kevman | 2:7aab896b1a3b | 552 | * |
kevman | 2:7aab896b1a3b | 553 | * \return Read register data |
kevman | 2:7aab896b1a3b | 554 | */ |
kevman | 2:7aab896b1a3b | 555 | static uint8_t rf_if_read_register(uint8_t addr) |
kevman | 2:7aab896b1a3b | 556 | { |
kevman | 2:7aab896b1a3b | 557 | return rf_if_read_register_with_status(addr, NULL); |
kevman | 2:7aab896b1a3b | 558 | } |
kevman | 2:7aab896b1a3b | 559 | |
kevman | 2:7aab896b1a3b | 560 | /* |
kevman | 2:7aab896b1a3b | 561 | * \brief Function resets the RF. |
kevman | 2:7aab896b1a3b | 562 | * |
kevman | 2:7aab896b1a3b | 563 | * \param none |
kevman | 2:7aab896b1a3b | 564 | * |
kevman | 2:7aab896b1a3b | 565 | * \return none |
kevman | 2:7aab896b1a3b | 566 | */ |
kevman | 2:7aab896b1a3b | 567 | static void rf_if_reset_radio(void) |
kevman | 2:7aab896b1a3b | 568 | { |
kevman | 2:7aab896b1a3b | 569 | #if MBED_CONF_ATMEL_RF_USE_SPI_SPACING_API |
kevman | 2:7aab896b1a3b | 570 | rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); |
kevman | 2:7aab896b1a3b | 571 | int spacing = rf->spi.write_spacing(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING); |
kevman | 2:7aab896b1a3b | 572 | if (spacing < MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING) { |
kevman | 2:7aab896b1a3b | 573 | rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); |
kevman | 2:7aab896b1a3b | 574 | rf->spi.write_spacing(0); |
kevman | 2:7aab896b1a3b | 575 | } |
kevman | 2:7aab896b1a3b | 576 | #elif MBED_CONF_ATMEL_RF_ASSUME_SPACED_SPI |
kevman | 2:7aab896b1a3b | 577 | rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); |
kevman | 2:7aab896b1a3b | 578 | #else |
kevman | 2:7aab896b1a3b | 579 | rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); |
kevman | 2:7aab896b1a3b | 580 | #endif |
kevman | 2:7aab896b1a3b | 581 | rf->IRQ.rise(0); |
kevman | 2:7aab896b1a3b | 582 | rf->RST = 1; |
kevman | 2:7aab896b1a3b | 583 | wait_ms(1); |
kevman | 2:7aab896b1a3b | 584 | rf->RST = 0; |
kevman | 2:7aab896b1a3b | 585 | wait_ms(10); |
kevman | 2:7aab896b1a3b | 586 | CS_RELEASE(); |
kevman | 2:7aab896b1a3b | 587 | rf->SLP_TR = 0; |
kevman | 2:7aab896b1a3b | 588 | wait_ms(10); |
kevman | 2:7aab896b1a3b | 589 | rf->RST = 1; |
kevman | 2:7aab896b1a3b | 590 | wait_ms(10); |
kevman | 2:7aab896b1a3b | 591 | |
kevman | 2:7aab896b1a3b | 592 | rf->IRQ.rise(&rf_if_interrupt_handler); |
kevman | 2:7aab896b1a3b | 593 | } |
kevman | 2:7aab896b1a3b | 594 | |
kevman | 2:7aab896b1a3b | 595 | /* |
kevman | 2:7aab896b1a3b | 596 | * \brief Function enables the promiscuous mode. |
kevman | 2:7aab896b1a3b | 597 | * |
kevman | 2:7aab896b1a3b | 598 | * \param none |
kevman | 2:7aab896b1a3b | 599 | * |
kevman | 2:7aab896b1a3b | 600 | * \return none |
kevman | 2:7aab896b1a3b | 601 | */ |
kevman | 2:7aab896b1a3b | 602 | static void rf_if_enable_promiscuous_mode(void) |
kevman | 2:7aab896b1a3b | 603 | { |
kevman | 2:7aab896b1a3b | 604 | if (!(xah_ctrl_1 & AACK_PROM_MODE)) { |
kevman | 2:7aab896b1a3b | 605 | /*Set AACK_PROM_MODE to enable the promiscuous mode*/ |
kevman | 2:7aab896b1a3b | 606 | rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 |= AACK_PROM_MODE); |
kevman | 2:7aab896b1a3b | 607 | } |
kevman | 2:7aab896b1a3b | 608 | } |
kevman | 2:7aab896b1a3b | 609 | |
kevman | 2:7aab896b1a3b | 610 | /* |
kevman | 2:7aab896b1a3b | 611 | * \brief Function disable the promiscuous mode. |
kevman | 2:7aab896b1a3b | 612 | * |
kevman | 2:7aab896b1a3b | 613 | * \param none |
kevman | 2:7aab896b1a3b | 614 | * |
kevman | 2:7aab896b1a3b | 615 | * \return none |
kevman | 2:7aab896b1a3b | 616 | */ |
kevman | 2:7aab896b1a3b | 617 | static void rf_if_disable_promiscuous_mode(void) |
kevman | 2:7aab896b1a3b | 618 | { |
kevman | 2:7aab896b1a3b | 619 | if (xah_ctrl_1 & AACK_PROM_MODE) { |
kevman | 2:7aab896b1a3b | 620 | /*Clear AACK_PROM_MODE to disable the promiscuous mode*/ |
kevman | 2:7aab896b1a3b | 621 | rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 &= ~AACK_PROM_MODE); |
kevman | 2:7aab896b1a3b | 622 | } |
kevman | 2:7aab896b1a3b | 623 | } |
kevman | 2:7aab896b1a3b | 624 | |
kevman | 2:7aab896b1a3b | 625 | /* |
kevman | 2:7aab896b1a3b | 626 | * \brief Function enables the Antenna diversity usage. |
kevman | 2:7aab896b1a3b | 627 | * |
kevman | 2:7aab896b1a3b | 628 | * \param none |
kevman | 2:7aab896b1a3b | 629 | * |
kevman | 2:7aab896b1a3b | 630 | * \return none |
kevman | 2:7aab896b1a3b | 631 | */ |
kevman | 2:7aab896b1a3b | 632 | static void rf_if_enable_ant_div(void) |
kevman | 2:7aab896b1a3b | 633 | { |
kevman | 2:7aab896b1a3b | 634 | /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/ |
kevman | 2:7aab896b1a3b | 635 | rf_if_set_bit(ANT_DIV, ANT_EXT_SW_EN, ANT_EXT_SW_EN); |
kevman | 2:7aab896b1a3b | 636 | } |
kevman | 2:7aab896b1a3b | 637 | |
kevman | 2:7aab896b1a3b | 638 | /* |
kevman | 2:7aab896b1a3b | 639 | * \brief Function disables the Antenna diversity usage. |
kevman | 2:7aab896b1a3b | 640 | * |
kevman | 2:7aab896b1a3b | 641 | * \param none |
kevman | 2:7aab896b1a3b | 642 | * |
kevman | 2:7aab896b1a3b | 643 | * \return none |
kevman | 2:7aab896b1a3b | 644 | */ |
kevman | 2:7aab896b1a3b | 645 | static void rf_if_disable_ant_div(void) |
kevman | 2:7aab896b1a3b | 646 | { |
kevman | 2:7aab896b1a3b | 647 | rf_if_clear_bit(ANT_DIV, ANT_EXT_SW_EN); |
kevman | 2:7aab896b1a3b | 648 | } |
kevman | 2:7aab896b1a3b | 649 | |
kevman | 2:7aab896b1a3b | 650 | /* |
kevman | 2:7aab896b1a3b | 651 | * \brief Function sets the SLP TR pin. |
kevman | 2:7aab896b1a3b | 652 | * |
kevman | 2:7aab896b1a3b | 653 | * \param none |
kevman | 2:7aab896b1a3b | 654 | * |
kevman | 2:7aab896b1a3b | 655 | * \return none |
kevman | 2:7aab896b1a3b | 656 | */ |
kevman | 2:7aab896b1a3b | 657 | static void rf_if_enable_slptr(void) |
kevman | 2:7aab896b1a3b | 658 | { |
kevman | 2:7aab896b1a3b | 659 | rf->SLP_TR = 1; |
kevman | 2:7aab896b1a3b | 660 | } |
kevman | 2:7aab896b1a3b | 661 | |
kevman | 2:7aab896b1a3b | 662 | /* |
kevman | 2:7aab896b1a3b | 663 | * \brief Function clears the SLP TR pin. |
kevman | 2:7aab896b1a3b | 664 | * |
kevman | 2:7aab896b1a3b | 665 | * \param none |
kevman | 2:7aab896b1a3b | 666 | * |
kevman | 2:7aab896b1a3b | 667 | * \return none |
kevman | 2:7aab896b1a3b | 668 | */ |
kevman | 2:7aab896b1a3b | 669 | static void rf_if_disable_slptr(void) |
kevman | 2:7aab896b1a3b | 670 | { |
kevman | 2:7aab896b1a3b | 671 | rf->SLP_TR = 0; |
kevman | 2:7aab896b1a3b | 672 | } |
kevman | 2:7aab896b1a3b | 673 | |
kevman | 2:7aab896b1a3b | 674 | /* |
kevman | 2:7aab896b1a3b | 675 | * \brief Function writes the antenna diversity settings. |
kevman | 2:7aab896b1a3b | 676 | * |
kevman | 2:7aab896b1a3b | 677 | * \param none |
kevman | 2:7aab896b1a3b | 678 | * |
kevman | 2:7aab896b1a3b | 679 | * \return none |
kevman | 2:7aab896b1a3b | 680 | */ |
kevman | 2:7aab896b1a3b | 681 | static void rf_if_write_antenna_diversity_settings(void) |
kevman | 2:7aab896b1a3b | 682 | { |
kevman | 2:7aab896b1a3b | 683 | /*Recommended setting of PDT_THRES is 3 when antenna diversity is used*/ |
kevman | 2:7aab896b1a3b | 684 | rf_if_set_bit(RX_CTRL, 0x03, 0x0f); |
kevman | 2:7aab896b1a3b | 685 | rf_if_write_register(ANT_DIV, ANT_DIV_EN | ANT_EXT_SW_EN | ANT_CTRL_DEFAULT); |
kevman | 2:7aab896b1a3b | 686 | } |
kevman | 2:7aab896b1a3b | 687 | |
kevman | 2:7aab896b1a3b | 688 | /* |
kevman | 2:7aab896b1a3b | 689 | * \brief Function writes the TX output power register. |
kevman | 2:7aab896b1a3b | 690 | * |
kevman | 2:7aab896b1a3b | 691 | * \param value Given register value |
kevman | 2:7aab896b1a3b | 692 | * |
kevman | 2:7aab896b1a3b | 693 | * \return none |
kevman | 2:7aab896b1a3b | 694 | */ |
kevman | 2:7aab896b1a3b | 695 | static void rf_if_write_set_tx_power_register(uint8_t value) |
kevman | 2:7aab896b1a3b | 696 | { |
kevman | 2:7aab896b1a3b | 697 | rf_if_write_register(PHY_TX_PWR, value); |
kevman | 2:7aab896b1a3b | 698 | } |
kevman | 2:7aab896b1a3b | 699 | |
kevman | 2:7aab896b1a3b | 700 | /* |
kevman | 2:7aab896b1a3b | 701 | * \brief Function returns the RF part number. |
kevman | 2:7aab896b1a3b | 702 | * |
kevman | 2:7aab896b1a3b | 703 | * \param none |
kevman | 2:7aab896b1a3b | 704 | * |
kevman | 2:7aab896b1a3b | 705 | * \return part number |
kevman | 2:7aab896b1a3b | 706 | */ |
kevman | 2:7aab896b1a3b | 707 | static uint8_t rf_if_read_part_num(void) |
kevman | 2:7aab896b1a3b | 708 | { |
kevman | 2:7aab896b1a3b | 709 | return rf_if_read_register(PART_NUM); |
kevman | 2:7aab896b1a3b | 710 | } |
kevman | 2:7aab896b1a3b | 711 | |
kevman | 2:7aab896b1a3b | 712 | /* |
kevman | 2:7aab896b1a3b | 713 | * \brief Function writes the RF settings and initialises SPI interface. |
kevman | 2:7aab896b1a3b | 714 | * |
kevman | 2:7aab896b1a3b | 715 | * \param none |
kevman | 2:7aab896b1a3b | 716 | * |
kevman | 2:7aab896b1a3b | 717 | * \return none |
kevman | 2:7aab896b1a3b | 718 | */ |
kevman | 2:7aab896b1a3b | 719 | static void rf_if_write_rf_settings(void) |
kevman | 2:7aab896b1a3b | 720 | { |
kevman | 2:7aab896b1a3b | 721 | /*Reset RF module*/ |
kevman | 2:7aab896b1a3b | 722 | rf_if_reset_radio(); |
kevman | 2:7aab896b1a3b | 723 | |
kevman | 2:7aab896b1a3b | 724 | rf_part_num = rf_if_read_part_num(); |
kevman | 2:7aab896b1a3b | 725 | |
kevman | 2:7aab896b1a3b | 726 | rf_if_write_register(XAH_CTRL_0,0); |
kevman | 2:7aab896b1a3b | 727 | |
kevman | 2:7aab896b1a3b | 728 | /* Auto CRC on, IRQ status shows unmasked only, TRX_STATUS output on all accesses */ |
kevman | 2:7aab896b1a3b | 729 | rf_if_write_register(TRX_CTRL_1, TX_AUTO_CRC_ON | SPI_CMD_MODE_TRX_STATUS); |
kevman | 2:7aab896b1a3b | 730 | |
kevman | 2:7aab896b1a3b | 731 | rf_if_write_register(IRQ_MASK, CCA_ED_DONE | TRX_END | TRX_UR); |
kevman | 2:7aab896b1a3b | 732 | |
kevman | 2:7aab896b1a3b | 733 | xah_ctrl_1 = rf_if_read_register(XAH_CTRL_1); |
kevman | 2:7aab896b1a3b | 734 | |
kevman | 2:7aab896b1a3b | 735 | /*Read transceiver PART_NUM*/ |
kevman | 2:7aab896b1a3b | 736 | rf_part_num = rf_if_read_register(PART_NUM); |
kevman | 2:7aab896b1a3b | 737 | |
kevman | 2:7aab896b1a3b | 738 | /*Sub-GHz RF settings*/ |
kevman | 2:7aab896b1a3b | 739 | if(rf_part_num == PART_AT86RF212) |
kevman | 2:7aab896b1a3b | 740 | { |
kevman | 2:7aab896b1a3b | 741 | /*GC_TX_OFFS mode-dependent setting - OQPSK*/ |
kevman | 2:7aab896b1a3b | 742 | rf_if_write_register(RF_CTRL_0, 0x32); |
kevman | 2:7aab896b1a3b | 743 | |
kevman | 2:7aab896b1a3b | 744 | if(rf_if_read_register(VERSION_NUM) == VERSION_AT86RF212B) |
kevman | 2:7aab896b1a3b | 745 | { |
kevman | 2:7aab896b1a3b | 746 | /*TX Output Power setting - 0 dBm North American Band*/ |
kevman | 2:7aab896b1a3b | 747 | rf_if_write_register(PHY_TX_PWR, 0x03); |
kevman | 2:7aab896b1a3b | 748 | } |
kevman | 2:7aab896b1a3b | 749 | else |
kevman | 2:7aab896b1a3b | 750 | { |
kevman | 2:7aab896b1a3b | 751 | /*TX Output Power setting - 0 dBm North American Band*/ |
kevman | 2:7aab896b1a3b | 752 | rf_if_write_register(PHY_TX_PWR, 0x24); |
kevman | 2:7aab896b1a3b | 753 | } |
kevman | 2:7aab896b1a3b | 754 | |
kevman | 2:7aab896b1a3b | 755 | /*PHY Mode: IEEE 802.15.4-2006/2011 - OQPSK-SIN-250*/ |
kevman | 2:7aab896b1a3b | 756 | rf_if_write_register(TRX_CTRL_2, RX_SAFE_MODE | RF_PHY_MODE); |
kevman | 2:7aab896b1a3b | 757 | /*Based on receiver Characteristics. See AT86RF212B Datasheet where RSSI BASE VALUE in range -97 - -100 dBm*/ |
kevman | 2:7aab896b1a3b | 758 | rf_rssi_base_val = -98; |
kevman | 2:7aab896b1a3b | 759 | } |
kevman | 2:7aab896b1a3b | 760 | /*2.4GHz RF settings*/ |
kevman | 2:7aab896b1a3b | 761 | else |
kevman | 2:7aab896b1a3b | 762 | { |
kevman | 2:7aab896b1a3b | 763 | #if 0 |
kevman | 2:7aab896b1a3b | 764 | /* Disable power saving functions for now - can only impact reliability, |
kevman | 2:7aab896b1a3b | 765 | * and don't have any users demanding it. */ |
kevman | 2:7aab896b1a3b | 766 | /*Set RPC register*/ |
kevman | 2:7aab896b1a3b | 767 | rf_if_write_register(TRX_RPC, RX_RPC_CTRL|RX_RPC_EN|PLL_RPC_EN|XAH_TX_RPC_EN|IPAN_RPC_EN|TRX_RPC_RSVD_1); |
kevman | 2:7aab896b1a3b | 768 | #endif |
kevman | 2:7aab896b1a3b | 769 | /*PHY Mode: IEEE 802.15.4 - Data Rate 250 kb/s*/ |
kevman | 2:7aab896b1a3b | 770 | rf_if_write_register(TRX_CTRL_2, RX_SAFE_MODE); |
kevman | 2:7aab896b1a3b | 771 | rf_rssi_base_val = -91; |
kevman | 2:7aab896b1a3b | 772 | } |
kevman | 2:7aab896b1a3b | 773 | } |
kevman | 2:7aab896b1a3b | 774 | |
kevman | 2:7aab896b1a3b | 775 | /* |
kevman | 2:7aab896b1a3b | 776 | * \brief Function returns the RF state |
kevman | 2:7aab896b1a3b | 777 | * |
kevman | 2:7aab896b1a3b | 778 | * \param none |
kevman | 2:7aab896b1a3b | 779 | * |
kevman | 2:7aab896b1a3b | 780 | * \return RF state |
kevman | 2:7aab896b1a3b | 781 | */ |
kevman | 2:7aab896b1a3b | 782 | static rf_trx_states_t rf_if_read_trx_state(void) |
kevman | 2:7aab896b1a3b | 783 | { |
kevman | 2:7aab896b1a3b | 784 | return rf_if_trx_status_from_full(rf_if_read_register(TRX_STATUS)); |
kevman | 2:7aab896b1a3b | 785 | } |
kevman | 2:7aab896b1a3b | 786 | |
kevman | 2:7aab896b1a3b | 787 | /* |
kevman | 2:7aab896b1a3b | 788 | * \brief Function reads packet buffer. |
kevman | 2:7aab896b1a3b | 789 | * |
kevman | 2:7aab896b1a3b | 790 | * \param data_out Output buffer |
kevman | 2:7aab896b1a3b | 791 | * \param lqi_out LQI output |
kevman | 2:7aab896b1a3b | 792 | * \param ed_out ED output |
kevman | 2:7aab896b1a3b | 793 | * \param crc_good CRC good indication |
kevman | 2:7aab896b1a3b | 794 | * |
kevman | 2:7aab896b1a3b | 795 | * \return PSDU length [0..RF_MTU] |
kevman | 2:7aab896b1a3b | 796 | */ |
kevman | 2:7aab896b1a3b | 797 | static uint16_t rf_if_read_packet(uint8_t data_out[RF_MTU], uint8_t *lqi_out, uint8_t *ed_out, bool *crc_good) |
kevman | 2:7aab896b1a3b | 798 | { |
kevman | 2:7aab896b1a3b | 799 | CS_SELECT(); |
kevman | 2:7aab896b1a3b | 800 | const uint8_t tx[1] = { 0x20 }; |
kevman | 2:7aab896b1a3b | 801 | uint8_t rx[3]; |
kevman | 2:7aab896b1a3b | 802 | rf_if_spi_exchange_n(tx, 1, rx, 2); |
kevman | 2:7aab896b1a3b | 803 | uint8_t len = rx[1] & 0x7F; |
kevman | 2:7aab896b1a3b | 804 | rf_if_spi_exchange_n(NULL, 0, data_out, len); |
kevman | 2:7aab896b1a3b | 805 | rf_if_spi_exchange_n(NULL, 0, rx, 3); |
kevman | 2:7aab896b1a3b | 806 | *lqi_out = rx[0]; |
kevman | 2:7aab896b1a3b | 807 | *ed_out = rx[1]; |
kevman | 2:7aab896b1a3b | 808 | *crc_good = rx[2] & 0x80; |
kevman | 2:7aab896b1a3b | 809 | CS_RELEASE(); |
kevman | 2:7aab896b1a3b | 810 | |
kevman | 2:7aab896b1a3b | 811 | return len; |
kevman | 2:7aab896b1a3b | 812 | } |
kevman | 2:7aab896b1a3b | 813 | |
kevman | 2:7aab896b1a3b | 814 | /* |
kevman | 2:7aab896b1a3b | 815 | * \brief Function writes RF short address registers |
kevman | 2:7aab896b1a3b | 816 | * |
kevman | 2:7aab896b1a3b | 817 | * \param short_address Given short address |
kevman | 2:7aab896b1a3b | 818 | * |
kevman | 2:7aab896b1a3b | 819 | * \return none |
kevman | 2:7aab896b1a3b | 820 | */ |
kevman | 2:7aab896b1a3b | 821 | static void rf_if_write_short_addr_registers(uint8_t *short_address) |
kevman | 2:7aab896b1a3b | 822 | { |
kevman | 2:7aab896b1a3b | 823 | rf_if_write_register(SHORT_ADDR_1, *short_address++); |
kevman | 2:7aab896b1a3b | 824 | rf_if_write_register(SHORT_ADDR_0, *short_address); |
kevman | 2:7aab896b1a3b | 825 | } |
kevman | 2:7aab896b1a3b | 826 | |
kevman | 2:7aab896b1a3b | 827 | /* |
kevman | 2:7aab896b1a3b | 828 | * \brief Function sets the frame pending in ACK message |
kevman | 2:7aab896b1a3b | 829 | * |
kevman | 2:7aab896b1a3b | 830 | * \param state Given frame pending state |
kevman | 2:7aab896b1a3b | 831 | * |
kevman | 2:7aab896b1a3b | 832 | * \return none |
kevman | 2:7aab896b1a3b | 833 | */ |
kevman | 2:7aab896b1a3b | 834 | static void rf_if_ack_pending_ctrl(uint8_t state) |
kevman | 2:7aab896b1a3b | 835 | { |
kevman | 2:7aab896b1a3b | 836 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 837 | if(state) |
kevman | 2:7aab896b1a3b | 838 | { |
kevman | 2:7aab896b1a3b | 839 | rf_if_set_bit(CSMA_SEED_1, (1 << AACK_SET_PD), (1 << AACK_SET_PD)); |
kevman | 2:7aab896b1a3b | 840 | } |
kevman | 2:7aab896b1a3b | 841 | else |
kevman | 2:7aab896b1a3b | 842 | { |
kevman | 2:7aab896b1a3b | 843 | rf_if_clear_bit(CSMA_SEED_1, (1 << AACK_SET_PD)); |
kevman | 2:7aab896b1a3b | 844 | } |
kevman | 2:7aab896b1a3b | 845 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 846 | } |
kevman | 2:7aab896b1a3b | 847 | |
kevman | 2:7aab896b1a3b | 848 | /* |
kevman | 2:7aab896b1a3b | 849 | * \brief Function returns the state of frame pending control |
kevman | 2:7aab896b1a3b | 850 | * |
kevman | 2:7aab896b1a3b | 851 | * \param none |
kevman | 2:7aab896b1a3b | 852 | * |
kevman | 2:7aab896b1a3b | 853 | * \return Frame pending state |
kevman | 2:7aab896b1a3b | 854 | */ |
kevman | 2:7aab896b1a3b | 855 | static uint8_t rf_if_last_acked_pending(void) |
kevman | 2:7aab896b1a3b | 856 | { |
kevman | 2:7aab896b1a3b | 857 | uint8_t last_acked_data_pending; |
kevman | 2:7aab896b1a3b | 858 | |
kevman | 2:7aab896b1a3b | 859 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 860 | if(rf_if_read_register(CSMA_SEED_1) & (1 << AACK_SET_PD)) |
kevman | 2:7aab896b1a3b | 861 | last_acked_data_pending = 1; |
kevman | 2:7aab896b1a3b | 862 | else |
kevman | 2:7aab896b1a3b | 863 | last_acked_data_pending = 0; |
kevman | 2:7aab896b1a3b | 864 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 865 | |
kevman | 2:7aab896b1a3b | 866 | return last_acked_data_pending; |
kevman | 2:7aab896b1a3b | 867 | } |
kevman | 2:7aab896b1a3b | 868 | |
kevman | 2:7aab896b1a3b | 869 | /* |
kevman | 2:7aab896b1a3b | 870 | * \brief Function calibrates the RF part. |
kevman | 2:7aab896b1a3b | 871 | * |
kevman | 2:7aab896b1a3b | 872 | * \param none |
kevman | 2:7aab896b1a3b | 873 | * |
kevman | 2:7aab896b1a3b | 874 | * \return none |
kevman | 2:7aab896b1a3b | 875 | */ |
kevman | 2:7aab896b1a3b | 876 | static void rf_if_calibration(void) |
kevman | 2:7aab896b1a3b | 877 | { |
kevman | 2:7aab896b1a3b | 878 | rf_if_set_bit(FTN_CTRL, FTN_START, FTN_START); |
kevman | 2:7aab896b1a3b | 879 | /*Wait while calibration is running*/ |
kevman | 2:7aab896b1a3b | 880 | while(rf_if_read_register(FTN_CTRL) & FTN_START); |
kevman | 2:7aab896b1a3b | 881 | } |
kevman | 2:7aab896b1a3b | 882 | |
kevman | 2:7aab896b1a3b | 883 | /* |
kevman | 2:7aab896b1a3b | 884 | * \brief Function writes RF PAN Id registers |
kevman | 2:7aab896b1a3b | 885 | * |
kevman | 2:7aab896b1a3b | 886 | * \param pan_id Given PAN Id |
kevman | 2:7aab896b1a3b | 887 | * |
kevman | 2:7aab896b1a3b | 888 | * \return none |
kevman | 2:7aab896b1a3b | 889 | */ |
kevman | 2:7aab896b1a3b | 890 | static void rf_if_write_pan_id_registers(uint8_t *pan_id) |
kevman | 2:7aab896b1a3b | 891 | { |
kevman | 2:7aab896b1a3b | 892 | rf_if_write_register(PAN_ID_1, *pan_id++); |
kevman | 2:7aab896b1a3b | 893 | rf_if_write_register(PAN_ID_0, *pan_id); |
kevman | 2:7aab896b1a3b | 894 | } |
kevman | 2:7aab896b1a3b | 895 | |
kevman | 2:7aab896b1a3b | 896 | /* |
kevman | 2:7aab896b1a3b | 897 | * \brief Function writes RF IEEE Address registers |
kevman | 2:7aab896b1a3b | 898 | * |
kevman | 2:7aab896b1a3b | 899 | * \param address Given IEEE Address |
kevman | 2:7aab896b1a3b | 900 | * |
kevman | 2:7aab896b1a3b | 901 | * \return none |
kevman | 2:7aab896b1a3b | 902 | */ |
kevman | 2:7aab896b1a3b | 903 | static void rf_if_write_ieee_addr_registers(uint8_t *address) |
kevman | 2:7aab896b1a3b | 904 | { |
kevman | 2:7aab896b1a3b | 905 | uint8_t i; |
kevman | 2:7aab896b1a3b | 906 | uint8_t temp = IEEE_ADDR_0; |
kevman | 2:7aab896b1a3b | 907 | |
kevman | 2:7aab896b1a3b | 908 | for(i=0; i<8; i++) |
kevman | 2:7aab896b1a3b | 909 | rf_if_write_register(temp++, address[7-i]); |
kevman | 2:7aab896b1a3b | 910 | } |
kevman | 2:7aab896b1a3b | 911 | |
kevman | 2:7aab896b1a3b | 912 | /* |
kevman | 2:7aab896b1a3b | 913 | * \brief Function writes data in RF frame buffer. |
kevman | 2:7aab896b1a3b | 914 | * |
kevman | 2:7aab896b1a3b | 915 | * \param ptr Pointer to data (PSDU, except FCS) |
kevman | 2:7aab896b1a3b | 916 | * \param length Pointer to length (PSDU length, minus 2 for FCS) |
kevman | 2:7aab896b1a3b | 917 | * |
kevman | 2:7aab896b1a3b | 918 | * \return none |
kevman | 2:7aab896b1a3b | 919 | */ |
kevman | 2:7aab896b1a3b | 920 | static void rf_if_write_frame_buffer(const uint8_t *ptr, uint8_t length) |
kevman | 2:7aab896b1a3b | 921 | { |
kevman | 2:7aab896b1a3b | 922 | const uint8_t cmd[2] = { 0x60, static_cast<uint8_t>(length + 2) }; |
kevman | 2:7aab896b1a3b | 923 | |
kevman | 2:7aab896b1a3b | 924 | CS_SELECT(); |
kevman | 2:7aab896b1a3b | 925 | rf_if_spi_exchange_n(cmd, 2, NULL, 0); |
kevman | 2:7aab896b1a3b | 926 | rf_if_spi_exchange_n(ptr, length, NULL, 0); |
kevman | 2:7aab896b1a3b | 927 | CS_RELEASE(); |
kevman | 2:7aab896b1a3b | 928 | } |
kevman | 2:7aab896b1a3b | 929 | |
kevman | 2:7aab896b1a3b | 930 | /* |
kevman | 2:7aab896b1a3b | 931 | * \brief Function returns 8-bit random value. |
kevman | 2:7aab896b1a3b | 932 | * |
kevman | 2:7aab896b1a3b | 933 | * \param none |
kevman | 2:7aab896b1a3b | 934 | * |
kevman | 2:7aab896b1a3b | 935 | * \return random value |
kevman | 2:7aab896b1a3b | 936 | */ |
kevman | 2:7aab896b1a3b | 937 | static uint8_t rf_if_read_rnd(void) |
kevman | 2:7aab896b1a3b | 938 | { |
kevman | 2:7aab896b1a3b | 939 | uint8_t temp; |
kevman | 2:7aab896b1a3b | 940 | uint8_t tmp_rpc_val = 0; |
kevman | 2:7aab896b1a3b | 941 | /*RPC must be disabled while reading the random number*/ |
kevman | 2:7aab896b1a3b | 942 | if(rf_part_num == PART_AT86RF233) |
kevman | 2:7aab896b1a3b | 943 | { |
kevman | 2:7aab896b1a3b | 944 | tmp_rpc_val = rf_if_read_register(TRX_RPC); |
kevman | 2:7aab896b1a3b | 945 | rf_if_write_register(TRX_RPC, RX_RPC_CTRL|TRX_RPC_RSVD_1); |
kevman | 2:7aab896b1a3b | 946 | } |
kevman | 2:7aab896b1a3b | 947 | |
kevman | 2:7aab896b1a3b | 948 | wait_ms(1); |
kevman | 2:7aab896b1a3b | 949 | temp = ((rf_if_read_register(PHY_RSSI)>>5) << 6); |
kevman | 2:7aab896b1a3b | 950 | wait_ms(1); |
kevman | 2:7aab896b1a3b | 951 | temp |= ((rf_if_read_register(PHY_RSSI)>>5) << 4); |
kevman | 2:7aab896b1a3b | 952 | wait_ms(1); |
kevman | 2:7aab896b1a3b | 953 | temp |= ((rf_if_read_register(PHY_RSSI)>>5) << 2); |
kevman | 2:7aab896b1a3b | 954 | wait_ms(1); |
kevman | 2:7aab896b1a3b | 955 | temp |= ((rf_if_read_register(PHY_RSSI)>>5)); |
kevman | 2:7aab896b1a3b | 956 | wait_ms(1); |
kevman | 2:7aab896b1a3b | 957 | if(rf_part_num == PART_AT86RF233) |
kevman | 2:7aab896b1a3b | 958 | rf_if_write_register(TRX_RPC, tmp_rpc_val); |
kevman | 2:7aab896b1a3b | 959 | return temp; |
kevman | 2:7aab896b1a3b | 960 | } |
kevman | 2:7aab896b1a3b | 961 | |
kevman | 2:7aab896b1a3b | 962 | /* |
kevman | 2:7aab896b1a3b | 963 | * \brief Function changes the state of the RF. |
kevman | 2:7aab896b1a3b | 964 | * |
kevman | 2:7aab896b1a3b | 965 | * \param trx_state Given RF state |
kevman | 2:7aab896b1a3b | 966 | * |
kevman | 2:7aab896b1a3b | 967 | * \return none |
kevman | 2:7aab896b1a3b | 968 | */ |
kevman | 2:7aab896b1a3b | 969 | static rf_trx_states_t rf_if_change_trx_state(rf_trx_states_t trx_state) |
kevman | 2:7aab896b1a3b | 970 | { |
kevman | 2:7aab896b1a3b | 971 | rf_if_write_register(TRX_STATE, trx_state); |
kevman | 2:7aab896b1a3b | 972 | /*Wait while not in desired state*/ |
kevman | 2:7aab896b1a3b | 973 | return rf_poll_trx_state_change(trx_state); |
kevman | 2:7aab896b1a3b | 974 | } |
kevman | 2:7aab896b1a3b | 975 | |
kevman | 2:7aab896b1a3b | 976 | /* |
kevman | 2:7aab896b1a3b | 977 | * \brief Function starts the CCA process |
kevman | 2:7aab896b1a3b | 978 | * |
kevman | 2:7aab896b1a3b | 979 | * \param none |
kevman | 2:7aab896b1a3b | 980 | * |
kevman | 2:7aab896b1a3b | 981 | * \return none |
kevman | 2:7aab896b1a3b | 982 | */ |
kevman | 2:7aab896b1a3b | 983 | static void rf_if_start_cca_process(void) |
kevman | 2:7aab896b1a3b | 984 | { |
kevman | 2:7aab896b1a3b | 985 | rf_if_write_register(PHY_CC_CCA, CCA_REQUEST | CCA_MODE_3A | rf_phy_channel); |
kevman | 2:7aab896b1a3b | 986 | } |
kevman | 2:7aab896b1a3b | 987 | |
kevman | 2:7aab896b1a3b | 988 | /* |
kevman | 2:7aab896b1a3b | 989 | * \brief Function scales RSSI |
kevman | 2:7aab896b1a3b | 990 | * |
kevman | 2:7aab896b1a3b | 991 | * \param ed_level ED level read from chip |
kevman | 2:7aab896b1a3b | 992 | * |
kevman | 2:7aab896b1a3b | 993 | * \return appropriately scaled RSSI dBm |
kevman | 2:7aab896b1a3b | 994 | */ |
kevman | 2:7aab896b1a3b | 995 | static int8_t rf_if_scale_rssi(uint8_t ed_level) |
kevman | 2:7aab896b1a3b | 996 | { |
kevman | 2:7aab896b1a3b | 997 | if (rf_part_num == PART_AT86RF212) { |
kevman | 2:7aab896b1a3b | 998 | /* Data sheet says to multiply by 1.03 - this is 1.03125, rounding down */ |
kevman | 2:7aab896b1a3b | 999 | ed_level += ed_level >> 5; |
kevman | 2:7aab896b1a3b | 1000 | } |
kevman | 2:7aab896b1a3b | 1001 | return rf_rssi_base_val + ed_level; |
kevman | 2:7aab896b1a3b | 1002 | } |
kevman | 2:7aab896b1a3b | 1003 | |
kevman | 2:7aab896b1a3b | 1004 | /* |
kevman | 2:7aab896b1a3b | 1005 | * \brief Function sets the RF channel field |
kevman | 2:7aab896b1a3b | 1006 | * |
kevman | 2:7aab896b1a3b | 1007 | * \param Given channel |
kevman | 2:7aab896b1a3b | 1008 | * |
kevman | 2:7aab896b1a3b | 1009 | * \return none |
kevman | 2:7aab896b1a3b | 1010 | */ |
kevman | 2:7aab896b1a3b | 1011 | static void rf_if_set_channel_register(uint8_t channel) |
kevman | 2:7aab896b1a3b | 1012 | { |
kevman | 2:7aab896b1a3b | 1013 | rf_if_set_bit(PHY_CC_CCA, channel, CCA_CHANNEL_MASK); |
kevman | 2:7aab896b1a3b | 1014 | } |
kevman | 2:7aab896b1a3b | 1015 | |
kevman | 2:7aab896b1a3b | 1016 | /* |
kevman | 2:7aab896b1a3b | 1017 | * \brief Function enables RF irq pin interrupts in RF interface. |
kevman | 2:7aab896b1a3b | 1018 | * |
kevman | 2:7aab896b1a3b | 1019 | * \param none |
kevman | 2:7aab896b1a3b | 1020 | * |
kevman | 2:7aab896b1a3b | 1021 | * \return none |
kevman | 2:7aab896b1a3b | 1022 | */ |
kevman | 2:7aab896b1a3b | 1023 | static void rf_if_enable_irq(void) |
kevman | 2:7aab896b1a3b | 1024 | { |
kevman | 2:7aab896b1a3b | 1025 | rf->IRQ.enable_irq(); |
kevman | 2:7aab896b1a3b | 1026 | } |
kevman | 2:7aab896b1a3b | 1027 | |
kevman | 2:7aab896b1a3b | 1028 | /* |
kevman | 2:7aab896b1a3b | 1029 | * \brief Function disables RF irq pin interrupts in RF interface. |
kevman | 2:7aab896b1a3b | 1030 | * |
kevman | 2:7aab896b1a3b | 1031 | * \param none |
kevman | 2:7aab896b1a3b | 1032 | * |
kevman | 2:7aab896b1a3b | 1033 | * \return none |
kevman | 2:7aab896b1a3b | 1034 | */ |
kevman | 2:7aab896b1a3b | 1035 | static void rf_if_disable_irq(void) |
kevman | 2:7aab896b1a3b | 1036 | { |
kevman | 2:7aab896b1a3b | 1037 | rf->IRQ.disable_irq(); |
kevman | 2:7aab896b1a3b | 1038 | } |
kevman | 2:7aab896b1a3b | 1039 | |
kevman | 2:7aab896b1a3b | 1040 | #ifdef MBED_CONF_RTOS_PRESENT |
kevman | 2:7aab896b1a3b | 1041 | static void rf_if_interrupt_handler(void) |
kevman | 2:7aab896b1a3b | 1042 | { |
kevman | 2:7aab896b1a3b | 1043 | rf->irq_thread.signal_set(SIG_RADIO); |
kevman | 2:7aab896b1a3b | 1044 | } |
kevman | 2:7aab896b1a3b | 1045 | |
kevman | 2:7aab896b1a3b | 1046 | // Started during construction of rf, so variable |
kevman | 2:7aab896b1a3b | 1047 | // rf isn't set at the start. Uses 'this' instead. |
kevman | 2:7aab896b1a3b | 1048 | void RFBits::rf_if_irq_task(void) |
kevman | 2:7aab896b1a3b | 1049 | { |
kevman | 2:7aab896b1a3b | 1050 | for (;;) { |
kevman | 2:7aab896b1a3b | 1051 | osEvent event = irq_thread.signal_wait(0); |
kevman | 2:7aab896b1a3b | 1052 | if (event.status != osEventSignal) { |
kevman | 2:7aab896b1a3b | 1053 | continue; |
kevman | 2:7aab896b1a3b | 1054 | } |
kevman | 2:7aab896b1a3b | 1055 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1056 | if (event.value.signals & SIG_RADIO) { |
kevman | 2:7aab896b1a3b | 1057 | rf_if_irq_task_process_irq(); |
kevman | 2:7aab896b1a3b | 1058 | } |
kevman | 2:7aab896b1a3b | 1059 | if (event.value.signals & SIG_TIMER_ACK) { |
kevman | 2:7aab896b1a3b | 1060 | rf_ack_wait_timer_interrupt(); |
kevman | 2:7aab896b1a3b | 1061 | } |
kevman | 2:7aab896b1a3b | 1062 | if (event.value.signals & SIG_TIMER_CCA) { |
kevman | 2:7aab896b1a3b | 1063 | rf_cca_timer_interrupt(); |
kevman | 2:7aab896b1a3b | 1064 | } |
kevman | 2:7aab896b1a3b | 1065 | if (event.value.signals & SIG_TIMER_CAL) { |
kevman | 2:7aab896b1a3b | 1066 | rf_calibration_timer_interrupt(); |
kevman | 2:7aab896b1a3b | 1067 | } |
kevman | 2:7aab896b1a3b | 1068 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1069 | } |
kevman | 2:7aab896b1a3b | 1070 | } |
kevman | 2:7aab896b1a3b | 1071 | |
kevman | 2:7aab896b1a3b | 1072 | static void rf_if_irq_task_process_irq(void) |
kevman | 2:7aab896b1a3b | 1073 | #else |
kevman | 2:7aab896b1a3b | 1074 | /* |
kevman | 2:7aab896b1a3b | 1075 | * \brief Function is a RF interrupt vector. End of frame in RX and TX are handled here as well as CCA process interrupt. |
kevman | 2:7aab896b1a3b | 1076 | * |
kevman | 2:7aab896b1a3b | 1077 | * \param none |
kevman | 2:7aab896b1a3b | 1078 | * |
kevman | 2:7aab896b1a3b | 1079 | * \return none |
kevman | 2:7aab896b1a3b | 1080 | */ |
kevman | 2:7aab896b1a3b | 1081 | static void rf_if_interrupt_handler(void) |
kevman | 2:7aab896b1a3b | 1082 | #endif |
kevman | 2:7aab896b1a3b | 1083 | { |
kevman | 2:7aab896b1a3b | 1084 | static uint8_t last_is, last_ts; |
kevman | 2:7aab896b1a3b | 1085 | uint8_t irq_status, full_trx_status; |
kevman | 2:7aab896b1a3b | 1086 | uint8_t orig_xah_ctrl_1 = xah_ctrl_1; |
kevman | 2:7aab896b1a3b | 1087 | |
kevman | 2:7aab896b1a3b | 1088 | /*Read and clear interrupt flag, and pick up trx_status*/ |
kevman | 2:7aab896b1a3b | 1089 | irq_status = rf_if_read_register_with_status(IRQ_STATUS, &full_trx_status); |
kevman | 2:7aab896b1a3b | 1090 | uint8_t orig_flags = rf_flags; |
kevman | 2:7aab896b1a3b | 1091 | |
kevman | 2:7aab896b1a3b | 1092 | /*Frame end interrupt (RX and TX)*/ |
kevman | 2:7aab896b1a3b | 1093 | if(irq_status & TRX_END) |
kevman | 2:7aab896b1a3b | 1094 | { |
kevman | 2:7aab896b1a3b | 1095 | /*TX done interrupt*/ |
kevman | 2:7aab896b1a3b | 1096 | rf_trx_states_t trx_status = rf_if_trx_status_from_full(full_trx_status); |
kevman | 2:7aab896b1a3b | 1097 | if(trx_status == PLL_ON || trx_status == TX_ARET_ON) |
kevman | 2:7aab896b1a3b | 1098 | { |
kevman | 2:7aab896b1a3b | 1099 | rf_handle_tx_end(trx_status); |
kevman | 2:7aab896b1a3b | 1100 | } |
kevman | 2:7aab896b1a3b | 1101 | /*Frame received interrupt*/ |
kevman | 2:7aab896b1a3b | 1102 | else |
kevman | 2:7aab896b1a3b | 1103 | { |
kevman | 2:7aab896b1a3b | 1104 | rf_handle_rx_end(trx_status); |
kevman | 2:7aab896b1a3b | 1105 | } |
kevman | 2:7aab896b1a3b | 1106 | } |
kevman | 2:7aab896b1a3b | 1107 | if(irq_status & CCA_ED_DONE) |
kevman | 2:7aab896b1a3b | 1108 | { |
kevman | 2:7aab896b1a3b | 1109 | rf_handle_cca_ed_done(full_trx_status); |
kevman | 2:7aab896b1a3b | 1110 | } |
kevman | 2:7aab896b1a3b | 1111 | if (irq_status & TRX_UR) |
kevman | 2:7aab896b1a3b | 1112 | { |
kevman | 2:7aab896b1a3b | 1113 | tr_error("Radio underrun is %x->%x ts %x->%x fl %x->%x x1 %x", last_is, irq_status, last_ts, full_trx_status, orig_flags, rf_flags, orig_xah_ctrl_1); |
kevman | 2:7aab896b1a3b | 1114 | } |
kevman | 2:7aab896b1a3b | 1115 | last_is = irq_status; |
kevman | 2:7aab896b1a3b | 1116 | last_ts = full_trx_status; |
kevman | 2:7aab896b1a3b | 1117 | } |
kevman | 2:7aab896b1a3b | 1118 | |
kevman | 2:7aab896b1a3b | 1119 | /* |
kevman | 2:7aab896b1a3b | 1120 | * \brief Function writes/read data in SPI interface |
kevman | 2:7aab896b1a3b | 1121 | */ |
kevman | 2:7aab896b1a3b | 1122 | static void rf_if_spi_exchange_n(const void *tx, size_t tx_len, void *rx, size_t rx_len) |
kevman | 2:7aab896b1a3b | 1123 | { |
kevman | 2:7aab896b1a3b | 1124 | #if 1 |
kevman | 2:7aab896b1a3b | 1125 | rf->spi.write(static_cast<const char *>(tx), tx_len, |
kevman | 2:7aab896b1a3b | 1126 | static_cast<char *>(rx), rx_len); |
kevman | 2:7aab896b1a3b | 1127 | #else |
kevman | 2:7aab896b1a3b | 1128 | const uint8_t *txb = static_cast<const uint8_t *>(tx); |
kevman | 2:7aab896b1a3b | 1129 | uint8_t *rxb = static_cast<uint8_t *>(rx); |
kevman | 2:7aab896b1a3b | 1130 | while (tx_len > 0 || rx_len > 0) { |
kevman | 2:7aab896b1a3b | 1131 | uint8_t b; |
kevman | 2:7aab896b1a3b | 1132 | if (tx_len) { |
kevman | 2:7aab896b1a3b | 1133 | tx_len--; |
kevman | 2:7aab896b1a3b | 1134 | b = *txb++; |
kevman | 2:7aab896b1a3b | 1135 | } else { |
kevman | 2:7aab896b1a3b | 1136 | b = 0xFF; |
kevman | 2:7aab896b1a3b | 1137 | } |
kevman | 2:7aab896b1a3b | 1138 | b = rf->spi.write(b); |
kevman | 2:7aab896b1a3b | 1139 | if (rx_len) { |
kevman | 2:7aab896b1a3b | 1140 | rx_len--; |
kevman | 2:7aab896b1a3b | 1141 | *rxb++ = b; |
kevman | 2:7aab896b1a3b | 1142 | } |
kevman | 2:7aab896b1a3b | 1143 | } |
kevman | 2:7aab896b1a3b | 1144 | #endif |
kevman | 2:7aab896b1a3b | 1145 | } |
kevman | 2:7aab896b1a3b | 1146 | |
kevman | 2:7aab896b1a3b | 1147 | /* |
kevman | 2:7aab896b1a3b | 1148 | * \brief Function sets given RF flag on. |
kevman | 2:7aab896b1a3b | 1149 | * |
kevman | 2:7aab896b1a3b | 1150 | * \param x Given RF flag |
kevman | 2:7aab896b1a3b | 1151 | * |
kevman | 2:7aab896b1a3b | 1152 | * \return none |
kevman | 2:7aab896b1a3b | 1153 | */ |
kevman | 2:7aab896b1a3b | 1154 | static void rf_flags_set(uint8_t x) |
kevman | 2:7aab896b1a3b | 1155 | { |
kevman | 2:7aab896b1a3b | 1156 | rf_flags |= x; |
kevman | 2:7aab896b1a3b | 1157 | } |
kevman | 2:7aab896b1a3b | 1158 | |
kevman | 2:7aab896b1a3b | 1159 | /* |
kevman | 2:7aab896b1a3b | 1160 | * \brief Function clears given RF flag on. |
kevman | 2:7aab896b1a3b | 1161 | * |
kevman | 2:7aab896b1a3b | 1162 | * \param x Given RF flag |
kevman | 2:7aab896b1a3b | 1163 | * |
kevman | 2:7aab896b1a3b | 1164 | * \return none |
kevman | 2:7aab896b1a3b | 1165 | */ |
kevman | 2:7aab896b1a3b | 1166 | static void rf_flags_clear(uint8_t x) |
kevman | 2:7aab896b1a3b | 1167 | { |
kevman | 2:7aab896b1a3b | 1168 | rf_flags &= ~x; |
kevman | 2:7aab896b1a3b | 1169 | } |
kevman | 2:7aab896b1a3b | 1170 | |
kevman | 2:7aab896b1a3b | 1171 | /* |
kevman | 2:7aab896b1a3b | 1172 | * \brief Function checks if given RF flag is on. |
kevman | 2:7aab896b1a3b | 1173 | * |
kevman | 2:7aab896b1a3b | 1174 | * \param x Given RF flag |
kevman | 2:7aab896b1a3b | 1175 | * |
kevman | 2:7aab896b1a3b | 1176 | * \return states of the given flags |
kevman | 2:7aab896b1a3b | 1177 | */ |
kevman | 2:7aab896b1a3b | 1178 | static uint8_t rf_flags_check(uint8_t x) |
kevman | 2:7aab896b1a3b | 1179 | { |
kevman | 2:7aab896b1a3b | 1180 | return (rf_flags & x); |
kevman | 2:7aab896b1a3b | 1181 | } |
kevman | 2:7aab896b1a3b | 1182 | |
kevman | 2:7aab896b1a3b | 1183 | /* |
kevman | 2:7aab896b1a3b | 1184 | * \brief Function clears all RF flags. |
kevman | 2:7aab896b1a3b | 1185 | * |
kevman | 2:7aab896b1a3b | 1186 | * \param none |
kevman | 2:7aab896b1a3b | 1187 | * |
kevman | 2:7aab896b1a3b | 1188 | * \return none |
kevman | 2:7aab896b1a3b | 1189 | */ |
kevman | 2:7aab896b1a3b | 1190 | static void rf_flags_reset(void) |
kevman | 2:7aab896b1a3b | 1191 | { |
kevman | 2:7aab896b1a3b | 1192 | rf_flags = 0; |
kevman | 2:7aab896b1a3b | 1193 | } |
kevman | 2:7aab896b1a3b | 1194 | |
kevman | 2:7aab896b1a3b | 1195 | /* |
kevman | 2:7aab896b1a3b | 1196 | * \brief Function initialises and registers the RF driver. |
kevman | 2:7aab896b1a3b | 1197 | * |
kevman | 2:7aab896b1a3b | 1198 | * \param none |
kevman | 2:7aab896b1a3b | 1199 | * |
kevman | 2:7aab896b1a3b | 1200 | * \return rf_radio_driver_id Driver ID given by NET library |
kevman | 2:7aab896b1a3b | 1201 | */ |
kevman | 2:7aab896b1a3b | 1202 | static int8_t rf_device_register(const uint8_t *mac_addr) |
kevman | 2:7aab896b1a3b | 1203 | { |
kevman | 2:7aab896b1a3b | 1204 | rf_trx_part_e radio_type; |
kevman | 2:7aab896b1a3b | 1205 | |
kevman | 2:7aab896b1a3b | 1206 | rf_init(); |
kevman | 2:7aab896b1a3b | 1207 | |
kevman | 2:7aab896b1a3b | 1208 | radio_type = rf_radio_type_read(); |
kevman | 2:7aab896b1a3b | 1209 | if(radio_type != ATMEL_UNKNOW_DEV) |
kevman | 2:7aab896b1a3b | 1210 | { |
kevman | 2:7aab896b1a3b | 1211 | /*Set pointer to MAC address*/ |
kevman | 2:7aab896b1a3b | 1212 | device_driver.PHY_MAC = (uint8_t *)mac_addr; |
kevman | 2:7aab896b1a3b | 1213 | device_driver.driver_description = (char*)"ATMEL_MAC"; |
kevman | 2:7aab896b1a3b | 1214 | //Create setup Used Radio chips |
kevman | 2:7aab896b1a3b | 1215 | if(radio_type == ATMEL_AT86RF212) |
kevman | 2:7aab896b1a3b | 1216 | { |
kevman | 2:7aab896b1a3b | 1217 | device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE; |
kevman | 2:7aab896b1a3b | 1218 | } |
kevman | 2:7aab896b1a3b | 1219 | else |
kevman | 2:7aab896b1a3b | 1220 | { |
kevman | 2:7aab896b1a3b | 1221 | device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE; |
kevman | 2:7aab896b1a3b | 1222 | } |
kevman | 2:7aab896b1a3b | 1223 | device_driver.phy_channel_pages = phy_channel_pages; |
kevman | 2:7aab896b1a3b | 1224 | /*Maximum size of payload is 127*/ |
kevman | 2:7aab896b1a3b | 1225 | device_driver.phy_MTU = 127; |
kevman | 2:7aab896b1a3b | 1226 | /*No header in PHY*/ |
kevman | 2:7aab896b1a3b | 1227 | device_driver.phy_header_length = 0; |
kevman | 2:7aab896b1a3b | 1228 | /*No tail in PHY*/ |
kevman | 2:7aab896b1a3b | 1229 | device_driver.phy_tail_length = 0; |
kevman | 2:7aab896b1a3b | 1230 | /*Set address write function*/ |
kevman | 2:7aab896b1a3b | 1231 | device_driver.address_write = &rf_address_write; |
kevman | 2:7aab896b1a3b | 1232 | /*Set RF extension function*/ |
kevman | 2:7aab896b1a3b | 1233 | device_driver.extension = &rf_extension; |
kevman | 2:7aab896b1a3b | 1234 | /*Set RF state control function*/ |
kevman | 2:7aab896b1a3b | 1235 | device_driver.state_control = &rf_interface_state_control; |
kevman | 2:7aab896b1a3b | 1236 | /*Set transmit function*/ |
kevman | 2:7aab896b1a3b | 1237 | device_driver.tx = &rf_start_cca; |
kevman | 2:7aab896b1a3b | 1238 | /*NULLIFY rx and tx_done callbacks*/ |
kevman | 2:7aab896b1a3b | 1239 | device_driver.phy_rx_cb = NULL; |
kevman | 2:7aab896b1a3b | 1240 | device_driver.phy_tx_done_cb = NULL; |
kevman | 2:7aab896b1a3b | 1241 | /*Register device driver*/ |
kevman | 2:7aab896b1a3b | 1242 | rf_radio_driver_id = arm_net_phy_register(&device_driver); |
kevman | 2:7aab896b1a3b | 1243 | } else { |
kevman | 2:7aab896b1a3b | 1244 | rf_if_disable_irq(); |
kevman | 2:7aab896b1a3b | 1245 | } |
kevman | 2:7aab896b1a3b | 1246 | return rf_radio_driver_id; |
kevman | 2:7aab896b1a3b | 1247 | } |
kevman | 2:7aab896b1a3b | 1248 | |
kevman | 2:7aab896b1a3b | 1249 | /* |
kevman | 2:7aab896b1a3b | 1250 | * \brief Function unregisters the RF driver. |
kevman | 2:7aab896b1a3b | 1251 | * |
kevman | 2:7aab896b1a3b | 1252 | * \param none |
kevman | 2:7aab896b1a3b | 1253 | * |
kevman | 2:7aab896b1a3b | 1254 | * \return none |
kevman | 2:7aab896b1a3b | 1255 | */ |
kevman | 2:7aab896b1a3b | 1256 | static void rf_device_unregister() |
kevman | 2:7aab896b1a3b | 1257 | { |
kevman | 2:7aab896b1a3b | 1258 | if (rf_radio_driver_id >= 0) { |
kevman | 2:7aab896b1a3b | 1259 | arm_net_phy_unregister(rf_radio_driver_id); |
kevman | 2:7aab896b1a3b | 1260 | rf_radio_driver_id = -1; |
kevman | 2:7aab896b1a3b | 1261 | } |
kevman | 2:7aab896b1a3b | 1262 | } |
kevman | 2:7aab896b1a3b | 1263 | |
kevman | 2:7aab896b1a3b | 1264 | |
kevman | 2:7aab896b1a3b | 1265 | /* |
kevman | 2:7aab896b1a3b | 1266 | * \brief Function is a call back for ACK wait timeout. |
kevman | 2:7aab896b1a3b | 1267 | * |
kevman | 2:7aab896b1a3b | 1268 | * \param none |
kevman | 2:7aab896b1a3b | 1269 | * |
kevman | 2:7aab896b1a3b | 1270 | * \return none |
kevman | 2:7aab896b1a3b | 1271 | */ |
kevman | 2:7aab896b1a3b | 1272 | static void rf_ack_wait_timer_interrupt(void) |
kevman | 2:7aab896b1a3b | 1273 | { |
kevman | 2:7aab896b1a3b | 1274 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1275 | rf_give_up_on_ack(); |
kevman | 2:7aab896b1a3b | 1276 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1277 | } |
kevman | 2:7aab896b1a3b | 1278 | |
kevman | 2:7aab896b1a3b | 1279 | /* |
kevman | 2:7aab896b1a3b | 1280 | * \brief Function is a call back for calibration interval timer. |
kevman | 2:7aab896b1a3b | 1281 | * |
kevman | 2:7aab896b1a3b | 1282 | * \param none |
kevman | 2:7aab896b1a3b | 1283 | * |
kevman | 2:7aab896b1a3b | 1284 | * \return none |
kevman | 2:7aab896b1a3b | 1285 | */ |
kevman | 2:7aab896b1a3b | 1286 | static void rf_calibration_timer_interrupt(void) |
kevman | 2:7aab896b1a3b | 1287 | { |
kevman | 2:7aab896b1a3b | 1288 | /*Calibrate RF*/ |
kevman | 2:7aab896b1a3b | 1289 | rf_calibration_cb(); |
kevman | 2:7aab896b1a3b | 1290 | /*Start new calibration timeout*/ |
kevman | 2:7aab896b1a3b | 1291 | rf_calibration_timer_start(RF_CALIBRATION_INTERVAL); |
kevman | 2:7aab896b1a3b | 1292 | } |
kevman | 2:7aab896b1a3b | 1293 | |
kevman | 2:7aab896b1a3b | 1294 | /* |
kevman | 2:7aab896b1a3b | 1295 | * \brief Function is a call back for cca interval timer. |
kevman | 2:7aab896b1a3b | 1296 | * |
kevman | 2:7aab896b1a3b | 1297 | * \param none |
kevman | 2:7aab896b1a3b | 1298 | * |
kevman | 2:7aab896b1a3b | 1299 | * \return none |
kevman | 2:7aab896b1a3b | 1300 | */ |
kevman | 2:7aab896b1a3b | 1301 | static void rf_cca_timer_interrupt(void) |
kevman | 2:7aab896b1a3b | 1302 | { |
kevman | 2:7aab896b1a3b | 1303 | rf_flags_set(RFF_CCA); |
kevman | 2:7aab896b1a3b | 1304 | /*Start CCA process*/ |
kevman | 2:7aab896b1a3b | 1305 | rf_if_start_cca_process(); |
kevman | 2:7aab896b1a3b | 1306 | } |
kevman | 2:7aab896b1a3b | 1307 | |
kevman | 2:7aab896b1a3b | 1308 | /* |
kevman | 2:7aab896b1a3b | 1309 | * \brief Function starts the ACK wait timeout. |
kevman | 2:7aab896b1a3b | 1310 | * |
kevman | 2:7aab896b1a3b | 1311 | * \param slots Given slots, resolution 50us |
kevman | 2:7aab896b1a3b | 1312 | * |
kevman | 2:7aab896b1a3b | 1313 | * \return none |
kevman | 2:7aab896b1a3b | 1314 | */ |
kevman | 2:7aab896b1a3b | 1315 | static void rf_ack_wait_timer_start(uint16_t slots) |
kevman | 2:7aab896b1a3b | 1316 | { |
kevman | 2:7aab896b1a3b | 1317 | rf_if_ack_wait_timer_start(slots); |
kevman | 2:7aab896b1a3b | 1318 | } |
kevman | 2:7aab896b1a3b | 1319 | |
kevman | 2:7aab896b1a3b | 1320 | /* |
kevman | 2:7aab896b1a3b | 1321 | * \brief Function starts the calibration interval. |
kevman | 2:7aab896b1a3b | 1322 | * |
kevman | 2:7aab896b1a3b | 1323 | * \param slots Given slots, resolution 50us |
kevman | 2:7aab896b1a3b | 1324 | * |
kevman | 2:7aab896b1a3b | 1325 | * \return none |
kevman | 2:7aab896b1a3b | 1326 | */ |
kevman | 2:7aab896b1a3b | 1327 | static void rf_calibration_timer_start(uint32_t slots) |
kevman | 2:7aab896b1a3b | 1328 | { |
kevman | 2:7aab896b1a3b | 1329 | rf_if_calibration_timer_start(slots); |
kevman | 2:7aab896b1a3b | 1330 | } |
kevman | 2:7aab896b1a3b | 1331 | |
kevman | 2:7aab896b1a3b | 1332 | /* |
kevman | 2:7aab896b1a3b | 1333 | * \brief Function starts the CCA backoff. |
kevman | 2:7aab896b1a3b | 1334 | * |
kevman | 2:7aab896b1a3b | 1335 | * \param slots Given slots, resolution 50us |
kevman | 2:7aab896b1a3b | 1336 | * |
kevman | 2:7aab896b1a3b | 1337 | * \return none |
kevman | 2:7aab896b1a3b | 1338 | */ |
kevman | 2:7aab896b1a3b | 1339 | static void rf_cca_timer_start(uint32_t slots) |
kevman | 2:7aab896b1a3b | 1340 | { |
kevman | 2:7aab896b1a3b | 1341 | rf_if_cca_timer_start(slots); |
kevman | 2:7aab896b1a3b | 1342 | } |
kevman | 2:7aab896b1a3b | 1343 | |
kevman | 2:7aab896b1a3b | 1344 | /* |
kevman | 2:7aab896b1a3b | 1345 | * \brief Function stops the CCA backoff. |
kevman | 2:7aab896b1a3b | 1346 | * |
kevman | 2:7aab896b1a3b | 1347 | * \return none |
kevman | 2:7aab896b1a3b | 1348 | */ |
kevman | 2:7aab896b1a3b | 1349 | static void rf_cca_timer_stop(void) |
kevman | 2:7aab896b1a3b | 1350 | { |
kevman | 2:7aab896b1a3b | 1351 | rf_if_cca_timer_stop(); |
kevman | 2:7aab896b1a3b | 1352 | } |
kevman | 2:7aab896b1a3b | 1353 | |
kevman | 2:7aab896b1a3b | 1354 | /* |
kevman | 2:7aab896b1a3b | 1355 | * \brief Function writes various RF settings in startup. |
kevman | 2:7aab896b1a3b | 1356 | * |
kevman | 2:7aab896b1a3b | 1357 | * \param none |
kevman | 2:7aab896b1a3b | 1358 | * |
kevman | 2:7aab896b1a3b | 1359 | * \return none |
kevman | 2:7aab896b1a3b | 1360 | */ |
kevman | 2:7aab896b1a3b | 1361 | static void rf_write_settings(void) |
kevman | 2:7aab896b1a3b | 1362 | { |
kevman | 2:7aab896b1a3b | 1363 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1364 | rf_if_write_rf_settings(); |
kevman | 2:7aab896b1a3b | 1365 | /*Set output power*/ |
kevman | 2:7aab896b1a3b | 1366 | rf_if_write_set_tx_power_register(radio_tx_power); |
kevman | 2:7aab896b1a3b | 1367 | /*Initialise Antenna Diversity*/ |
kevman | 2:7aab896b1a3b | 1368 | if(rf_use_antenna_diversity) |
kevman | 2:7aab896b1a3b | 1369 | rf_if_write_antenna_diversity_settings(); |
kevman | 2:7aab896b1a3b | 1370 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1371 | } |
kevman | 2:7aab896b1a3b | 1372 | |
kevman | 2:7aab896b1a3b | 1373 | /* |
kevman | 2:7aab896b1a3b | 1374 | * \brief Function writes 16-bit address in RF address filter. |
kevman | 2:7aab896b1a3b | 1375 | * |
kevman | 2:7aab896b1a3b | 1376 | * \param short_address Given short address |
kevman | 2:7aab896b1a3b | 1377 | * |
kevman | 2:7aab896b1a3b | 1378 | * \return none |
kevman | 2:7aab896b1a3b | 1379 | */ |
kevman | 2:7aab896b1a3b | 1380 | static void rf_set_short_adr(uint8_t * short_address) |
kevman | 2:7aab896b1a3b | 1381 | { |
kevman | 2:7aab896b1a3b | 1382 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1383 | /*Wake up RF if sleeping*/ |
kevman | 2:7aab896b1a3b | 1384 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1385 | { |
kevman | 2:7aab896b1a3b | 1386 | rf_if_disable_slptr(); |
kevman | 2:7aab896b1a3b | 1387 | rf_poll_trx_state_change(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1388 | } |
kevman | 2:7aab896b1a3b | 1389 | /*Write address filter registers*/ |
kevman | 2:7aab896b1a3b | 1390 | rf_if_write_short_addr_registers(short_address); |
kevman | 2:7aab896b1a3b | 1391 | /*RF back to sleep*/ |
kevman | 2:7aab896b1a3b | 1392 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1393 | { |
kevman | 2:7aab896b1a3b | 1394 | rf_if_enable_slptr(); |
kevman | 2:7aab896b1a3b | 1395 | } |
kevman | 2:7aab896b1a3b | 1396 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1397 | } |
kevman | 2:7aab896b1a3b | 1398 | |
kevman | 2:7aab896b1a3b | 1399 | /* |
kevman | 2:7aab896b1a3b | 1400 | * \brief Function writes PAN Id in RF PAN Id filter. |
kevman | 2:7aab896b1a3b | 1401 | * |
kevman | 2:7aab896b1a3b | 1402 | * \param pan_id Given PAN Id |
kevman | 2:7aab896b1a3b | 1403 | * |
kevman | 2:7aab896b1a3b | 1404 | * \return none |
kevman | 2:7aab896b1a3b | 1405 | */ |
kevman | 2:7aab896b1a3b | 1406 | static void rf_set_pan_id(uint8_t *pan_id) |
kevman | 2:7aab896b1a3b | 1407 | { |
kevman | 2:7aab896b1a3b | 1408 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1409 | /*Wake up RF if sleeping*/ |
kevman | 2:7aab896b1a3b | 1410 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1411 | { |
kevman | 2:7aab896b1a3b | 1412 | rf_if_disable_slptr(); |
kevman | 2:7aab896b1a3b | 1413 | rf_poll_trx_state_change(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1414 | } |
kevman | 2:7aab896b1a3b | 1415 | /*Write address filter registers*/ |
kevman | 2:7aab896b1a3b | 1416 | rf_if_write_pan_id_registers(pan_id); |
kevman | 2:7aab896b1a3b | 1417 | /*RF back to sleep*/ |
kevman | 2:7aab896b1a3b | 1418 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1419 | { |
kevman | 2:7aab896b1a3b | 1420 | rf_if_enable_slptr(); |
kevman | 2:7aab896b1a3b | 1421 | } |
kevman | 2:7aab896b1a3b | 1422 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1423 | } |
kevman | 2:7aab896b1a3b | 1424 | |
kevman | 2:7aab896b1a3b | 1425 | /* |
kevman | 2:7aab896b1a3b | 1426 | * \brief Function writes 64-bit address in RF address filter. |
kevman | 2:7aab896b1a3b | 1427 | * |
kevman | 2:7aab896b1a3b | 1428 | * \param address Given 64-bit address |
kevman | 2:7aab896b1a3b | 1429 | * |
kevman | 2:7aab896b1a3b | 1430 | * \return none |
kevman | 2:7aab896b1a3b | 1431 | */ |
kevman | 2:7aab896b1a3b | 1432 | static void rf_set_address(uint8_t *address) |
kevman | 2:7aab896b1a3b | 1433 | { |
kevman | 2:7aab896b1a3b | 1434 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1435 | /*Wake up RF if sleeping*/ |
kevman | 2:7aab896b1a3b | 1436 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1437 | { |
kevman | 2:7aab896b1a3b | 1438 | rf_if_disable_slptr(); |
kevman | 2:7aab896b1a3b | 1439 | rf_poll_trx_state_change(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1440 | } |
kevman | 2:7aab896b1a3b | 1441 | /*Write address filter registers*/ |
kevman | 2:7aab896b1a3b | 1442 | rf_if_write_ieee_addr_registers(address); |
kevman | 2:7aab896b1a3b | 1443 | /*RF back to sleep*/ |
kevman | 2:7aab896b1a3b | 1444 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1445 | { |
kevman | 2:7aab896b1a3b | 1446 | rf_if_enable_slptr(); |
kevman | 2:7aab896b1a3b | 1447 | } |
kevman | 2:7aab896b1a3b | 1448 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1449 | } |
kevman | 2:7aab896b1a3b | 1450 | |
kevman | 2:7aab896b1a3b | 1451 | /* |
kevman | 2:7aab896b1a3b | 1452 | * \brief Function sets the RF channel. |
kevman | 2:7aab896b1a3b | 1453 | * |
kevman | 2:7aab896b1a3b | 1454 | * \param ch New channel |
kevman | 2:7aab896b1a3b | 1455 | * |
kevman | 2:7aab896b1a3b | 1456 | * \return none |
kevman | 2:7aab896b1a3b | 1457 | */ |
kevman | 2:7aab896b1a3b | 1458 | static void rf_channel_set(uint8_t ch) |
kevman | 2:7aab896b1a3b | 1459 | { |
kevman | 2:7aab896b1a3b | 1460 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1461 | rf_phy_channel = ch; |
kevman | 2:7aab896b1a3b | 1462 | if(ch < 0x1f) |
kevman | 2:7aab896b1a3b | 1463 | rf_if_set_channel_register(ch); |
kevman | 2:7aab896b1a3b | 1464 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1465 | } |
kevman | 2:7aab896b1a3b | 1466 | |
kevman | 2:7aab896b1a3b | 1467 | |
kevman | 2:7aab896b1a3b | 1468 | /* |
kevman | 2:7aab896b1a3b | 1469 | * \brief Function initialises the radio driver and resets the radio. |
kevman | 2:7aab896b1a3b | 1470 | * |
kevman | 2:7aab896b1a3b | 1471 | * \param none |
kevman | 2:7aab896b1a3b | 1472 | * |
kevman | 2:7aab896b1a3b | 1473 | * \return none |
kevman | 2:7aab896b1a3b | 1474 | */ |
kevman | 2:7aab896b1a3b | 1475 | static void rf_init(void) |
kevman | 2:7aab896b1a3b | 1476 | { |
kevman | 2:7aab896b1a3b | 1477 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1478 | |
kevman | 2:7aab896b1a3b | 1479 | /*Write RF settings*/ |
kevman | 2:7aab896b1a3b | 1480 | rf_write_settings(); |
kevman | 2:7aab896b1a3b | 1481 | /*Initialise PHY mode*/ |
kevman | 2:7aab896b1a3b | 1482 | rf_init_phy_mode(); |
kevman | 2:7aab896b1a3b | 1483 | /*Clear RF flags*/ |
kevman | 2:7aab896b1a3b | 1484 | rf_flags_reset(); |
kevman | 2:7aab896b1a3b | 1485 | /*Set RF in TRX OFF state*/ |
kevman | 2:7aab896b1a3b | 1486 | rf_if_change_trx_state(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1487 | /*Set RF in PLL_ON state*/ |
kevman | 2:7aab896b1a3b | 1488 | rf_trx_states_t trx_status = rf_if_change_trx_state(PLL_ON); |
kevman | 2:7aab896b1a3b | 1489 | /*Start receiver*/ |
kevman | 2:7aab896b1a3b | 1490 | rf_receive(trx_status); |
kevman | 2:7aab896b1a3b | 1491 | /*Read randomness, and add to seed*/ |
kevman | 2:7aab896b1a3b | 1492 | randLIB_add_seed(rf_if_read_rnd()); |
kevman | 2:7aab896b1a3b | 1493 | /*Start RF calibration timer*/ |
kevman | 2:7aab896b1a3b | 1494 | rf_calibration_timer_start(RF_CALIBRATION_INTERVAL); |
kevman | 2:7aab896b1a3b | 1495 | |
kevman | 2:7aab896b1a3b | 1496 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1497 | } |
kevman | 2:7aab896b1a3b | 1498 | |
kevman | 2:7aab896b1a3b | 1499 | /** |
kevman | 2:7aab896b1a3b | 1500 | * \brief Function gets called when MAC is setting radio off. |
kevman | 2:7aab896b1a3b | 1501 | * |
kevman | 2:7aab896b1a3b | 1502 | * \param none |
kevman | 2:7aab896b1a3b | 1503 | * |
kevman | 2:7aab896b1a3b | 1504 | * \return none |
kevman | 2:7aab896b1a3b | 1505 | */ |
kevman | 2:7aab896b1a3b | 1506 | static void rf_off(void) |
kevman | 2:7aab896b1a3b | 1507 | { |
kevman | 2:7aab896b1a3b | 1508 | if(rf_flags_check(RFF_ON)) |
kevman | 2:7aab896b1a3b | 1509 | { |
kevman | 2:7aab896b1a3b | 1510 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1511 | rf_cca_abort(); |
kevman | 2:7aab896b1a3b | 1512 | uint16_t while_counter = 0; |
kevman | 2:7aab896b1a3b | 1513 | /*Wait while receiving*/ |
kevman | 2:7aab896b1a3b | 1514 | while(rf_if_read_trx_state() == BUSY_RX_AACK) |
kevman | 2:7aab896b1a3b | 1515 | { |
kevman | 2:7aab896b1a3b | 1516 | while_counter++; |
kevman | 2:7aab896b1a3b | 1517 | if(while_counter == 0xffff) |
kevman | 2:7aab896b1a3b | 1518 | break; |
kevman | 2:7aab896b1a3b | 1519 | } |
kevman | 2:7aab896b1a3b | 1520 | /*RF state change: RX_AACK_ON->PLL_ON->TRX_OFF->SLEEP*/ |
kevman | 2:7aab896b1a3b | 1521 | if(rf_if_read_trx_state() == RX_AACK_ON) |
kevman | 2:7aab896b1a3b | 1522 | { |
kevman | 2:7aab896b1a3b | 1523 | rf_if_change_trx_state(PLL_ON); |
kevman | 2:7aab896b1a3b | 1524 | } |
kevman | 2:7aab896b1a3b | 1525 | rf_if_change_trx_state(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1526 | rf_if_enable_slptr(); |
kevman | 2:7aab896b1a3b | 1527 | |
kevman | 2:7aab896b1a3b | 1528 | /*Disable Antenna Diversity*/ |
kevman | 2:7aab896b1a3b | 1529 | if(rf_use_antenna_diversity) |
kevman | 2:7aab896b1a3b | 1530 | rf_if_disable_ant_div(); |
kevman | 2:7aab896b1a3b | 1531 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1532 | } |
kevman | 2:7aab896b1a3b | 1533 | |
kevman | 2:7aab896b1a3b | 1534 | /*Clears all flags*/ |
kevman | 2:7aab896b1a3b | 1535 | rf_flags_reset(); |
kevman | 2:7aab896b1a3b | 1536 | } |
kevman | 2:7aab896b1a3b | 1537 | |
kevman | 2:7aab896b1a3b | 1538 | /* |
kevman | 2:7aab896b1a3b | 1539 | * \brief Function polls the RF state until it has changed to desired state. |
kevman | 2:7aab896b1a3b | 1540 | * |
kevman | 2:7aab896b1a3b | 1541 | * \param trx_state RF state |
kevman | 2:7aab896b1a3b | 1542 | * |
kevman | 2:7aab896b1a3b | 1543 | * \return none |
kevman | 2:7aab896b1a3b | 1544 | */ |
kevman | 2:7aab896b1a3b | 1545 | static rf_trx_states_t rf_poll_trx_state_change(rf_trx_states_t trx_state) |
kevman | 2:7aab896b1a3b | 1546 | { |
kevman | 2:7aab896b1a3b | 1547 | uint16_t while_counter = 0; |
kevman | 2:7aab896b1a3b | 1548 | |
kevman | 2:7aab896b1a3b | 1549 | if(trx_state == FORCE_PLL_ON) |
kevman | 2:7aab896b1a3b | 1550 | trx_state = PLL_ON; |
kevman | 2:7aab896b1a3b | 1551 | else if(trx_state == FORCE_TRX_OFF) |
kevman | 2:7aab896b1a3b | 1552 | trx_state = TRX_OFF; |
kevman | 2:7aab896b1a3b | 1553 | |
kevman | 2:7aab896b1a3b | 1554 | rf_trx_states_t state_out; |
kevman | 2:7aab896b1a3b | 1555 | while((state_out = rf_if_read_trx_state()) != trx_state) |
kevman | 2:7aab896b1a3b | 1556 | { |
kevman | 2:7aab896b1a3b | 1557 | while_counter++; |
kevman | 2:7aab896b1a3b | 1558 | if(while_counter == 0x1ff) |
kevman | 2:7aab896b1a3b | 1559 | break; |
kevman | 2:7aab896b1a3b | 1560 | } |
kevman | 2:7aab896b1a3b | 1561 | |
kevman | 2:7aab896b1a3b | 1562 | return state_out; |
kevman | 2:7aab896b1a3b | 1563 | } |
kevman | 2:7aab896b1a3b | 1564 | |
kevman | 2:7aab896b1a3b | 1565 | /* |
kevman | 2:7aab896b1a3b | 1566 | * \brief Function polls the RF state until it is no longer transitioning. |
kevman | 2:7aab896b1a3b | 1567 | * |
kevman | 2:7aab896b1a3b | 1568 | * \param trx_state RF state |
kevman | 2:7aab896b1a3b | 1569 | * |
kevman | 2:7aab896b1a3b | 1570 | * \return none |
kevman | 2:7aab896b1a3b | 1571 | */ |
kevman | 2:7aab896b1a3b | 1572 | static rf_trx_states_t rf_poll_for_state(void) |
kevman | 2:7aab896b1a3b | 1573 | { |
kevman | 2:7aab896b1a3b | 1574 | rf_trx_states_t state_out; |
kevman | 2:7aab896b1a3b | 1575 | while((state_out = rf_if_read_trx_state()) == STATE_TRANSITION_IN_PROGRESS) |
kevman | 2:7aab896b1a3b | 1576 | { |
kevman | 2:7aab896b1a3b | 1577 | } |
kevman | 2:7aab896b1a3b | 1578 | |
kevman | 2:7aab896b1a3b | 1579 | return state_out; |
kevman | 2:7aab896b1a3b | 1580 | } |
kevman | 2:7aab896b1a3b | 1581 | |
kevman | 2:7aab896b1a3b | 1582 | /* |
kevman | 2:7aab896b1a3b | 1583 | * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO. |
kevman | 2:7aab896b1a3b | 1584 | * |
kevman | 2:7aab896b1a3b | 1585 | * \param data_ptr Pointer to TX data (excluding FCS) |
kevman | 2:7aab896b1a3b | 1586 | * \param data_length Length of the TX data (excluding FCS) |
kevman | 2:7aab896b1a3b | 1587 | * \param tx_handle Handle to transmission |
kevman | 2:7aab896b1a3b | 1588 | * \return 0 Success |
kevman | 2:7aab896b1a3b | 1589 | * \return -1 Busy |
kevman | 2:7aab896b1a3b | 1590 | */ |
kevman | 2:7aab896b1a3b | 1591 | static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol ) |
kevman | 2:7aab896b1a3b | 1592 | { |
kevman | 2:7aab896b1a3b | 1593 | (void)data_protocol; |
kevman | 2:7aab896b1a3b | 1594 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1595 | /*Check if transmitter is busy*/ |
kevman | 2:7aab896b1a3b | 1596 | rf_trx_states_t trx_state = rf_if_read_trx_state(); |
kevman | 2:7aab896b1a3b | 1597 | if(trx_state == BUSY_RX || trx_state == BUSY_RX_AACK || data_length > RF_MTU - 2) |
kevman | 2:7aab896b1a3b | 1598 | { |
kevman | 2:7aab896b1a3b | 1599 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1600 | /*Return busy*/ |
kevman | 2:7aab896b1a3b | 1601 | return -1; |
kevman | 2:7aab896b1a3b | 1602 | } |
kevman | 2:7aab896b1a3b | 1603 | else |
kevman | 2:7aab896b1a3b | 1604 | { |
kevman | 2:7aab896b1a3b | 1605 | rf_give_up_on_ack(); |
kevman | 2:7aab896b1a3b | 1606 | |
kevman | 2:7aab896b1a3b | 1607 | /*Nanostack has a static TX buffer, which will remain valid until we*/ |
kevman | 2:7aab896b1a3b | 1608 | /*generate a callback, so we just note the pointer for reading later.*/ |
kevman | 2:7aab896b1a3b | 1609 | rf_tx_data = data_ptr; |
kevman | 2:7aab896b1a3b | 1610 | rf_tx_length = data_length; |
kevman | 2:7aab896b1a3b | 1611 | /*Start CCA timeout*/ |
kevman | 2:7aab896b1a3b | 1612 | rf_cca_timer_start(RF_CCA_BASE_BACKOFF + randLIB_get_random_in_range(0, RF_CCA_RANDOM_BACKOFF)); |
kevman | 2:7aab896b1a3b | 1613 | /*Store TX handle*/ |
kevman | 2:7aab896b1a3b | 1614 | mac_tx_handle = tx_handle; |
kevman | 2:7aab896b1a3b | 1615 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1616 | } |
kevman | 2:7aab896b1a3b | 1617 | |
kevman | 2:7aab896b1a3b | 1618 | /*Return success*/ |
kevman | 2:7aab896b1a3b | 1619 | return 0; |
kevman | 2:7aab896b1a3b | 1620 | } |
kevman | 2:7aab896b1a3b | 1621 | |
kevman | 2:7aab896b1a3b | 1622 | /* |
kevman | 2:7aab896b1a3b | 1623 | * \brief Function aborts CCA process. |
kevman | 2:7aab896b1a3b | 1624 | * |
kevman | 2:7aab896b1a3b | 1625 | * \param none |
kevman | 2:7aab896b1a3b | 1626 | * |
kevman | 2:7aab896b1a3b | 1627 | * \return none |
kevman | 2:7aab896b1a3b | 1628 | */ |
kevman | 2:7aab896b1a3b | 1629 | static void rf_cca_abort(void) |
kevman | 2:7aab896b1a3b | 1630 | { |
kevman | 2:7aab896b1a3b | 1631 | rf_cca_timer_stop(); |
kevman | 2:7aab896b1a3b | 1632 | rf_flags_clear(RFF_CCA); |
kevman | 2:7aab896b1a3b | 1633 | } |
kevman | 2:7aab896b1a3b | 1634 | |
kevman | 2:7aab896b1a3b | 1635 | /* |
kevman | 2:7aab896b1a3b | 1636 | * \brief Function starts the transmission of the frame. |
kevman | 2:7aab896b1a3b | 1637 | * |
kevman | 2:7aab896b1a3b | 1638 | * \param none |
kevman | 2:7aab896b1a3b | 1639 | * |
kevman | 2:7aab896b1a3b | 1640 | * \return none |
kevman | 2:7aab896b1a3b | 1641 | */ |
kevman | 2:7aab896b1a3b | 1642 | static bool rf_start_tx() |
kevman | 2:7aab896b1a3b | 1643 | { |
kevman | 2:7aab896b1a3b | 1644 | /* Attempt change to PLL_ON */ |
kevman | 2:7aab896b1a3b | 1645 | rf_if_write_register(TRX_STATE, PLL_ON); |
kevman | 2:7aab896b1a3b | 1646 | |
kevman | 2:7aab896b1a3b | 1647 | // It appears that if radio is busy, rather than ignoring the state change, |
kevman | 2:7aab896b1a3b | 1648 | // the state change happens when it stops being busy - eg |
kevman | 2:7aab896b1a3b | 1649 | // after address match fail or finishing reception. If this happens, we do |
kevman | 2:7aab896b1a3b | 1650 | // not want to transmit - our channel clear check is stale (either someone is |
kevman | 2:7aab896b1a3b | 1651 | // still transmitting, or it's a long time since we checked). So wait for the |
kevman | 2:7aab896b1a3b | 1652 | // PLL_ON change and then go to receive mode without trying to transmit. |
kevman | 2:7aab896b1a3b | 1653 | rf_trx_states_t state = rf_poll_for_state(); |
kevman | 2:7aab896b1a3b | 1654 | int poll_count = 0; |
kevman | 2:7aab896b1a3b | 1655 | while (state != PLL_ON) { |
kevman | 2:7aab896b1a3b | 1656 | /* Change didn't work (yet) - must be busy - assume it will eventually change */ |
kevman | 2:7aab896b1a3b | 1657 | state = rf_poll_for_state(); |
kevman | 2:7aab896b1a3b | 1658 | poll_count++; |
kevman | 2:7aab896b1a3b | 1659 | } |
kevman | 2:7aab896b1a3b | 1660 | |
kevman | 2:7aab896b1a3b | 1661 | rf_flags_clear(RFF_RX); |
kevman | 2:7aab896b1a3b | 1662 | // Check whether we saw any delay in the PLL_ON transition. |
kevman | 2:7aab896b1a3b | 1663 | if (poll_count > 0) { |
kevman | 2:7aab896b1a3b | 1664 | tr_warning("PLL_ON delayed, retry count: %d", poll_count); |
kevman | 2:7aab896b1a3b | 1665 | // let's get back to the receiving state. |
kevman | 2:7aab896b1a3b | 1666 | rf_receive(state); |
kevman | 2:7aab896b1a3b | 1667 | return false; |
kevman | 2:7aab896b1a3b | 1668 | } |
kevman | 2:7aab896b1a3b | 1669 | |
kevman | 2:7aab896b1a3b | 1670 | rf_flags_set(RFF_TX); |
kevman | 2:7aab896b1a3b | 1671 | /*RF state change: SLP_TR pulse triggers PLL_ON->BUSY_TX*/ |
kevman | 2:7aab896b1a3b | 1672 | rf_if_enable_slptr(); |
kevman | 2:7aab896b1a3b | 1673 | /*Chip permits us to write frame buffer while it is transmitting*/ |
kevman | 2:7aab896b1a3b | 1674 | /*As long as first byte of data is in within 176us of TX start, we're good */ |
kevman | 2:7aab896b1a3b | 1675 | rf_if_write_frame_buffer(rf_tx_data, rf_tx_length); |
kevman | 2:7aab896b1a3b | 1676 | rf_if_disable_slptr(); |
kevman | 2:7aab896b1a3b | 1677 | return true; |
kevman | 2:7aab896b1a3b | 1678 | } |
kevman | 2:7aab896b1a3b | 1679 | |
kevman | 2:7aab896b1a3b | 1680 | /* |
kevman | 2:7aab896b1a3b | 1681 | * \brief Function sets the RF in RX state. |
kevman | 2:7aab896b1a3b | 1682 | * |
kevman | 2:7aab896b1a3b | 1683 | * \param none |
kevman | 2:7aab896b1a3b | 1684 | * |
kevman | 2:7aab896b1a3b | 1685 | * \return none |
kevman | 2:7aab896b1a3b | 1686 | */ |
kevman | 2:7aab896b1a3b | 1687 | static void rf_receive(rf_trx_states_t trx_status) |
kevman | 2:7aab896b1a3b | 1688 | { |
kevman | 2:7aab896b1a3b | 1689 | uint16_t while_counter = 0; |
kevman | 2:7aab896b1a3b | 1690 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1691 | { |
kevman | 2:7aab896b1a3b | 1692 | rf_on(); |
kevman | 2:7aab896b1a3b | 1693 | rf_channel_set(rf_phy_channel); |
kevman | 2:7aab896b1a3b | 1694 | trx_status = TRX_OFF; |
kevman | 2:7aab896b1a3b | 1695 | } |
kevman | 2:7aab896b1a3b | 1696 | /*If not yet in RX state set it*/ |
kevman | 2:7aab896b1a3b | 1697 | if(rf_flags_check(RFF_RX) == 0) |
kevman | 2:7aab896b1a3b | 1698 | { |
kevman | 2:7aab896b1a3b | 1699 | /*Wait while receiving data. Just making sure, usually this shouldn't happen. */ |
kevman | 2:7aab896b1a3b | 1700 | while(trx_status == BUSY_RX || trx_status == BUSY_RX_AACK || trx_status == STATE_TRANSITION_IN_PROGRESS) |
kevman | 2:7aab896b1a3b | 1701 | { |
kevman | 2:7aab896b1a3b | 1702 | while_counter++; |
kevman | 2:7aab896b1a3b | 1703 | if(while_counter == 0xffff) |
kevman | 2:7aab896b1a3b | 1704 | { |
kevman | 2:7aab896b1a3b | 1705 | break; |
kevman | 2:7aab896b1a3b | 1706 | } |
kevman | 2:7aab896b1a3b | 1707 | trx_status = rf_if_read_trx_state(); |
kevman | 2:7aab896b1a3b | 1708 | } |
kevman | 2:7aab896b1a3b | 1709 | |
kevman | 2:7aab896b1a3b | 1710 | if((rf_mode == RF_MODE_SNIFFER) || (rf_mode == RF_MODE_ED)) |
kevman | 2:7aab896b1a3b | 1711 | { |
kevman | 2:7aab896b1a3b | 1712 | if (trx_status != RX_ON) { |
kevman | 2:7aab896b1a3b | 1713 | trx_status = rf_if_change_trx_state(RX_ON); |
kevman | 2:7aab896b1a3b | 1714 | } |
kevman | 2:7aab896b1a3b | 1715 | } |
kevman | 2:7aab896b1a3b | 1716 | else |
kevman | 2:7aab896b1a3b | 1717 | { |
kevman | 2:7aab896b1a3b | 1718 | /*ACK is always received in promiscuous mode to bypass address filters*/ |
kevman | 2:7aab896b1a3b | 1719 | if(rf_rx_mode) |
kevman | 2:7aab896b1a3b | 1720 | { |
kevman | 2:7aab896b1a3b | 1721 | rf_rx_mode = 0; |
kevman | 2:7aab896b1a3b | 1722 | rf_if_enable_promiscuous_mode(); |
kevman | 2:7aab896b1a3b | 1723 | } |
kevman | 2:7aab896b1a3b | 1724 | else |
kevman | 2:7aab896b1a3b | 1725 | { |
kevman | 2:7aab896b1a3b | 1726 | rf_if_disable_promiscuous_mode(); |
kevman | 2:7aab896b1a3b | 1727 | } |
kevman | 2:7aab896b1a3b | 1728 | if (trx_status != RX_AACK_ON) { |
kevman | 2:7aab896b1a3b | 1729 | trx_status = rf_if_change_trx_state(RX_AACK_ON); |
kevman | 2:7aab896b1a3b | 1730 | } |
kevman | 2:7aab896b1a3b | 1731 | } |
kevman | 2:7aab896b1a3b | 1732 | /*If calibration timer was unable to calibrate the RF, run calibration now*/ |
kevman | 2:7aab896b1a3b | 1733 | if(!rf_tuned) |
kevman | 2:7aab896b1a3b | 1734 | { |
kevman | 2:7aab896b1a3b | 1735 | /*Start calibration. This can be done in states TRX_OFF, PLL_ON or in any receive state*/ |
kevman | 2:7aab896b1a3b | 1736 | rf_if_calibration(); |
kevman | 2:7aab896b1a3b | 1737 | /*RF is tuned now*/ |
kevman | 2:7aab896b1a3b | 1738 | rf_tuned = 1; |
kevman | 2:7aab896b1a3b | 1739 | } |
kevman | 2:7aab896b1a3b | 1740 | |
kevman | 2:7aab896b1a3b | 1741 | rf_flags_set(RFF_RX); |
kevman | 2:7aab896b1a3b | 1742 | } |
kevman | 2:7aab896b1a3b | 1743 | } |
kevman | 2:7aab896b1a3b | 1744 | |
kevman | 2:7aab896b1a3b | 1745 | /* |
kevman | 2:7aab896b1a3b | 1746 | * \brief Function calibrates the radio. |
kevman | 2:7aab896b1a3b | 1747 | * |
kevman | 2:7aab896b1a3b | 1748 | * \param none |
kevman | 2:7aab896b1a3b | 1749 | * |
kevman | 2:7aab896b1a3b | 1750 | * \return none |
kevman | 2:7aab896b1a3b | 1751 | */ |
kevman | 2:7aab896b1a3b | 1752 | static void rf_calibration_cb(void) |
kevman | 2:7aab896b1a3b | 1753 | { |
kevman | 2:7aab896b1a3b | 1754 | /*clear tuned flag to start tuning in rf_receive*/ |
kevman | 2:7aab896b1a3b | 1755 | rf_tuned = 0; |
kevman | 2:7aab896b1a3b | 1756 | /*If RF is in default receive state, start calibration*/ |
kevman | 2:7aab896b1a3b | 1757 | if(rf_if_read_trx_state() == RX_AACK_ON) |
kevman | 2:7aab896b1a3b | 1758 | { |
kevman | 2:7aab896b1a3b | 1759 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1760 | /*Set RF in PLL_ON state*/ |
kevman | 2:7aab896b1a3b | 1761 | rf_if_change_trx_state(PLL_ON); |
kevman | 2:7aab896b1a3b | 1762 | /*Set RF in TRX_OFF state to start PLL tuning*/ |
kevman | 2:7aab896b1a3b | 1763 | rf_if_change_trx_state(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1764 | /*Set RF in RX_ON state to calibrate*/ |
kevman | 2:7aab896b1a3b | 1765 | rf_trx_states_t trx_status = rf_if_change_trx_state(RX_ON); |
kevman | 2:7aab896b1a3b | 1766 | /*Calibrate FTN*/ |
kevman | 2:7aab896b1a3b | 1767 | rf_if_calibration(); |
kevman | 2:7aab896b1a3b | 1768 | /*RF is tuned now*/ |
kevman | 2:7aab896b1a3b | 1769 | rf_tuned = 1; |
kevman | 2:7aab896b1a3b | 1770 | /*Back to default receive state*/ |
kevman | 2:7aab896b1a3b | 1771 | rf_flags_clear(RFF_RX); |
kevman | 2:7aab896b1a3b | 1772 | rf_receive(trx_status); |
kevman | 2:7aab896b1a3b | 1773 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1774 | } |
kevman | 2:7aab896b1a3b | 1775 | } |
kevman | 2:7aab896b1a3b | 1776 | |
kevman | 2:7aab896b1a3b | 1777 | /* |
kevman | 2:7aab896b1a3b | 1778 | * \brief Function sets RF_ON flag when radio is powered. |
kevman | 2:7aab896b1a3b | 1779 | * |
kevman | 2:7aab896b1a3b | 1780 | * \param none |
kevman | 2:7aab896b1a3b | 1781 | * |
kevman | 2:7aab896b1a3b | 1782 | * \return none |
kevman | 2:7aab896b1a3b | 1783 | */ |
kevman | 2:7aab896b1a3b | 1784 | static void rf_on(void) |
kevman | 2:7aab896b1a3b | 1785 | { |
kevman | 2:7aab896b1a3b | 1786 | /*Set RFF_ON flag*/ |
kevman | 2:7aab896b1a3b | 1787 | if(rf_flags_check(RFF_ON) == 0) |
kevman | 2:7aab896b1a3b | 1788 | { |
kevman | 2:7aab896b1a3b | 1789 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1790 | rf_flags_set(RFF_ON); |
kevman | 2:7aab896b1a3b | 1791 | /*Enable Antenna diversity*/ |
kevman | 2:7aab896b1a3b | 1792 | if(rf_use_antenna_diversity) |
kevman | 2:7aab896b1a3b | 1793 | /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/ |
kevman | 2:7aab896b1a3b | 1794 | rf_if_enable_ant_div(); |
kevman | 2:7aab896b1a3b | 1795 | |
kevman | 2:7aab896b1a3b | 1796 | /*Wake up from sleep state*/ |
kevman | 2:7aab896b1a3b | 1797 | rf_if_disable_slptr(); |
kevman | 2:7aab896b1a3b | 1798 | rf_poll_trx_state_change(TRX_OFF); |
kevman | 2:7aab896b1a3b | 1799 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 1800 | } |
kevman | 2:7aab896b1a3b | 1801 | } |
kevman | 2:7aab896b1a3b | 1802 | |
kevman | 2:7aab896b1a3b | 1803 | /* |
kevman | 2:7aab896b1a3b | 1804 | * \brief Abandon waiting for an ack frame |
kevman | 2:7aab896b1a3b | 1805 | |
kevman | 2:7aab896b1a3b | 1806 | * \return none |
kevman | 2:7aab896b1a3b | 1807 | */ |
kevman | 2:7aab896b1a3b | 1808 | static void rf_give_up_on_ack(void) |
kevman | 2:7aab896b1a3b | 1809 | { |
kevman | 2:7aab896b1a3b | 1810 | if (expected_ack_sequence == -1) { |
kevman | 2:7aab896b1a3b | 1811 | return; |
kevman | 2:7aab896b1a3b | 1812 | } |
kevman | 2:7aab896b1a3b | 1813 | |
kevman | 2:7aab896b1a3b | 1814 | rf_if_disable_promiscuous_mode(); |
kevman | 2:7aab896b1a3b | 1815 | rf_if_ack_wait_timer_stop(); |
kevman | 2:7aab896b1a3b | 1816 | expected_ack_sequence = -1; |
kevman | 2:7aab896b1a3b | 1817 | |
kevman | 2:7aab896b1a3b | 1818 | if(device_driver.phy_tx_done_cb){ |
kevman | 2:7aab896b1a3b | 1819 | device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 0, 0); |
kevman | 2:7aab896b1a3b | 1820 | } |
kevman | 2:7aab896b1a3b | 1821 | } |
kevman | 2:7aab896b1a3b | 1822 | |
kevman | 2:7aab896b1a3b | 1823 | /* |
kevman | 2:7aab896b1a3b | 1824 | * \brief Function handles the received ACK frame. |
kevman | 2:7aab896b1a3b | 1825 | * |
kevman | 2:7aab896b1a3b | 1826 | * \param seq_number Sequence number of received ACK |
kevman | 2:7aab896b1a3b | 1827 | * \param data_pending Pending bit state in received ACK |
kevman | 2:7aab896b1a3b | 1828 | * |
kevman | 2:7aab896b1a3b | 1829 | * \return none |
kevman | 2:7aab896b1a3b | 1830 | */ |
kevman | 2:7aab896b1a3b | 1831 | static void rf_handle_ack(uint8_t seq_number, uint8_t data_pending) |
kevman | 2:7aab896b1a3b | 1832 | { |
kevman | 2:7aab896b1a3b | 1833 | phy_link_tx_status_e phy_status; |
kevman | 2:7aab896b1a3b | 1834 | /*Received ACK sequence must be equal with transmitted packet sequence*/ |
kevman | 2:7aab896b1a3b | 1835 | if(expected_ack_sequence == seq_number) |
kevman | 2:7aab896b1a3b | 1836 | { |
kevman | 2:7aab896b1a3b | 1837 | rf_if_disable_promiscuous_mode(); |
kevman | 2:7aab896b1a3b | 1838 | rf_if_ack_wait_timer_stop(); |
kevman | 2:7aab896b1a3b | 1839 | expected_ack_sequence = -1; |
kevman | 2:7aab896b1a3b | 1840 | |
kevman | 2:7aab896b1a3b | 1841 | /*When data pending bit in ACK frame is set, inform NET library*/ |
kevman | 2:7aab896b1a3b | 1842 | if(data_pending) |
kevman | 2:7aab896b1a3b | 1843 | phy_status = PHY_LINK_TX_DONE_PENDING; |
kevman | 2:7aab896b1a3b | 1844 | else |
kevman | 2:7aab896b1a3b | 1845 | phy_status = PHY_LINK_TX_DONE; |
kevman | 2:7aab896b1a3b | 1846 | /*Call PHY TX Done API*/ |
kevman | 2:7aab896b1a3b | 1847 | if(device_driver.phy_tx_done_cb){ |
kevman | 2:7aab896b1a3b | 1848 | device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle,phy_status, 0, 0); |
kevman | 2:7aab896b1a3b | 1849 | } |
kevman | 2:7aab896b1a3b | 1850 | } else { |
kevman | 2:7aab896b1a3b | 1851 | rf_give_up_on_ack(); |
kevman | 2:7aab896b1a3b | 1852 | } |
kevman | 2:7aab896b1a3b | 1853 | } |
kevman | 2:7aab896b1a3b | 1854 | |
kevman | 2:7aab896b1a3b | 1855 | /* |
kevman | 2:7aab896b1a3b | 1856 | * \brief Function is a call back for RX end interrupt. |
kevman | 2:7aab896b1a3b | 1857 | * |
kevman | 2:7aab896b1a3b | 1858 | * \param none |
kevman | 2:7aab896b1a3b | 1859 | * |
kevman | 2:7aab896b1a3b | 1860 | * \return none |
kevman | 2:7aab896b1a3b | 1861 | */ |
kevman | 2:7aab896b1a3b | 1862 | static void rf_handle_rx_end(rf_trx_states_t trx_status) |
kevman | 2:7aab896b1a3b | 1863 | { |
kevman | 2:7aab896b1a3b | 1864 | /*Frame received interrupt*/ |
kevman | 2:7aab896b1a3b | 1865 | if(!rf_flags_check(RFF_RX)) { |
kevman | 2:7aab896b1a3b | 1866 | return; |
kevman | 2:7aab896b1a3b | 1867 | } |
kevman | 2:7aab896b1a3b | 1868 | |
kevman | 2:7aab896b1a3b | 1869 | static uint8_t rf_buffer[RF_MTU]; |
kevman | 2:7aab896b1a3b | 1870 | uint8_t rf_lqi, rf_ed; |
kevman | 2:7aab896b1a3b | 1871 | int8_t rf_rssi; |
kevman | 2:7aab896b1a3b | 1872 | bool crc_good; |
kevman | 2:7aab896b1a3b | 1873 | |
kevman | 2:7aab896b1a3b | 1874 | /*Read received packet*/ |
kevman | 2:7aab896b1a3b | 1875 | uint8_t len = rf_if_read_packet(rf_buffer, &rf_lqi, &rf_ed, &crc_good); |
kevman | 2:7aab896b1a3b | 1876 | |
kevman | 2:7aab896b1a3b | 1877 | if (len < 5 || !crc_good) { |
kevman | 2:7aab896b1a3b | 1878 | rf_give_up_on_ack(); |
kevman | 2:7aab896b1a3b | 1879 | return; |
kevman | 2:7aab896b1a3b | 1880 | } |
kevman | 2:7aab896b1a3b | 1881 | |
kevman | 2:7aab896b1a3b | 1882 | /* Convert raw ED to dBm value (chip-dependent) */ |
kevman | 2:7aab896b1a3b | 1883 | rf_rssi = rf_if_scale_rssi(rf_ed); |
kevman | 2:7aab896b1a3b | 1884 | |
kevman | 2:7aab896b1a3b | 1885 | /* Create a virtual LQI using received RSSI, forgetting actual HW LQI */ |
kevman | 2:7aab896b1a3b | 1886 | /* (should be done through PHY_EXTENSION_CONVERT_SIGNAL_INFO) */ |
kevman | 2:7aab896b1a3b | 1887 | rf_lqi = rf_scale_lqi(rf_rssi); |
kevman | 2:7aab896b1a3b | 1888 | |
kevman | 2:7aab896b1a3b | 1889 | /*Handle received ACK*/ |
kevman | 2:7aab896b1a3b | 1890 | if((rf_buffer[0] & 0x07) == 0x02 && rf_mode != RF_MODE_SNIFFER) |
kevman | 2:7aab896b1a3b | 1891 | { |
kevman | 2:7aab896b1a3b | 1892 | /*Check if data is pending*/ |
kevman | 2:7aab896b1a3b | 1893 | bool pending = (rf_buffer[0] & 0x10); |
kevman | 2:7aab896b1a3b | 1894 | |
kevman | 2:7aab896b1a3b | 1895 | /*Send sequence number in ACK handler*/ |
kevman | 2:7aab896b1a3b | 1896 | rf_handle_ack(rf_buffer[2], pending); |
kevman | 2:7aab896b1a3b | 1897 | } else { |
kevman | 2:7aab896b1a3b | 1898 | rf_give_up_on_ack(); |
kevman | 2:7aab896b1a3b | 1899 | if( device_driver.phy_rx_cb ){ |
kevman | 2:7aab896b1a3b | 1900 | device_driver.phy_rx_cb(rf_buffer, len - 2, rf_lqi, rf_rssi, rf_radio_driver_id); |
kevman | 2:7aab896b1a3b | 1901 | } |
kevman | 2:7aab896b1a3b | 1902 | } |
kevman | 2:7aab896b1a3b | 1903 | } |
kevman | 2:7aab896b1a3b | 1904 | |
kevman | 2:7aab896b1a3b | 1905 | /* |
kevman | 2:7aab896b1a3b | 1906 | * \brief Function is called when MAC is shutting down the radio. |
kevman | 2:7aab896b1a3b | 1907 | * |
kevman | 2:7aab896b1a3b | 1908 | * \param none |
kevman | 2:7aab896b1a3b | 1909 | * |
kevman | 2:7aab896b1a3b | 1910 | * \return none |
kevman | 2:7aab896b1a3b | 1911 | */ |
kevman | 2:7aab896b1a3b | 1912 | static void rf_shutdown(void) |
kevman | 2:7aab896b1a3b | 1913 | { |
kevman | 2:7aab896b1a3b | 1914 | /*Call RF OFF*/ |
kevman | 2:7aab896b1a3b | 1915 | rf_off(); |
kevman | 2:7aab896b1a3b | 1916 | } |
kevman | 2:7aab896b1a3b | 1917 | |
kevman | 2:7aab896b1a3b | 1918 | /* |
kevman | 2:7aab896b1a3b | 1919 | * \brief Function is a call back for TX end interrupt. |
kevman | 2:7aab896b1a3b | 1920 | * |
kevman | 2:7aab896b1a3b | 1921 | * \param none |
kevman | 2:7aab896b1a3b | 1922 | * |
kevman | 2:7aab896b1a3b | 1923 | * \return none |
kevman | 2:7aab896b1a3b | 1924 | */ |
kevman | 2:7aab896b1a3b | 1925 | static void rf_handle_tx_end(rf_trx_states_t trx_status) |
kevman | 2:7aab896b1a3b | 1926 | { |
kevman | 2:7aab896b1a3b | 1927 | rf_rx_mode = 0; |
kevman | 2:7aab896b1a3b | 1928 | /*If ACK is needed for this transmission*/ |
kevman | 2:7aab896b1a3b | 1929 | if((rf_tx_data[0] & 0x20) && rf_flags_check(RFF_TX)) |
kevman | 2:7aab896b1a3b | 1930 | { |
kevman | 2:7aab896b1a3b | 1931 | expected_ack_sequence = rf_tx_data[2]; |
kevman | 2:7aab896b1a3b | 1932 | rf_ack_wait_timer_start(rf_ack_wait_duration); |
kevman | 2:7aab896b1a3b | 1933 | rf_rx_mode = 1; |
kevman | 2:7aab896b1a3b | 1934 | } |
kevman | 2:7aab896b1a3b | 1935 | rf_flags_clear(RFF_TX); |
kevman | 2:7aab896b1a3b | 1936 | /*Start receiver*/ |
kevman | 2:7aab896b1a3b | 1937 | rf_receive(trx_status); |
kevman | 2:7aab896b1a3b | 1938 | |
kevman | 2:7aab896b1a3b | 1939 | /*Call PHY TX Done API*/ |
kevman | 2:7aab896b1a3b | 1940 | if(device_driver.phy_tx_done_cb){ |
kevman | 2:7aab896b1a3b | 1941 | device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0); |
kevman | 2:7aab896b1a3b | 1942 | } |
kevman | 2:7aab896b1a3b | 1943 | } |
kevman | 2:7aab896b1a3b | 1944 | |
kevman | 2:7aab896b1a3b | 1945 | /* |
kevman | 2:7aab896b1a3b | 1946 | * \brief Function is a call back for CCA ED done interrupt. |
kevman | 2:7aab896b1a3b | 1947 | * |
kevman | 2:7aab896b1a3b | 1948 | * \param none |
kevman | 2:7aab896b1a3b | 1949 | * |
kevman | 2:7aab896b1a3b | 1950 | * \return none |
kevman | 2:7aab896b1a3b | 1951 | */ |
kevman | 2:7aab896b1a3b | 1952 | static void rf_handle_cca_ed_done(uint8_t full_trx_status) |
kevman | 2:7aab896b1a3b | 1953 | { |
kevman | 2:7aab896b1a3b | 1954 | if (!rf_flags_check(RFF_CCA)) { |
kevman | 2:7aab896b1a3b | 1955 | return; |
kevman | 2:7aab896b1a3b | 1956 | } |
kevman | 2:7aab896b1a3b | 1957 | rf_flags_clear(RFF_CCA); |
kevman | 2:7aab896b1a3b | 1958 | |
kevman | 2:7aab896b1a3b | 1959 | bool success = false; |
kevman | 2:7aab896b1a3b | 1960 | |
kevman | 2:7aab896b1a3b | 1961 | /*Check the result of CCA process*/ |
kevman | 2:7aab896b1a3b | 1962 | if((full_trx_status & CCA_STATUS) && rf_if_trx_status_from_full(full_trx_status) == RX_AACK_ON) |
kevman | 2:7aab896b1a3b | 1963 | { |
kevman | 2:7aab896b1a3b | 1964 | success = rf_start_tx(); |
kevman | 2:7aab896b1a3b | 1965 | } |
kevman | 2:7aab896b1a3b | 1966 | |
kevman | 2:7aab896b1a3b | 1967 | if (!success) |
kevman | 2:7aab896b1a3b | 1968 | { |
kevman | 2:7aab896b1a3b | 1969 | /*Send CCA fail notification*/ |
kevman | 2:7aab896b1a3b | 1970 | if(device_driver.phy_tx_done_cb){ |
kevman | 2:7aab896b1a3b | 1971 | device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); |
kevman | 2:7aab896b1a3b | 1972 | } |
kevman | 2:7aab896b1a3b | 1973 | } |
kevman | 2:7aab896b1a3b | 1974 | } |
kevman | 2:7aab896b1a3b | 1975 | |
kevman | 2:7aab896b1a3b | 1976 | /* |
kevman | 2:7aab896b1a3b | 1977 | * \brief Function gives the control of RF states to MAC. |
kevman | 2:7aab896b1a3b | 1978 | * |
kevman | 2:7aab896b1a3b | 1979 | * \param new_state RF state |
kevman | 2:7aab896b1a3b | 1980 | * \param rf_channel RF channel |
kevman | 2:7aab896b1a3b | 1981 | * |
kevman | 2:7aab896b1a3b | 1982 | * \return 0 Success |
kevman | 2:7aab896b1a3b | 1983 | */ |
kevman | 2:7aab896b1a3b | 1984 | static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel) |
kevman | 2:7aab896b1a3b | 1985 | { |
kevman | 2:7aab896b1a3b | 1986 | int8_t ret_val = 0; |
kevman | 2:7aab896b1a3b | 1987 | switch (new_state) |
kevman | 2:7aab896b1a3b | 1988 | { |
kevman | 2:7aab896b1a3b | 1989 | /*Reset PHY driver and set to idle*/ |
kevman | 2:7aab896b1a3b | 1990 | case PHY_INTERFACE_RESET: |
kevman | 2:7aab896b1a3b | 1991 | break; |
kevman | 2:7aab896b1a3b | 1992 | /*Disable PHY Interface driver*/ |
kevman | 2:7aab896b1a3b | 1993 | case PHY_INTERFACE_DOWN: |
kevman | 2:7aab896b1a3b | 1994 | rf_shutdown(); |
kevman | 2:7aab896b1a3b | 1995 | break; |
kevman | 2:7aab896b1a3b | 1996 | /*Enable PHY Interface driver*/ |
kevman | 2:7aab896b1a3b | 1997 | case PHY_INTERFACE_UP: |
kevman | 2:7aab896b1a3b | 1998 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 1999 | rf_mode = RF_MODE_NORMAL; |
kevman | 2:7aab896b1a3b | 2000 | rf_channel_set(rf_channel); |
kevman | 2:7aab896b1a3b | 2001 | rf_receive(); |
kevman | 2:7aab896b1a3b | 2002 | rf_if_enable_irq(); |
kevman | 2:7aab896b1a3b | 2003 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2004 | break; |
kevman | 2:7aab896b1a3b | 2005 | /*Enable wireless interface ED scan mode*/ |
kevman | 2:7aab896b1a3b | 2006 | case PHY_INTERFACE_RX_ENERGY_STATE: |
kevman | 2:7aab896b1a3b | 2007 | rf_mode = RF_MODE_ED; |
kevman | 2:7aab896b1a3b | 2008 | rf_channel_set(rf_channel); |
kevman | 2:7aab896b1a3b | 2009 | rf_receive(); |
kevman | 2:7aab896b1a3b | 2010 | rf_if_disable_irq(); |
kevman | 2:7aab896b1a3b | 2011 | // Read status to clear pending flags. |
kevman | 2:7aab896b1a3b | 2012 | rf_if_read_register(IRQ_STATUS); |
kevman | 2:7aab896b1a3b | 2013 | // ED can be initiated by writing arbitrary value to PHY_ED_LEVEL |
kevman | 2:7aab896b1a3b | 2014 | rf_if_write_register(PHY_ED_LEVEL, 0xff); |
kevman | 2:7aab896b1a3b | 2015 | break; |
kevman | 2:7aab896b1a3b | 2016 | case PHY_INTERFACE_SNIFFER_STATE: /**< Enable Sniffer state */ |
kevman | 2:7aab896b1a3b | 2017 | rf_mode = RF_MODE_SNIFFER; |
kevman | 2:7aab896b1a3b | 2018 | rf_channel_set(rf_channel); |
kevman | 2:7aab896b1a3b | 2019 | rf_flags_clear(RFF_RX); |
kevman | 2:7aab896b1a3b | 2020 | rf_receive(); |
kevman | 2:7aab896b1a3b | 2021 | rf_if_enable_irq(); |
kevman | 2:7aab896b1a3b | 2022 | break; |
kevman | 2:7aab896b1a3b | 2023 | } |
kevman | 2:7aab896b1a3b | 2024 | return ret_val; |
kevman | 2:7aab896b1a3b | 2025 | } |
kevman | 2:7aab896b1a3b | 2026 | |
kevman | 2:7aab896b1a3b | 2027 | /* |
kevman | 2:7aab896b1a3b | 2028 | * \brief Function controls the ACK pending, channel setting and energy detection. |
kevman | 2:7aab896b1a3b | 2029 | * |
kevman | 2:7aab896b1a3b | 2030 | * \param extension_type Type of control |
kevman | 2:7aab896b1a3b | 2031 | * \param data_ptr Data from NET library |
kevman | 2:7aab896b1a3b | 2032 | * |
kevman | 2:7aab896b1a3b | 2033 | * \return 0 Success |
kevman | 2:7aab896b1a3b | 2034 | */ |
kevman | 2:7aab896b1a3b | 2035 | static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr) |
kevman | 2:7aab896b1a3b | 2036 | { |
kevman | 2:7aab896b1a3b | 2037 | switch (extension_type) |
kevman | 2:7aab896b1a3b | 2038 | { |
kevman | 2:7aab896b1a3b | 2039 | /*Control MAC pending bit for Indirect data transmission*/ |
kevman | 2:7aab896b1a3b | 2040 | case PHY_EXTENSION_CTRL_PENDING_BIT: |
kevman | 2:7aab896b1a3b | 2041 | if(*data_ptr) |
kevman | 2:7aab896b1a3b | 2042 | { |
kevman | 2:7aab896b1a3b | 2043 | rf_if_ack_pending_ctrl(1); |
kevman | 2:7aab896b1a3b | 2044 | } |
kevman | 2:7aab896b1a3b | 2045 | else |
kevman | 2:7aab896b1a3b | 2046 | { |
kevman | 2:7aab896b1a3b | 2047 | rf_if_ack_pending_ctrl(0); |
kevman | 2:7aab896b1a3b | 2048 | } |
kevman | 2:7aab896b1a3b | 2049 | break; |
kevman | 2:7aab896b1a3b | 2050 | /*Return frame pending status*/ |
kevman | 2:7aab896b1a3b | 2051 | case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS: |
kevman | 2:7aab896b1a3b | 2052 | *data_ptr = rf_if_last_acked_pending(); |
kevman | 2:7aab896b1a3b | 2053 | break; |
kevman | 2:7aab896b1a3b | 2054 | /*Set channel*/ |
kevman | 2:7aab896b1a3b | 2055 | case PHY_EXTENSION_SET_CHANNEL: |
kevman | 2:7aab896b1a3b | 2056 | break; |
kevman | 2:7aab896b1a3b | 2057 | /*Read energy on the channel*/ |
kevman | 2:7aab896b1a3b | 2058 | case PHY_EXTENSION_READ_CHANNEL_ENERGY: |
kevman | 2:7aab896b1a3b | 2059 | // End of the ED measurement is indicated by CCA_ED_DONE |
kevman | 2:7aab896b1a3b | 2060 | while (!(rf_if_read_register(IRQ_STATUS) & CCA_ED_DONE)); |
kevman | 2:7aab896b1a3b | 2061 | // RF input power: RSSI base level + 1[db] * PHY_ED_LEVEL |
kevman | 2:7aab896b1a3b | 2062 | *data_ptr = rf_sensitivity + rf_if_read_register(PHY_ED_LEVEL); |
kevman | 2:7aab896b1a3b | 2063 | // Read status to clear pending flags. |
kevman | 2:7aab896b1a3b | 2064 | rf_if_read_register(IRQ_STATUS); |
kevman | 2:7aab896b1a3b | 2065 | // Next ED measurement is started, next PHY_EXTENSION_READ_CHANNEL_ENERGY call will return the result. |
kevman | 2:7aab896b1a3b | 2066 | rf_if_write_register(PHY_ED_LEVEL, 0xff); |
kevman | 2:7aab896b1a3b | 2067 | break; |
kevman | 2:7aab896b1a3b | 2068 | /*Read status of the link*/ |
kevman | 2:7aab896b1a3b | 2069 | case PHY_EXTENSION_READ_LINK_STATUS: |
kevman | 2:7aab896b1a3b | 2070 | break; |
kevman | 2:7aab896b1a3b | 2071 | default: |
kevman | 2:7aab896b1a3b | 2072 | break; |
kevman | 2:7aab896b1a3b | 2073 | } |
kevman | 2:7aab896b1a3b | 2074 | return 0; |
kevman | 2:7aab896b1a3b | 2075 | } |
kevman | 2:7aab896b1a3b | 2076 | |
kevman | 2:7aab896b1a3b | 2077 | /* |
kevman | 2:7aab896b1a3b | 2078 | * \brief Function sets the addresses to RF address filters. |
kevman | 2:7aab896b1a3b | 2079 | * |
kevman | 2:7aab896b1a3b | 2080 | * \param address_type Type of address |
kevman | 2:7aab896b1a3b | 2081 | * \param address_ptr Pointer to given address |
kevman | 2:7aab896b1a3b | 2082 | * |
kevman | 2:7aab896b1a3b | 2083 | * \return 0 Success |
kevman | 2:7aab896b1a3b | 2084 | */ |
kevman | 2:7aab896b1a3b | 2085 | static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr) |
kevman | 2:7aab896b1a3b | 2086 | { |
kevman | 2:7aab896b1a3b | 2087 | int8_t ret_val = 0; |
kevman | 2:7aab896b1a3b | 2088 | switch (address_type) |
kevman | 2:7aab896b1a3b | 2089 | { |
kevman | 2:7aab896b1a3b | 2090 | /*Set 48-bit address*/ |
kevman | 2:7aab896b1a3b | 2091 | case PHY_MAC_48BIT: |
kevman | 2:7aab896b1a3b | 2092 | break; |
kevman | 2:7aab896b1a3b | 2093 | /*Set 64-bit address*/ |
kevman | 2:7aab896b1a3b | 2094 | case PHY_MAC_64BIT: |
kevman | 2:7aab896b1a3b | 2095 | rf_set_address(address_ptr); |
kevman | 2:7aab896b1a3b | 2096 | break; |
kevman | 2:7aab896b1a3b | 2097 | /*Set 16-bit address*/ |
kevman | 2:7aab896b1a3b | 2098 | case PHY_MAC_16BIT: |
kevman | 2:7aab896b1a3b | 2099 | rf_set_short_adr(address_ptr); |
kevman | 2:7aab896b1a3b | 2100 | break; |
kevman | 2:7aab896b1a3b | 2101 | /*Set PAN Id*/ |
kevman | 2:7aab896b1a3b | 2102 | case PHY_MAC_PANID: |
kevman | 2:7aab896b1a3b | 2103 | rf_set_pan_id(address_ptr); |
kevman | 2:7aab896b1a3b | 2104 | break; |
kevman | 2:7aab896b1a3b | 2105 | } |
kevman | 2:7aab896b1a3b | 2106 | return ret_val; |
kevman | 2:7aab896b1a3b | 2107 | } |
kevman | 2:7aab896b1a3b | 2108 | |
kevman | 2:7aab896b1a3b | 2109 | /* |
kevman | 2:7aab896b1a3b | 2110 | * \brief Function initialises the ACK wait time and returns the used PHY mode. |
kevman | 2:7aab896b1a3b | 2111 | * |
kevman | 2:7aab896b1a3b | 2112 | * \param none |
kevman | 2:7aab896b1a3b | 2113 | * |
kevman | 2:7aab896b1a3b | 2114 | * \return tmp Used PHY mode |
kevman | 2:7aab896b1a3b | 2115 | */ |
kevman | 2:7aab896b1a3b | 2116 | static void rf_init_phy_mode(void) |
kevman | 2:7aab896b1a3b | 2117 | { |
kevman | 2:7aab896b1a3b | 2118 | uint8_t tmp = 0; |
kevman | 2:7aab896b1a3b | 2119 | uint8_t part = rf_if_read_part_num(); |
kevman | 2:7aab896b1a3b | 2120 | /*Read used PHY Mode*/ |
kevman | 2:7aab896b1a3b | 2121 | tmp = rf_if_read_register(TRX_CTRL_2); |
kevman | 2:7aab896b1a3b | 2122 | /*Set ACK wait time for used data rate*/ |
kevman | 2:7aab896b1a3b | 2123 | if(part == PART_AT86RF212) |
kevman | 2:7aab896b1a3b | 2124 | { |
kevman | 2:7aab896b1a3b | 2125 | if((tmp & 0x1f) == 0x00) |
kevman | 2:7aab896b1a3b | 2126 | { |
kevman | 2:7aab896b1a3b | 2127 | rf_sensitivity = -110; |
kevman | 2:7aab896b1a3b | 2128 | rf_ack_wait_duration = 938; |
kevman | 2:7aab896b1a3b | 2129 | tmp = BPSK_20; |
kevman | 2:7aab896b1a3b | 2130 | } |
kevman | 2:7aab896b1a3b | 2131 | else if((tmp & 0x1f) == 0x04) |
kevman | 2:7aab896b1a3b | 2132 | { |
kevman | 2:7aab896b1a3b | 2133 | rf_sensitivity = -108; |
kevman | 2:7aab896b1a3b | 2134 | rf_ack_wait_duration = 469; |
kevman | 2:7aab896b1a3b | 2135 | tmp = BPSK_40; |
kevman | 2:7aab896b1a3b | 2136 | } |
kevman | 2:7aab896b1a3b | 2137 | else if((tmp & 0x1f) == 0x14) |
kevman | 2:7aab896b1a3b | 2138 | { |
kevman | 2:7aab896b1a3b | 2139 | rf_sensitivity = -108; |
kevman | 2:7aab896b1a3b | 2140 | rf_ack_wait_duration = 469; |
kevman | 2:7aab896b1a3b | 2141 | tmp = BPSK_40_ALT; |
kevman | 2:7aab896b1a3b | 2142 | } |
kevman | 2:7aab896b1a3b | 2143 | else if((tmp & 0x1f) == 0x08) |
kevman | 2:7aab896b1a3b | 2144 | { |
kevman | 2:7aab896b1a3b | 2145 | rf_sensitivity = -101; |
kevman | 2:7aab896b1a3b | 2146 | rf_ack_wait_duration = 50; |
kevman | 2:7aab896b1a3b | 2147 | tmp = OQPSK_SIN_RC_100; |
kevman | 2:7aab896b1a3b | 2148 | } |
kevman | 2:7aab896b1a3b | 2149 | else if((tmp & 0x1f) == 0x09) |
kevman | 2:7aab896b1a3b | 2150 | { |
kevman | 2:7aab896b1a3b | 2151 | rf_sensitivity = -99; |
kevman | 2:7aab896b1a3b | 2152 | rf_ack_wait_duration = 30; |
kevman | 2:7aab896b1a3b | 2153 | tmp = OQPSK_SIN_RC_200; |
kevman | 2:7aab896b1a3b | 2154 | } |
kevman | 2:7aab896b1a3b | 2155 | else if((tmp & 0x1f) == 0x18) |
kevman | 2:7aab896b1a3b | 2156 | { |
kevman | 2:7aab896b1a3b | 2157 | rf_sensitivity = -102; |
kevman | 2:7aab896b1a3b | 2158 | rf_ack_wait_duration = 50; |
kevman | 2:7aab896b1a3b | 2159 | tmp = OQPSK_RC_100; |
kevman | 2:7aab896b1a3b | 2160 | } |
kevman | 2:7aab896b1a3b | 2161 | else if((tmp & 0x1f) == 0x19) |
kevman | 2:7aab896b1a3b | 2162 | { |
kevman | 2:7aab896b1a3b | 2163 | rf_sensitivity = -100; |
kevman | 2:7aab896b1a3b | 2164 | rf_ack_wait_duration = 30; |
kevman | 2:7aab896b1a3b | 2165 | tmp = OQPSK_RC_200; |
kevman | 2:7aab896b1a3b | 2166 | } |
kevman | 2:7aab896b1a3b | 2167 | else if((tmp & 0x1f) == 0x0c) |
kevman | 2:7aab896b1a3b | 2168 | { |
kevman | 2:7aab896b1a3b | 2169 | rf_sensitivity = -100; |
kevman | 2:7aab896b1a3b | 2170 | rf_ack_wait_duration = 20; |
kevman | 2:7aab896b1a3b | 2171 | tmp = OQPSK_SIN_250; |
kevman | 2:7aab896b1a3b | 2172 | } |
kevman | 2:7aab896b1a3b | 2173 | else if((tmp & 0x1f) == 0x0d) |
kevman | 2:7aab896b1a3b | 2174 | { |
kevman | 2:7aab896b1a3b | 2175 | rf_sensitivity = -98; |
kevman | 2:7aab896b1a3b | 2176 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2177 | tmp = OQPSK_SIN_500; |
kevman | 2:7aab896b1a3b | 2178 | } |
kevman | 2:7aab896b1a3b | 2179 | else if((tmp & 0x1f) == 0x0f) |
kevman | 2:7aab896b1a3b | 2180 | { |
kevman | 2:7aab896b1a3b | 2181 | rf_sensitivity = -98; |
kevman | 2:7aab896b1a3b | 2182 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2183 | tmp = OQPSK_SIN_500_ALT; |
kevman | 2:7aab896b1a3b | 2184 | } |
kevman | 2:7aab896b1a3b | 2185 | else if((tmp & 0x1f) == 0x1c) |
kevman | 2:7aab896b1a3b | 2186 | { |
kevman | 2:7aab896b1a3b | 2187 | rf_sensitivity = -101; |
kevman | 2:7aab896b1a3b | 2188 | rf_ack_wait_duration = 20; |
kevman | 2:7aab896b1a3b | 2189 | tmp = OQPSK_RC_250; |
kevman | 2:7aab896b1a3b | 2190 | } |
kevman | 2:7aab896b1a3b | 2191 | else if((tmp & 0x1f) == 0x1d) |
kevman | 2:7aab896b1a3b | 2192 | { |
kevman | 2:7aab896b1a3b | 2193 | rf_sensitivity = -99; |
kevman | 2:7aab896b1a3b | 2194 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2195 | tmp = OQPSK_RC_500; |
kevman | 2:7aab896b1a3b | 2196 | } |
kevman | 2:7aab896b1a3b | 2197 | else if((tmp & 0x1f) == 0x1f) |
kevman | 2:7aab896b1a3b | 2198 | { |
kevman | 2:7aab896b1a3b | 2199 | rf_sensitivity = -99; |
kevman | 2:7aab896b1a3b | 2200 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2201 | tmp = OQPSK_RC_500_ALT; |
kevman | 2:7aab896b1a3b | 2202 | } |
kevman | 2:7aab896b1a3b | 2203 | else if((tmp & 0x3f) == 0x2A) |
kevman | 2:7aab896b1a3b | 2204 | { |
kevman | 2:7aab896b1a3b | 2205 | rf_sensitivity = -91; |
kevman | 2:7aab896b1a3b | 2206 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2207 | tmp = OQPSK_SIN_RC_400_SCR_ON; |
kevman | 2:7aab896b1a3b | 2208 | } |
kevman | 2:7aab896b1a3b | 2209 | else if((tmp & 0x3f) == 0x0A) |
kevman | 2:7aab896b1a3b | 2210 | { |
kevman | 2:7aab896b1a3b | 2211 | rf_sensitivity = -91; |
kevman | 2:7aab896b1a3b | 2212 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2213 | tmp = OQPSK_SIN_RC_400_SCR_OFF; |
kevman | 2:7aab896b1a3b | 2214 | } |
kevman | 2:7aab896b1a3b | 2215 | else if((tmp & 0x3f) == 0x3A) |
kevman | 2:7aab896b1a3b | 2216 | { |
kevman | 2:7aab896b1a3b | 2217 | rf_sensitivity = -97; |
kevman | 2:7aab896b1a3b | 2218 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2219 | tmp = OQPSK_RC_400_SCR_ON; |
kevman | 2:7aab896b1a3b | 2220 | } |
kevman | 2:7aab896b1a3b | 2221 | else if((tmp & 0x3f) == 0x1A) |
kevman | 2:7aab896b1a3b | 2222 | { |
kevman | 2:7aab896b1a3b | 2223 | rf_sensitivity = -97; |
kevman | 2:7aab896b1a3b | 2224 | rf_ack_wait_duration = 25; |
kevman | 2:7aab896b1a3b | 2225 | tmp = OQPSK_RC_400_SCR_OFF; |
kevman | 2:7aab896b1a3b | 2226 | } |
kevman | 2:7aab896b1a3b | 2227 | else if((tmp & 0x3f) == 0x2E) |
kevman | 2:7aab896b1a3b | 2228 | { |
kevman | 2:7aab896b1a3b | 2229 | rf_sensitivity = -93; |
kevman | 2:7aab896b1a3b | 2230 | rf_ack_wait_duration = 13; |
kevman | 2:7aab896b1a3b | 2231 | tmp = OQPSK_SIN_1000_SCR_ON; |
kevman | 2:7aab896b1a3b | 2232 | } |
kevman | 2:7aab896b1a3b | 2233 | else if((tmp & 0x3f) == 0x0E) |
kevman | 2:7aab896b1a3b | 2234 | { |
kevman | 2:7aab896b1a3b | 2235 | rf_sensitivity = -93; |
kevman | 2:7aab896b1a3b | 2236 | rf_ack_wait_duration = 13; |
kevman | 2:7aab896b1a3b | 2237 | tmp = OQPSK_SIN_1000_SCR_OFF; |
kevman | 2:7aab896b1a3b | 2238 | } |
kevman | 2:7aab896b1a3b | 2239 | else if((tmp & 0x3f) == 0x3E) |
kevman | 2:7aab896b1a3b | 2240 | { |
kevman | 2:7aab896b1a3b | 2241 | rf_sensitivity = -95; |
kevman | 2:7aab896b1a3b | 2242 | rf_ack_wait_duration = 13; |
kevman | 2:7aab896b1a3b | 2243 | tmp = OQPSK_RC_1000_SCR_ON; |
kevman | 2:7aab896b1a3b | 2244 | } |
kevman | 2:7aab896b1a3b | 2245 | else if((tmp & 0x3f) == 0x1E) |
kevman | 2:7aab896b1a3b | 2246 | { |
kevman | 2:7aab896b1a3b | 2247 | rf_sensitivity = -95; |
kevman | 2:7aab896b1a3b | 2248 | rf_ack_wait_duration = 13; |
kevman | 2:7aab896b1a3b | 2249 | tmp = OQPSK_RC_1000_SCR_OFF; |
kevman | 2:7aab896b1a3b | 2250 | } |
kevman | 2:7aab896b1a3b | 2251 | } |
kevman | 2:7aab896b1a3b | 2252 | else |
kevman | 2:7aab896b1a3b | 2253 | { |
kevman | 2:7aab896b1a3b | 2254 | rf_sensitivity = -101; |
kevman | 2:7aab896b1a3b | 2255 | rf_ack_wait_duration = 20; |
kevman | 2:7aab896b1a3b | 2256 | } |
kevman | 2:7aab896b1a3b | 2257 | /*Board design might reduces the sensitivity*/ |
kevman | 2:7aab896b1a3b | 2258 | //rf_sensitivity += RF_SENSITIVITY_CALIBRATION; |
kevman | 2:7aab896b1a3b | 2259 | } |
kevman | 2:7aab896b1a3b | 2260 | |
kevman | 2:7aab896b1a3b | 2261 | |
kevman | 2:7aab896b1a3b | 2262 | static uint8_t rf_scale_lqi(int8_t rssi) |
kevman | 2:7aab896b1a3b | 2263 | { |
kevman | 2:7aab896b1a3b | 2264 | uint8_t scaled_lqi; |
kevman | 2:7aab896b1a3b | 2265 | |
kevman | 2:7aab896b1a3b | 2266 | /*rssi < RF sensitivity*/ |
kevman | 2:7aab896b1a3b | 2267 | if(rssi < rf_sensitivity) |
kevman | 2:7aab896b1a3b | 2268 | scaled_lqi=0; |
kevman | 2:7aab896b1a3b | 2269 | /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2270 | /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2271 | else if(rssi < (rf_sensitivity + 10)) |
kevman | 2:7aab896b1a3b | 2272 | scaled_lqi=31; |
kevman | 2:7aab896b1a3b | 2273 | /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2274 | /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2275 | else if(rssi < (rf_sensitivity + 20)) |
kevman | 2:7aab896b1a3b | 2276 | scaled_lqi=207; |
kevman | 2:7aab896b1a3b | 2277 | /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2278 | /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2279 | else if(rssi < (rf_sensitivity + 30)) |
kevman | 2:7aab896b1a3b | 2280 | scaled_lqi=255; |
kevman | 2:7aab896b1a3b | 2281 | /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2282 | /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2283 | else if(rssi < (rf_sensitivity + 40)) |
kevman | 2:7aab896b1a3b | 2284 | scaled_lqi=255; |
kevman | 2:7aab896b1a3b | 2285 | /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2286 | /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2287 | else if(rssi < (rf_sensitivity + 50)) |
kevman | 2:7aab896b1a3b | 2288 | scaled_lqi=255; |
kevman | 2:7aab896b1a3b | 2289 | /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2290 | /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2291 | else if(rssi < (rf_sensitivity + 60)) |
kevman | 2:7aab896b1a3b | 2292 | scaled_lqi=255; |
kevman | 2:7aab896b1a3b | 2293 | /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2294 | /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2295 | else if(rssi < (rf_sensitivity + 70)) |
kevman | 2:7aab896b1a3b | 2296 | scaled_lqi=255; |
kevman | 2:7aab896b1a3b | 2297 | /*rssi > RF saturation*/ |
kevman | 2:7aab896b1a3b | 2298 | else if(rssi > (rf_sensitivity + 80)) |
kevman | 2:7aab896b1a3b | 2299 | scaled_lqi=111; |
kevman | 2:7aab896b1a3b | 2300 | /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/ |
kevman | 2:7aab896b1a3b | 2301 | /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/ |
kevman | 2:7aab896b1a3b | 2302 | else |
kevman | 2:7aab896b1a3b | 2303 | scaled_lqi=255; |
kevman | 2:7aab896b1a3b | 2304 | |
kevman | 2:7aab896b1a3b | 2305 | return scaled_lqi; |
kevman | 2:7aab896b1a3b | 2306 | } |
kevman | 2:7aab896b1a3b | 2307 | |
kevman | 2:7aab896b1a3b | 2308 | NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso, |
kevman | 2:7aab896b1a3b | 2309 | PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_slp, PinName spi_irq, |
kevman | 2:7aab896b1a3b | 2310 | PinName i2c_sda, PinName i2c_scl) |
kevman | 2:7aab896b1a3b | 2311 | : _mac(i2c_sda, i2c_scl), _mac_addr(), _rf(NULL), _mac_set(false), |
kevman | 2:7aab896b1a3b | 2312 | _spi_mosi(spi_mosi), _spi_miso(spi_miso), _spi_sclk(spi_sclk), |
kevman | 2:7aab896b1a3b | 2313 | _spi_cs(spi_cs), _spi_rst(spi_rst), _spi_slp(spi_slp), _spi_irq(spi_irq) |
kevman | 2:7aab896b1a3b | 2314 | { |
kevman | 2:7aab896b1a3b | 2315 | _rf = new RFBits(_spi_mosi, _spi_miso, _spi_sclk, _spi_cs, _spi_rst, _spi_slp, _spi_irq); |
kevman | 2:7aab896b1a3b | 2316 | } |
kevman | 2:7aab896b1a3b | 2317 | |
kevman | 2:7aab896b1a3b | 2318 | NanostackRfPhyAtmel::~NanostackRfPhyAtmel() |
kevman | 2:7aab896b1a3b | 2319 | { |
kevman | 2:7aab896b1a3b | 2320 | delete _rf; |
kevman | 2:7aab896b1a3b | 2321 | } |
kevman | 2:7aab896b1a3b | 2322 | |
kevman | 2:7aab896b1a3b | 2323 | int8_t NanostackRfPhyAtmel::rf_register() |
kevman | 2:7aab896b1a3b | 2324 | { |
kevman | 2:7aab896b1a3b | 2325 | if (NULL == _rf) { |
kevman | 2:7aab896b1a3b | 2326 | return -1; |
kevman | 2:7aab896b1a3b | 2327 | } |
kevman | 2:7aab896b1a3b | 2328 | |
kevman | 2:7aab896b1a3b | 2329 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 2330 | |
kevman | 2:7aab896b1a3b | 2331 | if (rf != NULL) { |
kevman | 2:7aab896b1a3b | 2332 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2333 | error("Multiple registrations of NanostackRfPhyAtmel not supported"); |
kevman | 2:7aab896b1a3b | 2334 | return -1; |
kevman | 2:7aab896b1a3b | 2335 | } |
kevman | 2:7aab896b1a3b | 2336 | |
kevman | 2:7aab896b1a3b | 2337 | // Read the mac address if it hasn't been set by a user |
kevman | 2:7aab896b1a3b | 2338 | rf = _rf; |
kevman | 2:7aab896b1a3b | 2339 | if (!_mac_set) { |
kevman | 2:7aab896b1a3b | 2340 | int ret = _mac.read_eui64((void*)_mac_addr); |
kevman | 2:7aab896b1a3b | 2341 | if (ret < 0) { |
kevman | 2:7aab896b1a3b | 2342 | rf = NULL; |
kevman | 2:7aab896b1a3b | 2343 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2344 | return -1; |
kevman | 2:7aab896b1a3b | 2345 | } |
kevman | 2:7aab896b1a3b | 2346 | } |
kevman | 2:7aab896b1a3b | 2347 | |
kevman | 2:7aab896b1a3b | 2348 | int8_t radio_id = rf_device_register(_mac_addr); |
kevman | 2:7aab896b1a3b | 2349 | if (radio_id < 0) { |
kevman | 2:7aab896b1a3b | 2350 | rf = NULL; |
kevman | 2:7aab896b1a3b | 2351 | } |
kevman | 2:7aab896b1a3b | 2352 | |
kevman | 2:7aab896b1a3b | 2353 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2354 | return radio_id; |
kevman | 2:7aab896b1a3b | 2355 | } |
kevman | 2:7aab896b1a3b | 2356 | |
kevman | 2:7aab896b1a3b | 2357 | void NanostackRfPhyAtmel::rf_unregister() |
kevman | 2:7aab896b1a3b | 2358 | { |
kevman | 2:7aab896b1a3b | 2359 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 2360 | |
kevman | 2:7aab896b1a3b | 2361 | if (NULL == rf) { |
kevman | 2:7aab896b1a3b | 2362 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2363 | return; |
kevman | 2:7aab896b1a3b | 2364 | } |
kevman | 2:7aab896b1a3b | 2365 | |
kevman | 2:7aab896b1a3b | 2366 | rf_device_unregister(); |
kevman | 2:7aab896b1a3b | 2367 | rf = NULL; |
kevman | 2:7aab896b1a3b | 2368 | |
kevman | 2:7aab896b1a3b | 2369 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2370 | } |
kevman | 2:7aab896b1a3b | 2371 | |
kevman | 2:7aab896b1a3b | 2372 | void NanostackRfPhyAtmel::get_mac_address(uint8_t *mac) |
kevman | 2:7aab896b1a3b | 2373 | { |
kevman | 2:7aab896b1a3b | 2374 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 2375 | |
kevman | 2:7aab896b1a3b | 2376 | if (NULL == rf) { |
kevman | 2:7aab896b1a3b | 2377 | error("NanostackRfPhyAtmel Must be registered to read mac address"); |
kevman | 2:7aab896b1a3b | 2378 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2379 | return; |
kevman | 2:7aab896b1a3b | 2380 | } |
kevman | 2:7aab896b1a3b | 2381 | memcpy((void*)mac, (void*)_mac_addr, sizeof(_mac_addr)); |
kevman | 2:7aab896b1a3b | 2382 | |
kevman | 2:7aab896b1a3b | 2383 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2384 | } |
kevman | 2:7aab896b1a3b | 2385 | |
kevman | 2:7aab896b1a3b | 2386 | void NanostackRfPhyAtmel::set_mac_address(uint8_t *mac) |
kevman | 2:7aab896b1a3b | 2387 | { |
kevman | 2:7aab896b1a3b | 2388 | rf_if_lock(); |
kevman | 2:7aab896b1a3b | 2389 | |
kevman | 2:7aab896b1a3b | 2390 | if (NULL != rf) { |
kevman | 2:7aab896b1a3b | 2391 | error("NanostackRfPhyAtmel cannot change mac address when running"); |
kevman | 2:7aab896b1a3b | 2392 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2393 | return; |
kevman | 2:7aab896b1a3b | 2394 | } |
kevman | 2:7aab896b1a3b | 2395 | memcpy((void*)_mac_addr, (void*)mac, sizeof(_mac_addr)); |
kevman | 2:7aab896b1a3b | 2396 | _mac_set = true; |
kevman | 2:7aab896b1a3b | 2397 | |
kevman | 2:7aab896b1a3b | 2398 | rf_if_unlock(); |
kevman | 2:7aab896b1a3b | 2399 | } |
kevman | 2:7aab896b1a3b | 2400 | |
kevman | 2:7aab896b1a3b | 2401 | #if MBED_CONF_ATMEL_RF_PROVIDE_DEFAULT |
kevman | 2:7aab896b1a3b | 2402 | |
kevman | 2:7aab896b1a3b | 2403 | NanostackRfPhy &NanostackRfPhy::get_default_instance() |
kevman | 2:7aab896b1a3b | 2404 | { |
kevman | 2:7aab896b1a3b | 2405 | static NanostackRfPhyAtmel rf_phy(ATMEL_SPI_MOSI, ATMEL_SPI_MISO, ATMEL_SPI_SCLK, ATMEL_SPI_CS, |
kevman | 2:7aab896b1a3b | 2406 | ATMEL_SPI_RST, ATMEL_SPI_SLP, ATMEL_SPI_IRQ, ATMEL_I2C_SDA, ATMEL_I2C_SCL); |
kevman | 2:7aab896b1a3b | 2407 | return rf_phy; |
kevman | 2:7aab896b1a3b | 2408 | } |
kevman | 2:7aab896b1a3b | 2409 | |
kevman | 2:7aab896b1a3b | 2410 | #endif // MBED_CONF_ATMEL_RF_PROVIDE_DEFAULT |
kevman | 2:7aab896b1a3b | 2411 | |
kevman | 2:7aab896b1a3b | 2412 | #endif // MBED_CONF_NANOSTACK_CONFIGURATION |