RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
2019-03-13

Who changed what in which revision?

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