mirror of https://github.com/ARMmbed/mbed-os.git
LoRa: LoRaPHY dependency removed from LoRaMacStack
- This is internal change, no functionality has been changed - LoRaWanInterface cleaned up and code moved to LoRaMacStack - Compliance code in LoRaMacStack moved to EOF - Green tea tests have been run manually - Doxygen updated accordingly LoRA: reorder class memberspull/6411/head
parent
fe225a8430
commit
b63c98e103
|
|
@ -98,7 +98,6 @@ LoRaWANStack::LoRaWANStack()
|
|||
#endif
|
||||
|
||||
memset(&_lw_session, 0, sizeof(_lw_session));
|
||||
memset(&_tx_msg, 0, sizeof(_tx_msg));
|
||||
memset(&_rx_msg, 0, sizeof(_rx_msg));
|
||||
|
||||
LoRaMacPrimitives.mcps_confirm = callback(this, &LoRaWANStack::mcps_confirm_handler);
|
||||
|
|
@ -122,12 +121,7 @@ LoRaWANStack& LoRaWANStack::get_lorawan_stack()
|
|||
|
||||
void LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
|
||||
{
|
||||
//Move these to LoRaMAC class
|
||||
radio_events_t *events = _loramac.get_phy_event_handlers();
|
||||
_lora_phy.set_radio_instance(radio);
|
||||
radio.lock();
|
||||
radio.init_radio(events);
|
||||
radio.unlock();
|
||||
_loramac.bind_radio_driver(radio);
|
||||
}
|
||||
|
||||
lorawan_status_t LoRaWANStack::connect()
|
||||
|
|
@ -209,7 +203,7 @@ lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
|
|||
_compliance_test.app_data_buffer = compliance_test_buffer;
|
||||
#endif
|
||||
|
||||
_loramac.initialize(&LoRaMacPrimitives, &_lora_phy, queue);
|
||||
_loramac.initialize(&LoRaMacPrimitives, queue);
|
||||
|
||||
// Reset counters to zero. Will change in future with 1.1 support.
|
||||
_lw_session.downlink_counter = 0;
|
||||
|
|
@ -218,81 +212,6 @@ lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
|
|||
return lora_state_machine(DEVICE_STATE_INIT);
|
||||
}
|
||||
|
||||
uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size)
|
||||
{
|
||||
loramac_tx_info_t tx_info;
|
||||
if (_loramac.query_tx_possible(size, &tx_info) == LORAWAN_STATUS_LENGTH_ERROR) {
|
||||
// Cannot transmit this much. Return how much data can be sent
|
||||
// at the moment
|
||||
return tx_info.max_possible_payload_size;
|
||||
}
|
||||
|
||||
return tx_info.current_payload_size;
|
||||
}
|
||||
|
||||
/** Hands over the frame to MAC layer
|
||||
*
|
||||
* \return returns the state of the LoRa MAC
|
||||
*/
|
||||
lorawan_status_t LoRaWANStack::send_frame_to_mac()
|
||||
{
|
||||
loramac_mcps_req_t mcps_req;
|
||||
lorawan_status_t status;
|
||||
loramac_mib_req_confirm_t mib_get_params;
|
||||
|
||||
mcps_req.type = _tx_msg.type;
|
||||
|
||||
if (MCPS_UNCONFIRMED == mcps_req.type) {
|
||||
mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
|
||||
mcps_req.fport = _tx_msg.fport;
|
||||
mcps_req.nb_trials = 1;
|
||||
mib_get_params.type = MIB_CHANNELS_DATARATE;
|
||||
if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) {
|
||||
tr_debug("Couldn't get MIB parameters: Using default data rate");
|
||||
mcps_req.data_rate = _lora_phy.get_default_tx_datarate();
|
||||
} else {
|
||||
mcps_req.data_rate = mib_get_params.param.channel_data_rate;
|
||||
}
|
||||
|
||||
} else if (mcps_req.type == MCPS_CONFIRMED) {
|
||||
mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
mcps_req.fport = _tx_msg.fport;
|
||||
mcps_req.nb_trials = _tx_msg.nb_trials;
|
||||
|
||||
mib_get_params.type = MIB_CHANNELS_DATARATE;
|
||||
if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) {
|
||||
tr_debug("Couldn't get MIB parameters: Using default data rate");
|
||||
mcps_req.data_rate = _lora_phy.get_default_tx_datarate();
|
||||
} else {
|
||||
mcps_req.data_rate = mib_get_params.param.channel_data_rate;
|
||||
}
|
||||
|
||||
} else if ( mcps_req.type == MCPS_PROPRIETARY) {
|
||||
mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
mcps_req.fport = 0;
|
||||
mcps_req.nb_trials = 1;
|
||||
|
||||
mib_get_params.type = MIB_CHANNELS_DATARATE;
|
||||
if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) {
|
||||
tr_debug("Couldn't get MIB parameters: Using default data rate");
|
||||
mcps_req.data_rate = _lora_phy.get_default_tx_datarate();
|
||||
} else {
|
||||
mcps_req.data_rate = mib_get_params.param.channel_data_rate;
|
||||
}
|
||||
|
||||
} else {
|
||||
return LORAWAN_STATUS_SERVICE_UNKNOWN;
|
||||
}
|
||||
|
||||
status = mcps_request_handler(&mcps_req);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
lorawan_status_t LoRaWANStack::set_confirmed_msg_retry(uint8_t count)
|
||||
{
|
||||
if (count >= MAX_CONFIRMED_MSG_RETRIES) {
|
||||
|
|
@ -396,6 +315,8 @@ lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled)
|
|||
return LORAWAN_STATUS_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
//return _loramac.enable_adaptive_datarate(adr_enabled);
|
||||
|
||||
loramac_mib_req_confirm_t adr_mib_params;
|
||||
|
||||
adr_mib_params.type = MIB_ADR;
|
||||
|
|
@ -489,11 +410,14 @@ lorawan_status_t LoRaWANStack::activation_by_personalization(const lorawan_conne
|
|||
}
|
||||
|
||||
int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
|
||||
uint16_t length, uint8_t flags)
|
||||
uint16_t length, uint8_t flags, bool null_allowed)
|
||||
{
|
||||
if (!null_allowed && !data) {
|
||||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
// add a link check request with normal data, until the application
|
||||
// explicitly removes it.
|
||||
if (_link_check_requested) {
|
||||
// add a link check request with normal data, until the application
|
||||
// explicitly removes it.
|
||||
set_link_check_request();
|
||||
}
|
||||
|
||||
|
|
@ -501,20 +425,17 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
|
|||
return LORAWAN_STATUS_NO_ACTIVE_SESSIONS;
|
||||
}
|
||||
|
||||
if (_tx_msg.tx_ongoing) {
|
||||
if(_loramac.tx_ongoing()) {
|
||||
return LORAWAN_STATUS_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
if (!data && length > 0) {
|
||||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
if (_compliance_test.running) {
|
||||
return LORAWAN_STATUS_COMPLIANCE_TEST_ON;
|
||||
}
|
||||
#endif
|
||||
|
||||
//TODO: Stack MUST know joining status!!!!
|
||||
loramac_mib_req_confirm_t mib_req;
|
||||
lorawan_status_t status;
|
||||
mib_req.type = MIB_NETWORK_JOINED;
|
||||
|
|
@ -539,62 +460,14 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data,
|
|||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
_tx_msg.port = port;
|
||||
int16_t len = _loramac.prepare_ongoing_tx(port, data, length, flags, _num_retry);
|
||||
|
||||
uint16_t max_possible_size = check_possible_tx_size(length);
|
||||
|
||||
if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
|
||||
// LORAWAN_APP_DATA_MAX_SIZE should at least be
|
||||
// either equal to or bigger than maximum possible
|
||||
// tx size because our tx message buffer takes its
|
||||
// length from that macro. Force maximum possible tx unit
|
||||
// to be equal to the buffer size user chose.
|
||||
max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
|
||||
}
|
||||
|
||||
if (max_possible_size < length) {
|
||||
tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
|
||||
length, max_possible_size);
|
||||
|
||||
_tx_msg.pending_size = length - max_possible_size;
|
||||
_tx_msg.f_buffer_size = max_possible_size;
|
||||
// copy user buffer upto the max_possible_size
|
||||
memcpy(_tx_msg.f_buffer, data, _tx_msg.f_buffer_size);
|
||||
} else {
|
||||
// Whole message can be sent at one time
|
||||
_tx_msg.f_buffer_size = length;
|
||||
_tx_msg.pending_size = 0;
|
||||
// copy user buffer upto the max_possible_size
|
||||
if (length > 0) {
|
||||
memcpy(_tx_msg.f_buffer, data, length);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles all unconfirmed messages, including proprietary and multicast
|
||||
if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) {
|
||||
|
||||
_tx_msg.type = MCPS_UNCONFIRMED;
|
||||
_tx_msg.fport = _app_port;
|
||||
}
|
||||
|
||||
// Handles all confirmed messages, including proprietary and multicast
|
||||
if ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) {
|
||||
|
||||
_tx_msg.type = MCPS_CONFIRMED;
|
||||
_tx_msg.fport = _app_port;
|
||||
_tx_msg.nb_trials = _num_retry;
|
||||
}
|
||||
|
||||
tr_info("RTS = %u bytes, PEND = %u", _tx_msg.f_buffer_size, _tx_msg.pending_size);
|
||||
status = lora_state_machine(DEVICE_STATE_SEND);
|
||||
|
||||
// send user the length of data which is scheduled now.
|
||||
// user should take care of the pending data.
|
||||
return (status == LORAWAN_STATUS_OK) ? _tx_msg.f_buffer_size : (int16_t) status;
|
||||
return (status == LORAWAN_STATUS_OK) ? len : (int16_t) status;
|
||||
}
|
||||
|
||||
int16_t LoRaWANStack::handle_rx(const uint8_t port, uint8_t* data,
|
||||
|
|
@ -766,9 +639,7 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
|
|||
// Couldn't schedule packet, ack not recieved in CONFIRMED case
|
||||
// or some other error happened. Discard buffer, unset the tx-ongoing
|
||||
// flag and let the application know
|
||||
_tx_msg.tx_ongoing = false;
|
||||
memset(_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
|
||||
_tx_msg.f_buffer_size = MBED_CONF_LORA_TX_MAX_SIZE;
|
||||
_loramac.reset_ongoing_tx();
|
||||
|
||||
tr_error("mcps_confirm_handler: Error code = %d", mcps_confirm->status);
|
||||
|
||||
|
|
@ -808,7 +679,7 @@ void LoRaWANStack::mcps_confirm_handler(loramac_mcps_confirm_t *mcps_confirm)
|
|||
// Tell the application about successful transmission and store
|
||||
// data rate plus frame counter.
|
||||
_lw_session.uplink_counter = mcps_confirm->ul_frame_counter;
|
||||
_tx_msg.tx_ongoing = false;
|
||||
_loramac.set_tx_ongoing(false);
|
||||
if (_callbacks.events) {
|
||||
const int ret = _queue->call(_callbacks.events, TX_DONE);
|
||||
MBED_ASSERT(ret != 0);
|
||||
|
|
@ -909,7 +780,7 @@ void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indic
|
|||
// that we could retry a certain number of times if the uplink
|
||||
// failed for some reason
|
||||
if (mcps_indication->fpending_status && mib_req.param.dev_class != CLASS_C) {
|
||||
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG);
|
||||
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG, true);
|
||||
}
|
||||
|
||||
// Class C and node received a confirmed message so we need to
|
||||
|
|
@ -918,7 +789,7 @@ void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indic
|
|||
// but version 1.1.0 says that network SHALL not send any new
|
||||
// confirmed messages until ack has been sent
|
||||
if (mib_req.param.dev_class == CLASS_C && mcps_indication->type == MCPS_CONFIRMED) {
|
||||
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG);
|
||||
handle_tx(mcps_indication->port, NULL, 0, MSG_CONFIRMED_FLAG, true);
|
||||
}
|
||||
} else {
|
||||
// Invalid port, ports 0, 224 and 225-255 are reserved.
|
||||
|
|
@ -928,144 +799,6 @@ void LoRaWANStack::mcps_indication_handler(loramac_mcps_indication_t *mcps_indic
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
/** Compliance testing function
|
||||
*
|
||||
* \param mcps_indication Pointer to the indication structure,
|
||||
* containing indication attributes.
|
||||
*/
|
||||
void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indication)
|
||||
{
|
||||
if (_compliance_test.running == false) {
|
||||
// Check compliance test enable command (i)
|
||||
if ((mcps_indication->buffer_size == 4) &&
|
||||
(mcps_indication->buffer[0] == 0x01) &&
|
||||
(mcps_indication->buffer[1] == 0x01) &&
|
||||
(mcps_indication->buffer[2] == 0x01) &&
|
||||
(mcps_indication->buffer[3] == 0x01)) {
|
||||
_compliance_test.is_tx_confirmed = false;
|
||||
_compliance_test.app_port = 224;
|
||||
_compliance_test.app_data_size = 2;
|
||||
_compliance_test.downlink_counter = 0;
|
||||
_compliance_test.link_check = false;
|
||||
_compliance_test.demod_margin = 0;
|
||||
_compliance_test.nb_gateways = 0;
|
||||
_compliance_test.running = true;
|
||||
_compliance_test.state = 1;
|
||||
|
||||
loramac_mib_req_confirm_t mib_req;
|
||||
mib_req.type = MIB_ADR;
|
||||
mib_req.param.is_adr_enable = true;
|
||||
mib_set_request(&mib_req);
|
||||
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(false);
|
||||
#endif
|
||||
//5000ms
|
||||
_loramac.LoRaMacSetTxTimer(5000);
|
||||
|
||||
//TODO: Should we call lora_state_machine here instead of just setting the state?
|
||||
_device_current_state = DEVICE_STATE_COMPLIANCE_TEST;
|
||||
// lora_state_machine(DEVICE_STATE_COMPLIANCE_TEST);
|
||||
tr_debug("Compliance test activated.");
|
||||
}
|
||||
} else {
|
||||
_compliance_test.state = mcps_indication->buffer[0];
|
||||
switch (_compliance_test.state) {
|
||||
case 0: // Check compliance test disable command (ii)
|
||||
_compliance_test.is_tx_confirmed = true;
|
||||
_compliance_test.app_port = MBED_CONF_LORA_APP_PORT;
|
||||
_compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE;
|
||||
_compliance_test.downlink_counter = 0;
|
||||
_compliance_test.running = false;
|
||||
|
||||
loramac_mib_req_confirm_t mib_req;
|
||||
mib_req.type = MIB_ADR;
|
||||
mib_req.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
|
||||
mib_set_request(&mib_req);
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
|
||||
#endif
|
||||
// Go to idle state after compliance test mode.
|
||||
tr_debug("Compliance test disabled.");
|
||||
_loramac.LoRaMacStopTxTimer();
|
||||
|
||||
// Clear any compliance test message stuff before going back to normal operation.
|
||||
memset(&_tx_msg, 0, sizeof(_tx_msg));
|
||||
lora_state_machine(DEVICE_STATE_IDLE);
|
||||
break;
|
||||
case 1: // (iii, iv)
|
||||
_compliance_test.app_data_size = 2;
|
||||
break;
|
||||
case 2: // Enable confirmed messages (v)
|
||||
_compliance_test.is_tx_confirmed = true;
|
||||
_compliance_test.state = 1;
|
||||
break;
|
||||
case 3: // Disable confirmed messages (vi)
|
||||
_compliance_test.is_tx_confirmed = false;
|
||||
_compliance_test.state = 1;
|
||||
break;
|
||||
case 4: // (vii)
|
||||
_compliance_test.app_data_size = mcps_indication->buffer_size;
|
||||
|
||||
_compliance_test.app_data_buffer[0] = 4;
|
||||
for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, LORAMAC_PHY_MAXPAYLOAD); ++i) {
|
||||
_compliance_test.app_data_buffer[i] = mcps_indication->buffer[i] + 1;
|
||||
}
|
||||
|
||||
send_compliance_test_frame_to_mac();
|
||||
break;
|
||||
case 5: // (viii)
|
||||
loramac_mlme_req_t mlme_req;
|
||||
mlme_req.type = MLME_LINK_CHECK;
|
||||
_loramac.mlme_request(&mlme_req);
|
||||
break;
|
||||
case 6: // (ix)
|
||||
loramac_mlme_req_t mlme_request;
|
||||
loramac_mib_req_confirm_t mib_request;
|
||||
|
||||
// Disable TestMode and revert back to normal operation
|
||||
_compliance_test.is_tx_confirmed = true;
|
||||
_compliance_test.app_port = MBED_CONF_LORA_APP_PORT;
|
||||
_compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE;
|
||||
_compliance_test.downlink_counter = 0;
|
||||
_compliance_test.running = false;
|
||||
|
||||
mib_request.type = MIB_ADR;
|
||||
mib_request.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
|
||||
mib_set_request(&mib_request);
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
|
||||
#endif
|
||||
mlme_request.type = MLME_JOIN;
|
||||
mlme_request.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
|
||||
mlme_request.req.join.app_eui = _lw_session.connection.connection_u.otaa.app_eui;
|
||||
mlme_request.req.join.app_key = _lw_session.connection.connection_u.otaa.app_key;
|
||||
mlme_request.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
|
||||
_loramac.mlme_request(&mlme_request);
|
||||
break;
|
||||
case 7: // (x)
|
||||
if (mcps_indication->buffer_size == 3) {
|
||||
loramac_mlme_req_t mlme_req;
|
||||
mlme_req.type = MLME_TXCW;
|
||||
mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
|
||||
_loramac.mlme_request(&mlme_req);
|
||||
} else if (mcps_indication->buffer_size == 7) {
|
||||
loramac_mlme_req_t mlme_req;
|
||||
mlme_req.type = MLME_TXCW_1;
|
||||
mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
|
||||
mlme_req.req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8)
|
||||
| mcps_indication->buffer[5]) * 100;
|
||||
mlme_req.req.cw_tx_mode.power = mcps_indication->buffer[6];
|
||||
_loramac.mlme_request(&mlme_req);
|
||||
}
|
||||
_compliance_test.state = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
lorawan_status_t LoRaWANStack::mib_set_request(loramac_mib_req_confirm_t *mib_set_params)
|
||||
{
|
||||
if (NULL == mib_set_params) {
|
||||
|
|
@ -1140,10 +873,8 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
|
|||
mib_set_request(&mib_req);
|
||||
|
||||
// reset buffers to original state
|
||||
memset(_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
|
||||
_tx_msg.pending_size = 0;
|
||||
_tx_msg.f_buffer_size = 0;
|
||||
_tx_msg.tx_ongoing = false;
|
||||
_loramac.reset_ongoing_tx(true);
|
||||
|
||||
_rx_msg.msg.mcps_indication.buffer = NULL;
|
||||
_rx_msg.receive_ready = false;
|
||||
_rx_msg.prev_read_size = 0;
|
||||
|
|
@ -1243,11 +974,11 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
|
|||
break;
|
||||
case DEVICE_STATE_SEND:
|
||||
// If a transmission is ongoing, don't interrupt
|
||||
if (_tx_msg.tx_ongoing) {
|
||||
if (_loramac.tx_ongoing()) {
|
||||
status = LORAWAN_STATUS_OK;
|
||||
} else {
|
||||
_tx_msg.tx_ongoing = true;
|
||||
status = send_frame_to_mac();
|
||||
_loramac.set_tx_ongoing(true);
|
||||
status = _loramac.send_ongoing_tx();
|
||||
|
||||
switch (status) {
|
||||
case LORAWAN_STATUS_OK:
|
||||
|
|
@ -1300,63 +1031,53 @@ lorawan_status_t LoRaWANStack::lora_state_machine(device_states_t new_state)
|
|||
}
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
/**
|
||||
*
|
||||
* Prepares the upload message to reserved ports
|
||||
*
|
||||
* \param port Application port
|
||||
*/
|
||||
void LoRaWANStack::prepare_special_tx_frame(uint8_t port)
|
||||
{
|
||||
if (port == 224) {
|
||||
// Clear any normal message stuff before compliance test.
|
||||
memset(&_tx_msg, 0, sizeof(_tx_msg));
|
||||
|
||||
if (_compliance_test.link_check == true) {
|
||||
_compliance_test.link_check = false;
|
||||
_compliance_test.state = 1;
|
||||
_tx_msg.f_buffer_size = 3;
|
||||
_tx_msg.f_buffer[0] = 5;
|
||||
_tx_msg.f_buffer[1] = _compliance_test.demod_margin;
|
||||
_tx_msg.f_buffer[2] = _compliance_test.nb_gateways;
|
||||
} else {
|
||||
switch (_compliance_test.state) {
|
||||
case 4:
|
||||
_compliance_test.state = 1;
|
||||
_tx_msg.f_buffer_size = _compliance_test.app_data_size;
|
||||
|
||||
_tx_msg.f_buffer[0] = _compliance_test.app_data_buffer[0];
|
||||
for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, MBED_CONF_LORA_TX_MAX_SIZE); ++i) {
|
||||
_tx_msg.f_buffer[i] = _compliance_test.app_data_buffer[i];
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
_tx_msg.f_buffer_size = 2;
|
||||
_tx_msg.f_buffer[0] = _compliance_test.downlink_counter >> 8;
|
||||
_tx_msg.f_buffer[1] = _compliance_test.downlink_counter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Hands over the compliance test frame to MAC layer
|
||||
*
|
||||
* \return returns the state of the LoRa MAC
|
||||
*/
|
||||
lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
|
||||
{
|
||||
loramac_mcps_req_t mcps_req;
|
||||
|
||||
prepare_special_tx_frame(_compliance_test.app_port);
|
||||
// prepare_special_tx_frame(_compliance_test.app_port);
|
||||
//TODO: What if the port is not 224 ???
|
||||
if (_compliance_test.app_port == 224) {
|
||||
// Clear any normal message stuff before compliance test.
|
||||
memset(&mcps_req, 0, sizeof(mcps_req));
|
||||
|
||||
if (_compliance_test.link_check == true) {
|
||||
_compliance_test.link_check = false;
|
||||
_compliance_test.state = 1;
|
||||
mcps_req.f_buffer_size = 3;
|
||||
mcps_req.f_buffer[0] = 5;
|
||||
mcps_req.f_buffer[1] = _compliance_test.demod_margin;
|
||||
mcps_req.f_buffer[2] = _compliance_test.nb_gateways;
|
||||
} else {
|
||||
switch (_compliance_test.state) {
|
||||
case 4:
|
||||
_compliance_test.state = 1;
|
||||
mcps_req.f_buffer_size = _compliance_test.app_data_size;
|
||||
|
||||
mcps_req.f_buffer[0] = _compliance_test.app_data_buffer[0];
|
||||
for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, MBED_CONF_LORA_TX_MAX_SIZE); ++i) {
|
||||
mcps_req.f_buffer[i] = _compliance_test.app_data_buffer[i];
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
mcps_req.f_buffer_size = 2;
|
||||
mcps_req.f_buffer[0] = _compliance_test.downlink_counter >> 8;
|
||||
mcps_req.f_buffer[1] = _compliance_test.downlink_counter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: If port is not 224, this might not work!
|
||||
//Is there a test case where same _tx_msg's buffer would be used, when port is not 224???
|
||||
if (!_compliance_test.is_tx_confirmed) {
|
||||
mcps_req.type = MCPS_UNCONFIRMED;
|
||||
mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
// mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
// mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
mcps_req.fport = _compliance_test.app_port;
|
||||
mcps_req.nb_trials = 1;
|
||||
mcps_req.data_rate = _lora_phy.get_default_tx_datarate();
|
||||
mcps_req.data_rate = _loramac.get_default_tx_datarate();
|
||||
|
||||
tr_info("Transmit unconfirmed compliance test frame %d bytes.", mcps_req.f_buffer_size);
|
||||
|
||||
|
|
@ -1365,11 +1086,11 @@ lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
|
|||
}
|
||||
} else if (_compliance_test.is_tx_confirmed) {
|
||||
mcps_req.type = MCPS_CONFIRMED;
|
||||
mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
// mcps_req.f_buffer = _tx_msg.f_buffer;
|
||||
// mcps_req.f_buffer_size = _tx_msg.f_buffer_size;
|
||||
mcps_req.fport = _compliance_test.app_port;
|
||||
mcps_req.nb_trials = _num_retry;
|
||||
mcps_req.data_rate = _lora_phy.get_default_tx_datarate();
|
||||
mcps_req.data_rate = _loramac.get_default_tx_datarate();
|
||||
|
||||
tr_info("Transmit confirmed compliance test frame %d bytes.", mcps_req.f_buffer_size);
|
||||
|
||||
|
|
@ -1382,5 +1103,141 @@ lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
|
|||
|
||||
return mcps_request_handler(&mcps_req);
|
||||
}
|
||||
|
||||
/** Compliance testing function
|
||||
*
|
||||
* \param mcps_indication Pointer to the indication structure,
|
||||
* containing indication attributes.
|
||||
*/
|
||||
void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indication)
|
||||
{
|
||||
if (_compliance_test.running == false) {
|
||||
// Check compliance test enable command (i)
|
||||
if ((mcps_indication->buffer_size == 4) &&
|
||||
(mcps_indication->buffer[0] == 0x01) &&
|
||||
(mcps_indication->buffer[1] == 0x01) &&
|
||||
(mcps_indication->buffer[2] == 0x01) &&
|
||||
(mcps_indication->buffer[3] == 0x01)) {
|
||||
_compliance_test.is_tx_confirmed = false;
|
||||
_compliance_test.app_port = 224;
|
||||
_compliance_test.app_data_size = 2;
|
||||
_compliance_test.downlink_counter = 0;
|
||||
_compliance_test.link_check = false;
|
||||
_compliance_test.demod_margin = 0;
|
||||
_compliance_test.nb_gateways = 0;
|
||||
_compliance_test.running = true;
|
||||
_compliance_test.state = 1;
|
||||
|
||||
loramac_mib_req_confirm_t mib_req;
|
||||
mib_req.type = MIB_ADR;
|
||||
mib_req.param.is_adr_enable = true;
|
||||
mib_set_request(&mib_req);
|
||||
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(false);
|
||||
#endif
|
||||
//5000ms
|
||||
_loramac.LoRaMacSetTxTimer(5000);
|
||||
|
||||
//TODO: Should we call lora_state_machine here instead of just setting the state?
|
||||
_device_current_state = DEVICE_STATE_COMPLIANCE_TEST;
|
||||
// lora_state_machine(DEVICE_STATE_COMPLIANCE_TEST);
|
||||
tr_debug("Compliance test activated.");
|
||||
}
|
||||
} else {
|
||||
_compliance_test.state = mcps_indication->buffer[0];
|
||||
switch (_compliance_test.state) {
|
||||
case 0: // Check compliance test disable command (ii)
|
||||
_compliance_test.is_tx_confirmed = true;
|
||||
_compliance_test.app_port = MBED_CONF_LORA_APP_PORT;
|
||||
_compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE;
|
||||
_compliance_test.downlink_counter = 0;
|
||||
_compliance_test.running = false;
|
||||
|
||||
loramac_mib_req_confirm_t mib_req;
|
||||
mib_req.type = MIB_ADR;
|
||||
mib_req.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
|
||||
mib_set_request(&mib_req);
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
|
||||
#endif
|
||||
// Go to idle state after compliance test mode.
|
||||
tr_debug("Compliance test disabled.");
|
||||
_loramac.LoRaMacStopTxTimer();
|
||||
|
||||
// Clear any compliance test message stuff before going back to normal operation.
|
||||
_loramac.reset_ongoing_tx();
|
||||
lora_state_machine(DEVICE_STATE_IDLE);
|
||||
break;
|
||||
case 1: // (iii, iv)
|
||||
_compliance_test.app_data_size = 2;
|
||||
break;
|
||||
case 2: // Enable confirmed messages (v)
|
||||
_compliance_test.is_tx_confirmed = true;
|
||||
_compliance_test.state = 1;
|
||||
break;
|
||||
case 3: // Disable confirmed messages (vi)
|
||||
_compliance_test.is_tx_confirmed = false;
|
||||
_compliance_test.state = 1;
|
||||
break;
|
||||
case 4: // (vii)
|
||||
_compliance_test.app_data_size = mcps_indication->buffer_size;
|
||||
|
||||
_compliance_test.app_data_buffer[0] = 4;
|
||||
for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, LORAMAC_PHY_MAXPAYLOAD); ++i) {
|
||||
_compliance_test.app_data_buffer[i] = mcps_indication->buffer[i] + 1;
|
||||
}
|
||||
|
||||
send_compliance_test_frame_to_mac();
|
||||
break;
|
||||
case 5: // (viii)
|
||||
loramac_mlme_req_t mlme_req;
|
||||
mlme_req.type = MLME_LINK_CHECK;
|
||||
_loramac.mlme_request(&mlme_req);
|
||||
break;
|
||||
case 6: // (ix)
|
||||
loramac_mlme_req_t mlme_request;
|
||||
loramac_mib_req_confirm_t mib_request;
|
||||
|
||||
// Disable TestMode and revert back to normal operation
|
||||
_compliance_test.is_tx_confirmed = true;
|
||||
_compliance_test.app_port = MBED_CONF_LORA_APP_PORT;
|
||||
_compliance_test.app_data_size = LORAWAN_COMPLIANCE_TEST_DATA_SIZE;
|
||||
_compliance_test.downlink_counter = 0;
|
||||
_compliance_test.running = false;
|
||||
|
||||
mib_request.type = MIB_ADR;
|
||||
mib_request.param.is_adr_enable = MBED_CONF_LORA_ADR_ON;
|
||||
mib_set_request(&mib_request);
|
||||
#if MBED_CONF_LORA_PHY == 0
|
||||
_loramac.LoRaMacTestSetDutyCycleOn(MBED_CONF_LORA_DUTY_CYCLE_ON);
|
||||
#endif
|
||||
mlme_request.type = MLME_JOIN;
|
||||
mlme_request.req.join.dev_eui = _lw_session.connection.connection_u.otaa.dev_eui;
|
||||
mlme_request.req.join.app_eui = _lw_session.connection.connection_u.otaa.app_eui;
|
||||
mlme_request.req.join.app_key = _lw_session.connection.connection_u.otaa.app_key;
|
||||
mlme_request.req.join.nb_trials = _lw_session.connection.connection_u.otaa.nb_trials;
|
||||
_loramac.mlme_request(&mlme_request);
|
||||
break;
|
||||
case 7: // (x)
|
||||
if (mcps_indication->buffer_size == 3) {
|
||||
loramac_mlme_req_t mlme_req;
|
||||
mlme_req.type = MLME_TXCW;
|
||||
mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
|
||||
_loramac.mlme_request(&mlme_req);
|
||||
} else if (mcps_indication->buffer_size == 7) {
|
||||
loramac_mlme_req_t mlme_req;
|
||||
mlme_req.type = MLME_TXCW_1;
|
||||
mlme_req.req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
|
||||
mlme_req.req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8)
|
||||
| mcps_indication->buffer[5]) * 100;
|
||||
mlme_req.req.cw_tx_mode.power = mcps_indication->buffer[6];
|
||||
_loramac.mlme_request(&mlme_req);
|
||||
}
|
||||
_compliance_test.state = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ SPDX-License-Identifier: BSD-3-Clause
|
|||
#include "lorastack/mac/LoRaMac.h"
|
||||
#include "lorawan/system/lorawan_data_structures.h"
|
||||
#include "LoRaRadio.h"
|
||||
#include "loraphy_target.h"
|
||||
|
||||
/**
|
||||
* A mask for the network ID.
|
||||
|
|
@ -279,13 +278,15 @@ public:
|
|||
* MSG_CONFIRMED_FLAG and MSG_UNCONFIRMED_FLAG are
|
||||
* mutually exclusive.
|
||||
*
|
||||
* @param null_allowed Internal use only. Needed for sending empty packet
|
||||
* having CONFIRMED bit on.
|
||||
*
|
||||
* @return The number of bytes sent, or
|
||||
* LORAWAN_STATUS_WOULD_BLOCK if another TX is
|
||||
* ongoing, or a negative error code on failure.
|
||||
*/
|
||||
int16_t handle_tx(uint8_t port, const uint8_t* data,
|
||||
uint16_t length, uint8_t flags);
|
||||
uint16_t length, uint8_t flags, bool null_allowed = false);
|
||||
|
||||
/** Receives a message from the Network Server.
|
||||
*
|
||||
|
|
@ -386,11 +387,6 @@ private:
|
|||
*/
|
||||
lorawan_status_t lora_state_machine(device_states_t new_state);
|
||||
|
||||
/**
|
||||
* Hands over the packet to Mac layer by posting an MCPS request.
|
||||
*/
|
||||
lorawan_status_t send_frame_to_mac();
|
||||
|
||||
/**
|
||||
* Callback function for MLME indication. Mac layer calls this function once
|
||||
* an MLME indication is received. This method translates Mac layer data
|
||||
|
|
@ -443,16 +439,6 @@ private:
|
|||
*/
|
||||
lorawan_status_t set_application_port(uint8_t port);
|
||||
|
||||
/**
|
||||
* Helper function to figure out if the user defined data size is possible
|
||||
* to send or not. The allowed size for transmission depends on the current
|
||||
* data rate set for the channel. If its not possible to send user defined
|
||||
* packet size, this method returns the maximum possible size at the moment,
|
||||
* otherwise the user defined size is returned which means all of user data
|
||||
* can be sent.
|
||||
*/
|
||||
uint16_t check_possible_tx_size(uint16_t size);
|
||||
|
||||
/** End device OTAA join.
|
||||
*
|
||||
* Based on the LoRaWAN standard 1.0.2.
|
||||
|
|
@ -481,9 +467,7 @@ private:
|
|||
|
||||
private:
|
||||
|
||||
LoRaWANTimeHandler _lora_time;
|
||||
LoRaMac _loramac;
|
||||
LoRaPHY_region _lora_phy;
|
||||
loramac_primitives_t LoRaMacPrimitives;
|
||||
|
||||
device_states_t _device_current_state;
|
||||
|
|
@ -498,10 +482,6 @@ private:
|
|||
events::EventQueue *_queue;
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
/**
|
||||
* This function is used only for compliance testing
|
||||
*/
|
||||
void prepare_special_tx_frame(uint8_t port);
|
||||
|
||||
/**
|
||||
* Used only for compliance testing
|
||||
|
|
|
|||
|
|
@ -77,10 +77,9 @@ using namespace events;
|
|||
#define DOWN_LINK 1
|
||||
|
||||
|
||||
LoRaMac::LoRaMac(LoRaWANTimeHandler &lora_time)
|
||||
: mac_commands(), _lora_time(lora_time)
|
||||
LoRaMac::LoRaMac()
|
||||
: _lora_phy(_lora_time), mac_commands()
|
||||
{
|
||||
lora_phy = NULL;
|
||||
//radio_events_t RadioEvents;
|
||||
_params.keys.dev_eui = NULL;
|
||||
_params.keys.app_eui = NULL;
|
||||
|
|
@ -88,6 +87,7 @@ LoRaMac::LoRaMac(LoRaWANTimeHandler &lora_time)
|
|||
|
||||
memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey));
|
||||
memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey));
|
||||
memset(&_ongoing_tx_msg, 0, sizeof(_ongoing_tx_msg));
|
||||
|
||||
_params.dev_nonce = 0;
|
||||
_params.net_id = 0;
|
||||
|
|
@ -188,7 +188,7 @@ void LoRaMac::on_radio_tx_done( void )
|
|||
loramac_mlme_confirm_t mlme_confirm = mlme.get_confirmation();
|
||||
|
||||
if (_params.dev_class != CLASS_C) {
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
} else {
|
||||
open_continuous_rx2_window();
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ void LoRaMac::on_radio_tx_done( void )
|
|||
if ((_params.dev_class == CLASS_C ) ||
|
||||
(_params.is_node_ack_requested == true)) {
|
||||
_lora_time.start(_params.timers.ack_timeout_timer,
|
||||
_params.rx_window2_delay + lora_phy->get_ack_timeout());
|
||||
_params.rx_window2_delay + _lora_phy.get_ack_timeout());
|
||||
}
|
||||
} else {
|
||||
mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||
|
|
@ -232,7 +232,7 @@ void LoRaMac::on_radio_tx_done( void )
|
|||
tx_done_params.channel = _params.channel;
|
||||
tx_done_params.joined = _params.is_nwk_joined;
|
||||
tx_done_params.last_tx_done_time = cur_time;
|
||||
lora_phy->set_last_tx_done(&tx_done_params);
|
||||
_lora_phy.set_last_tx_done(&tx_done_params);
|
||||
|
||||
// Update Aggregated last tx done time
|
||||
_params.timers.aggregated_last_tx_time = cur_time;
|
||||
|
|
@ -302,7 +302,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
mcps.get_indication().type = MCPS_UNCONFIRMED;
|
||||
|
||||
if (_params.dev_class != CLASS_C) {
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
}
|
||||
|
||||
_lora_time.stop( _params.timers.rx_window2_timer );
|
||||
|
|
@ -377,7 +377,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
// Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
|
||||
cflist.size = size - 17;
|
||||
|
||||
lora_phy->apply_cf_list(&cflist);
|
||||
_lora_phy.apply_cf_list(&cflist);
|
||||
|
||||
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||
_params.is_nwk_joined = true;
|
||||
|
|
@ -390,7 +390,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
case FRAME_TYPE_DATA_CONFIRMED_DOWN:
|
||||
case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
|
||||
{
|
||||
uint8_t value = lora_phy->get_max_payload(mcps.get_indication().rx_datarate, _params.is_repeater_supported);
|
||||
uint8_t value = _lora_phy.get_max_payload(mcps.get_indication().rx_datarate, _params.is_repeater_supported);
|
||||
|
||||
if (MAX(0, (int16_t) ((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD )) > (int32_t)value) {
|
||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
|
|
@ -469,7 +469,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
}
|
||||
}
|
||||
|
||||
if (sequence_counter_diff >= lora_phy->get_maximum_frame_counter_gap()) {
|
||||
if (sequence_counter_diff >= _lora_phy.get_maximum_frame_counter_gap()) {
|
||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
|
||||
mcps.get_indication().dl_frame_counter = downlink_counter;
|
||||
prepare_rx_done_abort( );
|
||||
|
|
@ -575,7 +575,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
// Decode frame payload MAC commands
|
||||
if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands(
|
||||
_params.payload, 0, frame_len, snr,
|
||||
mlme.get_confirmation(), _params.sys_params, *lora_phy)) {
|
||||
mlme.get_confirmation(), _params.sys_params, _lora_phy)) {
|
||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
} else if (mac_commands.has_sticky_mac_cmd()) {
|
||||
set_mlme_schedule_ul_indication();
|
||||
|
|
@ -592,7 +592,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
// Decode Options field MAC commands. Omit the fPort.
|
||||
if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands(
|
||||
payload, 8, app_payload_start_index - 1, snr,
|
||||
mlme.get_confirmation(), _params.sys_params, *lora_phy )) {
|
||||
mlme.get_confirmation(), _params.sys_params, _lora_phy )) {
|
||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
} else if (mac_commands.has_sticky_mac_cmd()) {
|
||||
set_mlme_schedule_ul_indication();
|
||||
|
|
@ -620,7 +620,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands(
|
||||
payload, 8, app_payload_start_index, snr,
|
||||
mlme.get_confirmation(),
|
||||
_params.sys_params, *lora_phy)) {
|
||||
_params.sys_params, _lora_phy)) {
|
||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
} else if (mac_commands.has_sticky_mac_cmd()) {
|
||||
set_mlme_schedule_ul_indication();
|
||||
|
|
@ -673,7 +673,7 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
|||
void LoRaMac::on_radio_tx_timeout( void )
|
||||
{
|
||||
if (_params.dev_class != CLASS_C) {
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
} else {
|
||||
open_continuous_rx2_window();
|
||||
}
|
||||
|
|
@ -688,7 +688,7 @@ void LoRaMac::on_radio_tx_timeout( void )
|
|||
void LoRaMac::on_radio_rx_error( void )
|
||||
{
|
||||
if (_params.dev_class != CLASS_C) {
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
}
|
||||
|
||||
if (_params.rx_slot == RX_SLOT_WIN_1) {
|
||||
|
|
@ -724,7 +724,7 @@ void LoRaMac::on_radio_rx_error( void )
|
|||
void LoRaMac::on_radio_rx_timeout(void)
|
||||
{
|
||||
if (_params.dev_class != CLASS_C) {
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
}
|
||||
|
||||
if (_params.rx_slot == RX_SLOT_WIN_1) {
|
||||
|
|
@ -864,7 +864,7 @@ void LoRaMac::on_mac_state_check_timer_event(void)
|
|||
_params.ack_timeout_retry_counter++;
|
||||
|
||||
if ((_params.ack_timeout_retry_counter % 2) == 1) {
|
||||
_params.sys_params.channel_data_rate = lora_phy->get_next_lower_tx_datarate(
|
||||
_params.sys_params.channel_data_rate = _lora_phy.get_next_lower_tx_datarate(
|
||||
_params.sys_params.channel_data_rate);
|
||||
}
|
||||
|
||||
|
|
@ -887,7 +887,7 @@ void LoRaMac::on_mac_state_check_timer_event(void)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
lora_phy->restore_default_channels();
|
||||
_lora_phy.restore_default_channels();
|
||||
|
||||
_params.mac_state &= ~LORAMAC_TX_RUNNING;
|
||||
|
||||
|
|
@ -970,7 +970,7 @@ void LoRaMac::on_tx_delayed_timer_event(void)
|
|||
|
||||
reset_mac_parameters();
|
||||
|
||||
_params.sys_params.channel_data_rate = lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
|
||||
_params.sys_params.channel_data_rate = _lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
|
||||
|
||||
mac_hdr.value = 0;
|
||||
mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
|
||||
|
|
@ -1004,10 +1004,10 @@ void LoRaMac::on_rx_window1_timer_event(void)
|
|||
_params.rx_window1_config.rx_slot = _params.rx_slot;
|
||||
|
||||
if (_params.dev_class == CLASS_C) {
|
||||
lora_phy->put_radio_to_standby();
|
||||
_lora_phy.put_radio_to_standby();
|
||||
}
|
||||
|
||||
lora_phy->rx_config(&_params.rx_window1_config,
|
||||
_lora_phy.rx_config(&_params.rx_window1_config,
|
||||
(int8_t*) &mcps.get_indication().rx_datarate);
|
||||
|
||||
rx_window_setup(_params.rx_window1_config.is_rx_continuous,
|
||||
|
|
@ -1031,7 +1031,7 @@ void LoRaMac::on_rx_window2_timer_event(void)
|
|||
_params.rx_window2_config.is_rx_continuous = true;
|
||||
}
|
||||
|
||||
if (lora_phy->rx_config(&_params.rx_window2_config,
|
||||
if (_lora_phy.rx_config(&_params.rx_window2_config,
|
||||
(int8_t*) &mcps.get_indication().rx_datarate) == true) {
|
||||
|
||||
rx_window_setup(_params.rx_window2_config.is_rx_continuous,
|
||||
|
|
@ -1089,7 +1089,7 @@ void LoRaMac::on_ack_timeout_timer_event(void)
|
|||
|
||||
void LoRaMac::rx_window_setup(bool rx_continuous, uint32_t max_rx_window_time)
|
||||
{
|
||||
lora_phy->setup_rx_window(rx_continuous, max_rx_window_time);
|
||||
_lora_phy.setup_rx_window(rx_continuous, max_rx_window_time);
|
||||
}
|
||||
|
||||
bool LoRaMac::validate_payload_length(uint8_t length, int8_t datarate,
|
||||
|
|
@ -1098,7 +1098,7 @@ bool LoRaMac::validate_payload_length(uint8_t length, int8_t datarate,
|
|||
uint16_t max_value = 0;
|
||||
uint16_t payloadSize = 0;
|
||||
|
||||
max_value = lora_phy->get_max_payload(datarate, _params.is_repeater_supported);
|
||||
max_value = _lora_phy.get_max_payload(datarate, _params.is_repeater_supported);
|
||||
|
||||
// Calculate the resulting payload size
|
||||
payloadSize = (length + fopts_len);
|
||||
|
|
@ -1176,7 +1176,7 @@ lorawan_status_t LoRaMac::schedule_tx(void)
|
|||
nextChan.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time;
|
||||
|
||||
// Select channel
|
||||
status = lora_phy->set_next_channel(&nextChan, &_params.channel,
|
||||
status = _lora_phy.set_next_channel(&nextChan, &_params.channel,
|
||||
&dutyCycleTimeOff,
|
||||
&_params.timers.aggregated_timeoff);
|
||||
switch (status) {
|
||||
|
|
@ -1198,15 +1198,15 @@ lorawan_status_t LoRaMac::schedule_tx(void)
|
|||
tr_debug("Next Channel Idx=%d, DR=%d", _params.channel, nextChan.current_datarate);
|
||||
|
||||
// Compute Rx1 windows parameters
|
||||
uint8_t dr_offset = lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate,
|
||||
uint8_t dr_offset = _lora_phy.apply_DR_offset(_params.sys_params.channel_data_rate,
|
||||
_params.sys_params.rx1_dr_offset);
|
||||
|
||||
lora_phy->compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb,
|
||||
_lora_phy.compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb,
|
||||
_params.sys_params.max_sys_rx_error,
|
||||
&_params.rx_window1_config);
|
||||
|
||||
// Compute Rx2 windows parameters
|
||||
lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
|
||||
_lora_phy.compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
|
||||
_params.sys_params.min_rx_symb,
|
||||
_params.sys_params.max_sys_rx_error,
|
||||
&_params.rx_window2_config);
|
||||
|
|
@ -1245,7 +1245,7 @@ void LoRaMac::calculate_backOff(uint8_t channel)
|
|||
backoff_params.last_tx_was_join_req = _params.is_last_tx_join_request;
|
||||
|
||||
// Update regional back-off
|
||||
lora_phy->calculate_backoff(&backoff_params);
|
||||
_lora_phy.calculate_backoff(&backoff_params);
|
||||
|
||||
// Update aggregated time-off. This must be an assignment and no incremental
|
||||
// update as we do only calculate the time-off based on the last transmission
|
||||
|
|
@ -1277,7 +1277,7 @@ void LoRaMac::reset_mac_parameters(void)
|
|||
|
||||
_params.is_rx_window_enabled = true;
|
||||
|
||||
lora_phy->reset_to_default_values(&_params, false);
|
||||
_lora_phy.reset_to_default_values(&_params, false);
|
||||
|
||||
_params.is_node_ack_requested = false;
|
||||
_params.is_srv_ack_requested = false;
|
||||
|
|
@ -1303,6 +1303,150 @@ void LoRaMac::open_continuous_rx2_window (void)
|
|||
_params.rx_slot = RX_SLOT_WIN_CLASS_C;
|
||||
}
|
||||
|
||||
uint8_t LoRaMac::get_default_tx_datarate()
|
||||
{
|
||||
return _lora_phy.get_default_tx_datarate();
|
||||
}
|
||||
|
||||
bool LoRaMac::tx_ongoing()
|
||||
{
|
||||
return _ongoing_tx_msg.tx_ongoing;
|
||||
}
|
||||
|
||||
void LoRaMac::set_tx_ongoing(bool ongoing)
|
||||
{
|
||||
_ongoing_tx_msg.tx_ongoing = ongoing;
|
||||
}
|
||||
|
||||
void LoRaMac::reset_ongoing_tx(bool reset_pending)
|
||||
{
|
||||
_ongoing_tx_msg.tx_ongoing = false;
|
||||
memset(_ongoing_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
|
||||
_ongoing_tx_msg.f_buffer_size = 0;
|
||||
if (reset_pending) {
|
||||
_ongoing_tx_msg.pending_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t LoRaMac::prepare_ongoing_tx(uint8_t port, const uint8_t* data,
|
||||
uint16_t length, uint8_t flags, uint8_t num_retries)
|
||||
{
|
||||
_ongoing_tx_msg.port = port;
|
||||
|
||||
uint8_t max_possible_size = query_tx_possible(length);
|
||||
|
||||
//TODO: refactor following 20 lines or so. There must be a better way for this
|
||||
if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
|
||||
// LORAWAN_APP_DATA_MAX_SIZE should at least be
|
||||
// either equal to or bigger than maximum possible
|
||||
// tx size because our tx message buffer takes its
|
||||
// length from that macro. Force maximum possible tx unit
|
||||
// to be equal to the buffer size user chose.
|
||||
max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
|
||||
}
|
||||
|
||||
if (max_possible_size < length) {
|
||||
tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
|
||||
length, max_possible_size);
|
||||
|
||||
_ongoing_tx_msg.pending_size = length - max_possible_size;
|
||||
_ongoing_tx_msg.f_buffer_size = max_possible_size;
|
||||
// copy user buffer upto the max_possible_size
|
||||
memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size);
|
||||
} else {
|
||||
// Whole message can be sent at one time
|
||||
_ongoing_tx_msg.f_buffer_size = length;
|
||||
_ongoing_tx_msg.pending_size = 0;
|
||||
// copy user buffer upto the max_possible_size
|
||||
if (length > 0) {
|
||||
memcpy(_ongoing_tx_msg.f_buffer, data, length);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles all unconfirmed messages, including proprietary and multicast
|
||||
if ((flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_FLAG
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_MULTICAST
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) {
|
||||
|
||||
_ongoing_tx_msg.type = MCPS_UNCONFIRMED;
|
||||
_ongoing_tx_msg.fport = port;
|
||||
_ongoing_tx_msg.nb_trials = 1;
|
||||
}
|
||||
|
||||
// Handles all confirmed messages, including proprietary and multicast
|
||||
if ((flags & MSG_FLAG_MASK) == MSG_CONFIRMED_FLAG
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_MULTICAST
|
||||
|| (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) {
|
||||
|
||||
_ongoing_tx_msg.type = MCPS_CONFIRMED;
|
||||
_ongoing_tx_msg.fport = port;
|
||||
_ongoing_tx_msg.nb_trials = num_retries;
|
||||
}
|
||||
|
||||
tr_info("RTS = %u bytes, PEND = %u", _ongoing_tx_msg.f_buffer_size, _ongoing_tx_msg.pending_size);
|
||||
return _ongoing_tx_msg.f_buffer_size;
|
||||
}
|
||||
|
||||
lorawan_status_t LoRaMac::send_ongoing_tx()
|
||||
{
|
||||
lorawan_status_t status;
|
||||
loramac_mib_req_confirm_t mib_get_params;
|
||||
|
||||
if (_params.mac_state != LORAMAC_IDLE) {
|
||||
return LORAWAN_STATUS_BUSY;
|
||||
}
|
||||
|
||||
int8_t datarate = get_default_tx_datarate();
|
||||
|
||||
mib_get_params.type = MIB_CHANNELS_DATARATE;
|
||||
if(mib_get_request_confirm(&mib_get_params) == LORAWAN_STATUS_OK) {
|
||||
datarate = mib_get_params.param.channel_data_rate;
|
||||
}
|
||||
// TODO: The comment is different than the code???
|
||||
// Apply the minimum possible datarate.
|
||||
// Some regions have limitations for the minimum datarate.
|
||||
datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate());
|
||||
|
||||
loramac_mhdr_t machdr;
|
||||
machdr.value = 0;
|
||||
|
||||
mcps.reset_confirmation();
|
||||
|
||||
_params.ack_timeout_retry_counter = 1;
|
||||
_params.max_ack_timeout_retries = 1;
|
||||
|
||||
if (MCPS_UNCONFIRMED == _ongoing_tx_msg.type) {
|
||||
machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP;
|
||||
} else if (_ongoing_tx_msg.type == MCPS_CONFIRMED) {
|
||||
machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP;
|
||||
_params.max_ack_timeout_retries = _ongoing_tx_msg.nb_trials;
|
||||
} else if ( _ongoing_tx_msg.type == MCPS_PROPRIETARY) {
|
||||
//Is this dead code currently??? Nobody sets this type
|
||||
machdr.bits.mtype = FRAME_TYPE_PROPRIETARY;
|
||||
} else {
|
||||
return LORAWAN_STATUS_SERVICE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (_params.sys_params.adr_on == false) {
|
||||
if (_lora_phy.verify_tx_datarate(datarate, false) == true) {
|
||||
_params.sys_params.channel_data_rate = datarate;
|
||||
} else {
|
||||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
status = send(&machdr, _ongoing_tx_msg.fport, _ongoing_tx_msg.f_buffer,
|
||||
_ongoing_tx_msg.f_buffer_size);
|
||||
if (status == LORAWAN_STATUS_OK) {
|
||||
mcps.get_confirmation().req_type = _ongoing_tx_msg.type;
|
||||
_params.flags.bits.mcps_req = 1;
|
||||
} else {
|
||||
_params.is_node_ack_requested = false;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void memcpy_convert_endianess(uint8_t *dst, const uint8_t *src,
|
||||
uint16_t size)
|
||||
{
|
||||
|
|
@ -1348,7 +1492,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
|
|||
_params.keys.dev_eui, 8);
|
||||
_params.buffer_pkt_len += 8;
|
||||
|
||||
_params.dev_nonce = lora_phy->get_radio_rng();
|
||||
_params.dev_nonce = _lora_phy.get_radio_rng();
|
||||
|
||||
_params.buffer[_params.buffer_pkt_len++] = _params.dev_nonce & 0xFF;
|
||||
_params.buffer[_params.buffer_pkt_len++] = (_params.dev_nonce >> 8) & 0xFF;
|
||||
|
|
@ -1375,7 +1519,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
|
|||
}
|
||||
|
||||
if (_params.sys_params.adr_on) {
|
||||
if (lora_phy->get_next_ADR(true,
|
||||
if (_lora_phy.get_next_ADR(true,
|
||||
_params.sys_params.channel_data_rate,
|
||||
_params.sys_params.channel_tx_power,
|
||||
_params.adr_ack_counter)) {
|
||||
|
|
@ -1503,7 +1647,7 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
|
|||
tx_config.antenna_gain = _params.sys_params.antenna_gain;
|
||||
tx_config.pkt_len = _params.buffer_pkt_len;
|
||||
|
||||
lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
|
||||
_lora_phy.tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
|
||||
|
||||
mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_ERROR;
|
||||
|
||||
|
|
@ -1525,61 +1669,15 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
|
|||
}
|
||||
|
||||
// Send now
|
||||
lora_phy->handle_send(_params.buffer, _params.buffer_pkt_len);
|
||||
_lora_phy.handle_send(_params.buffer, _params.buffer_pkt_len);
|
||||
|
||||
_params.mac_state |= LORAMAC_TX_RUNNING;
|
||||
|
||||
return LORAWAN_STATUS_OK;
|
||||
}
|
||||
|
||||
//lorawan_status_t LoRaMac::set_tx_continuous_wave(uint16_t timeout)
|
||||
//{
|
||||
// cw_mode_params_t continuous_wave;
|
||||
|
||||
// continuous_wave.channel = _params.channel;
|
||||
// continuous_wave.datarate = _params.sys_params.channel_data_rate;
|
||||
// continuous_wave.tx_power = _params.sys_params.channel_tx_power;
|
||||
// continuous_wave.max_eirp = _params.sys_params.max_eirp;
|
||||
// continuous_wave.antenna_gain = _params.sys_params.antenna_gain;
|
||||
// continuous_wave.timeout = timeout;
|
||||
|
||||
// lora_phy->set_tx_cont_mode(&continuous_wave);
|
||||
|
||||
// // Starts the MAC layer status check timer
|
||||
// _lora_time.start(_params.timers.mac_state_check_timer,
|
||||
// MAC_STATE_CHECK_TIMEOUT);
|
||||
|
||||
// _params.mac_state |= LORAMAC_TX_RUNNING;
|
||||
|
||||
// return LORAWAN_STATUS_OK;
|
||||
//}
|
||||
|
||||
//lorawan_status_t LoRaMac::set_tx_continuous_wave1(uint16_t timeout,
|
||||
// uint32_t frequency,
|
||||
// uint8_t power)
|
||||
//{
|
||||
// cw_mode_params_t continuous_wave;
|
||||
|
||||
// continuous_wave.channel = 0;
|
||||
// continuous_wave.datarate = 0;
|
||||
// continuous_wave.tx_power = power;
|
||||
// continuous_wave.max_eirp = 0;
|
||||
// continuous_wave.antenna_gain = 0;
|
||||
// continuous_wave.timeout = timeout;
|
||||
|
||||
// lora_phy->set_tx_cont_mode(&continuous_wave);
|
||||
|
||||
// // Starts the MAC layer status check timer
|
||||
// _lora_time.start(_params.timers.mac_state_check_timer,
|
||||
// MAC_STATE_CHECK_TIMEOUT);
|
||||
|
||||
// _params.mac_state |= LORAMAC_TX_RUNNING;
|
||||
|
||||
// return LORAWAN_STATUS_OK;
|
||||
//}
|
||||
|
||||
lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
|
||||
LoRaPHY *phy, EventQueue *queue)
|
||||
EventQueue *queue)
|
||||
{
|
||||
_lora_time.activate_timer_subsystem(queue);
|
||||
|
||||
|
|
@ -1590,19 +1688,17 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
|
|||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
lora_phy = phy;
|
||||
|
||||
// Activate MLME subsystem
|
||||
mlme.activate_mlme_subsystem(lora_phy);
|
||||
mlme.activate_mlme_subsystem(&_lora_phy);
|
||||
|
||||
// Activate MCPS subsystem
|
||||
mcps.activate_mcps_subsystem();
|
||||
|
||||
// Activate MIB subsystem
|
||||
mib.activate_mib_subsystem(lora_phy);
|
||||
mib.activate_mib_subsystem(&_lora_phy);
|
||||
|
||||
// Activate channel planning subsystem
|
||||
channel_plan.activate_channelplan_subsystem(lora_phy);
|
||||
channel_plan.activate_channelplan_subsystem(&_lora_phy);
|
||||
|
||||
mac_primitives = primitives;
|
||||
|
||||
|
|
@ -1619,7 +1715,7 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
|
|||
_params.timers.aggregated_last_tx_time = 0;
|
||||
_params.timers.aggregated_timeoff = 0;
|
||||
|
||||
lora_phy->reset_to_default_values(&_params, true);
|
||||
_lora_phy.reset_to_default_values(&_params, true);
|
||||
|
||||
// Init parameters which are not set in function ResetMacParameters
|
||||
_params.sys_params.max_sys_rx_error = 10;
|
||||
|
|
@ -1629,11 +1725,11 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives,
|
|||
reset_mac_parameters();
|
||||
|
||||
// Random seed initialization
|
||||
srand(lora_phy->get_radio_rng());
|
||||
srand(_lora_phy.get_radio_rng());
|
||||
|
||||
_params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
|
||||
lora_phy->setup_public_network_mode(_params.is_nwk_public);
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.setup_public_network_mode(_params.is_nwk_public);
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
|
||||
// Initialize timers
|
||||
_lora_time.init(_params.timers.mac_state_check_timer,
|
||||
|
|
@ -1673,7 +1769,7 @@ void LoRaMac::disconnect()
|
|||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||
|
||||
// Put radio to sleep
|
||||
lora_phy->put_radio_to_sleep();
|
||||
_lora_phy.put_radio_to_sleep();
|
||||
|
||||
// Reset internal state
|
||||
_params.is_nwk_joined = false;
|
||||
|
|
@ -1693,31 +1789,27 @@ void LoRaMac::disconnect()
|
|||
_params.mac_state = LORAMAC_IDLE;
|
||||
}
|
||||
|
||||
lorawan_status_t LoRaMac::query_tx_possible(uint8_t size,
|
||||
loramac_tx_info_t* tx_info)
|
||||
uint8_t LoRaMac::query_tx_possible(uint8_t size)
|
||||
{
|
||||
uint8_t max_possible_payload_size = 0;
|
||||
uint8_t current_payload_size = 0;
|
||||
uint8_t fopt_len = mac_commands.get_mac_cmd_length()
|
||||
+ mac_commands.get_repeat_commands_length();
|
||||
|
||||
if (tx_info == NULL) {
|
||||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
}
|
||||
|
||||
// if applicaion has turned on ADR, we want to opt it out
|
||||
// if application has turned on ADR, we want to opt it out
|
||||
if (_params.sys_params.adr_on) {
|
||||
lora_phy->get_next_ADR(false, _params.sys_params.channel_data_rate,
|
||||
_lora_phy.get_next_ADR(false, _params.sys_params.channel_data_rate,
|
||||
_params.sys_params.channel_tx_power,
|
||||
_params.adr_ack_counter);
|
||||
}
|
||||
|
||||
tx_info->current_payload_size = lora_phy->get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported);
|
||||
|
||||
current_payload_size = _lora_phy.get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported);
|
||||
|
||||
// Verify if the fOpts fit into the maximum payload
|
||||
if (tx_info->current_payload_size >= fopt_len) {
|
||||
tx_info->max_possible_payload_size = tx_info->current_payload_size - fopt_len;
|
||||
if (current_payload_size >= fopt_len) {
|
||||
max_possible_payload_size = current_payload_size - fopt_len;
|
||||
} else {
|
||||
tx_info->max_possible_payload_size = tx_info->current_payload_size;
|
||||
max_possible_payload_size = current_payload_size;
|
||||
// The fOpts don't fit into the maximum payload. Omit the MAC commands to
|
||||
// ensure that another uplink is possible.
|
||||
fopt_len = 0;
|
||||
|
|
@ -1728,9 +1820,9 @@ lorawan_status_t LoRaMac::query_tx_possible(uint8_t size,
|
|||
// Verify if the fOpts and the payload fit into the maximum payload
|
||||
if (validate_payload_length(size, _params.sys_params.channel_data_rate,
|
||||
fopt_len) == false) {
|
||||
return LORAWAN_STATUS_LENGTH_ERROR;
|
||||
return max_possible_payload_size;
|
||||
}
|
||||
return LORAWAN_STATUS_OK;
|
||||
return current_payload_size;
|
||||
}
|
||||
|
||||
lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t& plan)
|
||||
|
|
@ -1876,7 +1968,7 @@ lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest )
|
|||
_params.keys.app_key = mlmeRequest->req.join.app_key;
|
||||
_params.max_join_request_trials = mlmeRequest->req.join.nb_trials;
|
||||
|
||||
if (!lora_phy->verify_nb_join_trials(mlmeRequest->req.join.nb_trials)) {
|
||||
if (!_lora_phy.verify_nb_join_trials(mlmeRequest->req.join.nb_trials)) {
|
||||
// Value not supported, get default
|
||||
_params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
|
||||
}
|
||||
|
|
@ -1886,7 +1978,7 @@ lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t *mlmeRequest )
|
|||
reset_mac_parameters();
|
||||
|
||||
_params.sys_params.channel_data_rate =
|
||||
lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
|
||||
_lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
|
||||
|
||||
loramac_mhdr_t machdr;
|
||||
machdr.value = 0;
|
||||
|
|
@ -1929,7 +2021,7 @@ lorawan_status_t LoRaMac::mcps_request( loramac_mcps_req_t *mcpsRequest )
|
|||
// TODO: The comment is different than the code???
|
||||
// Apply the minimum possible datarate.
|
||||
// Some regions have limitations for the minimum datarate.
|
||||
datarate = MAX(datarate, (int8_t)lora_phy->get_minimum_tx_datarate());
|
||||
datarate = MAX(datarate, (int8_t)_lora_phy.get_minimum_tx_datarate());
|
||||
|
||||
machdr.value = 0;
|
||||
|
||||
|
|
@ -1963,7 +2055,7 @@ lorawan_status_t LoRaMac::mcps_request( loramac_mcps_req_t *mcpsRequest )
|
|||
// }
|
||||
|
||||
if (_params.sys_params.adr_on == false) {
|
||||
if (lora_phy->verify_tx_datarate(datarate, false) == true) {
|
||||
if (_lora_phy.verify_tx_datarate(datarate, false) == true) {
|
||||
_params.sys_params.channel_data_rate = datarate;
|
||||
} else {
|
||||
return LORAWAN_STATUS_PARAMETER_INVALID;
|
||||
|
|
@ -1997,7 +2089,7 @@ lorawan_status_t LoRaMac::mib_set_request_confirm( loramac_mib_req_confirm_t *mi
|
|||
return status;
|
||||
}
|
||||
|
||||
radio_events_t *LoRaMac::get_phy_event_handlers()
|
||||
void LoRaMac::bind_radio_driver(LoRaRadio& radio)
|
||||
{
|
||||
radio_events.tx_done = mbed::callback(this, &LoRaMac::handle_tx_done);
|
||||
radio_events.rx_done = mbed::callback(this, &LoRaMac::handle_rx_done);
|
||||
|
|
@ -2005,7 +2097,10 @@ radio_events_t *LoRaMac::get_phy_event_handlers()
|
|||
radio_events.tx_timeout = mbed::callback(this, &LoRaMac::handle_tx_timeout);
|
||||
radio_events.rx_timeout = mbed::callback(this, &LoRaMac::handle_rx_timeout);
|
||||
|
||||
return &radio_events;
|
||||
_lora_phy.set_radio_instance(radio);
|
||||
radio.lock();
|
||||
radio.init_radio(&radio_events);
|
||||
radio.unlock();
|
||||
}
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
|
|
@ -2038,7 +2133,7 @@ void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter )
|
|||
|
||||
void LoRaMac::LoRaMacTestSetDutyCycleOn( bool enable )
|
||||
{
|
||||
if(lora_phy->verify_duty_cycle(enable) == true)
|
||||
if(_lora_phy.verify_duty_cycle(enable) == true)
|
||||
{
|
||||
_params.is_dutycycle_on = enable;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "lorastack/mac/LoRaMacMcps.h"
|
||||
#include "lorastack/mac/LoRaMacMib.h"
|
||||
#include "lorastack/mac/LoRaMacChannelPlan.h"
|
||||
#include "loraphy_target.h"
|
||||
|
||||
class LoRaMac {
|
||||
|
||||
|
|
@ -57,7 +58,7 @@ public:
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
LoRaMac(LoRaWANTimeHandler &lora_time);
|
||||
LoRaMac();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
|
|
@ -75,15 +76,13 @@ public:
|
|||
* @param primitives [in] A pointer to the structure defining the LoRaMAC
|
||||
* event functions. Refer to \ref loramac_primitives_t.
|
||||
*
|
||||
* @param phy [in] A pointer to the selected PHY layer.
|
||||
*
|
||||
* @param queue [in] A pointer to the application provided EventQueue.
|
||||
*
|
||||
* @return `lorawan_status_t` The status of the operation. The possible values are:
|
||||
* \ref LORAWAN_STATUS_OK
|
||||
* \ref LORAWAN_STATUS_PARAMETER_INVALID
|
||||
*/
|
||||
lorawan_status_t initialize(loramac_primitives_t *primitives, LoRaPHY *phy,
|
||||
lorawan_status_t initialize(loramac_primitives_t *primitives,
|
||||
events::EventQueue *queue);
|
||||
|
||||
/**
|
||||
|
|
@ -97,26 +96,16 @@ public:
|
|||
/**
|
||||
* @brief Queries the LoRaMAC whether it is possible to send the next frame with
|
||||
* a given payload size. The LoRaMAC takes the scheduled MAC commands into
|
||||
* account and reports when the frame can be sent.
|
||||
* account and returns corresponding value.
|
||||
*
|
||||
* @param size [in] The size of the applicable payload to be sent next.
|
||||
* @param tx_info [out] The structure \ref loramac_tx_info_t contains
|
||||
* information on the actual maximum payload possible
|
||||
* (according to the configured datarate or the next
|
||||
* datarate according to ADR), and the maximum frame
|
||||
* size, taking the scheduled MAC commands into account.
|
||||
*
|
||||
* @return `lorawan_status_t` The status of the operation. When the parameters are
|
||||
* not valid, the function returns \ref LORAWAN_STATUS_PARAMETER_INVALID.
|
||||
* In case of a length error caused by the applicable payload in combination
|
||||
* with the MAC commands, the function returns \ref LORAWAN_STATUS_LENGTH_ERROR.
|
||||
* @return Size of the biggest packet that can be sent.
|
||||
* Please note that if the size of the MAC commands in the queue do
|
||||
* not fit into the payload size on the related datarate, the LoRaMAC will
|
||||
* omit the MAC commands.
|
||||
* If the query is valid, and the LoRaMAC is able to send the frame,
|
||||
* the function returns \ref LORAWAN_STATUS_OK.
|
||||
*/
|
||||
lorawan_status_t query_tx_possible(uint8_t size, loramac_tx_info_t* tx_info);
|
||||
uint8_t query_tx_possible(uint8_t size);
|
||||
|
||||
/**
|
||||
* @brief Adds a channel plan to the system.
|
||||
|
|
@ -358,13 +347,18 @@ public:
|
|||
*/
|
||||
lorawan_status_t mcps_request(loramac_mcps_req_t *request);
|
||||
|
||||
/**
|
||||
* @brief LoRaMAC layer provides its callback functions for
|
||||
* PHY layer.
|
||||
/** Binds radio driver to PHY layer.
|
||||
*
|
||||
* MAC layer is totally detached from the PHY layer so the stack layer
|
||||
* needs to play the role of an arbitrator. This API gets a radio driver
|
||||
* object from the application (via LoRaWANInterface), binds it to the PHY
|
||||
* layer and initialises radio callback handles which the radio driver will
|
||||
* use in order to report events.
|
||||
*
|
||||
* @param radio LoRaRadio object, i.e., the radio driver
|
||||
*
|
||||
* @return Pointer to callback functions for radio events
|
||||
*/
|
||||
radio_events_t *get_phy_event_handlers();
|
||||
void bind_radio_driver(LoRaRadio& radio);
|
||||
|
||||
/**
|
||||
* @brief Configures the events to trigger an MLME-Indication with
|
||||
|
|
@ -427,7 +421,49 @@ public:
|
|||
*/
|
||||
void open_continuous_rx2_window(void);
|
||||
|
||||
/**
|
||||
* @brief get_default_tx_datarate Gets the default TX datarate
|
||||
* @return default TX datarate.
|
||||
*/
|
||||
uint8_t get_default_tx_datarate();
|
||||
|
||||
/**
|
||||
* @brief tx_ongoing Check whether a prepare is done or not.
|
||||
* @return True if prepare_ongoing_tx is called, false otherwise.
|
||||
*/
|
||||
bool tx_ongoing();
|
||||
|
||||
/**
|
||||
* @brief set_tx_ongoing Changes the ongoing status for prepared message.
|
||||
* @param ongoing The value indicating the status.
|
||||
*/
|
||||
void set_tx_ongoing(bool ongoing);
|
||||
|
||||
/**
|
||||
* @brief reset_ongoing_tx Resets _ongoing_tx_msg.
|
||||
* @param reset_pending If true resets pending size also.
|
||||
*/
|
||||
void reset_ongoing_tx(bool reset_pending = false);
|
||||
|
||||
/**
|
||||
* @brief prepare_ongoing_tx This will prepare (and override) ongoing_tx_msg.
|
||||
* @param port The application port number.
|
||||
* @param data A pointer to the data being sent. The ownership of the
|
||||
* buffer is not transferred.
|
||||
* @param length The size of data in bytes.
|
||||
* @param flags A flag used to determine what type of
|
||||
* message is being sent.
|
||||
* @param num_retries Number of retries for a confirmed type message
|
||||
* @return The number of bytes prepared for sending.
|
||||
*/
|
||||
int16_t prepare_ongoing_tx(uint8_t port, const uint8_t* data,
|
||||
uint16_t length, uint8_t flags, uint8_t num_retries);
|
||||
|
||||
/**
|
||||
* @brief send_ongoing_tx Sends the ongoing_tx_msg
|
||||
* @return LORAWAN_STATUS_OK or a negative error code on failure.
|
||||
*/
|
||||
lorawan_status_t send_ongoing_tx();
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
@ -552,10 +588,15 @@ private:
|
|||
void handle_fhss_change_channel(uint8_t cur_channel);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Timer subsystem handle
|
||||
*/
|
||||
LoRaWANTimeHandler _lora_time;
|
||||
|
||||
/**
|
||||
* LoRa PHY layer object storage
|
||||
*/
|
||||
LoRaPHY *lora_phy;
|
||||
LoRaPHY_region _lora_phy;
|
||||
|
||||
/**
|
||||
* MAC command handle
|
||||
|
|
@ -582,11 +623,6 @@ private:
|
|||
*/
|
||||
LoRaMacChannelPlan channel_plan;
|
||||
|
||||
/**
|
||||
* Timer subsystem handle
|
||||
*/
|
||||
LoRaWANTimeHandler &_lora_time;
|
||||
|
||||
/**
|
||||
* Central MAC layer data storage
|
||||
*/
|
||||
|
|
@ -607,6 +643,8 @@ private:
|
|||
*/
|
||||
events::EventQueue *ev_queue;
|
||||
|
||||
loramac_tx_message_t _ongoing_tx_msg;
|
||||
|
||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||
public: // Test interface
|
||||
|
||||
|
|
|
|||
|
|
@ -1550,20 +1550,6 @@ typedef struct {
|
|||
mib_params_t param;
|
||||
}loramac_mib_req_confirm_t;
|
||||
|
||||
/*!
|
||||
* LoRaMAC TX information
|
||||
*/
|
||||
typedef struct {
|
||||
/*!
|
||||
* Defines the size of the applicable payload that can be processed.
|
||||
*/
|
||||
uint8_t max_possible_payload_size;
|
||||
/*!
|
||||
* The current payload size, dependent on the current datarate.
|
||||
*/
|
||||
uint8_t current_payload_size;
|
||||
} loramac_tx_info_t;
|
||||
|
||||
/** LoRaMAC status.
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue