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 "NanostackRfPhyMcr20a.h"
group-Avnet 0:478cfd88041f 17 #include "ns_types.h"
group-Avnet 0:478cfd88041f 18 #include "platform/arm_hal_interrupt.h"
group-Avnet 0:478cfd88041f 19 #include "nanostack/platform/arm_hal_phy.h"
group-Avnet 0:478cfd88041f 20 #include "toolchain.h"
group-Avnet 0:478cfd88041f 21 #include <string.h>
group-Avnet 0:478cfd88041f 22
group-Avnet 0:478cfd88041f 23 /* Freescale headers which are for C files */
group-Avnet 0:478cfd88041f 24 extern "C" {
group-Avnet 0:478cfd88041f 25 #include "MCR20Drv.h"
group-Avnet 0:478cfd88041f 26 #include "MCR20Reg.h"
group-Avnet 0:478cfd88041f 27 #include "MCR20Overwrites.h"
group-Avnet 0:478cfd88041f 28 }
group-Avnet 0:478cfd88041f 29
group-Avnet 0:478cfd88041f 30
group-Avnet 0:478cfd88041f 31 #define RF_BUFFER_SIZE 128
group-Avnet 0:478cfd88041f 32
group-Avnet 0:478cfd88041f 33 /*Radio RX and TX state definitions*/
group-Avnet 0:478cfd88041f 34 #define RFF_ON 0x01
group-Avnet 0:478cfd88041f 35 #define RFF_RX 0x02
group-Avnet 0:478cfd88041f 36 #define RFF_TX 0x04
group-Avnet 0:478cfd88041f 37 #define RFF_CCA 0x08
group-Avnet 0:478cfd88041f 38
group-Avnet 0:478cfd88041f 39 #define RF_MODE_NORMAL 0
group-Avnet 0:478cfd88041f 40 #define RF_MODE_SNIFFER 1
group-Avnet 0:478cfd88041f 41
group-Avnet 0:478cfd88041f 42 #define RF_CCA_THRESHOLD 75 /* -75 dBm */
group-Avnet 0:478cfd88041f 43
group-Avnet 0:478cfd88041f 44 #define RF_TX_POWER_MAX 0
group-Avnet 0:478cfd88041f 45
group-Avnet 0:478cfd88041f 46 /* PHY constants in symbols */
group-Avnet 0:478cfd88041f 47 #define gPhyWarmUpTime_c 9
group-Avnet 0:478cfd88041f 48 #define gPhySHRDuration_c 10
group-Avnet 0:478cfd88041f 49 #define gPhySymbolsPerOctet_c 2
group-Avnet 0:478cfd88041f 50 #define gPhyAckWaitDuration_c 54
group-Avnet 0:478cfd88041f 51
group-Avnet 0:478cfd88041f 52 #define gCcaED_c 0
group-Avnet 0:478cfd88041f 53 #define gCcaCCA_MODE1_c 1
group-Avnet 0:478cfd88041f 54
group-Avnet 0:478cfd88041f 55 #define gXcvrRunState_d gXcvrPwrAutodoze_c
group-Avnet 0:478cfd88041f 56 #define gXcvrLowPowerState_d gXcvrPwrHibernate_c
group-Avnet 0:478cfd88041f 57
group-Avnet 0:478cfd88041f 58
group-Avnet 0:478cfd88041f 59 /* MCR20A XCVR states */
group-Avnet 0:478cfd88041f 60 typedef enum xcvrState_tag{
group-Avnet 0:478cfd88041f 61 gIdle_c,
group-Avnet 0:478cfd88041f 62 gRX_c,
group-Avnet 0:478cfd88041f 63 gTX_c,
group-Avnet 0:478cfd88041f 64 gCCA_c,
group-Avnet 0:478cfd88041f 65 gTR_c,
group-Avnet 0:478cfd88041f 66 gCCCA_c,
group-Avnet 0:478cfd88041f 67 }xcvrState_t;
group-Avnet 0:478cfd88041f 68
group-Avnet 0:478cfd88041f 69 /* MCR20A XCVR low power states */
group-Avnet 0:478cfd88041f 70 typedef enum xcvrPwrMode_tag{
group-Avnet 0:478cfd88041f 71 gXcvrPwrIdle_c,
group-Avnet 0:478cfd88041f 72 gXcvrPwrAutodoze_c,
group-Avnet 0:478cfd88041f 73 gXcvrPwrDoze_c,
group-Avnet 0:478cfd88041f 74 gXcvrPwrHibernate_c
group-Avnet 0:478cfd88041f 75 }xcvrPwrMode_t;
group-Avnet 0:478cfd88041f 76
group-Avnet 0:478cfd88041f 77
group-Avnet 0:478cfd88041f 78 /*RF Part Type*/
group-Avnet 0:478cfd88041f 79 typedef enum
group-Avnet 0:478cfd88041f 80 {
group-Avnet 0:478cfd88041f 81 FREESCALE_UNKNOW_DEV = 0,
group-Avnet 0:478cfd88041f 82 FREESCALE_MCR20A
group-Avnet 0:478cfd88041f 83 }rf_trx_part_e;
group-Avnet 0:478cfd88041f 84
group-Avnet 0:478cfd88041f 85 /*Atmel RF states*/
group-Avnet 0:478cfd88041f 86 typedef enum
group-Avnet 0:478cfd88041f 87 {
group-Avnet 0:478cfd88041f 88 NOP = 0x00,
group-Avnet 0:478cfd88041f 89 BUSY_RX = 0x01,
group-Avnet 0:478cfd88041f 90 RF_TX_START = 0x02,
group-Avnet 0:478cfd88041f 91 FORCE_TRX_OFF = 0x03,
group-Avnet 0:478cfd88041f 92 FORCE_PLL_ON = 0x04,
group-Avnet 0:478cfd88041f 93 RX_ON = 0x06,
group-Avnet 0:478cfd88041f 94 TRX_OFF = 0x08,
group-Avnet 0:478cfd88041f 95 PLL_ON = 0x09,
group-Avnet 0:478cfd88041f 96 BUSY_RX_AACK = 0x11,
group-Avnet 0:478cfd88041f 97 SLEEP = 0x0F,
group-Avnet 0:478cfd88041f 98 RX_AACK_ON = 0x16,
group-Avnet 0:478cfd88041f 99 TX_ARET_ON = 0x19
group-Avnet 0:478cfd88041f 100 }rf_trx_states_t;
group-Avnet 0:478cfd88041f 101
group-Avnet 0:478cfd88041f 102 /*RF receive buffer*/
group-Avnet 0:478cfd88041f 103 static uint8_t rf_buffer[RF_BUFFER_SIZE];
group-Avnet 0:478cfd88041f 104
group-Avnet 0:478cfd88041f 105 /* TX info */
group-Avnet 0:478cfd88041f 106 static uint8_t radio_tx_power = 0x17; /* 0 dBm */
group-Avnet 0:478cfd88041f 107 static uint8_t mac_tx_handle = 0;
group-Avnet 0:478cfd88041f 108 static uint8_t need_ack = 0;
group-Avnet 0:478cfd88041f 109 static uint16_t tx_len = 0;
group-Avnet 0:478cfd88041f 110
group-Avnet 0:478cfd88041f 111 /* RF driver data */
group-Avnet 0:478cfd88041f 112 static xcvrState_t mPhySeqState;
group-Avnet 0:478cfd88041f 113 static xcvrPwrMode_t mPwrState;
group-Avnet 0:478cfd88041f 114 static phy_device_driver_s device_driver;
group-Avnet 0:478cfd88041f 115 static uint8_t mStatusAndControlRegs[8];
group-Avnet 0:478cfd88041f 116 static uint8_t rf_rnd = 0;
group-Avnet 0:478cfd88041f 117 static int8_t rf_radio_driver_id = -1;
group-Avnet 0:478cfd88041f 118 static uint8_t MAC_address[8] = {1, 2, 3, 4, 5, 6, 7, 8};
group-Avnet 0:478cfd88041f 119
group-Avnet 0:478cfd88041f 120 /* Driver instance handle and hardware */
group-Avnet 0:478cfd88041f 121 static NanostackRfPhyMcr20a *rf = NULL;
group-Avnet 0:478cfd88041f 122 static SPI *spi = NULL;
group-Avnet 0:478cfd88041f 123 static DigitalOut *cs = NULL;
group-Avnet 0:478cfd88041f 124 static DigitalOut *rst = NULL;
group-Avnet 0:478cfd88041f 125 static InterruptIn *irq = NULL;
group-Avnet 0:478cfd88041f 126 static DigitalIn *irq_pin = NULL;
group-Avnet 0:478cfd88041f 127
group-Avnet 0:478cfd88041f 128 /* Channel info */ /* 2405 2410 2415 2420 2425 2430 2435 2440 2445 2450 2455 2460 2465 2470 2475 2480 */
group-Avnet 0:478cfd88041f 129 static const uint8_t pll_int[16] = {0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D};
group-Avnet 0:478cfd88041f 130 static const uint16_t pll_frac[16] = {0x2800, 0x5000, 0x7800, 0xA000, 0xC800, 0xF000, 0x1800, 0x4000, 0x6800, 0x9000, 0xB800, 0xE000, 0x0800, 0x3000, 0x5800, 0x8000};
group-Avnet 0:478cfd88041f 131 static uint8_t rf_phy_channel = 0;
group-Avnet 0:478cfd88041f 132
group-Avnet 0:478cfd88041f 133 /* Channel configurations for 2.4 */
group-Avnet 0:478cfd88041f 134 static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
group-Avnet 0:478cfd88041f 135
group-Avnet 0:478cfd88041f 136 static const phy_device_channel_page_s phy_channel_pages[] = {
group-Avnet 0:478cfd88041f 137 { CHANNEL_PAGE_0, &phy_24ghz},
group-Avnet 0:478cfd88041f 138 { CHANNEL_PAGE_0, NULL}
group-Avnet 0:478cfd88041f 139 };
group-Avnet 0:478cfd88041f 140
group-Avnet 0:478cfd88041f 141
group-Avnet 0:478cfd88041f 142 static rf_trx_part_e rf_radio_type_read(void);
group-Avnet 0:478cfd88041f 143
group-Avnet 0:478cfd88041f 144 MBED_UNUSED static void rf_ack_wait_timer_start(uint16_t slots);
group-Avnet 0:478cfd88041f 145 MBED_UNUSED static void rf_ack_wait_timer_stop(void);
group-Avnet 0:478cfd88041f 146 MBED_UNUSED static void rf_handle_cca_ed_done(void);
group-Avnet 0:478cfd88041f 147 MBED_UNUSED static void rf_handle_tx_end(void);
group-Avnet 0:478cfd88041f 148 MBED_UNUSED static void rf_handle_rx_end(void);
group-Avnet 0:478cfd88041f 149 MBED_UNUSED static void rf_on(void);
group-Avnet 0:478cfd88041f 150 MBED_UNUSED static void rf_receive(void);
group-Avnet 0:478cfd88041f 151 MBED_UNUSED static void rf_poll_trx_state_change(rf_trx_states_t trx_state);
group-Avnet 0:478cfd88041f 152 MBED_UNUSED static void rf_init(void);
group-Avnet 0:478cfd88041f 153 MBED_UNUSED static void rf_set_mac_address(const uint8_t *ptr);
group-Avnet 0:478cfd88041f 154 MBED_UNUSED static int8_t rf_device_register(void);
group-Avnet 0:478cfd88041f 155 MBED_UNUSED static void rf_device_unregister(void);
group-Avnet 0:478cfd88041f 156 MBED_UNUSED 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 157 MBED_UNUSED static void rf_cca_abort(void);
group-Avnet 0:478cfd88041f 158 MBED_UNUSED static void rf_read_mac_address(uint8_t *ptr);
group-Avnet 0:478cfd88041f 159 MBED_UNUSED static int8_t rf_read_random(void);
group-Avnet 0:478cfd88041f 160 MBED_UNUSED static void rf_calibration_cb(void);
group-Avnet 0:478cfd88041f 161 MBED_UNUSED static void rf_init_phy_mode(void);
group-Avnet 0:478cfd88041f 162 MBED_UNUSED static void rf_ack_wait_timer_interrupt(void);
group-Avnet 0:478cfd88041f 163 MBED_UNUSED static void rf_calibration_timer_interrupt(void);
group-Avnet 0:478cfd88041f 164 MBED_UNUSED static void rf_calibration_timer_start(uint32_t slots);
group-Avnet 0:478cfd88041f 165 MBED_UNUSED static void rf_cca_timer_interrupt(void);
group-Avnet 0:478cfd88041f 166 MBED_UNUSED static void rf_cca_timer_start(uint32_t slots);
group-Avnet 0:478cfd88041f 167 MBED_UNUSED static uint16_t rf_get_phy_mtu_size(void);
group-Avnet 0:478cfd88041f 168 MBED_UNUSED static uint8_t rf_scale_lqi(int8_t rssi);
group-Avnet 0:478cfd88041f 169
group-Avnet 0:478cfd88041f 170 /**
group-Avnet 0:478cfd88041f 171 * RF output power write
group-Avnet 0:478cfd88041f 172 *
group-Avnet 0:478cfd88041f 173 * \brief TX power has to be set before network start.
group-Avnet 0:478cfd88041f 174 *
group-Avnet 0:478cfd88041f 175 * \param power
group-Avnet 0:478cfd88041f 176 * See datasheet for TX power settings
group-Avnet 0:478cfd88041f 177 *
group-Avnet 0:478cfd88041f 178 * \return 0, Supported Value
group-Avnet 0:478cfd88041f 179 * \return -1, Not Supported Value
group-Avnet 0:478cfd88041f 180 */
group-Avnet 0:478cfd88041f 181 MBED_UNUSED static int8_t rf_tx_power_set(uint8_t power);
group-Avnet 0:478cfd88041f 182 MBED_UNUSED static uint8_t rf_tx_power_get(void);
group-Avnet 0:478cfd88041f 183 MBED_UNUSED static int8_t rf_enable_antenna_diversity(void);
group-Avnet 0:478cfd88041f 184
group-Avnet 0:478cfd88041f 185 /* Private functions */
group-Avnet 0:478cfd88041f 186 MBED_UNUSED static void rf_abort(void);
group-Avnet 0:478cfd88041f 187 MBED_UNUSED static void rf_promiscuous(uint8_t mode);
group-Avnet 0:478cfd88041f 188 MBED_UNUSED static void rf_get_timestamp(uint32_t *pRetClk);
group-Avnet 0:478cfd88041f 189 MBED_UNUSED static void rf_set_timeout(uint32_t *pEndTime);
group-Avnet 0:478cfd88041f 190 MBED_UNUSED static void rf_set_power_state(xcvrPwrMode_t newState);
group-Avnet 0:478cfd88041f 191 MBED_UNUSED static uint8_t rf_if_read_rnd(void);
group-Avnet 0:478cfd88041f 192 MBED_UNUSED static uint8_t rf_convert_LQI(uint8_t hwLqi);
group-Avnet 0:478cfd88041f 193 MBED_UNUSED static uint8_t rf_get_channel_energy(void);
group-Avnet 0:478cfd88041f 194 MBED_UNUSED static uint8_t rf_convert_energy_level(uint8_t energyLevel);
group-Avnet 0:478cfd88041f 195 MBED_UNUSED static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi);
group-Avnet 0:478cfd88041f 196 MBED_UNUSED static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
group-Avnet 0:478cfd88041f 197 MBED_UNUSED static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr);
group-Avnet 0:478cfd88041f 198 MBED_UNUSED static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr);
group-Avnet 0:478cfd88041f 199 MBED_UNUSED static void rf_mac64_read(uint8_t *address);
group-Avnet 0:478cfd88041f 200
group-Avnet 0:478cfd88041f 201
group-Avnet 0:478cfd88041f 202
group-Avnet 0:478cfd88041f 203 /*
group-Avnet 0:478cfd88041f 204 * \brief Read connected radio part.
group-Avnet 0:478cfd88041f 205 *
group-Avnet 0:478cfd88041f 206 * This function only return valid information when rf_init() is called
group-Avnet 0:478cfd88041f 207 *
group-Avnet 0:478cfd88041f 208 * \return
group-Avnet 0:478cfd88041f 209 */
group-Avnet 0:478cfd88041f 210 static rf_trx_part_e rf_radio_type_read(void)
group-Avnet 0:478cfd88041f 211 {
group-Avnet 0:478cfd88041f 212 return FREESCALE_MCR20A;
group-Avnet 0:478cfd88041f 213 }
group-Avnet 0:478cfd88041f 214
group-Avnet 0:478cfd88041f 215 /*
group-Avnet 0:478cfd88041f 216 * \brief Function initialises and registers the RF driver.
group-Avnet 0:478cfd88041f 217 *
group-Avnet 0:478cfd88041f 218 * \param none
group-Avnet 0:478cfd88041f 219 *
group-Avnet 0:478cfd88041f 220 * \return rf_radio_driver_id Driver ID given by NET library
group-Avnet 0:478cfd88041f 221 */
group-Avnet 0:478cfd88041f 222 static int8_t rf_device_register(void)
group-Avnet 0:478cfd88041f 223 {
group-Avnet 0:478cfd88041f 224 rf_trx_part_e radio_type;
group-Avnet 0:478cfd88041f 225
group-Avnet 0:478cfd88041f 226 rf_init();
group-Avnet 0:478cfd88041f 227
group-Avnet 0:478cfd88041f 228
group-Avnet 0:478cfd88041f 229
group-Avnet 0:478cfd88041f 230 radio_type = rf_radio_type_read();
group-Avnet 0:478cfd88041f 231 if(radio_type == FREESCALE_MCR20A)
group-Avnet 0:478cfd88041f 232 {
group-Avnet 0:478cfd88041f 233 /*Set pointer to MAC address*/
group-Avnet 0:478cfd88041f 234 device_driver.PHY_MAC = MAC_address;
group-Avnet 0:478cfd88041f 235 device_driver.driver_description = (char*)"FREESCALE_MAC";
group-Avnet 0:478cfd88041f 236
group-Avnet 0:478cfd88041f 237 //Create setup Used Radio chips
group-Avnet 0:478cfd88041f 238 /*Type of RF PHY is SubGHz*/
group-Avnet 0:478cfd88041f 239 device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
group-Avnet 0:478cfd88041f 240
group-Avnet 0:478cfd88041f 241 device_driver.phy_channel_pages = phy_channel_pages;
group-Avnet 0:478cfd88041f 242 /*Maximum size of payload is 127*/
group-Avnet 0:478cfd88041f 243 device_driver.phy_MTU = 127;
group-Avnet 0:478cfd88041f 244 /*No header in PHY*/
group-Avnet 0:478cfd88041f 245 device_driver.phy_header_length = 0;
group-Avnet 0:478cfd88041f 246 /*No tail in PHY*/
group-Avnet 0:478cfd88041f 247 device_driver.phy_tail_length = 0;
group-Avnet 0:478cfd88041f 248 /*Set address write function*/
group-Avnet 0:478cfd88041f 249 device_driver.address_write = &rf_address_write;
group-Avnet 0:478cfd88041f 250 /*Set RF extension function*/
group-Avnet 0:478cfd88041f 251 device_driver.extension = &rf_extension;
group-Avnet 0:478cfd88041f 252 /*Set RF state control function*/
group-Avnet 0:478cfd88041f 253 device_driver.state_control = &rf_interface_state_control;
group-Avnet 0:478cfd88041f 254 /*Set transmit function*/
group-Avnet 0:478cfd88041f 255 device_driver.tx = &rf_start_cca;
group-Avnet 0:478cfd88041f 256 /*Upper layer callbacks init to NULL*/
group-Avnet 0:478cfd88041f 257 device_driver.phy_rx_cb = NULL;
group-Avnet 0:478cfd88041f 258 device_driver.phy_tx_done_cb = NULL;
group-Avnet 0:478cfd88041f 259 /*Virtual upper data callback init to NULL*/
group-Avnet 0:478cfd88041f 260 device_driver.arm_net_virtual_rx_cb = NULL;
group-Avnet 0:478cfd88041f 261 device_driver.arm_net_virtual_tx_cb = NULL;
group-Avnet 0:478cfd88041f 262
group-Avnet 0:478cfd88041f 263 /*Register device driver*/
group-Avnet 0:478cfd88041f 264 rf_radio_driver_id = arm_net_phy_register(&device_driver);
group-Avnet 0:478cfd88041f 265 }
group-Avnet 0:478cfd88041f 266
group-Avnet 0:478cfd88041f 267 return rf_radio_driver_id;
group-Avnet 0:478cfd88041f 268 }
group-Avnet 0:478cfd88041f 269
group-Avnet 0:478cfd88041f 270 /*
group-Avnet 0:478cfd88041f 271 * \brief Function unregisters the RF driver.
group-Avnet 0:478cfd88041f 272 *
group-Avnet 0:478cfd88041f 273 * \param none
group-Avnet 0:478cfd88041f 274 *
group-Avnet 0:478cfd88041f 275 * \return none
group-Avnet 0:478cfd88041f 276 */
group-Avnet 0:478cfd88041f 277 static void rf_device_unregister(void)
group-Avnet 0:478cfd88041f 278 {
group-Avnet 0:478cfd88041f 279 arm_net_phy_unregister(rf_radio_driver_id);
group-Avnet 0:478cfd88041f 280 }
group-Avnet 0:478cfd88041f 281
group-Avnet 0:478cfd88041f 282 /*
group-Avnet 0:478cfd88041f 283 * \brief Function returns the generated 8-bit random value for seeding Pseudo-random generator.
group-Avnet 0:478cfd88041f 284 *
group-Avnet 0:478cfd88041f 285 * \param none
group-Avnet 0:478cfd88041f 286 *
group-Avnet 0:478cfd88041f 287 * \return random value
group-Avnet 0:478cfd88041f 288 */
group-Avnet 0:478cfd88041f 289 static int8_t rf_read_random(void)
group-Avnet 0:478cfd88041f 290 {
group-Avnet 0:478cfd88041f 291 return rf_rnd;
group-Avnet 0:478cfd88041f 292 }
group-Avnet 0:478cfd88041f 293
group-Avnet 0:478cfd88041f 294 /*
group-Avnet 0:478cfd88041f 295 * \brief Function is a call back for ACK wait timeout.
group-Avnet 0:478cfd88041f 296 *
group-Avnet 0:478cfd88041f 297 * \param none
group-Avnet 0:478cfd88041f 298 *
group-Avnet 0:478cfd88041f 299 * \return none
group-Avnet 0:478cfd88041f 300 */
group-Avnet 0:478cfd88041f 301 static void rf_ack_wait_timer_interrupt(void)
group-Avnet 0:478cfd88041f 302 {
group-Avnet 0:478cfd88041f 303 /* The packet was transmitted successfully, but no ACK was received */
group-Avnet 0:478cfd88041f 304 if (device_driver.phy_tx_done_cb) {
group-Avnet 0:478cfd88041f 305 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
group-Avnet 0:478cfd88041f 306 }
group-Avnet 0:478cfd88041f 307 rf_receive();
group-Avnet 0:478cfd88041f 308 }
group-Avnet 0:478cfd88041f 309
group-Avnet 0:478cfd88041f 310 /*
group-Avnet 0:478cfd88041f 311 * \brief Function is a call back for calibration interval timer.
group-Avnet 0:478cfd88041f 312 *
group-Avnet 0:478cfd88041f 313 * \param none
group-Avnet 0:478cfd88041f 314 *
group-Avnet 0:478cfd88041f 315 * \return none
group-Avnet 0:478cfd88041f 316 */
group-Avnet 0:478cfd88041f 317 static void rf_calibration_timer_interrupt(void)
group-Avnet 0:478cfd88041f 318 {
group-Avnet 0:478cfd88041f 319 }
group-Avnet 0:478cfd88041f 320
group-Avnet 0:478cfd88041f 321 /*
group-Avnet 0:478cfd88041f 322 * \brief Function is a call back for cca interval timer.
group-Avnet 0:478cfd88041f 323 *
group-Avnet 0:478cfd88041f 324 * \param none
group-Avnet 0:478cfd88041f 325 *
group-Avnet 0:478cfd88041f 326 * \return none
group-Avnet 0:478cfd88041f 327 */
group-Avnet 0:478cfd88041f 328 static void rf_cca_timer_interrupt(void)
group-Avnet 0:478cfd88041f 329 {
group-Avnet 0:478cfd88041f 330 /* CCA time-out handled by Hardware */
group-Avnet 0:478cfd88041f 331 }
group-Avnet 0:478cfd88041f 332
group-Avnet 0:478cfd88041f 333
group-Avnet 0:478cfd88041f 334 /*
group-Avnet 0:478cfd88041f 335 * \brief Function starts the ACK wait time-out.
group-Avnet 0:478cfd88041f 336 *
group-Avnet 0:478cfd88041f 337 * \param slots The ACK wait time-out in [symbols]
group-Avnet 0:478cfd88041f 338 *
group-Avnet 0:478cfd88041f 339 * \return none
group-Avnet 0:478cfd88041f 340 */
group-Avnet 0:478cfd88041f 341 static void rf_ack_wait_timer_start(uint16_t time)
group-Avnet 0:478cfd88041f 342 {
group-Avnet 0:478cfd88041f 343 uint32_t timeout;
group-Avnet 0:478cfd88041f 344
group-Avnet 0:478cfd88041f 345 rf_get_timestamp(&timeout);
group-Avnet 0:478cfd88041f 346 timeout += time;
group-Avnet 0:478cfd88041f 347 rf_set_timeout(&timeout);
group-Avnet 0:478cfd88041f 348 }
group-Avnet 0:478cfd88041f 349
group-Avnet 0:478cfd88041f 350 /*
group-Avnet 0:478cfd88041f 351 * \brief Function starts the calibration interval.
group-Avnet 0:478cfd88041f 352 *
group-Avnet 0:478cfd88041f 353 * \param slots Given slots, resolution 50us
group-Avnet 0:478cfd88041f 354 *
group-Avnet 0:478cfd88041f 355 * \return none
group-Avnet 0:478cfd88041f 356 */
group-Avnet 0:478cfd88041f 357 static void rf_calibration_timer_start(uint32_t slots)
group-Avnet 0:478cfd88041f 358 {
group-Avnet 0:478cfd88041f 359 (void)slots;
group-Avnet 0:478cfd88041f 360 }
group-Avnet 0:478cfd88041f 361
group-Avnet 0:478cfd88041f 362 /*
group-Avnet 0:478cfd88041f 363 * \brief Function starts the CCA timout.
group-Avnet 0:478cfd88041f 364 *
group-Avnet 0:478cfd88041f 365 * \param slots Given slots, resolution 50us
group-Avnet 0:478cfd88041f 366 *
group-Avnet 0:478cfd88041f 367 * \return none
group-Avnet 0:478cfd88041f 368 */
group-Avnet 0:478cfd88041f 369 static void rf_cca_timer_start(uint32_t slots)
group-Avnet 0:478cfd88041f 370 {
group-Avnet 0:478cfd88041f 371 (void)slots;
group-Avnet 0:478cfd88041f 372 }
group-Avnet 0:478cfd88041f 373
group-Avnet 0:478cfd88041f 374 /*
group-Avnet 0:478cfd88041f 375 * \brief Function stops the ACK wait timeout.
group-Avnet 0:478cfd88041f 376 *
group-Avnet 0:478cfd88041f 377 * \param none
group-Avnet 0:478cfd88041f 378 *
group-Avnet 0:478cfd88041f 379 * \return none
group-Avnet 0:478cfd88041f 380 */
group-Avnet 0:478cfd88041f 381 static void rf_ack_wait_timer_stop(void)
group-Avnet 0:478cfd88041f 382 {
group-Avnet 0:478cfd88041f 383 }
group-Avnet 0:478cfd88041f 384
group-Avnet 0:478cfd88041f 385 /*
group-Avnet 0:478cfd88041f 386 * \brief Function reads the MAC address array.
group-Avnet 0:478cfd88041f 387 *
group-Avnet 0:478cfd88041f 388 * \param ptr Pointer to read array
group-Avnet 0:478cfd88041f 389 *
group-Avnet 0:478cfd88041f 390 * \return none
group-Avnet 0:478cfd88041f 391 */
group-Avnet 0:478cfd88041f 392 static void rf_read_mac_address(uint8_t *ptr)
group-Avnet 0:478cfd88041f 393 {
group-Avnet 0:478cfd88041f 394 memcpy(ptr, MAC_address, 8);
group-Avnet 0:478cfd88041f 395 }
group-Avnet 0:478cfd88041f 396
group-Avnet 0:478cfd88041f 397 /*
group-Avnet 0:478cfd88041f 398 * \brief Function sets the MAC address array.
group-Avnet 0:478cfd88041f 399 *
group-Avnet 0:478cfd88041f 400 * \param ptr Pointer to given MAC address array
group-Avnet 0:478cfd88041f 401 *
group-Avnet 0:478cfd88041f 402 * \return none
group-Avnet 0:478cfd88041f 403 */
group-Avnet 0:478cfd88041f 404 static void rf_set_mac_address(const uint8_t *ptr)
group-Avnet 0:478cfd88041f 405 {
group-Avnet 0:478cfd88041f 406 memcpy(MAC_address, ptr, 8);
group-Avnet 0:478cfd88041f 407 }
group-Avnet 0:478cfd88041f 408
group-Avnet 0:478cfd88041f 409 static uint16_t rf_get_phy_mtu_size(void)
group-Avnet 0:478cfd88041f 410 {
group-Avnet 0:478cfd88041f 411 return device_driver.phy_MTU;
group-Avnet 0:478cfd88041f 412 }
group-Avnet 0:478cfd88041f 413
group-Avnet 0:478cfd88041f 414 /*
group-Avnet 0:478cfd88041f 415 * \brief Function writes 16-bit address in RF address filter.
group-Avnet 0:478cfd88041f 416 *
group-Avnet 0:478cfd88041f 417 * \param short_address Given short address
group-Avnet 0:478cfd88041f 418 *
group-Avnet 0:478cfd88041f 419 * \return none
group-Avnet 0:478cfd88041f 420 */
group-Avnet 0:478cfd88041f 421 static void rf_set_short_adr(uint8_t * short_address)
group-Avnet 0:478cfd88041f 422 {
group-Avnet 0:478cfd88041f 423 /* Write one register at a time to be accessible from hibernate mode */
group-Avnet 0:478cfd88041f 424 MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_MSB, short_address[0]);
group-Avnet 0:478cfd88041f 425 MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_LSB, short_address[1]);
group-Avnet 0:478cfd88041f 426 }
group-Avnet 0:478cfd88041f 427
group-Avnet 0:478cfd88041f 428 /*
group-Avnet 0:478cfd88041f 429 * \brief Function writes PAN Id in RF PAN Id filter.
group-Avnet 0:478cfd88041f 430 *
group-Avnet 0:478cfd88041f 431 * \param pan_id Given PAN Id
group-Avnet 0:478cfd88041f 432 *
group-Avnet 0:478cfd88041f 433 * \return none
group-Avnet 0:478cfd88041f 434 */
group-Avnet 0:478cfd88041f 435 static void rf_set_pan_id(uint8_t *pan_id)
group-Avnet 0:478cfd88041f 436 {
group-Avnet 0:478cfd88041f 437 /* Write one register at a time to be accessible from hibernate mode */
group-Avnet 0:478cfd88041f 438 MCR20Drv_IndirectAccessSPIWrite(MACPANID0_MSB, pan_id[0]);
group-Avnet 0:478cfd88041f 439 MCR20Drv_IndirectAccessSPIWrite(MACPANID0_LSB, pan_id[1]);
group-Avnet 0:478cfd88041f 440 }
group-Avnet 0:478cfd88041f 441
group-Avnet 0:478cfd88041f 442 /*
group-Avnet 0:478cfd88041f 443 * \brief Function writes 64-bit address in RF address filter.
group-Avnet 0:478cfd88041f 444 *
group-Avnet 0:478cfd88041f 445 * \param address Given 64-bit address
group-Avnet 0:478cfd88041f 446 *
group-Avnet 0:478cfd88041f 447 * \return none
group-Avnet 0:478cfd88041f 448 */
group-Avnet 0:478cfd88041f 449 static void rf_set_address(uint8_t *address)
group-Avnet 0:478cfd88041f 450 {
group-Avnet 0:478cfd88041f 451 /* Write one register at a time to be accessible from hibernate mode */
group-Avnet 0:478cfd88041f 452 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_0, address[7]);
group-Avnet 0:478cfd88041f 453 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_8, address[6]);
group-Avnet 0:478cfd88041f 454 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_16, address[5]);
group-Avnet 0:478cfd88041f 455 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_24, address[4]);
group-Avnet 0:478cfd88041f 456 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_32, address[3]);
group-Avnet 0:478cfd88041f 457 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_40, address[2]);
group-Avnet 0:478cfd88041f 458 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_48, address[1]);
group-Avnet 0:478cfd88041f 459 MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_56, address[0]);
group-Avnet 0:478cfd88041f 460 }
group-Avnet 0:478cfd88041f 461
group-Avnet 0:478cfd88041f 462 /*
group-Avnet 0:478cfd88041f 463 * \brief Function sets the RF channel.
group-Avnet 0:478cfd88041f 464 *
group-Avnet 0:478cfd88041f 465 * \param ch New channel
group-Avnet 0:478cfd88041f 466 *
group-Avnet 0:478cfd88041f 467 * \return none
group-Avnet 0:478cfd88041f 468 */
group-Avnet 0:478cfd88041f 469 static void rf_channel_set(uint8_t channel)
group-Avnet 0:478cfd88041f 470 {
group-Avnet 0:478cfd88041f 471 rf_phy_channel = channel;
group-Avnet 0:478cfd88041f 472 MCR20Drv_DirectAccessSPIWrite(PLL_INT0, pll_int[channel - 11]);
group-Avnet 0:478cfd88041f 473 MCR20Drv_DirectAccessSPIMultiByteWrite(PLL_FRAC0_LSB, (uint8_t *) &pll_frac[channel - 11], 2);
group-Avnet 0:478cfd88041f 474 }
group-Avnet 0:478cfd88041f 475
group-Avnet 0:478cfd88041f 476
group-Avnet 0:478cfd88041f 477 /*
group-Avnet 0:478cfd88041f 478 * \brief Function initialises the radio driver and resets the radio.
group-Avnet 0:478cfd88041f 479 *
group-Avnet 0:478cfd88041f 480 * \param none
group-Avnet 0:478cfd88041f 481 *
group-Avnet 0:478cfd88041f 482 * \return none
group-Avnet 0:478cfd88041f 483 */
group-Avnet 0:478cfd88041f 484 static void rf_init(void)
group-Avnet 0:478cfd88041f 485 {
group-Avnet 0:478cfd88041f 486 uint32_t index;
group-Avnet 0:478cfd88041f 487 mPhySeqState = gIdle_c;
group-Avnet 0:478cfd88041f 488 mPwrState = gXcvrPwrIdle_c;
group-Avnet 0:478cfd88041f 489 /*Reset RF module*/
group-Avnet 0:478cfd88041f 490 MCR20Drv_RESET();
group-Avnet 0:478cfd88041f 491 /* Initialize the transceiver SPI driver */
group-Avnet 0:478cfd88041f 492 MCR20Drv_Init();
group-Avnet 0:478cfd88041f 493 /* Disable Tristate on MISO for SPI reads */
group-Avnet 0:478cfd88041f 494 MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, 0x02);
group-Avnet 0:478cfd88041f 495 /* Set XCVR clock output settings */
group-Avnet 0:478cfd88041f 496 MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d);
group-Avnet 0:478cfd88041f 497 /* Set default XCVR power state */
group-Avnet 0:478cfd88041f 498 rf_set_power_state(gXcvrRunState_d);
group-Avnet 0:478cfd88041f 499
group-Avnet 0:478cfd88041f 500 /* PHY_CTRL1 default HW settings + AUTOACK enabled */
group-Avnet 0:478cfd88041f 501 mStatusAndControlRegs[PHY_CTRL1] = cPHY_CTRL1_AUTOACK;
group-Avnet 0:478cfd88041f 502 /* PHY_CTRL2 : mask all PP interrupts */
group-Avnet 0:478cfd88041f 503 mStatusAndControlRegs[PHY_CTRL2] = cPHY_CTRL2_CRC_MSK | \
group-Avnet 0:478cfd88041f 504 cPHY_CTRL2_PLL_UNLOCK_MSK | \
group-Avnet 0:478cfd88041f 505 /*cPHY_CTRL2_FILTERFAIL_MSK | */ \
group-Avnet 0:478cfd88041f 506 cPHY_CTRL2_RX_WMRK_MSK | \
group-Avnet 0:478cfd88041f 507 cPHY_CTRL2_CCAMSK | \
group-Avnet 0:478cfd88041f 508 cPHY_CTRL2_RXMSK | \
group-Avnet 0:478cfd88041f 509 cPHY_CTRL2_TXMSK | \
group-Avnet 0:478cfd88041f 510 cPHY_CTRL2_SEQMSK;
group-Avnet 0:478cfd88041f 511 /* PHY_CTRL3 : enable timer 3 and disable remaining interrupts */
group-Avnet 0:478cfd88041f 512 mStatusAndControlRegs[PHY_CTRL3] = cPHY_CTRL3_ASM_MSK | \
group-Avnet 0:478cfd88041f 513 cPHY_CTRL3_PB_ERR_MSK | \
group-Avnet 0:478cfd88041f 514 cPHY_CTRL3_WAKE_MSK | \
group-Avnet 0:478cfd88041f 515 cPHY_CTRL3_TMR3CMP_EN;
group-Avnet 0:478cfd88041f 516 /* PHY_CTRL4 unmask global TRX interrupts, enable 16 bit mode for TC2 - TC2 prime EN */
group-Avnet 0:478cfd88041f 517 mStatusAndControlRegs[PHY_CTRL4] = cPHY_CTRL4_TC2PRIME_EN | (gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c);
group-Avnet 0:478cfd88041f 518 /* Clear all PP IRQ bits to avoid unexpected interrupts immediately after initialization */
group-Avnet 0:478cfd88041f 519 mStatusAndControlRegs[IRQSTS1] = cIRQSTS1_PLL_UNLOCK_IRQ | \
group-Avnet 0:478cfd88041f 520 cIRQSTS1_FILTERFAIL_IRQ | \
group-Avnet 0:478cfd88041f 521 cIRQSTS1_RXWTRMRKIRQ | \
group-Avnet 0:478cfd88041f 522 cIRQSTS1_CCAIRQ | \
group-Avnet 0:478cfd88041f 523 cIRQSTS1_RXIRQ | \
group-Avnet 0:478cfd88041f 524 cIRQSTS1_TXIRQ | \
group-Avnet 0:478cfd88041f 525 cIRQSTS1_SEQIRQ;
group-Avnet 0:478cfd88041f 526
group-Avnet 0:478cfd88041f 527 mStatusAndControlRegs[IRQSTS2] = cIRQSTS2_ASM_IRQ | cIRQSTS2_PB_ERR_IRQ | cIRQSTS2_WAKE_IRQ;
group-Avnet 0:478cfd88041f 528 /* Mask and clear all TMR IRQs */
group-Avnet 0:478cfd88041f 529 mStatusAndControlRegs[IRQSTS3] = cIRQSTS3_TMR4MSK | cIRQSTS3_TMR3MSK | cIRQSTS3_TMR2MSK | cIRQSTS3_TMR1MSK | \
group-Avnet 0:478cfd88041f 530 cIRQSTS3_TMR4IRQ | cIRQSTS3_TMR3IRQ | cIRQSTS3_TMR2IRQ | cIRQSTS3_TMR1IRQ;
group-Avnet 0:478cfd88041f 531 /* Write settings to XCVR */
group-Avnet 0:478cfd88041f 532 MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 5);
group-Avnet 0:478cfd88041f 533 /* Clear all interrupts */
group-Avnet 0:478cfd88041f 534 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, &mStatusAndControlRegs[IRQSTS1], 3);
group-Avnet 0:478cfd88041f 535
group-Avnet 0:478cfd88041f 536 /* RX_FRAME_FILTER. Accept FrameVersion 0 and 1 packets, reject all others */
group-Avnet 0:478cfd88041f 537 MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, (cRX_FRAME_FLT_FRM_VER | \
group-Avnet 0:478cfd88041f 538 cRX_FRAME_FLT_BEACON_FT | \
group-Avnet 0:478cfd88041f 539 cRX_FRAME_FLT_DATA_FT | \
group-Avnet 0:478cfd88041f 540 cRX_FRAME_FLT_CMD_FT ));
group-Avnet 0:478cfd88041f 541 /* Direct register overwrites */
group-Avnet 0:478cfd88041f 542 for (index = 0; index < sizeof(overwrites_direct)/sizeof(overwrites_t); index++)
group-Avnet 0:478cfd88041f 543 MCR20Drv_DirectAccessSPIWrite(overwrites_direct[index].address, overwrites_direct[index].data);
group-Avnet 0:478cfd88041f 544 /* Indirect register overwrites */
group-Avnet 0:478cfd88041f 545 for (index = 0; index < sizeof(overwrites_indirect)/sizeof(overwrites_t); index++)
group-Avnet 0:478cfd88041f 546 MCR20Drv_IndirectAccessSPIWrite(overwrites_indirect[index].address, overwrites_indirect[index].data);
group-Avnet 0:478cfd88041f 547
group-Avnet 0:478cfd88041f 548 /* Set the CCA energy threshold value */
group-Avnet 0:478cfd88041f 549 MCR20Drv_IndirectAccessSPIWrite(CCA1_THRESH, RF_CCA_THRESHOLD);
group-Avnet 0:478cfd88041f 550 /* Set prescaller to obtain 1 symbol (16us) timebase */
group-Avnet 0:478cfd88041f 551 MCR20Drv_IndirectAccessSPIWrite(TMR_PRESCALE, 0x05);
group-Avnet 0:478cfd88041f 552
group-Avnet 0:478cfd88041f 553 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 554
group-Avnet 0:478cfd88041f 555 /*Read random variable. This will be used when seeding pseudo-random generator*/
group-Avnet 0:478cfd88041f 556 rf_rnd = rf_if_read_rnd();
group-Avnet 0:478cfd88041f 557 /*Read eui64*/
group-Avnet 0:478cfd88041f 558 rf_mac64_read(MAC_address);
group-Avnet 0:478cfd88041f 559 /*set default channel to 11*/
group-Avnet 0:478cfd88041f 560 rf_channel_set(11);
group-Avnet 0:478cfd88041f 561 /*Start receiver*/
group-Avnet 0:478cfd88041f 562 rf_receive();
group-Avnet 0:478cfd88041f 563 }
group-Avnet 0:478cfd88041f 564
group-Avnet 0:478cfd88041f 565 /**
group-Avnet 0:478cfd88041f 566 * \brief Function gets called when MAC is setting radio off.
group-Avnet 0:478cfd88041f 567 *
group-Avnet 0:478cfd88041f 568 * \param none
group-Avnet 0:478cfd88041f 569 *
group-Avnet 0:478cfd88041f 570 * \return none
group-Avnet 0:478cfd88041f 571 */
group-Avnet 0:478cfd88041f 572 static void rf_off(void)
group-Avnet 0:478cfd88041f 573 {
group-Avnet 0:478cfd88041f 574 /* Abort any ongoing sequences */
group-Avnet 0:478cfd88041f 575 rf_abort();
group-Avnet 0:478cfd88041f 576 /* Set XCVR in a low power state */
group-Avnet 0:478cfd88041f 577 rf_set_power_state(gXcvrLowPowerState_d);
group-Avnet 0:478cfd88041f 578 }
group-Avnet 0:478cfd88041f 579
group-Avnet 0:478cfd88041f 580 /*
group-Avnet 0:478cfd88041f 581 * \brief Function polls the RF state until it has changed to desired state.
group-Avnet 0:478cfd88041f 582 *
group-Avnet 0:478cfd88041f 583 * \param trx_state RF state
group-Avnet 0:478cfd88041f 584 *
group-Avnet 0:478cfd88041f 585 * \return none
group-Avnet 0:478cfd88041f 586 */
group-Avnet 0:478cfd88041f 587 static void rf_poll_trx_state_change(rf_trx_states_t trx_state)
group-Avnet 0:478cfd88041f 588 {
group-Avnet 0:478cfd88041f 589 (void)trx_state;
group-Avnet 0:478cfd88041f 590 }
group-Avnet 0:478cfd88041f 591
group-Avnet 0:478cfd88041f 592 /*
group-Avnet 0:478cfd88041f 593 * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO.
group-Avnet 0:478cfd88041f 594 *
group-Avnet 0:478cfd88041f 595 * \param data_ptr Pointer to TX data
group-Avnet 0:478cfd88041f 596 * \param data_length Length of the TX data
group-Avnet 0:478cfd88041f 597 * \param tx_handle Handle to transmission
group-Avnet 0:478cfd88041f 598 * \return 0 Success
group-Avnet 0:478cfd88041f 599 * \return -1 Busy
group-Avnet 0:478cfd88041f 600 */
group-Avnet 0:478cfd88041f 601 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 602 {
group-Avnet 0:478cfd88041f 603 uint8_t ccaMode;
group-Avnet 0:478cfd88041f 604
group-Avnet 0:478cfd88041f 605 /* Parameter validation */
group-Avnet 0:478cfd88041f 606 if( !data_ptr || (data_length > 125) || (PHY_LAYER_PAYLOAD != data_protocol) )
group-Avnet 0:478cfd88041f 607 {
group-Avnet 0:478cfd88041f 608 return -1;
group-Avnet 0:478cfd88041f 609 }
group-Avnet 0:478cfd88041f 610
group-Avnet 0:478cfd88041f 611 if( mPhySeqState == gRX_c )
group-Avnet 0:478cfd88041f 612 {
group-Avnet 0:478cfd88041f 613 uint8_t phyReg = MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F;
group-Avnet 0:478cfd88041f 614 /* Check for an Rx in progress. */
group-Avnet 0:478cfd88041f 615 if((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16))
group-Avnet 0:478cfd88041f 616 {
group-Avnet 0:478cfd88041f 617 if (device_driver.phy_tx_done_cb) {
group-Avnet 0:478cfd88041f 618 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
group-Avnet 0:478cfd88041f 619 }
group-Avnet 0:478cfd88041f 620 return -1;
group-Avnet 0:478cfd88041f 621 }
group-Avnet 0:478cfd88041f 622 rf_abort();
group-Avnet 0:478cfd88041f 623 }
group-Avnet 0:478cfd88041f 624
group-Avnet 0:478cfd88041f 625 /*Check if transmitter is busy*/
group-Avnet 0:478cfd88041f 626 if( mPhySeqState != gIdle_c )
group-Avnet 0:478cfd88041f 627 {
group-Avnet 0:478cfd88041f 628 /*Return busy*/
group-Avnet 0:478cfd88041f 629 return -1;
group-Avnet 0:478cfd88041f 630 }
group-Avnet 0:478cfd88041f 631
group-Avnet 0:478cfd88041f 632 /*Store TX handle*/
group-Avnet 0:478cfd88041f 633 mac_tx_handle = tx_handle;
group-Avnet 0:478cfd88041f 634 /*Check if transmitted data needs to be acked*/
group-Avnet 0:478cfd88041f 635 need_ack = (*data_ptr & 0x20) == 0x20;
group-Avnet 0:478cfd88041f 636
group-Avnet 0:478cfd88041f 637 /* Set XCVR power state in run mode */
group-Avnet 0:478cfd88041f 638 rf_set_power_state(gXcvrRunState_d);
group-Avnet 0:478cfd88041f 639 /* Load data into XCVR */
group-Avnet 0:478cfd88041f 640 tx_len = data_length + 2;
group-Avnet 0:478cfd88041f 641 MCR20Drv_PB_SPIBurstWrite(data_ptr - 1, data_length + 1);
group-Avnet 0:478cfd88041f 642 MCR20Drv_PB_SPIByteWrite(0,tx_len);
group-Avnet 0:478cfd88041f 643
group-Avnet 0:478cfd88041f 644 /* Set CCA mode 1 */
group-Avnet 0:478cfd88041f 645 ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE;
group-Avnet 0:478cfd88041f 646 if( ccaMode != gCcaCCA_MODE1_c )
group-Avnet 0:478cfd88041f 647 {
group-Avnet 0:478cfd88041f 648 mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c);
group-Avnet 0:478cfd88041f 649 mStatusAndControlRegs[PHY_CTRL4] |= gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c;
group-Avnet 0:478cfd88041f 650 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]);
group-Avnet 0:478cfd88041f 651 }
group-Avnet 0:478cfd88041f 652
group-Avnet 0:478cfd88041f 653 /* Read XCVR registers */
group-Avnet 0:478cfd88041f 654 mStatusAndControlRegs[0] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[1], 4);
group-Avnet 0:478cfd88041f 655 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
group-Avnet 0:478cfd88041f 656 mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c;
group-Avnet 0:478cfd88041f 657 mPhySeqState = gCCA_c;
group-Avnet 0:478cfd88041f 658
group-Avnet 0:478cfd88041f 659 /* Ensure that no spurious interrupts are raised */
group-Avnet 0:478cfd88041f 660 mStatusAndControlRegs[IRQSTS3] &= 0xF0; /* do not change other IRQ status */
group-Avnet 0:478cfd88041f 661 mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ);
group-Avnet 0:478cfd88041f 662 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
group-Avnet 0:478cfd88041f 663
group-Avnet 0:478cfd88041f 664 /* Write XCVR settings */
group-Avnet 0:478cfd88041f 665 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
group-Avnet 0:478cfd88041f 666
group-Avnet 0:478cfd88041f 667 /* Unmask SEQ interrupt */
group-Avnet 0:478cfd88041f 668 mStatusAndControlRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
group-Avnet 0:478cfd88041f 669 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]);
group-Avnet 0:478cfd88041f 670
group-Avnet 0:478cfd88041f 671 /*Return success*/
group-Avnet 0:478cfd88041f 672 return 0;
group-Avnet 0:478cfd88041f 673 }
group-Avnet 0:478cfd88041f 674
group-Avnet 0:478cfd88041f 675 /*
group-Avnet 0:478cfd88041f 676 * \brief Function aborts CCA process.
group-Avnet 0:478cfd88041f 677 *
group-Avnet 0:478cfd88041f 678 * \param none
group-Avnet 0:478cfd88041f 679 *
group-Avnet 0:478cfd88041f 680 * \return none
group-Avnet 0:478cfd88041f 681 */
group-Avnet 0:478cfd88041f 682 static void rf_cca_abort(void)
group-Avnet 0:478cfd88041f 683 {
group-Avnet 0:478cfd88041f 684 rf_abort();
group-Avnet 0:478cfd88041f 685 }
group-Avnet 0:478cfd88041f 686
group-Avnet 0:478cfd88041f 687 /*
group-Avnet 0:478cfd88041f 688 * \brief Function starts the transmission of the frame. Called from ISR context!
group-Avnet 0:478cfd88041f 689 *
group-Avnet 0:478cfd88041f 690 * \param none
group-Avnet 0:478cfd88041f 691 *
group-Avnet 0:478cfd88041f 692 * \return none
group-Avnet 0:478cfd88041f 693 */
group-Avnet 0:478cfd88041f 694 static void rf_start_tx(void)
group-Avnet 0:478cfd88041f 695 {
group-Avnet 0:478cfd88041f 696 /* Perform TxRxAck sequence if required by phyTxMode */
group-Avnet 0:478cfd88041f 697 if( need_ack )
group-Avnet 0:478cfd88041f 698 {
group-Avnet 0:478cfd88041f 699 mStatusAndControlRegs[PHY_CTRL1] |= cPHY_CTRL1_RXACKRQD;
group-Avnet 0:478cfd88041f 700 mPhySeqState = gTR_c;
group-Avnet 0:478cfd88041f 701 }
group-Avnet 0:478cfd88041f 702 else
group-Avnet 0:478cfd88041f 703 {
group-Avnet 0:478cfd88041f 704 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_RXACKRQD);
group-Avnet 0:478cfd88041f 705 mPhySeqState = gTX_c;
group-Avnet 0:478cfd88041f 706 }
group-Avnet 0:478cfd88041f 707
group-Avnet 0:478cfd88041f 708 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
group-Avnet 0:478cfd88041f 709 mStatusAndControlRegs[PHY_CTRL1] |= mPhySeqState;
group-Avnet 0:478cfd88041f 710
group-Avnet 0:478cfd88041f 711 /* Unmask SEQ interrupt */
group-Avnet 0:478cfd88041f 712 mStatusAndControlRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
group-Avnet 0:478cfd88041f 713
group-Avnet 0:478cfd88041f 714 /* Start the sequence immediately */
group-Avnet 0:478cfd88041f 715 MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 2);
group-Avnet 0:478cfd88041f 716
group-Avnet 0:478cfd88041f 717 if( need_ack )
group-Avnet 0:478cfd88041f 718 {
group-Avnet 0:478cfd88041f 719 rf_ack_wait_timer_start(gPhyWarmUpTime_c + gPhySHRDuration_c + tx_len * gPhySymbolsPerOctet_c + gPhyAckWaitDuration_c);
group-Avnet 0:478cfd88041f 720 }
group-Avnet 0:478cfd88041f 721 }
group-Avnet 0:478cfd88041f 722
group-Avnet 0:478cfd88041f 723 /*
group-Avnet 0:478cfd88041f 724 * \brief Function sets the RF in RX state. Called from ISR context!
group-Avnet 0:478cfd88041f 725 *
group-Avnet 0:478cfd88041f 726 * \param none
group-Avnet 0:478cfd88041f 727 *
group-Avnet 0:478cfd88041f 728 * \return none
group-Avnet 0:478cfd88041f 729 */
group-Avnet 0:478cfd88041f 730 static void rf_receive(void)
group-Avnet 0:478cfd88041f 731 {
group-Avnet 0:478cfd88041f 732 uint8_t phyRegs[5];
group-Avnet 0:478cfd88041f 733
group-Avnet 0:478cfd88041f 734 /* RX can start only from Idle state */
group-Avnet 0:478cfd88041f 735 if( mPhySeqState != gIdle_c )
group-Avnet 0:478cfd88041f 736 {
group-Avnet 0:478cfd88041f 737 return;
group-Avnet 0:478cfd88041f 738 }
group-Avnet 0:478cfd88041f 739
group-Avnet 0:478cfd88041f 740 /* Set XCVR power state in run mode */
group-Avnet 0:478cfd88041f 741 rf_set_power_state(gXcvrRunState_d);
group-Avnet 0:478cfd88041f 742 /* read XVCR settings */
group-Avnet 0:478cfd88041f 743 phyRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &phyRegs[IRQSTS2], 4);
group-Avnet 0:478cfd88041f 744 /* unmask SEQ interrupt */
group-Avnet 0:478cfd88041f 745 phyRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
group-Avnet 0:478cfd88041f 746 /* set XcvrSeq to RX */
group-Avnet 0:478cfd88041f 747 phyRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
group-Avnet 0:478cfd88041f 748 phyRegs[PHY_CTRL1] |= gRX_c;
group-Avnet 0:478cfd88041f 749 mPhySeqState = gRX_c;
group-Avnet 0:478cfd88041f 750 /* Ensure that no spurious interrupts are raised */
group-Avnet 0:478cfd88041f 751 phyRegs[IRQSTS3] &= 0xF0; /* do not change other IRQ status */
group-Avnet 0:478cfd88041f 752 phyRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ;
group-Avnet 0:478cfd88041f 753 /* sync settings with XCVR */
group-Avnet 0:478cfd88041f 754 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, phyRegs, 5);
group-Avnet 0:478cfd88041f 755 }
group-Avnet 0:478cfd88041f 756
group-Avnet 0:478cfd88041f 757 /*
group-Avnet 0:478cfd88041f 758 * \brief Function calibrates the radio.
group-Avnet 0:478cfd88041f 759 *
group-Avnet 0:478cfd88041f 760 * \param none
group-Avnet 0:478cfd88041f 761 *
group-Avnet 0:478cfd88041f 762 * \return none
group-Avnet 0:478cfd88041f 763 */
group-Avnet 0:478cfd88041f 764 static void rf_calibration_cb(void)
group-Avnet 0:478cfd88041f 765 {
group-Avnet 0:478cfd88041f 766 }
group-Avnet 0:478cfd88041f 767
group-Avnet 0:478cfd88041f 768 /*
group-Avnet 0:478cfd88041f 769 * \brief Function sets RF_ON flag when radio is powered.
group-Avnet 0:478cfd88041f 770 *
group-Avnet 0:478cfd88041f 771 * \param none
group-Avnet 0:478cfd88041f 772 *
group-Avnet 0:478cfd88041f 773 * \return none
group-Avnet 0:478cfd88041f 774 */
group-Avnet 0:478cfd88041f 775 static void rf_on(void)
group-Avnet 0:478cfd88041f 776 {
group-Avnet 0:478cfd88041f 777 }
group-Avnet 0:478cfd88041f 778
group-Avnet 0:478cfd88041f 779 /*
group-Avnet 0:478cfd88041f 780 * \brief Function is a call back for RX end interrupt.
group-Avnet 0:478cfd88041f 781 *
group-Avnet 0:478cfd88041f 782 * \param none
group-Avnet 0:478cfd88041f 783 *
group-Avnet 0:478cfd88041f 784 * \return none
group-Avnet 0:478cfd88041f 785 */
group-Avnet 0:478cfd88041f 786 static void rf_handle_rx_end(void)
group-Avnet 0:478cfd88041f 787 {
group-Avnet 0:478cfd88041f 788 uint8_t rf_lqi = MCR20Drv_DirectAccessSPIRead(LQI_VALUE);
group-Avnet 0:478cfd88041f 789 int8_t rf_rssi = 0;
group-Avnet 0:478cfd88041f 790 uint8_t len = mStatusAndControlRegs[RX_FRM_LEN] - 2;
group-Avnet 0:478cfd88041f 791
group-Avnet 0:478cfd88041f 792
group-Avnet 0:478cfd88041f 793 /*Start receiver*/
group-Avnet 0:478cfd88041f 794 rf_receive();
group-Avnet 0:478cfd88041f 795
group-Avnet 0:478cfd88041f 796 /*Check the length is valid*/
group-Avnet 0:478cfd88041f 797 if(len > 1 && len < RF_BUFFER_SIZE)
group-Avnet 0:478cfd88041f 798 {
group-Avnet 0:478cfd88041f 799 rf_lqi = rf_convert_LQI(rf_lqi);
group-Avnet 0:478cfd88041f 800 rf_rssi = rf_convert_LQI_to_RSSI(rf_lqi);
group-Avnet 0:478cfd88041f 801 /*gcararu: Scale LQI using received RSSI, to match the LQI reported by the ATMEL radio */
group-Avnet 0:478cfd88041f 802 rf_lqi = rf_scale_lqi(rf_rssi);
group-Avnet 0:478cfd88041f 803
group-Avnet 0:478cfd88041f 804 /*Read received packet*/
group-Avnet 0:478cfd88041f 805 MCR20Drv_PB_SPIBurstRead(rf_buffer, len);
group-Avnet 0:478cfd88041f 806 if (device_driver.phy_rx_cb) {
group-Avnet 0:478cfd88041f 807 device_driver.phy_rx_cb(rf_buffer, len, rf_lqi, rf_rssi, rf_radio_driver_id);
group-Avnet 0:478cfd88041f 808 }
group-Avnet 0:478cfd88041f 809 }
group-Avnet 0:478cfd88041f 810 }
group-Avnet 0:478cfd88041f 811
group-Avnet 0:478cfd88041f 812 /*
group-Avnet 0:478cfd88041f 813 * \brief Function is called when MAC is shutting down the radio.
group-Avnet 0:478cfd88041f 814 *
group-Avnet 0:478cfd88041f 815 * \param none
group-Avnet 0:478cfd88041f 816 *
group-Avnet 0:478cfd88041f 817 * \return none
group-Avnet 0:478cfd88041f 818 */
group-Avnet 0:478cfd88041f 819 static void rf_shutdown(void)
group-Avnet 0:478cfd88041f 820 {
group-Avnet 0:478cfd88041f 821 /*Call RF OFF*/
group-Avnet 0:478cfd88041f 822 rf_off();
group-Avnet 0:478cfd88041f 823 }
group-Avnet 0:478cfd88041f 824
group-Avnet 0:478cfd88041f 825 /*
group-Avnet 0:478cfd88041f 826 * \brief Function is a call back for TX end interrupt.
group-Avnet 0:478cfd88041f 827 *
group-Avnet 0:478cfd88041f 828 * \param none
group-Avnet 0:478cfd88041f 829 *
group-Avnet 0:478cfd88041f 830 * \return none
group-Avnet 0:478cfd88041f 831 */
group-Avnet 0:478cfd88041f 832 static void rf_handle_tx_end(void)
group-Avnet 0:478cfd88041f 833 {
group-Avnet 0:478cfd88041f 834 uint8_t rx_frame_pending = mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_RX_FRM_PEND;
group-Avnet 0:478cfd88041f 835
group-Avnet 0:478cfd88041f 836 /*Start receiver*/
group-Avnet 0:478cfd88041f 837 rf_receive();
group-Avnet 0:478cfd88041f 838
group-Avnet 0:478cfd88041f 839 if (!device_driver.phy_tx_done_cb) {
group-Avnet 0:478cfd88041f 840 return;
group-Avnet 0:478cfd88041f 841 }
group-Avnet 0:478cfd88041f 842
group-Avnet 0:478cfd88041f 843 /*Call PHY TX Done API*/
group-Avnet 0:478cfd88041f 844 if( need_ack )
group-Avnet 0:478cfd88041f 845 {
group-Avnet 0:478cfd88041f 846 if( rx_frame_pending )
group-Avnet 0:478cfd88041f 847 {
group-Avnet 0:478cfd88041f 848 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE_PENDING, 1, 1);
group-Avnet 0:478cfd88041f 849 }
group-Avnet 0:478cfd88041f 850 else
group-Avnet 0:478cfd88041f 851 {
group-Avnet 0:478cfd88041f 852 // arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
group-Avnet 0:478cfd88041f 853 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1);
group-Avnet 0:478cfd88041f 854 }
group-Avnet 0:478cfd88041f 855 }
group-Avnet 0:478cfd88041f 856 else
group-Avnet 0:478cfd88041f 857 {
group-Avnet 0:478cfd88041f 858 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
group-Avnet 0:478cfd88041f 859 }
group-Avnet 0:478cfd88041f 860 }
group-Avnet 0:478cfd88041f 861
group-Avnet 0:478cfd88041f 862 /*
group-Avnet 0:478cfd88041f 863 * \brief Function is a call back for CCA ED done interrupt.
group-Avnet 0:478cfd88041f 864 *
group-Avnet 0:478cfd88041f 865 * \param none
group-Avnet 0:478cfd88041f 866 *
group-Avnet 0:478cfd88041f 867 * \return none
group-Avnet 0:478cfd88041f 868 */
group-Avnet 0:478cfd88041f 869 static void rf_handle_cca_ed_done(void)
group-Avnet 0:478cfd88041f 870 {
group-Avnet 0:478cfd88041f 871 /*Check the result of CCA process*/
group-Avnet 0:478cfd88041f 872 if( !(mStatusAndControlRegs[IRQSTS2] & cIRQSTS2_CCA) )
group-Avnet 0:478cfd88041f 873 {
group-Avnet 0:478cfd88041f 874 rf_start_tx();
group-Avnet 0:478cfd88041f 875 }
group-Avnet 0:478cfd88041f 876 else if (device_driver.phy_tx_done_cb)
group-Avnet 0:478cfd88041f 877 {
group-Avnet 0:478cfd88041f 878 /*Send CCA fail notification*/
group-Avnet 0:478cfd88041f 879 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
group-Avnet 0:478cfd88041f 880 }
group-Avnet 0:478cfd88041f 881 }
group-Avnet 0:478cfd88041f 882
group-Avnet 0:478cfd88041f 883 /*
group-Avnet 0:478cfd88041f 884 * \brief Function sets the TX power variable.
group-Avnet 0:478cfd88041f 885 *
group-Avnet 0:478cfd88041f 886 * \param power TX power setting
group-Avnet 0:478cfd88041f 887 *
group-Avnet 0:478cfd88041f 888 * \return 0 Success
group-Avnet 0:478cfd88041f 889 * \return -1 Fail
group-Avnet 0:478cfd88041f 890 */
group-Avnet 0:478cfd88041f 891 static int8_t rf_tx_power_set(uint8_t power)
group-Avnet 0:478cfd88041f 892 {
group-Avnet 0:478cfd88041f 893 /* gcapraru: Map MCR20A Tx power levels over ATMEL values */
group-Avnet 0:478cfd88041f 894 static uint8_t pwrLevelMapping[16] = {25,25,25,24,24,24,23,23,22,22,21,20,19,18,17,14};
group-Avnet 0:478cfd88041f 895
group-Avnet 0:478cfd88041f 896 if( power > 15 )
group-Avnet 0:478cfd88041f 897 {
group-Avnet 0:478cfd88041f 898 return -1;
group-Avnet 0:478cfd88041f 899 }
group-Avnet 0:478cfd88041f 900
group-Avnet 0:478cfd88041f 901 radio_tx_power = power;
group-Avnet 0:478cfd88041f 902 MCR20Drv_DirectAccessSPIWrite(PA_PWR, pwrLevelMapping[power]);
group-Avnet 0:478cfd88041f 903 return 0;
group-Avnet 0:478cfd88041f 904 }
group-Avnet 0:478cfd88041f 905
group-Avnet 0:478cfd88041f 906 /*
group-Avnet 0:478cfd88041f 907 * \brief Function returns the TX power variable.
group-Avnet 0:478cfd88041f 908 *
group-Avnet 0:478cfd88041f 909 * \param none
group-Avnet 0:478cfd88041f 910 *
group-Avnet 0:478cfd88041f 911 * \return radio_tx_power TX power variable
group-Avnet 0:478cfd88041f 912 */
group-Avnet 0:478cfd88041f 913 static uint8_t rf_tx_power_get(void)
group-Avnet 0:478cfd88041f 914 {
group-Avnet 0:478cfd88041f 915 return radio_tx_power;
group-Avnet 0:478cfd88041f 916 }
group-Avnet 0:478cfd88041f 917
group-Avnet 0:478cfd88041f 918 /*
group-Avnet 0:478cfd88041f 919 * \brief Function enables the usage of Antenna diversity.
group-Avnet 0:478cfd88041f 920 *
group-Avnet 0:478cfd88041f 921 * \param none
group-Avnet 0:478cfd88041f 922 *
group-Avnet 0:478cfd88041f 923 * \return 0 Success
group-Avnet 0:478cfd88041f 924 */
group-Avnet 0:478cfd88041f 925 static int8_t rf_enable_antenna_diversity(void)
group-Avnet 0:478cfd88041f 926 {
group-Avnet 0:478cfd88041f 927 uint8_t phyReg;
group-Avnet 0:478cfd88041f 928
group-Avnet 0:478cfd88041f 929 phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_AGC_CTRL);
group-Avnet 0:478cfd88041f 930 phyReg |= cANT_AGC_CTRL_FAD_EN_Mask_c;
group-Avnet 0:478cfd88041f 931 MCR20Drv_IndirectAccessSPIWrite(ANT_AGC_CTRL, phyReg);
group-Avnet 0:478cfd88041f 932
group-Avnet 0:478cfd88041f 933 phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_PAD_CTRL);
group-Avnet 0:478cfd88041f 934 phyReg |= 0x02;
group-Avnet 0:478cfd88041f 935 MCR20Drv_IndirectAccessSPIWrite(ANT_PAD_CTRL, phyReg);
group-Avnet 0:478cfd88041f 936
group-Avnet 0:478cfd88041f 937 return 0;
group-Avnet 0:478cfd88041f 938 }
group-Avnet 0:478cfd88041f 939
group-Avnet 0:478cfd88041f 940 /*
group-Avnet 0:478cfd88041f 941 * \brief Function gives the control of RF states to MAC.
group-Avnet 0:478cfd88041f 942 *
group-Avnet 0:478cfd88041f 943 * \param new_state RF state
group-Avnet 0:478cfd88041f 944 * \param rf_channel RF channel
group-Avnet 0:478cfd88041f 945 *
group-Avnet 0:478cfd88041f 946 * \return 0 Success
group-Avnet 0:478cfd88041f 947 */
group-Avnet 0:478cfd88041f 948 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
group-Avnet 0:478cfd88041f 949 {
group-Avnet 0:478cfd88041f 950 int8_t ret_val = 0;
group-Avnet 0:478cfd88041f 951 switch (new_state)
group-Avnet 0:478cfd88041f 952 {
group-Avnet 0:478cfd88041f 953 /*Reset PHY driver and set to idle*/
group-Avnet 0:478cfd88041f 954 case PHY_INTERFACE_RESET:
group-Avnet 0:478cfd88041f 955 break;
group-Avnet 0:478cfd88041f 956 /*Disable PHY Interface driver*/
group-Avnet 0:478cfd88041f 957 case PHY_INTERFACE_DOWN:
group-Avnet 0:478cfd88041f 958 rf_shutdown();
group-Avnet 0:478cfd88041f 959 break;
group-Avnet 0:478cfd88041f 960 /*Enable PHY Interface driver*/
group-Avnet 0:478cfd88041f 961 case PHY_INTERFACE_UP:
group-Avnet 0:478cfd88041f 962 rf_channel_set(rf_channel);
group-Avnet 0:478cfd88041f 963 rf_receive();
group-Avnet 0:478cfd88041f 964 break;
group-Avnet 0:478cfd88041f 965 /*Enable wireless interface ED scan mode*/
group-Avnet 0:478cfd88041f 966 case PHY_INTERFACE_RX_ENERGY_STATE:
group-Avnet 0:478cfd88041f 967 rf_abort();
group-Avnet 0:478cfd88041f 968 rf_channel_set(rf_channel);
group-Avnet 0:478cfd88041f 969 break;
group-Avnet 0:478cfd88041f 970 case PHY_INTERFACE_SNIFFER_STATE: /**< Enable Sniffer state */
group-Avnet 0:478cfd88041f 971 rf_promiscuous(1);
group-Avnet 0:478cfd88041f 972 rf_channel_set(rf_channel);
group-Avnet 0:478cfd88041f 973 rf_receive();
group-Avnet 0:478cfd88041f 974 break;
group-Avnet 0:478cfd88041f 975 }
group-Avnet 0:478cfd88041f 976 return ret_val;
group-Avnet 0:478cfd88041f 977 }
group-Avnet 0:478cfd88041f 978
group-Avnet 0:478cfd88041f 979 /*
group-Avnet 0:478cfd88041f 980 * \brief Function controls the ACK pending, channel setting and energy detection.
group-Avnet 0:478cfd88041f 981 *
group-Avnet 0:478cfd88041f 982 * \param extension_type Type of control
group-Avnet 0:478cfd88041f 983 * \param data_ptr Data from NET library
group-Avnet 0:478cfd88041f 984 *
group-Avnet 0:478cfd88041f 985 * \return 0 Success
group-Avnet 0:478cfd88041f 986 */
group-Avnet 0:478cfd88041f 987 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
group-Avnet 0:478cfd88041f 988 {
group-Avnet 0:478cfd88041f 989 switch (extension_type)
group-Avnet 0:478cfd88041f 990 {
group-Avnet 0:478cfd88041f 991 /*Control MAC pending bit for Indirect data transmission*/
group-Avnet 0:478cfd88041f 992 case PHY_EXTENSION_CTRL_PENDING_BIT:
group-Avnet 0:478cfd88041f 993 {
group-Avnet 0:478cfd88041f 994 uint8_t reg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
group-Avnet 0:478cfd88041f 995
group-Avnet 0:478cfd88041f 996 if(*data_ptr)
group-Avnet 0:478cfd88041f 997 {
group-Avnet 0:478cfd88041f 998 reg |= cSRC_CTRL_ACK_FRM_PND;
group-Avnet 0:478cfd88041f 999 }
group-Avnet 0:478cfd88041f 1000 else
group-Avnet 0:478cfd88041f 1001 {
group-Avnet 0:478cfd88041f 1002 reg &= ~cSRC_CTRL_ACK_FRM_PND;
group-Avnet 0:478cfd88041f 1003 }
group-Avnet 0:478cfd88041f 1004
group-Avnet 0:478cfd88041f 1005 MCR20Drv_DirectAccessSPIWrite(SRC_CTRL, reg);
group-Avnet 0:478cfd88041f 1006 break;
group-Avnet 0:478cfd88041f 1007
group-Avnet 0:478cfd88041f 1008 }
group-Avnet 0:478cfd88041f 1009 /*Return frame pending status*/
group-Avnet 0:478cfd88041f 1010 case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
group-Avnet 0:478cfd88041f 1011 *data_ptr = MCR20Drv_DirectAccessSPIRead(IRQSTS1 & cIRQSTS1_RX_FRM_PEND);
group-Avnet 0:478cfd88041f 1012 break;
group-Avnet 0:478cfd88041f 1013 /*Set channel*/
group-Avnet 0:478cfd88041f 1014 case PHY_EXTENSION_SET_CHANNEL:
group-Avnet 0:478cfd88041f 1015 break;
group-Avnet 0:478cfd88041f 1016 /*Read energy on the channel*/
group-Avnet 0:478cfd88041f 1017 case PHY_EXTENSION_READ_CHANNEL_ENERGY:
group-Avnet 0:478cfd88041f 1018 *data_ptr = rf_get_channel_energy();
group-Avnet 0:478cfd88041f 1019 break;
group-Avnet 0:478cfd88041f 1020 /*Read status of the link*/
group-Avnet 0:478cfd88041f 1021 case PHY_EXTENSION_READ_LINK_STATUS:
group-Avnet 0:478cfd88041f 1022 break;
group-Avnet 0:478cfd88041f 1023 case PHY_EXTENSION_CONVERT_SIGNAL_INFO:
group-Avnet 0:478cfd88041f 1024 break;
group-Avnet 0:478cfd88041f 1025 }
group-Avnet 0:478cfd88041f 1026 return 0;
group-Avnet 0:478cfd88041f 1027 }
group-Avnet 0:478cfd88041f 1028
group-Avnet 0:478cfd88041f 1029 /*
group-Avnet 0:478cfd88041f 1030 * \brief Function sets the addresses to RF address filters.
group-Avnet 0:478cfd88041f 1031 *
group-Avnet 0:478cfd88041f 1032 * \param address_type Type of address
group-Avnet 0:478cfd88041f 1033 * \param address_ptr Pointer to given address
group-Avnet 0:478cfd88041f 1034 *
group-Avnet 0:478cfd88041f 1035 * \return 0 Success
group-Avnet 0:478cfd88041f 1036 */
group-Avnet 0:478cfd88041f 1037 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
group-Avnet 0:478cfd88041f 1038 {
group-Avnet 0:478cfd88041f 1039 int8_t ret_val = 0;
group-Avnet 0:478cfd88041f 1040 switch (address_type)
group-Avnet 0:478cfd88041f 1041 {
group-Avnet 0:478cfd88041f 1042 /*Set 48-bit address*/
group-Avnet 0:478cfd88041f 1043 case PHY_MAC_48BIT:
group-Avnet 0:478cfd88041f 1044 break;
group-Avnet 0:478cfd88041f 1045 /*Set 64-bit address*/
group-Avnet 0:478cfd88041f 1046 case PHY_MAC_64BIT:
group-Avnet 0:478cfd88041f 1047 rf_set_address(address_ptr);
group-Avnet 0:478cfd88041f 1048 break;
group-Avnet 0:478cfd88041f 1049 /*Set 16-bit address*/
group-Avnet 0:478cfd88041f 1050 case PHY_MAC_16BIT:
group-Avnet 0:478cfd88041f 1051 rf_set_short_adr(address_ptr);
group-Avnet 0:478cfd88041f 1052 break;
group-Avnet 0:478cfd88041f 1053 /*Set PAN Id*/
group-Avnet 0:478cfd88041f 1054 case PHY_MAC_PANID:
group-Avnet 0:478cfd88041f 1055 rf_set_pan_id(address_ptr);
group-Avnet 0:478cfd88041f 1056 break;
group-Avnet 0:478cfd88041f 1057 }
group-Avnet 0:478cfd88041f 1058 return ret_val;
group-Avnet 0:478cfd88041f 1059 }
group-Avnet 0:478cfd88041f 1060
group-Avnet 0:478cfd88041f 1061 static void rf_mac64_read(uint8_t *address)
group-Avnet 0:478cfd88041f 1062 {
group-Avnet 0:478cfd88041f 1063 /* Write one register at a time to be accessible from hibernate mode */
group-Avnet 0:478cfd88041f 1064 address[7] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_0);
group-Avnet 0:478cfd88041f 1065 address[6] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_8);
group-Avnet 0:478cfd88041f 1066 address[5] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_16);
group-Avnet 0:478cfd88041f 1067 address[4] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_24);
group-Avnet 0:478cfd88041f 1068 address[3] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_32);
group-Avnet 0:478cfd88041f 1069 address[2] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_40);
group-Avnet 0:478cfd88041f 1070 address[1] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_48);
group-Avnet 0:478cfd88041f 1071 address[0] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_56);
group-Avnet 0:478cfd88041f 1072
group-Avnet 0:478cfd88041f 1073 }
group-Avnet 0:478cfd88041f 1074
group-Avnet 0:478cfd88041f 1075 /*
group-Avnet 0:478cfd88041f 1076 * \brief Function initialises the ACK wait time and returns the used PHY mode.
group-Avnet 0:478cfd88041f 1077 *
group-Avnet 0:478cfd88041f 1078 * \param none
group-Avnet 0:478cfd88041f 1079 *
group-Avnet 0:478cfd88041f 1080 * \return tmp Used PHY mode
group-Avnet 0:478cfd88041f 1081 */
group-Avnet 0:478cfd88041f 1082 static void rf_init_phy_mode(void)
group-Avnet 0:478cfd88041f 1083 {
group-Avnet 0:478cfd88041f 1084 }
group-Avnet 0:478cfd88041f 1085
group-Avnet 0:478cfd88041f 1086 /*
group-Avnet 0:478cfd88041f 1087 * \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 1088 *
group-Avnet 0:478cfd88041f 1089 * \param none
group-Avnet 0:478cfd88041f 1090 *
group-Avnet 0:478cfd88041f 1091 * \return none
group-Avnet 0:478cfd88041f 1092 */
group-Avnet 0:478cfd88041f 1093 static void PHY_InterruptHandler(void)
group-Avnet 0:478cfd88041f 1094 {
group-Avnet 0:478cfd88041f 1095 uint8_t xcvseqCopy;
group-Avnet 0:478cfd88041f 1096
group-Avnet 0:478cfd88041f 1097 /* Disable and clear transceiver(IRQ_B) interrupt */
group-Avnet 0:478cfd88041f 1098 MCR20Drv_IRQ_Disable();
group-Avnet 0:478cfd88041f 1099 //MCR20Drv_IRQ_Clear();
group-Avnet 0:478cfd88041f 1100
group-Avnet 0:478cfd88041f 1101 /* Read transceiver interrupt status and control registers */
group-Avnet 0:478cfd88041f 1102 mStatusAndControlRegs[IRQSTS1] =
group-Avnet 0:478cfd88041f 1103 MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 7);
group-Avnet 0:478cfd88041f 1104
group-Avnet 0:478cfd88041f 1105 xcvseqCopy = mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ;
group-Avnet 0:478cfd88041f 1106
group-Avnet 0:478cfd88041f 1107 /* Flter Fail IRQ */
group-Avnet 0:478cfd88041f 1108 if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_FILTERFAIL_IRQ) &&
group-Avnet 0:478cfd88041f 1109 !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_FILTERFAIL_MSK) )
group-Avnet 0:478cfd88041f 1110 {
group-Avnet 0:478cfd88041f 1111 if( xcvseqCopy == gRX_c )
group-Avnet 0:478cfd88041f 1112 {
group-Avnet 0:478cfd88041f 1113 /* Abort current SEQ */
group-Avnet 0:478cfd88041f 1114 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
group-Avnet 0:478cfd88041f 1115 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
group-Avnet 0:478cfd88041f 1116 /* Wait for Sequence Idle */
group-Avnet 0:478cfd88041f 1117 while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
group-Avnet 0:478cfd88041f 1118 /* Clear IRQ flags: */
group-Avnet 0:478cfd88041f 1119 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ);
group-Avnet 0:478cfd88041f 1120 /* Restart Rx asap */
group-Avnet 0:478cfd88041f 1121 mStatusAndControlRegs[PHY_CTRL1] |= gRX_c;
group-Avnet 0:478cfd88041f 1122 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
group-Avnet 0:478cfd88041f 1123 }
group-Avnet 0:478cfd88041f 1124 }
group-Avnet 0:478cfd88041f 1125
group-Avnet 0:478cfd88041f 1126 /* TMR3 IRQ: ACK wait time-out */
group-Avnet 0:478cfd88041f 1127 if( (mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3IRQ) &&
group-Avnet 0:478cfd88041f 1128 !(mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3MSK) )
group-Avnet 0:478cfd88041f 1129 {
group-Avnet 0:478cfd88041f 1130 /* Disable TMR3 IRQ */
group-Avnet 0:478cfd88041f 1131 mStatusAndControlRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK;
group-Avnet 0:478cfd88041f 1132
group-Avnet 0:478cfd88041f 1133 if( xcvseqCopy == gTR_c )
group-Avnet 0:478cfd88041f 1134 {
group-Avnet 0:478cfd88041f 1135 /* Set XCVR to Idle */
group-Avnet 0:478cfd88041f 1136 mPhySeqState = gIdle_c;
group-Avnet 0:478cfd88041f 1137 mStatusAndControlRegs[PHY_CTRL1] &= ~( cPHY_CTRL1_XCVSEQ );
group-Avnet 0:478cfd88041f 1138 /* Mask interrupts */
group-Avnet 0:478cfd88041f 1139 mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK;
group-Avnet 0:478cfd88041f 1140 /* Sync settings with XCVR */
group-Avnet 0:478cfd88041f 1141 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
group-Avnet 0:478cfd88041f 1142
group-Avnet 0:478cfd88041f 1143 rf_ack_wait_timer_interrupt();
group-Avnet 0:478cfd88041f 1144 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1145 return;
group-Avnet 0:478cfd88041f 1146 }
group-Avnet 0:478cfd88041f 1147 }
group-Avnet 0:478cfd88041f 1148
group-Avnet 0:478cfd88041f 1149 /* Sequencer interrupt, the autosequence has completed */
group-Avnet 0:478cfd88041f 1150 if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_SEQIRQ) &&
group-Avnet 0:478cfd88041f 1151 !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_SEQMSK) )
group-Avnet 0:478cfd88041f 1152 {
group-Avnet 0:478cfd88041f 1153 /* Set XCVR to Idle */
group-Avnet 0:478cfd88041f 1154 mPhySeqState = gIdle_c;
group-Avnet 0:478cfd88041f 1155 mStatusAndControlRegs[PHY_CTRL1] &= ~( cPHY_CTRL1_XCVSEQ );
group-Avnet 0:478cfd88041f 1156 /* Mask interrupts */
group-Avnet 0:478cfd88041f 1157 mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK;
group-Avnet 0:478cfd88041f 1158 /* Sync settings with XCVR */
group-Avnet 0:478cfd88041f 1159 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
group-Avnet 0:478cfd88041f 1160
group-Avnet 0:478cfd88041f 1161 /* PLL unlock, the autosequence has been aborted due to PLL unlock */
group-Avnet 0:478cfd88041f 1162 if( mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_PLL_UNLOCK_IRQ )
group-Avnet 0:478cfd88041f 1163 {
group-Avnet 0:478cfd88041f 1164 if(xcvseqCopy == gRX_c)
group-Avnet 0:478cfd88041f 1165 {
group-Avnet 0:478cfd88041f 1166 rf_receive();
group-Avnet 0:478cfd88041f 1167 }
group-Avnet 0:478cfd88041f 1168 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1169 return;
group-Avnet 0:478cfd88041f 1170 }
group-Avnet 0:478cfd88041f 1171
group-Avnet 0:478cfd88041f 1172 switch(xcvseqCopy)
group-Avnet 0:478cfd88041f 1173 {
group-Avnet 0:478cfd88041f 1174 case gTX_c:
group-Avnet 0:478cfd88041f 1175 case gTR_c:
group-Avnet 0:478cfd88041f 1176 rf_handle_tx_end();
group-Avnet 0:478cfd88041f 1177 break;
group-Avnet 0:478cfd88041f 1178
group-Avnet 0:478cfd88041f 1179 case gRX_c:
group-Avnet 0:478cfd88041f 1180 rf_handle_rx_end();
group-Avnet 0:478cfd88041f 1181 break;
group-Avnet 0:478cfd88041f 1182
group-Avnet 0:478cfd88041f 1183 case gCCA_c:
group-Avnet 0:478cfd88041f 1184 rf_handle_cca_ed_done();
group-Avnet 0:478cfd88041f 1185 break;
group-Avnet 0:478cfd88041f 1186
group-Avnet 0:478cfd88041f 1187 default:
group-Avnet 0:478cfd88041f 1188 break;
group-Avnet 0:478cfd88041f 1189 }
group-Avnet 0:478cfd88041f 1190
group-Avnet 0:478cfd88041f 1191 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1192 return;
group-Avnet 0:478cfd88041f 1193 }
group-Avnet 0:478cfd88041f 1194 /* Other IRQ. Clear XCVR interrupt flags */
group-Avnet 0:478cfd88041f 1195 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
group-Avnet 0:478cfd88041f 1196 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1197 }
group-Avnet 0:478cfd88041f 1198
group-Avnet 0:478cfd88041f 1199 /*
group-Avnet 0:478cfd88041f 1200 * \brief Function forces the XCVR to Idle state.
group-Avnet 0:478cfd88041f 1201 *
group-Avnet 0:478cfd88041f 1202 * \param none
group-Avnet 0:478cfd88041f 1203 *
group-Avnet 0:478cfd88041f 1204 * \return none
group-Avnet 0:478cfd88041f 1205 */
group-Avnet 0:478cfd88041f 1206 static void rf_abort(void)
group-Avnet 0:478cfd88041f 1207 {
group-Avnet 0:478cfd88041f 1208 /* Mask XCVR irq */
group-Avnet 0:478cfd88041f 1209 MCR20Drv_IRQ_Disable();
group-Avnet 0:478cfd88041f 1210
group-Avnet 0:478cfd88041f 1211 mPhySeqState = gIdle_c;
group-Avnet 0:478cfd88041f 1212
group-Avnet 0:478cfd88041f 1213 mStatusAndControlRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 5);
group-Avnet 0:478cfd88041f 1214
group-Avnet 0:478cfd88041f 1215 /* Mask SEQ interrupt */
group-Avnet 0:478cfd88041f 1216 mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_SEQMSK;
group-Avnet 0:478cfd88041f 1217 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]);
group-Avnet 0:478cfd88041f 1218
group-Avnet 0:478cfd88041f 1219 if( (mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c )
group-Avnet 0:478cfd88041f 1220 {
group-Avnet 0:478cfd88041f 1221 /* Abort current SEQ */
group-Avnet 0:478cfd88041f 1222 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
group-Avnet 0:478cfd88041f 1223 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
group-Avnet 0:478cfd88041f 1224
group-Avnet 0:478cfd88041f 1225 /* Wait for Sequence Idle (if not already) */
group-Avnet 0:478cfd88041f 1226 while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
group-Avnet 0:478cfd88041f 1227 //while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
group-Avnet 0:478cfd88041f 1228 mStatusAndControlRegs[IRQSTS1] |= cIRQSTS1_SEQIRQ;
group-Avnet 0:478cfd88041f 1229 }
group-Avnet 0:478cfd88041f 1230
group-Avnet 0:478cfd88041f 1231 /* Clear all PP IRQ bits to avoid unexpected interrupts and mask TMR3 interrupt.
group-Avnet 0:478cfd88041f 1232 Do not change TMR IRQ status. */
group-Avnet 0:478cfd88041f 1233 mStatusAndControlRegs[IRQSTS3] &= 0xF0;
group-Avnet 0:478cfd88041f 1234 mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ);
group-Avnet 0:478cfd88041f 1235 MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
group-Avnet 0:478cfd88041f 1236
group-Avnet 0:478cfd88041f 1237 /* Unmask XCVR irq */
group-Avnet 0:478cfd88041f 1238 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1239 }
group-Avnet 0:478cfd88041f 1240
group-Avnet 0:478cfd88041f 1241 /*
group-Avnet 0:478cfd88041f 1242 * \brief Function reads a time-stamp value from XCVR [symbols]
group-Avnet 0:478cfd88041f 1243 *
group-Avnet 0:478cfd88041f 1244 * \param pEndTime pointer to location where time-stamp will be stored
group-Avnet 0:478cfd88041f 1245 *
group-Avnet 0:478cfd88041f 1246 * \return none
group-Avnet 0:478cfd88041f 1247 */
group-Avnet 0:478cfd88041f 1248 static void rf_get_timestamp(uint32_t *pRetClk)
group-Avnet 0:478cfd88041f 1249 {
group-Avnet 0:478cfd88041f 1250 if(NULL == pRetClk)
group-Avnet 0:478cfd88041f 1251 {
group-Avnet 0:478cfd88041f 1252 return;
group-Avnet 0:478cfd88041f 1253 }
group-Avnet 0:478cfd88041f 1254
group-Avnet 0:478cfd88041f 1255 platform_enter_critical();
group-Avnet 0:478cfd88041f 1256
group-Avnet 0:478cfd88041f 1257 *pRetClk = 0;
group-Avnet 0:478cfd88041f 1258 MCR20Drv_DirectAccessSPIMultiByteRead(EVENT_TMR_LSB, (uint8_t *) pRetClk, 3);
group-Avnet 0:478cfd88041f 1259
group-Avnet 0:478cfd88041f 1260 platform_exit_critical();
group-Avnet 0:478cfd88041f 1261 }
group-Avnet 0:478cfd88041f 1262
group-Avnet 0:478cfd88041f 1263 /*
group-Avnet 0:478cfd88041f 1264 * \brief Function set a time-out to an XCVR sequence.
group-Avnet 0:478cfd88041f 1265 *
group-Avnet 0:478cfd88041f 1266 * \param pEndTime pointer to the sequence time-out value [symbols]
group-Avnet 0:478cfd88041f 1267 *
group-Avnet 0:478cfd88041f 1268 * \return none
group-Avnet 0:478cfd88041f 1269 */
group-Avnet 0:478cfd88041f 1270 static void rf_set_timeout(uint32_t *pEndTime)
group-Avnet 0:478cfd88041f 1271 {
group-Avnet 0:478cfd88041f 1272 uint8_t phyReg;
group-Avnet 0:478cfd88041f 1273
group-Avnet 0:478cfd88041f 1274 if(NULL == pEndTime)
group-Avnet 0:478cfd88041f 1275 {
group-Avnet 0:478cfd88041f 1276 return;
group-Avnet 0:478cfd88041f 1277 }
group-Avnet 0:478cfd88041f 1278
group-Avnet 0:478cfd88041f 1279 platform_enter_critical();
group-Avnet 0:478cfd88041f 1280
group-Avnet 0:478cfd88041f 1281 phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
group-Avnet 0:478cfd88041f 1282 phyReg &= 0xF0; /* do not change IRQ status */
group-Avnet 0:478cfd88041f 1283 phyReg |= (cIRQSTS3_TMR3MSK); /* mask TMR3 interrupt */
group-Avnet 0:478cfd88041f 1284 MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg);
group-Avnet 0:478cfd88041f 1285
group-Avnet 0:478cfd88041f 1286 MCR20Drv_DirectAccessSPIMultiByteWrite(T3CMP_LSB, (uint8_t *) pEndTime, 3);
group-Avnet 0:478cfd88041f 1287
group-Avnet 0:478cfd88041f 1288 phyReg &= ~(cIRQSTS3_TMR3MSK); /* unmask TMR3 interrupt */
group-Avnet 0:478cfd88041f 1289 phyReg |= (cIRQSTS3_TMR3IRQ); /* aknowledge TMR3 IRQ */
group-Avnet 0:478cfd88041f 1290 MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg);
group-Avnet 0:478cfd88041f 1291
group-Avnet 0:478cfd88041f 1292 platform_exit_critical();
group-Avnet 0:478cfd88041f 1293 }
group-Avnet 0:478cfd88041f 1294
group-Avnet 0:478cfd88041f 1295 /*
group-Avnet 0:478cfd88041f 1296 * \brief Function reads a random number from RF.
group-Avnet 0:478cfd88041f 1297 *
group-Avnet 0:478cfd88041f 1298 * \param none
group-Avnet 0:478cfd88041f 1299 *
group-Avnet 0:478cfd88041f 1300 * \return 8-bit random number
group-Avnet 0:478cfd88041f 1301 */
group-Avnet 0:478cfd88041f 1302 static uint8_t rf_if_read_rnd(void)
group-Avnet 0:478cfd88041f 1303 {
group-Avnet 0:478cfd88041f 1304 uint8_t phyReg;
group-Avnet 0:478cfd88041f 1305
group-Avnet 0:478cfd88041f 1306 MCR20Drv_IRQ_Disable();
group-Avnet 0:478cfd88041f 1307 /* Check if XCVR is idle */
group-Avnet 0:478cfd88041f 1308 phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
group-Avnet 0:478cfd88041f 1309
group-Avnet 0:478cfd88041f 1310 if( (phyReg & cPHY_CTRL1_XCVSEQ) == gIdle_c )
group-Avnet 0:478cfd88041f 1311 {
group-Avnet 0:478cfd88041f 1312 /* Program a new sequence */
group-Avnet 0:478cfd88041f 1313 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyReg | gCCA_c);
group-Avnet 0:478cfd88041f 1314 /* Wait for sequence to finish */
group-Avnet 0:478cfd88041f 1315 while( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ) );
group-Avnet 0:478cfd88041f 1316 /* Clear interrupt flag */
group-Avnet 0:478cfd88041f 1317 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ);
group-Avnet 0:478cfd88041f 1318 }
group-Avnet 0:478cfd88041f 1319
group-Avnet 0:478cfd88041f 1320 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1321
group-Avnet 0:478cfd88041f 1322 return MCR20Drv_IndirectAccessSPIRead(_RNG);
group-Avnet 0:478cfd88041f 1323 }
group-Avnet 0:478cfd88041f 1324
group-Avnet 0:478cfd88041f 1325 /*
group-Avnet 0:478cfd88041f 1326 * \brief Function converts LQI into RSSI.
group-Avnet 0:478cfd88041f 1327 *
group-Avnet 0:478cfd88041f 1328 * \param LQI
group-Avnet 0:478cfd88041f 1329 *
group-Avnet 0:478cfd88041f 1330 * \return RSSI
group-Avnet 0:478cfd88041f 1331 */
group-Avnet 0:478cfd88041f 1332 static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi)
group-Avnet 0:478cfd88041f 1333 {
group-Avnet 0:478cfd88041f 1334 int32_t rssi = (50*lqi - 16820) / 163;
group-Avnet 0:478cfd88041f 1335 return (int8_t)rssi;
group-Avnet 0:478cfd88041f 1336 }
group-Avnet 0:478cfd88041f 1337
group-Avnet 0:478cfd88041f 1338 /*
group-Avnet 0:478cfd88041f 1339 * \brief Function scale the LQI value reported by RF into a 0-255 value.
group-Avnet 0:478cfd88041f 1340 *
group-Avnet 0:478cfd88041f 1341 * \param hwLqi - the LQI value reported by RF
group-Avnet 0:478cfd88041f 1342 *
group-Avnet 0:478cfd88041f 1343 * \return scaled LQI
group-Avnet 0:478cfd88041f 1344 */
group-Avnet 0:478cfd88041f 1345 static uint8_t rf_convert_LQI(uint8_t hwLqi)
group-Avnet 0:478cfd88041f 1346 {
group-Avnet 0:478cfd88041f 1347 uint32_t tmpLQI;
group-Avnet 0:478cfd88041f 1348
group-Avnet 0:478cfd88041f 1349 /* LQI Saturation Level */
group-Avnet 0:478cfd88041f 1350 if (hwLqi >= 230)
group-Avnet 0:478cfd88041f 1351 {
group-Avnet 0:478cfd88041f 1352 return 0xFF;
group-Avnet 0:478cfd88041f 1353 }
group-Avnet 0:478cfd88041f 1354 else if (hwLqi <= 9)
group-Avnet 0:478cfd88041f 1355 {
group-Avnet 0:478cfd88041f 1356 return 0;
group-Avnet 0:478cfd88041f 1357 }
group-Avnet 0:478cfd88041f 1358 else
group-Avnet 0:478cfd88041f 1359 {
group-Avnet 0:478cfd88041f 1360 /* Rescale the LQI values from min to saturation to the 0x00 - 0xFF range */
group-Avnet 0:478cfd88041f 1361 /* The LQI value mst be multiplied by ~1.1087 */
group-Avnet 0:478cfd88041f 1362 /* tmpLQI = hwLqi * 7123 ~= hwLqi * 65536 * 0.1087 = hwLqi * 2^16 * 0.1087*/
group-Avnet 0:478cfd88041f 1363 tmpLQI = ((uint32_t)hwLqi * (uint32_t)7123 );
group-Avnet 0:478cfd88041f 1364 /* tmpLQI = (tmpLQI / 2^16) + hwLqi */
group-Avnet 0:478cfd88041f 1365 tmpLQI = (uint32_t)(tmpLQI >> 16) + (uint32_t)hwLqi;
group-Avnet 0:478cfd88041f 1366
group-Avnet 0:478cfd88041f 1367 return (uint8_t)tmpLQI;
group-Avnet 0:478cfd88041f 1368 }
group-Avnet 0:478cfd88041f 1369 }
group-Avnet 0:478cfd88041f 1370
group-Avnet 0:478cfd88041f 1371 /*
group-Avnet 0:478cfd88041f 1372 * \brief Function enables/disables Rx promiscuous mode.
group-Avnet 0:478cfd88041f 1373 *
group-Avnet 0:478cfd88041f 1374 * \param state of XCVR promiscuous mode
group-Avnet 0:478cfd88041f 1375 *
group-Avnet 0:478cfd88041f 1376 * \return none
group-Avnet 0:478cfd88041f 1377 */
group-Avnet 0:478cfd88041f 1378 static void rf_promiscuous(uint8_t state)
group-Avnet 0:478cfd88041f 1379 {
group-Avnet 0:478cfd88041f 1380 uint8_t rxFrameFltReg, phyCtrl4Reg;
group-Avnet 0:478cfd88041f 1381
group-Avnet 0:478cfd88041f 1382 rxFrameFltReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER);
group-Avnet 0:478cfd88041f 1383 phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4);
group-Avnet 0:478cfd88041f 1384
group-Avnet 0:478cfd88041f 1385 if( state )
group-Avnet 0:478cfd88041f 1386 {
group-Avnet 0:478cfd88041f 1387 /* FRM_VER[1:0] = b00. 00: Any FrameVersion accepted (0,1,2 & 3) */
group-Avnet 0:478cfd88041f 1388 /* All frame types accepted*/
group-Avnet 0:478cfd88041f 1389 phyCtrl4Reg |= cPHY_CTRL4_PROMISCUOUS;
group-Avnet 0:478cfd88041f 1390 rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
group-Avnet 0:478cfd88041f 1391 rxFrameFltReg |= (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
group-Avnet 0:478cfd88041f 1392 }
group-Avnet 0:478cfd88041f 1393 else
group-Avnet 0:478cfd88041f 1394 {
group-Avnet 0:478cfd88041f 1395 phyCtrl4Reg &= ~cPHY_CTRL4_PROMISCUOUS;
group-Avnet 0:478cfd88041f 1396 /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others */
group-Avnet 0:478cfd88041f 1397 /* Beacon, Data and MAC command frame types accepted */
group-Avnet 0:478cfd88041f 1398 rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
group-Avnet 0:478cfd88041f 1399 rxFrameFltReg |= (0x03 << cRX_FRAME_FLT_FRM_VER_Shift_c);
group-Avnet 0:478cfd88041f 1400 rxFrameFltReg &= ~(cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
group-Avnet 0:478cfd88041f 1401 }
group-Avnet 0:478cfd88041f 1402
group-Avnet 0:478cfd88041f 1403 MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, rxFrameFltReg);
group-Avnet 0:478cfd88041f 1404 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, phyCtrl4Reg);
group-Avnet 0:478cfd88041f 1405 }
group-Avnet 0:478cfd88041f 1406
group-Avnet 0:478cfd88041f 1407 /*
group-Avnet 0:478cfd88041f 1408 * \brief Function used to switch XCVR power state.
group-Avnet 0:478cfd88041f 1409 *
group-Avnet 0:478cfd88041f 1410 * \param state The XCVR power mode
group-Avnet 0:478cfd88041f 1411 *
group-Avnet 0:478cfd88041f 1412 * \return none
group-Avnet 0:478cfd88041f 1413 */
group-Avnet 0:478cfd88041f 1414 static void rf_set_power_state(xcvrPwrMode_t newState)
group-Avnet 0:478cfd88041f 1415 {
group-Avnet 0:478cfd88041f 1416 uint8_t pwrMode;
group-Avnet 0:478cfd88041f 1417 uint8_t xtalState;
group-Avnet 0:478cfd88041f 1418
group-Avnet 0:478cfd88041f 1419 if( mPwrState == newState )
group-Avnet 0:478cfd88041f 1420 {
group-Avnet 0:478cfd88041f 1421 return;
group-Avnet 0:478cfd88041f 1422 }
group-Avnet 0:478cfd88041f 1423
group-Avnet 0:478cfd88041f 1424 /* Read power settings from RF */
group-Avnet 0:478cfd88041f 1425 pwrMode = MCR20Drv_DirectAccessSPIRead(PWR_MODES);
group-Avnet 0:478cfd88041f 1426 xtalState = pwrMode & cPWR_MODES_XTALEN;
group-Avnet 0:478cfd88041f 1427
group-Avnet 0:478cfd88041f 1428 switch( newState )
group-Avnet 0:478cfd88041f 1429 {
group-Avnet 0:478cfd88041f 1430 case gXcvrPwrIdle_c:
group-Avnet 0:478cfd88041f 1431 pwrMode &= ~(cPWR_MODES_AUTODOZE);
group-Avnet 0:478cfd88041f 1432 pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE);
group-Avnet 0:478cfd88041f 1433 break;
group-Avnet 0:478cfd88041f 1434 case gXcvrPwrAutodoze_c:
group-Avnet 0:478cfd88041f 1435 pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
group-Avnet 0:478cfd88041f 1436 break;
group-Avnet 0:478cfd88041f 1437 case gXcvrPwrDoze_c:
group-Avnet 0:478cfd88041f 1438 pwrMode &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
group-Avnet 0:478cfd88041f 1439 pwrMode |= cPWR_MODES_XTALEN;
group-Avnet 0:478cfd88041f 1440 break;
group-Avnet 0:478cfd88041f 1441 case gXcvrPwrHibernate_c:
group-Avnet 0:478cfd88041f 1442 pwrMode &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
group-Avnet 0:478cfd88041f 1443 break;
group-Avnet 0:478cfd88041f 1444 default:
group-Avnet 0:478cfd88041f 1445 return;
group-Avnet 0:478cfd88041f 1446 }
group-Avnet 0:478cfd88041f 1447
group-Avnet 0:478cfd88041f 1448 mPwrState = newState;
group-Avnet 0:478cfd88041f 1449 MCR20Drv_DirectAccessSPIWrite(PWR_MODES, pwrMode);
group-Avnet 0:478cfd88041f 1450
group-Avnet 0:478cfd88041f 1451 if( !xtalState && (pwrMode & cPWR_MODES_XTALEN))
group-Avnet 0:478cfd88041f 1452 {
group-Avnet 0:478cfd88041f 1453 /* wait for crystal oscillator to complet its warmup */
group-Avnet 0:478cfd88041f 1454 while( ( MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY ) != cPWR_MODES_XTAL_READY);
group-Avnet 0:478cfd88041f 1455 /* wait for radio wakeup from hibernate interrupt */
group-Avnet 0:478cfd88041f 1456 while( ( MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) );
group-Avnet 0:478cfd88041f 1457
group-Avnet 0:478cfd88041f 1458 MCR20Drv_DirectAccessSPIWrite(IRQSTS2, cIRQSTS2_WAKE_IRQ);
group-Avnet 0:478cfd88041f 1459 }
group-Avnet 0:478cfd88041f 1460 }
group-Avnet 0:478cfd88041f 1461
group-Avnet 0:478cfd88041f 1462 /*
group-Avnet 0:478cfd88041f 1463 * \brief Function reads the energy level on the preselected channel.
group-Avnet 0:478cfd88041f 1464 *
group-Avnet 0:478cfd88041f 1465 * \return energy level
group-Avnet 0:478cfd88041f 1466 */
group-Avnet 0:478cfd88041f 1467 static uint8_t rf_get_channel_energy(void)
group-Avnet 0:478cfd88041f 1468 {
group-Avnet 0:478cfd88041f 1469 uint8_t ccaMode;
group-Avnet 0:478cfd88041f 1470
group-Avnet 0:478cfd88041f 1471 MCR20Drv_IRQ_Disable();
group-Avnet 0:478cfd88041f 1472 /* RX can start only from Idle state */
group-Avnet 0:478cfd88041f 1473 if( mPhySeqState != gIdle_c )
group-Avnet 0:478cfd88041f 1474 {
group-Avnet 0:478cfd88041f 1475 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1476 return 0;
group-Avnet 0:478cfd88041f 1477 }
group-Avnet 0:478cfd88041f 1478
group-Avnet 0:478cfd88041f 1479 /* Set XCVR power state in run mode */
group-Avnet 0:478cfd88041f 1480 rf_set_power_state(gXcvrRunState_d);
group-Avnet 0:478cfd88041f 1481
group-Avnet 0:478cfd88041f 1482 /* Switch to ED mode */
group-Avnet 0:478cfd88041f 1483 ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE;
group-Avnet 0:478cfd88041f 1484 if( ccaMode != gCcaED_c )
group-Avnet 0:478cfd88041f 1485 {
group-Avnet 0:478cfd88041f 1486 mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c);
group-Avnet 0:478cfd88041f 1487 mStatusAndControlRegs[PHY_CTRL4] |= gCcaED_c << cPHY_CTRL4_CCATYPE_Shift_c;
group-Avnet 0:478cfd88041f 1488 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]);
group-Avnet 0:478cfd88041f 1489 }
group-Avnet 0:478cfd88041f 1490
group-Avnet 0:478cfd88041f 1491 /* Start ED sequence */
group-Avnet 0:478cfd88041f 1492 mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c;
group-Avnet 0:478cfd88041f 1493 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ);
group-Avnet 0:478cfd88041f 1494 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
group-Avnet 0:478cfd88041f 1495 /* Wait for sequence to finish */
group-Avnet 0:478cfd88041f 1496 while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
group-Avnet 0:478cfd88041f 1497 /* Set XCVR to Idle */
group-Avnet 0:478cfd88041f 1498 mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
group-Avnet 0:478cfd88041f 1499 MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
group-Avnet 0:478cfd88041f 1500 MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ);
group-Avnet 0:478cfd88041f 1501
group-Avnet 0:478cfd88041f 1502 MCR20Drv_IRQ_Enable();
group-Avnet 0:478cfd88041f 1503
group-Avnet 0:478cfd88041f 1504 return rf_convert_energy_level(MCR20Drv_DirectAccessSPIRead(CCA1_ED_FNL));
group-Avnet 0:478cfd88041f 1505 }
group-Avnet 0:478cfd88041f 1506
group-Avnet 0:478cfd88041f 1507 /*
group-Avnet 0:478cfd88041f 1508 * \brief Function converts the energy level from dBm to a 0-255 value.
group-Avnet 0:478cfd88041f 1509 *
group-Avnet 0:478cfd88041f 1510 * \param energyLevel in dBm
group-Avnet 0:478cfd88041f 1511 *
group-Avnet 0:478cfd88041f 1512 * \return energy level (0-255)
group-Avnet 0:478cfd88041f 1513 */
group-Avnet 0:478cfd88041f 1514 static uint8_t rf_convert_energy_level(uint8_t energyLevel)
group-Avnet 0:478cfd88041f 1515 {
group-Avnet 0:478cfd88041f 1516 if(energyLevel >= 90)
group-Avnet 0:478cfd88041f 1517 {
group-Avnet 0:478cfd88041f 1518 /* ED value is below minimum. Return 0x00. */
group-Avnet 0:478cfd88041f 1519 energyLevel = 0x00;
group-Avnet 0:478cfd88041f 1520 }
group-Avnet 0:478cfd88041f 1521 else if(energyLevel <= 26)
group-Avnet 0:478cfd88041f 1522 {
group-Avnet 0:478cfd88041f 1523 /* ED value is above maximum. Return 0xFF. */
group-Avnet 0:478cfd88041f 1524 energyLevel = 0xFF;
group-Avnet 0:478cfd88041f 1525 }
group-Avnet 0:478cfd88041f 1526 else
group-Avnet 0:478cfd88041f 1527 {
group-Avnet 0:478cfd88041f 1528 /* Energy level (-90 dBm to -26 dBm ) --> varies form 0 to 64 */
group-Avnet 0:478cfd88041f 1529 energyLevel = (90 - energyLevel);
group-Avnet 0:478cfd88041f 1530 /* Rescale the energy level values to the 0x00-0xff range (0 to 64 translates in 0 to 255) */
group-Avnet 0:478cfd88041f 1531 /* energyLevel * 3.9844 ~= 4 */
group-Avnet 0:478cfd88041f 1532 /* Multiply with 4=2^2 by shifting left.
group-Avnet 0:478cfd88041f 1533 The multiplication will not overflow beacause energyLevel has values between 0 and 63 */
group-Avnet 0:478cfd88041f 1534 energyLevel <<= 2;
group-Avnet 0:478cfd88041f 1535 }
group-Avnet 0:478cfd88041f 1536
group-Avnet 0:478cfd88041f 1537 return energyLevel;
group-Avnet 0:478cfd88041f 1538 }
group-Avnet 0:478cfd88041f 1539
group-Avnet 0:478cfd88041f 1540 static uint8_t rf_scale_lqi(int8_t rssi)
group-Avnet 0:478cfd88041f 1541 {
group-Avnet 0:478cfd88041f 1542 uint8_t scaled_lqi;
group-Avnet 0:478cfd88041f 1543 /*Worst case sensitivity*/
group-Avnet 0:478cfd88041f 1544 const int8_t rf_sensitivity = -98;
group-Avnet 0:478cfd88041f 1545
group-Avnet 0:478cfd88041f 1546 /*rssi < RF sensitivity*/
group-Avnet 0:478cfd88041f 1547 if(rssi < rf_sensitivity)
group-Avnet 0:478cfd88041f 1548 scaled_lqi=0;
group-Avnet 0:478cfd88041f 1549 /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1550 /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1551 else if(rssi < (rf_sensitivity + 10))
group-Avnet 0:478cfd88041f 1552 scaled_lqi=31;
group-Avnet 0:478cfd88041f 1553 /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1554 /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1555 else if(rssi < (rf_sensitivity + 20))
group-Avnet 0:478cfd88041f 1556 scaled_lqi=207;
group-Avnet 0:478cfd88041f 1557 /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1558 /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1559 else if(rssi < (rf_sensitivity + 30))
group-Avnet 0:478cfd88041f 1560 scaled_lqi=255;
group-Avnet 0:478cfd88041f 1561 /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1562 /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1563 else if(rssi < (rf_sensitivity + 40))
group-Avnet 0:478cfd88041f 1564 scaled_lqi=255;
group-Avnet 0:478cfd88041f 1565 /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1566 /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1567 else if(rssi < (rf_sensitivity + 50))
group-Avnet 0:478cfd88041f 1568 scaled_lqi=255;
group-Avnet 0:478cfd88041f 1569 /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1570 /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1571 else if(rssi < (rf_sensitivity + 60))
group-Avnet 0:478cfd88041f 1572 scaled_lqi=255;
group-Avnet 0:478cfd88041f 1573 /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1574 /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1575 else if(rssi < (rf_sensitivity + 70))
group-Avnet 0:478cfd88041f 1576 scaled_lqi=255;
group-Avnet 0:478cfd88041f 1577 /*rssi > RF saturation*/
group-Avnet 0:478cfd88041f 1578 else if(rssi > (rf_sensitivity + 80))
group-Avnet 0:478cfd88041f 1579 scaled_lqi=111;
group-Avnet 0:478cfd88041f 1580 /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/
group-Avnet 0:478cfd88041f 1581 /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/
group-Avnet 0:478cfd88041f 1582 else
group-Avnet 0:478cfd88041f 1583 scaled_lqi=255;
group-Avnet 0:478cfd88041f 1584
group-Avnet 0:478cfd88041f 1585 return scaled_lqi;
group-Avnet 0:478cfd88041f 1586 }
group-Avnet 0:478cfd88041f 1587
group-Avnet 0:478cfd88041f 1588
group-Avnet 0:478cfd88041f 1589 /*****************************************************************************/
group-Avnet 0:478cfd88041f 1590 /* Layer porting to the Freescale driver */
group-Avnet 0:478cfd88041f 1591 /*****************************************************************************/
group-Avnet 0:478cfd88041f 1592 extern "C" void xcvr_spi_init(uint32_t instance)
group-Avnet 0:478cfd88041f 1593 {
group-Avnet 0:478cfd88041f 1594 (void)instance;
group-Avnet 0:478cfd88041f 1595 }
group-Avnet 0:478cfd88041f 1596
group-Avnet 0:478cfd88041f 1597 extern "C" void RF_IRQ_Init(void) {
group-Avnet 0:478cfd88041f 1598 MBED_ASSERT(irq != NULL);
group-Avnet 0:478cfd88041f 1599 irq->mode(PullUp);
group-Avnet 0:478cfd88041f 1600 irq->fall(&PHY_InterruptHandler);
group-Avnet 0:478cfd88041f 1601 }
group-Avnet 0:478cfd88041f 1602
group-Avnet 0:478cfd88041f 1603 extern "C" void RF_IRQ_Enable(void) {
group-Avnet 0:478cfd88041f 1604 MBED_ASSERT(irq != NULL);
group-Avnet 0:478cfd88041f 1605 irq->enable_irq();
group-Avnet 0:478cfd88041f 1606 }
group-Avnet 0:478cfd88041f 1607
group-Avnet 0:478cfd88041f 1608 extern "C" void RF_IRQ_Disable(void) {
group-Avnet 0:478cfd88041f 1609 MBED_ASSERT(irq != NULL);
group-Avnet 0:478cfd88041f 1610 irq->disable_irq();
group-Avnet 0:478cfd88041f 1611 }
group-Avnet 0:478cfd88041f 1612
group-Avnet 0:478cfd88041f 1613 extern "C" uint8_t RF_isIRQ_Pending(void) {
group-Avnet 0:478cfd88041f 1614 MBED_ASSERT(rf != NULL);
group-Avnet 0:478cfd88041f 1615 return !irq_pin->read();
group-Avnet 0:478cfd88041f 1616 }
group-Avnet 0:478cfd88041f 1617
group-Avnet 0:478cfd88041f 1618 extern "C" void RF_RST_Set(int state) {
group-Avnet 0:478cfd88041f 1619 MBED_ASSERT(rst != NULL);
group-Avnet 0:478cfd88041f 1620 *rst = state;
group-Avnet 0:478cfd88041f 1621 }
group-Avnet 0:478cfd88041f 1622
group-Avnet 0:478cfd88041f 1623 extern "C" void gXcvrAssertCS_d(void)
group-Avnet 0:478cfd88041f 1624 {
group-Avnet 0:478cfd88041f 1625 MBED_ASSERT(cs != NULL);
group-Avnet 0:478cfd88041f 1626 *cs = 0;
group-Avnet 0:478cfd88041f 1627 }
group-Avnet 0:478cfd88041f 1628
group-Avnet 0:478cfd88041f 1629 extern "C" void gXcvrDeassertCS_d(void)
group-Avnet 0:478cfd88041f 1630 {
group-Avnet 0:478cfd88041f 1631 MBED_ASSERT(cs != NULL);
group-Avnet 0:478cfd88041f 1632 *cs = 1;
group-Avnet 0:478cfd88041f 1633 }
group-Avnet 0:478cfd88041f 1634
group-Avnet 0:478cfd88041f 1635 extern "C" void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq)
group-Avnet 0:478cfd88041f 1636 {
group-Avnet 0:478cfd88041f 1637 MBED_ASSERT(spi != NULL);
group-Avnet 0:478cfd88041f 1638 (void)instance;
group-Avnet 0:478cfd88041f 1639 spi->frequency(freq);
group-Avnet 0:478cfd88041f 1640 }
group-Avnet 0:478cfd88041f 1641
group-Avnet 0:478cfd88041f 1642 extern "C" void xcvr_spi_transfer(uint32_t instance,
group-Avnet 0:478cfd88041f 1643 uint8_t * sendBuffer,
group-Avnet 0:478cfd88041f 1644 uint8_t * receiveBuffer,
group-Avnet 0:478cfd88041f 1645 size_t transferByteCount)
group-Avnet 0:478cfd88041f 1646 {
group-Avnet 0:478cfd88041f 1647 MBED_ASSERT(spi != NULL);
group-Avnet 0:478cfd88041f 1648 (void)instance;
group-Avnet 0:478cfd88041f 1649 volatile uint8_t dummy;
group-Avnet 0:478cfd88041f 1650
group-Avnet 0:478cfd88041f 1651 if( !transferByteCount )
group-Avnet 0:478cfd88041f 1652 return;
group-Avnet 0:478cfd88041f 1653
group-Avnet 0:478cfd88041f 1654 if( !sendBuffer && !receiveBuffer )
group-Avnet 0:478cfd88041f 1655 return;
group-Avnet 0:478cfd88041f 1656
group-Avnet 0:478cfd88041f 1657 while( transferByteCount-- )
group-Avnet 0:478cfd88041f 1658 {
group-Avnet 0:478cfd88041f 1659 if( sendBuffer )
group-Avnet 0:478cfd88041f 1660 {
group-Avnet 0:478cfd88041f 1661 dummy = *sendBuffer;
group-Avnet 0:478cfd88041f 1662 sendBuffer++;
group-Avnet 0:478cfd88041f 1663 }
group-Avnet 0:478cfd88041f 1664 else
group-Avnet 0:478cfd88041f 1665 {
group-Avnet 0:478cfd88041f 1666 dummy = 0xFF;
group-Avnet 0:478cfd88041f 1667 }
group-Avnet 0:478cfd88041f 1668
group-Avnet 0:478cfd88041f 1669 dummy = spi->write(dummy);
group-Avnet 0:478cfd88041f 1670
group-Avnet 0:478cfd88041f 1671 if( receiveBuffer )
group-Avnet 0:478cfd88041f 1672 {
group-Avnet 0:478cfd88041f 1673 *receiveBuffer = dummy;
group-Avnet 0:478cfd88041f 1674 receiveBuffer++;
group-Avnet 0:478cfd88041f 1675 }
group-Avnet 0:478cfd88041f 1676 }
group-Avnet 0:478cfd88041f 1677 }
group-Avnet 0:478cfd88041f 1678
group-Avnet 0:478cfd88041f 1679 /*****************************************************************************/
group-Avnet 0:478cfd88041f 1680 /*****************************************************************************/
group-Avnet 0:478cfd88041f 1681
group-Avnet 0:478cfd88041f 1682 static void rf_if_lock(void)
group-Avnet 0:478cfd88041f 1683 {
group-Avnet 0:478cfd88041f 1684 platform_enter_critical();
group-Avnet 0:478cfd88041f 1685 }
group-Avnet 0:478cfd88041f 1686
group-Avnet 0:478cfd88041f 1687 static void rf_if_unlock(void)
group-Avnet 0:478cfd88041f 1688 {
group-Avnet 0:478cfd88041f 1689 platform_exit_critical();
group-Avnet 0:478cfd88041f 1690 }
group-Avnet 0:478cfd88041f 1691
group-Avnet 0:478cfd88041f 1692 NanostackRfPhyMcr20a::NanostackRfPhyMcr20a(PinName spi_mosi, PinName spi_miso,
group-Avnet 0:478cfd88041f 1693 PinName spi_sclk, PinName spi_cs, PinName spi_rst, PinName spi_irq)
group-Avnet 0:478cfd88041f 1694 : _spi(spi_mosi, spi_miso, spi_sclk), _rf_cs(spi_cs), _rf_rst(spi_rst),
group-Avnet 0:478cfd88041f 1695 _rf_irq(spi_irq), _rf_irq_pin(spi_irq)
group-Avnet 0:478cfd88041f 1696 {
group-Avnet 0:478cfd88041f 1697 // Do nothing
group-Avnet 0:478cfd88041f 1698 }
group-Avnet 0:478cfd88041f 1699
group-Avnet 0:478cfd88041f 1700 NanostackRfPhyMcr20a::~NanostackRfPhyMcr20a()
group-Avnet 0:478cfd88041f 1701 {
group-Avnet 0:478cfd88041f 1702 // Do nothing
group-Avnet 0:478cfd88041f 1703 }
group-Avnet 0:478cfd88041f 1704
group-Avnet 0:478cfd88041f 1705 int8_t NanostackRfPhyMcr20a::rf_register()
group-Avnet 0:478cfd88041f 1706 {
group-Avnet 0:478cfd88041f 1707
group-Avnet 0:478cfd88041f 1708 rf_if_lock();
group-Avnet 0:478cfd88041f 1709
group-Avnet 0:478cfd88041f 1710 if (rf != NULL) {
group-Avnet 0:478cfd88041f 1711 rf_if_unlock();
group-Avnet 0:478cfd88041f 1712 error("Multiple registrations of NanostackRfPhyMcr20a not supported");
group-Avnet 0:478cfd88041f 1713 return -1;
group-Avnet 0:478cfd88041f 1714 }
group-Avnet 0:478cfd88041f 1715
group-Avnet 0:478cfd88041f 1716 _pins_set();
group-Avnet 0:478cfd88041f 1717 int8_t radio_id = rf_device_register();
group-Avnet 0:478cfd88041f 1718 if (radio_id < 0) {
group-Avnet 0:478cfd88041f 1719 _pins_clear();
group-Avnet 0:478cfd88041f 1720 rf = NULL;
group-Avnet 0:478cfd88041f 1721 }
group-Avnet 0:478cfd88041f 1722
group-Avnet 0:478cfd88041f 1723 rf_if_unlock();
group-Avnet 0:478cfd88041f 1724 return radio_id;
group-Avnet 0:478cfd88041f 1725 }
group-Avnet 0:478cfd88041f 1726
group-Avnet 0:478cfd88041f 1727 void NanostackRfPhyMcr20a::rf_unregister()
group-Avnet 0:478cfd88041f 1728 {
group-Avnet 0:478cfd88041f 1729 rf_if_lock();
group-Avnet 0:478cfd88041f 1730
group-Avnet 0:478cfd88041f 1731 if (rf != this) {
group-Avnet 0:478cfd88041f 1732 rf_if_unlock();
group-Avnet 0:478cfd88041f 1733 return;
group-Avnet 0:478cfd88041f 1734 }
group-Avnet 0:478cfd88041f 1735
group-Avnet 0:478cfd88041f 1736 rf_device_unregister();
group-Avnet 0:478cfd88041f 1737 rf = NULL;
group-Avnet 0:478cfd88041f 1738 _pins_clear();
group-Avnet 0:478cfd88041f 1739
group-Avnet 0:478cfd88041f 1740 rf_if_unlock();
group-Avnet 0:478cfd88041f 1741 }
group-Avnet 0:478cfd88041f 1742
group-Avnet 0:478cfd88041f 1743 void NanostackRfPhyMcr20a::get_mac_address(uint8_t *mac)
group-Avnet 0:478cfd88041f 1744 {
group-Avnet 0:478cfd88041f 1745 rf_if_lock();
group-Avnet 0:478cfd88041f 1746
group-Avnet 0:478cfd88041f 1747 memcpy((void*)mac, (void*)MAC_address, sizeof(MAC_address));
group-Avnet 0:478cfd88041f 1748
group-Avnet 0:478cfd88041f 1749 rf_if_unlock();
group-Avnet 0:478cfd88041f 1750 }
group-Avnet 0:478cfd88041f 1751
group-Avnet 0:478cfd88041f 1752 void NanostackRfPhyMcr20a::set_mac_address(uint8_t *mac)
group-Avnet 0:478cfd88041f 1753 {
group-Avnet 0:478cfd88041f 1754 rf_if_lock();
group-Avnet 0:478cfd88041f 1755
group-Avnet 0:478cfd88041f 1756 if (NULL != rf) {
group-Avnet 0:478cfd88041f 1757 error("NanostackRfPhyAtmel cannot change mac address when running");
group-Avnet 0:478cfd88041f 1758 rf_if_unlock();
group-Avnet 0:478cfd88041f 1759 return;
group-Avnet 0:478cfd88041f 1760 }
group-Avnet 0:478cfd88041f 1761 memcpy((void*)MAC_address, (void*)mac, sizeof(MAC_address));
group-Avnet 0:478cfd88041f 1762
group-Avnet 0:478cfd88041f 1763 rf_if_unlock();
group-Avnet 0:478cfd88041f 1764 }
group-Avnet 0:478cfd88041f 1765
group-Avnet 0:478cfd88041f 1766 void NanostackRfPhyMcr20a::_pins_set()
group-Avnet 0:478cfd88041f 1767 {
group-Avnet 0:478cfd88041f 1768 spi = &_spi;
group-Avnet 0:478cfd88041f 1769 cs = &_rf_cs;
group-Avnet 0:478cfd88041f 1770 rst = &_rf_rst;
group-Avnet 0:478cfd88041f 1771 irq = &_rf_irq;
group-Avnet 0:478cfd88041f 1772 irq_pin = &_rf_irq_pin;
group-Avnet 0:478cfd88041f 1773 }
group-Avnet 0:478cfd88041f 1774
group-Avnet 0:478cfd88041f 1775 void NanostackRfPhyMcr20a::_pins_clear()
group-Avnet 0:478cfd88041f 1776 {
group-Avnet 0:478cfd88041f 1777 spi = NULL;
group-Avnet 0:478cfd88041f 1778 cs = NULL;
group-Avnet 0:478cfd88041f 1779 rst = NULL;
group-Avnet 0:478cfd88041f 1780 irq = NULL;
group-Avnet 0:478cfd88041f 1781 irq_pin = NULL;
group-Avnet 0:478cfd88041f 1782 }