takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /*
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2016 Silicon Laboratories, Inc. http://www.silabs.com
kadonotakashi 0:8fdf9a60065b 3 * SPDX-License-Identifier: Apache-2.0
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the License); you may
kadonotakashi 0:8fdf9a60065b 5 * not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
kadonotakashi 0:8fdf9a60065b 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16 #include "NanostackRfPhyEfr32.h"
kadonotakashi 0:8fdf9a60065b 17
kadonotakashi 0:8fdf9a60065b 18 #include <string.h>
kadonotakashi 0:8fdf9a60065b 19
kadonotakashi 0:8fdf9a60065b 20 #include "mbed.h"
kadonotakashi 0:8fdf9a60065b 21 #include "mbed_power_mgmt.h"
kadonotakashi 0:8fdf9a60065b 22 #include "ns_types.h"
kadonotakashi 0:8fdf9a60065b 23 #include "platform/arm_hal_interrupt.h"
kadonotakashi 0:8fdf9a60065b 24 #include "nanostack/platform/arm_hal_phy.h"
kadonotakashi 0:8fdf9a60065b 25 #include "mbed_toolchain.h"
kadonotakashi 0:8fdf9a60065b 26
kadonotakashi 0:8fdf9a60065b 27 #include "mbed-trace/mbed_trace.h"
kadonotakashi 0:8fdf9a60065b 28 #define TRACE_GROUP "SLRF"
kadonotakashi 0:8fdf9a60065b 29
kadonotakashi 0:8fdf9a60065b 30 /* Enable debug printing with SL_RADIO_DEBUG, override debug printer with SL_DEBUG_PRINT. */
kadonotakashi 0:8fdf9a60065b 31 #ifdef SL_RADIO_DEBUG
kadonotakashi 0:8fdf9a60065b 32 #ifndef SL_DEBUG_PRINT
kadonotakashi 0:8fdf9a60065b 33 #define SL_DEBUG_PRINT(...) tr_debug(__VA_ARGS__)
kadonotakashi 0:8fdf9a60065b 34 #endif
kadonotakashi 0:8fdf9a60065b 35 #else
kadonotakashi 0:8fdf9a60065b 36 #define SL_DEBUG_PRINT(...)
kadonotakashi 0:8fdf9a60065b 37 #endif
kadonotakashi 0:8fdf9a60065b 38
kadonotakashi 0:8fdf9a60065b 39 /* RF_THREAD_STACK_SIZE defines tack size for the RF adaptor thread */
kadonotakashi 0:8fdf9a60065b 40 #ifndef RF_THREAD_STACK_SIZE
kadonotakashi 0:8fdf9a60065b 41 #define RF_THREAD_STACK_SIZE 1024
kadonotakashi 0:8fdf9a60065b 42 #endif
kadonotakashi 0:8fdf9a60065b 43
kadonotakashi 0:8fdf9a60065b 44 /* RF_QUEUE_SIZE defines queue size for incoming messages */
kadonotakashi 0:8fdf9a60065b 45 #ifndef RF_QUEUE_SIZE
kadonotakashi 0:8fdf9a60065b 46 #define RF_QUEUE_SIZE 8
kadonotakashi 0:8fdf9a60065b 47 #endif
kadonotakashi 0:8fdf9a60065b 48
kadonotakashi 0:8fdf9a60065b 49 /* 802.15.4 maximum size of a single packet including PHY byte is 128 bytes */
kadonotakashi 0:8fdf9a60065b 50 #define MAC_PACKET_MAX_LENGTH 128
kadonotakashi 0:8fdf9a60065b 51 /* Offsets of prepended data in packet buffer */
kadonotakashi 0:8fdf9a60065b 52 #define MAC_PACKET_OFFSET_RSSI 0
kadonotakashi 0:8fdf9a60065b 53 #define MAC_PACKET_OFFSET_LQI 1
kadonotakashi 0:8fdf9a60065b 54 /* This driver prepends RSSI and LQI */
kadonotakashi 0:8fdf9a60065b 55 #define MAC_PACKET_INFO_LENGTH 2
kadonotakashi 0:8fdf9a60065b 56
kadonotakashi 0:8fdf9a60065b 57 /* RFThreadSignal used to signal from interrupts to the adaptor thread */
kadonotakashi 0:8fdf9a60065b 58 enum RFThreadSignal {
kadonotakashi 0:8fdf9a60065b 59 SL_RX_DONE = (1 << 1),
kadonotakashi 0:8fdf9a60065b 60 SL_TX_DONE = (1 << 2),
kadonotakashi 0:8fdf9a60065b 61 SL_TX_ERR = (1 << 3),
kadonotakashi 0:8fdf9a60065b 62 SL_TX_TIMEOUT = (1 << 4),
kadonotakashi 0:8fdf9a60065b 63 SL_ACK_RECV = (1 << 5),
kadonotakashi 0:8fdf9a60065b 64 SL_ACK_TIMEOUT = (1 << 6),
kadonotakashi 0:8fdf9a60065b 65 SL_TXFIFO_ERR = (1 << 7),
kadonotakashi 0:8fdf9a60065b 66 SL_RXFIFO_ERR = (1 << 8),
kadonotakashi 0:8fdf9a60065b 67 SL_CAL_REQ = (1 << 9),
kadonotakashi 0:8fdf9a60065b 68 SL_RSSI_DONE = (1 << 10),
kadonotakashi 0:8fdf9a60065b 69 SL_QUEUE_FULL = (1 << 11),
kadonotakashi 0:8fdf9a60065b 70
kadonotakashi 0:8fdf9a60065b 71 // ACK pend flag can be signalled in addition to RX_DONE
kadonotakashi 0:8fdf9a60065b 72 SL_ACK_PEND = (1 << 30),
kadonotakashi 0:8fdf9a60065b 73 };
kadonotakashi 0:8fdf9a60065b 74
kadonotakashi 0:8fdf9a60065b 75 /* Adaptor thread definitions */
kadonotakashi 0:8fdf9a60065b 76 static void rf_thread_loop(const void *arg);
kadonotakashi 0:8fdf9a60065b 77 static osThreadDef(rf_thread_loop, osPriorityRealtime, RF_THREAD_STACK_SIZE);
kadonotakashi 0:8fdf9a60065b 78 static osThreadId rf_thread_id = 0;
kadonotakashi 0:8fdf9a60065b 79
kadonotakashi 0:8fdf9a60065b 80 /* Queue for passing messages from interrupt to adaptor thread */
kadonotakashi 0:8fdf9a60065b 81 static volatile uint8_t rx_queue[RF_QUEUE_SIZE][MAC_PACKET_MAX_LENGTH + MAC_PACKET_INFO_LENGTH];
kadonotakashi 0:8fdf9a60065b 82 static volatile size_t rx_queue_head = 0;
kadonotakashi 0:8fdf9a60065b 83 static volatile size_t rx_queue_tail = 0;
kadonotakashi 0:8fdf9a60065b 84
kadonotakashi 0:8fdf9a60065b 85 /* Silicon Labs headers */
kadonotakashi 0:8fdf9a60065b 86 extern "C" {
kadonotakashi 0:8fdf9a60065b 87 #include "rail/rail.h"
kadonotakashi 0:8fdf9a60065b 88 #include "rail/pa.h"
kadonotakashi 0:8fdf9a60065b 89 #include "rail/pti.h"
kadonotakashi 0:8fdf9a60065b 90 #include "rail/ieee802154/rail_ieee802154.h"
kadonotakashi 0:8fdf9a60065b 91 }
kadonotakashi 0:8fdf9a60065b 92
kadonotakashi 0:8fdf9a60065b 93 /* RF driver data */
kadonotakashi 0:8fdf9a60065b 94 static phy_device_driver_s device_driver;
kadonotakashi 0:8fdf9a60065b 95 static int8_t rf_radio_driver_id = -1;
kadonotakashi 0:8fdf9a60065b 96 static uint8_t MAC_address[8];
kadonotakashi 0:8fdf9a60065b 97 static uint16_t PAN_address;
kadonotakashi 0:8fdf9a60065b 98 static uint16_t short_address;
kadonotakashi 0:8fdf9a60065b 99
kadonotakashi 0:8fdf9a60065b 100 /* Driver instance handle */
kadonotakashi 0:8fdf9a60065b 101 static NanostackRfPhyEfr32 *rf = NULL;
kadonotakashi 0:8fdf9a60065b 102
kadonotakashi 0:8fdf9a60065b 103 /* Channel configurations */
kadonotakashi 0:8fdf9a60065b 104 static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
kadonotakashi 0:8fdf9a60065b 105 static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 2000000U, 250000U, 11U, M_OQPSK};
kadonotakashi 0:8fdf9a60065b 106
kadonotakashi 0:8fdf9a60065b 107 static const phy_device_channel_page_s phy_channel_pages[] = {
kadonotakashi 0:8fdf9a60065b 108 { CHANNEL_PAGE_0, &phy_24ghz},
kadonotakashi 0:8fdf9a60065b 109 { CHANNEL_PAGE_2, &phy_subghz},
kadonotakashi 0:8fdf9a60065b 110 { CHANNEL_PAGE_0, NULL}
kadonotakashi 0:8fdf9a60065b 111 };
kadonotakashi 0:8fdf9a60065b 112
kadonotakashi 0:8fdf9a60065b 113 /* Driver structures */
kadonotakashi 0:8fdf9a60065b 114 typedef enum {
kadonotakashi 0:8fdf9a60065b 115 RADIO_UNINIT,
kadonotakashi 0:8fdf9a60065b 116 RADIO_INITING,
kadonotakashi 0:8fdf9a60065b 117 RADIO_IDLE,
kadonotakashi 0:8fdf9a60065b 118 RADIO_TX,
kadonotakashi 0:8fdf9a60065b 119 RADIO_RX,
kadonotakashi 0:8fdf9a60065b 120 RADIO_CALIBRATION
kadonotakashi 0:8fdf9a60065b 121 } siliconlabs_modem_state_t;
kadonotakashi 0:8fdf9a60065b 122
kadonotakashi 0:8fdf9a60065b 123 static const RAIL_CsmaConfig_t csma_config = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
kadonotakashi 0:8fdf9a60065b 124
kadonotakashi 0:8fdf9a60065b 125 #if defined(TARGET_EFR32_1)
kadonotakashi 0:8fdf9a60065b 126 #include "ieee802154_subg_efr32xg1_configurator_out.h"
kadonotakashi 0:8fdf9a60065b 127 #elif defined(TARGET_EFR32_12)
kadonotakashi 0:8fdf9a60065b 128 /* TODO: Add SubG support for EFR32_12 */
kadonotakashi 0:8fdf9a60065b 129 #else
kadonotakashi 0:8fdf9a60065b 130 #error "Not a valid target."
kadonotakashi 0:8fdf9a60065b 131 #endif
kadonotakashi 0:8fdf9a60065b 132
kadonotakashi 0:8fdf9a60065b 133 #if MBED_CONF_SL_RAIL_HAS_SUBGIG
kadonotakashi 0:8fdf9a60065b 134 static RAIL_ChannelConfigEntryAttr_t entry_868;
kadonotakashi 0:8fdf9a60065b 135 static RAIL_ChannelConfigEntryAttr_t entry_915;
kadonotakashi 0:8fdf9a60065b 136 static const RAIL_ChannelConfigEntry_t entry[] = {
kadonotakashi 0:8fdf9a60065b 137 {
kadonotakashi 0:8fdf9a60065b 138 .phyConfigDeltaAdd = NULL, // Add this to default config for this entry
kadonotakashi 0:8fdf9a60065b 139 .baseFrequency = 868300000U,
kadonotakashi 0:8fdf9a60065b 140 .channelSpacing = 600000U,
kadonotakashi 0:8fdf9a60065b 141 .physicalChannelOffset = 0,
kadonotakashi 0:8fdf9a60065b 142 .channelNumberStart = 0,
kadonotakashi 0:8fdf9a60065b 143 .channelNumberEnd = 0,
kadonotakashi 0:8fdf9a60065b 144 .maxPower = RAIL_TX_POWER_MAX,
kadonotakashi 0:8fdf9a60065b 145 .attr = &entry_868
kadonotakashi 0:8fdf9a60065b 146 },
kadonotakashi 0:8fdf9a60065b 147 {
kadonotakashi 0:8fdf9a60065b 148 .phyConfigDeltaAdd = NULL, // Add this to default config for this entry
kadonotakashi 0:8fdf9a60065b 149 .baseFrequency = 906000000U,
kadonotakashi 0:8fdf9a60065b 150 .channelSpacing = 2000000U,
kadonotakashi 0:8fdf9a60065b 151 .physicalChannelOffset = 1,
kadonotakashi 0:8fdf9a60065b 152 .channelNumberStart = 1,
kadonotakashi 0:8fdf9a60065b 153 .channelNumberEnd = 10,
kadonotakashi 0:8fdf9a60065b 154 .maxPower = RAIL_TX_POWER_MAX,
kadonotakashi 0:8fdf9a60065b 155 .attr = &entry_915
kadonotakashi 0:8fdf9a60065b 156 }
kadonotakashi 0:8fdf9a60065b 157 };
kadonotakashi 0:8fdf9a60065b 158 #endif
kadonotakashi 0:8fdf9a60065b 159
kadonotakashi 0:8fdf9a60065b 160 #if MBED_CONF_SL_RAIL_BAND == 868
kadonotakashi 0:8fdf9a60065b 161 #if !MBED_CONF_SL_RAIL_HAS_SUBGIG
kadonotakashi 0:8fdf9a60065b 162 #error "Sub-Gigahertz band is not supported on this target."
kadonotakashi 0:8fdf9a60065b 163 #endif
kadonotakashi 0:8fdf9a60065b 164 static const RAIL_ChannelConfig_t channels = {
kadonotakashi 0:8fdf9a60065b 165 ieee802154_config_863,
kadonotakashi 0:8fdf9a60065b 166 ieee802154_config_863_min,
kadonotakashi 0:8fdf9a60065b 167 &entry[0],
kadonotakashi 0:8fdf9a60065b 168 1
kadonotakashi 0:8fdf9a60065b 169 };
kadonotakashi 0:8fdf9a60065b 170 #elif MBED_CONF_SL_RAIL_BAND == 915
kadonotakashi 0:8fdf9a60065b 171 #if !MBED_CONF_SL_RAIL_HAS_SUBGIG
kadonotakashi 0:8fdf9a60065b 172 #error "Sub-Gigahertz band is not supported on this target."
kadonotakashi 0:8fdf9a60065b 173 #endif
kadonotakashi 0:8fdf9a60065b 174 static const RAIL_ChannelConfig_t channels = {
kadonotakashi 0:8fdf9a60065b 175 ieee802154_config_915,
kadonotakashi 0:8fdf9a60065b 176 ieee802154_config_915_min,
kadonotakashi 0:8fdf9a60065b 177 &entry[1],
kadonotakashi 0:8fdf9a60065b 178 1
kadonotakashi 0:8fdf9a60065b 179 };
kadonotakashi 0:8fdf9a60065b 180 #elif MBED_CONF_SL_RAIL_BAND == 2400
kadonotakashi 0:8fdf9a60065b 181 #ifndef MBED_CONF_SL_RAIL_HAS_2P4
kadonotakashi 0:8fdf9a60065b 182 #error "2.4GHz band is not supported on this target."
kadonotakashi 0:8fdf9a60065b 183 #endif
kadonotakashi 0:8fdf9a60065b 184 #else
kadonotakashi 0:8fdf9a60065b 185 #error "sl-rail.band is not correctly defined"
kadonotakashi 0:8fdf9a60065b 186 #endif
kadonotakashi 0:8fdf9a60065b 187
kadonotakashi 0:8fdf9a60065b 188 #if defined (MBED_CONF_SL_RAIL_HAS_2P4)
kadonotakashi 0:8fdf9a60065b 189 // Set up the PA for 2.4 GHz operation
kadonotakashi 0:8fdf9a60065b 190 static const RAIL_TxPowerConfig_t paInit2p4 = {
kadonotakashi 0:8fdf9a60065b 191 .mode = RAIL_TX_POWER_MODE_2P4_HP,
kadonotakashi 0:8fdf9a60065b 192 .voltage = 1800,
kadonotakashi 0:8fdf9a60065b 193 .rampTime = 10,
kadonotakashi 0:8fdf9a60065b 194 };
kadonotakashi 0:8fdf9a60065b 195 #endif
kadonotakashi 0:8fdf9a60065b 196
kadonotakashi 0:8fdf9a60065b 197 #if MBED_CONF_SL_RAIL_HAS_SUBGIG
kadonotakashi 0:8fdf9a60065b 198 // Set up the PA for sub-GHz operation
kadonotakashi 0:8fdf9a60065b 199 static const RAIL_TxPowerConfig_t paInitSubGhz = {
kadonotakashi 0:8fdf9a60065b 200 .mode = RAIL_TX_POWER_MODE_SUBGIG,
kadonotakashi 0:8fdf9a60065b 201 .voltage = 1800,
kadonotakashi 0:8fdf9a60065b 202 .rampTime = 10,
kadonotakashi 0:8fdf9a60065b 203 };
kadonotakashi 0:8fdf9a60065b 204 #endif
kadonotakashi 0:8fdf9a60065b 205
kadonotakashi 0:8fdf9a60065b 206 static const RAIL_StateTiming_t timings = {
kadonotakashi 0:8fdf9a60065b 207 .idleToRx = 100,
kadonotakashi 0:8fdf9a60065b 208 // Make txToRx slightly lower than desired to make sure we get to
kadonotakashi 0:8fdf9a60065b 209 // RX in time
kadonotakashi 0:8fdf9a60065b 210 .txToRx = 192 - 10,
kadonotakashi 0:8fdf9a60065b 211 .idleToTx = 100,
kadonotakashi 0:8fdf9a60065b 212 .rxToTx = 192,
kadonotakashi 0:8fdf9a60065b 213 .rxSearchTimeout = 0,
kadonotakashi 0:8fdf9a60065b 214 .txToRxSearchTimeout = 0
kadonotakashi 0:8fdf9a60065b 215 };
kadonotakashi 0:8fdf9a60065b 216
kadonotakashi 0:8fdf9a60065b 217 static const RAIL_IEEE802154_Config_t config = {
kadonotakashi 0:8fdf9a60065b 218 .addresses = NULL,
kadonotakashi 0:8fdf9a60065b 219 .ackConfig = {
kadonotakashi 0:8fdf9a60065b 220 .enable = true,
kadonotakashi 0:8fdf9a60065b 221 .ackTimeout = 1200,
kadonotakashi 0:8fdf9a60065b 222 .rxTransitions = {
kadonotakashi 0:8fdf9a60065b 223 .success = RAIL_RF_STATE_RX,
kadonotakashi 0:8fdf9a60065b 224 .error = RAIL_RF_STATE_RX // ignored
kadonotakashi 0:8fdf9a60065b 225 },
kadonotakashi 0:8fdf9a60065b 226 .txTransitions = {
kadonotakashi 0:8fdf9a60065b 227 .success = RAIL_RF_STATE_RX,
kadonotakashi 0:8fdf9a60065b 228 .error = RAIL_RF_STATE_RX // ignored
kadonotakashi 0:8fdf9a60065b 229 }
kadonotakashi 0:8fdf9a60065b 230 },
kadonotakashi 0:8fdf9a60065b 231 .timings = timings,
kadonotakashi 0:8fdf9a60065b 232 .framesMask = RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES,
kadonotakashi 0:8fdf9a60065b 233 .promiscuousMode = false,
kadonotakashi 0:8fdf9a60065b 234 .isPanCoordinator = false
kadonotakashi 0:8fdf9a60065b 235 };
kadonotakashi 0:8fdf9a60065b 236
kadonotakashi 0:8fdf9a60065b 237 static volatile siliconlabs_modem_state_t radio_state = RADIO_UNINIT;
kadonotakashi 0:8fdf9a60065b 238 static volatile bool sleep_blocked = false;
kadonotakashi 0:8fdf9a60065b 239 static volatile int8_t channel = -1;
kadonotakashi 0:8fdf9a60065b 240 static volatile uint8_t current_tx_handle = 0;
kadonotakashi 0:8fdf9a60065b 241 static volatile uint8_t current_tx_sequence = 0;
kadonotakashi 0:8fdf9a60065b 242 static volatile bool waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 243 static volatile bool data_pending = false, last_ack_pending_bit = false;
kadonotakashi 0:8fdf9a60065b 244 static volatile uint32_t last_tx = 0;
kadonotakashi 0:8fdf9a60065b 245 static volatile RAIL_Handle_t gRailHandle = NULL;
kadonotakashi 0:8fdf9a60065b 246 static uint8_t txFifo[256];
kadonotakashi 0:8fdf9a60065b 247
kadonotakashi 0:8fdf9a60065b 248 /* ARM_NWK_HAL prototypes */
kadonotakashi 0:8fdf9a60065b 249 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr);
kadonotakashi 0:8fdf9a60065b 250 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
kadonotakashi 0:8fdf9a60065b 251 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr);
kadonotakashi 0:8fdf9a60065b 252 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol );
kadonotakashi 0:8fdf9a60065b 253
kadonotakashi 0:8fdf9a60065b 254 /* Local function prototypes */
kadonotakashi 0:8fdf9a60065b 255 static bool rail_checkAndSwitchChannel(uint8_t channel);
kadonotakashi 0:8fdf9a60065b 256 static void RAILCb_RfReady(RAIL_Handle_t railHandle);
kadonotakashi 0:8fdf9a60065b 257 static void radioEventHandler(RAIL_Handle_t railHandle, RAIL_Events_t events);
kadonotakashi 0:8fdf9a60065b 258
kadonotakashi 0:8fdf9a60065b 259 static RAIL_Config_t railCfg = { // Must never be const
kadonotakashi 0:8fdf9a60065b 260 .eventsCallback = &radioEventHandler,
kadonotakashi 0:8fdf9a60065b 261 .protocol = NULL, // For BLE, pointer to a RAIL_BLE_State_t. For IEEE802.15.4 this must be NULL.
kadonotakashi 0:8fdf9a60065b 262 .scheduler = NULL, // For MultiProtocol, pointer to a RAIL_SchedConfig_t
kadonotakashi 0:8fdf9a60065b 263 };
kadonotakashi 0:8fdf9a60065b 264
kadonotakashi 0:8fdf9a60065b 265 static void rf_thread_loop(const void *arg)
kadonotakashi 0:8fdf9a60065b 266 {
kadonotakashi 0:8fdf9a60065b 267 SL_DEBUG_PRINT("rf_thread_loop: starting (id: %d)\n", (int)rf_thread_id);
kadonotakashi 0:8fdf9a60065b 268 for (;;) {
kadonotakashi 0:8fdf9a60065b 269 osEvent event = osSignalWait(0, osWaitForever);
kadonotakashi 0:8fdf9a60065b 270
kadonotakashi 0:8fdf9a60065b 271 if (event.status != osEventSignal) {
kadonotakashi 0:8fdf9a60065b 272 continue;
kadonotakashi 0:8fdf9a60065b 273 }
kadonotakashi 0:8fdf9a60065b 274
kadonotakashi 0:8fdf9a60065b 275 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 276
kadonotakashi 0:8fdf9a60065b 277 if (event.value.signals & SL_RX_DONE) {
kadonotakashi 0:8fdf9a60065b 278 while(rx_queue_tail != rx_queue_head) {
kadonotakashi 0:8fdf9a60065b 279 uint8_t* packet = (uint8_t*) rx_queue[rx_queue_tail];
kadonotakashi 0:8fdf9a60065b 280 SL_DEBUG_PRINT("rPKT %d\n", packet[MAC_PACKET_INFO_LENGTH] - 2);
kadonotakashi 0:8fdf9a60065b 281 device_driver.phy_rx_cb(
kadonotakashi 0:8fdf9a60065b 282 &packet[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */
kadonotakashi 0:8fdf9a60065b 283 packet[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
kadonotakashi 0:8fdf9a60065b 284 packet[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */
kadonotakashi 0:8fdf9a60065b 285 packet[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */
kadonotakashi 0:8fdf9a60065b 286 rf_radio_driver_id);
kadonotakashi 0:8fdf9a60065b 287 rx_queue_tail = (rx_queue_tail + 1) % RF_QUEUE_SIZE;
kadonotakashi 0:8fdf9a60065b 288 }
kadonotakashi 0:8fdf9a60065b 289
kadonotakashi 0:8fdf9a60065b 290 } else if (event.value.signals & SL_TX_DONE) {
kadonotakashi 0:8fdf9a60065b 291 device_driver.phy_tx_done_cb(rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 292 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 293 PHY_LINK_TX_SUCCESS,
kadonotakashi 0:8fdf9a60065b 294 1,
kadonotakashi 0:8fdf9a60065b 295 1);
kadonotakashi 0:8fdf9a60065b 296 } else if (event.value.signals & SL_ACK_RECV) {
kadonotakashi 0:8fdf9a60065b 297 device_driver.phy_tx_done_cb( rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 298 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 299 (event.value.signals & SL_ACK_PEND) ? PHY_LINK_TX_DONE_PENDING : PHY_LINK_TX_DONE,
kadonotakashi 0:8fdf9a60065b 300 1,
kadonotakashi 0:8fdf9a60065b 301 1);
kadonotakashi 0:8fdf9a60065b 302 } else if (event.value.signals & SL_ACK_TIMEOUT) {
kadonotakashi 0:8fdf9a60065b 303 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 304 device_driver.phy_tx_done_cb(rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 305 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 306 PHY_LINK_TX_FAIL,
kadonotakashi 0:8fdf9a60065b 307 1,
kadonotakashi 0:8fdf9a60065b 308 1);
kadonotakashi 0:8fdf9a60065b 309 } else if(event.value.signals & SL_TX_ERR) {
kadonotakashi 0:8fdf9a60065b 310 device_driver.phy_tx_done_cb( rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 311 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 312 PHY_LINK_CCA_FAIL,
kadonotakashi 0:8fdf9a60065b 313 8,
kadonotakashi 0:8fdf9a60065b 314 1);
kadonotakashi 0:8fdf9a60065b 315 } else if(event.value.signals & SL_TX_TIMEOUT) {
kadonotakashi 0:8fdf9a60065b 316 device_driver.phy_tx_done_cb( rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 317 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 318 PHY_LINK_CCA_FAIL,
kadonotakashi 0:8fdf9a60065b 319 8,
kadonotakashi 0:8fdf9a60065b 320 1);
kadonotakashi 0:8fdf9a60065b 321 } else if(event.value.signals & SL_CAL_REQ) {
kadonotakashi 0:8fdf9a60065b 322 SL_DEBUG_PRINT("rf_thread_loop: SL_CAL_REQ signal received (unhandled)\n");
kadonotakashi 0:8fdf9a60065b 323 } else if(event.value.signals & SL_RXFIFO_ERR) {
kadonotakashi 0:8fdf9a60065b 324 SL_DEBUG_PRINT("rf_thread_loop: SL_RXFIFO_ERR signal received (unhandled)\n");
kadonotakashi 0:8fdf9a60065b 325 } else if(event.value.signals & SL_TXFIFO_ERR) {
kadonotakashi 0:8fdf9a60065b 326 SL_DEBUG_PRINT("rf_thread_loop: SL_TXFIFO_ERR signal received (unhandled)\n");
kadonotakashi 0:8fdf9a60065b 327 } else if(event.value.signals & SL_QUEUE_FULL) {
kadonotakashi 0:8fdf9a60065b 328 SL_DEBUG_PRINT("rf_thread_loop: SL_QUEUE_FULL signal received (packet dropped)\n");
kadonotakashi 0:8fdf9a60065b 329 } else {
kadonotakashi 0:8fdf9a60065b 330 SL_DEBUG_PRINT("rf_thread_loop unhandled event status: %d value: %d\n", event.status, (int)event.value.signals);
kadonotakashi 0:8fdf9a60065b 331 }
kadonotakashi 0:8fdf9a60065b 332
kadonotakashi 0:8fdf9a60065b 333 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 334 }
kadonotakashi 0:8fdf9a60065b 335 }
kadonotakashi 0:8fdf9a60065b 336
kadonotakashi 0:8fdf9a60065b 337 /*============ CODE =========*/
kadonotakashi 0:8fdf9a60065b 338
kadonotakashi 0:8fdf9a60065b 339 /*
kadonotakashi 0:8fdf9a60065b 340 * \brief Function initialises and registers the RF driver.
kadonotakashi 0:8fdf9a60065b 341 *
kadonotakashi 0:8fdf9a60065b 342 * \param none
kadonotakashi 0:8fdf9a60065b 343 *
kadonotakashi 0:8fdf9a60065b 344 * \return rf_radio_driver_id Driver ID given by NET library
kadonotakashi 0:8fdf9a60065b 345 */
kadonotakashi 0:8fdf9a60065b 346 static int8_t rf_device_register(void)
kadonotakashi 0:8fdf9a60065b 347 {
kadonotakashi 0:8fdf9a60065b 348 // If we already exist, bail.
kadonotakashi 0:8fdf9a60065b 349 if(radio_state != RADIO_UNINIT) {
kadonotakashi 0:8fdf9a60065b 350 return -1;
kadonotakashi 0:8fdf9a60065b 351 }
kadonotakashi 0:8fdf9a60065b 352
kadonotakashi 0:8fdf9a60065b 353 SL_DEBUG_PRINT("rf_device_register: entry\n");
kadonotakashi 0:8fdf9a60065b 354
kadonotakashi 0:8fdf9a60065b 355 // Set up RAIL
kadonotakashi 0:8fdf9a60065b 356 // Initialize the RAIL library and any internal state it requires
kadonotakashi 0:8fdf9a60065b 357 gRailHandle = RAIL_Init(&railCfg, &RAILCb_RfReady);
kadonotakashi 0:8fdf9a60065b 358
kadonotakashi 0:8fdf9a60065b 359 // Configure calibration settings
kadonotakashi 0:8fdf9a60065b 360 RAIL_ConfigCal(gRailHandle, RAIL_CAL_ALL);
kadonotakashi 0:8fdf9a60065b 361
kadonotakashi 0:8fdf9a60065b 362 // Set up library for IEEE802.15.4 PHY operation
kadonotakashi 0:8fdf9a60065b 363 #if (MBED_CONF_SL_RAIL_BAND == 2400)
kadonotakashi 0:8fdf9a60065b 364 RAIL_IEEE802154_Config2p4GHzRadio(gRailHandle);
kadonotakashi 0:8fdf9a60065b 365 channel = 11;
kadonotakashi 0:8fdf9a60065b 366 #elif (MBED_CONF_SL_RAIL_BAND == 915)
kadonotakashi 0:8fdf9a60065b 367 RAIL_ConfigChannels(gRailHandle, &channels, NULL);
kadonotakashi 0:8fdf9a60065b 368 channel = 1;
kadonotakashi 0:8fdf9a60065b 369 #elif (MBED_CONF_SL_RAIL_BAND == 868)
kadonotakashi 0:8fdf9a60065b 370 RAIL_ConfigChannels(gRailHandle, &channels, NULL);
kadonotakashi 0:8fdf9a60065b 371 channel = 0;
kadonotakashi 0:8fdf9a60065b 372 #endif
kadonotakashi 0:8fdf9a60065b 373
kadonotakashi 0:8fdf9a60065b 374 // Enable 802.15.4 acceleration features
kadonotakashi 0:8fdf9a60065b 375 RAIL_IEEE802154_Init(gRailHandle, &config);
kadonotakashi 0:8fdf9a60065b 376
kadonotakashi 0:8fdf9a60065b 377 // Fire all events by default
kadonotakashi 0:8fdf9a60065b 378 RAIL_ConfigEvents(gRailHandle,
kadonotakashi 0:8fdf9a60065b 379 RAIL_EVENTS_ALL,
kadonotakashi 0:8fdf9a60065b 380 RAIL_EVENTS_ALL);
kadonotakashi 0:8fdf9a60065b 381
kadonotakashi 0:8fdf9a60065b 382 // Setup the transmit buffer
kadonotakashi 0:8fdf9a60065b 383 RAIL_SetTxFifo(gRailHandle, txFifo, 0, sizeof(txFifo));
kadonotakashi 0:8fdf9a60065b 384
kadonotakashi 0:8fdf9a60065b 385 #if MBED_CONF_SL_RAIL_BAND == 2400
kadonotakashi 0:8fdf9a60065b 386 if (RAIL_ConfigTxPower(gRailHandle, &paInit2p4) != RAIL_STATUS_NO_ERROR) {
kadonotakashi 0:8fdf9a60065b 387 // Error: The PA could not be initialized due to an improper configuration.
kadonotakashi 0:8fdf9a60065b 388 // Please ensure your configuration is valid for the selected part.
kadonotakashi 0:8fdf9a60065b 389 while (1) ;
kadonotakashi 0:8fdf9a60065b 390 }
kadonotakashi 0:8fdf9a60065b 391 #elif (MBED_CONF_SL_RAIL_BAND == 915) || (MBED_CONF_SL_RAIL_BAND == 868)
kadonotakashi 0:8fdf9a60065b 392 if (RAIL_ConfigTxPower(gRailHandle, &paInitSubGhz) != RAIL_STATUS_NO_ERROR) {
kadonotakashi 0:8fdf9a60065b 393 // Error: The PA could not be initialized due to an improper configuration.
kadonotakashi 0:8fdf9a60065b 394 // Please ensure your configuration is valid for the selected part.
kadonotakashi 0:8fdf9a60065b 395 while (1) ;
kadonotakashi 0:8fdf9a60065b 396 }
kadonotakashi 0:8fdf9a60065b 397 #endif
kadonotakashi 0:8fdf9a60065b 398 // Set the output power to the maximum supported by this chip
kadonotakashi 0:8fdf9a60065b 399 RAIL_SetTxPower(gRailHandle, 255);
kadonotakashi 0:8fdf9a60065b 400
kadonotakashi 0:8fdf9a60065b 401 // Set up PTI since it makes life so much easier
kadonotakashi 0:8fdf9a60065b 402 #if defined(MBED_CONF_SL_RAIL_PTI) && (MBED_CONF_SL_RAIL_PTI == 1)
kadonotakashi 0:8fdf9a60065b 403 RAIL_PtiConfig_t ptiConfig = {
kadonotakashi 0:8fdf9a60065b 404 MBED_CONF_SL_RAIL_PTI_MODE,
kadonotakashi 0:8fdf9a60065b 405 MBED_CONF_SL_RAIL_PTI_BAUDRATE,
kadonotakashi 0:8fdf9a60065b 406 MBED_CONF_SL_RAIL_PTI_DOUT_LOCATION,
kadonotakashi 0:8fdf9a60065b 407 MBED_CONF_SL_RAIL_PTI_DOUT_PORT,
kadonotakashi 0:8fdf9a60065b 408 MBED_CONF_SL_RAIL_PTI_DOUT_PIN,
kadonotakashi 0:8fdf9a60065b 409 MBED_CONF_SL_RAIL_PTI_DCLK_LOCATION,
kadonotakashi 0:8fdf9a60065b 410 MBED_CONF_SL_RAIL_PTI_DCLK_PORT,
kadonotakashi 0:8fdf9a60065b 411 MBED_CONF_SL_RAIL_PTI_DCLK_PIN,
kadonotakashi 0:8fdf9a60065b 412 MBED_CONF_SL_RAIL_PTI_DFRAME_LOCATION,
kadonotakashi 0:8fdf9a60065b 413 MBED_CONF_SL_RAIL_PTI_DFRAME_PORT,
kadonotakashi 0:8fdf9a60065b 414 MBED_CONF_SL_RAIL_PTI_DFRAME_PIN
kadonotakashi 0:8fdf9a60065b 415 };
kadonotakashi 0:8fdf9a60065b 416
kadonotakashi 0:8fdf9a60065b 417 // Initialize the Packet Trace Interface (PTI) for the EFR32
kadonotakashi 0:8fdf9a60065b 418 RAIL_ConfigPti(RAIL_EFR32_HANDLE, &ptiConfig);
kadonotakashi 0:8fdf9a60065b 419 // Enable Packet Trace (PTI)
kadonotakashi 0:8fdf9a60065b 420 RAIL_EnablePti(RAIL_EFR32_HANDLE, true);
kadonotakashi 0:8fdf9a60065b 421 #endif
kadonotakashi 0:8fdf9a60065b 422
kadonotakashi 0:8fdf9a60065b 423 /* Get real MAC address */
kadonotakashi 0:8fdf9a60065b 424 /* MAC is stored MSB first */
kadonotakashi 0:8fdf9a60065b 425 memcpy(MAC_address, (const void*)&DEVINFO->UNIQUEH, 4);
kadonotakashi 0:8fdf9a60065b 426 memcpy(&MAC_address[4], (const void*)&DEVINFO->UNIQUEL, 4);
kadonotakashi 0:8fdf9a60065b 427
kadonotakashi 0:8fdf9a60065b 428 /*Set pointer to MAC address*/
kadonotakashi 0:8fdf9a60065b 429 device_driver.PHY_MAC = MAC_address;
kadonotakashi 0:8fdf9a60065b 430 device_driver.driver_description = (char*)"EFR32_154";
kadonotakashi 0:8fdf9a60065b 431
kadonotakashi 0:8fdf9a60065b 432 /*Type of RF PHY*/
kadonotakashi 0:8fdf9a60065b 433 #if MBED_CONF_SL_RAIL_BAND == 2400
kadonotakashi 0:8fdf9a60065b 434 device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
kadonotakashi 0:8fdf9a60065b 435 #elif (MBED_CONF_SL_RAIL_BAND == 915) || (MBED_CONF_SL_RAIL_BAND == 868)
kadonotakashi 0:8fdf9a60065b 436 device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
kadonotakashi 0:8fdf9a60065b 437 #endif
kadonotakashi 0:8fdf9a60065b 438
kadonotakashi 0:8fdf9a60065b 439 device_driver.phy_channel_pages = phy_channel_pages;
kadonotakashi 0:8fdf9a60065b 440 /*Maximum size of payload is 127*/
kadonotakashi 0:8fdf9a60065b 441 device_driver.phy_MTU = 127;
kadonotakashi 0:8fdf9a60065b 442 /*1 byte header in PHY layer (length)*/
kadonotakashi 0:8fdf9a60065b 443 device_driver.phy_header_length = 1;
kadonotakashi 0:8fdf9a60065b 444 /*No tail in PHY layer*/
kadonotakashi 0:8fdf9a60065b 445 device_driver.phy_tail_length = 0;
kadonotakashi 0:8fdf9a60065b 446 /*Set address write function*/
kadonotakashi 0:8fdf9a60065b 447 device_driver.address_write = &rf_address_write;
kadonotakashi 0:8fdf9a60065b 448 /*Set RF extension function*/
kadonotakashi 0:8fdf9a60065b 449 device_driver.extension = &rf_extension;
kadonotakashi 0:8fdf9a60065b 450 /*Set RF state control function*/
kadonotakashi 0:8fdf9a60065b 451 device_driver.state_control = &rf_interface_state_control;
kadonotakashi 0:8fdf9a60065b 452 /*Set transmit function*/
kadonotakashi 0:8fdf9a60065b 453 device_driver.tx = &rf_start_cca;
kadonotakashi 0:8fdf9a60065b 454 /*Upper layer callbacks init to NULL, get populated by arm_net_phy_register*/
kadonotakashi 0:8fdf9a60065b 455 device_driver.phy_rx_cb = NULL;
kadonotakashi 0:8fdf9a60065b 456 device_driver.phy_tx_done_cb = NULL;
kadonotakashi 0:8fdf9a60065b 457 /*Virtual upper data callback init to NULL*/
kadonotakashi 0:8fdf9a60065b 458 device_driver.arm_net_virtual_rx_cb = NULL;
kadonotakashi 0:8fdf9a60065b 459 device_driver.arm_net_virtual_tx_cb = NULL;
kadonotakashi 0:8fdf9a60065b 460
kadonotakashi 0:8fdf9a60065b 461 /*Register device driver*/
kadonotakashi 0:8fdf9a60065b 462 rf_radio_driver_id = arm_net_phy_register(&device_driver);
kadonotakashi 0:8fdf9a60065b 463
kadonotakashi 0:8fdf9a60065b 464 // If the radio hasn't called the ready callback by now, place it in the initing state
kadonotakashi 0:8fdf9a60065b 465 if(radio_state == RADIO_UNINIT) {
kadonotakashi 0:8fdf9a60065b 466 radio_state = RADIO_INITING;
kadonotakashi 0:8fdf9a60065b 467 }
kadonotakashi 0:8fdf9a60065b 468
kadonotakashi 0:8fdf9a60065b 469 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 470 rx_queue_head = 0;
kadonotakashi 0:8fdf9a60065b 471 rx_queue_tail = 0;
kadonotakashi 0:8fdf9a60065b 472 rf_thread_id = osThreadCreate(osThread(rf_thread_loop), NULL);
kadonotakashi 0:8fdf9a60065b 473 #endif
kadonotakashi 0:8fdf9a60065b 474
kadonotakashi 0:8fdf9a60065b 475 return rf_radio_driver_id;
kadonotakashi 0:8fdf9a60065b 476 }
kadonotakashi 0:8fdf9a60065b 477
kadonotakashi 0:8fdf9a60065b 478 /*
kadonotakashi 0:8fdf9a60065b 479 * \brief Function unregisters the RF driver.
kadonotakashi 0:8fdf9a60065b 480 *
kadonotakashi 0:8fdf9a60065b 481 * \param none
kadonotakashi 0:8fdf9a60065b 482 *
kadonotakashi 0:8fdf9a60065b 483 * \return none
kadonotakashi 0:8fdf9a60065b 484 */
kadonotakashi 0:8fdf9a60065b 485 static void rf_device_unregister(void)
kadonotakashi 0:8fdf9a60065b 486 {
kadonotakashi 0:8fdf9a60065b 487 arm_net_phy_unregister(rf_radio_driver_id);
kadonotakashi 0:8fdf9a60065b 488 if(sleep_blocked) {
kadonotakashi 0:8fdf9a60065b 489 sleep_manager_unlock_deep_sleep();
kadonotakashi 0:8fdf9a60065b 490 sleep_blocked = false;
kadonotakashi 0:8fdf9a60065b 491 }
kadonotakashi 0:8fdf9a60065b 492 }
kadonotakashi 0:8fdf9a60065b 493
kadonotakashi 0:8fdf9a60065b 494 /*
kadonotakashi 0:8fdf9a60065b 495 * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO.
kadonotakashi 0:8fdf9a60065b 496 *
kadonotakashi 0:8fdf9a60065b 497 * \param data_ptr Pointer to TX data
kadonotakashi 0:8fdf9a60065b 498 * \param data_length Length of the TX data
kadonotakashi 0:8fdf9a60065b 499 * \param tx_handle Handle to transmission
kadonotakashi 0:8fdf9a60065b 500 * \return 0 Success
kadonotakashi 0:8fdf9a60065b 501 * \return -1 Busy
kadonotakashi 0:8fdf9a60065b 502 */
kadonotakashi 0:8fdf9a60065b 503 static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol )
kadonotakashi 0:8fdf9a60065b 504 {
kadonotakashi 0:8fdf9a60065b 505 switch(radio_state) {
kadonotakashi 0:8fdf9a60065b 506 case RADIO_UNINIT:
kadonotakashi 0:8fdf9a60065b 507 SL_DEBUG_PRINT("rf_start_cca: Radio uninit\n");
kadonotakashi 0:8fdf9a60065b 508 return -1;
kadonotakashi 0:8fdf9a60065b 509 case RADIO_INITING:
kadonotakashi 0:8fdf9a60065b 510 SL_DEBUG_PRINT("rf_start_cca: Radio initing\n");
kadonotakashi 0:8fdf9a60065b 511 return -1;
kadonotakashi 0:8fdf9a60065b 512 case RADIO_CALIBRATION:
kadonotakashi 0:8fdf9a60065b 513 SL_DEBUG_PRINT("rf_start_cca: Radio calibrating\n");
kadonotakashi 0:8fdf9a60065b 514 return -1;
kadonotakashi 0:8fdf9a60065b 515 case RADIO_TX:
kadonotakashi 0:8fdf9a60065b 516 SL_DEBUG_PRINT("rf_start_cca: Radio in TX mode\n");
kadonotakashi 0:8fdf9a60065b 517 return -1;
kadonotakashi 0:8fdf9a60065b 518 case RADIO_IDLE:
kadonotakashi 0:8fdf9a60065b 519 case RADIO_RX:
kadonotakashi 0:8fdf9a60065b 520 // If we're still waiting for an ACK, don't mess up the internal state
kadonotakashi 0:8fdf9a60065b 521 if(waiting_for_ack || RAIL_GetRadioState(gRailHandle) == RAIL_RF_STATE_TX) {
kadonotakashi 0:8fdf9a60065b 522 if((RAIL_GetTime() - last_tx) < 30000) {
kadonotakashi 0:8fdf9a60065b 523 SL_DEBUG_PRINT("rf_start_cca: Still waiting on previous ACK\n");
kadonotakashi 0:8fdf9a60065b 524 return -1;
kadonotakashi 0:8fdf9a60065b 525 } else {
kadonotakashi 0:8fdf9a60065b 526 SL_DEBUG_PRINT("rf_start_cca: TXerr\n");
kadonotakashi 0:8fdf9a60065b 527 }
kadonotakashi 0:8fdf9a60065b 528 }
kadonotakashi 0:8fdf9a60065b 529
kadonotakashi 0:8fdf9a60065b 530 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 531
kadonotakashi 0:8fdf9a60065b 532 /* Since we set up Nanostack to give us a 1-byte PHY header, we get the one extra byte at the start of data_ptr
kadonotakashi 0:8fdf9a60065b 533 * and need to populate it with the MAC-frame length byte (including the 2-byte hardware-inserted CRC) */
kadonotakashi 0:8fdf9a60065b 534 data_ptr[0] = data_length + 2;
kadonotakashi 0:8fdf9a60065b 535
kadonotakashi 0:8fdf9a60065b 536 RAIL_Idle(gRailHandle, RAIL_IDLE_ABORT, true);
kadonotakashi 0:8fdf9a60065b 537 RAIL_WriteTxFifo(gRailHandle, data_ptr, data_length + 1, true);
kadonotakashi 0:8fdf9a60065b 538 radio_state = RADIO_TX;
kadonotakashi 0:8fdf9a60065b 539
kadonotakashi 0:8fdf9a60065b 540 RAIL_TxOptions_t txOpt = RAIL_TX_OPTIONS_DEFAULT;
kadonotakashi 0:8fdf9a60065b 541 //Check to see whether we'll be waiting for an ACK
kadonotakashi 0:8fdf9a60065b 542 if(data_ptr[1] & (1 << 5)) {
kadonotakashi 0:8fdf9a60065b 543 txOpt |= RAIL_TX_OPTION_WAIT_FOR_ACK;
kadonotakashi 0:8fdf9a60065b 544 waiting_for_ack = true;
kadonotakashi 0:8fdf9a60065b 545 } else {
kadonotakashi 0:8fdf9a60065b 546 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 547 }
kadonotakashi 0:8fdf9a60065b 548
kadonotakashi 0:8fdf9a60065b 549 SL_DEBUG_PRINT("rf_start_cca: Called TX, len %d, chan %d, ack %d\n", data_length, channel, waiting_for_ack ? 1 : 0);
kadonotakashi 0:8fdf9a60065b 550
kadonotakashi 0:8fdf9a60065b 551 if(RAIL_StartCcaCsmaTx(gRailHandle, channel, txOpt, &csma_config, NULL) == 0) {
kadonotakashi 0:8fdf9a60065b 552 //Save packet number and sequence
kadonotakashi 0:8fdf9a60065b 553 current_tx_handle = tx_handle;
kadonotakashi 0:8fdf9a60065b 554 current_tx_sequence = data_ptr[3];
kadonotakashi 0:8fdf9a60065b 555 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 556 return 0;
kadonotakashi 0:8fdf9a60065b 557 } else {
kadonotakashi 0:8fdf9a60065b 558 RAIL_Idle(gRailHandle, RAIL_IDLE_ABORT, true);
kadonotakashi 0:8fdf9a60065b 559 RAIL_StartRx(gRailHandle, channel, NULL);
kadonotakashi 0:8fdf9a60065b 560 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 561 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 562 return -1;
kadonotakashi 0:8fdf9a60065b 563 }
kadonotakashi 0:8fdf9a60065b 564 }
kadonotakashi 0:8fdf9a60065b 565 //Should never get here...
kadonotakashi 0:8fdf9a60065b 566 return -1;
kadonotakashi 0:8fdf9a60065b 567 }
kadonotakashi 0:8fdf9a60065b 568
kadonotakashi 0:8fdf9a60065b 569 /*
kadonotakashi 0:8fdf9a60065b 570 * \brief Function gives the control of RF states to MAC.
kadonotakashi 0:8fdf9a60065b 571 *
kadonotakashi 0:8fdf9a60065b 572 * \param new_state RF state
kadonotakashi 0:8fdf9a60065b 573 * \param rf_channel RF channel
kadonotakashi 0:8fdf9a60065b 574 *
kadonotakashi 0:8fdf9a60065b 575 * \return 0 Success
kadonotakashi 0:8fdf9a60065b 576 */
kadonotakashi 0:8fdf9a60065b 577 static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
kadonotakashi 0:8fdf9a60065b 578 {
kadonotakashi 0:8fdf9a60065b 579 int8_t ret_val = 0;
kadonotakashi 0:8fdf9a60065b 580 switch (new_state)
kadonotakashi 0:8fdf9a60065b 581 {
kadonotakashi 0:8fdf9a60065b 582 /* Reset PHY driver and set to idle */
kadonotakashi 0:8fdf9a60065b 583 case PHY_INTERFACE_RESET:
kadonotakashi 0:8fdf9a60065b 584 RAIL_Idle(gRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true);
kadonotakashi 0:8fdf9a60065b 585 radio_state = RADIO_IDLE;
kadonotakashi 0:8fdf9a60065b 586 if(sleep_blocked) {
kadonotakashi 0:8fdf9a60065b 587 sleep_manager_unlock_deep_sleep();
kadonotakashi 0:8fdf9a60065b 588 sleep_blocked = false;
kadonotakashi 0:8fdf9a60065b 589 }
kadonotakashi 0:8fdf9a60065b 590 break;
kadonotakashi 0:8fdf9a60065b 591 /* Disable PHY Interface driver */
kadonotakashi 0:8fdf9a60065b 592 case PHY_INTERFACE_DOWN:
kadonotakashi 0:8fdf9a60065b 593 RAIL_Idle(gRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true);
kadonotakashi 0:8fdf9a60065b 594 radio_state = RADIO_IDLE;
kadonotakashi 0:8fdf9a60065b 595 if(sleep_blocked) {
kadonotakashi 0:8fdf9a60065b 596 sleep_manager_unlock_deep_sleep();
kadonotakashi 0:8fdf9a60065b 597 sleep_blocked = false;
kadonotakashi 0:8fdf9a60065b 598 }
kadonotakashi 0:8fdf9a60065b 599 break;
kadonotakashi 0:8fdf9a60065b 600 /* Enable RX */
kadonotakashi 0:8fdf9a60065b 601 case PHY_INTERFACE_UP:
kadonotakashi 0:8fdf9a60065b 602 if(rail_checkAndSwitchChannel(rf_channel)) {
kadonotakashi 0:8fdf9a60065b 603 RAIL_Idle(gRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true);
kadonotakashi 0:8fdf9a60065b 604 RAIL_IEEE802154_SetPromiscuousMode(gRailHandle, false);
kadonotakashi 0:8fdf9a60065b 605 RAIL_StartRx(gRailHandle, channel, NULL);
kadonotakashi 0:8fdf9a60065b 606 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 607 if(!sleep_blocked) {
kadonotakashi 0:8fdf9a60065b 608 /* RX can only happen in EM0/1*/
kadonotakashi 0:8fdf9a60065b 609 sleep_manager_lock_deep_sleep();
kadonotakashi 0:8fdf9a60065b 610 sleep_blocked = true;
kadonotakashi 0:8fdf9a60065b 611 }
kadonotakashi 0:8fdf9a60065b 612 } else {
kadonotakashi 0:8fdf9a60065b 613 ret_val = -1;
kadonotakashi 0:8fdf9a60065b 614 }
kadonotakashi 0:8fdf9a60065b 615 break;
kadonotakashi 0:8fdf9a60065b 616 /* Enable wireless interface ED scan mode */
kadonotakashi 0:8fdf9a60065b 617 case PHY_INTERFACE_RX_ENERGY_STATE:
kadonotakashi 0:8fdf9a60065b 618 SL_DEBUG_PRINT("rf_interface_state_control: Energy det req\n");
kadonotakashi 0:8fdf9a60065b 619 // TODO: implement energy detection
kadonotakashi 0:8fdf9a60065b 620 break;
kadonotakashi 0:8fdf9a60065b 621 /* Enable RX in promiscuous mode (aka no address filtering) */
kadonotakashi 0:8fdf9a60065b 622 case PHY_INTERFACE_SNIFFER_STATE:
kadonotakashi 0:8fdf9a60065b 623 if(rail_checkAndSwitchChannel(rf_channel)) {
kadonotakashi 0:8fdf9a60065b 624 RAIL_Idle(gRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true);
kadonotakashi 0:8fdf9a60065b 625 RAIL_IEEE802154_SetPromiscuousMode(gRailHandle, true);
kadonotakashi 0:8fdf9a60065b 626 RAIL_StartRx(gRailHandle, channel, NULL);
kadonotakashi 0:8fdf9a60065b 627 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 628 if(!sleep_blocked) {
kadonotakashi 0:8fdf9a60065b 629 /* RX can only happen in EM0/1*/
kadonotakashi 0:8fdf9a60065b 630 sleep_manager_lock_deep_sleep();
kadonotakashi 0:8fdf9a60065b 631 sleep_blocked = true;
kadonotakashi 0:8fdf9a60065b 632 }
kadonotakashi 0:8fdf9a60065b 633 } else {
kadonotakashi 0:8fdf9a60065b 634 ret_val = -1;
kadonotakashi 0:8fdf9a60065b 635 }
kadonotakashi 0:8fdf9a60065b 636 break;
kadonotakashi 0:8fdf9a60065b 637 }
kadonotakashi 0:8fdf9a60065b 638 return ret_val;
kadonotakashi 0:8fdf9a60065b 639 }
kadonotakashi 0:8fdf9a60065b 640
kadonotakashi 0:8fdf9a60065b 641 /*
kadonotakashi 0:8fdf9a60065b 642 * \brief Function controls the ACK pending, channel setting and energy detection.
kadonotakashi 0:8fdf9a60065b 643 *
kadonotakashi 0:8fdf9a60065b 644 * \param extension_type Type of control
kadonotakashi 0:8fdf9a60065b 645 * \param data_ptr Data from NET library
kadonotakashi 0:8fdf9a60065b 646 *
kadonotakashi 0:8fdf9a60065b 647 * \return 0 Success
kadonotakashi 0:8fdf9a60065b 648 */
kadonotakashi 0:8fdf9a60065b 649 static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
kadonotakashi 0:8fdf9a60065b 650 {
kadonotakashi 0:8fdf9a60065b 651 switch (extension_type)
kadonotakashi 0:8fdf9a60065b 652 {
kadonotakashi 0:8fdf9a60065b 653 /* Control MAC pending bit for Indirect data transmission */
kadonotakashi 0:8fdf9a60065b 654 case PHY_EXTENSION_CTRL_PENDING_BIT:
kadonotakashi 0:8fdf9a60065b 655 if(*data_ptr) {
kadonotakashi 0:8fdf9a60065b 656 data_pending = true;
kadonotakashi 0:8fdf9a60065b 657 } else {
kadonotakashi 0:8fdf9a60065b 658 data_pending = false;
kadonotakashi 0:8fdf9a60065b 659 }
kadonotakashi 0:8fdf9a60065b 660 break;
kadonotakashi 0:8fdf9a60065b 661 /* Return frame pending bit from last received ACK */
kadonotakashi 0:8fdf9a60065b 662 case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
kadonotakashi 0:8fdf9a60065b 663 if(last_ack_pending_bit) {
kadonotakashi 0:8fdf9a60065b 664 *data_ptr = 0xFF;
kadonotakashi 0:8fdf9a60065b 665 } else {
kadonotakashi 0:8fdf9a60065b 666 *data_ptr = 0;
kadonotakashi 0:8fdf9a60065b 667 }
kadonotakashi 0:8fdf9a60065b 668 break;
kadonotakashi 0:8fdf9a60065b 669 /* Set channel */
kadonotakashi 0:8fdf9a60065b 670 case PHY_EXTENSION_SET_CHANNEL:
kadonotakashi 0:8fdf9a60065b 671 channel = *data_ptr;
kadonotakashi 0:8fdf9a60065b 672 break;
kadonotakashi 0:8fdf9a60065b 673 /* Read energy on the channel */
kadonotakashi 0:8fdf9a60065b 674 case PHY_EXTENSION_READ_CHANNEL_ENERGY:
kadonotakashi 0:8fdf9a60065b 675 // TODO: implement energy detection
kadonotakashi 0:8fdf9a60065b 676 *data_ptr = 0;
kadonotakashi 0:8fdf9a60065b 677 break;
kadonotakashi 0:8fdf9a60065b 678 /* Read status of the link */
kadonotakashi 0:8fdf9a60065b 679 case PHY_EXTENSION_READ_LINK_STATUS:
kadonotakashi 0:8fdf9a60065b 680 // TODO: return accurate value here
kadonotakashi 0:8fdf9a60065b 681 SL_DEBUG_PRINT("rf_extension: Trying to read link status\n");
kadonotakashi 0:8fdf9a60065b 682 break;
kadonotakashi 0:8fdf9a60065b 683 /* Convert between LQI and RSSI */
kadonotakashi 0:8fdf9a60065b 684 case PHY_EXTENSION_CONVERT_SIGNAL_INFO:
kadonotakashi 0:8fdf9a60065b 685 // TODO: return accurate value here
kadonotakashi 0:8fdf9a60065b 686 SL_DEBUG_PRINT("rf_extension: Trying to read signal info\n");
kadonotakashi 0:8fdf9a60065b 687 break;
kadonotakashi 0:8fdf9a60065b 688 case PHY_EXTENSION_ACCEPT_ANY_BEACON:
kadonotakashi 0:8fdf9a60065b 689 SL_DEBUG_PRINT("rf_extension: Trying to accept any beacon\n");
kadonotakashi 0:8fdf9a60065b 690 break;
kadonotakashi 0:8fdf9a60065b 691 }
kadonotakashi 0:8fdf9a60065b 692 return 0;
kadonotakashi 0:8fdf9a60065b 693 }
kadonotakashi 0:8fdf9a60065b 694
kadonotakashi 0:8fdf9a60065b 695 /*
kadonotakashi 0:8fdf9a60065b 696 * \brief Function sets the addresses to RF address filters.
kadonotakashi 0:8fdf9a60065b 697 *
kadonotakashi 0:8fdf9a60065b 698 * \param address_type Type of address
kadonotakashi 0:8fdf9a60065b 699 * \param address_ptr Pointer to given address
kadonotakashi 0:8fdf9a60065b 700 *
kadonotakashi 0:8fdf9a60065b 701 * \return 0 Success
kadonotakashi 0:8fdf9a60065b 702 */
kadonotakashi 0:8fdf9a60065b 703 static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
kadonotakashi 0:8fdf9a60065b 704 {
kadonotakashi 0:8fdf9a60065b 705 int8_t ret_val = 0;
kadonotakashi 0:8fdf9a60065b 706 switch (address_type)
kadonotakashi 0:8fdf9a60065b 707 {
kadonotakashi 0:8fdf9a60065b 708 /*Set 48-bit address*/
kadonotakashi 0:8fdf9a60065b 709 case PHY_MAC_48BIT:
kadonotakashi 0:8fdf9a60065b 710 // 15.4 does not support 48-bit addressing
kadonotakashi 0:8fdf9a60065b 711 ret_val = -1;
kadonotakashi 0:8fdf9a60065b 712 break;
kadonotakashi 0:8fdf9a60065b 713 /*Set 64-bit MAC address*/
kadonotakashi 0:8fdf9a60065b 714 case PHY_MAC_64BIT:
kadonotakashi 0:8fdf9a60065b 715 /* Store MAC in MSB order */
kadonotakashi 0:8fdf9a60065b 716 memcpy(MAC_address, address_ptr, 8);
kadonotakashi 0:8fdf9a60065b 717 SL_DEBUG_PRINT("rf_address_write: MACw ");
kadonotakashi 0:8fdf9a60065b 718 for(unsigned int i = 0; i < sizeof(MAC_address); i ++) {
kadonotakashi 0:8fdf9a60065b 719 SL_DEBUG_PRINT("%02x:", MAC_address[i]);
kadonotakashi 0:8fdf9a60065b 720 }
kadonotakashi 0:8fdf9a60065b 721 SL_DEBUG_PRINT("\n");
kadonotakashi 0:8fdf9a60065b 722 /* Pass MAC to the RF driver in LSB order */
kadonotakashi 0:8fdf9a60065b 723 uint8_t MAC_reversed[8];
kadonotakashi 0:8fdf9a60065b 724 for(unsigned int i = 0; i < sizeof(MAC_address); i ++) {
kadonotakashi 0:8fdf9a60065b 725 MAC_reversed[i] = MAC_address[sizeof(MAC_address) - 1 - i];
kadonotakashi 0:8fdf9a60065b 726 }
kadonotakashi 0:8fdf9a60065b 727 RAIL_IEEE802154_SetLongAddress(gRailHandle, MAC_reversed, 0);
kadonotakashi 0:8fdf9a60065b 728 break;
kadonotakashi 0:8fdf9a60065b 729 /*Set 16-bit address*/
kadonotakashi 0:8fdf9a60065b 730 case PHY_MAC_16BIT:
kadonotakashi 0:8fdf9a60065b 731 short_address = address_ptr[0] << 8 | address_ptr[1];
kadonotakashi 0:8fdf9a60065b 732 RAIL_IEEE802154_SetShortAddress(gRailHandle, short_address, 0);
kadonotakashi 0:8fdf9a60065b 733 break;
kadonotakashi 0:8fdf9a60065b 734 /*Set PAN Id*/
kadonotakashi 0:8fdf9a60065b 735 case PHY_MAC_PANID:
kadonotakashi 0:8fdf9a60065b 736 PAN_address = address_ptr[0] << 8 | address_ptr[1];
kadonotakashi 0:8fdf9a60065b 737 RAIL_IEEE802154_SetPanId(gRailHandle, PAN_address, 0);
kadonotakashi 0:8fdf9a60065b 738 break;
kadonotakashi 0:8fdf9a60065b 739 }
kadonotakashi 0:8fdf9a60065b 740 return ret_val;
kadonotakashi 0:8fdf9a60065b 741 }
kadonotakashi 0:8fdf9a60065b 742
kadonotakashi 0:8fdf9a60065b 743 /*****************************************************************************/
kadonotakashi 0:8fdf9a60065b 744 /*****************************************************************************/
kadonotakashi 0:8fdf9a60065b 745
kadonotakashi 0:8fdf9a60065b 746 static void rf_if_lock(void)
kadonotakashi 0:8fdf9a60065b 747 {
kadonotakashi 0:8fdf9a60065b 748 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 749 }
kadonotakashi 0:8fdf9a60065b 750
kadonotakashi 0:8fdf9a60065b 751 static void rf_if_unlock(void)
kadonotakashi 0:8fdf9a60065b 752 {
kadonotakashi 0:8fdf9a60065b 753 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 754 }
kadonotakashi 0:8fdf9a60065b 755
kadonotakashi 0:8fdf9a60065b 756 NanostackRfPhyEfr32::NanostackRfPhyEfr32() : NanostackRfPhy()
kadonotakashi 0:8fdf9a60065b 757 {
kadonotakashi 0:8fdf9a60065b 758 // Do nothing
kadonotakashi 0:8fdf9a60065b 759 }
kadonotakashi 0:8fdf9a60065b 760
kadonotakashi 0:8fdf9a60065b 761 NanostackRfPhyEfr32::~NanostackRfPhyEfr32()
kadonotakashi 0:8fdf9a60065b 762 {
kadonotakashi 0:8fdf9a60065b 763 rf_unregister();
kadonotakashi 0:8fdf9a60065b 764 }
kadonotakashi 0:8fdf9a60065b 765
kadonotakashi 0:8fdf9a60065b 766 int8_t NanostackRfPhyEfr32::rf_register()
kadonotakashi 0:8fdf9a60065b 767 {
kadonotakashi 0:8fdf9a60065b 768
kadonotakashi 0:8fdf9a60065b 769 rf_if_lock();
kadonotakashi 0:8fdf9a60065b 770
kadonotakashi 0:8fdf9a60065b 771 if (rf != NULL) {
kadonotakashi 0:8fdf9a60065b 772 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 773 error("Multiple registrations of NanostackRfPhyEfr32 not supported");
kadonotakashi 0:8fdf9a60065b 774 return -1;
kadonotakashi 0:8fdf9a60065b 775 }
kadonotakashi 0:8fdf9a60065b 776
kadonotakashi 0:8fdf9a60065b 777 int8_t radio_id = rf_device_register();
kadonotakashi 0:8fdf9a60065b 778 if (radio_id < 0) {
kadonotakashi 0:8fdf9a60065b 779 rf = NULL;
kadonotakashi 0:8fdf9a60065b 780 } else {
kadonotakashi 0:8fdf9a60065b 781 rf = this;
kadonotakashi 0:8fdf9a60065b 782 }
kadonotakashi 0:8fdf9a60065b 783
kadonotakashi 0:8fdf9a60065b 784 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 785 return radio_id;
kadonotakashi 0:8fdf9a60065b 786 }
kadonotakashi 0:8fdf9a60065b 787
kadonotakashi 0:8fdf9a60065b 788 void NanostackRfPhyEfr32::rf_unregister()
kadonotakashi 0:8fdf9a60065b 789 {
kadonotakashi 0:8fdf9a60065b 790 rf_if_lock();
kadonotakashi 0:8fdf9a60065b 791
kadonotakashi 0:8fdf9a60065b 792 if (rf != this) {
kadonotakashi 0:8fdf9a60065b 793 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 794 return;
kadonotakashi 0:8fdf9a60065b 795 }
kadonotakashi 0:8fdf9a60065b 796
kadonotakashi 0:8fdf9a60065b 797 rf_device_unregister();
kadonotakashi 0:8fdf9a60065b 798 rf = NULL;
kadonotakashi 0:8fdf9a60065b 799
kadonotakashi 0:8fdf9a60065b 800 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 801 }
kadonotakashi 0:8fdf9a60065b 802
kadonotakashi 0:8fdf9a60065b 803 void NanostackRfPhyEfr32::get_mac_address(uint8_t *mac)
kadonotakashi 0:8fdf9a60065b 804 {
kadonotakashi 0:8fdf9a60065b 805 rf_if_lock();
kadonotakashi 0:8fdf9a60065b 806
kadonotakashi 0:8fdf9a60065b 807 memcpy(mac, MAC_address, sizeof(MAC_address));
kadonotakashi 0:8fdf9a60065b 808
kadonotakashi 0:8fdf9a60065b 809 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 810 }
kadonotakashi 0:8fdf9a60065b 811
kadonotakashi 0:8fdf9a60065b 812 void NanostackRfPhyEfr32::set_mac_address(uint8_t *mac)
kadonotakashi 0:8fdf9a60065b 813 {
kadonotakashi 0:8fdf9a60065b 814 rf_if_lock();
kadonotakashi 0:8fdf9a60065b 815
kadonotakashi 0:8fdf9a60065b 816 if (NULL != rf) {
kadonotakashi 0:8fdf9a60065b 817 error("NanostackRfPhyEfr32 cannot change mac address when running");
kadonotakashi 0:8fdf9a60065b 818 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 819 return;
kadonotakashi 0:8fdf9a60065b 820 }
kadonotakashi 0:8fdf9a60065b 821
kadonotakashi 0:8fdf9a60065b 822 memcpy(MAC_address, mac, sizeof(MAC_address));
kadonotakashi 0:8fdf9a60065b 823
kadonotakashi 0:8fdf9a60065b 824 rf_if_unlock();
kadonotakashi 0:8fdf9a60065b 825 }
kadonotakashi 0:8fdf9a60065b 826
kadonotakashi 0:8fdf9a60065b 827 uint32_t NanostackRfPhyEfr32::get_driver_version()
kadonotakashi 0:8fdf9a60065b 828 {
kadonotakashi 0:8fdf9a60065b 829 RAIL_Version_t railversion;
kadonotakashi 0:8fdf9a60065b 830 RAIL_GetVersion(&railversion, false);
kadonotakashi 0:8fdf9a60065b 831
kadonotakashi 0:8fdf9a60065b 832 return (railversion.major << 24) |
kadonotakashi 0:8fdf9a60065b 833 (railversion.minor << 16) |
kadonotakashi 0:8fdf9a60065b 834 (railversion.rev << 8) |
kadonotakashi 0:8fdf9a60065b 835 (railversion.build);
kadonotakashi 0:8fdf9a60065b 836 }
kadonotakashi 0:8fdf9a60065b 837
kadonotakashi 0:8fdf9a60065b 838
kadonotakashi 0:8fdf9a60065b 839 //====================== RAIL-defined callbacks =========================
kadonotakashi 0:8fdf9a60065b 840 /**
kadonotakashi 0:8fdf9a60065b 841 * Callback that lets the app know when the radio has finished init
kadonotakashi 0:8fdf9a60065b 842 * and is ready.
kadonotakashi 0:8fdf9a60065b 843 */
kadonotakashi 0:8fdf9a60065b 844 static void RAILCb_RfReady(RAIL_Handle_t handle) {
kadonotakashi 0:8fdf9a60065b 845 (void) handle;
kadonotakashi 0:8fdf9a60065b 846 radio_state = RADIO_IDLE;
kadonotakashi 0:8fdf9a60065b 847 }
kadonotakashi 0:8fdf9a60065b 848
kadonotakashi 0:8fdf9a60065b 849 /**
kadonotakashi 0:8fdf9a60065b 850 * Function to check the requested channel against the current channel,
kadonotakashi 0:8fdf9a60065b 851 * and change the radio configuration if necessary.
kadonotakashi 0:8fdf9a60065b 852 *
kadonotakashi 0:8fdf9a60065b 853 * @param channel The new channel number requested
kadonotakashi 0:8fdf9a60065b 854 * @return bool True if able to switch to the requested channel
kadonotakashi 0:8fdf9a60065b 855 *
kadonotakashi 0:8fdf9a60065b 856 */
kadonotakashi 0:8fdf9a60065b 857 static bool rail_checkAndSwitchChannel(uint8_t newChannel) {
kadonotakashi 0:8fdf9a60065b 858 if(channel == newChannel) {
kadonotakashi 0:8fdf9a60065b 859 return true;
kadonotakashi 0:8fdf9a60065b 860 }
kadonotakashi 0:8fdf9a60065b 861
kadonotakashi 0:8fdf9a60065b 862 if(newChannel > 0 && newChannel < 11) {
kadonotakashi 0:8fdf9a60065b 863 if(MBED_CONF_SL_RAIL_BAND == 915) {
kadonotakashi 0:8fdf9a60065b 864 channel = newChannel;
kadonotakashi 0:8fdf9a60065b 865 return true;
kadonotakashi 0:8fdf9a60065b 866 } else {
kadonotakashi 0:8fdf9a60065b 867 return false;
kadonotakashi 0:8fdf9a60065b 868 }
kadonotakashi 0:8fdf9a60065b 869 } else if(newChannel >= 11 && newChannel <= 26) {
kadonotakashi 0:8fdf9a60065b 870 if(MBED_CONF_SL_RAIL_BAND == 2400) {
kadonotakashi 0:8fdf9a60065b 871 channel = newChannel;
kadonotakashi 0:8fdf9a60065b 872 return true;
kadonotakashi 0:8fdf9a60065b 873 } else {
kadonotakashi 0:8fdf9a60065b 874 return false;
kadonotakashi 0:8fdf9a60065b 875 }
kadonotakashi 0:8fdf9a60065b 876 } else {
kadonotakashi 0:8fdf9a60065b 877 return false;
kadonotakashi 0:8fdf9a60065b 878 }
kadonotakashi 0:8fdf9a60065b 879 }
kadonotakashi 0:8fdf9a60065b 880
kadonotakashi 0:8fdf9a60065b 881 /**
kadonotakashi 0:8fdf9a60065b 882 * Event handler for RAIL-fired events. Usually gets called from IRQ context.
kadonotakashi 0:8fdf9a60065b 883 * Due to IRQ latency and tailchaining, multiple event flags might be set simultaneously,
kadonotakashi 0:8fdf9a60065b 884 * so we have to check all of them */
kadonotakashi 0:8fdf9a60065b 885 static void radioEventHandler(RAIL_Handle_t railHandle,
kadonotakashi 0:8fdf9a60065b 886 RAIL_Events_t events)
kadonotakashi 0:8fdf9a60065b 887 {
kadonotakashi 0:8fdf9a60065b 888 /* RAIL_Events_t is a 64-bit event mask, but a thread only supports 32
kadonotakashi 0:8fdf9a60065b 889 * signal bits. This means we have to convert from a RAIL event mask to
kadonotakashi 0:8fdf9a60065b 890 * our own custom event mask. */
kadonotakashi 0:8fdf9a60065b 891 if (railHandle != gRailHandle)
kadonotakashi 0:8fdf9a60065b 892 return;
kadonotakashi 0:8fdf9a60065b 893
kadonotakashi 0:8fdf9a60065b 894 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 895 if(rf_thread_id == 0) {
kadonotakashi 0:8fdf9a60065b 896 return;
kadonotakashi 0:8fdf9a60065b 897 }
kadonotakashi 0:8fdf9a60065b 898 #endif
kadonotakashi 0:8fdf9a60065b 899
kadonotakashi 0:8fdf9a60065b 900 size_t index = 0;
kadonotakashi 0:8fdf9a60065b 901 do {
kadonotakashi 0:8fdf9a60065b 902 if (events & 1ull) {
kadonotakashi 0:8fdf9a60065b 903 switch(index) {
kadonotakashi 0:8fdf9a60065b 904 /*
kadonotakashi 0:8fdf9a60065b 905 * Occurs when the AGC averaged RSSI is done.
kadonotakashi 0:8fdf9a60065b 906 * It occurs in response to RAIL_StartAverageRssi() to indicate that the
kadonotakashi 0:8fdf9a60065b 907 * hardware has completed averaging. Call \ref RAIL_GetAverageRssi to get the
kadonotakashi 0:8fdf9a60065b 908 * result.
kadonotakashi 0:8fdf9a60065b 909 */
kadonotakashi 0:8fdf9a60065b 910 case RAIL_EVENT_RSSI_AVERAGE_DONE_SHIFT:
kadonotakashi 0:8fdf9a60065b 911 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 912 osSignalSet(rf_thread_id, SL_RSSI_DONE);
kadonotakashi 0:8fdf9a60065b 913 #else
kadonotakashi 0:8fdf9a60065b 914 SL_DEBUG_PRINT("RSSI done (%d)\n", RAIL_GetAverageRssi(gRailHandle));
kadonotakashi 0:8fdf9a60065b 915 #endif
kadonotakashi 0:8fdf9a60065b 916 break;
kadonotakashi 0:8fdf9a60065b 917 /*
kadonotakashi 0:8fdf9a60065b 918 * Notifies the application when searching for an ACK has timed
kadonotakashi 0:8fdf9a60065b 919 * out. This event occurs whenever the timeout for searching for an
kadonotakashi 0:8fdf9a60065b 920 * ACK is exceeded.
kadonotakashi 0:8fdf9a60065b 921 */
kadonotakashi 0:8fdf9a60065b 922 case RAIL_EVENT_RX_ACK_TIMEOUT_SHIFT:
kadonotakashi 0:8fdf9a60065b 923 if(waiting_for_ack) {
kadonotakashi 0:8fdf9a60065b 924 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 925 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 926 osSignalSet(rf_thread_id, SL_ACK_TIMEOUT);
kadonotakashi 0:8fdf9a60065b 927 #else
kadonotakashi 0:8fdf9a60065b 928 device_driver.phy_tx_done_cb( rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 929 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 930 PHY_LINK_TX_FAIL,
kadonotakashi 0:8fdf9a60065b 931 1,
kadonotakashi 0:8fdf9a60065b 932 1);
kadonotakashi 0:8fdf9a60065b 933 #endif
kadonotakashi 0:8fdf9a60065b 934 }
kadonotakashi 0:8fdf9a60065b 935 break;
kadonotakashi 0:8fdf9a60065b 936 /*
kadonotakashi 0:8fdf9a60065b 937 * Occurs when the receive FIFO exceeds the configured threshold
kadonotakashi 0:8fdf9a60065b 938 * value. Call \ref RAIL_GetRxFifoBytesAvailable to get the number of bytes
kadonotakashi 0:8fdf9a60065b 939 * available.
kadonotakashi 0:8fdf9a60065b 940 */
kadonotakashi 0:8fdf9a60065b 941 case RAIL_EVENT_RX_FIFO_ALMOST_FULL_SHIFT:
kadonotakashi 0:8fdf9a60065b 942 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 943 osSignalSet(rf_thread_id, SL_RXFIFO_ERR);
kadonotakashi 0:8fdf9a60065b 944 #else
kadonotakashi 0:8fdf9a60065b 945 SL_DEBUG_PRINT("RX near full (%d)\n", RAIL_GetRxFifoBytesAvailable(gRailHandle));
kadonotakashi 0:8fdf9a60065b 946 #endif
kadonotakashi 0:8fdf9a60065b 947 break;
kadonotakashi 0:8fdf9a60065b 948 /*
kadonotakashi 0:8fdf9a60065b 949 * Occurs whenever a packet is received.
kadonotakashi 0:8fdf9a60065b 950 * Call RAIL_GetRxPacketInfo() to get basic packet information along
kadonotakashi 0:8fdf9a60065b 951 * with a handle to this packet for subsequent use with
kadonotakashi 0:8fdf9a60065b 952 * RAIL_PeekRxPacket(), RAIL_GetRxPacketDetails(),
kadonotakashi 0:8fdf9a60065b 953 * RAIL_HoldRxPacket(), and RAIL_ReleaseRxPacket() as needed.
kadonotakashi 0:8fdf9a60065b 954 *
kadonotakashi 0:8fdf9a60065b 955 * If \ref RAIL_RX_OPTION_IGNORE_CRC_ERRORS is set, this event also occurs
kadonotakashi 0:8fdf9a60065b 956 * for packets with CRC errors.
kadonotakashi 0:8fdf9a60065b 957 */
kadonotakashi 0:8fdf9a60065b 958 case RAIL_EVENT_RX_PACKET_RECEIVED_SHIFT:
kadonotakashi 0:8fdf9a60065b 959 {
kadonotakashi 0:8fdf9a60065b 960 /* Get RX packet that got signaled */
kadonotakashi 0:8fdf9a60065b 961 RAIL_RxPacketInfo_t rxPacketInfo;
kadonotakashi 0:8fdf9a60065b 962 RAIL_RxPacketHandle_t rxHandle = RAIL_GetRxPacketInfo(gRailHandle,
kadonotakashi 0:8fdf9a60065b 963 RAIL_RX_PACKET_HANDLE_NEWEST,
kadonotakashi 0:8fdf9a60065b 964 &rxPacketInfo
kadonotakashi 0:8fdf9a60065b 965 );
kadonotakashi 0:8fdf9a60065b 966
kadonotakashi 0:8fdf9a60065b 967 /* Only process the packet if it had a correct CRC */
kadonotakashi 0:8fdf9a60065b 968 if(rxPacketInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS) {
kadonotakashi 0:8fdf9a60065b 969 uint8_t header[4];
kadonotakashi 0:8fdf9a60065b 970 RAIL_PeekRxPacket(gRailHandle, rxHandle, header, 4, 0);
kadonotakashi 0:8fdf9a60065b 971
kadonotakashi 0:8fdf9a60065b 972 /* If this is an ACK, deal with it early */
kadonotakashi 0:8fdf9a60065b 973 if( (header[0] == 5) &&
kadonotakashi 0:8fdf9a60065b 974 (header[3] == current_tx_sequence) &&
kadonotakashi 0:8fdf9a60065b 975 waiting_for_ack) {
kadonotakashi 0:8fdf9a60065b 976 /* Tell the radio to not ACK an ACK */
kadonotakashi 0:8fdf9a60065b 977 RAIL_CancelAutoAck(gRailHandle);
kadonotakashi 0:8fdf9a60065b 978 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 979 /* Save the pending bit */
kadonotakashi 0:8fdf9a60065b 980 last_ack_pending_bit = (header[1] & (1 << 4)) != 0;
kadonotakashi 0:8fdf9a60065b 981 /* Release packet */
kadonotakashi 0:8fdf9a60065b 982 RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
kadonotakashi 0:8fdf9a60065b 983 /* Tell the stack we got an ACK */
kadonotakashi 0:8fdf9a60065b 984 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 985 osSignalSet(rf_thread_id, SL_ACK_RECV | (last_ack_pending_bit ? SL_ACK_PEND : 0));
kadonotakashi 0:8fdf9a60065b 986 #else
kadonotakashi 0:8fdf9a60065b 987 SL_DEBUG_PRINT("rACK\n");
kadonotakashi 0:8fdf9a60065b 988 device_driver.phy_tx_done_cb( rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 989 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 990 last_ack_pending_bit ? PHY_LINK_TX_DONE_PENDING : PHY_LINK_TX_DONE,
kadonotakashi 0:8fdf9a60065b 991 1,
kadonotakashi 0:8fdf9a60065b 992 1);
kadonotakashi 0:8fdf9a60065b 993 #endif
kadonotakashi 0:8fdf9a60065b 994 } else {
kadonotakashi 0:8fdf9a60065b 995 /* Get RSSI and LQI information about this packet */
kadonotakashi 0:8fdf9a60065b 996 RAIL_RxPacketDetails_t rxPacketDetails;
kadonotakashi 0:8fdf9a60065b 997 rxPacketDetails.timeReceived.timePosition = RAIL_PACKET_TIME_DEFAULT;
kadonotakashi 0:8fdf9a60065b 998 rxPacketDetails.timeReceived.totalPacketBytes = 0;
kadonotakashi 0:8fdf9a60065b 999 RAIL_GetRxPacketDetails(gRailHandle, rxHandle, &rxPacketDetails);
kadonotakashi 0:8fdf9a60065b 1000
kadonotakashi 0:8fdf9a60065b 1001 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1002 /* Drop this packet if we're out of space */
kadonotakashi 0:8fdf9a60065b 1003 if (((rx_queue_head + 1) % RF_QUEUE_SIZE) == rx_queue_tail) {
kadonotakashi 0:8fdf9a60065b 1004 osSignalSet(rf_thread_id, SL_QUEUE_FULL);
kadonotakashi 0:8fdf9a60065b 1005 RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
kadonotakashi 0:8fdf9a60065b 1006 break;
kadonotakashi 0:8fdf9a60065b 1007 }
kadonotakashi 0:8fdf9a60065b 1008
kadonotakashi 0:8fdf9a60065b 1009 /* Copy into queue */
kadonotakashi 0:8fdf9a60065b 1010 uint8_t* packetBuffer = (uint8_t*)rx_queue[rx_queue_head];
kadonotakashi 0:8fdf9a60065b 1011 #else
kadonotakashi 0:8fdf9a60065b 1012 /* Packet going temporarily onto stack for bare-metal apps */
kadonotakashi 0:8fdf9a60065b 1013 uint8_t packetBuffer[MAC_PACKET_MAX_LENGTH + MAC_PACKET_INFO_LENGTH];
kadonotakashi 0:8fdf9a60065b 1014 #endif
kadonotakashi 0:8fdf9a60065b 1015 /* First two bytes are RSSI and LQI, respecitvely */
kadonotakashi 0:8fdf9a60065b 1016 packetBuffer[MAC_PACKET_OFFSET_RSSI] = (uint8_t)rxPacketDetails.rssi;
kadonotakashi 0:8fdf9a60065b 1017 packetBuffer[MAC_PACKET_OFFSET_LQI] = (uint8_t)rxPacketDetails.lqi;
kadonotakashi 0:8fdf9a60065b 1018
kadonotakashi 0:8fdf9a60065b 1019 /* Copy packet payload from circular FIFO into contiguous memory */
kadonotakashi 0:8fdf9a60065b 1020 RAIL_CopyRxPacket(&packetBuffer[MAC_PACKET_INFO_LENGTH], &rxPacketInfo);
kadonotakashi 0:8fdf9a60065b 1021
kadonotakashi 0:8fdf9a60065b 1022 /* Release RAIL resources early */
kadonotakashi 0:8fdf9a60065b 1023 RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
kadonotakashi 0:8fdf9a60065b 1024
kadonotakashi 0:8fdf9a60065b 1025 /* Figure out whether we want to not ACK this packet */
kadonotakashi 0:8fdf9a60065b 1026
kadonotakashi 0:8fdf9a60065b 1027 /*
kadonotakashi 0:8fdf9a60065b 1028 * packetBuffer[0] = length
kadonotakashi 0:8fdf9a60065b 1029 * dataLength = length w/o length byte
kadonotakashi 0:8fdf9a60065b 1030 * packetBuffer[1:2] = 0x61C9 -> 0b01100001 0b1100 1001 (version 1, dest 3, src 2, ACKreq, type = 1)
kadonotakashi 0:8fdf9a60065b 1031 * [1] => b[0:2] frame type, b[3] = security enabled, b[4] = frame pending, b[5] = ACKreq, b[6] = intrapan
kadonotakashi 0:8fdf9a60065b 1032 * [2] => b[2:3] destmode, b[4:5] version, b[6:7] srcmode
kadonotakashi 0:8fdf9a60065b 1033 */
kadonotakashi 0:8fdf9a60065b 1034 if( (packetBuffer[MAC_PACKET_INFO_LENGTH + 1] & (1 << 5)) == 0 ) {
kadonotakashi 0:8fdf9a60065b 1035 /* Cancel the ACK if the sender did not request one */
kadonotakashi 0:8fdf9a60065b 1036 RAIL_CancelAutoAck(gRailHandle);
kadonotakashi 0:8fdf9a60065b 1037 }
kadonotakashi 0:8fdf9a60065b 1038 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1039 rx_queue_head = (rx_queue_head + 1) % RF_QUEUE_SIZE;
kadonotakashi 0:8fdf9a60065b 1040 osSignalSet(rf_thread_id, SL_RX_DONE);
kadonotakashi 0:8fdf9a60065b 1041 #else
kadonotakashi 0:8fdf9a60065b 1042 SL_DEBUG_PRINT("rPKT %d\n", packetBuffer[MAC_PACKET_INFO_LENGTH] - 2);
kadonotakashi 0:8fdf9a60065b 1043 device_driver.phy_rx_cb(&packetBuffer[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */
kadonotakashi 0:8fdf9a60065b 1044 packetBuffer[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
kadonotakashi 0:8fdf9a60065b 1045 packetBuffer[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */
kadonotakashi 0:8fdf9a60065b 1046 packetBuffer[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */
kadonotakashi 0:8fdf9a60065b 1047 rf_radio_driver_id);
kadonotakashi 0:8fdf9a60065b 1048 #endif
kadonotakashi 0:8fdf9a60065b 1049 }
kadonotakashi 0:8fdf9a60065b 1050 }
kadonotakashi 0:8fdf9a60065b 1051 }
kadonotakashi 0:8fdf9a60065b 1052 break;
kadonotakashi 0:8fdf9a60065b 1053 /* Event for preamble detection */
kadonotakashi 0:8fdf9a60065b 1054 case RAIL_EVENT_RX_PREAMBLE_DETECT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1055 break;
kadonotakashi 0:8fdf9a60065b 1056 /* Event for detection of the first sync word */
kadonotakashi 0:8fdf9a60065b 1057 case RAIL_EVENT_RX_SYNC1_DETECT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1058 break;
kadonotakashi 0:8fdf9a60065b 1059 /** Event for detection of the second sync word */
kadonotakashi 0:8fdf9a60065b 1060 case RAIL_EVENT_RX_SYNC2_DETECT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1061 break;
kadonotakashi 0:8fdf9a60065b 1062 /* Event for detection of frame errors
kadonotakashi 0:8fdf9a60065b 1063 *
kadonotakashi 0:8fdf9a60065b 1064 * For efr32xg1x parts, frame errors include violations of variable length
kadonotakashi 0:8fdf9a60065b 1065 * minimum/maximum limits, frame coding errors, and CRC errors. If \ref
kadonotakashi 0:8fdf9a60065b 1066 * RAIL_RX_OPTION_IGNORE_CRC_ERRORS is set, \ref RAIL_EVENT_RX_FRAME_ERROR
kadonotakashi 0:8fdf9a60065b 1067 * will not occur for CRC errors.
kadonotakashi 0:8fdf9a60065b 1068 */
kadonotakashi 0:8fdf9a60065b 1069 case RAIL_EVENT_RX_FRAME_ERROR_SHIFT:
kadonotakashi 0:8fdf9a60065b 1070 break;
kadonotakashi 0:8fdf9a60065b 1071 /* Occurs when RX buffer is full */
kadonotakashi 0:8fdf9a60065b 1072 case RAIL_EVENT_RX_FIFO_OVERFLOW_SHIFT:
kadonotakashi 0:8fdf9a60065b 1073 break;
kadonotakashi 0:8fdf9a60065b 1074 /* Occurs when a packet is address filtered */
kadonotakashi 0:8fdf9a60065b 1075 case RAIL_EVENT_RX_ADDRESS_FILTERED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1076 break;
kadonotakashi 0:8fdf9a60065b 1077 /* Occurs when an RX event times out */
kadonotakashi 0:8fdf9a60065b 1078 case RAIL_EVENT_RX_TIMEOUT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1079 break;
kadonotakashi 0:8fdf9a60065b 1080 /* Occurs when the scheduled RX window ends */
kadonotakashi 0:8fdf9a60065b 1081 case RAIL_EVENT_RX_SCHEDULED_RX_END_SHIFT:
kadonotakashi 0:8fdf9a60065b 1082 break;
kadonotakashi 0:8fdf9a60065b 1083 /* An event for an aborted packet. It is triggered when a more specific
kadonotakashi 0:8fdf9a60065b 1084 * reason isn't known for why the packet was aborted (e.g.
kadonotakashi 0:8fdf9a60065b 1085 * \ref RAIL_EVENT_RX_ADDRESS_FILTERED). */
kadonotakashi 0:8fdf9a60065b 1086 case RAIL_EVENT_RX_PACKET_ABORTED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1087 break;
kadonotakashi 0:8fdf9a60065b 1088 /*
kadonotakashi 0:8fdf9a60065b 1089 * Occurs when the packet has passed any configured address and frame
kadonotakashi 0:8fdf9a60065b 1090 * filtering options.
kadonotakashi 0:8fdf9a60065b 1091 */
kadonotakashi 0:8fdf9a60065b 1092 case RAIL_EVENT_RX_FILTER_PASSED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1093 break;
kadonotakashi 0:8fdf9a60065b 1094 /* Occurs when modem timing is lost */
kadonotakashi 0:8fdf9a60065b 1095 case RAIL_EVENT_RX_TIMING_LOST_SHIFT:
kadonotakashi 0:8fdf9a60065b 1096 break;
kadonotakashi 0:8fdf9a60065b 1097 /* Occurs when modem timing is detected */
kadonotakashi 0:8fdf9a60065b 1098 case RAIL_EVENT_RX_TIMING_DETECT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1099 break;
kadonotakashi 0:8fdf9a60065b 1100 /*
kadonotakashi 0:8fdf9a60065b 1101 * Indicates a Data Request is being received when using IEEE 802.15.4
kadonotakashi 0:8fdf9a60065b 1102 * functionality. This occurs when the command byte of an incoming frame is
kadonotakashi 0:8fdf9a60065b 1103 * for a data request, which requests an ACK. This callback is called before
kadonotakashi 0:8fdf9a60065b 1104 * the packet is fully received to allow the node to have more time to decide
kadonotakashi 0:8fdf9a60065b 1105 * whether to set the frame pending in the outgoing ACK. This event only ever
kadonotakashi 0:8fdf9a60065b 1106 * occurs if the RAIL IEEE 802.15.4 functionality is enabled.
kadonotakashi 0:8fdf9a60065b 1107 *
kadonotakashi 0:8fdf9a60065b 1108 * Call \ref RAIL_IEEE802154_GetAddress to get the source address of the
kadonotakashi 0:8fdf9a60065b 1109 * packet.
kadonotakashi 0:8fdf9a60065b 1110 */
kadonotakashi 0:8fdf9a60065b 1111 case RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND_SHIFT:
kadonotakashi 0:8fdf9a60065b 1112 if(data_pending) {
kadonotakashi 0:8fdf9a60065b 1113 RAIL_IEEE802154_SetFramePending(gRailHandle);
kadonotakashi 0:8fdf9a60065b 1114 }
kadonotakashi 0:8fdf9a60065b 1115 break;
kadonotakashi 0:8fdf9a60065b 1116
kadonotakashi 0:8fdf9a60065b 1117 // TX Event Bitmasks
kadonotakashi 0:8fdf9a60065b 1118
kadonotakashi 0:8fdf9a60065b 1119 /*
kadonotakashi 0:8fdf9a60065b 1120 * Occurs when the transmit FIFO falls under the configured
kadonotakashi 0:8fdf9a60065b 1121 * threshold value. It only occurs if a rising edge occurs across this
kadonotakashi 0:8fdf9a60065b 1122 * threshold. This event does not occur on initailization or after resetting
kadonotakashi 0:8fdf9a60065b 1123 * the transmit FIFO with RAIL_ResetFifo().
kadonotakashi 0:8fdf9a60065b 1124 * Call \ref RAIL_GetTxFifoSpaceAvailable to get the number of bytes
kadonotakashi 0:8fdf9a60065b 1125 * available in the transmit FIFO at the time of the callback dispatch.
kadonotakashi 0:8fdf9a60065b 1126 */
kadonotakashi 0:8fdf9a60065b 1127 case RAIL_EVENT_TX_FIFO_ALMOST_EMPTY_SHIFT:
kadonotakashi 0:8fdf9a60065b 1128 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1129 osSignalSet(rf_thread_id, SL_TXFIFO_ERR);
kadonotakashi 0:8fdf9a60065b 1130 #else
kadonotakashi 0:8fdf9a60065b 1131 SL_DEBUG_PRINT("TX near empty (%d)\n", spaceAvailable);
kadonotakashi 0:8fdf9a60065b 1132 #endif
kadonotakashi 0:8fdf9a60065b 1133 break;
kadonotakashi 0:8fdf9a60065b 1134 /*
kadonotakashi 0:8fdf9a60065b 1135 * Interrupt level event to signify when the packet was sent.
kadonotakashi 0:8fdf9a60065b 1136 * Call RAIL_GetTxPacketDetails() to get information about the packet
kadonotakashi 0:8fdf9a60065b 1137 * that was transmitted.
kadonotakashi 0:8fdf9a60065b 1138 * @note that this structure is only valid during the timeframe of the
kadonotakashi 0:8fdf9a60065b 1139 * \ref RAIL_Config_t::eventsCallback.
kadonotakashi 0:8fdf9a60065b 1140 */
kadonotakashi 0:8fdf9a60065b 1141 case RAIL_EVENT_TX_PACKET_SENT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1142 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1143 osSignalSet(rf_thread_id, SL_TX_DONE);
kadonotakashi 0:8fdf9a60065b 1144 #else
kadonotakashi 0:8fdf9a60065b 1145 if(device_driver.phy_tx_done_cb != NULL) {
kadonotakashi 0:8fdf9a60065b 1146 device_driver.phy_tx_done_cb( rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 1147 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 1148 // Normally we'd switch on ACK requested here, but Nanostack does that for us.
kadonotakashi 0:8fdf9a60065b 1149 PHY_LINK_TX_SUCCESS,
kadonotakashi 0:8fdf9a60065b 1150 // Succeeded, so how many times we tried is really not relevant.
kadonotakashi 0:8fdf9a60065b 1151 1,
kadonotakashi 0:8fdf9a60065b 1152 1);
kadonotakashi 0:8fdf9a60065b 1153 }
kadonotakashi 0:8fdf9a60065b 1154 #endif
kadonotakashi 0:8fdf9a60065b 1155 last_tx = RAIL_GetTime();
kadonotakashi 0:8fdf9a60065b 1156 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 1157 break;
kadonotakashi 0:8fdf9a60065b 1158 /*
kadonotakashi 0:8fdf9a60065b 1159 * An interrupt level event to signify when the packet was sent.
kadonotakashi 0:8fdf9a60065b 1160 * Call RAIL_GetTxPacketDetails() to get information about the packet
kadonotakashi 0:8fdf9a60065b 1161 * that was transmitted.
kadonotakashi 0:8fdf9a60065b 1162 * @note This structure is only valid during the timeframe of the
kadonotakashi 0:8fdf9a60065b 1163 * \ref RAIL_Config_t::eventsCallback.
kadonotakashi 0:8fdf9a60065b 1164 */
kadonotakashi 0:8fdf9a60065b 1165 case RAIL_EVENT_TXACK_PACKET_SENT_SHIFT:
kadonotakashi 0:8fdf9a60065b 1166 break;
kadonotakashi 0:8fdf9a60065b 1167 /* Occurs when a TX is aborted by the user */
kadonotakashi 0:8fdf9a60065b 1168 case RAIL_EVENT_TX_ABORTED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1169 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1170 osSignalSet(rf_thread_id, SL_TX_TIMEOUT);
kadonotakashi 0:8fdf9a60065b 1171 #else
kadonotakashi 0:8fdf9a60065b 1172 device_driver.phy_tx_done_cb(rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 1173 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 1174 PHY_LINK_CCA_FAIL,
kadonotakashi 0:8fdf9a60065b 1175 8,
kadonotakashi 0:8fdf9a60065b 1176 1);
kadonotakashi 0:8fdf9a60065b 1177 #endif
kadonotakashi 0:8fdf9a60065b 1178 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 1179 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 1180 break;
kadonotakashi 0:8fdf9a60065b 1181 /* Occurs when a TX ACK is aborted by the user */
kadonotakashi 0:8fdf9a60065b 1182 case RAIL_EVENT_TXACK_ABORTED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1183 break;
kadonotakashi 0:8fdf9a60065b 1184 /* Occurs when a TX is blocked by something like PTA or RHO */
kadonotakashi 0:8fdf9a60065b 1185 case RAIL_EVENT_TX_BLOCKED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1186 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1187 osSignalSet(rf_thread_id, SL_TX_TIMEOUT);
kadonotakashi 0:8fdf9a60065b 1188 #else
kadonotakashi 0:8fdf9a60065b 1189 device_driver.phy_tx_done_cb(rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 1190 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 1191 PHY_LINK_CCA_FAIL,
kadonotakashi 0:8fdf9a60065b 1192 8,
kadonotakashi 0:8fdf9a60065b 1193 1);
kadonotakashi 0:8fdf9a60065b 1194 #endif
kadonotakashi 0:8fdf9a60065b 1195 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 1196 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 1197 break;
kadonotakashi 0:8fdf9a60065b 1198 /* Occurs when a TX ACK is blocked by something like PTA or RHO */
kadonotakashi 0:8fdf9a60065b 1199 case RAIL_EVENT_TXACK_BLOCKED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1200 break;
kadonotakashi 0:8fdf9a60065b 1201 /* Occurs when the TX buffer underflows */
kadonotakashi 0:8fdf9a60065b 1202 case RAIL_EVENT_TX_UNDERFLOW_SHIFT:
kadonotakashi 0:8fdf9a60065b 1203 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1204 osSignalSet(rf_thread_id, SL_TX_TIMEOUT);
kadonotakashi 0:8fdf9a60065b 1205 #else
kadonotakashi 0:8fdf9a60065b 1206 device_driver.phy_tx_done_cb(rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 1207 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 1208 PHY_LINK_CCA_FAIL,
kadonotakashi 0:8fdf9a60065b 1209 8,
kadonotakashi 0:8fdf9a60065b 1210 1);
kadonotakashi 0:8fdf9a60065b 1211 #endif
kadonotakashi 0:8fdf9a60065b 1212 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 1213 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 1214 break;
kadonotakashi 0:8fdf9a60065b 1215 /* Occurs when the buffer used for TX acking underflows */
kadonotakashi 0:8fdf9a60065b 1216 case RAIL_EVENT_TXACK_UNDERFLOW_SHIFT:
kadonotakashi 0:8fdf9a60065b 1217 break;
kadonotakashi 0:8fdf9a60065b 1218 /* Occurs when CCA/CSMA/LBT succeeds */
kadonotakashi 0:8fdf9a60065b 1219 case RAIL_EVENT_TX_CHANNEL_CLEAR_SHIFT:
kadonotakashi 0:8fdf9a60065b 1220 break;
kadonotakashi 0:8fdf9a60065b 1221 /* Occurs when CCA/CSMA/LBT fails */
kadonotakashi 0:8fdf9a60065b 1222 case RAIL_EVENT_TX_CHANNEL_BUSY_SHIFT:
kadonotakashi 0:8fdf9a60065b 1223 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1224 osSignalSet(rf_thread_id, SL_TX_TIMEOUT);
kadonotakashi 0:8fdf9a60065b 1225 #else
kadonotakashi 0:8fdf9a60065b 1226 device_driver.phy_tx_done_cb(rf_radio_driver_id,
kadonotakashi 0:8fdf9a60065b 1227 current_tx_handle,
kadonotakashi 0:8fdf9a60065b 1228 PHY_LINK_CCA_FAIL,
kadonotakashi 0:8fdf9a60065b 1229 8,
kadonotakashi 0:8fdf9a60065b 1230 1);
kadonotakashi 0:8fdf9a60065b 1231 #endif
kadonotakashi 0:8fdf9a60065b 1232 waiting_for_ack = false;
kadonotakashi 0:8fdf9a60065b 1233 radio_state = RADIO_RX;
kadonotakashi 0:8fdf9a60065b 1234 break;
kadonotakashi 0:8fdf9a60065b 1235 /* Occurs when a CCA check is being retried */
kadonotakashi 0:8fdf9a60065b 1236 case RAIL_EVENT_TX_CCA_RETRY_SHIFT:
kadonotakashi 0:8fdf9a60065b 1237 break;
kadonotakashi 0:8fdf9a60065b 1238 /** Occurs when a clear channel assessment (CCA) is begun */
kadonotakashi 0:8fdf9a60065b 1239 case RAIL_EVENT_TX_START_CCA_SHIFT:
kadonotakashi 0:8fdf9a60065b 1240 break;
kadonotakashi 0:8fdf9a60065b 1241
kadonotakashi 0:8fdf9a60065b 1242 // Scheduler Event Bitmasks: Not used
kadonotakashi 0:8fdf9a60065b 1243
kadonotakashi 0:8fdf9a60065b 1244 /* Event for when the scheduler switches away from this configuration */
kadonotakashi 0:8fdf9a60065b 1245 case RAIL_EVENT_CONFIG_UNSCHEDULED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1246 break;
kadonotakashi 0:8fdf9a60065b 1247 /* Event for when the scheduler switches to this configuration */
kadonotakashi 0:8fdf9a60065b 1248 case RAIL_EVENT_CONFIG_SCHEDULED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1249 break;
kadonotakashi 0:8fdf9a60065b 1250 /* Event for when the status of the scheduler changes */
kadonotakashi 0:8fdf9a60065b 1251 case RAIL_EVENT_SCHEDULER_STATUS_SHIFT:
kadonotakashi 0:8fdf9a60065b 1252 break;
kadonotakashi 0:8fdf9a60065b 1253
kadonotakashi 0:8fdf9a60065b 1254 // Other Event Bitmasks
kadonotakashi 0:8fdf9a60065b 1255
kadonotakashi 0:8fdf9a60065b 1256 /*
kadonotakashi 0:8fdf9a60065b 1257 * Notifies the application that a calibration is needed.
kadonotakashi 0:8fdf9a60065b 1258 * It occurs whenever the RAIL library detects that a
kadonotakashi 0:8fdf9a60065b 1259 * calibration is needed. An application determines a valid
kadonotakashi 0:8fdf9a60065b 1260 * window to call \ref RAIL_Calibrate().
kadonotakashi 0:8fdf9a60065b 1261 */
kadonotakashi 0:8fdf9a60065b 1262 case RAIL_EVENT_CAL_NEEDED_SHIFT:
kadonotakashi 0:8fdf9a60065b 1263 #ifdef MBED_CONF_RTOS_PRESENT
kadonotakashi 0:8fdf9a60065b 1264 osSignalSet(rf_thread_id, SL_CAL_REQ);
kadonotakashi 0:8fdf9a60065b 1265 #else
kadonotakashi 0:8fdf9a60065b 1266 SL_DEBUG_PRINT("!!!! Calling for calibration\n");
kadonotakashi 0:8fdf9a60065b 1267 #endif
kadonotakashi 0:8fdf9a60065b 1268 break;
kadonotakashi 0:8fdf9a60065b 1269 default:
kadonotakashi 0:8fdf9a60065b 1270 break;
kadonotakashi 0:8fdf9a60065b 1271 }
kadonotakashi 0:8fdf9a60065b 1272 }
kadonotakashi 0:8fdf9a60065b 1273 events = events >> 1;
kadonotakashi 0:8fdf9a60065b 1274 index += 1;
kadonotakashi 0:8fdf9a60065b 1275 }
kadonotakashi 0:8fdf9a60065b 1276 while (events != 0);
kadonotakashi 0:8fdf9a60065b 1277 }
kadonotakashi 0:8fdf9a60065b 1278
kadonotakashi 0:8fdf9a60065b 1279 NanostackRfPhy &NanostackRfPhy::get_default_instance()
kadonotakashi 0:8fdf9a60065b 1280 {
kadonotakashi 0:8fdf9a60065b 1281 static NanostackRfPhyEfr32 rf_phy;
kadonotakashi 0:8fdf9a60065b 1282 return rf_phy;
kadonotakashi 0:8fdf9a60065b 1283 }