Version of easy-connect with the u-blox cellular platforms C027 and C030 added.

Dependents:   HelloMQTT

Committer:
RobMeades
Date:
Fri Nov 03 13:01:23 2017 +0000
Revision:
6:304d3ba87a01
Parent:
0:19aa55d66228
Add comment concerning N2XX baud rate.

Who changed what in which revision?

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