http

Committer:
reeml3
Date:
Mon Apr 15 18:12:24 2019 +0000
Revision:
1:ce6ccd14af4c
Parent:
0:a49e37a83a7a
http

Who changed what in which revision?

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