RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew 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