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) 2018 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 <string.h>
kevman 2:7aab896b1a3b 17 #if defined(MBED_CONF_NANOSTACK_CONFIGURATION) && DEVICE_SPI
kevman 2:7aab896b1a3b 18 #include "platform/arm_hal_interrupt.h"
kevman 2:7aab896b1a3b 19 #include "nanostack/platform/arm_hal_phy.h"
kevman 2:7aab896b1a3b 20 #include "ns_types.h"
kevman 2:7aab896b1a3b 21 #include "NanostackRfPhys2lp.h"
kevman 2:7aab896b1a3b 22 #include "s2lpReg.h"
kevman 2:7aab896b1a3b 23 #include "rf_configuration.h"
kevman 2:7aab896b1a3b 24 #include "randLIB.h"
kevman 2:7aab896b1a3b 25 #include "mbed_trace.h"
kevman 2:7aab896b1a3b 26 #include "mbed_toolchain.h"
kevman 2:7aab896b1a3b 27 #include "common_functions.h"
kevman 2:7aab896b1a3b 28 #include <Timer.h>
kevman 2:7aab896b1a3b 29
kevman 2:7aab896b1a3b 30 #define TRACE_GROUP "s2lp"
kevman 2:7aab896b1a3b 31
kevman 2:7aab896b1a3b 32 #define INTERRUPT_GPIO S2LP_GPIO3
kevman 2:7aab896b1a3b 33
kevman 2:7aab896b1a3b 34 #if INTERRUPT_GPIO == S2LP_GPIO0
kevman 2:7aab896b1a3b 35 #define INT_IN_GPIO rf->RF_S2LP_GPIO0
kevman 2:7aab896b1a3b 36 #elif INTERRUPT_GPIO == S2LP_GPIO1
kevman 2:7aab896b1a3b 37 #define INT_IN_GPIO rf->RF_S2LP_GPIO1
kevman 2:7aab896b1a3b 38 #elif INTERRUPT_GPIO == S2LP_GPIO2
kevman 2:7aab896b1a3b 39 #define INT_IN_GPIO rf->RF_S2LP_GPIO2
kevman 2:7aab896b1a3b 40 #else
kevman 2:7aab896b1a3b 41 #define INT_IN_GPIO rf->RF_S2LP_GPIO3
kevman 2:7aab896b1a3b 42 #endif
kevman 2:7aab896b1a3b 43
kevman 2:7aab896b1a3b 44 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 45 #define TEST_TX_STARTED rf->TEST1 = 1;
kevman 2:7aab896b1a3b 46 #define TEST_TX_DONE rf->TEST1 = 0;
kevman 2:7aab896b1a3b 47 #define TEST_RX_STARTED rf->TEST2 = 1;
kevman 2:7aab896b1a3b 48 #define TEST_RX_DONE rf->TEST2 = 0;
kevman 2:7aab896b1a3b 49 #define TEST_ACK_TX_STARTED rf->TEST3 = 1;
kevman 2:7aab896b1a3b 50 #define TEST_ACK_TX_DONE rf->TEST3 = 0;
kevman 2:7aab896b1a3b 51 #define TEST1_ON rf->TEST4 = 1;
kevman 2:7aab896b1a3b 52 #define TEST1_OFF rf->TEST4 = 0;
kevman 2:7aab896b1a3b 53 #define TEST2_ON rf->TEST5 = 1;
kevman 2:7aab896b1a3b 54 #define TEST2_OFF rf->TEST5 = 0;
kevman 2:7aab896b1a3b 55 extern void (*fhss_uc_switch)(void);
kevman 2:7aab896b1a3b 56 extern void (*fhss_bc_switch)(void);
kevman 2:7aab896b1a3b 57 #else //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 58 #define TEST_TX_STARTED
kevman 2:7aab896b1a3b 59 #define TEST_TX_DONE
kevman 2:7aab896b1a3b 60 #define TEST_RX_STARTED
kevman 2:7aab896b1a3b 61 #define TEST_RX_DONE
kevman 2:7aab896b1a3b 62 #define TEST_ACK_TX_STARTED
kevman 2:7aab896b1a3b 63 #define TEST_ACK_TX_DONE
kevman 2:7aab896b1a3b 64 #define TEST1_ON
kevman 2:7aab896b1a3b 65 #define TEST1_OFF
kevman 2:7aab896b1a3b 66 #define TEST2_ON
kevman 2:7aab896b1a3b 67 #define TEST2_OFF
kevman 2:7aab896b1a3b 68 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 69
kevman 2:7aab896b1a3b 70 #define MAC_FRAME_TYPE_MASK 0x07
kevman 2:7aab896b1a3b 71 #define MAC_FRAME_BEACON (0)
kevman 2:7aab896b1a3b 72 #define MAC_TYPE_DATA (1)
kevman 2:7aab896b1a3b 73 #define MAC_TYPE_ACK (2)
kevman 2:7aab896b1a3b 74 #define MAC_TYPE_COMMAND (3)
kevman 2:7aab896b1a3b 75 #define MAC_DATA_PENDING 0x10
kevman 2:7aab896b1a3b 76 #define MAC_FRAME_VERSION_2 (2)
kevman 2:7aab896b1a3b 77 #define FC_DST_MODE 0x0C
kevman 2:7aab896b1a3b 78 #define FC_SRC_MODE 0xC0
kevman 2:7aab896b1a3b 79 #define FC_DST_ADDR_NONE 0x00
kevman 2:7aab896b1a3b 80 #define FC_DST_16_BITS 0x08
kevman 2:7aab896b1a3b 81 #define FC_DST_64_BITS 0x0C
kevman 2:7aab896b1a3b 82 #define FC_SRC_64_BITS 0xC0
kevman 2:7aab896b1a3b 83 #define FC_SEQUENCE_COMPRESSION 0x01
kevman 2:7aab896b1a3b 84 #define FC_AR 0x20
kevman 2:7aab896b1a3b 85 #define FC_PAN_ID_COMPRESSION 0x40
kevman 2:7aab896b1a3b 86 #define VERSION_FIELD_MASK 0x30
kevman 2:7aab896b1a3b 87 #define SHIFT_SEQ_COMP_FIELD (0)
kevman 2:7aab896b1a3b 88 #define SHIFT_VERSION_FIELD (4)
kevman 2:7aab896b1a3b 89 #define SHIFT_PANID_COMP_FIELD (6)
kevman 2:7aab896b1a3b 90 #define OFFSET_DST_PAN_ID (3)
kevman 2:7aab896b1a3b 91 #define OFFSET_DST_ADDR (5)
kevman 2:7aab896b1a3b 92
kevman 2:7aab896b1a3b 93 #define CS_SELECT() {rf->CS = 0;}
kevman 2:7aab896b1a3b 94 #define CS_RELEASE() {rf->CS = 1;}
kevman 2:7aab896b1a3b 95
kevman 2:7aab896b1a3b 96 class UnlockedSPI : public SPI {
kevman 2:7aab896b1a3b 97 public:
kevman 2:7aab896b1a3b 98 UnlockedSPI(PinName sdi, PinName sdo, PinName sclk) :
kevman 2:7aab896b1a3b 99 SPI(sdi, sdo, sclk) { }
kevman 2:7aab896b1a3b 100 virtual void lock() { }
kevman 2:7aab896b1a3b 101 virtual void unlock() { }
kevman 2:7aab896b1a3b 102 };
kevman 2:7aab896b1a3b 103
kevman 2:7aab896b1a3b 104 class RFPins {
kevman 2:7aab896b1a3b 105 public:
kevman 2:7aab896b1a3b 106 RFPins(PinName spi_sdi, PinName spi_sdo,
kevman 2:7aab896b1a3b 107 PinName spi_sclk, PinName spi_cs, PinName spi_sdn,
kevman 2:7aab896b1a3b 108 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 109 PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5,
kevman 2:7aab896b1a3b 110 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 111 PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2,
kevman 2:7aab896b1a3b 112 PinName spi_gpio3);
kevman 2:7aab896b1a3b 113 UnlockedSPI spi;
kevman 2:7aab896b1a3b 114 DigitalOut CS;
kevman 2:7aab896b1a3b 115 DigitalOut SDN;
kevman 2:7aab896b1a3b 116 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 117 DigitalOut TEST1;
kevman 2:7aab896b1a3b 118 DigitalOut TEST2;
kevman 2:7aab896b1a3b 119 DigitalOut TEST3;
kevman 2:7aab896b1a3b 120 DigitalOut TEST4;
kevman 2:7aab896b1a3b 121 DigitalOut TEST5;
kevman 2:7aab896b1a3b 122 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 123 InterruptIn RF_S2LP_GPIO0;
kevman 2:7aab896b1a3b 124 InterruptIn RF_S2LP_GPIO1;
kevman 2:7aab896b1a3b 125 InterruptIn RF_S2LP_GPIO2;
kevman 2:7aab896b1a3b 126 InterruptIn RF_S2LP_GPIO3;
kevman 2:7aab896b1a3b 127 Timeout cca_timer;
kevman 2:7aab896b1a3b 128 Timeout backup_timer;
kevman 2:7aab896b1a3b 129 Timer tx_timer;
kevman 2:7aab896b1a3b 130 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 131 Thread irq_thread;
kevman 2:7aab896b1a3b 132 Mutex mutex;
kevman 2:7aab896b1a3b 133 void rf_irq_task();
kevman 2:7aab896b1a3b 134 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 135 };
kevman 2:7aab896b1a3b 136
kevman 2:7aab896b1a3b 137 RFPins::RFPins(PinName spi_sdi, PinName spi_sdo,
kevman 2:7aab896b1a3b 138 PinName spi_sclk, PinName spi_cs, PinName spi_sdn,
kevman 2:7aab896b1a3b 139 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 140 PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5,
kevman 2:7aab896b1a3b 141 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 142 PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2,
kevman 2:7aab896b1a3b 143 PinName spi_gpio3)
kevman 2:7aab896b1a3b 144 : spi(spi_sdi, spi_sdo, spi_sclk),
kevman 2:7aab896b1a3b 145 CS(spi_cs),
kevman 2:7aab896b1a3b 146 SDN(spi_sdn),
kevman 2:7aab896b1a3b 147 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 148 TEST1(spi_test1),
kevman 2:7aab896b1a3b 149 TEST2(spi_test2),
kevman 2:7aab896b1a3b 150 TEST3(spi_test3),
kevman 2:7aab896b1a3b 151 TEST4(spi_test4),
kevman 2:7aab896b1a3b 152 TEST5(spi_test5),
kevman 2:7aab896b1a3b 153 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 154 RF_S2LP_GPIO0(spi_gpio0),
kevman 2:7aab896b1a3b 155 RF_S2LP_GPIO1(spi_gpio1),
kevman 2:7aab896b1a3b 156 RF_S2LP_GPIO2(spi_gpio2),
kevman 2:7aab896b1a3b 157 RF_S2LP_GPIO3(spi_gpio3)
kevman 2:7aab896b1a3b 158 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 159 , irq_thread(osPriorityRealtime, 1024)
kevman 2:7aab896b1a3b 160 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 161 {
kevman 2:7aab896b1a3b 162 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 163 irq_thread.start(mbed::callback(this, &RFPins::rf_irq_task));
kevman 2:7aab896b1a3b 164 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 165 }
kevman 2:7aab896b1a3b 166
kevman 2:7aab896b1a3b 167 static uint8_t rf_read_register_with_status(uint8_t addr, uint16_t *status_out);
kevman 2:7aab896b1a3b 168 static s2lp_states_e rf_read_state(void);
kevman 2:7aab896b1a3b 169 static void rf_write_register(uint8_t addr, uint8_t data);
kevman 2:7aab896b1a3b 170 static void rf_print_registers(void);
kevman 2:7aab896b1a3b 171 static void rf_interrupt_handler(void);
kevman 2:7aab896b1a3b 172 static void rf_receive(uint8_t rx_channel);
kevman 2:7aab896b1a3b 173 static void rf_cca_timer_stop(void);
kevman 2:7aab896b1a3b 174 static void rf_backup_timer_start(uint32_t slots);
kevman 2:7aab896b1a3b 175 static void rf_backup_timer_stop(void);
kevman 2:7aab896b1a3b 176 static void rf_rx_ready_handler(void);
kevman 2:7aab896b1a3b 177 static uint32_t read_irq_status(void);
kevman 2:7aab896b1a3b 178 static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t *pan_id);
kevman 2:7aab896b1a3b 179
kevman 2:7aab896b1a3b 180 static RFPins *rf;
kevman 2:7aab896b1a3b 181 static phy_device_driver_s device_driver;
kevman 2:7aab896b1a3b 182 static int8_t rf_radio_driver_id = -1;
kevman 2:7aab896b1a3b 183 static uint8_t *tx_data_ptr;
kevman 2:7aab896b1a3b 184 static uint16_t tx_data_length;
kevman 2:7aab896b1a3b 185 static uint16_t rx_data_length;
kevman 2:7aab896b1a3b 186 static uint32_t enabled_interrupts;
kevman 2:7aab896b1a3b 187 static uint8_t mac_tx_handle;
kevman 2:7aab896b1a3b 188 static uint8_t rf_rx_channel;
kevman 2:7aab896b1a3b 189 static uint8_t rf_new_channel;
kevman 2:7aab896b1a3b 190 static uint8_t rx_buffer[RF_MTU];
kevman 2:7aab896b1a3b 191 static rf_states_e rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 192 // This will be used when given channel spacing cannot be supported by transceiver
kevman 2:7aab896b1a3b 193 static uint8_t rf_channel_multiplier = 1;
kevman 2:7aab896b1a3b 194 static uint16_t tx_sequence = 0xffff;
kevman 2:7aab896b1a3b 195 static uint32_t tx_time = 0;
kevman 2:7aab896b1a3b 196 static uint32_t rx_time = 0;
kevman 2:7aab896b1a3b 197 static uint32_t tx_finnish_time = 0;
kevman 2:7aab896b1a3b 198 static uint32_t symbols_in_seconds;
kevman 2:7aab896b1a3b 199 static bool cca_enabled = true;
kevman 2:7aab896b1a3b 200 static uint8_t s2lp_PAN_ID[2] = {0xff, 0xff};
kevman 2:7aab896b1a3b 201 static uint8_t s2lp_short_address[2];
kevman 2:7aab896b1a3b 202 static uint8_t s2lp_MAC[8];
kevman 2:7aab896b1a3b 203
kevman 2:7aab896b1a3b 204 /* Channel configurations for sub-GHz */
kevman 2:7aab896b1a3b 205 static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 500000U, 250000U, 11U, M_UNDEFINED};
kevman 2:7aab896b1a3b 206
kevman 2:7aab896b1a3b 207 static const phy_device_channel_page_s phy_channel_pages[] = {
kevman 2:7aab896b1a3b 208 { CHANNEL_PAGE_2, &phy_subghz},
kevman 2:7aab896b1a3b 209 { CHANNEL_PAGE_0, NULL}
kevman 2:7aab896b1a3b 210 };
kevman 2:7aab896b1a3b 211
kevman 2:7aab896b1a3b 212 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 213 #include "mbed.h"
kevman 2:7aab896b1a3b 214 #include "rtos.h"
kevman 2:7aab896b1a3b 215
kevman 2:7aab896b1a3b 216 static void rf_irq_task_process_irq();
kevman 2:7aab896b1a3b 217
kevman 2:7aab896b1a3b 218 #define SIG_RADIO 1
kevman 2:7aab896b1a3b 219 #define SIG_TIMER_CCA 2
kevman 2:7aab896b1a3b 220 #define SIG_TIMER_BACKUP 4
kevman 2:7aab896b1a3b 221
kevman 2:7aab896b1a3b 222 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 223
kevman 2:7aab896b1a3b 224 #define ACK_FRAME_LENGTH 3
kevman 2:7aab896b1a3b 225 // Give some additional time for processing, PHY headers, CRC etc.
kevman 2:7aab896b1a3b 226 #define PACKET_SENDING_EXTRA_TIME 10000
kevman 2:7aab896b1a3b 227 #define MAX_PACKET_SENDING_TIME (uint32_t)(8000000/phy_subghz.datarate)*RF_MTU + PACKET_SENDING_EXTRA_TIME
kevman 2:7aab896b1a3b 228 #define ACK_SENDING_TIME (uint32_t)(8000000/phy_subghz.datarate)*ACK_FRAME_LENGTH + PACKET_SENDING_EXTRA_TIME
kevman 2:7aab896b1a3b 229
kevman 2:7aab896b1a3b 230 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 231 void test1_toggle(void)
kevman 2:7aab896b1a3b 232 {
kevman 2:7aab896b1a3b 233 if (rf->TEST4) {
kevman 2:7aab896b1a3b 234 rf->TEST4 = 0;
kevman 2:7aab896b1a3b 235 } else {
kevman 2:7aab896b1a3b 236 rf->TEST4 = 1;
kevman 2:7aab896b1a3b 237 }
kevman 2:7aab896b1a3b 238 }
kevman 2:7aab896b1a3b 239 void test2_toggle(void)
kevman 2:7aab896b1a3b 240 {
kevman 2:7aab896b1a3b 241 if (rf->TEST5) {
kevman 2:7aab896b1a3b 242 rf->TEST5 = 0;
kevman 2:7aab896b1a3b 243 } else {
kevman 2:7aab896b1a3b 244 rf->TEST5 = 1;
kevman 2:7aab896b1a3b 245 }
kevman 2:7aab896b1a3b 246 }
kevman 2:7aab896b1a3b 247 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 248
kevman 2:7aab896b1a3b 249 static void rf_calculate_symbols_in_seconds(uint32_t baudrate, phy_modulation_e modulation)
kevman 2:7aab896b1a3b 250 {
kevman 2:7aab896b1a3b 251 (void) modulation;
kevman 2:7aab896b1a3b 252 uint8_t bits_in_symbols = 1;
kevman 2:7aab896b1a3b 253 symbols_in_seconds = baudrate / bits_in_symbols;
kevman 2:7aab896b1a3b 254 }
kevman 2:7aab896b1a3b 255
kevman 2:7aab896b1a3b 256 static uint32_t rf_get_timestamp(void)
kevman 2:7aab896b1a3b 257 {
kevman 2:7aab896b1a3b 258 return (uint32_t)rf->tx_timer.read_us();
kevman 2:7aab896b1a3b 259 }
kevman 2:7aab896b1a3b 260
kevman 2:7aab896b1a3b 261 static void rf_lock(void)
kevman 2:7aab896b1a3b 262 {
kevman 2:7aab896b1a3b 263 platform_enter_critical();
kevman 2:7aab896b1a3b 264 }
kevman 2:7aab896b1a3b 265
kevman 2:7aab896b1a3b 266 static void rf_unlock(void)
kevman 2:7aab896b1a3b 267 {
kevman 2:7aab896b1a3b 268 platform_exit_critical();
kevman 2:7aab896b1a3b 269 }
kevman 2:7aab896b1a3b 270
kevman 2:7aab896b1a3b 271 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 272 static void rf_cca_timer_signal(void)
kevman 2:7aab896b1a3b 273 {
kevman 2:7aab896b1a3b 274 rf->irq_thread.signal_set(SIG_TIMER_CCA);
kevman 2:7aab896b1a3b 275 }
kevman 2:7aab896b1a3b 276
kevman 2:7aab896b1a3b 277 static void rf_backup_timer_signal(void)
kevman 2:7aab896b1a3b 278 {
kevman 2:7aab896b1a3b 279 rf->irq_thread.signal_set(SIG_TIMER_BACKUP);
kevman 2:7aab896b1a3b 280 }
kevman 2:7aab896b1a3b 281 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 282
kevman 2:7aab896b1a3b 283 /*
kevman 2:7aab896b1a3b 284 * \brief Function writes/read data in SPI interface
kevman 2:7aab896b1a3b 285 */
kevman 2:7aab896b1a3b 286 static void rf_spi_exchange(const void *tx, size_t tx_len, void *rx, size_t rx_len)
kevman 2:7aab896b1a3b 287 {
kevman 2:7aab896b1a3b 288 rf->spi.write(static_cast<const char *>(tx), tx_len, static_cast<char *>(rx), rx_len);
kevman 2:7aab896b1a3b 289 }
kevman 2:7aab896b1a3b 290
kevman 2:7aab896b1a3b 291 static uint8_t rf_read_register_with_status(uint8_t addr, uint16_t *status_out)
kevman 2:7aab896b1a3b 292 {
kevman 2:7aab896b1a3b 293 const uint8_t tx[2] = {SPI_RD_REG, addr};
kevman 2:7aab896b1a3b 294 uint8_t rx[3];
kevman 2:7aab896b1a3b 295 rf_lock();
kevman 2:7aab896b1a3b 296 CS_SELECT();
kevman 2:7aab896b1a3b 297 rf_spi_exchange(tx, sizeof(tx), rx, sizeof(rx));
kevman 2:7aab896b1a3b 298 CS_RELEASE();
kevman 2:7aab896b1a3b 299 if (status_out) {
kevman 2:7aab896b1a3b 300 *status_out = (rx[0] << 8) | rx[1];
kevman 2:7aab896b1a3b 301 }
kevman 2:7aab896b1a3b 302 rf_unlock();
kevman 2:7aab896b1a3b 303 return rx[2];
kevman 2:7aab896b1a3b 304 }
kevman 2:7aab896b1a3b 305
kevman 2:7aab896b1a3b 306 static void rf_write_register(uint8_t addr, uint8_t data)
kevman 2:7aab896b1a3b 307 {
kevman 2:7aab896b1a3b 308 const uint8_t tx[3] = {SPI_WR_REG, addr, data};
kevman 2:7aab896b1a3b 309 rf_lock();
kevman 2:7aab896b1a3b 310 CS_SELECT();
kevman 2:7aab896b1a3b 311 rf_spi_exchange(tx, sizeof(tx), NULL, 0);
kevman 2:7aab896b1a3b 312 CS_RELEASE();
kevman 2:7aab896b1a3b 313 rf_unlock();
kevman 2:7aab896b1a3b 314 }
kevman 2:7aab896b1a3b 315
kevman 2:7aab896b1a3b 316 static void rf_write_register_field(uint8_t addr, uint8_t field, uint8_t value)
kevman 2:7aab896b1a3b 317 {
kevman 2:7aab896b1a3b 318 uint8_t reg_tmp = rf_read_register_with_status(addr, NULL);
kevman 2:7aab896b1a3b 319 reg_tmp &= ~field;
kevman 2:7aab896b1a3b 320 reg_tmp |= value;
kevman 2:7aab896b1a3b 321 rf_write_register(addr, reg_tmp);
kevman 2:7aab896b1a3b 322 }
kevman 2:7aab896b1a3b 323
kevman 2:7aab896b1a3b 324 static s2lp_states_e rf_read_state(void)
kevman 2:7aab896b1a3b 325 {
kevman 2:7aab896b1a3b 326 return (s2lp_states_e)(rf_read_register_with_status(MC_STATE0, NULL) >> 1);
kevman 2:7aab896b1a3b 327 }
kevman 2:7aab896b1a3b 328
kevman 2:7aab896b1a3b 329 static void rf_poll_state_change(s2lp_states_e state)
kevman 2:7aab896b1a3b 330 {
kevman 2:7aab896b1a3b 331 uint16_t break_counter = 0;
kevman 2:7aab896b1a3b 332 while (state != rf_read_state()) {
kevman 2:7aab896b1a3b 333 if (break_counter++ == 0xffff) {
kevman 2:7aab896b1a3b 334 tr_err("Failed to change state from %x to: %x", rf_read_state(), state);
kevman 2:7aab896b1a3b 335 break;
kevman 2:7aab896b1a3b 336 }
kevman 2:7aab896b1a3b 337 }
kevman 2:7aab896b1a3b 338 }
kevman 2:7aab896b1a3b 339
kevman 2:7aab896b1a3b 340 static void rf_enable_gpio_signal(uint8_t gpio_pin, uint8_t interrupt_signal, uint8_t gpio_mode)
kevman 2:7aab896b1a3b 341 {
kevman 2:7aab896b1a3b 342 rf_write_register(GPIO0_CONF + gpio_pin, (interrupt_signal << 3) | gpio_mode);
kevman 2:7aab896b1a3b 343 }
kevman 2:7aab896b1a3b 344
kevman 2:7aab896b1a3b 345 static void rf_enable_interrupt(uint8_t event)
kevman 2:7aab896b1a3b 346 {
kevman 2:7aab896b1a3b 347 rf_write_register_field(IRQ_MASK0 - (event / 8), 1 << (event % 8), 1 << (event % 8));
kevman 2:7aab896b1a3b 348 enabled_interrupts |= (1 << event);
kevman 2:7aab896b1a3b 349 }
kevman 2:7aab896b1a3b 350
kevman 2:7aab896b1a3b 351 static void rf_disable_interrupt(uint8_t event)
kevman 2:7aab896b1a3b 352 {
kevman 2:7aab896b1a3b 353 rf_write_register_field(IRQ_MASK0 - (event / 8), 1 << (event % 8), 0 << (event % 8));
kevman 2:7aab896b1a3b 354 enabled_interrupts &= ~(1 << event);
kevman 2:7aab896b1a3b 355 }
kevman 2:7aab896b1a3b 356
kevman 2:7aab896b1a3b 357 static void rf_disable_all_interrupts(void)
kevman 2:7aab896b1a3b 358 {
kevman 2:7aab896b1a3b 359 rf_write_register(IRQ_MASK0, 0);
kevman 2:7aab896b1a3b 360 rf_write_register(IRQ_MASK1, 0);
kevman 2:7aab896b1a3b 361 rf_write_register(IRQ_MASK2, 0);
kevman 2:7aab896b1a3b 362 rf_write_register(IRQ_MASK3, 0);
kevman 2:7aab896b1a3b 363 enabled_interrupts = 0;
kevman 2:7aab896b1a3b 364 read_irq_status();
kevman 2:7aab896b1a3b 365 }
kevman 2:7aab896b1a3b 366
kevman 2:7aab896b1a3b 367 static void rf_enable_gpio_interrupt(void)
kevman 2:7aab896b1a3b 368 {
kevman 2:7aab896b1a3b 369 rf_enable_gpio_signal(INTERRUPT_GPIO, NIRQ, DIG_OUT_HIGH);
kevman 2:7aab896b1a3b 370 INT_IN_GPIO.mode(PullUp);
kevman 2:7aab896b1a3b 371 INT_IN_GPIO.fall(&rf_interrupt_handler);
kevman 2:7aab896b1a3b 372 INT_IN_GPIO.enable_irq();
kevman 2:7aab896b1a3b 373 }
kevman 2:7aab896b1a3b 374
kevman 2:7aab896b1a3b 375 static void rf_send_command(s2lp_commands_e command)
kevman 2:7aab896b1a3b 376 {
kevman 2:7aab896b1a3b 377 const uint8_t tx[2] = {SPI_CMD, command};
kevman 2:7aab896b1a3b 378 rf_lock();
kevman 2:7aab896b1a3b 379 CS_SELECT();
kevman 2:7aab896b1a3b 380 rf_spi_exchange(tx, sizeof(tx), NULL, 0);
kevman 2:7aab896b1a3b 381 CS_RELEASE();
kevman 2:7aab896b1a3b 382 rf_unlock();
kevman 2:7aab896b1a3b 383 }
kevman 2:7aab896b1a3b 384
kevman 2:7aab896b1a3b 385 static void rf_state_change(s2lp_states_e state, bool lock_mode_tx)
kevman 2:7aab896b1a3b 386 {
kevman 2:7aab896b1a3b 387 s2lp_commands_e command;
kevman 2:7aab896b1a3b 388
kevman 2:7aab896b1a3b 389 if (S2LP_STATE_READY == state) {
kevman 2:7aab896b1a3b 390 s2lp_states_e cur_state = rf_read_state();
kevman 2:7aab896b1a3b 391 if (S2LP_STATE_TX == cur_state || S2LP_STATE_RX == cur_state) {
kevman 2:7aab896b1a3b 392 command = S2LP_CMD_SABORT;
kevman 2:7aab896b1a3b 393 } else {
kevman 2:7aab896b1a3b 394 command = S2LP_CMD_READY;
kevman 2:7aab896b1a3b 395 }
kevman 2:7aab896b1a3b 396 } else if (S2LP_STATE_LOCK == state && lock_mode_tx) {
kevman 2:7aab896b1a3b 397 command = S2LP_CMD_LOCKTX;
kevman 2:7aab896b1a3b 398 } else if (S2LP_STATE_LOCK == state && !lock_mode_tx) {
kevman 2:7aab896b1a3b 399 command = S2LP_CMD_LOCKRX;
kevman 2:7aab896b1a3b 400 } else if (S2LP_STATE_RX == state) {
kevman 2:7aab896b1a3b 401 command = S2LP_CMD_RX;
kevman 2:7aab896b1a3b 402 } else if (S2LP_STATE_TX == state) {
kevman 2:7aab896b1a3b 403 command = S2LP_CMD_TX;
kevman 2:7aab896b1a3b 404 } else {
kevman 2:7aab896b1a3b 405 tr_err("Invalid state %x", state);
kevman 2:7aab896b1a3b 406 return;
kevman 2:7aab896b1a3b 407 }
kevman 2:7aab896b1a3b 408 rf_send_command(command);
kevman 2:7aab896b1a3b 409 rf_poll_state_change(state);
kevman 2:7aab896b1a3b 410 }
kevman 2:7aab896b1a3b 411
kevman 2:7aab896b1a3b 412 static uint8_t rf_write_tx_fifo(uint8_t *ptr, uint16_t length, uint8_t max_write)
kevman 2:7aab896b1a3b 413 {
kevman 2:7aab896b1a3b 414 const uint8_t spi_header[SPI_HEADER_LENGTH] = {SPI_WR_REG, TX_FIFO};
kevman 2:7aab896b1a3b 415 uint8_t written_length = length;
kevman 2:7aab896b1a3b 416 if (length > max_write) {
kevman 2:7aab896b1a3b 417 written_length = max_write;
kevman 2:7aab896b1a3b 418 }
kevman 2:7aab896b1a3b 419 CS_SELECT();
kevman 2:7aab896b1a3b 420 rf_spi_exchange(spi_header, SPI_HEADER_LENGTH, NULL, 0);
kevman 2:7aab896b1a3b 421 rf_spi_exchange(ptr, written_length, NULL, 0);
kevman 2:7aab896b1a3b 422 CS_RELEASE();
kevman 2:7aab896b1a3b 423 return written_length;
kevman 2:7aab896b1a3b 424 }
kevman 2:7aab896b1a3b 425
kevman 2:7aab896b1a3b 426 static uint8_t rf_read_rx_fifo(uint8_t *ptr, uint16_t length)
kevman 2:7aab896b1a3b 427 {
kevman 2:7aab896b1a3b 428 const uint8_t spi_header[SPI_HEADER_LENGTH] = {SPI_RD_REG, RX_FIFO};
kevman 2:7aab896b1a3b 429 CS_SELECT();
kevman 2:7aab896b1a3b 430 rf_spi_exchange(spi_header, SPI_HEADER_LENGTH, NULL, 0);
kevman 2:7aab896b1a3b 431 rf_spi_exchange(NULL, 0, ptr, length);
kevman 2:7aab896b1a3b 432 CS_RELEASE();
kevman 2:7aab896b1a3b 433 return length;
kevman 2:7aab896b1a3b 434 }
kevman 2:7aab896b1a3b 435
kevman 2:7aab896b1a3b 436 static void rf_write_packet_length(uint16_t packet_length)
kevman 2:7aab896b1a3b 437 {
kevman 2:7aab896b1a3b 438 rf_write_register(PCKTLEN1, packet_length / 256);
kevman 2:7aab896b1a3b 439 rf_write_register(PCKTLEN0, packet_length % 256);
kevman 2:7aab896b1a3b 440 }
kevman 2:7aab896b1a3b 441
kevman 2:7aab896b1a3b 442 static uint32_t read_irq_status(void)
kevman 2:7aab896b1a3b 443 {
kevman 2:7aab896b1a3b 444 const uint8_t tx[2] = {SPI_RD_REG, IRQ_STATUS3};
kevman 2:7aab896b1a3b 445 uint8_t rx[6];
kevman 2:7aab896b1a3b 446 CS_SELECT();
kevman 2:7aab896b1a3b 447 rf_spi_exchange(tx, sizeof(tx), rx, sizeof(rx));
kevman 2:7aab896b1a3b 448 CS_RELEASE();
kevman 2:7aab896b1a3b 449 return (((uint32_t)rx[2] << 24) | ((uint32_t)rx[3] << 16) | ((uint32_t)rx[4] << 8) | rx[5]);
kevman 2:7aab896b1a3b 450 }
kevman 2:7aab896b1a3b 451
kevman 2:7aab896b1a3b 452 static void rf_init_registers(void)
kevman 2:7aab896b1a3b 453 {
kevman 2:7aab896b1a3b 454 rf_write_register_field(PCKTCTRL3, PCKT_FORMAT_FIELD, PCKT_FORMAT_802_15_4);
kevman 2:7aab896b1a3b 455 // Set deviation
kevman 2:7aab896b1a3b 456 uint8_t fdev_m, fdev_e;
kevman 2:7aab896b1a3b 457 rf_conf_calculate_deviation_registers(DEVIATION, &fdev_m, &fdev_e);
kevman 2:7aab896b1a3b 458 rf_write_register(MOD0, fdev_m);
kevman 2:7aab896b1a3b 459 rf_write_register_field(MOD1, FDEV_E_FIELD, fdev_e);
kevman 2:7aab896b1a3b 460 rf_write_register_field(MOD2, MOD_TYPE_FIELD, MOD_2FSK);
kevman 2:7aab896b1a3b 461 // Set datarate
kevman 2:7aab896b1a3b 462 uint16_t datarate_m;
kevman 2:7aab896b1a3b 463 uint8_t datarate_e;
kevman 2:7aab896b1a3b 464 rf_conf_calculate_datarate_registers(phy_subghz.datarate, &datarate_m, &datarate_e);
kevman 2:7aab896b1a3b 465 rf_write_register_field(MOD2, DATARATE_E_FIELD, datarate_e);
kevman 2:7aab896b1a3b 466 rf_write_register(MOD3, (uint8_t)datarate_m);
kevman 2:7aab896b1a3b 467 rf_write_register(MOD4, datarate_m >> 8);
kevman 2:7aab896b1a3b 468 // Set RX filter bandwidth
kevman 2:7aab896b1a3b 469 uint8_t chflt_m, chflt_e;
kevman 2:7aab896b1a3b 470 rf_conf_calculate_rx_filter_bandwidth_registers(RX_FILTER_BANDWIDTH, &chflt_m, &chflt_e);
kevman 2:7aab896b1a3b 471 rf_write_register_field(CHFLT, CHFLT_M_FIELD, chflt_m << 4);
kevman 2:7aab896b1a3b 472 rf_write_register_field(CHFLT, CHFLT_E_FIELD, chflt_e);
kevman 2:7aab896b1a3b 473 rf_write_register(PCKT_FLT_OPTIONS, 0);
kevman 2:7aab896b1a3b 474 // Set base frequency (Channel 0 center frequency)
kevman 2:7aab896b1a3b 475 uint8_t synt3, synt2, synt1, synt0;
kevman 2:7aab896b1a3b 476 rf_conf_calculate_base_frequency_registers(phy_subghz.channel_0_center_frequency, &synt3, &synt2, &synt1, &synt0);
kevman 2:7aab896b1a3b 477 rf_write_register_field(SYNT3, SYNT_FIELD, synt3);
kevman 2:7aab896b1a3b 478 rf_write_register(SYNT2, synt2);
kevman 2:7aab896b1a3b 479 rf_write_register(SYNT1, synt1);
kevman 2:7aab896b1a3b 480 rf_write_register(SYNT0, synt0);
kevman 2:7aab896b1a3b 481 // Set channel spacing
kevman 2:7aab896b1a3b 482 uint8_t ch_space;
kevman 2:7aab896b1a3b 483 uint8_t ch_space_divider = 1;
kevman 2:7aab896b1a3b 484 while (rf_conf_calculate_channel_spacing_registers(phy_subghz.channel_spacing / ch_space_divider, &ch_space)) {
kevman 2:7aab896b1a3b 485 ch_space_divider++;
kevman 2:7aab896b1a3b 486 rf_channel_multiplier++;
kevman 2:7aab896b1a3b 487 }
kevman 2:7aab896b1a3b 488 rf_write_register(CHSPACE, ch_space);
kevman 2:7aab896b1a3b 489 rf_write_register_field(PCKTCTRL1, PCKT_CRCMODE_FIELD, PCKT_CRCMODE_0X1021);
kevman 2:7aab896b1a3b 490 rf_write_register_field(PCKTCTRL1, PCKT_TXSOURCE_FIELD, PCKT_TXSOURCE_NORMAL);
kevman 2:7aab896b1a3b 491 rf_write_register_field(PCKTCTRL1, PCKT_WHITENING_FIELD, PCKT_WHITENING_ENABLED);
kevman 2:7aab896b1a3b 492 rf_write_register_field(PCKTCTRL2, PCKT_FIXVARLEN_FIELD, PCKT_VARIABLE_LEN);
kevman 2:7aab896b1a3b 493 rf_write_register_field(PCKTCTRL3, PCKT_RXMODE_FIELD, PCKT_RXMODE_NORMAL);
kevman 2:7aab896b1a3b 494 rf_write_register(PCKTCTRL5, PCKT_PREAMBLE_LEN);
kevman 2:7aab896b1a3b 495 rf_write_register_field(PCKTCTRL6, PCKT_SYNCLEN_FIELD, PCKT_SYNCLEN);
kevman 2:7aab896b1a3b 496 rf_write_register_field(QI, PQI_TH_FIELD, PQI_TH);
kevman 2:7aab896b1a3b 497 rf_write_register_field(QI, SQI_EN_FIELD, SQI_EN);
kevman 2:7aab896b1a3b 498 rf_write_register(SYNC0, SFD0);
kevman 2:7aab896b1a3b 499 rf_write_register(SYNC1, SFD1);
kevman 2:7aab896b1a3b 500 // Set RSSI threshold
kevman 2:7aab896b1a3b 501 uint8_t rssi_th;
kevman 2:7aab896b1a3b 502 rf_conf_calculate_rssi_threshold_registers(RSSI_THRESHOLD, &rssi_th);
kevman 2:7aab896b1a3b 503 rf_write_register(RSSI_TH, rssi_th);
kevman 2:7aab896b1a3b 504 }
kevman 2:7aab896b1a3b 505
kevman 2:7aab896b1a3b 506 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
kevman 2:7aab896b1a3b 507 {
kevman 2:7aab896b1a3b 508 int8_t ret_val = 0;
kevman 2:7aab896b1a3b 509 switch (address_type) {
kevman 2:7aab896b1a3b 510 /*Set 48-bit address*/
kevman 2:7aab896b1a3b 511 case PHY_MAC_48BIT:
kevman 2:7aab896b1a3b 512 break;
kevman 2:7aab896b1a3b 513 /*Set 64-bit address*/
kevman 2:7aab896b1a3b 514 case PHY_MAC_64BIT:
kevman 2:7aab896b1a3b 515 memcpy(s2lp_MAC, address_ptr, 8);
kevman 2:7aab896b1a3b 516 break;
kevman 2:7aab896b1a3b 517 /*Set 16-bit address*/
kevman 2:7aab896b1a3b 518 case PHY_MAC_16BIT:
kevman 2:7aab896b1a3b 519 memcpy(s2lp_short_address, address_ptr, 2);
kevman 2:7aab896b1a3b 520 break;
kevman 2:7aab896b1a3b 521 /*Set PAN Id*/
kevman 2:7aab896b1a3b 522 case PHY_MAC_PANID:
kevman 2:7aab896b1a3b 523 memcpy(s2lp_PAN_ID, address_ptr, 2);
kevman 2:7aab896b1a3b 524 break;
kevman 2:7aab896b1a3b 525 }
kevman 2:7aab896b1a3b 526 return ret_val;
kevman 2:7aab896b1a3b 527 }
kevman 2:7aab896b1a3b 528
kevman 2:7aab896b1a3b 529 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
kevman 2:7aab896b1a3b 530 {
kevman 2:7aab896b1a3b 531 int8_t retval = 0;
kevman 2:7aab896b1a3b 532 phy_csma_params_t *csma_params;
kevman 2:7aab896b1a3b 533 uint32_t *timer_value;
kevman 2:7aab896b1a3b 534 switch (extension_type) {
kevman 2:7aab896b1a3b 535 case PHY_EXTENSION_SET_CHANNEL:
kevman 2:7aab896b1a3b 536 if (rf_state == RF_IDLE || rf_state == RF_CSMA_STARTED) {
kevman 2:7aab896b1a3b 537 rf_receive(*data_ptr);
kevman 2:7aab896b1a3b 538 } else {
kevman 2:7aab896b1a3b 539 // Store the new channel if couldn't change it yet.
kevman 2:7aab896b1a3b 540 rf_new_channel = *data_ptr;
kevman 2:7aab896b1a3b 541 retval = -1;
kevman 2:7aab896b1a3b 542 }
kevman 2:7aab896b1a3b 543 break;
kevman 2:7aab896b1a3b 544 case PHY_EXTENSION_CTRL_PENDING_BIT:
kevman 2:7aab896b1a3b 545 break;
kevman 2:7aab896b1a3b 546 /*Return frame pending status*/
kevman 2:7aab896b1a3b 547 case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
kevman 2:7aab896b1a3b 548 break;
kevman 2:7aab896b1a3b 549 case PHY_EXTENSION_ACCEPT_ANY_BEACON:
kevman 2:7aab896b1a3b 550 break;
kevman 2:7aab896b1a3b 551 case PHY_EXTENSION_SET_TX_TIME:
kevman 2:7aab896b1a3b 552 tx_time = common_read_32_bit(data_ptr);
kevman 2:7aab896b1a3b 553 break;
kevman 2:7aab896b1a3b 554 case PHY_EXTENSION_READ_RX_TIME:
kevman 2:7aab896b1a3b 555 common_write_32_bit(rx_time, data_ptr);
kevman 2:7aab896b1a3b 556 break;
kevman 2:7aab896b1a3b 557 case PHY_EXTENSION_DYNAMIC_RF_SUPPORTED:
kevman 2:7aab896b1a3b 558 *data_ptr = true;
kevman 2:7aab896b1a3b 559 break;
kevman 2:7aab896b1a3b 560 case PHY_EXTENSION_GET_TIMESTAMP:
kevman 2:7aab896b1a3b 561 timer_value = (uint32_t *)data_ptr;
kevman 2:7aab896b1a3b 562 *timer_value = rf_get_timestamp();
kevman 2:7aab896b1a3b 563 break;
kevman 2:7aab896b1a3b 564 case PHY_EXTENSION_SET_CSMA_PARAMETERS:
kevman 2:7aab896b1a3b 565 csma_params = (phy_csma_params_t *)data_ptr;
kevman 2:7aab896b1a3b 566 if (csma_params->backoff_time == 0) {
kevman 2:7aab896b1a3b 567 rf_cca_timer_stop();
kevman 2:7aab896b1a3b 568 if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) {
kevman 2:7aab896b1a3b 569 rf_send_command(S2LP_CMD_SABORT);
kevman 2:7aab896b1a3b 570 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 571 rf_send_command(S2LP_CMD_FLUSHTXFIFO);
kevman 2:7aab896b1a3b 572 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 573 }
kevman 2:7aab896b1a3b 574 if (rf_state == RF_TX_STARTED) {
kevman 2:7aab896b1a3b 575 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 576 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 577 }
kevman 2:7aab896b1a3b 578 tx_time = 0;
kevman 2:7aab896b1a3b 579 } else {
kevman 2:7aab896b1a3b 580 tx_time = csma_params->backoff_time;
kevman 2:7aab896b1a3b 581 cca_enabled = csma_params->cca_enabled;
kevman 2:7aab896b1a3b 582 }
kevman 2:7aab896b1a3b 583 break;
kevman 2:7aab896b1a3b 584 case PHY_EXTENSION_READ_TX_FINNISH_TIME:
kevman 2:7aab896b1a3b 585 timer_value = (uint32_t *)data_ptr;
kevman 2:7aab896b1a3b 586 *timer_value = tx_finnish_time;
kevman 2:7aab896b1a3b 587 break;
kevman 2:7aab896b1a3b 588
kevman 2:7aab896b1a3b 589 case PHY_EXTENSION_GET_SYMBOLS_PER_SECOND:
kevman 2:7aab896b1a3b 590 timer_value = (uint32_t *)data_ptr;
kevman 2:7aab896b1a3b 591 *timer_value = symbols_in_seconds;
kevman 2:7aab896b1a3b 592 break;
kevman 2:7aab896b1a3b 593
kevman 2:7aab896b1a3b 594 default:
kevman 2:7aab896b1a3b 595 break;
kevman 2:7aab896b1a3b 596 }
kevman 2:7aab896b1a3b 597
kevman 2:7aab896b1a3b 598 return retval;
kevman 2:7aab896b1a3b 599 }
kevman 2:7aab896b1a3b 600
kevman 2:7aab896b1a3b 601
kevman 2:7aab896b1a3b 602 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
kevman 2:7aab896b1a3b 603 {
kevman 2:7aab896b1a3b 604 int8_t ret_val = 0;
kevman 2:7aab896b1a3b 605 switch (new_state) {
kevman 2:7aab896b1a3b 606 /*Reset PHY driver and set to idle*/
kevman 2:7aab896b1a3b 607 case PHY_INTERFACE_RESET:
kevman 2:7aab896b1a3b 608 break;
kevman 2:7aab896b1a3b 609 /*Disable PHY Interface driver*/
kevman 2:7aab896b1a3b 610 case PHY_INTERFACE_DOWN:
kevman 2:7aab896b1a3b 611 break;
kevman 2:7aab896b1a3b 612 /*Enable PHY Interface driver*/
kevman 2:7aab896b1a3b 613 case PHY_INTERFACE_UP:
kevman 2:7aab896b1a3b 614 rf_receive(rf_channel);
kevman 2:7aab896b1a3b 615 break;
kevman 2:7aab896b1a3b 616 /*Enable wireless interface ED scan mode*/
kevman 2:7aab896b1a3b 617 case PHY_INTERFACE_RX_ENERGY_STATE:
kevman 2:7aab896b1a3b 618 break;
kevman 2:7aab896b1a3b 619 /*Enable Sniffer state*/
kevman 2:7aab896b1a3b 620 case PHY_INTERFACE_SNIFFER_STATE:
kevman 2:7aab896b1a3b 621 break;
kevman 2:7aab896b1a3b 622 }
kevman 2:7aab896b1a3b 623 return ret_val;
kevman 2:7aab896b1a3b 624 }
kevman 2:7aab896b1a3b 625
kevman 2:7aab896b1a3b 626 static void rf_tx_sent_handler(void)
kevman 2:7aab896b1a3b 627 {
kevman 2:7aab896b1a3b 628 rf_backup_timer_stop();
kevman 2:7aab896b1a3b 629 rf_disable_interrupt(TX_DATA_SENT);
kevman 2:7aab896b1a3b 630 if (rf_state != RF_TX_ACK) {
kevman 2:7aab896b1a3b 631 tx_finnish_time = rf_get_timestamp();
kevman 2:7aab896b1a3b 632 TEST_TX_DONE
kevman 2:7aab896b1a3b 633 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 634 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 635 if (device_driver.phy_tx_done_cb) {
kevman 2:7aab896b1a3b 636 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0);
kevman 2:7aab896b1a3b 637 }
kevman 2:7aab896b1a3b 638 } else {
kevman 2:7aab896b1a3b 639 TEST_ACK_TX_DONE
kevman 2:7aab896b1a3b 640 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 641 }
kevman 2:7aab896b1a3b 642 }
kevman 2:7aab896b1a3b 643
kevman 2:7aab896b1a3b 644 static void rf_tx_threshold_handler(void)
kevman 2:7aab896b1a3b 645 {
kevman 2:7aab896b1a3b 646 rf_disable_interrupt(TX_FIFO_ALMOST_EMPTY);
kevman 2:7aab896b1a3b 647 // TODO check the FIFO threshold. By default, threshold is half of the FIFO size
kevman 2:7aab896b1a3b 648 uint8_t written_length = rf_write_tx_fifo(tx_data_ptr, tx_data_length, FIFO_SIZE / 2);
kevman 2:7aab896b1a3b 649 if (written_length < tx_data_length) {
kevman 2:7aab896b1a3b 650 tx_data_ptr += written_length;
kevman 2:7aab896b1a3b 651 tx_data_length -= written_length;
kevman 2:7aab896b1a3b 652 rf_enable_interrupt(TX_FIFO_ALMOST_EMPTY);
kevman 2:7aab896b1a3b 653 }
kevman 2:7aab896b1a3b 654 }
kevman 2:7aab896b1a3b 655
kevman 2:7aab896b1a3b 656 static void rf_start_tx(void)
kevman 2:7aab896b1a3b 657 {
kevman 2:7aab896b1a3b 658 rf_disable_all_interrupts();
kevman 2:7aab896b1a3b 659 // More TX data to be written in FIFO when TX threshold interrupt occurs
kevman 2:7aab896b1a3b 660 if (tx_data_ptr) {
kevman 2:7aab896b1a3b 661 rf_enable_interrupt(TX_FIFO_ALMOST_EMPTY);
kevman 2:7aab896b1a3b 662 }
kevman 2:7aab896b1a3b 663 rf_enable_interrupt(TX_DATA_SENT);
kevman 2:7aab896b1a3b 664 rf_enable_interrupt(TX_FIFO_UNF_OVF);
kevman 2:7aab896b1a3b 665 rf_state_change(S2LP_STATE_READY, false);
kevman 2:7aab896b1a3b 666 rf_state_change(S2LP_STATE_LOCK, true);
kevman 2:7aab896b1a3b 667 rf_state_change(S2LP_STATE_TX, false);
kevman 2:7aab896b1a3b 668 rf_backup_timer_start(MAX_PACKET_SENDING_TIME);
kevman 2:7aab896b1a3b 669 }
kevman 2:7aab896b1a3b 670
kevman 2:7aab896b1a3b 671 static void rf_cca_timer_interrupt(void)
kevman 2:7aab896b1a3b 672 {
kevman 2:7aab896b1a3b 673 if (device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_PREPARE, 0, 0) != 0) {
kevman 2:7aab896b1a3b 674 if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) {
kevman 2:7aab896b1a3b 675 rf_send_command(S2LP_CMD_FLUSHTXFIFO);
kevman 2:7aab896b1a3b 676 }
kevman 2:7aab896b1a3b 677 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 678 return;
kevman 2:7aab896b1a3b 679 }
kevman 2:7aab896b1a3b 680 if ((cca_enabled == true) && (rf_read_register_with_status(LINK_QUALIF1, NULL) & CARRIER_SENSE || (rf_state != RF_CSMA_STARTED && rf_state != RF_IDLE))) {
kevman 2:7aab896b1a3b 681 if (rf_state == RF_CSMA_STARTED) {
kevman 2:7aab896b1a3b 682 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 683 }
kevman 2:7aab896b1a3b 684 if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) {
kevman 2:7aab896b1a3b 685 rf_send_command(S2LP_CMD_FLUSHTXFIFO);
kevman 2:7aab896b1a3b 686 }
kevman 2:7aab896b1a3b 687 tx_finnish_time = rf_get_timestamp();
kevman 2:7aab896b1a3b 688 if (device_driver.phy_tx_done_cb) {
kevman 2:7aab896b1a3b 689 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
kevman 2:7aab896b1a3b 690 }
kevman 2:7aab896b1a3b 691 } else {
kevman 2:7aab896b1a3b 692 rf_start_tx();
kevman 2:7aab896b1a3b 693 rf_state = RF_TX_STARTED;
kevman 2:7aab896b1a3b 694 TEST_TX_STARTED
kevman 2:7aab896b1a3b 695 }
kevman 2:7aab896b1a3b 696 }
kevman 2:7aab896b1a3b 697
kevman 2:7aab896b1a3b 698 static void rf_cca_timer_stop(void)
kevman 2:7aab896b1a3b 699 {
kevman 2:7aab896b1a3b 700 rf->cca_timer.detach();
kevman 2:7aab896b1a3b 701 }
kevman 2:7aab896b1a3b 702
kevman 2:7aab896b1a3b 703 static void rf_cca_timer_start(uint32_t slots)
kevman 2:7aab896b1a3b 704 {
kevman 2:7aab896b1a3b 705 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 706 rf->cca_timer.attach_us(rf_cca_timer_signal, slots);
kevman 2:7aab896b1a3b 707 #else //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 708 rf->cca_timer.attach_us(rf_cca_timer_interrupt, slots);
kevman 2:7aab896b1a3b 709 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 710 }
kevman 2:7aab896b1a3b 711
kevman 2:7aab896b1a3b 712 static void rf_backup_timer_interrupt(void)
kevman 2:7aab896b1a3b 713 {
kevman 2:7aab896b1a3b 714 tx_finnish_time = rf_get_timestamp();
kevman 2:7aab896b1a3b 715 if (rf_state == RF_TX_STARTED) {
kevman 2:7aab896b1a3b 716 if (device_driver.phy_tx_done_cb) {
kevman 2:7aab896b1a3b 717 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0);
kevman 2:7aab896b1a3b 718 }
kevman 2:7aab896b1a3b 719 }
kevman 2:7aab896b1a3b 720 if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) {
kevman 2:7aab896b1a3b 721 rf_send_command(S2LP_CMD_FLUSHTXFIFO);
kevman 2:7aab896b1a3b 722 }
kevman 2:7aab896b1a3b 723 TEST_TX_DONE
kevman 2:7aab896b1a3b 724 TEST_RX_DONE
kevman 2:7aab896b1a3b 725 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 726 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 727 }
kevman 2:7aab896b1a3b 728
kevman 2:7aab896b1a3b 729 static void rf_backup_timer_stop(void)
kevman 2:7aab896b1a3b 730 {
kevman 2:7aab896b1a3b 731 rf->backup_timer.detach();
kevman 2:7aab896b1a3b 732 }
kevman 2:7aab896b1a3b 733
kevman 2:7aab896b1a3b 734 static void rf_backup_timer_start(uint32_t slots)
kevman 2:7aab896b1a3b 735 {
kevman 2:7aab896b1a3b 736 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 737 rf->backup_timer.attach_us(rf_backup_timer_signal, slots);
kevman 2:7aab896b1a3b 738 #else //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 739 rf->backup_timer.attach_us(rf_backup_timer_interrupt, slots);
kevman 2:7aab896b1a3b 740 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 741 }
kevman 2:7aab896b1a3b 742
kevman 2:7aab896b1a3b 743 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 744 {
kevman 2:7aab896b1a3b 745 rf_lock();
kevman 2:7aab896b1a3b 746 if (rf_state != RF_IDLE) {
kevman 2:7aab896b1a3b 747 rf_unlock();
kevman 2:7aab896b1a3b 748 return -1;
kevman 2:7aab896b1a3b 749 }
kevman 2:7aab896b1a3b 750 rf_state = RF_CSMA_STARTED;
kevman 2:7aab896b1a3b 751 uint8_t written_length = rf_write_tx_fifo(data_ptr, data_length, FIFO_SIZE);
kevman 2:7aab896b1a3b 752 if (written_length < data_length) {
kevman 2:7aab896b1a3b 753 tx_data_ptr = data_ptr + written_length;
kevman 2:7aab896b1a3b 754 tx_data_length = data_length - written_length;
kevman 2:7aab896b1a3b 755 } else {
kevman 2:7aab896b1a3b 756 tx_data_ptr = NULL;
kevman 2:7aab896b1a3b 757 }
kevman 2:7aab896b1a3b 758 // If Ack is requested, store the MAC sequence. This will be compared with received Ack.
kevman 2:7aab896b1a3b 759 uint8_t version = ((*(data_ptr + 1) & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD);
kevman 2:7aab896b1a3b 760 if ((version != MAC_FRAME_VERSION_2) && (*data_ptr & FC_AR)) {
kevman 2:7aab896b1a3b 761 tx_sequence = *(data_ptr + 2);
kevman 2:7aab896b1a3b 762 }
kevman 2:7aab896b1a3b 763 // TODO: Define this better
kevman 2:7aab896b1a3b 764 rf_write_packet_length(data_length + 4);
kevman 2:7aab896b1a3b 765 mac_tx_handle = tx_handle;
kevman 2:7aab896b1a3b 766 if (tx_time) {
kevman 2:7aab896b1a3b 767 uint32_t backoff_time = tx_time - rf_get_timestamp();
kevman 2:7aab896b1a3b 768 // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately
kevman 2:7aab896b1a3b 769 if (backoff_time <= 65000) {
kevman 2:7aab896b1a3b 770 rf_cca_timer_start(backoff_time);
kevman 2:7aab896b1a3b 771 rf_unlock();
kevman 2:7aab896b1a3b 772 return 0;
kevman 2:7aab896b1a3b 773 }
kevman 2:7aab896b1a3b 774 }
kevman 2:7aab896b1a3b 775 rf_cca_timer_interrupt();
kevman 2:7aab896b1a3b 776 rf_unlock();
kevman 2:7aab896b1a3b 777 return 0;
kevman 2:7aab896b1a3b 778 }
kevman 2:7aab896b1a3b 779
kevman 2:7aab896b1a3b 780 static void rf_send_ack(uint8_t seq)
kevman 2:7aab896b1a3b 781 {
kevman 2:7aab896b1a3b 782 // If the reception started during CCA process, the TX FIFO may already contain a data packet
kevman 2:7aab896b1a3b 783 if (rf_read_register_with_status(TX_FIFO_STATUS, NULL)) {
kevman 2:7aab896b1a3b 784 rf_send_command(S2LP_CMD_SABORT);
kevman 2:7aab896b1a3b 785 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 786 rf_send_command(S2LP_CMD_FLUSHTXFIFO);
kevman 2:7aab896b1a3b 787 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 788 }
kevman 2:7aab896b1a3b 789 rf_state = RF_TX_ACK;
kevman 2:7aab896b1a3b 790 uint8_t ack_frame[3] = {MAC_TYPE_ACK, 0, seq};
kevman 2:7aab896b1a3b 791 rf_write_tx_fifo(ack_frame, sizeof(ack_frame), FIFO_SIZE);
kevman 2:7aab896b1a3b 792 rf_write_packet_length(sizeof(ack_frame) + 4);
kevman 2:7aab896b1a3b 793 tx_data_ptr = NULL;
kevman 2:7aab896b1a3b 794 rf_start_tx();
kevman 2:7aab896b1a3b 795 TEST_ACK_TX_STARTED
kevman 2:7aab896b1a3b 796 rf_backup_timer_start(ACK_SENDING_TIME);
kevman 2:7aab896b1a3b 797 }
kevman 2:7aab896b1a3b 798
kevman 2:7aab896b1a3b 799 static void rf_handle_ack(uint8_t seq_number, uint8_t pending)
kevman 2:7aab896b1a3b 800 {
kevman 2:7aab896b1a3b 801 phy_link_tx_status_e phy_status;
kevman 2:7aab896b1a3b 802 if (tx_sequence == (uint16_t)seq_number) {
kevman 2:7aab896b1a3b 803 tx_finnish_time = rf_get_timestamp();
kevman 2:7aab896b1a3b 804 if (pending) {
kevman 2:7aab896b1a3b 805 phy_status = PHY_LINK_TX_DONE_PENDING;
kevman 2:7aab896b1a3b 806 } else {
kevman 2:7aab896b1a3b 807 phy_status = PHY_LINK_TX_DONE;
kevman 2:7aab896b1a3b 808 }
kevman 2:7aab896b1a3b 809 // No CCA attempts done, just waited Ack
kevman 2:7aab896b1a3b 810 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status, 0, 0);
kevman 2:7aab896b1a3b 811 // Clear TX sequence when Ack is received to avoid duplicate Acks
kevman 2:7aab896b1a3b 812 tx_sequence = 0xffff;
kevman 2:7aab896b1a3b 813 }
kevman 2:7aab896b1a3b 814 }
kevman 2:7aab896b1a3b 815
kevman 2:7aab896b1a3b 816 static void rf_rx_ready_handler(void)
kevman 2:7aab896b1a3b 817 {
kevman 2:7aab896b1a3b 818 rf_backup_timer_stop();
kevman 2:7aab896b1a3b 819 TEST_RX_DONE
kevman 2:7aab896b1a3b 820 rx_data_length += rf_read_rx_fifo(&rx_buffer[rx_data_length], rf_read_register_with_status(RX_FIFO_STATUS, NULL));
kevman 2:7aab896b1a3b 821 uint8_t version = ((rx_buffer[1] & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD);
kevman 2:7aab896b1a3b 822 if (((rx_buffer[0] & MAC_FRAME_TYPE_MASK) == MAC_TYPE_ACK) && (version < MAC_FRAME_VERSION_2)) {
kevman 2:7aab896b1a3b 823 rf_handle_ack(rx_buffer[2], rx_buffer[0] & MAC_DATA_PENDING);
kevman 2:7aab896b1a3b 824 } else if (rf_rx_filter(rx_buffer, s2lp_MAC, s2lp_short_address, s2lp_PAN_ID)) {
kevman 2:7aab896b1a3b 825 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 826 int8_t rssi = (rf_read_register_with_status(RSSI_LEVEL, NULL) - RSSI_OFFSET);
kevman 2:7aab896b1a3b 827 if (device_driver.phy_rx_cb) {
kevman 2:7aab896b1a3b 828 device_driver.phy_rx_cb(rx_buffer, rx_data_length, 0xf0, rssi, rf_radio_driver_id);
kevman 2:7aab896b1a3b 829 }
kevman 2:7aab896b1a3b 830 // Check Ack request
kevman 2:7aab896b1a3b 831 if ((version != MAC_FRAME_VERSION_2) && (rx_buffer[0] & FC_AR)) {
kevman 2:7aab896b1a3b 832 rf_send_ack(rx_buffer[2]);
kevman 2:7aab896b1a3b 833 }
kevman 2:7aab896b1a3b 834 }
kevman 2:7aab896b1a3b 835 if ((rf_state != RF_TX_ACK) && (rf_state != RF_CSMA_STARTED)) {
kevman 2:7aab896b1a3b 836 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 837 }
kevman 2:7aab896b1a3b 838 }
kevman 2:7aab896b1a3b 839
kevman 2:7aab896b1a3b 840 static void rf_rx_threshold_handler(void)
kevman 2:7aab896b1a3b 841 {
kevman 2:7aab896b1a3b 842 rx_data_length += rf_read_rx_fifo(&rx_buffer[rx_data_length], rf_read_register_with_status(RX_FIFO_STATUS, NULL));
kevman 2:7aab896b1a3b 843 }
kevman 2:7aab896b1a3b 844
kevman 2:7aab896b1a3b 845 static void rf_sync_detected_handler(void)
kevman 2:7aab896b1a3b 846 {
kevman 2:7aab896b1a3b 847 rx_time = rf_get_timestamp();
kevman 2:7aab896b1a3b 848 rf_state = RF_RX_STARTED;
kevman 2:7aab896b1a3b 849 TEST_RX_STARTED
kevman 2:7aab896b1a3b 850 rf_disable_interrupt(SYNC_WORD);
kevman 2:7aab896b1a3b 851 rf_backup_timer_start(MAX_PACKET_SENDING_TIME);
kevman 2:7aab896b1a3b 852 }
kevman 2:7aab896b1a3b 853
kevman 2:7aab896b1a3b 854 static void rf_receive(uint8_t rx_channel)
kevman 2:7aab896b1a3b 855 {
kevman 2:7aab896b1a3b 856 if (rf_state == RF_TX_STARTED) {
kevman 2:7aab896b1a3b 857 return;
kevman 2:7aab896b1a3b 858 }
kevman 2:7aab896b1a3b 859 rf_lock();
kevman 2:7aab896b1a3b 860 rf_disable_all_interrupts();
kevman 2:7aab896b1a3b 861 rf_state_change(S2LP_STATE_READY, false);
kevman 2:7aab896b1a3b 862 rf_send_command(S2LP_CMD_FLUSHRXFIFO);
kevman 2:7aab896b1a3b 863 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 864 if (rx_channel != rf_rx_channel) {
kevman 2:7aab896b1a3b 865 rf_write_register(CHNUM, rx_channel * rf_channel_multiplier);
kevman 2:7aab896b1a3b 866 rf_rx_channel = rf_new_channel = rx_channel;
kevman 2:7aab896b1a3b 867 }
kevman 2:7aab896b1a3b 868 rf_state_change(S2LP_STATE_LOCK, false);
kevman 2:7aab896b1a3b 869 rf_state_change(S2LP_STATE_RX, false);
kevman 2:7aab896b1a3b 870 rf_enable_interrupt(SYNC_WORD);
kevman 2:7aab896b1a3b 871 rf_enable_interrupt(RX_FIFO_ALMOST_FULL);
kevman 2:7aab896b1a3b 872 rf_enable_interrupt(RX_DATA_READY);
kevman 2:7aab896b1a3b 873 rf_enable_interrupt(RX_FIFO_UNF_OVF);
kevman 2:7aab896b1a3b 874 rx_data_length = 0;
kevman 2:7aab896b1a3b 875 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 876 rf_unlock();
kevman 2:7aab896b1a3b 877 }
kevman 2:7aab896b1a3b 878
kevman 2:7aab896b1a3b 879 #ifdef MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 880 static void rf_interrupt_handler(void)
kevman 2:7aab896b1a3b 881 {
kevman 2:7aab896b1a3b 882 rf->irq_thread.signal_set(SIG_RADIO);
kevman 2:7aab896b1a3b 883 }
kevman 2:7aab896b1a3b 884
kevman 2:7aab896b1a3b 885 void RFPins::rf_irq_task(void)
kevman 2:7aab896b1a3b 886 {
kevman 2:7aab896b1a3b 887 for (;;) {
kevman 2:7aab896b1a3b 888 osEvent event = irq_thread.signal_wait(0);
kevman 2:7aab896b1a3b 889 if (event.status != osEventSignal) {
kevman 2:7aab896b1a3b 890 continue;
kevman 2:7aab896b1a3b 891 }
kevman 2:7aab896b1a3b 892 rf_lock();
kevman 2:7aab896b1a3b 893 if (event.value.signals & SIG_RADIO) {
kevman 2:7aab896b1a3b 894 rf_irq_task_process_irq();
kevman 2:7aab896b1a3b 895 }
kevman 2:7aab896b1a3b 896 if (event.value.signals & SIG_TIMER_CCA) {
kevman 2:7aab896b1a3b 897 rf_cca_timer_interrupt();
kevman 2:7aab896b1a3b 898 }
kevman 2:7aab896b1a3b 899 if (event.value.signals & SIG_TIMER_BACKUP) {
kevman 2:7aab896b1a3b 900 rf_backup_timer_interrupt();
kevman 2:7aab896b1a3b 901 }
kevman 2:7aab896b1a3b 902 rf_unlock();
kevman 2:7aab896b1a3b 903 }
kevman 2:7aab896b1a3b 904 }
kevman 2:7aab896b1a3b 905
kevman 2:7aab896b1a3b 906 static void rf_irq_task_process_irq(void)
kevman 2:7aab896b1a3b 907 #else //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 908 static void rf_interrupt_handler(void)
kevman 2:7aab896b1a3b 909 #endif //MBED_CONF_RTOS_PRESENT
kevman 2:7aab896b1a3b 910 {
kevman 2:7aab896b1a3b 911 rf_lock();
kevman 2:7aab896b1a3b 912 uint32_t irq_status = read_irq_status();
kevman 2:7aab896b1a3b 913 if (rf_state == RF_TX_STARTED || rf_state == RF_TX_ACK) {
kevman 2:7aab896b1a3b 914 if ((irq_status & (1 << TX_DATA_SENT)) && (enabled_interrupts & (1 << TX_DATA_SENT))) {
kevman 2:7aab896b1a3b 915 rf_tx_sent_handler();
kevman 2:7aab896b1a3b 916 }
kevman 2:7aab896b1a3b 917 }
kevman 2:7aab896b1a3b 918 if (rf_state == RF_TX_STARTED) {
kevman 2:7aab896b1a3b 919 if ((irq_status & (1 << TX_FIFO_ALMOST_EMPTY)) && (enabled_interrupts & (1 << TX_FIFO_ALMOST_EMPTY))) {
kevman 2:7aab896b1a3b 920 rf_tx_threshold_handler();
kevman 2:7aab896b1a3b 921 }
kevman 2:7aab896b1a3b 922 }
kevman 2:7aab896b1a3b 923 if ((irq_status & (1 << TX_FIFO_UNF_OVF)) && (enabled_interrupts & (1 << TX_FIFO_UNF_OVF))) {
kevman 2:7aab896b1a3b 924 tx_finnish_time = rf_get_timestamp();
kevman 2:7aab896b1a3b 925 TEST_TX_DONE
kevman 2:7aab896b1a3b 926 device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 1, 0);
kevman 2:7aab896b1a3b 927 rf_send_command(S2LP_CMD_SABORT);
kevman 2:7aab896b1a3b 928 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 929 rf_send_command(S2LP_CMD_FLUSHTXFIFO);
kevman 2:7aab896b1a3b 930 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 931 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 932 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 933 }
kevman 2:7aab896b1a3b 934 if (rf_state == RF_IDLE || rf_state == RF_TX_STARTED) {
kevman 2:7aab896b1a3b 935 if ((irq_status & (1 << SYNC_WORD)) && (enabled_interrupts & (1 << SYNC_WORD))) {
kevman 2:7aab896b1a3b 936 rf_sync_detected_handler();
kevman 2:7aab896b1a3b 937 }
kevman 2:7aab896b1a3b 938 } else if (rf_state == RF_RX_STARTED) {
kevman 2:7aab896b1a3b 939 if ((irq_status & (1 << RX_DATA_READY)) && (enabled_interrupts & (1 << RX_DATA_READY))) {
kevman 2:7aab896b1a3b 940 if (!(irq_status & (1 << CRC_ERROR))) {
kevman 2:7aab896b1a3b 941 rf_rx_ready_handler();
kevman 2:7aab896b1a3b 942 } else {
kevman 2:7aab896b1a3b 943 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 944 // In case the channel change was called during reception, driver is responsible to change the channel if CRC failed.
kevman 2:7aab896b1a3b 945 rf_receive(rf_new_channel);
kevman 2:7aab896b1a3b 946 }
kevman 2:7aab896b1a3b 947 }
kevman 2:7aab896b1a3b 948 if ((irq_status & (1 << RX_FIFO_ALMOST_FULL)) && (enabled_interrupts & (1 << RX_FIFO_ALMOST_FULL))) {
kevman 2:7aab896b1a3b 949 rf_rx_threshold_handler();
kevman 2:7aab896b1a3b 950 }
kevman 2:7aab896b1a3b 951 if ((irq_status & (1 << RX_DATA_DISCARDED)) && (enabled_interrupts & (1 << RX_DATA_DISCARDED))) {
kevman 2:7aab896b1a3b 952
kevman 2:7aab896b1a3b 953 }
kevman 2:7aab896b1a3b 954 if ((irq_status & (1 << CRC_ERROR)) && (enabled_interrupts & (1 << CRC_ERROR))) {
kevman 2:7aab896b1a3b 955
kevman 2:7aab896b1a3b 956 }
kevman 2:7aab896b1a3b 957 }
kevman 2:7aab896b1a3b 958 if ((irq_status & (1 << RX_FIFO_UNF_OVF)) && (enabled_interrupts & (1 << RX_FIFO_UNF_OVF))) {
kevman 2:7aab896b1a3b 959 TEST_RX_DONE
kevman 2:7aab896b1a3b 960 rf_send_command(S2LP_CMD_SABORT);
kevman 2:7aab896b1a3b 961 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 962 rf_send_command(S2LP_CMD_FLUSHRXFIFO);
kevman 2:7aab896b1a3b 963 rf_poll_state_change(S2LP_STATE_READY);
kevman 2:7aab896b1a3b 964 rf_state = RF_IDLE;
kevman 2:7aab896b1a3b 965 rf_receive(rf_rx_channel);
kevman 2:7aab896b1a3b 966 }
kevman 2:7aab896b1a3b 967 rf_unlock();
kevman 2:7aab896b1a3b 968 }
kevman 2:7aab896b1a3b 969
kevman 2:7aab896b1a3b 970 static void rf_reset(void)
kevman 2:7aab896b1a3b 971 {
kevman 2:7aab896b1a3b 972 // Shutdown
kevman 2:7aab896b1a3b 973 rf->SDN = 1;
kevman 2:7aab896b1a3b 974 wait_ms(10);
kevman 2:7aab896b1a3b 975 // Wake up
kevman 2:7aab896b1a3b 976 rf->SDN = 0;
kevman 2:7aab896b1a3b 977 // Wait until GPIO0 (RESETN) goes high
kevman 2:7aab896b1a3b 978 while (rf->RF_S2LP_GPIO0 == 0);
kevman 2:7aab896b1a3b 979 }
kevman 2:7aab896b1a3b 980
kevman 2:7aab896b1a3b 981 static void rf_init(void)
kevman 2:7aab896b1a3b 982 {
kevman 2:7aab896b1a3b 983 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 984 fhss_bc_switch = test1_toggle;
kevman 2:7aab896b1a3b 985 fhss_uc_switch = test2_toggle;
kevman 2:7aab896b1a3b 986 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 987 rf_reset();
kevman 2:7aab896b1a3b 988 rf->spi.frequency(10000000);
kevman 2:7aab896b1a3b 989 CS_RELEASE();
kevman 2:7aab896b1a3b 990 if (PARTNUM != rf_read_register_with_status(DEVICE_INFO1, NULL)) {
kevman 2:7aab896b1a3b 991 tr_err("Invalid part number: %x", rf_read_register_with_status(DEVICE_INFO1, NULL));
kevman 2:7aab896b1a3b 992 }
kevman 2:7aab896b1a3b 993 if (VERSION != rf_read_register_with_status(DEVICE_INFO0, NULL)) {
kevman 2:7aab896b1a3b 994 tr_err("Invalid version: %x", rf_read_register_with_status(DEVICE_INFO0, NULL));
kevman 2:7aab896b1a3b 995 }
kevman 2:7aab896b1a3b 996 rf_init_registers();
kevman 2:7aab896b1a3b 997 rf_enable_gpio_interrupt();
kevman 2:7aab896b1a3b 998 rf_calculate_symbols_in_seconds(phy_subghz.datarate, phy_subghz.modulation);
kevman 2:7aab896b1a3b 999 rf->tx_timer.start();
kevman 2:7aab896b1a3b 1000 rf_print_registers();
kevman 2:7aab896b1a3b 1001 }
kevman 2:7aab896b1a3b 1002
kevman 2:7aab896b1a3b 1003 static int8_t rf_device_register(const uint8_t *mac_addr)
kevman 2:7aab896b1a3b 1004 {
kevman 2:7aab896b1a3b 1005 rf_init();
kevman 2:7aab896b1a3b 1006 /*Set pointer to MAC address*/
kevman 2:7aab896b1a3b 1007 device_driver.PHY_MAC = (uint8_t *)mac_addr;
kevman 2:7aab896b1a3b 1008 device_driver.driver_description = (char *)"S2LP_MAC";
kevman 2:7aab896b1a3b 1009 device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
kevman 2:7aab896b1a3b 1010 device_driver.phy_channel_pages = phy_channel_pages;
kevman 2:7aab896b1a3b 1011 device_driver.phy_MTU = RF_MTU;
kevman 2:7aab896b1a3b 1012 /*No header in PHY*/
kevman 2:7aab896b1a3b 1013 device_driver.phy_header_length = 0;
kevman 2:7aab896b1a3b 1014 /*No tail in PHY*/
kevman 2:7aab896b1a3b 1015 device_driver.phy_tail_length = 0;
kevman 2:7aab896b1a3b 1016 /*Set address write function*/
kevman 2:7aab896b1a3b 1017 device_driver.address_write = &rf_address_write;
kevman 2:7aab896b1a3b 1018 /*Set RF extension function*/
kevman 2:7aab896b1a3b 1019 device_driver.extension = &rf_extension;
kevman 2:7aab896b1a3b 1020 /*Set RF state control function*/
kevman 2:7aab896b1a3b 1021 device_driver.state_control = &rf_interface_state_control;
kevman 2:7aab896b1a3b 1022 /*Set transmit function*/
kevman 2:7aab896b1a3b 1023 device_driver.tx = &rf_start_cca;
kevman 2:7aab896b1a3b 1024 /*NULLIFY rx and tx_done callbacks*/
kevman 2:7aab896b1a3b 1025 device_driver.phy_rx_cb = NULL;
kevman 2:7aab896b1a3b 1026 device_driver.phy_tx_done_cb = NULL;
kevman 2:7aab896b1a3b 1027 /*Register device driver*/
kevman 2:7aab896b1a3b 1028 rf_radio_driver_id = arm_net_phy_register(&device_driver);
kevman 2:7aab896b1a3b 1029 return rf_radio_driver_id;
kevman 2:7aab896b1a3b 1030 }
kevman 2:7aab896b1a3b 1031
kevman 2:7aab896b1a3b 1032 static void rf_device_unregister()
kevman 2:7aab896b1a3b 1033 {
kevman 2:7aab896b1a3b 1034 if (rf_radio_driver_id >= 0) {
kevman 2:7aab896b1a3b 1035 arm_net_phy_unregister(rf_radio_driver_id);
kevman 2:7aab896b1a3b 1036 rf_radio_driver_id = -1;
kevman 2:7aab896b1a3b 1037 }
kevman 2:7aab896b1a3b 1038 }
kevman 2:7aab896b1a3b 1039
kevman 2:7aab896b1a3b 1040 void NanostackRfPhys2lp::get_mac_address(uint8_t *mac)
kevman 2:7aab896b1a3b 1041 {
kevman 2:7aab896b1a3b 1042
kevman 2:7aab896b1a3b 1043 }
kevman 2:7aab896b1a3b 1044
kevman 2:7aab896b1a3b 1045 void NanostackRfPhys2lp::set_mac_address(uint8_t *mac)
kevman 2:7aab896b1a3b 1046 {
kevman 2:7aab896b1a3b 1047
kevman 2:7aab896b1a3b 1048 }
kevman 2:7aab896b1a3b 1049
kevman 2:7aab896b1a3b 1050 int8_t NanostackRfPhys2lp::rf_register()
kevman 2:7aab896b1a3b 1051 {
kevman 2:7aab896b1a3b 1052 if (NULL == _rf) {
kevman 2:7aab896b1a3b 1053 return -1;
kevman 2:7aab896b1a3b 1054 }
kevman 2:7aab896b1a3b 1055 rf_lock();
kevman 2:7aab896b1a3b 1056 if (rf != NULL) {
kevman 2:7aab896b1a3b 1057 rf_unlock();
kevman 2:7aab896b1a3b 1058 error("Multiple registrations of NanostackRfPhyAtmel not supported");
kevman 2:7aab896b1a3b 1059 return -1;
kevman 2:7aab896b1a3b 1060 }
kevman 2:7aab896b1a3b 1061 rf = _rf;
kevman 2:7aab896b1a3b 1062 int8_t radio_id = rf_device_register(_mac_addr);
kevman 2:7aab896b1a3b 1063 if (radio_id < 0) {
kevman 2:7aab896b1a3b 1064 rf = NULL;
kevman 2:7aab896b1a3b 1065 }
kevman 2:7aab896b1a3b 1066 rf_unlock();
kevman 2:7aab896b1a3b 1067 return radio_id;
kevman 2:7aab896b1a3b 1068 }
kevman 2:7aab896b1a3b 1069
kevman 2:7aab896b1a3b 1070 void NanostackRfPhys2lp::rf_unregister()
kevman 2:7aab896b1a3b 1071 {
kevman 2:7aab896b1a3b 1072 rf_lock();
kevman 2:7aab896b1a3b 1073 if (NULL == rf) {
kevman 2:7aab896b1a3b 1074 rf_unlock();
kevman 2:7aab896b1a3b 1075 return;
kevman 2:7aab896b1a3b 1076 }
kevman 2:7aab896b1a3b 1077 rf_device_unregister();
kevman 2:7aab896b1a3b 1078 rf = NULL;
kevman 2:7aab896b1a3b 1079 rf_unlock();
kevman 2:7aab896b1a3b 1080 }
kevman 2:7aab896b1a3b 1081
kevman 2:7aab896b1a3b 1082 NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn,
kevman 2:7aab896b1a3b 1083 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1084 PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5,
kevman 2:7aab896b1a3b 1085 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1086 PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3)
kevman 2:7aab896b1a3b 1087 : _mac_addr(), _rf(NULL), _mac_set(false),
kevman 2:7aab896b1a3b 1088 _spi_sdi(spi_sdi), _spi_sdo(spi_sdo), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_sdn(spi_sdn),
kevman 2:7aab896b1a3b 1089 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1090 _spi_test1(spi_test1), _spi_test2(spi_test2), _spi_test3(spi_test3), _spi_test4(spi_test4), _spi_test5(spi_test5),
kevman 2:7aab896b1a3b 1091 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1092 _spi_gpio0(spi_gpio0), _spi_gpio1(spi_gpio1), _spi_gpio2(spi_gpio2), _spi_gpio3(spi_gpio3)
kevman 2:7aab896b1a3b 1093 {
kevman 2:7aab896b1a3b 1094 _rf = new RFPins(_spi_sdi, _spi_sdo, _spi_sclk, _spi_cs, _spi_sdn,
kevman 2:7aab896b1a3b 1095 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1096 _spi_test1, _spi_test2, _spi_test3, _spi_test4, _spi_test5,
kevman 2:7aab896b1a3b 1097 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1098 _spi_gpio0, _spi_gpio1, _spi_gpio2, _spi_gpio3);
kevman 2:7aab896b1a3b 1099 }
kevman 2:7aab896b1a3b 1100
kevman 2:7aab896b1a3b 1101 NanostackRfPhys2lp::~NanostackRfPhys2lp()
kevman 2:7aab896b1a3b 1102 {
kevman 2:7aab896b1a3b 1103 delete _rf;
kevman 2:7aab896b1a3b 1104 }
kevman 2:7aab896b1a3b 1105
kevman 2:7aab896b1a3b 1106 static bool rf_panid_filter_common(uint8_t *panid_start, uint8_t *pan_id, uint8_t frame_type)
kevman 2:7aab896b1a3b 1107 {
kevman 2:7aab896b1a3b 1108 // PHY driver shouldn't drop received Beacon frames as they might be used by load balancing
kevman 2:7aab896b1a3b 1109 if (frame_type == MAC_FRAME_BEACON) {
kevman 2:7aab896b1a3b 1110 return true;
kevman 2:7aab896b1a3b 1111 }
kevman 2:7aab896b1a3b 1112 bool retval = true;
kevman 2:7aab896b1a3b 1113 uint8_t cmp_table[2] = {0xff, 0xff};
kevman 2:7aab896b1a3b 1114 if (!(pan_id[0] == 0xff && pan_id[1] == 0xff)) {
kevman 2:7aab896b1a3b 1115 if (memcmp((uint8_t *)panid_start, (uint8_t *) cmp_table, 2)) {
kevman 2:7aab896b1a3b 1116 retval = false;
kevman 2:7aab896b1a3b 1117 }
kevman 2:7aab896b1a3b 1118 if (!retval) {
kevman 2:7aab896b1a3b 1119 for (uint8_t i = 0; i < 2; i++) {
kevman 2:7aab896b1a3b 1120 cmp_table[1 - i] = panid_start[i];
kevman 2:7aab896b1a3b 1121 }
kevman 2:7aab896b1a3b 1122 if (!memcmp(pan_id, cmp_table, 2)) {
kevman 2:7aab896b1a3b 1123 retval = true;
kevman 2:7aab896b1a3b 1124 }
kevman 2:7aab896b1a3b 1125 }
kevman 2:7aab896b1a3b 1126 }
kevman 2:7aab896b1a3b 1127 return retval;
kevman 2:7aab896b1a3b 1128 }
kevman 2:7aab896b1a3b 1129
kevman 2:7aab896b1a3b 1130 static bool rf_panid_v2_filter(uint8_t *ptr, uint8_t *pan_id, uint8_t dst_mode, uint8_t src_mode, uint8_t seq_compressed, uint8_t panid_compressed, uint8_t frame_type)
kevman 2:7aab896b1a3b 1131 {
kevman 2:7aab896b1a3b 1132 if ((dst_mode == FC_DST_ADDR_NONE) && (frame_type == MAC_TYPE_DATA || frame_type == MAC_TYPE_COMMAND)) {
kevman 2:7aab896b1a3b 1133 return true;
kevman 2:7aab896b1a3b 1134 }
kevman 2:7aab896b1a3b 1135 if ((dst_mode == FC_DST_64_BITS) && (src_mode == FC_SRC_64_BITS) && panid_compressed) {
kevman 2:7aab896b1a3b 1136 return true;
kevman 2:7aab896b1a3b 1137 }
kevman 2:7aab896b1a3b 1138 if (seq_compressed) {
kevman 2:7aab896b1a3b 1139 ptr--;
kevman 2:7aab896b1a3b 1140 }
kevman 2:7aab896b1a3b 1141 return rf_panid_filter_common(ptr, pan_id, frame_type);
kevman 2:7aab896b1a3b 1142 }
kevman 2:7aab896b1a3b 1143
kevman 2:7aab896b1a3b 1144 static bool rf_panid_v1_v0_filter(uint8_t *ptr, uint8_t *pan_id, uint8_t frame_type)
kevman 2:7aab896b1a3b 1145 {
kevman 2:7aab896b1a3b 1146 return rf_panid_filter_common(ptr, pan_id, frame_type);
kevman 2:7aab896b1a3b 1147 }
kevman 2:7aab896b1a3b 1148
kevman 2:7aab896b1a3b 1149 static bool rf_addr_filter_common(uint8_t *ptr, uint8_t addr_mode, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr)
kevman 2:7aab896b1a3b 1150 {
kevman 2:7aab896b1a3b 1151 uint8_t cmp_table[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
kevman 2:7aab896b1a3b 1152 bool retval = true;
kevman 2:7aab896b1a3b 1153 switch (addr_mode) {
kevman 2:7aab896b1a3b 1154 case FC_DST_16_BITS:
kevman 2:7aab896b1a3b 1155 if (memcmp((uint8_t *)ptr, (uint8_t *) cmp_table, 2)) {
kevman 2:7aab896b1a3b 1156 retval = false;
kevman 2:7aab896b1a3b 1157 }
kevman 2:7aab896b1a3b 1158 if (!retval) {
kevman 2:7aab896b1a3b 1159 for (uint8_t i = 0; i < 2; i++) {
kevman 2:7aab896b1a3b 1160 cmp_table[1 - i] = ptr[i];
kevman 2:7aab896b1a3b 1161 }
kevman 2:7aab896b1a3b 1162
kevman 2:7aab896b1a3b 1163 if (!memcmp((uint8_t *)mac_16bit_addr, (uint8_t *) cmp_table, 2)) {
kevman 2:7aab896b1a3b 1164 retval = true;
kevman 2:7aab896b1a3b 1165 }
kevman 2:7aab896b1a3b 1166 }
kevman 2:7aab896b1a3b 1167 break;
kevman 2:7aab896b1a3b 1168 case FC_DST_64_BITS:
kevman 2:7aab896b1a3b 1169 if (memcmp((uint8_t *)ptr, (uint8_t *) cmp_table, 8)) {
kevman 2:7aab896b1a3b 1170 retval = false;
kevman 2:7aab896b1a3b 1171 }
kevman 2:7aab896b1a3b 1172 if (!retval) {
kevman 2:7aab896b1a3b 1173 for (uint8_t i = 0; i < 8; i++) {
kevman 2:7aab896b1a3b 1174 cmp_table[7 - i] = ptr[i];
kevman 2:7aab896b1a3b 1175 }
kevman 2:7aab896b1a3b 1176
kevman 2:7aab896b1a3b 1177 if (!memcmp((uint8_t *)mac_64bit_addr, (uint8_t *) cmp_table, 8)) {
kevman 2:7aab896b1a3b 1178 retval = true;
kevman 2:7aab896b1a3b 1179 }
kevman 2:7aab896b1a3b 1180 }
kevman 2:7aab896b1a3b 1181 break;
kevman 2:7aab896b1a3b 1182 case FC_DST_ADDR_NONE:
kevman 2:7aab896b1a3b 1183 retval = true;
kevman 2:7aab896b1a3b 1184 break;
kevman 2:7aab896b1a3b 1185 default:
kevman 2:7aab896b1a3b 1186 retval = false;
kevman 2:7aab896b1a3b 1187 break;
kevman 2:7aab896b1a3b 1188 }
kevman 2:7aab896b1a3b 1189 return retval;
kevman 2:7aab896b1a3b 1190 }
kevman 2:7aab896b1a3b 1191
kevman 2:7aab896b1a3b 1192 static bool rf_addr_v2_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t dst_mode, uint8_t seq_compressed, uint8_t panid_compressed)
kevman 2:7aab896b1a3b 1193 {
kevman 2:7aab896b1a3b 1194 if (seq_compressed) {
kevman 2:7aab896b1a3b 1195 ptr--;
kevman 2:7aab896b1a3b 1196 }
kevman 2:7aab896b1a3b 1197 if (panid_compressed) {
kevman 2:7aab896b1a3b 1198 ptr -= 2;
kevman 2:7aab896b1a3b 1199 }
kevman 2:7aab896b1a3b 1200 return rf_addr_filter_common(ptr, dst_mode, mac_64bit_addr, mac_16bit_addr);
kevman 2:7aab896b1a3b 1201 }
kevman 2:7aab896b1a3b 1202
kevman 2:7aab896b1a3b 1203 static bool rf_addr_v1_v0_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t dst_mode)
kevman 2:7aab896b1a3b 1204 {
kevman 2:7aab896b1a3b 1205 return rf_addr_filter_common(ptr, dst_mode, mac_64bit_addr, mac_16bit_addr);
kevman 2:7aab896b1a3b 1206 }
kevman 2:7aab896b1a3b 1207
kevman 2:7aab896b1a3b 1208 static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t *pan_id)
kevman 2:7aab896b1a3b 1209 {
kevman 2:7aab896b1a3b 1210 uint8_t dst_mode = (mac_header[1] & FC_DST_MODE);
kevman 2:7aab896b1a3b 1211 uint8_t src_mode = (mac_header[1] & FC_SRC_MODE);
kevman 2:7aab896b1a3b 1212 uint8_t seq_compressed = ((mac_header[1] & FC_SEQUENCE_COMPRESSION) >> SHIFT_SEQ_COMP_FIELD);
kevman 2:7aab896b1a3b 1213 uint8_t panid_compressed = ((mac_header[0] & FC_PAN_ID_COMPRESSION) >> SHIFT_PANID_COMP_FIELD);
kevman 2:7aab896b1a3b 1214 uint8_t frame_type = mac_header[0] & MAC_FRAME_TYPE_MASK;
kevman 2:7aab896b1a3b 1215 uint8_t version = ((mac_header[1] & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD);
kevman 2:7aab896b1a3b 1216 if (version == MAC_FRAME_VERSION_2) {
kevman 2:7aab896b1a3b 1217 if (!rf_panid_v2_filter(mac_header + OFFSET_DST_PAN_ID, pan_id, dst_mode, src_mode, seq_compressed, panid_compressed, frame_type)) {
kevman 2:7aab896b1a3b 1218 return false;
kevman 2:7aab896b1a3b 1219 }
kevman 2:7aab896b1a3b 1220 if (!rf_addr_v2_filter(mac_header + OFFSET_DST_ADDR, mac_64bit_addr, mac_16bit_addr, dst_mode, seq_compressed, panid_compressed)) {
kevman 2:7aab896b1a3b 1221 return false;
kevman 2:7aab896b1a3b 1222 }
kevman 2:7aab896b1a3b 1223 } else {
kevman 2:7aab896b1a3b 1224 if (!rf_panid_v1_v0_filter(mac_header + OFFSET_DST_PAN_ID, pan_id, frame_type)) {
kevman 2:7aab896b1a3b 1225 return false;
kevman 2:7aab896b1a3b 1226 }
kevman 2:7aab896b1a3b 1227 if (!rf_addr_v1_v0_filter(mac_header + OFFSET_DST_ADDR, mac_64bit_addr, mac_16bit_addr, dst_mode)) {
kevman 2:7aab896b1a3b 1228 return false;
kevman 2:7aab896b1a3b 1229 }
kevman 2:7aab896b1a3b 1230 }
kevman 2:7aab896b1a3b 1231 return true;
kevman 2:7aab896b1a3b 1232 }
kevman 2:7aab896b1a3b 1233
kevman 2:7aab896b1a3b 1234 static void rf_print_registers(void)
kevman 2:7aab896b1a3b 1235 {
kevman 2:7aab896b1a3b 1236 tr_debug("GPIO0_CONF: %x", rf_read_register_with_status(GPIO0_CONF, NULL));
kevman 2:7aab896b1a3b 1237 tr_debug("GPIO1_CONF: %x", rf_read_register_with_status(GPIO1_CONF, NULL));
kevman 2:7aab896b1a3b 1238 tr_debug("GPIO2_CONF: %x", rf_read_register_with_status(GPIO2_CONF, NULL));
kevman 2:7aab896b1a3b 1239 tr_debug("GPIO3_CONF: %x", rf_read_register_with_status(GPIO3_CONF, NULL));
kevman 2:7aab896b1a3b 1240 tr_debug("SYNT3: %x", rf_read_register_with_status(SYNT3, NULL));
kevman 2:7aab896b1a3b 1241 tr_debug("SYNT2: %x", rf_read_register_with_status(SYNT2, NULL));
kevman 2:7aab896b1a3b 1242 tr_debug("SYNT1: %x", rf_read_register_with_status(SYNT1, NULL));
kevman 2:7aab896b1a3b 1243 tr_debug("SYNT0: %x", rf_read_register_with_status(SYNT0, NULL));
kevman 2:7aab896b1a3b 1244 tr_debug("IF_OFFSET_ANA: %x", rf_read_register_with_status(IF_OFFSET_ANA, NULL));
kevman 2:7aab896b1a3b 1245 tr_debug("IF_OFFSET_DIG: %x", rf_read_register_with_status(IF_OFFSET_DIG, NULL));
kevman 2:7aab896b1a3b 1246 tr_debug("CHSPACE: %x", rf_read_register_with_status(CHSPACE, NULL));
kevman 2:7aab896b1a3b 1247 tr_debug("CHNUM: %x", rf_read_register_with_status(CHNUM, NULL));
kevman 2:7aab896b1a3b 1248 tr_debug("MOD4: %x", rf_read_register_with_status(MOD4, NULL));
kevman 2:7aab896b1a3b 1249 tr_debug("MOD3: %x", rf_read_register_with_status(MOD3, NULL));
kevman 2:7aab896b1a3b 1250 tr_debug("MOD2: %x", rf_read_register_with_status(MOD2, NULL));
kevman 2:7aab896b1a3b 1251 tr_debug("MOD1: %x", rf_read_register_with_status(MOD1, NULL));
kevman 2:7aab896b1a3b 1252 tr_debug("MOD0: %x", rf_read_register_with_status(MOD0, NULL));
kevman 2:7aab896b1a3b 1253 tr_debug("CHFLT: %x", rf_read_register_with_status(CHFLT, NULL));
kevman 2:7aab896b1a3b 1254 tr_debug("AFC2: %x", rf_read_register_with_status(AFC2, NULL));
kevman 2:7aab896b1a3b 1255 tr_debug("AFC1: %x", rf_read_register_with_status(AFC1, NULL));
kevman 2:7aab896b1a3b 1256 tr_debug("AFC0: %x", rf_read_register_with_status(AFC0, NULL));
kevman 2:7aab896b1a3b 1257 tr_debug("RSSI_FLT: %x", rf_read_register_with_status(RSSI_FLT, NULL));
kevman 2:7aab896b1a3b 1258 tr_debug("RSSI_TH: %x", rf_read_register_with_status(RSSI_TH, NULL));
kevman 2:7aab896b1a3b 1259 tr_debug("AGCCTRL4: %x", rf_read_register_with_status(AGCCTRL4, NULL));
kevman 2:7aab896b1a3b 1260 tr_debug("AGCCTRL3: %x", rf_read_register_with_status(AGCCTRL3, NULL));
kevman 2:7aab896b1a3b 1261 tr_debug("AGCCTRL2: %x", rf_read_register_with_status(AGCCTRL2, NULL));
kevman 2:7aab896b1a3b 1262 tr_debug("AGCCTRL1: %x", rf_read_register_with_status(AGCCTRL1, NULL));
kevman 2:7aab896b1a3b 1263 tr_debug("AGCCTRL0: %x", rf_read_register_with_status(AGCCTRL0, NULL));
kevman 2:7aab896b1a3b 1264 tr_debug("ANT_SELECT_CONF: %x", rf_read_register_with_status(ANT_SELECT_CONF, NULL));
kevman 2:7aab896b1a3b 1265 tr_debug("CLOCKREC2: %x", rf_read_register_with_status(CLOCKREC2, NULL));
kevman 2:7aab896b1a3b 1266 tr_debug("CLOCKREC1: %x", rf_read_register_with_status(CLOCKREC1, NULL));
kevman 2:7aab896b1a3b 1267 tr_debug("PCKTCTRL6: %x", rf_read_register_with_status(PCKTCTRL6, NULL));
kevman 2:7aab896b1a3b 1268 tr_debug("PCKTCTRL5: %x", rf_read_register_with_status(PCKTCTRL5, NULL));
kevman 2:7aab896b1a3b 1269 tr_debug("PCKTCTRL4: %x", rf_read_register_with_status(PCKTCTRL4, NULL));
kevman 2:7aab896b1a3b 1270 tr_debug("PCKTCTRL3: %x", rf_read_register_with_status(PCKTCTRL3, NULL));
kevman 2:7aab896b1a3b 1271 tr_debug("PCKTCTRL2: %x", rf_read_register_with_status(PCKTCTRL2, NULL));
kevman 2:7aab896b1a3b 1272 tr_debug("PCKTCTRL1: %x", rf_read_register_with_status(PCKTCTRL1, NULL));
kevman 2:7aab896b1a3b 1273 tr_debug("PCKTLEN1: %x", rf_read_register_with_status(PCKTLEN1, NULL));
kevman 2:7aab896b1a3b 1274 tr_debug("PCKTLEN0: %x", rf_read_register_with_status(PCKTLEN0, NULL));
kevman 2:7aab896b1a3b 1275 tr_debug("SYNC3: %x", rf_read_register_with_status(SYNC3, NULL));
kevman 2:7aab896b1a3b 1276 tr_debug("SYNC2: %x", rf_read_register_with_status(SYNC2, NULL));
kevman 2:7aab896b1a3b 1277 tr_debug("SYNC1: %x", rf_read_register_with_status(SYNC1, NULL));
kevman 2:7aab896b1a3b 1278 tr_debug("SYNC0: %x", rf_read_register_with_status(SYNC0, NULL));
kevman 2:7aab896b1a3b 1279 tr_debug("QI: %x", rf_read_register_with_status(QI, NULL));
kevman 2:7aab896b1a3b 1280 tr_debug("PCKT_PSTMBL: %x", rf_read_register_with_status(PCKT_PSTMBL, NULL));
kevman 2:7aab896b1a3b 1281 tr_debug("PROTOCOL2: %x", rf_read_register_with_status(PROTOCOL2, NULL));
kevman 2:7aab896b1a3b 1282 tr_debug("PROTOCOL1: %x", rf_read_register_with_status(PROTOCOL1, NULL));
kevman 2:7aab896b1a3b 1283 tr_debug("PROTOCOL0: %x", rf_read_register_with_status(PROTOCOL0, NULL));
kevman 2:7aab896b1a3b 1284 tr_debug("FIFO_CONFIG3: %x", rf_read_register_with_status(FIFO_CONFIG3, NULL));
kevman 2:7aab896b1a3b 1285 tr_debug("FIFO_CONFIG2: %x", rf_read_register_with_status(FIFO_CONFIG2, NULL));
kevman 2:7aab896b1a3b 1286 tr_debug("FIFO_CONFIG1: %x", rf_read_register_with_status(FIFO_CONFIG1, NULL));
kevman 2:7aab896b1a3b 1287 tr_debug("FIFO_CONFIG0: %x", rf_read_register_with_status(FIFO_CONFIG0, NULL));
kevman 2:7aab896b1a3b 1288 tr_debug("PCKT_FLT_OPTIONS: %x", rf_read_register_with_status(PCKT_FLT_OPTIONS, NULL));
kevman 2:7aab896b1a3b 1289 tr_debug("PCKT_FLT_GOALS4: %x", rf_read_register_with_status(PCKT_FLT_GOALS4, NULL));
kevman 2:7aab896b1a3b 1290 tr_debug("PCKT_FLT_GOALS3: %x", rf_read_register_with_status(PCKT_FLT_GOALS3, NULL));
kevman 2:7aab896b1a3b 1291 tr_debug("PCKT_FLT_GOALS2: %x", rf_read_register_with_status(PCKT_FLT_GOALS2, NULL));
kevman 2:7aab896b1a3b 1292 tr_debug("PCKT_FLT_GOALS1: %x", rf_read_register_with_status(PCKT_FLT_GOALS1, NULL));
kevman 2:7aab896b1a3b 1293 tr_debug("PCKT_FLT_GOALS0: %x", rf_read_register_with_status(PCKT_FLT_GOALS0, NULL));
kevman 2:7aab896b1a3b 1294 tr_debug("TIMERS5: %x", rf_read_register_with_status(TIMERS5, NULL));
kevman 2:7aab896b1a3b 1295 tr_debug("TIMERS4: %x", rf_read_register_with_status(TIMERS4, NULL));
kevman 2:7aab896b1a3b 1296 tr_debug("TIMERS3: %x", rf_read_register_with_status(TIMERS3, NULL));
kevman 2:7aab896b1a3b 1297 tr_debug("TIMERS2: %x", rf_read_register_with_status(TIMERS2, NULL));
kevman 2:7aab896b1a3b 1298 tr_debug("TIMERS1: %x", rf_read_register_with_status(TIMERS1, NULL));
kevman 2:7aab896b1a3b 1299 tr_debug("TIMERS0: %x", rf_read_register_with_status(TIMERS0, NULL));
kevman 2:7aab896b1a3b 1300 tr_debug("CSMA_CONF3: %x", rf_read_register_with_status(CSMA_CONF3, NULL));
kevman 2:7aab896b1a3b 1301 tr_debug("CSMA_CONF2: %x", rf_read_register_with_status(CSMA_CONF2, NULL));
kevman 2:7aab896b1a3b 1302 tr_debug("CSMA_CONF1: %x", rf_read_register_with_status(CSMA_CONF1, NULL));
kevman 2:7aab896b1a3b 1303 tr_debug("CSMA_CONF0: %x", rf_read_register_with_status(CSMA_CONF0, NULL));
kevman 2:7aab896b1a3b 1304 tr_debug("IRQ_MASK3: %x", rf_read_register_with_status(IRQ_MASK3, NULL));
kevman 2:7aab896b1a3b 1305 tr_debug("IRQ_MASK2: %x", rf_read_register_with_status(IRQ_MASK2, NULL));
kevman 2:7aab896b1a3b 1306 tr_debug("IRQ_MASK1: %x", rf_read_register_with_status(IRQ_MASK1, NULL));
kevman 2:7aab896b1a3b 1307 tr_debug("IRQ_MASK0: %x", rf_read_register_with_status(IRQ_MASK0, NULL));
kevman 2:7aab896b1a3b 1308 tr_debug("FAST_RX_TIMER: %x", rf_read_register_with_status(FAST_RX_TIMER, NULL));
kevman 2:7aab896b1a3b 1309 tr_debug("PA_POWER8: %x", rf_read_register_with_status(PA_POWER8, NULL));
kevman 2:7aab896b1a3b 1310 tr_debug("PA_POWER7: %x", rf_read_register_with_status(PA_POWER7, NULL));
kevman 2:7aab896b1a3b 1311 tr_debug("PA_POWER6: %x", rf_read_register_with_status(PA_POWER6, NULL));
kevman 2:7aab896b1a3b 1312 tr_debug("PA_POWER5: %x", rf_read_register_with_status(PA_POWER5, NULL));
kevman 2:7aab896b1a3b 1313 tr_debug("PA_POWER4: %x", rf_read_register_with_status(PA_POWER4, NULL));
kevman 2:7aab896b1a3b 1314 tr_debug("PA_POWER3: %x", rf_read_register_with_status(PA_POWER3, NULL));
kevman 2:7aab896b1a3b 1315 tr_debug("PA_POWER2: %x", rf_read_register_with_status(PA_POWER2, NULL));
kevman 2:7aab896b1a3b 1316 tr_debug("PA_POWER1: %x", rf_read_register_with_status(PA_POWER1, NULL));
kevman 2:7aab896b1a3b 1317 tr_debug("PA_POWER0: %x", rf_read_register_with_status(PA_POWER0, NULL));
kevman 2:7aab896b1a3b 1318 tr_debug("PA_CONFIG1: %x", rf_read_register_with_status(PA_CONFIG1, NULL));
kevman 2:7aab896b1a3b 1319 tr_debug("PA_CONFIG0: %x", rf_read_register_with_status(PA_CONFIG0, NULL));
kevman 2:7aab896b1a3b 1320 tr_debug("SYNTH_CONFIG2: %x", rf_read_register_with_status(SYNTH_CONFIG2, NULL));
kevman 2:7aab896b1a3b 1321 tr_debug("VCO_CONFIG: %x", rf_read_register_with_status(VCO_CONFIG, NULL));
kevman 2:7aab896b1a3b 1322 tr_debug("VCO_CALIBR_IN2: %x", rf_read_register_with_status(VCO_CALIBR_IN2, NULL));
kevman 2:7aab896b1a3b 1323 tr_debug("VCO_CALIBR_IN1: %x", rf_read_register_with_status(VCO_CALIBR_IN1, NULL));
kevman 2:7aab896b1a3b 1324 tr_debug("VCO_CALIBR_IN0: %x", rf_read_register_with_status(VCO_CALIBR_IN0, NULL));
kevman 2:7aab896b1a3b 1325 tr_debug("XO_RCO_CONF1: %x", rf_read_register_with_status(XO_RCO_CONF1, NULL));
kevman 2:7aab896b1a3b 1326 tr_debug("XO_RCO_CONF0: %x", rf_read_register_with_status(XO_RCO_CONF0, NULL));
kevman 2:7aab896b1a3b 1327 tr_debug("RCO_CALIBR_CONF3: %x", rf_read_register_with_status(RCO_CALIBR_CONF3, NULL));
kevman 2:7aab896b1a3b 1328 tr_debug("RCO_CALIBR_CONF2: %x", rf_read_register_with_status(RCO_CALIBR_CONF2, NULL));
kevman 2:7aab896b1a3b 1329 tr_debug("PM_CONF4: %x", rf_read_register_with_status(PM_CONF4, NULL));
kevman 2:7aab896b1a3b 1330 tr_debug("PM_CONF3: %x", rf_read_register_with_status(PM_CONF3, NULL));
kevman 2:7aab896b1a3b 1331 tr_debug("PM_CONF2: %x", rf_read_register_with_status(PM_CONF2, NULL));
kevman 2:7aab896b1a3b 1332 tr_debug("PM_CONF1: %x", rf_read_register_with_status(PM_CONF1, NULL));
kevman 2:7aab896b1a3b 1333 tr_debug("PM_CONF0: %x", rf_read_register_with_status(PM_CONF0, NULL));
kevman 2:7aab896b1a3b 1334 tr_debug("MC_STATE1: %x", rf_read_register_with_status(MC_STATE1, NULL));
kevman 2:7aab896b1a3b 1335 tr_debug("MC_STATE0: %x", rf_read_register_with_status(MC_STATE0, NULL));
kevman 2:7aab896b1a3b 1336 tr_debug("TX_FIFO_STATUS: %x", rf_read_register_with_status(TX_FIFO_STATUS, NULL));
kevman 2:7aab896b1a3b 1337 tr_debug("RX_FIFO_STATUS: %x", rf_read_register_with_status(RX_FIFO_STATUS, NULL));
kevman 2:7aab896b1a3b 1338 tr_debug("RCO_CALIBR_OUT4: %x", rf_read_register_with_status(RCO_CALIBR_OUT4, NULL));
kevman 2:7aab896b1a3b 1339 tr_debug("RCO_CALIBR_OUT3: %x", rf_read_register_with_status(RCO_CALIBR_OUT3, NULL));
kevman 2:7aab896b1a3b 1340 tr_debug("VCO_CALIBR_OUT1: %x", rf_read_register_with_status(VCO_CALIBR_OUT1, NULL));
kevman 2:7aab896b1a3b 1341 tr_debug("VCO_CALIBR_OUT0: %x", rf_read_register_with_status(VCO_CALIBR_OUT0, NULL));
kevman 2:7aab896b1a3b 1342 tr_debug("TX_PCKT_INFO: %x", rf_read_register_with_status(TX_PCKT_INFO, NULL));
kevman 2:7aab896b1a3b 1343 tr_debug("RX_PCKT_INFO: %x", rf_read_register_with_status(RX_PCKT_INFO, NULL));
kevman 2:7aab896b1a3b 1344 tr_debug("AFC_CORR: %x", rf_read_register_with_status(AFC_CORR, NULL));
kevman 2:7aab896b1a3b 1345 tr_debug("LINK_QUALIF2: %x", rf_read_register_with_status(LINK_QUALIF2, NULL));
kevman 2:7aab896b1a3b 1346 tr_debug("LINK_QUALIF1: %x", rf_read_register_with_status(LINK_QUALIF1, NULL));
kevman 2:7aab896b1a3b 1347 tr_debug("RSSI_LEVEL: %x", rf_read_register_with_status(RSSI_LEVEL, NULL));
kevman 2:7aab896b1a3b 1348 tr_debug("RX_PCKT_LEN1: %x", rf_read_register_with_status(RX_PCKT_LEN1, NULL));
kevman 2:7aab896b1a3b 1349 tr_debug("RX_PCKT_LEN0: %x", rf_read_register_with_status(RX_PCKT_LEN0, NULL));
kevman 2:7aab896b1a3b 1350 tr_debug("CRC_FIELD3: %x", rf_read_register_with_status(CRC_FIELD3, NULL));
kevman 2:7aab896b1a3b 1351 tr_debug("CRC_FIELD2: %x", rf_read_register_with_status(CRC_FIELD2, NULL));
kevman 2:7aab896b1a3b 1352 tr_debug("CRC_FIELD1: %x", rf_read_register_with_status(CRC_FIELD1, NULL));
kevman 2:7aab896b1a3b 1353 tr_debug("CRC_FIELD0: %x", rf_read_register_with_status(CRC_FIELD0, NULL));
kevman 2:7aab896b1a3b 1354 tr_debug("RX_ADDRE_FIELD1: %x", rf_read_register_with_status(RX_ADDRE_FIELD1, NULL));
kevman 2:7aab896b1a3b 1355 tr_debug("RX_ADDRE_FIELD0: %x", rf_read_register_with_status(RX_ADDRE_FIELD0, NULL));
kevman 2:7aab896b1a3b 1356 tr_debug("RSSI_LEVEL_RUN: %x", rf_read_register_with_status(RSSI_LEVEL_RUN, NULL));
kevman 2:7aab896b1a3b 1357 tr_debug("DEVICE_INFO1: %x", rf_read_register_with_status(DEVICE_INFO1, NULL));
kevman 2:7aab896b1a3b 1358 tr_debug("DEVICE_INFO0: %x", rf_read_register_with_status(DEVICE_INFO0, NULL));
kevman 2:7aab896b1a3b 1359 tr_debug("IRQ_STATUS3: %x", rf_read_register_with_status(IRQ_STATUS3, NULL));
kevman 2:7aab896b1a3b 1360 tr_debug("IRQ_STATUS2: %x", rf_read_register_with_status(IRQ_STATUS2, NULL));
kevman 2:7aab896b1a3b 1361 tr_debug("IRQ_STATUS1: %x", rf_read_register_with_status(IRQ_STATUS1, NULL));
kevman 2:7aab896b1a3b 1362 tr_debug("IRQ_STATUS0: %x", rf_read_register_with_status(IRQ_STATUS0, NULL));
kevman 2:7aab896b1a3b 1363 }
kevman 2:7aab896b1a3b 1364
kevman 2:7aab896b1a3b 1365 #if MBED_CONF_S2LP_PROVIDE_DEFAULT
kevman 2:7aab896b1a3b 1366 NanostackRfPhy &NanostackRfPhy::get_default_instance()
kevman 2:7aab896b1a3b 1367 {
kevman 2:7aab896b1a3b 1368 static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN,
kevman 2:7aab896b1a3b 1369 #ifdef TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1370 S2LP_SPI_TEST1, S2LP_SPI_TEST2, S2LP_SPI_TEST3, S2LP_SPI_TEST4, S2LP_SPI_TEST5,
kevman 2:7aab896b1a3b 1371 #endif //TEST_GPIOS_ENABLED
kevman 2:7aab896b1a3b 1372 S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3);
kevman 2:7aab896b1a3b 1373 return rf_phy;
kevman 2:7aab896b1a3b 1374 }
kevman 2:7aab896b1a3b 1375 #endif // MBED_CONF_S2LP_PROVIDE_DEFAULT
kevman 2:7aab896b1a3b 1376 #endif // MBED_CONF_NANOSTACK_CONFIGURATION && DEVICE_SPI