|
|
@@ -8,6 +8,7 @@
|
|
|
*/
|
|
|
|
|
|
#include "BLE_TX.h"
|
|
|
+#include "options.h"
|
|
|
#include <esp_system.h>
|
|
|
|
|
|
#include <BLEDevice.h>
|
|
|
@@ -16,52 +17,39 @@
|
|
|
// set max power
|
|
|
static const int8_t tx_power = ESP_PWR_LVL_P18;
|
|
|
|
|
|
-static esp_ble_gap_ext_adv_params_t ext_adv_params_1M = {
|
|
|
- .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE,
|
|
|
- .interval_min = 0x30,
|
|
|
- .interval_max = 0x30,
|
|
|
- .channel_map = ADV_CHNL_ALL,
|
|
|
- .own_addr_type = BLE_ADDR_TYPE_RANDOM,
|
|
|
- .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
|
|
- .tx_power = tx_power,
|
|
|
- .primary_phy = ESP_BLE_GAP_PHY_CODED,
|
|
|
- .max_skip = 0,
|
|
|
- .secondary_phy = ESP_BLE_GAP_PHY_1M,
|
|
|
- .sid = 0,
|
|
|
- .scan_req_notif = false,
|
|
|
-};
|
|
|
-
|
|
|
+//interval min/max are configured for 1 Hz update rate. Somehow dynamic setting of these fields fails
|
|
|
+//shorter intervals lead to more BLE transmissions. This would result in increased power consumption and can lead to more interference to other radio systems.
|
|
|
static esp_ble_gap_ext_adv_params_t legacy_adv_params = {
|
|
|
- .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND,
|
|
|
- .interval_min = 0x45,
|
|
|
- .interval_max = 0x45,
|
|
|
+ .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN,
|
|
|
+ .interval_min = 125, //(unsigned int) 0.75*1000/(OUTPUT_RATE_HZ*6); //allow ble controller to have some room for transmission.
|
|
|
+ .interval_max = 167, //(unsigned int) 1000/(OUTPUT_RATE_HZ*6);
|
|
|
.channel_map = ADV_CHNL_ALL,
|
|
|
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
|
|
|
- .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
|
|
+ .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST, // we want unicast non-connectable transmission
|
|
|
.tx_power = tx_power,
|
|
|
.primary_phy = ESP_BLE_GAP_PHY_1M,
|
|
|
.max_skip = 0,
|
|
|
.secondary_phy = ESP_BLE_GAP_PHY_1M,
|
|
|
- .sid = 2,
|
|
|
+ .sid = 0,
|
|
|
.scan_req_notif = false,
|
|
|
};
|
|
|
|
|
|
static esp_ble_gap_ext_adv_params_t ext_adv_params_coded = {
|
|
|
- .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE,
|
|
|
- .interval_min = 0x50,
|
|
|
- .interval_max = 0x50,
|
|
|
+ .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_NONCONN_NONSCANNABLE_UNDIRECTED, //set to unicast advertising
|
|
|
+ .interval_min = 750, //(unsigned int) 0.75*1000/(OUTPUT_RATE_HZ); //allow ble controller to have some room for transmission.
|
|
|
+ .interval_max = 1000, // (unsigned int) 1000/(OUTPUT_RATE_HZ);
|
|
|
.channel_map = ADV_CHNL_ALL,
|
|
|
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
|
|
|
- .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
|
|
+ .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST, // we want unicast non-connectable transmission
|
|
|
.tx_power = tx_power,
|
|
|
- .primary_phy = ESP_BLE_GAP_PHY_1M,
|
|
|
+ .primary_phy = ESP_BLE_GAP_PHY_CODED,
|
|
|
.max_skip = 0,
|
|
|
.secondary_phy = ESP_BLE_GAP_PHY_CODED,
|
|
|
- .sid = 3,
|
|
|
+ .sid = 1,
|
|
|
.scan_req_notif = false,
|
|
|
};
|
|
|
|
|
|
-static BLEMultiAdvertising advert(3);
|
|
|
+static BLEMultiAdvertising advert(2);
|
|
|
|
|
|
bool BLE_TX::init(void)
|
|
|
{
|
|
|
@@ -75,62 +63,44 @@ bool BLE_TX::init(void)
|
|
|
// set as a bluetooth random static address
|
|
|
mac_addr[0] |= 0xc0;
|
|
|
|
|
|
- advert.setAdvertisingParams(0, &ext_adv_params_1M);
|
|
|
+ advert.setAdvertisingParams(0, &legacy_adv_params);
|
|
|
advert.setInstanceAddress(0, mac_addr);
|
|
|
advert.setDuration(0);
|
|
|
|
|
|
- advert.setAdvertisingParams(1, &legacy_adv_params);
|
|
|
- advert.setInstanceAddress(1, mac_addr);
|
|
|
+ advert.setAdvertisingParams(1, &ext_adv_params_coded);
|
|
|
advert.setDuration(1);
|
|
|
-
|
|
|
- advert.setAdvertisingParams(2, &ext_adv_params_coded);
|
|
|
- advert.setDuration(2);
|
|
|
- advert.setInstanceAddress(2, mac_addr);
|
|
|
+ advert.setInstanceAddress(1, mac_addr);
|
|
|
|
|
|
// prefer S8 coding
|
|
|
if (esp_ble_gap_set_prefered_default_phy(ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING, ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING) != ESP_OK) {
|
|
|
Serial.printf("Failed to setup S8 coding\n");
|
|
|
}
|
|
|
|
|
|
+ legacy_msg_counter = 0;
|
|
|
+ longrange_msg_counter = 0;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
#define IMIN(a,b) ((a)<(b)?(a):(b))
|
|
|
|
|
|
-bool BLE_TX::transmit(ODID_UAS_Data &UAS_data)
|
|
|
+bool BLE_TX::transmit_longrange(ODID_UAS_Data &UAS_data)
|
|
|
{
|
|
|
// create a packed UAS data message
|
|
|
+ uint8_t payload[250];
|
|
|
int length = odid_message_build_pack(&UAS_data, payload, 255);
|
|
|
if (length <= 0) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
// setup ASTM header
|
|
|
- const uint8_t header[] { uint8_t(length+5), 0x16, 0xfa, 0xff, 0x0d, uint8_t(msg_counter++) };
|
|
|
+ const uint8_t header[] { uint8_t(length+5), 0x16, 0xfa, 0xff, 0x0d, uint8_t(longrange_msg_counter++) };
|
|
|
|
|
|
// combine header with payload
|
|
|
- memcpy(payload2, header, sizeof(header));
|
|
|
- memcpy(&payload2[sizeof(header)], payload, length);
|
|
|
- int length2 = sizeof(header) + length;
|
|
|
-
|
|
|
- char legacy_name[28] {};
|
|
|
- const char *UAS_ID = (const char *)UAS_data.BasicID[0].UASID;
|
|
|
- const uint8_t ID_len = strlen(UAS_ID);
|
|
|
- const uint8_t ID_tail = IMIN(4, ID_len);
|
|
|
- snprintf(legacy_name, sizeof(legacy_name), "DroneBeacon_%s", &UAS_ID[ID_len-ID_tail]);
|
|
|
-
|
|
|
- memset(legacy_payload, 0, sizeof(legacy_payload));
|
|
|
- const uint8_t legacy_header[] { 0x02, 0x01, 0x06, uint8_t(strlen(legacy_name)+1), ESP_BLE_AD_TYPE_NAME_SHORT};
|
|
|
-
|
|
|
- memcpy(legacy_payload, legacy_header, sizeof(legacy_header));
|
|
|
- memcpy(&legacy_payload[sizeof(legacy_header)], legacy_name, strlen(legacy_name));
|
|
|
- const uint8_t legacy_length = sizeof(legacy_header) + strlen(legacy_name);
|
|
|
-
|
|
|
- // setup advertising data
|
|
|
- advert.setAdvertisingData(0, length2, payload2);
|
|
|
- advert.setScanRspData(1, legacy_length, legacy_payload);
|
|
|
- advert.setAdvertisingData(1, legacy_length, legacy_payload);
|
|
|
- advert.setScanRspData(2, length2, payload2);
|
|
|
+ memcpy(longrange_payload, header, sizeof(header));
|
|
|
+ memcpy(&longrange_payload[sizeof(header)], payload, length);
|
|
|
+ int longrange_length = sizeof(header) + length;
|
|
|
+
|
|
|
+ advert.setAdvertisingData(1, longrange_length, longrange_payload);
|
|
|
|
|
|
// we start advertising when we have the first lot of data to send
|
|
|
if (!started) {
|
|
|
@@ -140,3 +110,105 @@ bool BLE_TX::transmit(ODID_UAS_Data &UAS_data)
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ bool BLE_TX::transmit_legacy(ODID_UAS_Data &UAS_data)
|
|
|
+ {
|
|
|
+ static uint8_t legacy_phase = 0;
|
|
|
+ int legacy_length = 0;
|
|
|
+ // setup ASTM header
|
|
|
+ const uint8_t header[] { 0x1e, 0x16, 0xfa, 0xff, 0x0d, uint8_t(legacy_msg_counter++) };
|
|
|
+ // combine header with payload
|
|
|
+ memset(legacy_payload, 0, sizeof(legacy_payload));
|
|
|
+ memcpy(legacy_payload, header, sizeof(header));
|
|
|
+
|
|
|
+ switch (legacy_phase)
|
|
|
+ {
|
|
|
+ case 0:
|
|
|
+ ODID_Location_encoded location_encoded;
|
|
|
+ memset(&location_encoded, 0, sizeof(location_encoded));
|
|
|
+ if (encodeLocationMessage(&location_encoded, &UAS_data.Location) != ODID_SUCCESS) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&legacy_payload[sizeof(header)], &location_encoded, sizeof(location_encoded));
|
|
|
+ legacy_length = sizeof(header) + sizeof(location_encoded);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 1:
|
|
|
+ ODID_BasicID_encoded basicid_encoded;
|
|
|
+ memset(&basicid_encoded, 0, sizeof(basicid_encoded));
|
|
|
+ if (encodeBasicIDMessage(&basicid_encoded, &UAS_data.BasicID[0]) != ODID_SUCCESS) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&legacy_payload[sizeof(header)], &basicid_encoded, sizeof(basicid_encoded));
|
|
|
+ legacy_length = sizeof(header) + sizeof(basicid_encoded);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 2:
|
|
|
+ ODID_SelfID_encoded selfid_encoded;
|
|
|
+ memset(&selfid_encoded, 0, sizeof(selfid_encoded));
|
|
|
+ if (encodeSelfIDMessage(&selfid_encoded, &UAS_data.SelfID) != ODID_SUCCESS) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&legacy_payload[sizeof(header)], &selfid_encoded, sizeof(selfid_encoded));
|
|
|
+ legacy_length = sizeof(header) + sizeof(selfid_encoded);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 3:
|
|
|
+ ODID_System_encoded system_encoded;
|
|
|
+ memset(&system_encoded, 0, sizeof(system_encoded));
|
|
|
+ if (encodeSystemMessage(&system_encoded, &UAS_data.System) != ODID_SUCCESS) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&legacy_payload[sizeof(header)], &system_encoded, sizeof(system_encoded));
|
|
|
+ legacy_length = sizeof(header) + sizeof(system_encoded);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 4:
|
|
|
+ ODID_OperatorID_encoded operatorid_encoded;
|
|
|
+ memset(&operatorid_encoded, 0, sizeof(operatorid_encoded));
|
|
|
+ if (encodeOperatorIDMessage(&operatorid_encoded, &UAS_data.OperatorID) != ODID_SUCCESS) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&legacy_payload[sizeof(header)], &operatorid_encoded, sizeof(operatorid_encoded));
|
|
|
+ legacy_length = sizeof(header) + sizeof(operatorid_encoded);
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 5: //broadcast BLE name
|
|
|
+ char legacy_name[28] {};
|
|
|
+ const char *UAS_ID = (const char *)UAS_data.BasicID[0].UASID;
|
|
|
+ const uint8_t ID_len = strlen(UAS_ID);
|
|
|
+ const uint8_t ID_tail = IMIN(4, ID_len);
|
|
|
+ snprintf(legacy_name, sizeof(legacy_name), "ArduRemoteID_%s", &UAS_ID[ID_len-ID_tail]);
|
|
|
+
|
|
|
+ memset(legacy_payload, 0, sizeof(legacy_payload));
|
|
|
+ const uint8_t legacy_header_ble_name[] { 0x02, 0x01, 0x06, uint8_t(strlen(legacy_name)+1), ESP_BLE_AD_TYPE_NAME_SHORT};
|
|
|
+
|
|
|
+ memcpy(legacy_payload, legacy_header_ble_name, sizeof(legacy_header_ble_name));
|
|
|
+ memcpy(&legacy_payload[sizeof(legacy_header_ble_name)], legacy_name, strlen(legacy_name) + 1);
|
|
|
+ legacy_length = sizeof(legacy_header_ble_name) + strlen(legacy_name);
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ legacy_phase++;
|
|
|
+ legacy_phase %= 6;
|
|
|
+
|
|
|
+ advert.setAdvertisingData(0, legacy_length, legacy_payload);
|
|
|
+
|
|
|
+ if (!started) {
|
|
|
+ advert.start();
|
|
|
+ }
|
|
|
+ started = true;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|