mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-20 08:41:41 +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;
|
break;
|
||||||
case INA3221_ADDR:
|
case INA3221_ADDR:
|
||||||
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
|
||||||
type = INA3221;
|
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||||
break;
|
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:
|
case MCP9808_ADDR:
|
||||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2);
|
||||||
if (registerValue == 0x0400) {
|
if (registerValue == 0x0400) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <NodeDB.h>
|
#include <NodeDB.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#define ONE_DAY 24 * 60 * 60
|
#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_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)
|
||||||
#define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 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 "MeshModule.h"
|
||||||
|
#include "Throttle.h"
|
||||||
|
|
||||||
/** Update position info for this node based on received position data
|
/** 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);
|
powerFSM.trigger(EVENT_NODEDB_UPDATED);
|
||||||
notifyObservers(true); // Force an update whether or not our node counts have changed
|
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||||
|
|
||||||
// We just changed something important about the user, store our DB
|
// We just changed something about the user, store our DB
|
||||||
saveToDisk(SEGMENT_DEVICESTATE);
|
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;
|
return changed;
|
||||||
|
@ -150,16 +150,18 @@ class NodeDB
|
|||||||
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
||||||
{
|
{
|
||||||
if (timeOnly) {
|
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.time = position.time;
|
||||||
|
localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i\n", position.latitude_i, position.longitude_i,
|
LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i, timeestamp=%i\n", position.latitude_i,
|
||||||
position.time);
|
position.longitude_i, position.time, position.timestamp);
|
||||||
localPosition = position;
|
localPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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
|
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||||
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
||||||
|
|
||||||
|
@ -465,21 +465,22 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
|||||||
cancelSending(p->from, p->id);
|
cancelSending(p->from, p->id);
|
||||||
skipHandle = true;
|
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 {
|
} else {
|
||||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
packetPool.release(p_encrypted); // Release the encrypted packet
|
|
||||||
|
|
||||||
// call modules here
|
// call modules here
|
||||||
if (!skipHandle)
|
if (!skipHandle) {
|
||||||
MeshModule::callModules(*p, src);
|
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)
|
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;
|
bool disable_triple_click;
|
||||||
/* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */
|
/* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */
|
||||||
char tzdef[65];
|
char tzdef[65];
|
||||||
|
/* If true, disable the default blinking LED (LED_PIN) behavior on the device */
|
||||||
|
bool led_heartbeat_disabled;
|
||||||
} meshtastic_Config_DeviceConfig;
|
} meshtastic_Config_DeviceConfig;
|
||||||
|
|
||||||
/* Position Config */
|
/* Position Config */
|
||||||
@ -324,35 +326,30 @@ typedef struct _meshtastic_Config_PositionConfig {
|
|||||||
/* Power Config\
|
/* Power Config\
|
||||||
See [Power Config](/docs/settings/config/power) for additional power config details. */
|
See [Power Config](/docs/settings/config/power) for additional power config details. */
|
||||||
typedef struct _meshtastic_Config_PowerConfig {
|
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
|
/* Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio.
|
||||||
we should try to minimize power consumption as much as possible.
|
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.
|
||||||
YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case).
|
Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles */
|
||||||
Advanced Option */
|
|
||||||
bool is_power_saving;
|
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;
|
uint32_t on_battery_shutdown_after_secs;
|
||||||
/* Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k)
|
/* 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.
|
Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation.
|
||||||
Should be set to floating point value between 2 and 4
|
https://meshtastic.org/docs/configuration/radio/power/#adc-multiplier-override
|
||||||
Fixes issues on Heltec v2 */
|
Should be set to floating point value between 2 and 6 */
|
||||||
float adc_multiplier_override;
|
float adc_multiplier_override;
|
||||||
/* Wait Bluetooth Seconds
|
/* Description: The number of seconds for to wait before turning off BLE in No Bluetooth states
|
||||||
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 */
|
||||||
0 for default of 1 minute */
|
|
||||||
uint32_t wait_bluetooth_secs;
|
uint32_t wait_bluetooth_secs;
|
||||||
/* Super Deep Sleep Seconds
|
/* Super Deep Sleep Seconds
|
||||||
While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep
|
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
|
for this value (default 1 year) or a button press
|
||||||
0 for default of one year */
|
0 for default of one year */
|
||||||
uint32_t sds_secs;
|
uint32_t sds_secs;
|
||||||
/* Light Sleep Seconds
|
/* Description: In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on
|
||||||
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 */
|
||||||
ESP32 Only
|
|
||||||
0 for default of 300 */
|
|
||||||
uint32_t ls_secs;
|
uint32_t ls_secs;
|
||||||
/* Minimum Wake 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
|
||||||
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 */
|
||||||
0 for default of 10 seconds */
|
|
||||||
uint32_t min_wake_secs;
|
uint32_t min_wake_secs;
|
||||||
/* I2C address of INA_2XX to use for reading device battery voltage */
|
/* I2C address of INA_2XX to use for reading device battery voltage */
|
||||||
uint8_t device_battery_ina_address;
|
uint8_t device_battery_ina_address;
|
||||||
@ -585,7 +582,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Initializer values for message structs */
|
/* Initializer values for message structs */
|
||||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
#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_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_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, ""}
|
#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_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_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
#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_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_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, ""}
|
#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_is_managed_tag 9
|
||||||
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
|
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
|
||||||
#define meshtastic_Config_DeviceConfig_tzdef_tag 11
|
#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_secs_tag 1
|
||||||
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
|
||||||
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
|
#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, double_tap_as_button_press, 8) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
|
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
|
||||||
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
|
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_CALLBACK NULL
|
||||||
#define meshtastic_Config_DeviceConfig_DEFAULT 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) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
|
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
|
||||||
#define meshtastic_Config_BluetoothConfig_size 10
|
#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_DisplayConfig_size 28
|
||||||
#define meshtastic_Config_LoRaConfig_size 80
|
#define meshtastic_Config_LoRaConfig_size 80
|
||||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
#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_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size
|
||||||
#define meshtastic_ChannelFile_size 702
|
#define meshtastic_ChannelFile_size 702
|
||||||
#define meshtastic_NodeInfoLite_size 166
|
#define meshtastic_NodeInfoLite_size 166
|
||||||
#define meshtastic_OEMStore_size 3344
|
#define meshtastic_OEMStore_size 3346
|
||||||
#define meshtastic_PositionLite_size 28
|
#define meshtastic_PositionLite_size 28
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -181,7 +181,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
|||||||
|
|
||||||
/* Maximum encoded size of messages (where known) */
|
/* Maximum encoded size of messages (where known) */
|
||||||
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size
|
#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
|
#define meshtastic_LocalModuleConfig_size 663
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -43,7 +43,9 @@ typedef enum _meshtastic_TelemetrySensorType {
|
|||||||
/* INA3221 3 Channel Voltage / Current Sensor */
|
/* INA3221 3 Channel Voltage / Current Sensor */
|
||||||
meshtastic_TelemetrySensorType_INA3221 = 14,
|
meshtastic_TelemetrySensorType_INA3221 = 14,
|
||||||
/* BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) */
|
/* 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;
|
} meshtastic_TelemetrySensorType;
|
||||||
|
|
||||||
/* Struct definitions */
|
/* Struct definitions */
|
||||||
@ -78,6 +80,8 @@ typedef struct _meshtastic_EnvironmentMetrics {
|
|||||||
/* relative scale IAQ value as measured by Bosch BME680 . value 0-500.
|
/* 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. */
|
Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */
|
||||||
uint16_t iaq;
|
uint16_t iaq;
|
||||||
|
/* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */
|
||||||
|
float distance;
|
||||||
} meshtastic_EnvironmentMetrics;
|
} meshtastic_EnvironmentMetrics;
|
||||||
|
|
||||||
/* Power Metrics (voltage / current / etc) */
|
/* Power Metrics (voltage / current / etc) */
|
||||||
@ -148,8 +152,8 @@ extern "C" {
|
|||||||
|
|
||||||
/* Helper constants for enums */
|
/* Helper constants for enums */
|
||||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_BMP085
|
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RCWL9620
|
||||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_BMP085+1))
|
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RCWL9620+1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -159,12 +163,12 @@ extern "C" {
|
|||||||
|
|
||||||
/* Initializer values for message structs */
|
/* Initializer values for message structs */
|
||||||
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0}
|
#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_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_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_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
|
||||||
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0}
|
#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_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_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}}
|
#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_voltage_tag 5
|
||||||
#define meshtastic_EnvironmentMetrics_current_tag 6
|
#define meshtastic_EnvironmentMetrics_current_tag 6
|
||||||
#define meshtastic_EnvironmentMetrics_iaq_tag 7
|
#define meshtastic_EnvironmentMetrics_iaq_tag 7
|
||||||
|
#define meshtastic_EnvironmentMetrics_distance_tag 8
|
||||||
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
|
#define meshtastic_PowerMetrics_ch1_voltage_tag 1
|
||||||
#define meshtastic_PowerMetrics_ch1_current_tag 2
|
#define meshtastic_PowerMetrics_ch1_current_tag 2
|
||||||
#define meshtastic_PowerMetrics_ch2_voltage_tag 3
|
#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, gas_resistance, 4) \
|
||||||
X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \
|
X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \
|
||||||
X(a, STATIC, SINGULAR, FLOAT, current, 6) \
|
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_CALLBACK NULL
|
||||||
#define meshtastic_EnvironmentMetrics_DEFAULT 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_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
|
||||||
#define meshtastic_AirQualityMetrics_size 72
|
#define meshtastic_AirQualityMetrics_size 72
|
||||||
#define meshtastic_DeviceMetrics_size 27
|
#define meshtastic_DeviceMetrics_size 27
|
||||||
#define meshtastic_EnvironmentMetrics_size 34
|
#define meshtastic_EnvironmentMetrics_size 39
|
||||||
#define meshtastic_PowerMetrics_size 30
|
#define meshtastic_PowerMetrics_size 30
|
||||||
#define meshtastic_Telemetry_size 79
|
#define meshtastic_Telemetry_size 79
|
||||||
|
|
||||||
|
@ -4,11 +4,8 @@
|
|||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
|
|
||||||
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
|
|
||||||
NeighborInfoModule *neighborInfoModule;
|
NeighborInfoModule *neighborInfoModule;
|
||||||
|
|
||||||
static const char *neighborInfoConfigFile = "/prefs/neighbors.proto";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prints a single neighbor info packet and associated neighbors
|
Prints a single neighbor info packet and associated neighbors
|
||||||
Uses LOG_DEBUG, which equates to Console.log
|
Uses LOG_DEBUG, which equates to Console.log
|
||||||
@ -30,26 +27,23 @@ NOTE: for debugging only
|
|||||||
*/
|
*/
|
||||||
void NeighborInfoModule::printNodeDBNeighbors()
|
void NeighborInfoModule::printNodeDBNeighbors()
|
||||||
{
|
{
|
||||||
int num_neighbors = getNumNeighbors();
|
LOG_DEBUG("Our NodeDB contains %d neighbors\n", neighbors.size());
|
||||||
LOG_DEBUG("Our NodeDB contains %d neighbors\n", num_neighbors);
|
for (size_t i = 0; i < neighbors.size(); i++) {
|
||||||
for (int i = 0; i < num_neighbors; i++) {
|
LOG_DEBUG("Node %d: node_id=0x%x, snr=%.2f\n", i, neighbors[i].node_id, neighbors[i].snr);
|
||||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
|
||||||
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
|
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
|
||||||
NeighborInfoModule::NeighborInfoModule()
|
NeighborInfoModule::NeighborInfoModule()
|
||||||
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
|
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
|
||||||
concurrency::OSThread("NeighborInfoModule"), neighbors(neighborState.neighbors),
|
concurrency::OSThread("NeighborInfoModule")
|
||||||
numNeighbors(&neighborState.neighbors_count)
|
|
||||||
{
|
{
|
||||||
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
|
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
|
||||||
|
|
||||||
if (moduleConfig.neighbor_info.enabled) {
|
if (moduleConfig.neighbor_info.enabled) {
|
||||||
isPromiscuous = true; // Update neighbors from all packets
|
isPromiscuous = true; // Update neighbors from all packets
|
||||||
this->loadProtoForModule();
|
setIntervalFromNow(
|
||||||
setIntervalFromNow(35 * 1000);
|
Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs));
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("NeighborInfoModule is disabled\n");
|
LOG_DEBUG("NeighborInfoModule is disabled\n");
|
||||||
disable();
|
disable();
|
||||||
@ -63,18 +57,17 @@ Assumes that the neighborInfo packet has been allocated
|
|||||||
*/
|
*/
|
||||||
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
|
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->node_id = my_node_id;
|
||||||
neighborInfo->last_sent_by_id = my_node_id;
|
neighborInfo->last_sent_by_id = my_node_id;
|
||||||
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||||
|
|
||||||
int num_neighbors = cleanUpNeighbors();
|
cleanUpNeighbors();
|
||||||
|
|
||||||
for (int i = 0; i < num_neighbors; i++) {
|
for (auto nbr : neighbors) {
|
||||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (nbr.node_id != my_node_id)) {
|
||||||
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) {
|
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = nbr.node_id;
|
||||||
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id;
|
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = nbr.snr;
|
||||||
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->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
|
// 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
|
// the mesh
|
||||||
neighborInfo->neighbors_count++;
|
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
|
Remove neighbors from the database that we haven't heard from in a while
|
||||||
@returns new number of neighbors
|
|
||||||
*/
|
*/
|
||||||
size_t NeighborInfoModule::cleanUpNeighbors()
|
void NeighborInfoModule::cleanUpNeighbors()
|
||||||
{
|
{
|
||||||
uint32_t now = getTime();
|
uint32_t now = getTime();
|
||||||
int num_neighbors = getNumNeighbors();
|
|
||||||
NodeNum my_node_id = nodeDB->getNodeNum();
|
NodeNum my_node_id = nodeDB->getNodeNum();
|
||||||
|
for (auto it = neighbors.rbegin(); it != neighbors.rend();) {
|
||||||
// Find neighbors to remove
|
|
||||||
std::vector<int> indices_to_remove;
|
|
||||||
for (int i = 0; i < num_neighbors; i++) {
|
|
||||||
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
|
||||||
// We will remove a neighbor if we haven't heard from them in twice the broadcast interval
|
// 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)) {
|
if ((now - it->last_rx_time > it->node_broadcast_interval_secs * 2) && (it->node_id != my_node_id)) {
|
||||||
indices_to_remove.push_back(i);
|
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 */
|
/* Send neighbor info to the mesh */
|
||||||
@ -143,7 +117,9 @@ Will be used for broadcast.
|
|||||||
int32_t NeighborInfoModule::runOnce()
|
int32_t NeighborInfoModule::runOnce()
|
||||||
{
|
{
|
||||||
bool requestReplies = false;
|
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);
|
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()
|
void NeighborInfoModule::resetNeighbors()
|
||||||
{
|
{
|
||||||
*numNeighbors = 0;
|
neighbors.clear();
|
||||||
neighborState.neighbors_count = 0;
|
|
||||||
memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors));
|
|
||||||
saveProtoForModule();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
|
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
|
||||||
@ -201,61 +174,36 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
|
|||||||
n = nodeDB->getNodeNum();
|
n = nodeDB->getNodeNum();
|
||||||
}
|
}
|
||||||
// look for one in the existing list
|
// look for one in the existing list
|
||||||
for (int i = 0; i < (*numNeighbors); i++) {
|
for (size_t i = 0; i < neighbors.size(); i++) {
|
||||||
meshtastic_Neighbor *nbr = &neighbors[i];
|
if (neighbors[i].node_id == n) {
|
||||||
if (nbr->node_id == n) {
|
|
||||||
// if found, update it
|
// if found, update it
|
||||||
nbr->snr = snr;
|
neighbors[i].snr = snr;
|
||||||
nbr->last_rx_time = getTime();
|
neighbors[i].last_rx_time = getTime();
|
||||||
// Only if this is the original sender, the broadcast interval corresponds to it
|
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
if (originalSender == n && node_broadcast_interval_secs != 0)
|
||||||
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
neighbors[i].node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
return nbr;
|
return &neighbors[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// otherwise, allocate one and assign data to it
|
// 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) {
|
meshtastic_Neighbor new_nbr = meshtastic_Neighbor_init_zero;
|
||||||
(*numNeighbors)++;
|
new_nbr.node_id = n;
|
||||||
}
|
new_nbr.snr = snr;
|
||||||
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)];
|
new_nbr.last_rx_time = getTime();
|
||||||
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
|
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||||
if (originalSender == n && node_broadcast_interval_secs != 0)
|
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
|
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;
|
new_nbr.node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||||
shouldSave = true; // Save the new neighbor upon next cleanup
|
|
||||||
return new_nbr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NeighborInfoModule::loadProtoForModule()
|
if (neighbors.size() < MAX_NUM_NEIGHBORS) {
|
||||||
{
|
neighbors.push_back(new_nbr);
|
||||||
if (nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
|
} else {
|
||||||
&meshtastic_NeighborInfo_msg, &neighborState) != LoadFileResult::SUCCESS) {
|
// If we have too many neighbors, replace the oldest one
|
||||||
neighborState = meshtastic_NeighborInfo_init_zero;
|
LOG_WARN("Neighbor DB is full, replacing oldest neighbor\n");
|
||||||
|
neighbors.erase(neighbors.begin());
|
||||||
|
neighbors.push_back(new_nbr);
|
||||||
}
|
}
|
||||||
}
|
return &neighbors.back();
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "ProtobufModule.h"
|
#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
|
* Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh
|
||||||
*/
|
*/
|
||||||
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
|
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
meshtastic_Neighbor *neighbors;
|
std::vector<meshtastic_Neighbor> neighbors;
|
||||||
pb_size_t *numNeighbors;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
@ -18,15 +18,7 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
|||||||
/* Reset neighbor info after clearing nodeDB*/
|
/* Reset neighbor info after clearing nodeDB*/
|
||||||
void resetNeighbors();
|
void resetNeighbors();
|
||||||
|
|
||||||
bool saveProtoForModule();
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool shouldSave = false; // Whether we should save the neighbor info to flash
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Note: this holds our local info.
|
|
||||||
meshtastic_NeighborInfo neighborState;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to handle a particular incoming message
|
* 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
|
* @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);
|
uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Remove neighbors from the database that we haven't heard from in a while
|
Remove neighbors from the database that we haven't heard from in a while
|
||||||
@returns new number of neighbors
|
|
||||||
*/
|
*/
|
||||||
size_t cleanUpNeighbors();
|
void cleanUpNeighbors();
|
||||||
|
|
||||||
/* Allocate a new NeighborInfo packet */
|
/* Allocate a new NeighborInfo packet */
|
||||||
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
|
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
|
||||||
@ -56,22 +47,12 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
|
|||||||
*/
|
*/
|
||||||
void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
|
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 */
|
/* update neighbors with subpacket sniffed from network */
|
||||||
void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np);
|
void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np);
|
||||||
|
|
||||||
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
|
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
|
||||||
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n) override;
|
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n) override;
|
||||||
|
|
||||||
void loadProtoForModule();
|
|
||||||
|
|
||||||
/* Does our periodic broadcast */
|
/* Does our periodic broadcast */
|
||||||
int32_t runOnce() override;
|
int32_t runOnce() override;
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "mesh/compression/unishox2.h"
|
#include "mesh/compression/unishox2.h"
|
||||||
|
#include <Throttle.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionModule *positionModule;
|
PositionModule *positionModule;
|
||||||
@ -63,11 +64,11 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log packet size and data fields
|
// 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 "
|
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",
|
"time=%d\n",
|
||||||
getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae,
|
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.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp,
|
||||||
p.time);
|
p.time);
|
||||||
|
|
||||||
if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
|
if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -222,6 +223,16 @@ meshtastic_MeshPacket *PositionModule::allocAtakPli()
|
|||||||
return mp;
|
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)
|
void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel)
|
||||||
{
|
{
|
||||||
// cancel any not yet sent (now stale) position packets
|
// cancel any not yet sent (now stale) position packets
|
||||||
@ -299,12 +310,7 @@ int32_t PositionModule::runOnce()
|
|||||||
lastGpsLatitude = node->position.latitude_i;
|
lastGpsLatitude = node->position.latitude_i;
|
||||||
lastGpsLongitude = node->position.longitude_i;
|
lastGpsLongitude = node->position.longitude_i;
|
||||||
|
|
||||||
// If we changed channels, ask everyone else for their latest info
|
sendOurPosition();
|
||||||
bool requestReplies = currentGeneration != radioGeneration;
|
|
||||||
currentGeneration = radioGeneration;
|
|
||||||
|
|
||||||
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
|
|
||||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) {
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) {
|
||||||
sendLostAndFoundText();
|
sendLostAndFoundText();
|
||||||
}
|
}
|
||||||
@ -314,29 +320,23 @@ int32_t PositionModule::runOnce()
|
|||||||
|
|
||||||
if (hasValidPosition(node2)) {
|
if (hasValidPosition(node2)) {
|
||||||
// The minimum time (in seconds) that would pass before we are able to send a new position packet.
|
// 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);
|
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
||||||
|
uint32_t msSinceLastSend = now - lastGpsSend;
|
||||||
|
|
||||||
if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) {
|
if (smartPosition.hasTraveledOverThreshold &&
|
||||||
bool requestReplies = currentGeneration != radioGeneration;
|
Throttle::execute(
|
||||||
currentGeneration = radioGeneration;
|
&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, "
|
LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
|
||||||
"minTimeInterval=%ims)\n",
|
"minTimeInterval=%ims)\n",
|
||||||
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold,
|
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold,
|
||||||
msSinceLastSend, minimumTimeThreshold);
|
msSinceLastSend, minimumTimeThreshold);
|
||||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
|
||||||
|
|
||||||
// Set the current coords as our last ones, after we've compared distance with current and decided to send
|
// Set the current coords as our last ones, after we've compared distance with current and decided to send
|
||||||
lastGpsLatitude = node->position.latitude_i;
|
lastGpsLatitude = node->position.latitude_i;
|
||||||
lastGpsLongitude = node->position.longitude_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());
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
||||||
// We limit our GPS broadcasts to a max rate
|
// We limit our GPS broadcasts to a max rate
|
||||||
uint32_t now = millis();
|
|
||||||
uint32_t msSinceLastSend = now - lastGpsSend;
|
|
||||||
|
|
||||||
if (hasValidPosition(node2)) {
|
if (hasValidPosition(node2)) {
|
||||||
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
|
||||||
if (smartPosition.hasTraveledOverThreshold) {
|
uint32_t msSinceLastSend = millis() - lastGpsSend;
|
||||||
bool requestReplies = currentGeneration != radioGeneration;
|
if (smartPosition.hasTraveledOverThreshold &&
|
||||||
currentGeneration = radioGeneration;
|
Throttle::execute(
|
||||||
|
&lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); },
|
||||||
LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims)\n",
|
[]() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) {
|
||||||
localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend);
|
LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
|
||||||
sendOurPosition(NODENUM_BROADCAST, requestReplies);
|
"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
|
// Set the current coords as our last ones, after we've compared distance with current and decided to send
|
||||||
lastGpsLatitude = node->position.latitude_i;
|
lastGpsLatitude = node->position.latitude_i;
|
||||||
lastGpsLongitude = node->position.longitude_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
|
#pragma once
|
||||||
|
#include "Default.h"
|
||||||
#include "ProtobufModule.h"
|
#include "ProtobufModule.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
|
|
||||||
@ -29,7 +30,8 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
|||||||
/**
|
/**
|
||||||
* Send our position into the mesh
|
* 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();
|
void handleNewPosition();
|
||||||
|
|
||||||
@ -52,6 +54,9 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
|||||||
meshtastic_MeshPacket *allocAtakPli();
|
meshtastic_MeshPacket *allocAtakPli();
|
||||||
uint32_t precision;
|
uint32_t precision;
|
||||||
void sendLostAndFoundText();
|
void sendLostAndFoundText();
|
||||||
|
|
||||||
|
const uint32_t minimumTimeThreshold =
|
||||||
|
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SmartPosition {
|
struct SmartPosition {
|
||||||
|
@ -506,7 +506,7 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0); // unexpected state
|
break; // no need to do anything
|
||||||
}
|
}
|
||||||
return true; // There's no need for others to look at this message.
|
return true; // There's no need for others to look at this message.
|
||||||
}
|
}
|
||||||
|
@ -106,20 +106,26 @@ static NimbleBluetoothFromRadioCallback *fromRadioCallbacks;
|
|||||||
|
|
||||||
void NimbleBluetooth::shutdown()
|
void NimbleBluetooth::shutdown()
|
||||||
{
|
{
|
||||||
|
// No measurable power saving for ESP32 during light-sleep(?)
|
||||||
|
#ifndef ARCH_ESP32
|
||||||
// Shutdown bluetooth for minimum power draw
|
// Shutdown bluetooth for minimum power draw
|
||||||
LOG_INFO("Disable bluetooth\n");
|
LOG_INFO("Disable bluetooth\n");
|
||||||
// Bluefruit.Advertising.stop();
|
|
||||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
pAdvertising->reset();
|
pAdvertising->reset();
|
||||||
pAdvertising->stop();
|
pAdvertising->stop();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extra power-saving on some devices
|
// Proper shutdown for ESP32. Needs reboot to reverse.
|
||||||
void NimbleBluetooth::deinit()
|
void NimbleBluetooth::deinit()
|
||||||
{
|
{
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
LOG_INFO("Disable bluetooth until reboot\n");
|
||||||
NimBLEDevice::deinit();
|
NimBLEDevice::deinit();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Has initial setup been completed
|
||||||
bool NimbleBluetooth::isActive()
|
bool NimbleBluetooth::isActive()
|
||||||
{
|
{
|
||||||
return bleServer;
|
return bleServer;
|
||||||
|
@ -117,8 +117,8 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
|
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER
|
||||||
#elif defined(TLORA_T3S3_V1)
|
#elif defined(TLORA_T3S3_V1)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
|
#define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3
|
||||||
#elif defined(CDEBYTE_ELORA_S3)
|
#elif defined(CDEBYTE_EORA_S3)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_ELORA_S3
|
#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_EORA_S3
|
||||||
#elif defined(BETAFPV_2400_TX)
|
#elif defined(BETAFPV_2400_TX)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX
|
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX
|
||||||
#elif defined(NANO_G1_EXPLORER)
|
#elif defined(NANO_G1_EXPLORER)
|
||||||
@ -127,6 +127,10 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX
|
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX
|
||||||
#elif defined(PICOMPUTER_S3)
|
#elif defined(PICOMPUTER_S3)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_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)
|
#elif defined(ESP32_S3_PICO)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO
|
#define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO
|
||||||
#elif defined(SENSELORA_S3)
|
#elif defined(SENSELORA_S3)
|
||||||
|
@ -30,9 +30,10 @@ void setBluetoothEnable(bool enable)
|
|||||||
}
|
}
|
||||||
if (enable && !nimbleBluetooth->isActive()) {
|
if (enable && !nimbleBluetooth->isActive()) {
|
||||||
nimbleBluetooth->setup();
|
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
|
#else
|
||||||
|
@ -178,18 +178,31 @@ void portduinoSetup()
|
|||||||
settingsMap[displayPanel] = st7735;
|
settingsMap[displayPanel] = st7735;
|
||||||
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
|
||||||
settingsMap[displayPanel] = 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")
|
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341")
|
||||||
settingsMap[displayPanel] = 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[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
|
||||||
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
|
||||||
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
|
||||||
settingsMap[displayCS] = yamlConfig["Display"]["CS"].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[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[displayReset] = yamlConfig["Display"]["Reset"].as<int>(-1);
|
||||||
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
|
||||||
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
|
||||||
settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
|
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[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
|
||||||
|
settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
|
||||||
if (yamlConfig["Display"]["spidev"]) {
|
if (yamlConfig["Display"]["spidev"]) {
|
||||||
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
|
||||||
}
|
}
|
||||||
@ -200,8 +213,14 @@ void portduinoSetup()
|
|||||||
settingsMap[touchscreenModule] = xpt2046;
|
settingsMap[touchscreenModule] = xpt2046;
|
||||||
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
|
||||||
settingsMap[touchscreenModule] = 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[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
|
||||||
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].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"]) {
|
if (yamlConfig["Touchscreen"]["spidev"]) {
|
||||||
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,23 @@ enum configNames {
|
|||||||
touchscreenModule,
|
touchscreenModule,
|
||||||
touchscreenCS,
|
touchscreenCS,
|
||||||
touchscreenIRQ,
|
touchscreenIRQ,
|
||||||
|
touchscreenBusFrequency,
|
||||||
|
touchscreenRotate,
|
||||||
touchscreenspidev,
|
touchscreenspidev,
|
||||||
displayspidev,
|
displayspidev,
|
||||||
|
displayBusFrequency,
|
||||||
displayPanel,
|
displayPanel,
|
||||||
displayWidth,
|
displayWidth,
|
||||||
displayHeight,
|
displayHeight,
|
||||||
displayCS,
|
displayCS,
|
||||||
displayDC,
|
displayDC,
|
||||||
|
displayRGBOrder,
|
||||||
displayBacklight,
|
displayBacklight,
|
||||||
|
displayBacklightPWMChannel,
|
||||||
|
displayBacklightInvert,
|
||||||
displayReset,
|
displayReset,
|
||||||
displayRotate,
|
displayRotate,
|
||||||
|
displayOffsetRotate,
|
||||||
displayOffsetX,
|
displayOffsetX,
|
||||||
displayOffsetY,
|
displayOffsetY,
|
||||||
displayInvert,
|
displayInvert,
|
||||||
@ -41,8 +48,8 @@ enum configNames {
|
|||||||
webserverrootpath,
|
webserverrootpath,
|
||||||
maxnodes
|
maxnodes
|
||||||
};
|
};
|
||||||
enum { no_screen, st7789, st7735, st7735s, ili9341 };
|
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d };
|
||||||
enum { no_touchscreen, xpt2046, stmpe610 };
|
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
|
||||||
enum { level_error, level_warn, level_info, level_debug };
|
enum { level_error, level_warn, level_info, level_debug };
|
||||||
|
|
||||||
extern std::map<configNames, int> settingsMap;
|
extern std::map<configNames, int> settingsMap;
|
||||||
|
@ -157,6 +157,10 @@ void initDeepSleep()
|
|||||||
for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) {
|
for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) {
|
||||||
if (rtc_gpio_is_valid_gpio((gpio_num_t)i))
|
if (rtc_gpio_is_valid_gpio((gpio_num_t)i))
|
||||||
rtc_gpio_hold_dis((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
|
#endif
|
||||||
@ -207,9 +211,10 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
|
|||||||
// esp_wifi_stop();
|
// esp_wifi_stop();
|
||||||
waitEnterSleep(skipPreflight);
|
waitEnterSleep(skipPreflight);
|
||||||
|
|
||||||
#ifdef NIMBLE_DEINIT_FOR_DEEPSLEEP
|
#ifdef ARCH_ESP32
|
||||||
// Extra power saving on some devices
|
// Full shutdown of bluetooth hardware
|
||||||
nimbleBluetooth->deinit();
|
if (nimbleBluetooth)
|
||||||
|
nimbleBluetooth->deinit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@ -258,14 +263,17 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
|
|||||||
}
|
}
|
||||||
#ifdef BUTTON_PIN
|
#ifdef BUTTON_PIN
|
||||||
// Avoid leakage through button pin
|
// Avoid leakage through button pin
|
||||||
pinMode(BUTTON_PIN, INPUT);
|
if (GPIO_IS_VALID_OUTPUT_GPIO(BUTTON_PIN)) {
|
||||||
gpio_hold_en((gpio_num_t)BUTTON_PIN);
|
pinMode(BUTTON_PIN, INPUT);
|
||||||
|
gpio_hold_en((gpio_num_t)BUTTON_PIN);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (GPIO_IS_VALID_OUTPUT_GPIO(LORA_CS)) {
|
||||||
// LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep
|
// LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep
|
||||||
pinMode(LORA_CS, OUTPUT);
|
pinMode(LORA_CS, OUTPUT);
|
||||||
digitalWrite(LORA_CS, HIGH);
|
digitalWrite(LORA_CS, HIGH);
|
||||||
gpio_hold_en((gpio_num_t)LORA_CS);
|
gpio_hold_en((gpio_num_t)LORA_CS);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_PMU
|
#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_DIO2_AS_RF_SWITCH
|
||||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
#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_DIO2_AS_RF_SWITCH
|
||||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
#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]
|
[VERSION]
|
||||||
major = 2
|
major = 2
|
||||||
minor = 3
|
minor = 3
|
||||||
build = 6
|
build = 7
|
||||||
|
Loading…
Reference in New Issue
Block a user