Nathan Yonkee / Mbed 2 deprecated Nucleo_sinewave_output_copy

Dependencies:   mbed

Committer:
Nathan Yonkee
Date:
Fri Mar 02 07:12:37 2018 -0700
Revision:
9:d58e77ebd769
add mbed-os library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Nathan Yonkee 9:d58e77ebd769 1 /**
Nathan Yonkee 9:d58e77ebd769 2 / _____) _ | |
Nathan Yonkee 9:d58e77ebd769 3 ( (____ _____ ____ _| |_ _____ ____| |__
Nathan Yonkee 9:d58e77ebd769 4 \____ \| ___ | (_ _) ___ |/ ___) _ \
Nathan Yonkee 9:d58e77ebd769 5 _____) ) ____| | | || |_| ____( (___| | | |
Nathan Yonkee 9:d58e77ebd769 6 (______/|_____)_|_|_| \__)_____)\____)_| |_|
Nathan Yonkee 9:d58e77ebd769 7 (C)2013 Semtech
Nathan Yonkee 9:d58e77ebd769 8 ___ _____ _ ___ _ _____ ___ ___ ___ ___
Nathan Yonkee 9:d58e77ebd769 9 / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
Nathan Yonkee 9:d58e77ebd769 10 \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
Nathan Yonkee 9:d58e77ebd769 11 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
Nathan Yonkee 9:d58e77ebd769 12 embedded.connectivity.solutions===============
Nathan Yonkee 9:d58e77ebd769 13
Nathan Yonkee 9:d58e77ebd769 14 Description: LoRaWAN stack layer that controls both MAC and PHY underneath
Nathan Yonkee 9:d58e77ebd769 15
Nathan Yonkee 9:d58e77ebd769 16 License: Revised BSD License, see LICENSE.TXT file include in the project
Nathan Yonkee 9:d58e77ebd769 17
Nathan Yonkee 9:d58e77ebd769 18 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
Nathan Yonkee 9:d58e77ebd769 19
Nathan Yonkee 9:d58e77ebd769 20
Nathan Yonkee 9:d58e77ebd769 21 Copyright (c) 2017, Arm Limited and affiliates.
Nathan Yonkee 9:d58e77ebd769 22
Nathan Yonkee 9:d58e77ebd769 23 SPDX-License-Identifier: BSD-3-Clause
Nathan Yonkee 9:d58e77ebd769 24 */
Nathan Yonkee 9:d58e77ebd769 25
Nathan Yonkee 9:d58e77ebd769 26 #include <string.h>
Nathan Yonkee 9:d58e77ebd769 27 #include <stdlib.h>
Nathan Yonkee 9:d58e77ebd769 28 #include "platform/Callback.h"
Nathan Yonkee 9:d58e77ebd769 29 #include "events/EventQueue.h"
Nathan Yonkee 9:d58e77ebd769 30 #include "lorawan/LoRaWANStack.h"
Nathan Yonkee 9:d58e77ebd769 31 #if defined(FEATURE_COMMON_PAL)
Nathan Yonkee 9:d58e77ebd769 32 #include "mbed_trace.h"
Nathan Yonkee 9:d58e77ebd769 33 #define TRACE_GROUP "LSTK"
Nathan Yonkee 9:d58e77ebd769 34 #else
Nathan Yonkee 9:d58e77ebd769 35 #define tr_debug(...) (void(0)) //dummies if feature common pal is not added
Nathan Yonkee 9:d58e77ebd769 36 #define tr_info(...) (void(0)) //dummies if feature common pal is not added
Nathan Yonkee 9:d58e77ebd769 37 #define tr_error(...) (void(0)) //dummies if feature common pal is not added
Nathan Yonkee 9:d58e77ebd769 38 #define tr_warn(...) (void(0)) //dummies if feature common pal is not added
Nathan Yonkee 9:d58e77ebd769 39 #endif //defined(FEATURE_COMMON_PAL)
Nathan Yonkee 9:d58e77ebd769 40
Nathan Yonkee 9:d58e77ebd769 41 #define INVALID_PORT 0xFF
Nathan Yonkee 9:d58e77ebd769 42 #define MAX_CONFIRMED_MSG_RETRIES 255
Nathan Yonkee 9:d58e77ebd769 43
Nathan Yonkee 9:d58e77ebd769 44 using namespace mbed;
Nathan Yonkee 9:d58e77ebd769 45 using namespace events;
Nathan Yonkee 9:d58e77ebd769 46
Nathan Yonkee 9:d58e77ebd769 47 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 48 /**
Nathan Yonkee 9:d58e77ebd769 49 *
Nathan Yonkee 9:d58e77ebd769 50 * User application data buffer size if compliance test is used
Nathan Yonkee 9:d58e77ebd769 51 */
Nathan Yonkee 9:d58e77ebd769 52 #if (MBED_CONF_LORA_PHY == 0 || MBED_CONF_LORA_PHY == 4 || MBED_CONF_LORA_PHY == 6 || MBED_CONF_LORA_PHY == 7)
Nathan Yonkee 9:d58e77ebd769 53 #define LORAWAN_COMPLIANCE_TEST_DATA_SIZE 16
Nathan Yonkee 9:d58e77ebd769 54 #elif (MBED_CONF_LORA_PHY == 1 || MBED_CONF_LORA_PHY == 2 || MBED_CONF_LORA_PHY == 8 || MBED_CONF_LORA_PHY == 9)
Nathan Yonkee 9:d58e77ebd769 55 #define LORAWAN_COMPLIANCE_TEST_DATA_SIZE 11
Nathan Yonkee 9:d58e77ebd769 56 #else
Nathan Yonkee 9:d58e77ebd769 57 #error "Must set LoRa PHY layer parameters."
Nathan Yonkee 9:d58e77ebd769 58 #endif
Nathan Yonkee 9:d58e77ebd769 59 #endif
Nathan Yonkee 9:d58e77ebd769 60
Nathan Yonkee 9:d58e77ebd769 61 /*****************************************************************************
Nathan Yonkee 9:d58e77ebd769 62 * Private Member Functions *
Nathan Yonkee 9:d58e77ebd769 63 ****************************************************************************/
Nathan Yonkee 9:d58e77ebd769 64 bool LoRaWANStack::is_port_valid(uint8_t port)
Nathan Yonkee 9:d58e77ebd769 65 {
Nathan Yonkee 9:d58e77ebd769 66 //Application should not use reserved and illegal port numbers.
Nathan Yonkee 9:d58e77ebd769 67 if (port >= 224 || port == 0) {
Nathan Yonkee 9:d58e77ebd769 68 return false;
Nathan Yonkee 9:d58e77ebd769 69 } else {
Nathan Yonkee 9:d58e77ebd769 70 return true;
Nathan Yonkee 9:d58e77ebd769 71 }
Nathan Yonkee 9:d58e77ebd769 72 }
Nathan Yonkee 9:d58e77ebd769 73
Nathan Yonkee 9:d58e77ebd769 74 lorawan_status_t LoRaWANStack::set_application_port(uint8_t port)
Nathan Yonkee 9:d58e77ebd769 75 {
Nathan Yonkee 9:d58e77ebd769 76 if (is_port_valid(port)) {
Nathan Yonkee 9:d58e77ebd769 77 _app_port = port;
Nathan Yonkee 9:d58e77ebd769 78 return LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 79 }
Nathan Yonkee 9:d58e77ebd769 80
Nathan Yonkee 9:d58e77ebd769 81 return LORAWAN_STATUS_PORT_INVALID;
Nathan Yonkee 9:d58e77ebd769 82 }
Nathan Yonkee 9:d58e77ebd769 83
Nathan Yonkee 9:d58e77ebd769 84 /*****************************************************************************
Nathan Yonkee 9:d58e77ebd769 85 * Constructor and destructor *
Nathan Yonkee 9:d58e77ebd769 86 ****************************************************************************/
Nathan Yonkee 9:d58e77ebd769 87 LoRaWANStack::LoRaWANStack()
Nathan Yonkee 9:d58e77ebd769 88 : _loramac(_lora_time), _lora_phy(_lora_time),
Nathan Yonkee 9:d58e77ebd769 89 _device_current_state(DEVICE_STATE_NOT_INITIALIZED), _mac_handlers(NULL),
Nathan Yonkee 9:d58e77ebd769 90 _num_retry(1), _queue(NULL), _duty_cycle_on(MBED_CONF_LORA_DUTY_CYCLE_ON)
Nathan Yonkee 9:d58e77ebd769 91 {
Nathan Yonkee 9:d58e77ebd769 92 #ifdef MBED_CONF_LORA_APP_PORT
Nathan Yonkee 9:d58e77ebd769 93 // is_port_valid() is not virtual, so we can call it in constructor
Nathan Yonkee 9:d58e77ebd769 94 if (is_port_valid(MBED_CONF_LORA_APP_PORT)) {
Nathan Yonkee 9:d58e77ebd769 95 _app_port = MBED_CONF_LORA_APP_PORT;
Nathan Yonkee 9:d58e77ebd769 96 } else {
Nathan Yonkee 9:d58e77ebd769 97 tr_error("User defined port in .json is illegal.");
Nathan Yonkee 9:d58e77ebd769 98 _app_port = INVALID_PORT;
Nathan Yonkee 9:d58e77ebd769 99 }
Nathan Yonkee 9:d58e77ebd769 100
Nathan Yonkee 9:d58e77ebd769 101 #else
Nathan Yonkee 9:d58e77ebd769 102 // initialize it to INVALID_PORT (255) an illegal port number.
Nathan Yonkee 9:d58e77ebd769 103 // user should set the port
Nathan Yonkee 9:d58e77ebd769 104 _app_port = INVALID_PORT;
Nathan Yonkee 9:d58e77ebd769 105 #endif
Nathan Yonkee 9:d58e77ebd769 106
Nathan Yonkee 9:d58e77ebd769 107 memset(&_lw_session, 0, sizeof(_lw_session));
Nathan Yonkee 9:d58e77ebd769 108 memset(&_tx_msg, 0, sizeof(_tx_msg));
Nathan Yonkee 9:d58e77ebd769 109 memset(&_rx_msg, 0, sizeof(_rx_msg));
Nathan Yonkee 9:d58e77ebd769 110
Nathan Yonkee 9:d58e77ebd769 111 LoRaMacPrimitives.mcps_confirm = callback(this, &LoRaWANStack::mcps_confirm_handler);
Nathan Yonkee 9:d58e77ebd769 112 LoRaMacPrimitives.mcps_indication = callback(this, &LoRaWANStack::mcps_indication_handler);
Nathan Yonkee 9:d58e77ebd769 113 LoRaMacPrimitives.mlme_confirm = callback(this, &LoRaWANStack::mlme_confirm_handler);
Nathan Yonkee 9:d58e77ebd769 114 LoRaMacPrimitives.mlme_indication = callback(this, &LoRaWANStack::mlme_indication_handler);
Nathan Yonkee 9:d58e77ebd769 115 }
Nathan Yonkee 9:d58e77ebd769 116
Nathan Yonkee 9:d58e77ebd769 117 LoRaWANStack::~LoRaWANStack()
Nathan Yonkee 9:d58e77ebd769 118 {
Nathan Yonkee 9:d58e77ebd769 119 }
Nathan Yonkee 9:d58e77ebd769 120
Nathan Yonkee 9:d58e77ebd769 121 /*****************************************************************************
Nathan Yonkee 9:d58e77ebd769 122 * Public member functions *
Nathan Yonkee 9:d58e77ebd769 123 ****************************************************************************/
Nathan Yonkee 9:d58e77ebd769 124 LoRaWANStack& LoRaWANStack::get_lorawan_stack()
Nathan Yonkee 9:d58e77ebd769 125 {
Nathan Yonkee 9:d58e77ebd769 126 static LoRaWANStack _lw_stack;
Nathan Yonkee 9:d58e77ebd769 127 return _lw_stack;
Nathan Yonkee 9:d58e77ebd769 128 }
Nathan Yonkee 9:d58e77ebd769 129
Nathan Yonkee 9:d58e77ebd769 130 radio_events_t *LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
Nathan Yonkee 9:d58e77ebd769 131 {
Nathan Yonkee 9:d58e77ebd769 132 // Store pointer to callback routines inside MAC layer (non-IRQ safe)
Nathan Yonkee 9:d58e77ebd769 133 _mac_handlers = _loramac.get_phy_event_handlers();
Nathan Yonkee 9:d58e77ebd769 134 // passes the reference to radio driver down to PHY layer
Nathan Yonkee 9:d58e77ebd769 135 _lora_phy.set_radio_instance(radio);
Nathan Yonkee 9:d58e77ebd769 136 return _mac_handlers;
Nathan Yonkee 9:d58e77ebd769 137 }
Nathan Yonkee 9:d58e77ebd769 138
Nathan Yonkee 9:d58e77ebd769 139 lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
Nathan Yonkee 9:d58e77ebd769 140 {
Nathan Yonkee 9:d58e77ebd769 141 if (DEVICE_STATE_NOT_INITIALIZED != _device_current_state)
Nathan Yonkee 9:d58e77ebd769 142 {
Nathan Yonkee 9:d58e77ebd769 143 tr_debug("Initialized already");
Nathan Yonkee 9:d58e77ebd769 144 return LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 145 }
Nathan Yonkee 9:d58e77ebd769 146
Nathan Yonkee 9:d58e77ebd769 147 tr_debug("Initializing MAC layer");
Nathan Yonkee 9:d58e77ebd769 148
Nathan Yonkee 9:d58e77ebd769 149 //store a pointer to Event Queue
Nathan Yonkee 9:d58e77ebd769 150 _queue = queue;
Nathan Yonkee 9:d58e77ebd769 151
Nathan Yonkee 9:d58e77ebd769 152 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 153 _compliance_test.app_data_buffer = compliance_test_buffer;
Nathan Yonkee 9:d58e77ebd769 154 #endif
Nathan Yonkee 9:d58e77ebd769 155
Nathan Yonkee 9:d58e77ebd769 156 _lora_time.activate_timer_subsystem(queue);
Nathan Yonkee 9:d58e77ebd769 157 _loramac.initialize(&LoRaMacPrimitives, &_lora_phy, queue);
Nathan Yonkee 9:d58e77ebd769 158
Nathan Yonkee 9:d58e77ebd769 159 loramac_mib_req_confirm_t mib_req;
Nathan Yonkee 9:d58e77ebd769 160
Nathan Yonkee 9:d58e77ebd769 161 mib_req.type = MIB_ADR;
Nathan Yonkee 9:d58e77ebd769 162 mib_req.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
Nathan Yonkee 9:d58e77ebd769 163 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 164
Nathan Yonkee 9:d58e77ebd769 165 mib_req.type = MIB_PUBLIC_NETWORK;
Nathan Yonkee 9:d58e77ebd769 166 mib_req.param.enable_public_nwk = MBED_CONF_LORA_PUBLIC_NETWORK;
Nathan Yonkee 9:d58e77ebd769 167 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 168
Nathan Yonkee 9:d58e77ebd769 169 // Reset counters to zero. Will change in future with 1.1 support.
Nathan Yonkee 9:d58e77ebd769 170 _lw_session.downlink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 171 _lw_session.uplink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 172
Nathan Yonkee 9:d58e77ebd769 173 // Start loRaWAN state machine.
Nathan Yonkee 9:d58e77ebd769 174 set_device_state(DEVICE_STATE_INIT);
Nathan Yonkee 9:d58e77ebd769 175 return lora_state_machine();
Nathan Yonkee 9:d58e77ebd769 176 }
Nathan Yonkee 9:d58e77ebd769 177
Nathan Yonkee 9:d58e77ebd769 178 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 179 /**
Nathan Yonkee 9:d58e77ebd769 180 *
Nathan Yonkee 9:d58e77ebd769 181 * Prepares the upload message to reserved ports
Nathan Yonkee 9:d58e77ebd769 182 *
Nathan Yonkee 9:d58e77ebd769 183 * \param port Application port
Nathan Yonkee 9:d58e77ebd769 184 */
Nathan Yonkee 9:d58e77ebd769 185 void LoRaWANStack::prepare_special_tx_frame(uint8_t port)
Nathan Yonkee 9:d58e77ebd769 186 {
Nathan Yonkee 9:d58e77ebd769 187 if (port == 224) {
Nathan Yonkee 9:d58e77ebd769 188 // Clear any normal message stuff before compliance test.
Nathan Yonkee 9:d58e77ebd769 189 memset(&_tx_msg, 0, sizeof(_tx_msg));
Nathan Yonkee 9:d58e77ebd769 190
Nathan Yonkee 9:d58e77ebd769 191 if (_compliance_test.link_check == true) {
Nathan Yonkee 9:d58e77ebd769 192 _compliance_test.link_check = false;
Nathan Yonkee 9:d58e77ebd769 193 _compliance_test.state = 1;
Nathan Yonkee 9:d58e77ebd769 194 _tx_msg.f_buffer_size = 3;
Nathan Yonkee 9:d58e77ebd769 195 _tx_msg.f_buffer[0] = 5;
Nathan Yonkee 9:d58e77ebd769 196 _tx_msg.f_buffer[1] = _compliance_test.demod_margin;
Nathan Yonkee 9:d58e77ebd769 197 _tx_msg.f_buffer[2] = _compliance_test.nb_gateways;
Nathan Yonkee 9:d58e77ebd769 198 } else {
Nathan Yonkee 9:d58e77ebd769 199 switch (_compliance_test.state) {
Nathan Yonkee 9:d58e77ebd769 200 case 4:
Nathan Yonkee 9:d58e77ebd769 201 _compliance_test.state = 1;
Nathan Yonkee 9:d58e77ebd769 202 _tx_msg.f_buffer_size = _compliance_test.app_data_size;
Nathan Yonkee 9:d58e77ebd769 203
Nathan Yonkee 9:d58e77ebd769 204 _tx_msg.f_buffer[0] = _compliance_test.app_data_buffer[0];
Nathan Yonkee 9:d58e77ebd769 205 for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, MBED_CONF_LORA_TX_MAX_SIZE); ++i) {
Nathan Yonkee 9:d58e77ebd769 206 _tx_msg.f_buffer[i] = _compliance_test.app_data_buffer[i];
Nathan Yonkee 9:d58e77ebd769 207 }
Nathan Yonkee 9:d58e77ebd769 208 break;
Nathan Yonkee 9:d58e77ebd769 209 case 1:
Nathan Yonkee 9:d58e77ebd769 210 _tx_msg.f_buffer_size = 2;
Nathan Yonkee 9:d58e77ebd769 211 _tx_msg.f_buffer[0] = _compliance_test.downlink_counter >> 8;
Nathan Yonkee 9:d58e77ebd769 212 _tx_msg.f_buffer[1] = _compliance_test.downlink_counter;
Nathan Yonkee 9:d58e77ebd769 213 break;
Nathan Yonkee 9:d58e77ebd769 214 }
Nathan Yonkee 9:d58e77ebd769 215 }
Nathan Yonkee 9:d58e77ebd769 216 }
Nathan Yonkee 9:d58e77ebd769 217 }
Nathan Yonkee 9:d58e77ebd769 218
Nathan Yonkee 9:d58e77ebd769 219 /** Hands over the compliance test frame to MAC layer
Nathan Yonkee 9:d58e77ebd769 220 *
Nathan Yonkee 9:d58e77ebd769 221 * \return returns the state of the LoRa MAC
Nathan Yonkee 9:d58e77ebd769 222 */
Nathan Yonkee 9:d58e77ebd769 223 lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
Nathan Yonkee 9:d58e77ebd769 224 {
Nathan Yonkee 9:d58e77ebd769 225 loramac_mcps_req_t mcps_req;
Nathan Yonkee 9:d58e77ebd769 226
Nathan Yonkee 9:d58e77ebd769 227 get_phy_params_t phy_params;
Nathan Yonkee 9:d58e77ebd769 228 phy_param_t default_datarate;
Nathan Yonkee 9:d58e77ebd769 229 phy_params.attribute = PHY_DEF_TX_DR;
Nathan Yonkee 9:d58e77ebd769 230 default_datarate = _lora_phy.get_phy_params(&phy_params);
Nathan Yonkee 9:d58e77ebd769 231
Nathan Yonkee 9:d58e77ebd769 232 prepare_special_tx_frame(_compliance_test.app_port);
Nathan Yonkee 9:d58e77ebd769 233
Nathan Yonkee 9:d58e77ebd769 234 if (!_compliance_test.is_tx_confirmed) {
Nathan Yonkee 9:d58e77ebd769 235 mcps_req.type = MCPS_UNCONFIRMED;
Nathan Yonkee 9:d58e77ebd769 236 mcps_req.req.unconfirmed.fport = _compliance_test.app_port;
Nathan Yonkee 9:d58e77ebd769 237 mcps_req.f_buffer = _tx_msg.f_buffer;
Nathan Yonkee 9:d58e77ebd769 238 mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
Nathan Yonkee 9:d58e77ebd769 239 mcps_req.req.unconfirmed.data_rate = default_datarate.value;
Nathan Yonkee 9:d58e77ebd769 240
Nathan Yonkee 9:d58e77ebd769 241 tr_info("Transmit unconfirmed compliance test frame %d bytes.", mcps_req.f_buffer_size);
Nathan Yonkee 9:d58e77ebd769 242
Nathan Yonkee 9:d58e77ebd769 243 for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) {
Nathan Yonkee 9:d58e77ebd769 244 tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]);
Nathan Yonkee 9:d58e77ebd769 245 }
Nathan Yonkee 9:d58e77ebd769 246 } else if (_compliance_test.is_tx_confirmed) {
Nathan Yonkee 9:d58e77ebd769 247 mcps_req.type = MCPS_CONFIRMED;
Nathan Yonkee 9:d58e77ebd769 248 mcps_req.req.confirmed.fport = _compliance_test.app_port;
Nathan Yonkee 9:d58e77ebd769 249 mcps_req.f_buffer = _tx_msg.f_buffer;
Nathan Yonkee 9:d58e77ebd769 250 mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
Nathan Yonkee 9:d58e77ebd769 251 mcps_req.req.confirmed.nb_trials = _num_retry;
Nathan Yonkee 9:d58e77ebd769 252 mcps_req.req.confirmed.data_rate = default_datarate.value;
Nathan Yonkee 9:d58e77ebd769 253
Nathan Yonkee 9:d58e77ebd769 254 tr_info("Transmit confirmed compliance test frame %d bytes.", mcps_req.f_buffer_size);
Nathan Yonkee 9:d58e77ebd769 255
Nathan Yonkee 9:d58e77ebd769 256 for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) {
Nathan Yonkee 9:d58e77ebd769 257 tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]);
Nathan Yonkee 9:d58e77ebd769 258 }
Nathan Yonkee 9:d58e77ebd769 259 } else {
Nathan Yonkee 9:d58e77ebd769 260 return LORAWAN_STATUS_SERVICE_UNKNOWN;
Nathan Yonkee 9:d58e77ebd769 261 }
Nathan Yonkee 9:d58e77ebd769 262
Nathan Yonkee 9:d58e77ebd769 263 return mcps_request_handler(&mcps_req);
Nathan Yonkee 9:d58e77ebd769 264 }
Nathan Yonkee 9:d58e77ebd769 265 #endif
Nathan Yonkee 9:d58e77ebd769 266
Nathan Yonkee 9:d58e77ebd769 267 uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size)
Nathan Yonkee 9:d58e77ebd769 268 {
Nathan Yonkee 9:d58e77ebd769 269 loramac_tx_info_t tx_info;
Nathan Yonkee 9:d58e77ebd769 270 if (_loramac.query_tx_possible(size, &tx_info) == LORAWAN_STATUS_LENGTH_ERROR) {
Nathan Yonkee 9:d58e77ebd769 271 // Cannot transmit this much. Return how much data can be sent
Nathan Yonkee 9:d58e77ebd769 272 // at the moment
Nathan Yonkee 9:d58e77ebd769 273 return tx_info.max_possible_payload_size;
Nathan Yonkee 9:d58e77ebd769 274 }
Nathan Yonkee 9:d58e77ebd769 275
Nathan Yonkee 9:d58e77ebd769 276 return tx_info.current_payload_size;
Nathan Yonkee 9:d58e77ebd769 277 }
Nathan Yonkee 9:d58e77ebd769 278
Nathan Yonkee 9:d58e77ebd769 279 /** Hands over the frame to MAC layer
Nathan Yonkee 9:d58e77ebd769 280 *
Nathan Yonkee 9:d58e77ebd769 281 * \return returns the state of the LoRa MAC
Nathan Yonkee 9:d58e77ebd769 282 */
Nathan Yonkee 9:d58e77ebd769 283 lorawan_status_t LoRaWANStack::send_frame_to_mac()
Nathan Yonkee 9:d58e77ebd769 284 {
Nathan Yonkee 9:d58e77ebd769 285 loramac_mcps_req_t mcps_req;
Nathan Yonkee 9:d58e77ebd769 286 lorawan_status_t status;
Nathan Yonkee 9:d58e77ebd769 287 loramac_mib_req_confirm_t mib_get_params;
Nathan Yonkee 9:d58e77ebd769 288
Nathan Yonkee 9:d58e77ebd769 289 get_phy_params_t phy_params;
Nathan Yonkee 9:d58e77ebd769 290 phy_param_t default_datarate;
Nathan Yonkee 9:d58e77ebd769 291 phy_params.attribute = PHY_DEF_TX_DR;
Nathan Yonkee 9:d58e77ebd769 292 default_datarate = _lora_phy.get_phy_params(&phy_params);
Nathan Yonkee 9:d58e77ebd769 293
Nathan Yonkee 9:d58e77ebd769 294 mcps_req.type = _tx_msg.type;
Nathan Yonkee 9:d58e77ebd769 295
Nathan Yonkee 9:d58e77ebd769 296 if (MCPS_UNCONFIRMED == mcps_req.type) {
Nathan Yonkee 9:d58e77ebd769 297 mcps_req.req.unconfirmed.fport = _tx_msg.message_u.unconfirmed.fport;
Nathan Yonkee 9:d58e77ebd769 298 mcps_req.f_buffer = _tx_msg.f_buffer;
Nathan Yonkee 9:d58e77ebd769 299
Nathan Yonkee 9:d58e77ebd769 300 mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
Nathan Yonkee 9:d58e77ebd769 301
Nathan Yonkee 9:d58e77ebd769 302 mib_get_params.type = MIB_CHANNELS_DATARATE;
Nathan Yonkee 9:d58e77ebd769 303 if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 304 tr_debug("Couldn't get MIB parameters: Using default data rate");
Nathan Yonkee 9:d58e77ebd769 305 mcps_req.req.unconfirmed.data_rate = default_datarate.value;
Nathan Yonkee 9:d58e77ebd769 306 } else {
Nathan Yonkee 9:d58e77ebd769 307 mcps_req.req.unconfirmed.data_rate = mib_get_params.param.channel_data_rate;
Nathan Yonkee 9:d58e77ebd769 308 }
Nathan Yonkee 9:d58e77ebd769 309
Nathan Yonkee 9:d58e77ebd769 310 } else if (mcps_req.type == MCPS_CONFIRMED) {
Nathan Yonkee 9:d58e77ebd769 311 mcps_req.req.confirmed.fport = _tx_msg.message_u.confirmed.fport;
Nathan Yonkee 9:d58e77ebd769 312 mcps_req.f_buffer = _tx_msg.f_buffer;
Nathan Yonkee 9:d58e77ebd769 313 mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
Nathan Yonkee 9:d58e77ebd769 314 mcps_req.req.confirmed.nb_trials = _tx_msg.message_u.confirmed.nb_trials;
Nathan Yonkee 9:d58e77ebd769 315
Nathan Yonkee 9:d58e77ebd769 316 mib_get_params.type = MIB_CHANNELS_DATARATE;
Nathan Yonkee 9:d58e77ebd769 317 if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 318 tr_debug("Couldn't get MIB parameters: Using default data rate");
Nathan Yonkee 9:d58e77ebd769 319 mcps_req.req.confirmed.data_rate = default_datarate.value;
Nathan Yonkee 9:d58e77ebd769 320 } else {
Nathan Yonkee 9:d58e77ebd769 321 mcps_req.req.confirmed.data_rate = mib_get_params.param.channel_data_rate;
Nathan Yonkee 9:d58e77ebd769 322 }
Nathan Yonkee 9:d58e77ebd769 323
Nathan Yonkee 9:d58e77ebd769 324 } else if ( mcps_req.type == MCPS_PROPRIETARY) {
Nathan Yonkee 9:d58e77ebd769 325 mcps_req.f_buffer = _tx_msg.f_buffer;
Nathan Yonkee 9:d58e77ebd769 326 mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
Nathan Yonkee 9:d58e77ebd769 327
Nathan Yonkee 9:d58e77ebd769 328 mib_get_params.type = MIB_CHANNELS_DATARATE;
Nathan Yonkee 9:d58e77ebd769 329 if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 330 tr_debug("Couldn't get MIB parameters: Using default data rate");
Nathan Yonkee 9:d58e77ebd769 331 mcps_req.req.proprietary.data_rate = default_datarate.value;
Nathan Yonkee 9:d58e77ebd769 332 } else {
Nathan Yonkee 9:d58e77ebd769 333 mcps_req.req.proprietary.data_rate = mib_get_params.param.channel_data_rate;
Nathan Yonkee 9:d58e77ebd769 334 }
Nathan Yonkee 9:d58e77ebd769 335
Nathan Yonkee 9:d58e77ebd769 336 } else {
Nathan Yonkee 9:d58e77ebd769 337 return LORAWAN_STATUS_SERVICE_UNKNOWN;
Nathan Yonkee 9:d58e77ebd769 338 }
Nathan Yonkee 9:d58e77ebd769 339
Nathan Yonkee 9:d58e77ebd769 340 status = mcps_request_handler(&mcps_req);
Nathan Yonkee 9:d58e77ebd769 341
Nathan Yonkee 9:d58e77ebd769 342 return status;
Nathan Yonkee 9:d58e77ebd769 343 }
Nathan Yonkee 9:d58e77ebd769 344
Nathan Yonkee 9:d58e77ebd769 345 lorawan_status_t LoRaWANStack::set_confirmed_msg_retry(uint8_t count)
Nathan Yonkee 9:d58e77ebd769 346 {
Nathan Yonkee 9:d58e77ebd769 347 if (count >= MAX_CONFIRMED_MSG_RETRIES) {
Nathan Yonkee 9:d58e77ebd769 348 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 349 }
Nathan Yonkee 9:d58e77ebd769 350
Nathan Yonkee 9:d58e77ebd769 351 _num_retry = count;
Nathan Yonkee 9:d58e77ebd769 352
Nathan Yonkee 9:d58e77ebd769 353 return LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 354 }
Nathan Yonkee 9:d58e77ebd769 355
Nathan Yonkee 9:d58e77ebd769 356 void LoRaWANStack::set_device_state(device_states_t new_state)
Nathan Yonkee 9:d58e77ebd769 357 {
Nathan Yonkee 9:d58e77ebd769 358 _device_current_state = new_state;
Nathan Yonkee 9:d58e77ebd769 359 }
Nathan Yonkee 9:d58e77ebd769 360
Nathan Yonkee 9:d58e77ebd769 361 /*!
Nathan Yonkee 9:d58e77ebd769 362 * \brief MLME-Indication event function
Nathan Yonkee 9:d58e77ebd769 363 *
Nathan Yonkee 9:d58e77ebd769 364 * \param [IN] mlmeIndication - Pointer to the indication structure.
Nathan Yonkee 9:d58e77ebd769 365 */
Nathan Yonkee 9:d58e77ebd769 366 void LoRaWANStack::mlme_indication_handler(loramac_mlme_indication_t *mlmeIndication)
Nathan Yonkee 9:d58e77ebd769 367 {
Nathan Yonkee 9:d58e77ebd769 368 switch( mlmeIndication->indication_type )
Nathan Yonkee 9:d58e77ebd769 369 {
Nathan Yonkee 9:d58e77ebd769 370 case MLME_SCHEDULE_UPLINK:
Nathan Yonkee 9:d58e77ebd769 371 {// The MAC signals that we shall provide an uplink as soon as possible
Nathan Yonkee 9:d58e77ebd769 372 // TODO: Sending implementation missing and will be implemented using
Nathan Yonkee 9:d58e77ebd769 373 // another task.
Nathan Yonkee 9:d58e77ebd769 374 //OnTxNextPacketTimerEvent( );
Nathan Yonkee 9:d58e77ebd769 375 break;
Nathan Yonkee 9:d58e77ebd769 376 }
Nathan Yonkee 9:d58e77ebd769 377 default:
Nathan Yonkee 9:d58e77ebd769 378 break;
Nathan Yonkee 9:d58e77ebd769 379 }
Nathan Yonkee 9:d58e77ebd769 380 }
Nathan Yonkee 9:d58e77ebd769 381
Nathan Yonkee 9:d58e77ebd769 382 void LoRaWANStack::set_lora_callbacks(lorawan_app_callbacks_t *cbs)
Nathan Yonkee 9:d58e77ebd769 383 {
Nathan Yonkee 9:d58e77ebd769 384 if (cbs) {
Nathan Yonkee 9:d58e77ebd769 385 if (cbs->events) {
Nathan Yonkee 9:d58e77ebd769 386 _callbacks.events = cbs->events;
Nathan Yonkee 9:d58e77ebd769 387 }
Nathan Yonkee 9:d58e77ebd769 388
Nathan Yonkee 9:d58e77ebd769 389 if (cbs->link_check_resp) {
Nathan Yonkee 9:d58e77ebd769 390 _callbacks.link_check_resp = cbs->link_check_resp;
Nathan Yonkee 9:d58e77ebd769 391 }
Nathan Yonkee 9:d58e77ebd769 392
Nathan Yonkee 9:d58e77ebd769 393 if (cbs->battery_level) {
Nathan Yonkee 9:d58e77ebd769 394 _callbacks.battery_level = cbs->battery_level;
Nathan Yonkee 9:d58e77ebd769 395 }
Nathan Yonkee 9:d58e77ebd769 396 }
Nathan Yonkee 9:d58e77ebd769 397 }
Nathan Yonkee 9:d58e77ebd769 398
Nathan Yonkee 9:d58e77ebd769 399 lorawan_status_t LoRaWANStack::add_channels(const lorawan_channelplan_t &channel_plan)
Nathan Yonkee 9:d58e77ebd769 400 {
Nathan Yonkee 9:d58e77ebd769 401 // If device is not initialized, stop right away
Nathan Yonkee 9:d58e77ebd769 402 if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
Nathan Yonkee 9:d58e77ebd769 403 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 404 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 405 }
Nathan Yonkee 9:d58e77ebd769 406
Nathan Yonkee 9:d58e77ebd769 407 return _loramac.add_channel_plan(channel_plan);
Nathan Yonkee 9:d58e77ebd769 408 }
Nathan Yonkee 9:d58e77ebd769 409
Nathan Yonkee 9:d58e77ebd769 410 lorawan_status_t LoRaWANStack::drop_channel_list()
Nathan Yonkee 9:d58e77ebd769 411 {
Nathan Yonkee 9:d58e77ebd769 412 if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED) {
Nathan Yonkee 9:d58e77ebd769 413 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 414 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 415 }
Nathan Yonkee 9:d58e77ebd769 416
Nathan Yonkee 9:d58e77ebd769 417 return _loramac.remove_channel_plan();
Nathan Yonkee 9:d58e77ebd769 418 }
Nathan Yonkee 9:d58e77ebd769 419
Nathan Yonkee 9:d58e77ebd769 420 lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
Nathan Yonkee 9:d58e77ebd769 421 {
Nathan Yonkee 9:d58e77ebd769 422 if (_device_current_state == DEVICE_STATE_NOT_INITIALIZED )
Nathan Yonkee 9:d58e77ebd769 423 {
Nathan Yonkee 9:d58e77ebd769 424 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 425 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 426 }
Nathan Yonkee 9:d58e77ebd769 427
Nathan Yonkee 9:d58e77ebd769 428 return _loramac.remove_single_channel(channel_id);
Nathan Yonkee 9:d58e77ebd769 429 }
Nathan Yonkee 9:d58e77ebd769 430
Nathan Yonkee 9:d58e77ebd769 431 lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t& channel_plan)
Nathan Yonkee 9:d58e77ebd769 432 {
Nathan Yonkee 9:d58e77ebd769 433 if (_device_current_state == DEVICE_STATE_JOINING
Nathan Yonkee 9:d58e77ebd769 434 || _device_current_state == DEVICE_STATE_NOT_INITIALIZED
Nathan Yonkee 9:d58e77ebd769 435 || _device_current_state == DEVICE_STATE_INIT)
Nathan Yonkee 9:d58e77ebd769 436 {
Nathan Yonkee 9:d58e77ebd769 437 tr_error("Cannot get channel plan until Joined!");
Nathan Yonkee 9:d58e77ebd769 438 return LORAWAN_STATUS_BUSY;
Nathan Yonkee 9:d58e77ebd769 439 }
Nathan Yonkee 9:d58e77ebd769 440
Nathan Yonkee 9:d58e77ebd769 441 return _loramac.get_channel_plan(channel_plan);
Nathan Yonkee 9:d58e77ebd769 442 }
Nathan Yonkee 9:d58e77ebd769 443
Nathan Yonkee 9:d58e77ebd769 444 lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled)
Nathan Yonkee 9:d58e77ebd769 445 {
Nathan Yonkee 9:d58e77ebd769 446 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state)
Nathan Yonkee 9:d58e77ebd769 447 {
Nathan Yonkee 9:d58e77ebd769 448 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 449 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 450 }
Nathan Yonkee 9:d58e77ebd769 451
Nathan Yonkee 9:d58e77ebd769 452 loramac_mib_req_confirm_t adr_mib_params;
Nathan Yonkee 9:d58e77ebd769 453
Nathan Yonkee 9:d58e77ebd769 454 adr_mib_params.type = MIB_ADR;
Nathan Yonkee 9:d58e77ebd769 455 adr_mib_params.param.is_adr_enable = adr_enabled;
Nathan Yonkee 9:d58e77ebd769 456
Nathan Yonkee 9:d58e77ebd769 457 return mib_set_request(&adr_mib_params);
Nathan Yonkee 9:d58e77ebd769 458 }
Nathan Yonkee 9:d58e77ebd769 459
Nathan Yonkee 9:d58e77ebd769 460 lorawan_status_t LoRaWANStack::set_channel_data_rate(uint8_t data_rate)
Nathan Yonkee 9:d58e77ebd769 461 {
Nathan Yonkee 9:d58e77ebd769 462 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state)
Nathan Yonkee 9:d58e77ebd769 463 {
Nathan Yonkee 9:d58e77ebd769 464 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 465 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 466 }
Nathan Yonkee 9:d58e77ebd769 467
Nathan Yonkee 9:d58e77ebd769 468 loramac_mib_req_confirm_t mib_params;
Nathan Yonkee 9:d58e77ebd769 469 mib_params.type = MIB_ADR;
Nathan Yonkee 9:d58e77ebd769 470 if (mib_get_request(&mib_params) != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 471 tr_error("Cannot set data rate. Please turn off ADR first.");
Nathan Yonkee 9:d58e77ebd769 472 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 473 }
Nathan Yonkee 9:d58e77ebd769 474
Nathan Yonkee 9:d58e77ebd769 475 mib_params.type = MIB_CHANNELS_DATARATE;
Nathan Yonkee 9:d58e77ebd769 476 mib_params.param.channel_data_rate = data_rate;
Nathan Yonkee 9:d58e77ebd769 477
Nathan Yonkee 9:d58e77ebd769 478 return mib_set_request(&mib_params);
Nathan Yonkee 9:d58e77ebd769 479 }
Nathan Yonkee 9:d58e77ebd769 480
Nathan Yonkee 9:d58e77ebd769 481 void LoRaWANStack::commission_device(const lorawan_dev_commission_t &commission_data)
Nathan Yonkee 9:d58e77ebd769 482 {
Nathan Yonkee 9:d58e77ebd769 483 _lw_session.connection.connect_type = commission_data.connection.connect_type;
Nathan Yonkee 9:d58e77ebd769 484 _lw_session.downlink_counter = commission_data.downlink_counter;
Nathan Yonkee 9:d58e77ebd769 485 _lw_session.uplink_counter = commission_data.uplink_counter;
Nathan Yonkee 9:d58e77ebd769 486
Nathan Yonkee 9:d58e77ebd769 487 if (commission_data.connection.connect_type == LORAWAN_CONNECTION_OTAA) {
Nathan Yonkee 9:d58e77ebd769 488 _lw_session.connection.connection_u.otaa.app_eui =
Nathan Yonkee 9:d58e77ebd769 489 commission_data.connection.connection_u.otaa.app_eui;
Nathan Yonkee 9:d58e77ebd769 490 _lw_session.connection.connection_u.otaa.app_key =
Nathan Yonkee 9:d58e77ebd769 491 commission_data.connection.connection_u.otaa.app_key;
Nathan Yonkee 9:d58e77ebd769 492 _lw_session.connection.connection_u.otaa.dev_eui =
Nathan Yonkee 9:d58e77ebd769 493 commission_data.connection.connection_u.otaa.dev_eui;
Nathan Yonkee 9:d58e77ebd769 494 _lw_session.connection.connection_u.otaa.nb_trials =
Nathan Yonkee 9:d58e77ebd769 495 commission_data.connection.connection_u.otaa.nb_trials;
Nathan Yonkee 9:d58e77ebd769 496 } else {
Nathan Yonkee 9:d58e77ebd769 497 _lw_session.connection.connection_u.abp.dev_addr =
Nathan Yonkee 9:d58e77ebd769 498 commission_data.connection.connection_u.abp.dev_addr;
Nathan Yonkee 9:d58e77ebd769 499 _lw_session.connection.connection_u.abp.nwk_skey =
Nathan Yonkee 9:d58e77ebd769 500 commission_data.connection.connection_u.abp.nwk_skey;
Nathan Yonkee 9:d58e77ebd769 501 _lw_session.connection.connection_u.abp.app_skey =
Nathan Yonkee 9:d58e77ebd769 502 commission_data.connection.connection_u.abp.app_skey;
Nathan Yonkee 9:d58e77ebd769 503 }
Nathan Yonkee 9:d58e77ebd769 504 }
Nathan Yonkee 9:d58e77ebd769 505
Nathan Yonkee 9:d58e77ebd769 506 /**
Nathan Yonkee 9:d58e77ebd769 507 *
Nathan Yonkee 9:d58e77ebd769 508 * Join OTAA
Nathan Yonkee 9:d58e77ebd769 509 */
Nathan Yonkee 9:d58e77ebd769 510 lorawan_status_t LoRaWANStack::join_request_by_otaa(const lorawan_connect_t &params)
Nathan Yonkee 9:d58e77ebd769 511 {
Nathan Yonkee 9:d58e77ebd769 512 lorawan_dev_commission_t commission;
Nathan Yonkee 9:d58e77ebd769 513
Nathan Yonkee 9:d58e77ebd769 514 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state)
Nathan Yonkee 9:d58e77ebd769 515 {
Nathan Yonkee 9:d58e77ebd769 516 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 517 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 518 }
Nathan Yonkee 9:d58e77ebd769 519
Nathan Yonkee 9:d58e77ebd769 520 tr_debug("Initiating OTAA");
Nathan Yonkee 9:d58e77ebd769 521
Nathan Yonkee 9:d58e77ebd769 522 commission.connection.connect_type = LORAWAN_CONNECTION_OTAA;
Nathan Yonkee 9:d58e77ebd769 523 commission.connection.connection_u.otaa.dev_eui = params.connection_u.otaa.dev_eui;
Nathan Yonkee 9:d58e77ebd769 524 commission.connection.connection_u.otaa.app_eui = params.connection_u.otaa.app_eui;
Nathan Yonkee 9:d58e77ebd769 525 commission.connection.connection_u.otaa.app_key = params.connection_u.otaa.app_key;
Nathan Yonkee 9:d58e77ebd769 526 commission.connection.connection_u.otaa.nb_trials = params.connection_u.otaa.nb_trials;
Nathan Yonkee 9:d58e77ebd769 527
Nathan Yonkee 9:d58e77ebd769 528 // As mentioned in the comment above, in 1.0.2 spec, counters are always set
Nathan Yonkee 9:d58e77ebd769 529 // to zero for new connection. This section is common for both normal and
Nathan Yonkee 9:d58e77ebd769 530 // connection restore at this moment. Will change in future with 1.1 support.
Nathan Yonkee 9:d58e77ebd769 531 commission.downlink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 532 commission.uplink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 533
Nathan Yonkee 9:d58e77ebd769 534 commission_device(commission);
Nathan Yonkee 9:d58e77ebd769 535 set_device_state(DEVICE_STATE_JOINING);
Nathan Yonkee 9:d58e77ebd769 536 return lora_state_machine();
Nathan Yonkee 9:d58e77ebd769 537 }
Nathan Yonkee 9:d58e77ebd769 538
Nathan Yonkee 9:d58e77ebd769 539 /**
Nathan Yonkee 9:d58e77ebd769 540 *
Nathan Yonkee 9:d58e77ebd769 541 * Connect ABP
Nathan Yonkee 9:d58e77ebd769 542 */
Nathan Yonkee 9:d58e77ebd769 543 lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_connect_t &params)
Nathan Yonkee 9:d58e77ebd769 544 {
Nathan Yonkee 9:d58e77ebd769 545 lorawan_status_t status;
Nathan Yonkee 9:d58e77ebd769 546 lorawan_dev_commission_t commission;
Nathan Yonkee 9:d58e77ebd769 547
Nathan Yonkee 9:d58e77ebd769 548 if (DEVICE_STATE_NOT_INITIALIZED == _device_current_state) {
Nathan Yonkee 9:d58e77ebd769 549 tr_error("Stack not initialized!");
Nathan Yonkee 9:d58e77ebd769 550 return LORAWAN_STATUS_NOT_INITIALIZED;
Nathan Yonkee 9:d58e77ebd769 551 }
Nathan Yonkee 9:d58e77ebd769 552
Nathan Yonkee 9:d58e77ebd769 553 tr_debug("Initiating ABP");
Nathan Yonkee 9:d58e77ebd769 554
Nathan Yonkee 9:d58e77ebd769 555 commission.connection.connect_type = LORAWAN_CONNECTION_ABP;
Nathan Yonkee 9:d58e77ebd769 556 commission.connection.connection_u.abp.dev_addr = params.connection_u.abp.dev_addr;
Nathan Yonkee 9:d58e77ebd769 557 commission.connection.connection_u.abp.nwk_skey = params.connection_u.abp.nwk_skey;
Nathan Yonkee 9:d58e77ebd769 558 commission.connection.connection_u.abp.app_skey = params.connection_u.abp.app_skey;
Nathan Yonkee 9:d58e77ebd769 559
Nathan Yonkee 9:d58e77ebd769 560 // If current state is SHUTDOWN, device may be trying to re-establish
Nathan Yonkee 9:d58e77ebd769 561 // communication. In case of ABP specification is meddled about frame counters.
Nathan Yonkee 9:d58e77ebd769 562 // It says to reset counters to zero but there is no mechanism to tell the
Nathan Yonkee 9:d58e77ebd769 563 // network server that the device was disconnected or restarted.
Nathan Yonkee 9:d58e77ebd769 564 // At the moment, this implementation does not support a non-volatile
Nathan Yonkee 9:d58e77ebd769 565 // memory storage, so we try a last ditch effort here to restore correct
Nathan Yonkee 9:d58e77ebd769 566 // frame counters. If that doesn't work, user must manually reset frame
Nathan Yonkee 9:d58e77ebd769 567 // counters on their network server.
Nathan Yonkee 9:d58e77ebd769 568 commission.downlink_counter = _lw_session.downlink_counter;
Nathan Yonkee 9:d58e77ebd769 569 commission.uplink_counter = _lw_session.uplink_counter;
Nathan Yonkee 9:d58e77ebd769 570
Nathan Yonkee 9:d58e77ebd769 571 tr_debug("Frame Counters. UpCnt=%lu, DownCnt=%lu",
Nathan Yonkee 9:d58e77ebd769 572 commission.uplink_counter, commission.downlink_counter);
Nathan Yonkee 9:d58e77ebd769 573
Nathan Yonkee 9:d58e77ebd769 574 commission_device(commission);
Nathan Yonkee 9:d58e77ebd769 575
Nathan Yonkee 9:d58e77ebd769 576 set_device_state(DEVICE_STATE_ABP_CONNECTING);
Nathan Yonkee 9:d58e77ebd769 577 status = lora_state_machine();
Nathan Yonkee 9:d58e77ebd769 578
Nathan Yonkee 9:d58e77ebd769 579 return status;
Nathan Yonkee 9:d58e77ebd769 580 }
Nathan Yonkee 9:d58e77ebd769 581
Nathan Yonkee 9:d58e77ebd769 582 int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
Nathan Yonkee 9:d58e77ebd769 583 uint16_t length, uint8_t flags)
Nathan Yonkee 9:d58e77ebd769 584 {
Nathan Yonkee 9:d58e77ebd769 585 if (!_lw_session.active) {
Nathan Yonkee 9:d58e77ebd769 586 return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
Nathan Yonkee 9:d58e77ebd769 587 }
Nathan Yonkee 9:d58e77ebd769 588
Nathan Yonkee 9:d58e77ebd769 589 if (_tx_msg.tx_ongoing) {
Nathan Yonkee 9:d58e77ebd769 590 return LORAWAN_STATUS_WOULD_BLOCK;
Nathan Yonkee 9:d58e77ebd769 591 }
Nathan Yonkee 9:d58e77ebd769 592
Nathan Yonkee 9:d58e77ebd769 593 if (!data && length > 0) {
Nathan Yonkee 9:d58e77ebd769 594 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 595 }
Nathan Yonkee 9:d58e77ebd769 596
Nathan Yonkee 9:d58e77ebd769 597 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 598 if (_compliance_test.running) {
Nathan Yonkee 9:d58e77ebd769 599 return LORAWAN_STATUS_COMPLIANCE_TEST_ON;
Nathan Yonkee 9:d58e77ebd769 600 }
Nathan Yonkee 9:d58e77ebd769 601 #endif
Nathan Yonkee 9:d58e77ebd769 602
Nathan Yonkee 9:d58e77ebd769 603 loramac_mib_req_confirm_t mib_req;
Nathan Yonkee 9:d58e77ebd769 604 lorawan_status_t status;
Nathan Yonkee 9:d58e77ebd769 605 mib_req.type = MIB_NETWORK_JOINED;
Nathan Yonkee 9:d58e77ebd769 606 status = mib_get_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 607
Nathan Yonkee 9:d58e77ebd769 608 if (status == LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 609 if (mib_req.param.is_nwk_joined == false) {
Nathan Yonkee 9:d58e77ebd769 610 return LORAWAN_STATUS_NO_NETWORK_JOINED;
Nathan Yonkee 9:d58e77ebd769 611 }
Nathan Yonkee 9:d58e77ebd769 612 }
Nathan Yonkee 9:d58e77ebd769 613
Nathan Yonkee 9:d58e77ebd769 614 status = set_application_port(port);
Nathan Yonkee 9:d58e77ebd769 615
Nathan Yonkee 9:d58e77ebd769 616 if (status != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 617 tr_error("Illegal application port definition.");
Nathan Yonkee 9:d58e77ebd769 618 return status;
Nathan Yonkee 9:d58e77ebd769 619 }
Nathan Yonkee 9:d58e77ebd769 620
Nathan Yonkee 9:d58e77ebd769 621 if (flags == 0
Nathan Yonkee 9:d58e77ebd769 622 || (flags & MSG_FLAG_MASK) == (MSG_CONFIRMED_FLAG|MSG_UNCONFIRMED_FLAG)) {
Nathan Yonkee 9:d58e77ebd769 623 tr_error("CONFIRMED and UNCONFIRMED are mutually exclusive for send()");
Nathan Yonkee 9:d58e77ebd769 624 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 625 }
Nathan Yonkee 9:d58e77ebd769 626
Nathan Yonkee 9:d58e77ebd769 627 _tx_msg.port = port;
Nathan Yonkee 9:d58e77ebd769 628
Nathan Yonkee 9:d58e77ebd769 629 uint16_t max_possible_size = check_possible_tx_size(length);
Nathan Yonkee 9:d58e77ebd769 630
Nathan Yonkee 9:d58e77ebd769 631 if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
Nathan Yonkee 9:d58e77ebd769 632 // LORAWAN_APP_DATA_MAX_SIZE should at least be
Nathan Yonkee 9:d58e77ebd769 633 // either equal to or bigger than maximum possible
Nathan Yonkee 9:d58e77ebd769 634 // tx size because our tx message buffer takes its
Nathan Yonkee 9:d58e77ebd769 635 // length from that macro. Force maximum possible tx unit
Nathan Yonkee 9:d58e77ebd769 636 // to be equal to the buffer size user chose.
Nathan Yonkee 9:d58e77ebd769 637 max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
Nathan Yonkee 9:d58e77ebd769 638 }
Nathan Yonkee 9:d58e77ebd769 639
Nathan Yonkee 9:d58e77ebd769 640 if (max_possible_size < length) {
Nathan Yonkee 9:d58e77ebd769 641 tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
Nathan Yonkee 9:d58e77ebd769 642 length, max_possible_size);
Nathan Yonkee 9:d58e77ebd769 643
Nathan Yonkee 9:d58e77ebd769 644 _tx_msg.pending_size = length - max_possible_size;
Nathan Yonkee 9:d58e77ebd769 645 _tx_msg.f_buffer_size = max_possible_size;
Nathan Yonkee 9:d58e77ebd769 646 // copy user buffer upto the max_possible_size
Nathan Yonkee 9:d58e77ebd769 647 memcpy(_tx_msg.f_buffer, data, _tx_msg.f_buffer_size);
Nathan Yonkee 9:d58e77ebd769 648 } else {
Nathan Yonkee 9:d58e77ebd769 649 // Whole message can be sent at one time
Nathan Yonkee 9:d58e77ebd769 650 _tx_msg.f_buffer_size = length;
Nathan Yonkee 9:d58e77ebd769 651 _tx_msg.pending_size = 0;
Nathan Yonkee 9:d58e77ebd769 652 // copy user buffer upto the max_possible_size
Nathan Yonkee 9:d58e77ebd769 653 if (length > 0) {
Nathan Yonkee 9:d58e77ebd769 654 memcpy(_tx_msg.f_buffer, data, length);
Nathan Yonkee 9:d58e77ebd769 655 }
Nathan Yonkee 9:d58e77ebd769 656 }
Nathan Yonkee 9:d58e77ebd769 657
Nathan Yonkee 9:d58e77ebd769 658 // Handles all unconfirmed messages, including proprietary and multicast
Nathan Yonkee 9:d58e77ebd769 659 if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG
Nathan Yonkee 9:d58e77ebd769 660 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST
Nathan Yonkee 9:d58e77ebd769 661 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) {
Nathan Yonkee 9:d58e77ebd769 662
Nathan Yonkee 9:d58e77ebd769 663 _tx_msg.type = MCPS_UNCONFIRMED;
Nathan Yonkee 9:d58e77ebd769 664 _tx_msg.message_u.unconfirmed.fport = _app_port;
Nathan Yonkee 9:d58e77ebd769 665 }
Nathan Yonkee 9:d58e77ebd769 666
Nathan Yonkee 9:d58e77ebd769 667 // Handles all confirmed messages, including proprietary and multicast
Nathan Yonkee 9:d58e77ebd769 668 if ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG
Nathan Yonkee 9:d58e77ebd769 669 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST
Nathan Yonkee 9:d58e77ebd769 670 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) {
Nathan Yonkee 9:d58e77ebd769 671
Nathan Yonkee 9:d58e77ebd769 672 _tx_msg.type = MCPS_CONFIRMED;
Nathan Yonkee 9:d58e77ebd769 673 _tx_msg.message_u.confirmed.fport = _app_port;
Nathan Yonkee 9:d58e77ebd769 674 _tx_msg.message_u.confirmed.nb_trials = _num_retry;
Nathan Yonkee 9:d58e77ebd769 675 }
Nathan Yonkee 9:d58e77ebd769 676
Nathan Yonkee 9:d58e77ebd769 677 tr_info("RTS = %u bytes, PEND = %u", _tx_msg.f_buffer_size, _tx_msg.pending_size);
Nathan Yonkee 9:d58e77ebd769 678 set_device_state(DEVICE_STATE_SEND);
Nathan Yonkee 9:d58e77ebd769 679 status = lora_state_machine();
Nathan Yonkee 9:d58e77ebd769 680
Nathan Yonkee 9:d58e77ebd769 681 // send user the length of data which is scheduled now.
Nathan Yonkee 9:d58e77ebd769 682 // user should take care of the pending data.
Nathan Yonkee 9:d58e77ebd769 683 return (status == LORAWAN_STATUS_OK) ? _tx_msg.f_buffer_size : (int16_t) status;
Nathan Yonkee 9:d58e77ebd769 684 }
Nathan Yonkee 9:d58e77ebd769 685
Nathan Yonkee 9:d58e77ebd769 686 int16_t LoRaWANStack::handle_rx(const uint8_t port, uint8_t* data,
Nathan Yonkee 9:d58e77ebd769 687 uint16_t length, uint8_t flags)
Nathan Yonkee 9:d58e77ebd769 688 {
Nathan Yonkee 9:d58e77ebd769 689 if (!_lw_session.active) {
Nathan Yonkee 9:d58e77ebd769 690 return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
Nathan Yonkee 9:d58e77ebd769 691 }
Nathan Yonkee 9:d58e77ebd769 692
Nathan Yonkee 9:d58e77ebd769 693 // No messages to read.
Nathan Yonkee 9:d58e77ebd769 694 if (!_rx_msg.receive_ready) {
Nathan Yonkee 9:d58e77ebd769 695 return LORAWAN_STATUS_WOULD_BLOCK;
Nathan Yonkee 9:d58e77ebd769 696 }
Nathan Yonkee 9:d58e77ebd769 697
Nathan Yonkee 9:d58e77ebd769 698 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 699 if (_compliance_test.running) {
Nathan Yonkee 9:d58e77ebd769 700 return LORAWAN_STATUS_COMPLIANCE_TEST_ON;
Nathan Yonkee 9:d58e77ebd769 701 }
Nathan Yonkee 9:d58e77ebd769 702 #endif
Nathan Yonkee 9:d58e77ebd769 703
Nathan Yonkee 9:d58e77ebd769 704 if (data == NULL) {
Nathan Yonkee 9:d58e77ebd769 705 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 706 }
Nathan Yonkee 9:d58e77ebd769 707
Nathan Yonkee 9:d58e77ebd769 708 uint8_t *base_ptr = _rx_msg.msg.mcps_indication.buffer;
Nathan Yonkee 9:d58e77ebd769 709 uint16_t base_size = _rx_msg.msg.mcps_indication.buffer_size;
Nathan Yonkee 9:d58e77ebd769 710 bool read_complete = false;
Nathan Yonkee 9:d58e77ebd769 711
Nathan Yonkee 9:d58e77ebd769 712 if (_rx_msg.msg.mcps_indication.port != port) {
Nathan Yonkee 9:d58e77ebd769 713 // Nothing yet received for this particular port
Nathan Yonkee 9:d58e77ebd769 714 return LORAWAN_STATUS_WOULD_BLOCK;
Nathan Yonkee 9:d58e77ebd769 715 }
Nathan Yonkee 9:d58e77ebd769 716
Nathan Yonkee 9:d58e77ebd769 717 // check if message received is a Confirmed message and user subscribed to it or not
Nathan Yonkee 9:d58e77ebd769 718 if (_rx_msg.msg.mcps_indication.type == MCPS_CONFIRMED
Nathan Yonkee 9:d58e77ebd769 719 && ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG
Nathan Yonkee 9:d58e77ebd769 720 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST
Nathan Yonkee 9:d58e77ebd769 721 || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY)) {
Nathan Yonkee 9:d58e77ebd769 722
Nathan Yonkee 9:d58e77ebd769 723 tr_debug("RX - Confirmed Message, flags=%d", flags);
Nathan Yonkee 9:d58e77ebd769 724 }
Nathan Yonkee 9:d58e77ebd769 725
Nathan Yonkee 9:d58e77ebd769 726 // check if message received is a Unconfirmed message and user subscribed to it or not
Nathan Yonkee 9:d58e77ebd769 727 if (_rx_msg.msg.mcps_indication.type == MCPS_UNCONFIRMED
Nathan Yonkee 9:d58e77ebd769 728 && ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG
Nathan Yonkee 9:d58e77ebd769 729 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST
Nathan Yonkee 9:d58e77ebd769 730 || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY)) {
Nathan Yonkee 9:d58e77ebd769 731 tr_debug("RX - Unconfirmed Message - flags=%d", flags);
Nathan Yonkee 9:d58e77ebd769 732 }
Nathan Yonkee 9:d58e77ebd769 733
Nathan Yonkee 9:d58e77ebd769 734 // check the length of received message whether we can fit into user
Nathan Yonkee 9:d58e77ebd769 735 // buffer completely or not
Nathan Yonkee 9:d58e77ebd769 736 if (_rx_msg.msg.mcps_indication.buffer_size > length &&
Nathan Yonkee 9:d58e77ebd769 737 _rx_msg.prev_read_size == 0) {
Nathan Yonkee 9:d58e77ebd769 738 // we can't fit into user buffer. Invoke counter measures
Nathan Yonkee 9:d58e77ebd769 739 _rx_msg.pending_size = _rx_msg.msg.mcps_indication.buffer_size - length;
Nathan Yonkee 9:d58e77ebd769 740 base_size = length;
Nathan Yonkee 9:d58e77ebd769 741 _rx_msg.prev_read_size = base_size;
Nathan Yonkee 9:d58e77ebd769 742 memcpy(data, base_ptr, base_size);
Nathan Yonkee 9:d58e77ebd769 743 } else if (_rx_msg.prev_read_size == 0) {
Nathan Yonkee 9:d58e77ebd769 744 _rx_msg.pending_size = 0;
Nathan Yonkee 9:d58e77ebd769 745 _rx_msg.prev_read_size = 0;
Nathan Yonkee 9:d58e77ebd769 746 memcpy(data, base_ptr, base_size);
Nathan Yonkee 9:d58e77ebd769 747 read_complete = true;
Nathan Yonkee 9:d58e77ebd769 748 }
Nathan Yonkee 9:d58e77ebd769 749
Nathan Yonkee 9:d58e77ebd769 750 // If its the pending read then we should copy only the remaining part of
Nathan Yonkee 9:d58e77ebd769 751 // the buffer. Due to checks above, in case of a pending read, this block
Nathan Yonkee 9:d58e77ebd769 752 // will be the only one to get invoked
Nathan Yonkee 9:d58e77ebd769 753 if (_rx_msg.pending_size > 0 && _rx_msg.prev_read_size > 0) {
Nathan Yonkee 9:d58e77ebd769 754 memcpy(data, base_ptr+_rx_msg.prev_read_size, base_size);
Nathan Yonkee 9:d58e77ebd769 755 }
Nathan Yonkee 9:d58e77ebd769 756
Nathan Yonkee 9:d58e77ebd769 757 // we are done handing over received buffer to user. check if there is
Nathan Yonkee 9:d58e77ebd769 758 // anything pending. If not, memset the buffer to zero and indicate
Nathan Yonkee 9:d58e77ebd769 759 // that no read is in progress
Nathan Yonkee 9:d58e77ebd769 760 if (read_complete) {
Nathan Yonkee 9:d58e77ebd769 761 memset(_rx_msg.msg.mcps_indication.buffer, 0, LORAMAC_PHY_MAXPAYLOAD);
Nathan Yonkee 9:d58e77ebd769 762 _rx_msg.receive_ready = false;
Nathan Yonkee 9:d58e77ebd769 763 }
Nathan Yonkee 9:d58e77ebd769 764
Nathan Yonkee 9:d58e77ebd769 765 return base_size;
Nathan Yonkee 9:d58e77ebd769 766 }
Nathan Yonkee 9:d58e77ebd769 767
Nathan Yonkee 9:d58e77ebd769 768 lorawan_status_t LoRaWANStack::mlme_request_handler(loramac_mlme_req_t *mlme_request)
Nathan Yonkee 9:d58e77ebd769 769 {
Nathan Yonkee 9:d58e77ebd769 770 if (mlme_request == NULL) {
Nathan Yonkee 9:d58e77ebd769 771 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 772 }
Nathan Yonkee 9:d58e77ebd769 773
Nathan Yonkee 9:d58e77ebd769 774 return _loramac.mlme_request(mlme_request);
Nathan Yonkee 9:d58e77ebd769 775 }
Nathan Yonkee 9:d58e77ebd769 776
Nathan Yonkee 9:d58e77ebd769 777 /** MLME-Confirm event function
Nathan Yonkee 9:d58e77ebd769 778 *
Nathan Yonkee 9:d58e77ebd769 779 * \param mlme_confirm Pointer to the confirm structure,
Nathan Yonkee 9:d58e77ebd769 780 * containing confirm attributes.
Nathan Yonkee 9:d58e77ebd769 781 */
Nathan Yonkee 9:d58e77ebd769 782 void LoRaWANStack::mlme_confirm_handler(loramac_mlme_confirm_t *mlme_confirm)
Nathan Yonkee 9:d58e77ebd769 783 {
Nathan Yonkee 9:d58e77ebd769 784 if (NULL == mlme_confirm) {
Nathan Yonkee 9:d58e77ebd769 785 tr_error("mlme_confirm: struct [in] is null!");
Nathan Yonkee 9:d58e77ebd769 786 MBED_ASSERT(0);
Nathan Yonkee 9:d58e77ebd769 787 return;
Nathan Yonkee 9:d58e77ebd769 788 }
Nathan Yonkee 9:d58e77ebd769 789
Nathan Yonkee 9:d58e77ebd769 790 switch (mlme_confirm->req_type) {
Nathan Yonkee 9:d58e77ebd769 791 case MLME_JOIN:
Nathan Yonkee 9:d58e77ebd769 792 if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 793 // Status is OK, node has joined the network
Nathan Yonkee 9:d58e77ebd769 794 set_device_state(DEVICE_STATE_JOINED);
Nathan Yonkee 9:d58e77ebd769 795 if (lora_state_machine() != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 796 tr_error("Lora state machine did not return LORAWAN_STATUS_OK");
Nathan Yonkee 9:d58e77ebd769 797 }
Nathan Yonkee 9:d58e77ebd769 798 } else {
Nathan Yonkee 9:d58e77ebd769 799 // Join attempt failed.
Nathan Yonkee 9:d58e77ebd769 800 set_device_state(DEVICE_STATE_IDLE);
Nathan Yonkee 9:d58e77ebd769 801 if (lora_state_machine() != LORAWAN_STATUS_IDLE) {
Nathan Yonkee 9:d58e77ebd769 802 tr_error("Lora state machine did not return DEVICE_STATE_IDLE !");
Nathan Yonkee 9:d58e77ebd769 803 }
Nathan Yonkee 9:d58e77ebd769 804
Nathan Yonkee 9:d58e77ebd769 805 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 806 const int ret = _queue->call(_callbacks.events, JOIN_FAILURE);
Nathan Yonkee 9:d58e77ebd769 807 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 808 (void)ret;
Nathan Yonkee 9:d58e77ebd769 809 }
Nathan Yonkee 9:d58e77ebd769 810 }
Nathan Yonkee 9:d58e77ebd769 811 break;
Nathan Yonkee 9:d58e77ebd769 812 case MLME_LINK_CHECK:
Nathan Yonkee 9:d58e77ebd769 813 if (mlme_confirm->status == LORAMAC_EVENT_INFO_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 814 // Check DemodMargin
Nathan Yonkee 9:d58e77ebd769 815 // Check NbGateways
Nathan Yonkee 9:d58e77ebd769 816 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 817 if (_compliance_test.running == true) {
Nathan Yonkee 9:d58e77ebd769 818 _compliance_test.link_check = true;
Nathan Yonkee 9:d58e77ebd769 819 _compliance_test.demod_margin = mlme_confirm->demod_margin;
Nathan Yonkee 9:d58e77ebd769 820 _compliance_test.nb_gateways = mlme_confirm->nb_gateways;
Nathan Yonkee 9:d58e77ebd769 821 } else
Nathan Yonkee 9:d58e77ebd769 822 #endif
Nathan Yonkee 9:d58e77ebd769 823 {
Nathan Yonkee 9:d58e77ebd769 824 // normal operation as oppose to compliance testing
Nathan Yonkee 9:d58e77ebd769 825 if (_callbacks.link_check_resp) {
Nathan Yonkee 9:d58e77ebd769 826 const int ret = _queue->call(_callbacks.link_check_resp,
Nathan Yonkee 9:d58e77ebd769 827 mlme_confirm->demod_margin,
Nathan Yonkee 9:d58e77ebd769 828 mlme_confirm->nb_gateways);
Nathan Yonkee 9:d58e77ebd769 829 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 830 (void)ret;
Nathan Yonkee 9:d58e77ebd769 831 }
Nathan Yonkee 9:d58e77ebd769 832 }
Nathan Yonkee 9:d58e77ebd769 833 }
Nathan Yonkee 9:d58e77ebd769 834 break;
Nathan Yonkee 9:d58e77ebd769 835 default:
Nathan Yonkee 9:d58e77ebd769 836 break;
Nathan Yonkee 9:d58e77ebd769 837 }
Nathan Yonkee 9:d58e77ebd769 838 }
Nathan Yonkee 9:d58e77ebd769 839
Nathan Yonkee 9:d58e77ebd769 840 lorawan_status_t LoRaWANStack::mcps_request_handler(loramac_mcps_req_t *mcps_request)
Nathan Yonkee 9:d58e77ebd769 841 {
Nathan Yonkee 9:d58e77ebd769 842 if (mcps_request == NULL) {
Nathan Yonkee 9:d58e77ebd769 843 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 844 }
Nathan Yonkee 9:d58e77ebd769 845
Nathan Yonkee 9:d58e77ebd769 846 return _loramac.mcps_request(mcps_request);
Nathan Yonkee 9:d58e77ebd769 847 }
Nathan Yonkee 9:d58e77ebd769 848
Nathan Yonkee 9:d58e77ebd769 849 /** MCPS-Confirm event function
Nathan Yonkee 9:d58e77ebd769 850 *
Nathan Yonkee 9:d58e77ebd769 851 * \param mcps_confirm Pointer to the confirm structure,
Nathan Yonkee 9:d58e77ebd769 852 * containing confirm attributes.
Nathan Yonkee 9:d58e77ebd769 853 */
Nathan Yonkee 9:d58e77ebd769 854 void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
Nathan Yonkee 9:d58e77ebd769 855 {
Nathan Yonkee 9:d58e77ebd769 856 if (mcps_confirm == NULL) {
Nathan Yonkee 9:d58e77ebd769 857 tr_error("mcps_confirm: struct [in] is null!");
Nathan Yonkee 9:d58e77ebd769 858 MBED_ASSERT(0);
Nathan Yonkee 9:d58e77ebd769 859 return;
Nathan Yonkee 9:d58e77ebd769 860 }
Nathan Yonkee 9:d58e77ebd769 861
Nathan Yonkee 9:d58e77ebd769 862 if (mcps_confirm->status != LORAMAC_EVENT_INFO_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 863 // Couldn't schedule packet, ack not recieved in CONFIRMED case
Nathan Yonkee 9:d58e77ebd769 864 // or some other error happened. Discard buffer, unset the tx-ongoing
Nathan Yonkee 9:d58e77ebd769 865 // flag and let the application know
Nathan Yonkee 9:d58e77ebd769 866 _tx_msg.tx_ongoing = false;
Nathan Yonkee 9:d58e77ebd769 867 memset(_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
Nathan Yonkee 9:d58e77ebd769 868 _tx_msg.f_buffer_size = MBED_CONF_LORA_TX_MAX_SIZE;
Nathan Yonkee 9:d58e77ebd769 869
Nathan Yonkee 9:d58e77ebd769 870 tr_error("mcps_confirm_handler: Error code = %d", mcps_confirm->status);
Nathan Yonkee 9:d58e77ebd769 871
Nathan Yonkee 9:d58e77ebd769 872 // If sending timed out, we have a special event for that
Nathan Yonkee 9:d58e77ebd769 873 if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT) {
Nathan Yonkee 9:d58e77ebd769 874 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 875 const int ret = _queue->call(_callbacks.events, TX_TIMEOUT);
Nathan Yonkee 9:d58e77ebd769 876 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 877 (void)ret;
Nathan Yonkee 9:d58e77ebd769 878 }
Nathan Yonkee 9:d58e77ebd769 879 return;
Nathan Yonkee 9:d58e77ebd769 880 } if (mcps_confirm->status == LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT) {
Nathan Yonkee 9:d58e77ebd769 881 tr_debug("Did not receive Ack");
Nathan Yonkee 9:d58e77ebd769 882 }
Nathan Yonkee 9:d58e77ebd769 883
Nathan Yonkee 9:d58e77ebd769 884 // Otherwise send a general TX_ERROR event
Nathan Yonkee 9:d58e77ebd769 885 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 886 const int ret = _queue->call(_callbacks.events, TX_ERROR);
Nathan Yonkee 9:d58e77ebd769 887 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 888 (void)ret;
Nathan Yonkee 9:d58e77ebd769 889 }
Nathan Yonkee 9:d58e77ebd769 890 return;
Nathan Yonkee 9:d58e77ebd769 891 }
Nathan Yonkee 9:d58e77ebd769 892
Nathan Yonkee 9:d58e77ebd769 893 // If No errors encountered, let's proceed with the status.
Nathan Yonkee 9:d58e77ebd769 894 // CONFIRMED needs special handling because of acks
Nathan Yonkee 9:d58e77ebd769 895 if (mcps_confirm->req_type == MCPS_CONFIRMED) {
Nathan Yonkee 9:d58e77ebd769 896 // In confirmed case, we need to check if we have received the Ack or not.
Nathan Yonkee 9:d58e77ebd769 897 // This is actually just being paranoid about ack because LoRaMac.cpp doesn't
Nathan Yonkee 9:d58e77ebd769 898 // call this callback until an ack is received.
Nathan Yonkee 9:d58e77ebd769 899 if (mcps_confirm->ack_received) {
Nathan Yonkee 9:d58e77ebd769 900 tr_debug("Ack received.");
Nathan Yonkee 9:d58e77ebd769 901 }
Nathan Yonkee 9:d58e77ebd769 902 }
Nathan Yonkee 9:d58e77ebd769 903
Nathan Yonkee 9:d58e77ebd769 904 // This part is common to both CONFIRMED and UNCONFIRMED.
Nathan Yonkee 9:d58e77ebd769 905 // Tell the application about successful transmission and store
Nathan Yonkee 9:d58e77ebd769 906 // data rate plus frame counter.
Nathan Yonkee 9:d58e77ebd769 907 _lw_session.uplink_counter = mcps_confirm->ul_frame_counter;
Nathan Yonkee 9:d58e77ebd769 908 _tx_msg.tx_ongoing = false;
Nathan Yonkee 9:d58e77ebd769 909 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 910 const int ret = _queue->call(_callbacks.events, TX_DONE);
Nathan Yonkee 9:d58e77ebd769 911 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 912 (void)ret;
Nathan Yonkee 9:d58e77ebd769 913 }
Nathan Yonkee 9:d58e77ebd769 914 }
Nathan Yonkee 9:d58e77ebd769 915
Nathan Yonkee 9:d58e77ebd769 916 /** MCPS-Indication event function
Nathan Yonkee 9:d58e77ebd769 917 *
Nathan Yonkee 9:d58e77ebd769 918 * \param mcps_indication Pointer to the indication structure,
Nathan Yonkee 9:d58e77ebd769 919 * containing indication attributes.
Nathan Yonkee 9:d58e77ebd769 920 */
Nathan Yonkee 9:d58e77ebd769 921 void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indication)
Nathan Yonkee 9:d58e77ebd769 922 {
Nathan Yonkee 9:d58e77ebd769 923 if (mcps_indication == NULL) {
Nathan Yonkee 9:d58e77ebd769 924 tr_error("mcps_indication: struct [in] is null.");
Nathan Yonkee 9:d58e77ebd769 925 return;
Nathan Yonkee 9:d58e77ebd769 926 }
Nathan Yonkee 9:d58e77ebd769 927
Nathan Yonkee 9:d58e77ebd769 928 if (mcps_indication->status != LORAMAC_EVENT_INFO_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 929 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 930 const int ret = _queue->call(_callbacks.events, RX_ERROR);
Nathan Yonkee 9:d58e77ebd769 931 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 932 (void)ret;
Nathan Yonkee 9:d58e77ebd769 933 }
Nathan Yonkee 9:d58e77ebd769 934 return;
Nathan Yonkee 9:d58e77ebd769 935 }
Nathan Yonkee 9:d58e77ebd769 936
Nathan Yonkee 9:d58e77ebd769 937 switch (mcps_indication->type) {
Nathan Yonkee 9:d58e77ebd769 938 case MCPS_UNCONFIRMED:
Nathan Yonkee 9:d58e77ebd769 939 break;
Nathan Yonkee 9:d58e77ebd769 940 case MCPS_CONFIRMED:
Nathan Yonkee 9:d58e77ebd769 941 break;
Nathan Yonkee 9:d58e77ebd769 942 case MCPS_PROPRIETARY:
Nathan Yonkee 9:d58e77ebd769 943 break;
Nathan Yonkee 9:d58e77ebd769 944 case MCPS_MULTICAST:
Nathan Yonkee 9:d58e77ebd769 945 break;
Nathan Yonkee 9:d58e77ebd769 946 default:
Nathan Yonkee 9:d58e77ebd769 947 break;
Nathan Yonkee 9:d58e77ebd769 948 }
Nathan Yonkee 9:d58e77ebd769 949
Nathan Yonkee 9:d58e77ebd769 950 // Check Multicast
Nathan Yonkee 9:d58e77ebd769 951 // Check Port
Nathan Yonkee 9:d58e77ebd769 952 // Check Datarate
Nathan Yonkee 9:d58e77ebd769 953 // Check FramePending
Nathan Yonkee 9:d58e77ebd769 954 // Check Buffer
Nathan Yonkee 9:d58e77ebd769 955 // Check BufferSize
Nathan Yonkee 9:d58e77ebd769 956 // Check Rssi
Nathan Yonkee 9:d58e77ebd769 957 // Check Snr
Nathan Yonkee 9:d58e77ebd769 958 // Check RxSlot
Nathan Yonkee 9:d58e77ebd769 959
Nathan Yonkee 9:d58e77ebd769 960 _lw_session.downlink_counter++;
Nathan Yonkee 9:d58e77ebd769 961
Nathan Yonkee 9:d58e77ebd769 962 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 963 if (_compliance_test.running == true) {
Nathan Yonkee 9:d58e77ebd769 964 _compliance_test.downlink_counter++;
Nathan Yonkee 9:d58e77ebd769 965 }
Nathan Yonkee 9:d58e77ebd769 966 #endif
Nathan Yonkee 9:d58e77ebd769 967
Nathan Yonkee 9:d58e77ebd769 968 if (mcps_indication->is_data_recvd == true) {
Nathan Yonkee 9:d58e77ebd769 969 switch (mcps_indication->port) {
Nathan Yonkee 9:d58e77ebd769 970 case 224:
Nathan Yonkee 9:d58e77ebd769 971 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 972 tr_debug("Compliance test command received.");
Nathan Yonkee 9:d58e77ebd769 973 compliance_test_handler(mcps_indication);
Nathan Yonkee 9:d58e77ebd769 974 #else
Nathan Yonkee 9:d58e77ebd769 975 tr_debug("Compliance test disabled.");
Nathan Yonkee 9:d58e77ebd769 976 #endif
Nathan Yonkee 9:d58e77ebd769 977 break;
Nathan Yonkee 9:d58e77ebd769 978 default:
Nathan Yonkee 9:d58e77ebd769 979 if (is_port_valid(mcps_indication->port) == true ||
Nathan Yonkee 9:d58e77ebd769 980 mcps_indication->type == MCPS_PROPRIETARY) {
Nathan Yonkee 9:d58e77ebd769 981
Nathan Yonkee 9:d58e77ebd769 982 // Valid message arrived.
Nathan Yonkee 9:d58e77ebd769 983 _rx_msg.type = LORAMAC_RX_MCPS_INDICATION;
Nathan Yonkee 9:d58e77ebd769 984 _rx_msg.msg.mcps_indication.buffer_size = mcps_indication->buffer_size;
Nathan Yonkee 9:d58e77ebd769 985 _rx_msg.msg.mcps_indication.port = mcps_indication->port;
Nathan Yonkee 9:d58e77ebd769 986
Nathan Yonkee 9:d58e77ebd769 987 // no copy, just set the pointer for the user
Nathan Yonkee 9:d58e77ebd769 988 _rx_msg.msg.mcps_indication.buffer =
Nathan Yonkee 9:d58e77ebd769 989 mcps_indication->buffer;
Nathan Yonkee 9:d58e77ebd769 990
Nathan Yonkee 9:d58e77ebd769 991 // Notify application about received frame..
Nathan Yonkee 9:d58e77ebd769 992 tr_debug("Received %d bytes", _rx_msg.msg.mcps_indication.buffer_size);
Nathan Yonkee 9:d58e77ebd769 993 _rx_msg.receive_ready = true;
Nathan Yonkee 9:d58e77ebd769 994
Nathan Yonkee 9:d58e77ebd769 995 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 996 const int ret = _queue->call(_callbacks.events, RX_DONE);
Nathan Yonkee 9:d58e77ebd769 997 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 998 (void)ret;
Nathan Yonkee 9:d58e77ebd769 999 }
Nathan Yonkee 9:d58e77ebd769 1000
Nathan Yonkee 9:d58e77ebd769 1001 // If fPending bit is set we try to generate an empty packet
Nathan Yonkee 9:d58e77ebd769 1002 // with CONFIRMED flag set. We always set a CONFIRMED flag so
Nathan Yonkee 9:d58e77ebd769 1003 // that we could retry a certain number of times if the uplink
Nathan Yonkee 9:d58e77ebd769 1004 // failed for some reason
Nathan Yonkee 9:d58e77ebd769 1005 if (mcps_indication->fpending_status) {
Nathan Yonkee 9:d58e77ebd769 1006 handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG);
Nathan Yonkee 9:d58e77ebd769 1007 }
Nathan Yonkee 9:d58e77ebd769 1008 } else {
Nathan Yonkee 9:d58e77ebd769 1009 // Invalid port, ports 0, 224 and 225-255 are reserved.
Nathan Yonkee 9:d58e77ebd769 1010 }
Nathan Yonkee 9:d58e77ebd769 1011 break;
Nathan Yonkee 9:d58e77ebd769 1012 }
Nathan Yonkee 9:d58e77ebd769 1013 }
Nathan Yonkee 9:d58e77ebd769 1014 }
Nathan Yonkee 9:d58e77ebd769 1015
Nathan Yonkee 9:d58e77ebd769 1016 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 1017 /** Compliance testing function
Nathan Yonkee 9:d58e77ebd769 1018 *
Nathan Yonkee 9:d58e77ebd769 1019 * \param mcps_indication Pointer to the indication structure,
Nathan Yonkee 9:d58e77ebd769 1020 * containing indication attributes.
Nathan Yonkee 9:d58e77ebd769 1021 */
Nathan Yonkee 9:d58e77ebd769 1022 void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indication)
Nathan Yonkee 9:d58e77ebd769 1023 {
Nathan Yonkee 9:d58e77ebd769 1024 if (_compliance_test.running == false) {
Nathan Yonkee 9:d58e77ebd769 1025 // Check compliance test enable command (i)
Nathan Yonkee 9:d58e77ebd769 1026 if ((mcps_indication->buffer_size == 4) &&
Nathan Yonkee 9:d58e77ebd769 1027 (mcps_indication->buffer[0] == 0x01) &&
Nathan Yonkee 9:d58e77ebd769 1028 (mcps_indication->buffer[1] == 0x01) &&
Nathan Yonkee 9:d58e77ebd769 1029 (mcps_indication->buffer[2] == 0x01) &&
Nathan Yonkee 9:d58e77ebd769 1030 (mcps_indication->buffer[3] == 0x01)) {
Nathan Yonkee 9:d58e77ebd769 1031 _compliance_test.is_tx_confirmed = false;
Nathan Yonkee 9:d58e77ebd769 1032 _compliance_test.app_port = 224;
Nathan Yonkee 9:d58e77ebd769 1033 _compliance_test.app_data_size = 2;
Nathan Yonkee 9:d58e77ebd769 1034 _compliance_test.downlink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 1035 _compliance_test.link_check = false;
Nathan Yonkee 9:d58e77ebd769 1036 _compliance_test.demod_margin = 0;
Nathan Yonkee 9:d58e77ebd769 1037 _compliance_test.nb_gateways = 0;
Nathan Yonkee 9:d58e77ebd769 1038 _compliance_test.running = true;
Nathan Yonkee 9:d58e77ebd769 1039 _compliance_test.state = 1;
Nathan Yonkee 9:d58e77ebd769 1040
Nathan Yonkee 9:d58e77ebd769 1041 loramac_mib_req_confirm_t mib_req;
Nathan Yonkee 9:d58e77ebd769 1042 mib_req.type = MIB_ADR;
Nathan Yonkee 9:d58e77ebd769 1043 mib_req.param.is_adr_enable = true;
Nathan Yonkee 9:d58e77ebd769 1044 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1045
Nathan Yonkee 9:d58e77ebd769 1046 #if MBED_CONF_LORA_PHY == 0
Nathan Yonkee 9:d58e77ebd769 1047 _loramac.LoRaMacTestSetDutyCycleOn(false);
Nathan Yonkee 9:d58e77ebd769 1048 #endif
Nathan Yonkee 9:d58e77ebd769 1049 //5000ms
Nathan Yonkee 9:d58e77ebd769 1050 _loramac.LoRaMacSetTxTimer(5000);
Nathan Yonkee 9:d58e77ebd769 1051 set_device_state(DEVICE_STATE_COMPLIANCE_TEST);
Nathan Yonkee 9:d58e77ebd769 1052 tr_debug("Compliance test activated.");
Nathan Yonkee 9:d58e77ebd769 1053 }
Nathan Yonkee 9:d58e77ebd769 1054 } else {
Nathan Yonkee 9:d58e77ebd769 1055 _compliance_test.state = mcps_indication->buffer[0];
Nathan Yonkee 9:d58e77ebd769 1056 switch (_compliance_test.state) {
Nathan Yonkee 9:d58e77ebd769 1057 case 0: // Check compliance test disable command (ii)
Nathan Yonkee 9:d58e77ebd769 1058 _compliance_test.is_tx_confirmed = true;
Nathan Yonkee 9:d58e77ebd769 1059 _compliance_test.app_port = MBED_CONF_LORA_APP_PORT;
Nathan Yonkee 9:d58e77ebd769 1060 _compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE;
Nathan Yonkee 9:d58e77ebd769 1061 _compliance_test.downlink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 1062 _compliance_test.running = false;
Nathan Yonkee 9:d58e77ebd769 1063
Nathan Yonkee 9:d58e77ebd769 1064 loramac_mib_req_confirm_t mib_req;
Nathan Yonkee 9:d58e77ebd769 1065 mib_req.type = MIB_ADR;
Nathan Yonkee 9:d58e77ebd769 1066 mib_req.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
Nathan Yonkee 9:d58e77ebd769 1067 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1068 #if MBED_CONF_LORA_PHY == 0
Nathan Yonkee 9:d58e77ebd769 1069 _loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
Nathan Yonkee 9:d58e77ebd769 1070 #endif
Nathan Yonkee 9:d58e77ebd769 1071 // Go to idle state after compliance test mode.
Nathan Yonkee 9:d58e77ebd769 1072 tr_debug("Compliance test disabled.");
Nathan Yonkee 9:d58e77ebd769 1073 _loramac.LoRaMacStopTxTimer();
Nathan Yonkee 9:d58e77ebd769 1074
Nathan Yonkee 9:d58e77ebd769 1075 // Clear any compliance test message stuff before going back to normal operation.
Nathan Yonkee 9:d58e77ebd769 1076 memset(&_tx_msg, 0, sizeof(_tx_msg));
Nathan Yonkee 9:d58e77ebd769 1077 set_device_state(DEVICE_STATE_IDLE);
Nathan Yonkee 9:d58e77ebd769 1078 lora_state_machine();
Nathan Yonkee 9:d58e77ebd769 1079 break;
Nathan Yonkee 9:d58e77ebd769 1080 case 1: // (iii, iv)
Nathan Yonkee 9:d58e77ebd769 1081 _compliance_test.app_data_size = 2;
Nathan Yonkee 9:d58e77ebd769 1082 break;
Nathan Yonkee 9:d58e77ebd769 1083 case 2: // Enable confirmed messages (v)
Nathan Yonkee 9:d58e77ebd769 1084 _compliance_test.is_tx_confirmed = true;
Nathan Yonkee 9:d58e77ebd769 1085 _compliance_test.state = 1;
Nathan Yonkee 9:d58e77ebd769 1086 break;
Nathan Yonkee 9:d58e77ebd769 1087 case 3: // Disable confirmed messages (vi)
Nathan Yonkee 9:d58e77ebd769 1088 _compliance_test.is_tx_confirmed = false;
Nathan Yonkee 9:d58e77ebd769 1089 _compliance_test.state = 1;
Nathan Yonkee 9:d58e77ebd769 1090 break;
Nathan Yonkee 9:d58e77ebd769 1091 case 4: // (vii)
Nathan Yonkee 9:d58e77ebd769 1092 _compliance_test.app_data_size = mcps_indication->buffer_size;
Nathan Yonkee 9:d58e77ebd769 1093
Nathan Yonkee 9:d58e77ebd769 1094 _compliance_test.app_data_buffer[0] = 4;
Nathan Yonkee 9:d58e77ebd769 1095 for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, LORAMAC_PHY_MAXPAYLOAD); ++i) {
Nathan Yonkee 9:d58e77ebd769 1096 _compliance_test.app_data_buffer[i] = mcps_indication->buffer[i] + 1;
Nathan Yonkee 9:d58e77ebd769 1097 }
Nathan Yonkee 9:d58e77ebd769 1098
Nathan Yonkee 9:d58e77ebd769 1099 send_compliance_test_frame_to_mac();
Nathan Yonkee 9:d58e77ebd769 1100 break;
Nathan Yonkee 9:d58e77ebd769 1101 case 5: // (viii)
Nathan Yonkee 9:d58e77ebd769 1102 loramac_mlme_req_t mlme_req;
Nathan Yonkee 9:d58e77ebd769 1103 mlme_req.type = MLME_LINK_CHECK;
Nathan Yonkee 9:d58e77ebd769 1104 mlme_request_handler(&mlme_req);
Nathan Yonkee 9:d58e77ebd769 1105 break;
Nathan Yonkee 9:d58e77ebd769 1106 case 6: // (ix)
Nathan Yonkee 9:d58e77ebd769 1107 loramac_mlme_req_t mlme_request;
Nathan Yonkee 9:d58e77ebd769 1108 loramac_mib_req_confirm_t mib_request;
Nathan Yonkee 9:d58e77ebd769 1109
Nathan Yonkee 9:d58e77ebd769 1110 // Disable TestMode and revert back to normal operation
Nathan Yonkee 9:d58e77ebd769 1111 _compliance_test.is_tx_confirmed = true;
Nathan Yonkee 9:d58e77ebd769 1112 _compliance_test.app_port = MBED_CONF_LORA_APP_PORT;
Nathan Yonkee 9:d58e77ebd769 1113 _compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE;
Nathan Yonkee 9:d58e77ebd769 1114 _compliance_test.downlink_counter = 0;
Nathan Yonkee 9:d58e77ebd769 1115 _compliance_test.running = false;
Nathan Yonkee 9:d58e77ebd769 1116
Nathan Yonkee 9:d58e77ebd769 1117 mib_request.type = MIB_ADR;
Nathan Yonkee 9:d58e77ebd769 1118 mib_request.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
Nathan Yonkee 9:d58e77ebd769 1119 mib_set_request(&mib_request);
Nathan Yonkee 9:d58e77ebd769 1120 #if MBED_CONF_LORA_PHY == 0
Nathan Yonkee 9:d58e77ebd769 1121 _loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
Nathan Yonkee 9:d58e77ebd769 1122 #endif
Nathan Yonkee 9:d58e77ebd769 1123 mlme_request.type = MLME_JOIN;
Nathan Yonkee 9:d58e77ebd769 1124 mlme_request.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
Nathan Yonkee 9:d58e77ebd769 1125 mlme_request.req.join.app_eui = _lw_session.connection.connection_u.otaa.app_eui;
Nathan Yonkee 9:d58e77ebd769 1126 mlme_request.req.join.app_key = _lw_session.connection.connection_u.otaa.app_key;
Nathan Yonkee 9:d58e77ebd769 1127 mlme_request.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
Nathan Yonkee 9:d58e77ebd769 1128 mlme_request_handler(&mlme_request);
Nathan Yonkee 9:d58e77ebd769 1129 break;
Nathan Yonkee 9:d58e77ebd769 1130 case 7: // (x)
Nathan Yonkee 9:d58e77ebd769 1131 if (mcps_indication->buffer_size == 3) {
Nathan Yonkee 9:d58e77ebd769 1132 loramac_mlme_req_t mlme_req;
Nathan Yonkee 9:d58e77ebd769 1133 mlme_req.type = MLME_TXCW;
Nathan Yonkee 9:d58e77ebd769 1134 mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
Nathan Yonkee 9:d58e77ebd769 1135 mlme_request_handler(&mlme_req);
Nathan Yonkee 9:d58e77ebd769 1136 } else if (mcps_indication->buffer_size == 7) {
Nathan Yonkee 9:d58e77ebd769 1137 loramac_mlme_req_t mlme_req;
Nathan Yonkee 9:d58e77ebd769 1138 mlme_req.type = MLME_TXCW_1;
Nathan Yonkee 9:d58e77ebd769 1139 mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
Nathan Yonkee 9:d58e77ebd769 1140 mlme_req.req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8)
Nathan Yonkee 9:d58e77ebd769 1141 | mcps_indication->buffer[5]) * 100;
Nathan Yonkee 9:d58e77ebd769 1142 mlme_req.req.cw_tx_mode.power = mcps_indication->buffer[6];
Nathan Yonkee 9:d58e77ebd769 1143 mlme_request_handler(&mlme_req);
Nathan Yonkee 9:d58e77ebd769 1144 }
Nathan Yonkee 9:d58e77ebd769 1145 _compliance_test.state = 1;
Nathan Yonkee 9:d58e77ebd769 1146 break;
Nathan Yonkee 9:d58e77ebd769 1147 }
Nathan Yonkee 9:d58e77ebd769 1148 }
Nathan Yonkee 9:d58e77ebd769 1149 }
Nathan Yonkee 9:d58e77ebd769 1150 #endif
Nathan Yonkee 9:d58e77ebd769 1151
Nathan Yonkee 9:d58e77ebd769 1152 lorawan_status_t LoRaWANStack::mib_set_request(loramac_mib_req_confirm_t *mib_set_params)
Nathan Yonkee 9:d58e77ebd769 1153 {
Nathan Yonkee 9:d58e77ebd769 1154 if (NULL == mib_set_params) {
Nathan Yonkee 9:d58e77ebd769 1155 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 1156 }
Nathan Yonkee 9:d58e77ebd769 1157 return _loramac.mib_set_request_confirm(mib_set_params);
Nathan Yonkee 9:d58e77ebd769 1158 }
Nathan Yonkee 9:d58e77ebd769 1159
Nathan Yonkee 9:d58e77ebd769 1160 lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_get_params)
Nathan Yonkee 9:d58e77ebd769 1161 {
Nathan Yonkee 9:d58e77ebd769 1162 if(NULL == mib_get_params) {
Nathan Yonkee 9:d58e77ebd769 1163 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 1164 }
Nathan Yonkee 9:d58e77ebd769 1165 return _loramac.mib_get_request_confirm(mib_get_params);
Nathan Yonkee 9:d58e77ebd769 1166 }
Nathan Yonkee 9:d58e77ebd769 1167
Nathan Yonkee 9:d58e77ebd769 1168 lorawan_status_t LoRaWANStack::set_link_check_request()
Nathan Yonkee 9:d58e77ebd769 1169 {
Nathan Yonkee 9:d58e77ebd769 1170 if (!_callbacks.link_check_resp) {
Nathan Yonkee 9:d58e77ebd769 1171 tr_error("Must assign a callback function for link check request. ");
Nathan Yonkee 9:d58e77ebd769 1172 return LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 1173 }
Nathan Yonkee 9:d58e77ebd769 1174
Nathan Yonkee 9:d58e77ebd769 1175 loramac_mlme_req_t mlme_req;
Nathan Yonkee 9:d58e77ebd769 1176
Nathan Yonkee 9:d58e77ebd769 1177 mlme_req.type = MLME_LINK_CHECK;
Nathan Yonkee 9:d58e77ebd769 1178 return mlme_request_handler(&mlme_req);
Nathan Yonkee 9:d58e77ebd769 1179 }
Nathan Yonkee 9:d58e77ebd769 1180
Nathan Yonkee 9:d58e77ebd769 1181 lorawan_status_t LoRaWANStack::shutdown()
Nathan Yonkee 9:d58e77ebd769 1182 {
Nathan Yonkee 9:d58e77ebd769 1183 set_device_state(DEVICE_STATE_SHUTDOWN);
Nathan Yonkee 9:d58e77ebd769 1184 return lora_state_machine();
Nathan Yonkee 9:d58e77ebd769 1185 }
Nathan Yonkee 9:d58e77ebd769 1186
Nathan Yonkee 9:d58e77ebd769 1187 lorawan_status_t LoRaWANStack::lora_state_machine()
Nathan Yonkee 9:d58e77ebd769 1188 {
Nathan Yonkee 9:d58e77ebd769 1189 loramac_mib_req_confirm_t mib_req;
Nathan Yonkee 9:d58e77ebd769 1190 lorawan_status_t status = LORAWAN_STATUS_DEVICE_OFF;
Nathan Yonkee 9:d58e77ebd769 1191
Nathan Yonkee 9:d58e77ebd769 1192 switch (_device_current_state) {
Nathan Yonkee 9:d58e77ebd769 1193 case DEVICE_STATE_SHUTDOWN:
Nathan Yonkee 9:d58e77ebd769 1194 /*
Nathan Yonkee 9:d58e77ebd769 1195 * Remove channels
Nathan Yonkee 9:d58e77ebd769 1196 * Radio will be put to sleep by the APIs underneath
Nathan Yonkee 9:d58e77ebd769 1197 */
Nathan Yonkee 9:d58e77ebd769 1198 drop_channel_list();
Nathan Yonkee 9:d58e77ebd769 1199
Nathan Yonkee 9:d58e77ebd769 1200 // Shutdown LoRaMac
Nathan Yonkee 9:d58e77ebd769 1201 _loramac.disconnect();
Nathan Yonkee 9:d58e77ebd769 1202
Nathan Yonkee 9:d58e77ebd769 1203 // Stop sending messages and set joined status to false.
Nathan Yonkee 9:d58e77ebd769 1204 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 1205 _loramac.LoRaMacStopTxTimer();
Nathan Yonkee 9:d58e77ebd769 1206 #endif
Nathan Yonkee 9:d58e77ebd769 1207 mib_req.type = MIB_NETWORK_JOINED;
Nathan Yonkee 9:d58e77ebd769 1208 mib_req.param.is_nwk_joined = false;
Nathan Yonkee 9:d58e77ebd769 1209 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1210
Nathan Yonkee 9:d58e77ebd769 1211 // reset buffers to original state
Nathan Yonkee 9:d58e77ebd769 1212 memset(_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
Nathan Yonkee 9:d58e77ebd769 1213 _tx_msg.pending_size = 0;
Nathan Yonkee 9:d58e77ebd769 1214 _tx_msg.f_buffer_size = 0;
Nathan Yonkee 9:d58e77ebd769 1215 _tx_msg.tx_ongoing = false;
Nathan Yonkee 9:d58e77ebd769 1216 _rx_msg.msg.mcps_indication.buffer = NULL;
Nathan Yonkee 9:d58e77ebd769 1217 _rx_msg.receive_ready = false;
Nathan Yonkee 9:d58e77ebd769 1218 _rx_msg.prev_read_size = 0;
Nathan Yonkee 9:d58e77ebd769 1219 _rx_msg.msg.mcps_indication.buffer_size = 0;
Nathan Yonkee 9:d58e77ebd769 1220
Nathan Yonkee 9:d58e77ebd769 1221 // disable the session
Nathan Yonkee 9:d58e77ebd769 1222 _lw_session.active = false;
Nathan Yonkee 9:d58e77ebd769 1223
Nathan Yonkee 9:d58e77ebd769 1224 tr_debug("LoRaWAN protocol has been shut down.");
Nathan Yonkee 9:d58e77ebd769 1225 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 1226 const int ret = _queue->call(_callbacks.events, DISCONNECTED);
Nathan Yonkee 9:d58e77ebd769 1227 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 1228 (void)ret;
Nathan Yonkee 9:d58e77ebd769 1229 }
Nathan Yonkee 9:d58e77ebd769 1230 status = LORAWAN_STATUS_DEVICE_OFF;
Nathan Yonkee 9:d58e77ebd769 1231 break;
Nathan Yonkee 9:d58e77ebd769 1232 case DEVICE_STATE_NOT_INITIALIZED:
Nathan Yonkee 9:d58e77ebd769 1233 // Device is disconnected.
Nathan Yonkee 9:d58e77ebd769 1234 status = LORAWAN_STATUS_DEVICE_OFF;
Nathan Yonkee 9:d58e77ebd769 1235 break;
Nathan Yonkee 9:d58e77ebd769 1236 case DEVICE_STATE_INIT:
Nathan Yonkee 9:d58e77ebd769 1237 status = LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 1238 break;
Nathan Yonkee 9:d58e77ebd769 1239 case DEVICE_STATE_JOINING:
Nathan Yonkee 9:d58e77ebd769 1240 if (_lw_session.connection.connect_type == LORAWAN_CONNECTION_OTAA) {
Nathan Yonkee 9:d58e77ebd769 1241 /*
Nathan Yonkee 9:d58e77ebd769 1242 * OTAA join
Nathan Yonkee 9:d58e77ebd769 1243 */
Nathan Yonkee 9:d58e77ebd769 1244 tr_debug("Send Join-request..");
Nathan Yonkee 9:d58e77ebd769 1245 loramac_mlme_req_t mlme_req;
Nathan Yonkee 9:d58e77ebd769 1246 mlme_req.type = MLME_JOIN;
Nathan Yonkee 9:d58e77ebd769 1247
Nathan Yonkee 9:d58e77ebd769 1248 mlme_req.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
Nathan Yonkee 9:d58e77ebd769 1249 mlme_req.req.join.app_eui = _lw_session.connection.connection_u.otaa.app_eui;
Nathan Yonkee 9:d58e77ebd769 1250 mlme_req.req.join.app_key = _lw_session.connection.connection_u.otaa.app_key;
Nathan Yonkee 9:d58e77ebd769 1251 mlme_req.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
Nathan Yonkee 9:d58e77ebd769 1252
Nathan Yonkee 9:d58e77ebd769 1253 // Send join request to server.
Nathan Yonkee 9:d58e77ebd769 1254 status = mlme_request_handler(&mlme_req);
Nathan Yonkee 9:d58e77ebd769 1255 if (status != LORAWAN_STATUS_OK) {
Nathan Yonkee 9:d58e77ebd769 1256 return status;
Nathan Yonkee 9:d58e77ebd769 1257 }
Nathan Yonkee 9:d58e77ebd769 1258 // Otherwise request was successful and OTAA connect is in
Nathan Yonkee 9:d58e77ebd769 1259 //progress
Nathan Yonkee 9:d58e77ebd769 1260 return LORAWAN_STATUS_CONNECT_IN_PROGRESS;
Nathan Yonkee 9:d58e77ebd769 1261 } else {
Nathan Yonkee 9:d58e77ebd769 1262 status = LORAWAN_STATUS_PARAMETER_INVALID;
Nathan Yonkee 9:d58e77ebd769 1263 }
Nathan Yonkee 9:d58e77ebd769 1264 break;
Nathan Yonkee 9:d58e77ebd769 1265 case DEVICE_STATE_JOINED:
Nathan Yonkee 9:d58e77ebd769 1266 tr_debug("Join OK!");
Nathan Yonkee 9:d58e77ebd769 1267 // Session is now active
Nathan Yonkee 9:d58e77ebd769 1268 _lw_session.active = true;
Nathan Yonkee 9:d58e77ebd769 1269 // Tell the application that we are connected
Nathan Yonkee 9:d58e77ebd769 1270 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 1271 const int ret = _queue->call(_callbacks.events, CONNECTED);
Nathan Yonkee 9:d58e77ebd769 1272 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 1273 (void)ret;
Nathan Yonkee 9:d58e77ebd769 1274 }
Nathan Yonkee 9:d58e77ebd769 1275 status = LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 1276 break;
Nathan Yonkee 9:d58e77ebd769 1277 case DEVICE_STATE_ABP_CONNECTING:
Nathan Yonkee 9:d58e77ebd769 1278 /*
Nathan Yonkee 9:d58e77ebd769 1279 * ABP connection
Nathan Yonkee 9:d58e77ebd769 1280 */
Nathan Yonkee 9:d58e77ebd769 1281 mib_req.type = MIB_NET_ID;
Nathan Yonkee 9:d58e77ebd769 1282 mib_req.param.net_id = _lw_session.connection.connection_u.abp.nwk_id;
Nathan Yonkee 9:d58e77ebd769 1283 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1284
Nathan Yonkee 9:d58e77ebd769 1285 mib_req.type = MIB_DEV_ADDR;
Nathan Yonkee 9:d58e77ebd769 1286 mib_req.param.dev_addr = _lw_session.connection.connection_u.abp.dev_addr;
Nathan Yonkee 9:d58e77ebd769 1287 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1288
Nathan Yonkee 9:d58e77ebd769 1289 mib_req.type = MIB_NWK_SKEY;
Nathan Yonkee 9:d58e77ebd769 1290 mib_req.param.nwk_skey = _lw_session.connection.connection_u.abp.nwk_skey;
Nathan Yonkee 9:d58e77ebd769 1291 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1292
Nathan Yonkee 9:d58e77ebd769 1293 mib_req.type = MIB_APP_SKEY;
Nathan Yonkee 9:d58e77ebd769 1294 mib_req.param.app_skey = _lw_session.connection.connection_u.abp.app_skey;
Nathan Yonkee 9:d58e77ebd769 1295 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1296
Nathan Yonkee 9:d58e77ebd769 1297 mib_req.type = MIB_NETWORK_JOINED;
Nathan Yonkee 9:d58e77ebd769 1298 mib_req.param.is_nwk_joined = true;
Nathan Yonkee 9:d58e77ebd769 1299 mib_set_request(&mib_req);
Nathan Yonkee 9:d58e77ebd769 1300 tr_debug("ABP Connection OK!");
Nathan Yonkee 9:d58e77ebd769 1301 // tell the application we are okay
Nathan Yonkee 9:d58e77ebd769 1302 // if users provide wrong keys, it's their responsibility
Nathan Yonkee 9:d58e77ebd769 1303 // there is no way to test ABP authentication success
Nathan Yonkee 9:d58e77ebd769 1304 status = LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 1305 // Session is now active
Nathan Yonkee 9:d58e77ebd769 1306 _lw_session.active = true;
Nathan Yonkee 9:d58e77ebd769 1307 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 1308 const int ret = _queue->call(_callbacks.events, CONNECTED);
Nathan Yonkee 9:d58e77ebd769 1309 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 1310 (void)ret;
Nathan Yonkee 9:d58e77ebd769 1311 }
Nathan Yonkee 9:d58e77ebd769 1312 break;
Nathan Yonkee 9:d58e77ebd769 1313 case DEVICE_STATE_SEND:
Nathan Yonkee 9:d58e77ebd769 1314 // If a transmission is ongoing, don't interrupt
Nathan Yonkee 9:d58e77ebd769 1315 if (_tx_msg.tx_ongoing) {
Nathan Yonkee 9:d58e77ebd769 1316 status = LORAWAN_STATUS_OK;
Nathan Yonkee 9:d58e77ebd769 1317 } else {
Nathan Yonkee 9:d58e77ebd769 1318 _tx_msg.tx_ongoing = true;
Nathan Yonkee 9:d58e77ebd769 1319 status = send_frame_to_mac();
Nathan Yonkee 9:d58e77ebd769 1320
Nathan Yonkee 9:d58e77ebd769 1321 switch (status) {
Nathan Yonkee 9:d58e77ebd769 1322 case LORAWAN_STATUS_OK:
Nathan Yonkee 9:d58e77ebd769 1323 tr_debug("Frame scheduled to TX..");
Nathan Yonkee 9:d58e77ebd769 1324 break;
Nathan Yonkee 9:d58e77ebd769 1325 case LORAWAN_STATUS_CRYPTO_FAIL:
Nathan Yonkee 9:d58e77ebd769 1326 tr_error("Crypto failed. Clearing TX buffers");
Nathan Yonkee 9:d58e77ebd769 1327 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 1328 const int ret = _queue->call(_callbacks.events, TX_CRYPTO_ERROR);
Nathan Yonkee 9:d58e77ebd769 1329 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 1330 (void)ret;
Nathan Yonkee 9:d58e77ebd769 1331 }
Nathan Yonkee 9:d58e77ebd769 1332 break;
Nathan Yonkee 9:d58e77ebd769 1333 default:
Nathan Yonkee 9:d58e77ebd769 1334 tr_error("Failure to schedule TX!");
Nathan Yonkee 9:d58e77ebd769 1335 if (_callbacks.events) {
Nathan Yonkee 9:d58e77ebd769 1336 const int ret = _queue->call(_callbacks.events, TX_SCHEDULING_ERROR);
Nathan Yonkee 9:d58e77ebd769 1337 MBED_ASSERT(ret != 0);
Nathan Yonkee 9:d58e77ebd769 1338 (void)ret;
Nathan Yonkee 9:d58e77ebd769 1339 }
Nathan Yonkee 9:d58e77ebd769 1340 break;
Nathan Yonkee 9:d58e77ebd769 1341 }
Nathan Yonkee 9:d58e77ebd769 1342 }
Nathan Yonkee 9:d58e77ebd769 1343 // otherwise all done, put device in idle state
Nathan Yonkee 9:d58e77ebd769 1344 set_device_state(DEVICE_STATE_IDLE);
Nathan Yonkee 9:d58e77ebd769 1345 break;
Nathan Yonkee 9:d58e77ebd769 1346 case DEVICE_STATE_IDLE:
Nathan Yonkee 9:d58e77ebd769 1347 //Do nothing
Nathan Yonkee 9:d58e77ebd769 1348 status = LORAWAN_STATUS_IDLE;
Nathan Yonkee 9:d58e77ebd769 1349 break;
Nathan Yonkee 9:d58e77ebd769 1350 #if defined(LORAWAN_COMPLIANCE_TEST)
Nathan Yonkee 9:d58e77ebd769 1351 case DEVICE_STATE_COMPLIANCE_TEST:
Nathan Yonkee 9:d58e77ebd769 1352 //Device is in compliance test mode
Nathan Yonkee 9:d58e77ebd769 1353 tr_debug("Device is in compliance test mode.");
Nathan Yonkee 9:d58e77ebd769 1354
Nathan Yonkee 9:d58e77ebd769 1355 //5000ms
Nathan Yonkee 9:d58e77ebd769 1356 _loramac.LoRaMacSetTxTimer(5000);
Nathan Yonkee 9:d58e77ebd769 1357 if (_compliance_test.running == true) {
Nathan Yonkee 9:d58e77ebd769 1358 send_compliance_test_frame_to_mac();
Nathan Yonkee 9:d58e77ebd769 1359 }
Nathan Yonkee 9:d58e77ebd769 1360 status = LORAWAN_STATUS_COMPLIANCE_TEST_ON;
Nathan Yonkee 9:d58e77ebd769 1361 break;
Nathan Yonkee 9:d58e77ebd769 1362 #endif
Nathan Yonkee 9:d58e77ebd769 1363 default:
Nathan Yonkee 9:d58e77ebd769 1364 status = LORAWAN_STATUS_SERVICE_UNKNOWN;
Nathan Yonkee 9:d58e77ebd769 1365 break;
Nathan Yonkee 9:d58e77ebd769 1366 }
Nathan Yonkee 9:d58e77ebd769 1367
Nathan Yonkee 9:d58e77ebd769 1368 return status;
Nathan Yonkee 9:d58e77ebd769 1369 }