Added support for the WNC M14A2A Cellular LTE Data Module.

Dependencies:   WNC14A2AInterface

Easy Connect

Easily add all supported connectivity methods to your mbed OS project

This project is derived from https://developer.mbed.org/teams/sandbox/code/simple-mbed-client-example/file/dd6231df71bb/easy-connect.lib. It give user the ability to switch between connectivity methods and includes support for the WNC14A2A Data Module. The `NetworkInterface` API makes this easy, but you still need a mechanism for the user to select the connection method, The selection is made by modifying the `mbed_app.json` file and using `easy_connect()` from your application.

Specifying connectivity method

To add support for the WNC14A2A, add the following to your ``mbed_app.json`` file:

mbed_app.json

{
    "config": {
        "network-interface":{
            "help": "options are ETHERNET,WIFI_ESP8266,WIFI_ODIN,MESH_LOWPAN_ND,MESH_THREAD,WNC14A2A",
            "value": "WNC14A2A"
        }
    },
}

After you choose `WNC14A2A` you'll also need to indicate if you want debug output or not by Enabling (true) or Disabling (false) WNC_DEBUG.

If WNC_DEBUG is enabled, there are 3 different levels of debug output (selected via bit settings). These debug levels are set using the following values:

ValueDescription
1Basic WNC driver debug output
2Comprehensive WNC driver debug output
4Network Layer debug output

You can have any combination of these three bit values for a total value of 0 – 7.

WNC Debug Settings

    "config": {
        "WNC_DEBUG": {
            "value": false
        },
        "WNC_DEBUG_SETTING": {
            "value": 4
        },
    }

Using Easy Connect from your application

Easy Connect has just one function which will either return a `NetworkInterface`-pointer or `NULL`:

Sample Code

#include "easy-connect.h"

int main(int, char**) {
    NetworkInterface* network = easy_connect(true); /* has 1 argument, enable_logging (pass in true to log to serial port) */
    if (!network) {
        printf("Connecting to the network failed... See serial output.\r\n");
        return 1;
    }
 
    // Rest of your program
}

Tested on

  • K64F with Ethernet.
  • AT&T Cellular IoT Starter Kit with WNC M14A2A Cellular Data Module

The WNCInterface class currently supports the following version(s):

  • MPSS: M14A2A_v11.50.164451 APSS: M14A2A_v11.53.164451

License

This library is released under the Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License and may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Committer:
group-Avnet
Date:
Wed Apr 19 01:08:11 2017 +0000
Revision:
0:478cfd88041f
Initial commit

Who changed what in which revision?

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