Fork of my MQTTGateway

Dependencies:   mbed-http

Committer:
vpcola
Date:
Sat Apr 08 14:45:51 2017 +0000
Revision:
0:f1d3878b8dd9
Initial commit

Who changed what in which revision?

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