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