mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-19 08:17:26 +00:00
Merge branch 'meshtastic:master' into master
This commit is contained in:
commit
3729424505
39
boards/ESP32-S3-WROOM-1-N4.json
Normal file
39
boards/ESP32-S3-WROOM-1-N4.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-D ARDUINO_USB_CDC_ON_BOOT=0",
|
||||
"-D ARDUINO_USB_MSC_ON_BOOT=0",
|
||||
"-D ARDUINO_USB_DFU_ON_BOOT=0",
|
||||
"-D ARDUINO_USB_MODE=0",
|
||||
"-D ARDUINO_RUNNING_CORE=1",
|
||||
"-D ARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "ESP32-S3-WROOM-1-N4"
|
||||
},
|
||||
"connectivity": ["wifi"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "ESP32-S3-WROOM-1-N4 (4 MB Flash, No PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 524288,
|
||||
"maximum_size": 4194304,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
|
||||
"vendor": "Espressif"
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit ecf105f66d182531423b73f4408c53701313c4eb
|
||||
Subproject commit eade2c6befb65a9c46c5d28ae1e8e24c37a1a3d0
|
@ -271,9 +271,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
}
|
||||
break;
|
||||
case INA3221_ADDR:
|
||||
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA3221;
|
||||
break;
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA3221;
|
||||
} else { // Unknown device
|
||||
LOG_INFO("No INA3221 found at address 0x%x\n", (uint8_t)addr.address);
|
||||
}
|
||||
case MCP9808_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||
if (registerValue == 0x0400) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <NodeDB.h>
|
||||
#include <cstdint>
|
||||
#define ONE_DAY 24 * 60 * 60
|
||||
#define ONE_MINUTE_MS 60 * 1000
|
||||
|
||||
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60)
|
||||
|
@ -813,6 +813,7 @@ size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
|
||||
}
|
||||
|
||||
#include "MeshModule.h"
|
||||
#include "Throttle.h"
|
||||
|
||||
/** Update position info for this node based on received position data
|
||||
*/
|
||||
@ -907,8 +908,10 @@ bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p, uint8_t chann
|
||||
powerFSM.trigger(EVENT_NODEDB_UPDATED);
|
||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||
|
||||
// We just changed something important about the user, store our DB
|
||||
saveToDisk(SEGMENT_DEVICESTATE);
|
||||
// We just changed something about the user, store our DB
|
||||
Throttle::execute(
|
||||
&lastNodeDbSave, ONE_MINUTE_MS, []() { nodeDB->saveToDisk(SEGMENT_DEVICESTATE); },
|
||||
[]() { LOG_DEBUG("Deferring NodeDB saveToDisk for now, since we saved less than a minute ago\n"); });
|
||||
}
|
||||
|
||||
return changed;
|
||||
|
@ -150,16 +150,18 @@ class NodeDB
|
||||
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
||||
{
|
||||
if (timeOnly) {
|
||||
LOG_DEBUG("Setting local position time only: time=%i\n", position.time);
|
||||
LOG_DEBUG("Setting local position time only: time=%i timestamp=%i\n", position.time, position.timestamp);
|
||||
localPosition.time = position.time;
|
||||
localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time;
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i\n", position.latitude_i, position.longitude_i,
|
||||
position.time);
|
||||
LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i, timeestamp=%i\n", position.latitude_i,
|
||||
position.longitude_i, position.time, position.timestamp);
|
||||
localPosition = position;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
||||
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
||||
|
||||
|
@ -465,21 +465,22 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
// Publish received message to MQTT if we're not the original transmitter of the packet
|
||||
if (!skipHandle && moduleConfig.mqtt.enabled && getFrom(p) != nodeDB->getNodeNum() && mqtt)
|
||||
mqtt->onSend(*p_encrypted, *p, p->channel);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||
}
|
||||
|
||||
packetPool.release(p_encrypted); // Release the encrypted packet
|
||||
|
||||
// call modules here
|
||||
if (!skipHandle)
|
||||
if (!skipHandle) {
|
||||
MeshModule::callModules(*p, src);
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
// After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet
|
||||
if (decoded && moduleConfig.mqtt.enabled && getFrom(p) != nodeDB->getNodeNum() && mqtt)
|
||||
mqtt->onSend(*p_encrypted, *p, p->channel);
|
||||
#endif
|
||||
}
|
||||
|
||||
packetPool.release(p_encrypted); // Release the encrypted packet
|
||||
}
|
||||
|
||||
void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
||||
|
27
src/mesh/Throttle.cpp
Normal file
27
src/mesh/Throttle.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "Throttle.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/// @brief Execute a function throttled to a minimum interval
|
||||
/// @param lastExecutionMs Pointer to the last execution time in milliseconds
|
||||
/// @param minumumIntervalMs Minimum execution interval in milliseconds
|
||||
/// @param throttleFunc Function to execute if the execution is not deferred
|
||||
/// @param onDefer Default to NULL, execute the function if the execution is deferred
|
||||
/// @return true if the function was executed, false if it was deferred
|
||||
bool Throttle::execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, void (*throttleFunc)(void), void (*onDefer)(void))
|
||||
{
|
||||
if (*lastExecutionMs == 0) {
|
||||
*lastExecutionMs = millis();
|
||||
throttleFunc();
|
||||
return true;
|
||||
}
|
||||
uint32_t now = millis();
|
||||
|
||||
if ((now - *lastExecutionMs) >= minumumIntervalMs) {
|
||||
throttleFunc();
|
||||
*lastExecutionMs = now;
|
||||
return true;
|
||||
} else if (onDefer != NULL) {
|
||||
onDefer();
|
||||
}
|
||||
return false;
|
||||
}
|
9
src/mesh/Throttle.h
Normal file
9
src/mesh/Throttle.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class Throttle
|
||||
{
|
||||
public:
|
||||
static bool execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, void (*func)(void), void (*onDefer)(void) = NULL);
|
||||
};
|
@ -283,6 +283,8 @@ typedef struct _meshtastic_Config_DeviceConfig {
|
||||
bool disable_triple_click;
|
||||
/* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */
|
||||
char tzdef[65];
|
||||
/* If true, disable the default blinking LED (LED_PIN) behavior on the device */
|
||||
bool led_heartbeat_disabled;
|
||||
} meshtastic_Config_DeviceConfig;
|
||||
|
||||
/* Position Config */
|
||||
@ -324,35 +326,30 @@ typedef struct _meshtastic_Config_PositionConfig {
|
||||
/* Power Config\
|
||||
See [Power Config](/docs/settings/config/power) for additional power config details. */
|
||||
typedef struct _meshtastic_Config_PowerConfig {
|
||||
/* If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in
|
||||
we should try to minimize power consumption as much as possible.
|
||||
YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case).
|
||||
Advanced Option */
|
||||
/* Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
|
||||
Don't use this setting if you want to use your device with the phone apps or are using a device without a user button.
|
||||
Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles */
|
||||
bool is_power_saving;
|
||||
/* If non-zero, the device will fully power off this many seconds after external power is removed. */
|
||||
/* Description: If non-zero, the device will fully power off this many seconds after external power is removed. */
|
||||
uint32_t on_battery_shutdown_after_secs;
|
||||
/* Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k)
|
||||
Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation.
|
||||
Should be set to floating point value between 2 and 4
|
||||
Fixes issues on Heltec v2 */
|
||||
https://meshtastic.org/docs/configuration/radio/power/#adc-multiplier-override
|
||||
Should be set to floating point value between 2 and 6 */
|
||||
float adc_multiplier_override;
|
||||
/* Wait Bluetooth Seconds
|
||||
The number of seconds for to wait before turning off BLE in No Bluetooth states
|
||||
0 for default of 1 minute */
|
||||
/* Description: The number of seconds for to wait before turning off BLE in No Bluetooth states
|
||||
Technical Details: ESP32 Only 0 for default of 1 minute */
|
||||
uint32_t wait_bluetooth_secs;
|
||||
/* Super Deep Sleep Seconds
|
||||
While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep
|
||||
for this value (default 1 year) or a button press
|
||||
0 for default of one year */
|
||||
uint32_t sds_secs;
|
||||
/* Light Sleep Seconds
|
||||
In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on
|
||||
ESP32 Only
|
||||
0 for default of 300 */
|
||||
/* Description: In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on
|
||||
Technical Details: ESP32 Only 0 for default of 300 */
|
||||
uint32_t ls_secs;
|
||||
/* Minimum Wake Seconds
|
||||
While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value
|
||||
0 for default of 10 seconds */
|
||||
/* Description: While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value
|
||||
Technical Details: ESP32 Only 0 for default of 10 seconds */
|
||||
uint32_t min_wake_secs;
|
||||
/* I2C address of INA_2XX to use for reading device battery voltage */
|
||||
uint8_t device_battery_ina_address;
|
||||
@ -585,7 +582,7 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
@ -594,7 +591,7 @@ extern "C" {
|
||||
#define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0}
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
@ -615,6 +612,7 @@ extern "C" {
|
||||
#define meshtastic_Config_DeviceConfig_is_managed_tag 9
|
||||
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
|
||||
#define meshtastic_Config_DeviceConfig_tzdef_tag 11
|
||||
#define meshtastic_Config_DeviceConfig_led_heartbeat_disabled_tag 12
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
|
||||
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
||||
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
|
||||
@ -715,7 +713,8 @@ X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
|
||||
X(a, STATIC, SINGULAR, STRING, tzdef, 11)
|
||||
X(a, STATIC, SINGULAR, STRING, tzdef, 11) \
|
||||
X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12)
|
||||
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
|
||||
|
||||
@ -834,7 +833,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
|
||||
#define meshtastic_Config_BluetoothConfig_size 10
|
||||
#define meshtastic_Config_DeviceConfig_size 98
|
||||
#define meshtastic_Config_DeviceConfig_size 100
|
||||
#define meshtastic_Config_DisplayConfig_size 28
|
||||
#define meshtastic_Config_LoRaConfig_size 80
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
|
@ -308,7 +308,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
|
||||
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size
|
||||
#define meshtastic_ChannelFile_size 702
|
||||
#define meshtastic_NodeInfoLite_size 166
|
||||
#define meshtastic_OEMStore_size 3344
|
||||
#define meshtastic_OEMStore_size 3346
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -181,7 +181,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
|
||||
#define meshtastic_LocalConfig_size 535
|
||||
#define meshtastic_LocalConfig_size 537
|
||||
#define meshtastic_LocalModuleConfig_size 663
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -43,7 +43,9 @@ typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* INA3221 3 Channel Voltage / Current Sensor */
|
||||
meshtastic_TelemetrySensorType_INA3221 = 14,
|
||||
/* BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) */
|
||||
meshtastic_TelemetrySensorType_BMP085 = 15
|
||||
meshtastic_TelemetrySensorType_BMP085 = 15,
|
||||
/* RCWL-9620 Doppler Radar Distance Sensor, used for water level detection */
|
||||
meshtastic_TelemetrySensorType_RCWL9620 = 16
|
||||
} meshtastic_TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
@ -78,6 +80,8 @@ typedef struct _meshtastic_EnvironmentMetrics {
|
||||
/* relative scale IAQ value as measured by Bosch BME680 . value 0-500.
|
||||
Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */
|
||||
uint16_t iaq;
|
||||
/* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */
|
||||
float distance;
|
||||
} meshtastic_EnvironmentMetrics;
|
||||
|
||||
/* Power Metrics (voltage / current / etc) */
|
||||
@ -148,8 +152,8 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_BMP085
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_BMP085+1))
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RCWL9620
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RCWL9620+1))
|
||||
|
||||
|
||||
|
||||
@ -159,12 +163,12 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
|
||||
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
|
||||
@ -182,6 +186,7 @@ extern "C" {
|
||||
#define meshtastic_EnvironmentMetrics_voltage_tag 5
|
||||
#define meshtastic_EnvironmentMetrics_current_tag 6
|
||||
#define meshtastic_EnvironmentMetrics_iaq_tag 7
|
||||
#define meshtastic_EnvironmentMetrics_distance_tag 8
|
||||
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
|
||||
#define meshtastic_PowerMetrics_ch1_current_tag 2
|
||||
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
|
||||
@ -223,7 +228,8 @@ X(a, STATIC, SINGULAR, FLOAT, barometric_pressure, 3) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, current, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, iaq, 7)
|
||||
X(a, STATIC, SINGULAR, UINT32, iaq, 7) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, distance, 8)
|
||||
#define meshtastic_EnvironmentMetrics_CALLBACK NULL
|
||||
#define meshtastic_EnvironmentMetrics_DEFAULT NULL
|
||||
|
||||
@ -283,7 +289,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg;
|
||||
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
|
||||
#define meshtastic_AirQualityMetrics_size 72
|
||||
#define meshtastic_DeviceMetrics_size 27
|
||||
#define meshtastic_EnvironmentMetrics_size 34
|
||||
#define meshtastic_EnvironmentMetrics_size 39
|
||||
#define meshtastic_PowerMetrics_size 30
|
||||
#define meshtastic_Telemetry_size 79
|
||||
|
||||
|
@ -4,11 +4,8 @@
|
||||
#include "NodeDB.h"
|
||||
#include "RTC.h"
|
||||
|
||||
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
|
||||
NeighborInfoModule *neighborInfoModule;
|
||||
|
||||
static const char *neighborInfoConfigFile = "/prefs/neighbors.proto";
|
||||
|
||||
/*
|
||||
Prints a single neighbor info packet and associated neighbors
|
||||
Uses LOG_DEBUG, which equates to Console.log
|
||||
@ -30,26 +27,23 @@ NOTE: for debugging only
|
||||
*/
|
||||
void NeighborInfoModule::printNodeDBNeighbors()
|
||||
{
|
||||
int num_neighbors = getNumNeighbors();
|
||||
LOG_DEBUG("Our NodeDB contains %d neighbors\n", num_neighbors);
|
||||
for (int i = 0; i < num_neighbors; i++) {
|
||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||
LOG_DEBUG("Our NodeDB contains %d neighbors\n", neighbors.size());
|
||||
for (size_t i = 0; i < neighbors.size(); i++) {
|
||||
LOG_DEBUG("Node %d: node_id=0x%x, snr=%.2f\n", i, neighbors[i].node_id, neighbors[i].snr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
|
||||
NeighborInfoModule::NeighborInfoModule()
|
||||
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
|
||||
concurrency::OSThread("NeighborInfoModule"), neighbors(neighborState.neighbors),
|
||||
numNeighbors(&neighborState.neighbors_count)
|
||||
concurrency::OSThread("NeighborInfoModule")
|
||||
{
|
||||
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
|
||||
|
||||
if (moduleConfig.neighbor_info.enabled) {
|
||||
isPromiscuous = true; // Update neighbors from all packets
|
||||
this->loadProtoForModule();
|
||||
setIntervalFromNow(35 * 1000);
|
||||
setIntervalFromNow(
|
||||
Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs));
|
||||
} else {
|
||||
LOG_DEBUG("NeighborInfoModule is disabled\n");
|
||||
disable();
|
||||
@ -63,18 +57,17 @@ Assumes that the neighborInfo packet has been allocated
|
||||
*/
|
||||
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
|
||||
{
|
||||
uint my_node_id = nodeDB->getNodeNum();
|
||||
NodeNum my_node_id = nodeDB->getNodeNum();
|
||||
neighborInfo->node_id = my_node_id;
|
||||
neighborInfo->last_sent_by_id = my_node_id;
|
||||
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||
|
||||
int num_neighbors = cleanUpNeighbors();
|
||||
cleanUpNeighbors();
|
||||
|
||||
for (int i = 0; i < num_neighbors; i++) {
|
||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) {
|
||||
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id;
|
||||
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr;
|
||||
for (auto nbr : neighbors) {
|
||||
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (nbr.node_id != my_node_id)) {
|
||||
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = nbr.node_id;
|
||||
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = nbr.snr;
|
||||
// Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over
|
||||
// the mesh
|
||||
neighborInfo->neighbors_count++;
|
||||
@ -85,41 +78,22 @@ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighb
|
||||
}
|
||||
|
||||
/*
|
||||
Remove neighbors from the database that we haven't heard from in a while
|
||||
@returns new number of neighbors
|
||||
Remove neighbors from the database that we haven't heard from in a while
|
||||
*/
|
||||
size_t NeighborInfoModule::cleanUpNeighbors()
|
||||
void NeighborInfoModule::cleanUpNeighbors()
|
||||
{
|
||||
uint32_t now = getTime();
|
||||
int num_neighbors = getNumNeighbors();
|
||||
NodeNum my_node_id = nodeDB->getNodeNum();
|
||||
|
||||
// Find neighbors to remove
|
||||
std::vector<int> indices_to_remove;
|
||||
for (int i = 0; i < num_neighbors; i++) {
|
||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||
for (auto it = neighbors.rbegin(); it != neighbors.rend();) {
|
||||
// We will remove a neighbor if we haven't heard from them in twice the broadcast interval
|
||||
if ((now - dbEntry->last_rx_time > dbEntry->node_broadcast_interval_secs * 2) && (dbEntry->node_id != my_node_id)) {
|
||||
indices_to_remove.push_back(i);
|
||||
if ((now - it->last_rx_time > it->node_broadcast_interval_secs * 2) && (it->node_id != my_node_id)) {
|
||||
LOG_DEBUG("Removing neighbor with node ID 0x%x\n", it->node_id);
|
||||
it = std::vector<meshtastic_Neighbor>::reverse_iterator(
|
||||
neighbors.erase(std::next(it).base())); // Erase the element and update the iterator
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the neighbor list
|
||||
for (uint i = 0; i < indices_to_remove.size(); i++) {
|
||||
int index = indices_to_remove[i];
|
||||
LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id);
|
||||
for (int j = index; j < num_neighbors - 1; j++) {
|
||||
neighbors[j] = neighbors[j + 1];
|
||||
}
|
||||
(*numNeighbors)--;
|
||||
}
|
||||
|
||||
// Save the neighbor list if we removed any neighbors or neighbors were already updated upon receiving a packet
|
||||
if (indices_to_remove.size() > 0 || shouldSave) {
|
||||
saveProtoForModule();
|
||||
}
|
||||
|
||||
return *numNeighbors;
|
||||
}
|
||||
|
||||
/* Send neighbor info to the mesh */
|
||||
@ -143,7 +117,9 @@ Will be used for broadcast.
|
||||
int32_t NeighborInfoModule::runOnce()
|
||||
{
|
||||
bool requestReplies = false;
|
||||
sendNeighborInfo(NODENUM_BROADCAST, requestReplies);
|
||||
if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) {
|
||||
sendNeighborInfo(NODENUM_BROADCAST, requestReplies);
|
||||
}
|
||||
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs);
|
||||
}
|
||||
|
||||
@ -178,10 +154,7 @@ void NeighborInfoModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtas
|
||||
|
||||
void NeighborInfoModule::resetNeighbors()
|
||||
{
|
||||
*numNeighbors = 0;
|
||||
neighborState.neighbors_count = 0;
|
||||
memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors));
|
||||
saveProtoForModule();
|
||||
neighbors.clear();
|
||||
}
|
||||
|
||||
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
|
||||
@ -201,61 +174,36 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
||||
n = nodeDB->getNodeNum();
|
||||
}
|
||||
// look for one in the existing list
|
||||
for (int i = 0; i < (*numNeighbors); i++) {
|
||||
meshtastic_Neighbor *nbr = &neighbors[i];
|
||||
if (nbr->node_id == n) {
|
||||
for (size_t i = 0; i < neighbors.size(); i++) {
|
||||
if (neighbors[i].node_id == n) {
|
||||
// if found, update it
|
||||
nbr->snr = snr;
|
||||
nbr->last_rx_time = getTime();
|
||||
neighbors[i].snr = snr;
|
||||
neighbors[i].last_rx_time = getTime();
|
||||
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
||||
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||
return nbr;
|
||||
neighbors[i].node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||
return &neighbors[i];
|
||||
}
|
||||
}
|
||||
// otherwise, allocate one and assign data to it
|
||||
// TODO: max memory for the database should take neighbors into account, but currently doesn't
|
||||
if (*numNeighbors < MAX_NUM_NEIGHBORS) {
|
||||
(*numNeighbors)++;
|
||||
}
|
||||
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)];
|
||||
new_nbr->node_id = n;
|
||||
new_nbr->snr = snr;
|
||||
new_nbr->last_rx_time = getTime();
|
||||
|
||||
meshtastic_Neighbor new_nbr = meshtastic_Neighbor_init_zero;
|
||||
new_nbr.node_id = n;
|
||||
new_nbr.snr = snr;
|
||||
new_nbr.last_rx_time = getTime();
|
||||
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
||||
new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||
new_nbr.node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||
else // Assume the same broadcast interval as us for the neighbor if we don't know it
|
||||
new_nbr->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||
shouldSave = true; // Save the new neighbor upon next cleanup
|
||||
return new_nbr;
|
||||
}
|
||||
new_nbr.node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||
|
||||
void NeighborInfoModule::loadProtoForModule()
|
||||
{
|
||||
if (nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
|
||||
&meshtastic_NeighborInfo_msg, &neighborState) != LoadFileResult::SUCCESS) {
|
||||
neighborState = meshtastic_NeighborInfo_init_zero;
|
||||
if (neighbors.size() < MAX_NUM_NEIGHBORS) {
|
||||
neighbors.push_back(new_nbr);
|
||||
} else {
|
||||
// If we have too many neighbors, replace the oldest one
|
||||
LOG_WARN("Neighbor DB is full, replacing oldest neighbor\n");
|
||||
neighbors.erase(neighbors.begin());
|
||||
neighbors.push_back(new_nbr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Save the module config to file.
|
||||
*
|
||||
* @return true On success.
|
||||
* @return false On error.
|
||||
*/
|
||||
bool NeighborInfoModule::saveProtoForModule()
|
||||
{
|
||||
bool okay = true;
|
||||
|
||||
#ifdef FS
|
||||
FS.mkdir("/prefs");
|
||||
#endif
|
||||
|
||||
okay &= nodeDB->saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState);
|
||||
if (okay)
|
||||
shouldSave = false;
|
||||
|
||||
return okay;
|
||||
return &neighbors.back();
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
#include "ProtobufModule.h"
|
||||
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
|
||||
|
||||
/*
|
||||
* Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh
|
||||
*/
|
||||
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
|
||||
{
|
||||
meshtastic_Neighbor *neighbors;
|
||||
pb_size_t *numNeighbors;
|
||||
std::vector<meshtastic_Neighbor> neighbors;
|
||||
|
||||
public:
|
||||
/*
|
||||
@ -18,15 +18,7 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
||||
/* Reset neighbor info after clearing nodeDB*/
|
||||
void resetNeighbors();
|
||||
|
||||
bool saveProtoForModule();
|
||||
|
||||
private:
|
||||
bool shouldSave = false; // Whether we should save the neighbor info to flash
|
||||
|
||||
protected:
|
||||
// Note: this holds our local info.
|
||||
meshtastic_NeighborInfo neighborState;
|
||||
|
||||
/*
|
||||
* Called to handle a particular incoming message
|
||||
* @return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
@ -40,10 +32,9 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
||||
uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo);
|
||||
|
||||
/*
|
||||
Remove neighbors from the database that we haven't heard from in a while
|
||||
@returns new number of neighbors
|
||||
Remove neighbors from the database that we haven't heard from in a while
|
||||
*/
|
||||
size_t cleanUpNeighbors();
|
||||
void cleanUpNeighbors();
|
||||
|
||||
/* Allocate a new NeighborInfo packet */
|
||||
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
|
||||
@ -56,22 +47,12 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
||||
*/
|
||||
void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
||||
|
||||
size_t getNumNeighbors() { return *numNeighbors; }
|
||||
|
||||
meshtastic_Neighbor *getNeighborByIndex(size_t x)
|
||||
{
|
||||
assert(x < *numNeighbors);
|
||||
return &neighbors[x];
|
||||
}
|
||||
|
||||
/* update neighbors with subpacket sniffed from network */
|
||||
void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np);
|
||||
|
||||
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
|
||||
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n) override;
|
||||
|
||||
void loadProtoForModule();
|
||||
|
||||
/* Does our periodic broadcast */
|
||||
int32_t runOnce() override;
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include "mesh/compression/unishox2.h"
|
||||
#include <Throttle.h>
|
||||
}
|
||||
|
||||
PositionModule *positionModule;
|
||||
@ -63,11 +64,11 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
||||
}
|
||||
|
||||
// Log packet size and data fields
|
||||
LOG_INFO("POSITION node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
|
||||
"time=%d\n",
|
||||
getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae,
|
||||
p.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp,
|
||||
p.time);
|
||||
LOG_DEBUG("POSITION node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d "
|
||||
"time=%d\n",
|
||||
getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae,
|
||||
p.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp,
|
||||
p.time);
|
||||
|
||||
if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
|
||||
struct timeval tv;
|
||||
@ -222,6 +223,16 @@ meshtastic_MeshPacket *PositionModule::allocAtakPli()
|
||||
return mp;
|
||||
}
|
||||
|
||||
void PositionModule::sendOurPosition()
|
||||
{
|
||||
bool requestReplies = currentGeneration != radioGeneration;
|
||||
currentGeneration = radioGeneration;
|
||||
|
||||
// If we changed channels, ask everyone else for their latest info
|
||||
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
|
||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||
}
|
||||
|
||||
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
||||
{
|
||||
// cancel any not yet sent (now stale) position packets
|
||||
@ -299,12 +310,7 @@ int32_t PositionModule::runOnce()
|
||||
lastGpsLatitude = node->position.latitude_i;
|
||||
lastGpsLongitude = node->position.longitude_i;
|
||||
|
||||
// If we changed channels, ask everyone else for their latest info
|
||||
bool requestReplies = currentGeneration != radioGeneration;
|
||||
currentGeneration = radioGeneration;
|
||||
|
||||
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
|
||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||
sendOurPosition();
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) {
|
||||
sendLostAndFoundText();
|
||||
}
|
||||
@ -314,29 +320,23 @@ int32_t PositionModule::runOnce()
|
||||
|
||||
if (hasValidPosition(node2)) {
|
||||
// The minimum time (in seconds) that would pass before we are able to send a new position packet.
|
||||
const uint32_t minimumTimeThreshold =
|
||||
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||
|
||||
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
||||
uint32_t msSinceLastSend = now - lastGpsSend;
|
||||
|
||||
if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) {
|
||||
bool requestReplies = currentGeneration != radioGeneration;
|
||||
currentGeneration = radioGeneration;
|
||||
if (smartPosition.hasTraveledOverThreshold &&
|
||||
Throttle::execute(
|
||||
&lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); },
|
||||
[]() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) {
|
||||
|
||||
LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
|
||||
"minTimeInterval=%ims)\n",
|
||||
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold,
|
||||
msSinceLastSend, minimumTimeThreshold);
|
||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||
LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
|
||||
"minTimeInterval=%ims)\n",
|
||||
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold,
|
||||
msSinceLastSend, minimumTimeThreshold);
|
||||
|
||||
// Set the current coords as our last ones, after we've compared distance with current and decided to send
|
||||
lastGpsLatitude = node->position.latitude_i;
|
||||
lastGpsLongitude = node->position.longitude_i;
|
||||
|
||||
/* Update lastGpsSend to now. This means if the device is stationary, then
|
||||
getPref_position_broadcast_secs will still apply.
|
||||
*/
|
||||
lastGpsSend = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -396,27 +396,21 @@ void PositionModule::handleNewPosition()
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
||||
// We limit our GPS broadcasts to a max rate
|
||||
uint32_t now = millis();
|
||||
uint32_t msSinceLastSend = now - lastGpsSend;
|
||||
|
||||
if (hasValidPosition(node2)) {
|
||||
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
||||
if (smartPosition.hasTraveledOverThreshold) {
|
||||
bool requestReplies = currentGeneration != radioGeneration;
|
||||
currentGeneration = radioGeneration;
|
||||
|
||||
LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims)\n",
|
||||
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend);
|
||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
||||
uint32_t msSinceLastSend = millis() - lastGpsSend;
|
||||
if (smartPosition.hasTraveledOverThreshold &&
|
||||
Throttle::execute(
|
||||
&lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); },
|
||||
[]() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) {
|
||||
LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
|
||||
"minTimeInterval=%ims)\n",
|
||||
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend,
|
||||
minimumTimeThreshold);
|
||||
|
||||
// Set the current coords as our last ones, after we've compared distance with current and decided to send
|
||||
lastGpsLatitude = node->position.latitude_i;
|
||||
lastGpsLongitude = node->position.longitude_i;
|
||||
|
||||
/* Update lastGpsSend to now. This means if the device is stationary, then
|
||||
getPref_position_broadcast_secs will still apply.
|
||||
*/
|
||||
lastGpsSend = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Default.h"
|
||||
#include "ProtobufModule.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
@ -29,7 +30,8 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
/**
|
||||
* Send our position into the mesh
|
||||
*/
|
||||
void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0);
|
||||
void sendOurPosition(NodeNum dest, bool wantReplies = false, uint8_t channel = 0);
|
||||
void sendOurPosition();
|
||||
|
||||
void handleNewPosition();
|
||||
|
||||
@ -52,6 +54,9 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
meshtastic_MeshPacket *allocAtakPli();
|
||||
uint32_t precision;
|
||||
void sendLostAndFoundText();
|
||||
|
||||
const uint32_t minimumTimeThreshold =
|
||||
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||
};
|
||||
|
||||
struct SmartPosition {
|
||||
|
@ -506,7 +506,7 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0); // unexpected state
|
||||
break; // no need to do anything
|
||||
}
|
||||
return true; // There's no need for others to look at this message.
|
||||
}
|
||||
|
@ -106,20 +106,26 @@ static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
|
||||
|
||||
void NimbleBluetooth::shutdown()
|
||||
{
|
||||
// No measurable power saving for ESP32 during light-sleep(?)
|
||||
#ifndef ARCH_ESP32
|
||||
// Shutdown bluetooth for minimum power draw
|
||||
LOG_INFO("Disable bluetooth\n");
|
||||
// Bluefruit.Advertising.stop();
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->reset();
|
||||
pAdvertising->stop();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Extra power-saving on some devices
|
||||
// Proper shutdown for ESP32. Needs reboot to reverse.
|
||||
void NimbleBluetooth::deinit()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
LOG_INFO("Disable bluetooth until reboot\n");
|
||||
NimBLEDevice::deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Has initial setup been completed
|
||||
bool NimbleBluetooth::isActive()
|
||||
{
|
||||
return bleServer;
|
||||
|
@ -117,8 +117,8 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
|
||||
#elif defined(TLORA_T3S3_V1)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
|
||||
#elif defined(CDEBYTE_ELORA_S3)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_ELORA_S3
|
||||
#elif defined(CDEBYTE_EORA_S3)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_EORA_S3
|
||||
#elif defined(BETAFPV_2400_TX)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX
|
||||
#elif defined(NANO_G1_EXPLORER)
|
||||
@ -127,6 +127,10 @@
|
||||
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX
|
||||
#elif defined(PICOMPUTER_S3)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3
|
||||
#elif defined(HELTEC_HT62)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
|
||||
#elif defined(EBYTE_ESP32_S3)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_EBYTE_ESP32_S3
|
||||
#elif defined(ESP32_S3_PICO)
|
||||
#define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO
|
||||
#elif defined(SENSELORA_S3)
|
||||
|
@ -30,9 +30,10 @@ void setBluetoothEnable(bool enable)
|
||||
}
|
||||
if (enable && !nimbleBluetooth->isActive()) {
|
||||
nimbleBluetooth->setup();
|
||||
} else if (!enable) {
|
||||
nimbleBluetooth->shutdown();
|
||||
}
|
||||
// For ESP32, no way to recover from bluetooth shutdown without reboot
|
||||
// BLE advertising automatically stops when MCU enters light-sleep(?)
|
||||
// For deep-sleep, shutdown hardware with nimbleBluetooth->deinit(). Requires reboot to reverse
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -178,18 +178,31 @@ void portduinoSetup()
|
||||
settingsMap[displayPanel] = st7735;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
||||
settingsMap[displayPanel] = st7735s;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7796")
|
||||
settingsMap[displayPanel] = st7796;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341")
|
||||
settingsMap[displayPanel] = ili9341;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9488")
|
||||
settingsMap[displayPanel] = ili9488;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "HX8357D")
|
||||
settingsMap[displayPanel] = hx8357d;
|
||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "X11")
|
||||
settingsMap[displayPanel] = x11;
|
||||
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
|
||||
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
||||
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
||||
settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1);
|
||||
settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
|
||||
settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1);
|
||||
settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
|
||||
settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as<int>(-1);
|
||||
settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as<int>(-1);
|
||||
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
||||
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
||||
settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
|
||||
settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
|
||||
settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
|
||||
settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
|
||||
if (yamlConfig["Display"]["spidev"]) {
|
||||
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
||||
}
|
||||
@ -200,8 +213,14 @@ void portduinoSetup()
|
||||
settingsMap[touchscreenModule] = xpt2046;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
||||
settingsMap[touchscreenModule] = stmpe610;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911")
|
||||
settingsMap[touchscreenModule] = gt911;
|
||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06")
|
||||
settingsMap[touchscreenModule] = ft5x06;
|
||||
settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
|
||||
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as<int>(-1);
|
||||
settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000);
|
||||
settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
|
||||
if (yamlConfig["Touchscreen"]["spidev"]) {
|
||||
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
||||
}
|
||||
|
@ -21,16 +21,23 @@ enum configNames {
|
||||
touchscreenModule,
|
||||
touchscreenCS,
|
||||
touchscreenIRQ,
|
||||
touchscreenBusFrequency,
|
||||
touchscreenRotate,
|
||||
touchscreenspidev,
|
||||
displayspidev,
|
||||
displayBusFrequency,
|
||||
displayPanel,
|
||||
displayWidth,
|
||||
displayHeight,
|
||||
displayCS,
|
||||
displayDC,
|
||||
displayRGBOrder,
|
||||
displayBacklight,
|
||||
displayBacklightPWMChannel,
|
||||
displayBacklightInvert,
|
||||
displayReset,
|
||||
displayRotate,
|
||||
displayOffsetRotate,
|
||||
displayOffsetX,
|
||||
displayOffsetY,
|
||||
displayInvert,
|
||||
@ -41,8 +48,8 @@ enum configNames {
|
||||
webserverrootpath,
|
||||
maxnodes
|
||||
};
|
||||
enum { no_screen, st7789, st7735, st7735s, ili9341 };
|
||||
enum { no_touchscreen, xpt2046, stmpe610 };
|
||||
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d };
|
||||
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
||||
enum { level_error, level_warn, level_info, level_debug };
|
||||
|
||||
extern std::map<configNames, int> settingsMap;
|
||||
|
@ -157,6 +157,10 @@ void initDeepSleep()
|
||||
for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) {
|
||||
if (rtc_gpio_is_valid_gpio((gpio_num_t)i))
|
||||
rtc_gpio_hold_dis((gpio_num_t)i);
|
||||
|
||||
// ESP32 (original)
|
||||
else if (GPIO_IS_VALID_OUTPUT_GPIO((gpio_num_t)i))
|
||||
gpio_hold_dis((gpio_num_t)i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -207,9 +211,10 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
|
||||
// esp_wifi_stop();
|
||||
waitEnterSleep(skipPreflight);
|
||||
|
||||
#ifdef NIMBLE_DEINIT_FOR_DEEPSLEEP
|
||||
// Extra power saving on some devices
|
||||
nimbleBluetooth->deinit();
|
||||
#ifdef ARCH_ESP32
|
||||
// Full shutdown of bluetooth hardware
|
||||
if (nimbleBluetooth)
|
||||
nimbleBluetooth->deinit();
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
@ -258,14 +263,17 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
|
||||
}
|
||||
#ifdef BUTTON_PIN
|
||||
// Avoid leakage through button pin
|
||||
pinMode(BUTTON_PIN, INPUT);
|
||||
gpio_hold_en((gpio_num_t)BUTTON_PIN);
|
||||
if (GPIO_IS_VALID_OUTPUT_GPIO(BUTTON_PIN)) {
|
||||
pinMode(BUTTON_PIN, INPUT);
|
||||
gpio_hold_en((gpio_num_t)BUTTON_PIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
// LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep
|
||||
pinMode(LORA_CS, OUTPUT);
|
||||
digitalWrite(LORA_CS, HIGH);
|
||||
gpio_hold_en((gpio_num_t)LORA_CS);
|
||||
if (GPIO_IS_VALID_OUTPUT_GPIO(LORA_CS)) {
|
||||
// LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep
|
||||
pinMode(LORA_CS, OUTPUT);
|
||||
digitalWrite(LORA_CS, HIGH);
|
||||
gpio_hold_en((gpio_num_t)LORA_CS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
|
37
variants/EBYTE_ESP32-S3/pins_arduino.h
Normal file
37
variants/EBYTE_ESP32-S3/pins_arduino.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Need this file for ESP32-S3
|
||||
// No need to modify this file, changes to pins imported from variant.h
|
||||
// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h
|
||||
|
||||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <variant.h>
|
||||
|
||||
#define USB_VID 0x303a
|
||||
#define USB_PID 0x1001
|
||||
|
||||
#define EXTERNAL_NUM_INTERRUPTS 46
|
||||
#define NUM_DIGITAL_PINS 48
|
||||
#define NUM_ANALOG_INPUTS 20
|
||||
|
||||
#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
|
||||
#define digitalPinToInterrupt(p) \
|
||||
(((p) < 48) ? (p) : -1) // Maybe it should be <= 48 but this is from a trustworthy source so it is likely correct
|
||||
#define digitalPinHasPWM(p) (p < 46)
|
||||
|
||||
// Serial
|
||||
static const uint8_t TX = UART_TX;
|
||||
static const uint8_t RX = UART_RX;
|
||||
|
||||
// Default SPI will be mapped to Radio
|
||||
static const uint8_t SS = LORA_CS;
|
||||
static const uint8_t SCK = LORA_SCK;
|
||||
static const uint8_t MOSI = LORA_MOSI;
|
||||
static const uint8_t MISO = LORA_MISO;
|
||||
|
||||
// The default Wire will be mapped to PMU and RTC
|
||||
static const uint8_t SCL = I2C_SCL;
|
||||
static const uint8_t SDA = I2C_SDA;
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
9
variants/EBYTE_ESP32-S3/platformio.ini
Normal file
9
variants/EBYTE_ESP32-S3/platformio.ini
Normal file
@ -0,0 +1,9 @@
|
||||
[env:EBYTE_ESP32-S3]
|
||||
extends = esp32s3_base
|
||||
; board assumes the lowest spec WROOM module: 4 MB (Quad SPI) Flash, No PSRAM
|
||||
board = ESP32-S3-WROOM-1-N4
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-D EBYTE_ESP32_S3
|
||||
-I variants/EBYTE_ESP32-S3
|
193
variants/EBYTE_ESP32-S3/variant.h
Normal file
193
variants/EBYTE_ESP32-S3/variant.h
Normal file
@ -0,0 +1,193 @@
|
||||
// Supporting information: https://github.com/S5NC/EBYTE_ESP32-S3/
|
||||
|
||||
// Originally developed for E22-900M30S with ESP32-S3-WROOM-1-N4
|
||||
// NOTE: Uses ESP32-S3-WROOM-1-N4.json in boards folder (via platformio.ini board field), assumes 4 MB (quad SPI) flash, no PSRAM
|
||||
|
||||
// FIXME: implement SX12 module type autodetection and have setup for each case (add E32 support)
|
||||
// E32 has same pinout except having extra pins. I assume that the GND on it is connected internally to other GNDs so it is not a
|
||||
// problem to NC the extra GND pins.
|
||||
|
||||
// For each EBYTE module pin in this section, provide the pin number of the ESP32-S3 you connected it to
|
||||
// The ESP32-S3 is great because YOU CAN USE PRACTICALLY ANY PINS for the connections, but avoid some pins (such as on the WROOM
|
||||
// modules the following): strapping pins (except 0 as a user button input as it already has a pulldown resistor in typical
|
||||
// application schematic) (0, 3, 45, 46), USB-reserved (19, 20), and pins which aren't present on the WROOM-2 module for
|
||||
// compatiblity as it uses octal SPI, or are likely connected internally in either WROOM version (26-37), and avoid pins whose
|
||||
// voltages are set by the SPI voltage (47, 48), and pins that don't exist (22-25) You can ALSO set the SPI pins (SX126X_CS,
|
||||
// SX126X_SCK, SX126X_MISO, SX126X_MOSI) to any pin with the ESP32-S3 due to \ GPIO Matrix / IO MUX / RTC IO MUX \, and also the
|
||||
// serial pins, but this isn't recommended for Serial0 as the WROOM modules have a 499 Ohm resistor on U0TXD (to reduce harmonics
|
||||
// but also acting as a sort of protection)
|
||||
|
||||
// We have many free pins on the ESP32-S3-WROOM-X-Y module, perhaps it is best to use one of its pins to control TXEN, and use
|
||||
// DIO2 as an extra interrupt, but right now Meshtastic does not benefit from having another interrupt pin available.
|
||||
|
||||
// Adding two 0-ohm links on your PCB design so that you can choose between the two modes for controlling the E22's TXEN would
|
||||
// enable future software to make the most of an extra available interrupt pin
|
||||
|
||||
// Possible improvement: can add extremely low resistance MOSFET to physically toggle power to E22 module when in full sleep (not
|
||||
// waiting for interrupt)?
|
||||
|
||||
// PA stands for Power Amplifier, used when transmitting to increase output power
|
||||
// LNA stands for Low Noise Amplifier, used when \ listening for / receiving \ data to increase sensitivity
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Have custom connections or functionality? Configure them in this section //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SX126X_CS 14 // EBYTE module's NSS pin // FIXME: rename to SX126X_SS
|
||||
#define LORA_SCK 21 // EBYTE module's SCK pin
|
||||
#define LORA_MOSI 38 // EBYTE module's MOSI pin
|
||||
#define LORA_MISO 39 // EBYTE module's MISO pin
|
||||
#define SX126X_RESET 40 // EBYTE module's NRST pin
|
||||
#define SX126X_BUSY 41 // EBYTE module's BUSY pin
|
||||
#define SX126X_DIO1 42 // EBYTE module's DIO1 pin
|
||||
// We don't define a pin for SX126X_DIO2 as Meshtastic doesn't use it as an interrupt output, so it is never connected to an MCU
|
||||
// pin! Also E22 module datasheets say not to connect it to an MCU pin.
|
||||
// We don't define a pin for SX126X_DIO3 as Meshtastic doesn't use it as an interrupt output, so it is never connected to an MCU
|
||||
// pin! Also E22 module datasheets say to use it as the TCXO's reference voltage.
|
||||
// E32 module (which uses SX1276) may not have ability to set TCXO voltage using a DIO pin.
|
||||
|
||||
// The radio module needs to be told whether to enable RX mode or TX mode. Each radio module takes different actions based on
|
||||
// these values, but generally the path from the antenna to SX1262 is changed from signal output to signal input. Also, if there
|
||||
// are LNAs (Low-Noise Amplifiers) or PAs (Power Amplifiers) in the output or input paths, their power is also controlled by
|
||||
// these pins. You should never have both TXEN and RXEN set high, this can cause problems for some radio modules, and is
|
||||
// commonly referred to as 'undefined behaviour' in datasheets. For the SX1262, you shouldn't connect DIO2 to the MCU. DIO2 is
|
||||
// an output only, and can be controlled via SPI instructions, the use for this is to save an MCU pin by using the DIO2 pin to
|
||||
// control the RF switching mode.
|
||||
|
||||
// Choose ONLY ONE option from below, comment in/out the '/*'s and '*/'s
|
||||
// SX126X_TXEN is the E22's [SX1262's] TXEN pin, SX126X_RXEN is the E22's [SX1262's] RXEN pin
|
||||
|
||||
// Option 1: E22's TXEN pin connected to E22's DIO2 pin, E22's RXEN pin connected to NEGATED output of E22's DIO2 pin (more
|
||||
// expensive option hardware-wise, is the 'most proper' way, removes need for routing one/two traces from MCU to RF switching
|
||||
// pins), however you can't have E22 in low-power 'sleep' mode (TXEN and RXEN both low cannot be achieved this this option).
|
||||
/*
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_RXEN RADIOLIB_NC
|
||||
*/
|
||||
|
||||
// Option 2: E22's TXEN pin connected to E22's DIO2 pin, E22's RXEN pin connected to MCU pin (cheaper option hardware-wise,
|
||||
// removes need for routing another trace from MCU to an RF switching pin).
|
||||
// /*
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_RXEN 10
|
||||
// */
|
||||
|
||||
// Option 3: E22's TXEN pin connected to MCU pin, E22's RXEN pin connected to MCU pin (cheaper option hardware-wise, allows for
|
||||
// ramping up PA before transmission (add/expand on feature yourself in RadioLib) if PA takes a while to stabilise)
|
||||
// Don't define DIO2_AS_RF_SWITCH because we only use DIO2 or an MCU pin mutually exclusively to connect to E22's TXEN (to prevent
|
||||
// a short if they are both connected at the same time (suboptimal PCB design) and there's a slight non-neglibible delay and/or
|
||||
// voltage difference between DIO2 and TXEN). Can use DIO2 as an IRQ (but not in Meshtastic at the moment).
|
||||
/*
|
||||
#define SX126X_TXEN 9
|
||||
#define SX126X_RXEN 10
|
||||
*/
|
||||
|
||||
// (NOT RECOMMENDED, if need to ramp up PA before transmission, better to use option 3)
|
||||
// Option 4: E22's TXEN pin connected to MCU pin, E22's RXEN pin connected to NEGATED output of E22's DIO2 pin (more expensive
|
||||
// option hardware-wise, allows for ramping up PA before transmission (add/expand on feature yourself in RadioLib) if PA takes
|
||||
// a while to stabilise, removes need for routing another trace from MCU to an RF switching pin, however may mean if in
|
||||
// RadioLib you don't tell DIO2 to go high to indicate transmission (so the negated output goes to RXEN to turn the LNA off)
|
||||
// then you may end up enabling E22's TXEN and RXEN pins at the same time whilst you ramp up the PA which is not ideal,
|
||||
// changing DIO2's switching advance in RadioLib may not even be possible, may be baked into the SX126x).
|
||||
/*
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_TXEN 9
|
||||
#define SX126X_RXEN RADIOLIB_NC
|
||||
*/
|
||||
|
||||
// Status
|
||||
#define LED_PIN 1
|
||||
#define LED_INVERTED 0
|
||||
// External notification
|
||||
// FIXME: Check if EXT_NOTIFY_OUT actualy has any effect and removes the need for setting the external notication pin in the
|
||||
// app/preferences
|
||||
#define EXT_NOTIFY_OUT 2 // The GPIO pin that acts as the external notification output (here we connect an LED to it)
|
||||
// Buzzer
|
||||
#define PIN_BUZZER 11
|
||||
// Buttons
|
||||
#define BUTTON_PIN 0 // Use the BOOT button as the user button
|
||||
// I2C
|
||||
#define I2C_SCL 18
|
||||
#define I2C_SDA 8
|
||||
// UART
|
||||
#define UART_TX 43
|
||||
#define UART_RX 44
|
||||
|
||||
// Power
|
||||
// Outputting 22dBm from SX1262 results in ~30dBm E22-900M30S output (module only uses last stage of the YP2233W PA)
|
||||
// Respect local regulations! If your E22-900M30S outputs the advertised 30 dBm and you use a 6 dBi antenna, you are at the
|
||||
// equivalent of 36 EIRP (Effective Isotropic Radiated Power), which in this case is the limit for non-HAM users in the US (4W
|
||||
// EIRP, at SPECIFIC frequencies).
|
||||
// In the EU (and UK), as of now, you are allowed 27 dBm ERP which is 29.15 EIRP.
|
||||
// https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022D0180
|
||||
// https://www.legislation.gov.uk/uksi/1999/930/schedule/6/made
|
||||
// To respect the 29.15 dBm EIRP (at SPECIFIC frequencies, others are lower) EU limit with a 2.5 dBi gain antenna, consulting
|
||||
// https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/power%20testing.txt, assuming 0.1 dBm insertion loss, output 20 dBm from the
|
||||
// E22-900M30S's SX1262. It is worth noting that if you are in this situation and don't have a HAM license, you may be better off
|
||||
// with a lower gain antenna, and output the difference as a higher total power input into the antenna, as your EIRP would be the
|
||||
// same, but you would get a wider angle of coverage. Also take insertion loss and possibly VSWR into account
|
||||
// (https://www.everythingrf.com/tech-resources/vswr). Please check regulations yourself and check airtime, usage (for example
|
||||
// whether you are airborne), frequency, and power laws.
|
||||
#define SX126X_MAX_POWER 22 // SX126xInterface.cpp defaults to 22 if not defined, but here we define it for good practice
|
||||
|
||||
// Display
|
||||
// FIXME: change behavior in src to default to not having screen if is undefined
|
||||
// FIXME: remove 0/1 option for HAS_SCREEN in src, change to being defined or not
|
||||
// FIXME: check if it actually causes a crash when not specifiying that a display isn't present
|
||||
#define HAS_SCREEN 0 // Assume no screen present by default to prevent crash...
|
||||
|
||||
// GPS
|
||||
// FIXME: unsure what to define HAS_GPS as if GPS isn't always present
|
||||
#define HAS_GPS 1 // Don't need to set this to 0 to prevent a crash as it doesn't crash if GPS not found, will probe by default
|
||||
#define PIN_GPS_EN 15
|
||||
#define GPS_EN_ACTIVE 1
|
||||
#define GPS_TX_PIN 16
|
||||
#define GPS_RX_PIN 17
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// You should have no need to modify the code below, nor in pins_arduino.h //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define USE_SX1262 // E22-900M30S, E22-900M22S, and E22-900MM22S (not E220!) use SX1262
|
||||
#define USE_SX1268 // E22-400M30S, E22-400M33S, E22-400M22S, and E22-400MM22S use SX1268
|
||||
|
||||
// The below isn't needed as we directly define SX126X_TXEN and SX126X_RXEN instead of using proxies E22_TXEN and E22_RXEN
|
||||
/*
|
||||
// FALLBACK: If somehow E22_TXEN isn't defined or clearly isn't a valid pin number, set it to RADIOLIB_NC to avoid SX126X_TXEN
|
||||
being defined but having no value #if (!defined(E22_TXEN) || !(0 <= E22_TXEN && E22_TXEN <= 48)) #define E22_TXEN RADIOLIB_NC
|
||||
#endif
|
||||
// FALLBACK: If somehow E22_RXEN isn't defined or clearly isn't a valid pin number, set it to RADIOLIB_NC to avoid SX126X_RXEN
|
||||
being defined but having no value #if (!defined(E22_RXEN) || !(0 <= E22_RXEN && E22_RXEN <= 48)) #define E22_RXEN RADIOLIB_NC
|
||||
#endif
|
||||
#define SX126X_TXEN E22_TXEN
|
||||
#define SX126X_RXEN E22_RXEN
|
||||
*/
|
||||
|
||||
// E22 series TCXO voltage is 1.8V per https://www.ebyte.com/en/pdf-down.aspx?id=781 (source
|
||||
// https://github.com/jgromes/RadioLib/issues/12#issuecomment-520695575), so set it as such
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
#define LORA_CS SX126X_CS // FIXME: for some reason both are used in /src
|
||||
|
||||
// Many of the below values would only be used if USE_RF95 was defined, but it's not as we aren't actually using an RF95, just
|
||||
// that the 4 pins above are named like it If they aren't used they don't need to be defined and doing so cause confusion to those
|
||||
// adapting this file LORA_RESET value is never used in src (as we are not using RF95), so no need to define LORA_DIO0 is not used
|
||||
// in src (as we are not using RF95) as SX1262 does not have it per SX1262 datasheet, so no need to define
|
||||
// FIXME: confirm that the linked lines below are actually only called when using the SX126x or SX128x and no other modules
|
||||
// then use SX126X_DIO1 and SX128X_DIO1 respectively for that purpose, removing the need for RF95-style LORA_* definitions when
|
||||
// the RF95 isn't used
|
||||
#define LORA_DIO1 \
|
||||
SX126X_DIO1 // The old name is used in
|
||||
// https://github.com/meshtastic/firmware/blob/7eff5e7bcb2084499b723c5e3846c15ee089e36d/src/sleep.cpp#L298, so
|
||||
// must also define the old name
|
||||
// LORA_DIO2 value is never used in src (as we are not using RF95), so no need to define, and if DIO2_AS_RF_SWITCH is set then it
|
||||
// cannot serve any extra function even if requested to LORA_DIO3 value is never used in src (as we are not using RF95), so no
|
||||
// need to define, and DIO3_AS_TCXO_AT_1V8 is set so it cannot serve any extra function even if requested to (from 13.3.2.1
|
||||
// DioxMask in SX1262 datasheet: Note that if DIO2 or DIO3 are used to control the RF Switch or the TCXO, the IRQ will not be
|
||||
// generated even if it is mapped to the pins.)
|
@ -55,6 +55,3 @@
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
// Power management
|
||||
#define NIMBLE_DEINIT_FOR_DEEPSLEEP // Required to reach manufacturers claim of 18uA
|
||||
|
@ -55,6 +55,3 @@
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
|
||||
// Power management
|
||||
#define NIMBLE_DEINIT_FOR_DEEPSLEEP // Required to reach manufacturers claim of 18uA
|
||||
|
@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 3
|
||||
build = 6
|
||||
build = 7
|
||||
|
Loading…
Reference in New Issue
Block a user