Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

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