uint8_t LoRaPHYCN470::link_ADR_request(adr_req_params_t* params, int8_t* dr_out, int8_t* tx_power_out, uint8_t* nb_rep_out, uint8_t* nb_bytes_parsed) { uint8_t status = 0x07; link_adr_params_t adr_settings; uint8_t next_index = 0; uint8_t bytes_processed = 0; uint16_t temp_channel_masks[CN470_CHANNEL_MASK_SIZE] = {0, 0, 0, 0, 0, 0}; verify_adr_params_t verify_params; // Initialize local copy of channels mask copy_channel_mask(temp_channel_masks, channel_mask, CN470_CHANNEL_MASK_SIZE); while(bytes_processed < params->payload_size) { // Get ADR request parameters next_index = parse_link_ADR_req(&(params->payload[bytes_processed]), &adr_settings); if (next_index == 0) { break; // break loop, since no more request has been found } // Update bytes processed bytes_processed += next_index; // Revert status, as we only check the last ADR request for the channel mask KO status = 0x07; if (adr_settings.ch_mask_ctrl == 6) { // Enable all 125 kHz channels for (uint8_t i = 0; i < CN470_CHANNEL_MASK_SIZE; i++) { temp_channel_masks[i] = 0xFFFF; } } else if( adr_settings.ch_mask_ctrl == 7 ) { status &= 0xFE; // Channel mask KO } else { for (uint8_t i = 0; i < 16; i++) { if (((adr_settings.channel_mask & (1 << i)) != 0 ) && (channels[adr_settings.ch_mask_ctrl * 16 + i].frequency == 0)) { // Trying to enable an undefined channel status &= 0xFE; // Channel mask KO } } temp_channel_masks[adr_settings.ch_mask_ctrl] = adr_settings.channel_mask; } } verify_params.status = status; verify_params.adr_enabled = params->adr_enabled; verify_params.datarate = adr_settings.datarate; verify_params.tx_power = adr_settings.tx_power; verify_params.nb_rep = adr_settings.nb_rep; verify_params.current_datarate = params->current_datarate; verify_params.current_tx_power = params->current_tx_power; verify_params.current_nb_rep = params->current_nb_rep; verify_params.channel_mask = temp_channel_masks; // Verify the parameters and update, if necessary status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, &adr_settings.tx_power, &adr_settings.nb_rep); // Update channelsMask if everything is correct if (status == 0x07) { // Copy Mask copy_channel_mask(channel_mask, temp_channel_masks, CN470_CHANNEL_MASK_SIZE); } // Update status variables *dr_out = adr_settings.datarate; *tx_power_out = adr_settings.tx_power; *nb_rep_out = adr_settings.nb_rep; *nb_bytes_parsed = bytes_processed; return status; }
uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params, int8_t* dr_out, int8_t* tx_power_out, uint8_t* nb_rep_out, uint8_t* nb_bytes_parsed) { uint8_t status = 0x07; link_adr_params_t adr_settings; uint8_t next_idx = 0; uint8_t bytes_processed = 0; uint16_t temp_channel_masks[US915_CHANNEL_MASK_SIZE] = {0, 0, 0, 0, 0}; verify_adr_params_t verify_params; // Initialize local copy of channels mask copy_channel_mask(temp_channel_masks, channel_mask, US915_CHANNEL_MASK_SIZE); while (bytes_processed < params->payload_size) { next_idx = parse_link_ADR_req(&(params->payload[bytes_processed]), &adr_settings); if (next_idx == 0) { break; // break loop, since no more request has been found } // Update bytes processed bytes_processed += next_idx; // Revert status, as we only check the last ADR request for the channel mask KO status = 0x07; if (adr_settings.ch_mask_ctrl == 6) { // Enable all 125 kHz channels temp_channel_masks[0] = 0xFFFF; temp_channel_masks[1] = 0xFFFF; temp_channel_masks[2] = 0xFFFF; temp_channel_masks[3] = 0xFFFF; // Apply chMask to channels 64 to 71 temp_channel_masks[4] = adr_settings.channel_mask; } else if (adr_settings.ch_mask_ctrl == 7) { // Disable all 125 kHz channels temp_channel_masks[0] = 0x0000; temp_channel_masks[1] = 0x0000; temp_channel_masks[2] = 0x0000; temp_channel_masks[3] = 0x0000; // Apply chMask to channels 64 to 71 temp_channel_masks[4] = adr_settings.channel_mask; } else if (adr_settings.ch_mask_ctrl == 5) { // RFU status &= 0xFE; // Channel mask KO } else { temp_channel_masks[adr_settings.ch_mask_ctrl] = adr_settings.channel_mask; } } // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels if ((adr_settings.datarate < DR_4) && (num_active_channels(temp_channel_masks, 0, 4) < 2)) { status &= 0xFE; // Channel mask KO } verify_params.status = status; verify_params.adr_enabled = params->adr_enabled; verify_params.datarate = adr_settings.datarate; verify_params.tx_power = adr_settings.tx_power; verify_params.nb_rep = adr_settings.nb_rep; verify_params.current_datarate = params->current_datarate; verify_params.current_tx_power = params->current_tx_power; verify_params.current_nb_rep = params->current_nb_rep; verify_params.channel_mask = temp_channel_masks; // Verify the parameters and update, if necessary status = verify_link_ADR_req(&verify_params, &adr_settings.datarate, &adr_settings.tx_power, &adr_settings.nb_rep); // Update channelsMask if everything is correct if (status == 0x07) { // Copy Mask copy_channel_mask(channel_mask, temp_channel_masks, US915_CHANNEL_MASK_SIZE); current_channel_mask[0] &= channel_mask[0]; current_channel_mask[1] &= channel_mask[1]; current_channel_mask[2] &= channel_mask[2]; current_channel_mask[3] &= channel_mask[3]; current_channel_mask[4] = channel_mask[4]; } // Update status variables *dr_out = adr_settings.datarate; *tx_power_out = adr_settings.tx_power; *nb_rep_out = adr_settings.nb_rep; *nb_bytes_parsed = bytes_processed; return status; }