Compare commits

...

44 Commits

Author SHA1 Message Date
Ben Meadors
10265aabd5 Fix buggy phone positions (#2876)
* Guard-clause channel util. to reduce nesting

* Try-fix PhoneAPI position not updating

* Trunk

* Missed it

* Really disable GPS when asked to

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-10-09 18:33:04 -05:00
Jonathan Bennett
8780d93941 Remove missed GPS definition (#2878) 2023-10-09 13:30:51 -05:00
Sacha Weatherstone
54f0c045e4 Update README.md 2023-10-09 22:30:02 +10:00
github-actions[bot]
3ddad671a5 [create-pull-request] automated change (#2875)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-10-08 08:12:42 -05:00
pat-trunk-io
dc6f0b8e0b mention trunk is beta on windows (#2871)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-06 15:31:04 -05:00
pat-trunk-io
33f28c3d56 Add trunk githooks to the repo (#2870) 2023-10-06 15:02:27 -05:00
github-actions[bot]
ef1d8c8eee [create-pull-request] automated change (#2869) 2023-10-05 17:51:23 -05:00
Ben Meadors
950d5f0946 Power saving sensor (#2865)
* Trunk

* Again

* This thing just keeps updating itself

* Ignore tools

* Sleepy sensor

* Batrunkadunk
2023-10-05 12:42:03 -05:00
Thomas Göttgens
fc06754e1f Possibly fix #2704 "Heltec Wireless Tracker screen doesn't display anything" (#2749)
* fix #2704


Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2023-10-04 22:24:25 -05:00
github-actions[bot]
fbf74fc0b2 [create-pull-request] automated change (#2863)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-10-04 10:23:55 -05:00
code8buster
7cebd79475 Use doNotEnterOff flag to prevent GNSS poweroff before fix acquisition (#2861)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-03 19:50:27 -05:00
Jonathan Bennett
aa38f53aed Fix for T-Beam 1.2 GPS (#2858)
* Fix for T-Beam 1.2 GPS, with DEBUG enabled

* Don't break other devices

* Saving GPS data on this breaks on next boot. Fix.

* derp

* disable the extra verbosity

* Try the same sort of factory reset as the Lilygo image

* Catch GPS reboots and squash

* trunk

* GPS

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-03 12:05:40 -05:00
Ben Meadors
2a6c8be684 Avoid problematic sleep state transitions for power saving sensors and trackers (#2860)
* Avoid problematic sleep state transitions for power saving sensors and trackers

* Line got duped :-|
2023-10-03 10:09:27 -05:00
GUVWAF
37c3d15978 Check if packet is decrypted before using portnum when converting to JSON (#2857)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-03 06:39:35 -05:00
Manuel
f301e236eb fix crash during shutdown (#2859)
* fix null pointer access

* ptr initialize
2023-10-03 06:37:46 -05:00
Manuel
94c2ade272 make esp32 deepsleep button wakeup functional again (#2854)
* make deepsleep button wakeup functional again

* Remove unused var

* Cleanup comment

* suppress screen wake on button

* add resume screen

* trunk fmt

* added missing #ifdef

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-10-02 16:16:29 -05:00
Ben Meadors
a6e4402e41 Screen on secs router default (#2855) 2023-10-02 06:28:05 -05:00
Jonathan Bennett
50db2d0e9b Add timeout to ublox PMREQ command (#2851) 2023-10-01 20:39:18 -05:00
Ben Meadors
5ecdbd0dbb Removed non-functional deep sleep button awake functionality (user can RST instead) (#2852)
* Fixed mask length

* Don't want_response if we're a tracker or sensor

* Fixes

* Removing non-functioning deep sleep button awake
2023-10-01 12:48:12 -05:00
Jonathan Bennett
47c6738c0d Fix GPS init bug -- power up even when disabled (#2850) 2023-09-30 23:38:51 -05:00
Ben Meadors
1552aa0081 Tracker role wakeup and sleep cycle when power.is_power_saving true (#2846)
* WIP

* Sleepy sleepy low power tracker

* Sleepy tracker clear

* NRF52 PoC

* Simplify NRF52 "sleep"

* Trackers aren't polite

* Remove unnecessary include

* Removed accidental commit

* Fixed not-so-sleepy T-Beam due to button gpio mask precendence

* Added sleepOnNextExecution for allowing fulfillment of pending messages before shutting down

* Cleanup

* Don't wantResponse for trackers

* Heltec wireless tracker doesn't like the button interrupt (maybe all s3 because user button press doubles as bootloader mode trigger?)
2023-09-30 21:09:17 -05:00
github-actions[bot]
6ebec8fcd9 [create-pull-request] automated change (#2849)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-30 20:40:04 -05:00
Manuel
e9215a5d70 revert KB_POWERON changes (#2847) 2023-09-30 06:43:36 -05:00
S5NC
4e3576ae48 Simplify SX126x variant configuration (#2813)
* Update SX126xInterface.cpp

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update SX126xInterface.cpp

* Update SX126xInterface.cpp

* Update variant.h

* Update variant.h

* trunk fmt

* trunk fmt

* Update variant.h

* trunk fmt

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update pins_arduino.h

* Update pins_arduino.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* trunk fmt

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

Specify behavior

* Update variant.h

Maintain behavior

* trunk fmt

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-27 16:01:40 -05:00
Tavis
98290e5d7b Re issue: #2496 Populate the position log entries from PositionModule with data fields (#2839)
* Populate the position log entries with data fields

includes datafields with no data as 0

* trunk check formatted.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-27 16:00:56 -05:00
Ben Meadors
ad529924f1 Code duplication cleanup for smart position logic (#2840) 2023-09-27 10:32:35 -05:00
github-actions[bot]
07d51a2ca4 [create-pull-request] automated change (#2837) 2023-09-26 14:54:35 -05:00
github-actions[bot]
47301a5ac0 [create-pull-request] automated change (#2836)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-26 11:11:54 -05:00
Ben Meadors
0d023ea215 Revert "Fix compression (#2806) (#2819)" (#2835)
This reverts commit cdac643749.
2023-09-26 07:02:06 -05:00
Ben Meadors
b5e952db24 No more goober traffic on public mqtt (#2831)
* No more goober traffic on public mqtt

* Oops
2023-09-26 06:19:17 -05:00
GUVWAF
a1c433748a RP2040: Add SerialModule support (#2830)
* Support for SerialModule on RP2040

* Remove one !defined too many

* Increase serial RX_BUFFER: more reliable for long packets
Even results into an error for ESP32

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-26 05:45:34 -05:00
Jonathan Bennett
04b2ab82dc Add GPS pin definitions missed in revamp (#2834) 2023-09-26 05:44:08 -05:00
github-actions[bot]
e96ba7cbcf [create-pull-request] automated change (#2827)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-25 06:31:22 -05:00
Andre K
61f6fb22c5 move STATE_SEND_METADATA to beginning of wantConfig (#2820)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-24 07:22:54 -05:00
github-actions[bot]
db7b77c76e [create-pull-request] automated change (#2823)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-24 07:01:46 -05:00
Andre K
350090ec0d remove residual code for mesh_sds_timeout_secs (#2821)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-24 06:49:35 -05:00
GUVWAF
cdac643749 Fix compression (#2806) (#2819)
* Fix compression: encode to bytes after `decoded` is modified

* Change payload size to decompressed length

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-24 06:49:21 -05:00
Jonathan Bennett
1a2c7f00e1 Gps cleanup and powersave (#2807)
* Refactor GPS to not probe if pins not defined

* Use Named Constructor to clean up code

* Move doGPSPowerSave to GPS class

* Make sure to set GPS awake on triple-click

* Cleanup and remove dead code

* Rename GPS_PIN_WAKE to GPS_PIN_STANDBY

* Actually put GPS to sleep between fixes

* add GPS_POWER_TOGGLE for heltec-tracker and t-deck

* Change GPS_THREAD_INTERVAL to 200 ms

* More dead code, compiler warnings, and add returns

* Add Number of sats to log output

* Add pgs enable and triple-click config

* Track average GPS fix time to judge low-power time

* Feed PositionModule on GPS fix

* Don't turn off the 3v3_s line on RAK4631
when the rotary is present.

* Add GPS power standbyOnly option

* Delay setting time currentQuality
to avoid strange log message.

* Typos, comments, and remove unused variable

* Short-circuit the setAwake logic on GPS disable

* heltec-tracker 0.3 GPS power saving

* set en_gpio to defined state

* Fix fixed_position logic with GPS disabled

* Don't process GPS serial when not isAwake

* Add quirk for Heltec Tracker GPS powersave

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
2023-09-23 23:45:35 -05:00
Jonathan Bennett
7eff5e7bcb Fix for Pi Pico hang (#2817)
* Fix for Pi Pico hang

* Pi Pico fix part 2: Electric Boogaloo
2023-09-20 19:34:45 -05:00
Jonathan Bennett
17207681ef Remove GPS pins from devices lacking built-in GPS (#2812) 2023-09-19 10:55:14 -05:00
Thomas Göttgens
94f7c7e472 Merge pull request #2814 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-09-19 12:46:26 +02:00
caveman99
0a12d67d19 [create-pull-request] automated change 2023-09-19 10:45:28 +00:00
Thomas Göttgens
3175a3d630 Merge pull request #2811 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2023-09-19 10:48:41 +02:00
thebentern
4e9bf75340 [create-pull-request] automated change 2023-09-18 19:49:42 +00:00
101 changed files with 1236 additions and 821 deletions

View File

@@ -7,7 +7,7 @@
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
- Please do not check in files that don't have real changes
- Please do not reformat lines that you didn't have to change the code on
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (WSL2 is required on windows),
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (In beta for windows, WSL2 for the linux version),
because it automatically follows our indentation rules and its auto reformatting will not cause spurious changes to lines.
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
- If your other co-developers have comments on your PR please tweak as needed.

2
.trunk/.gitignore vendored
View File

@@ -2,7 +2,7 @@
*logs
*actions
*notifications
*tools
plugins
user_trunk.yaml
user.yaml
tools

View File

@@ -1,53 +1,53 @@
version: 0.1
cli:
version: 1.13.0
version: 1.16.2
plugins:
sources:
- id: trunk
ref: v1.1.1
ref: v1.2.5
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- bandit@1.7.5
- checkov@2.4.1
- checkov@2.5.0
- terrascan@1.18.3
- trivy@0.44.1
- trufflehog@3.48.0
- trivy@0.45.1
- trufflehog@3.59.0
- taplo@0.8.1
- ruff@0.0.284
- ruff@0.0.292
- yamllint@1.32.0
- isort@5.12.0
- markdownlint@0.35.0
- markdownlint@0.37.0
- oxipng@8.0.0
- svgo@3.0.2
- actionlint@1.6.25
- actionlint@1.6.26
- flake8@6.1.0
- hadolint@2.12.0
- shfmt@3.6.0
- shellcheck@0.9.0
- black@23.7.0
- black@23.9.1
- git-diff-check
- gitleaks@8.17.0
- gitleaks@8.18.0
- clang-format@16.0.3
- prettier@3.0.2
- prettier@3.0.3
disabled:
- taplo@0.8.1
- shellcheck@0.9.0
- shfmt@3.6.0
- oxipng@8.0.0
- actionlint@1.6.22
- markdownlint@0.35.0
- markdownlint@0.37.0
- hadolint@2.12.0
- svgo@3.0.2
runtimes:
enabled:
- python@3.10.8
- go@1.19.5
- go@1.21.0
- node@18.12.1
actions:
disabled:
- trunk-announce
- trunk-check-pre-push
- trunk-fmt-pre-commit
enabled:
- trunk-fmt-pre-commit
- trunk-check-pre-push
- trunk-upgrade-available

View File

@@ -10,8 +10,8 @@
This repository contains the device firmware for the Meshtastic project.
**[Building Instructions](https://meshtastic.org/docs/development/firmware/build)**
**[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
- **[Building Instructions](https://meshtastic.org/docs/development/firmware/build)**
- **[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
## Stats

View File

@@ -70,7 +70,7 @@ lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
https://github.com/mathertel/OneButton#2.1.0 ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4
https://github.com/meshtastic/TinyGPSPlus.git#076e8d2c8fb702d9be5b08c55b93ff76f8af7e61
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.7
erriez/ErriezCRC32@^1.0.1

View File

@@ -164,17 +164,17 @@ class ButtonThread : public concurrency::OSThread
static void userButtonMultiPressed()
{
#if defined(GPS_POWER_TOGGLE)
if (gps != nullptr) {
if (config.position.gps_enabled) {
LOG_DEBUG("Flag set to false for gps power\n");
} else {
LOG_DEBUG("Flag set to true to restore power\n");
}
if (!config.device.disable_triple_click && (gps != nullptr)) {
config.position.gps_enabled = !(config.position.gps_enabled);
gps->doGPSpowersave(config.position.gps_enabled);
if (config.position.gps_enabled) {
LOG_DEBUG("Flag set to true to restore power\n");
gps->enable();
} else {
LOG_DEBUG("Flag set to false for gps power\n");
gps->disable();
}
}
#endif
}
static void userButtonPressedLongStart()

View File

@@ -175,9 +175,21 @@ class AnalogBatteryLevel : public HasBatteryLevel
uint32_t raw = 0;
#ifdef ARCH_ESP32
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
#ifdef ADC_CTRL
if (heltec_version == 5) {
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, HIGH);
delay(10);
}
#endif
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
raw += adc1_get_raw(adc_channel);
}
#ifdef ADC_CTRL
if (heltec_version == 5) {
digitalWrite(ADC_CTRL, LOW);
}
#endif
#else // ADC2
int32_t adc_buf = 0;
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
@@ -414,7 +426,7 @@ void Power::shutdown()
#ifdef PIN_LED3
ledOff(PIN_LED2);
#endif
doDeepSleep(DELAY_FOREVER);
doDeepSleep(DELAY_FOREVER, false);
#endif
}

View File

@@ -8,7 +8,6 @@
* actions to be taken upon entering or exiting each state.
*/
#include "PowerFSM.h"
#include "GPS.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "configuration.h"
@@ -46,7 +45,7 @@ static void sdsEnter()
{
LOG_DEBUG("Enter state: SDS\n");
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs));
doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs), false);
}
extern Power *power;
@@ -137,9 +136,6 @@ static void lsIdle()
static void lsExit()
{
LOG_INFO("Exit state: LS\n");
// setGPSPower(true); // restore GPS power
if (gps)
gps->forceWake(true);
}
static void nbEnter()
@@ -158,9 +154,6 @@ static void darkEnter()
{
setBluetoothEnable(true);
screen->setOn(false);
#ifdef KB_POWERON
digitalWrite(KB_POWERON, LOW);
#endif
}
static void serialEnter()
@@ -188,9 +181,6 @@ static void powerEnter()
} else {
screen->setOn(true);
setBluetoothEnable(true);
#ifdef KB_POWERON
digitalWrite(KB_POWERON, HIGH);
#endif
// within enter() the function getState() returns the state we came from
if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 &&
strcmp(powerFSM.getState()->name, "DARK") != 0) {
@@ -221,9 +211,6 @@ static void onEnter()
LOG_DEBUG("Enter state: ON\n");
screen->setOn(true);
setBluetoothEnable(true);
#ifdef KB_POWERON
digitalWrite(KB_POWERON, HIGH);
#endif
}
static void onIdle()
@@ -258,6 +245,8 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup()
{
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
bool hasPower = isPowered();
LOG_INFO("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0);
@@ -361,12 +350,12 @@ void PowerFSM_setup()
getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
"Screen-on timeout");
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
#ifdef ARCH_ESP32
State *lowPowerState = &stateLS;
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
// See: https://github.com/meshtastic/firmware/issues/1071
if (isRouter || config.power.is_power_saving) {
// Don't add power saving transitions if we are a power saving tracker or sensor. Sleep will be initiatiated through the
// modules
if ((isRouter || config.power.is_power_saving) && !isTrackerOrSensor) {
powerFSM.add_timed_transition(&stateNB, &stateLS,
getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
"Min wake timeout");
@@ -374,10 +363,6 @@ void PowerFSM_setup()
getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs),
NULL, "Bluetooth timeout");
}
if (config.power.sds_secs != UINT32_MAX)
powerFSM.add_timed_transition(lowPowerState, &stateSDS, getConfiguredOrDefaultMs(config.power.sds_secs), NULL,
"mesh timeout");
#endif
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state

View File

@@ -53,7 +53,7 @@ class OSThread : public Thread
static void setup();
int32_t disable();
virtual int32_t disable();
/**
* Wait a specified number msecs starting from the current time (rather than the last time we were run)
@@ -67,6 +67,7 @@ class OSThread : public Thread
* Returns desired period for next invocation (or RUN_SAME for no change)
*/
virtual int32_t runOnce() = 0;
bool sleepOnNextExecution = false;
// Do not override this
virtual void run();
@@ -87,4 +88,4 @@ extern bool hasBeenSetup;
void assertIsSetup();
} // namespace concurrency
} // namespace concurrency

View File

@@ -145,7 +145,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define GPS_BAUDRATE 9600
#ifndef GPS_THREAD_INTERVAL
#define GPS_THREAD_INTERVAL 100
#define GPS_THREAD_INTERVAL 200
#endif
// convert 24-bit color to 16-bit (56K)

View File

@@ -2,6 +2,7 @@
#include "NodeDB.h"
#include "RTC.h"
#include "configuration.h"
#include "main.h" // pmu_found
#include "sleep.h"
#include "ubx.h"
@@ -19,7 +20,7 @@ HardwareSerial *GPS::_serial_gps = &Serial1;
HardwareSerial *GPS::_serial_gps = NULL;
#endif
GPS *gps;
GPS *gps = nullptr;
/// Multiple GPS instances might use the same serial port (in sequence), but we can
/// only init that port once.
@@ -75,28 +76,25 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
while (millis() < startTimeout) {
if (_serial_gps->available()) {
b = _serial_gps->read();
#ifdef GPS_DEBUG
LOG_DEBUG("%02X", (char *)buffer);
#endif
buffer[bytesRead] = b;
bytesRead++;
if ((bytesRead == 767) || (b == '\r')) {
if (strnstr((char *)buffer, message, bytesRead) != nullptr) {
#ifdef GPS_DEBUG
buffer[bytesRead] = '\0';
LOG_DEBUG("%s\r", (char *)buffer);
LOG_DEBUG("\r");
#endif
return GNSS_RESPONSE_OK;
} else {
#ifdef GPS_DEBUG
buffer[bytesRead] = '\0';
LOG_INFO("Bytes read:%s\n", (char *)buffer);
#endif
bytesRead = 0;
}
}
}
}
#ifdef GPS_DEBUG
buffer[bytesRead] = '\0';
LOG_INFO("Bytes read:%s\n", (char *)buffer);
LOG_DEBUG("\n");
#endif
return GNSS_RESPONSE_NONE;
}
@@ -251,10 +249,18 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
bool GPS::setup()
{
int msglen = 0;
bool isProblematicGPS = false;
if (_serial_gps && !didSerialInit) {
if (!didSerialInit) {
#if !defined(GPS_UC6580)
if (tx_gpio) {
#ifdef HAS_PMU
// The T-Beam 1.2 has issues with the GPS
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM && PMU->getChipModel() == XPOWERS_AXP2101) {
gnssModel = GNSS_MODEL_UBLOX;
isProblematicGPS = true;
}
#endif
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
LOG_DEBUG("Probing for GPS at %d \n", serialSpeeds[speedSelect]);
gnssModel = probe(serialSpeeds[speedSelect]);
if (gnssModel == GNSS_MODEL_UNKNOWN) {
@@ -389,74 +395,116 @@ bool GPS::setup()
LOG_WARN("Unable to enable powersaving for GPS.\n");
}
} else {
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode has only been tested on this hardware
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
} else {
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving ECO mode for GPS.\n");
if (!(isProblematicGPS)) {
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode has only been tested on this hardware
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
}
msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n");
}
} else {
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving ECO mode for GPS.\n");
}
}
}
}
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n");
} else {
LOG_INFO("GNSS module configuration saved!\n");
// The T-beam 1.2 has issues.
if (!(isProblematicGPS)) {
msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n");
} else {
LOG_INFO("GNSS module configuration saved!\n");
}
}
}
didSerialInit = true;
}
notifySleepObserver.observe(&notifySleep);
notifyDeepSleepObserver.observe(&notifyDeepSleep);
notifyGPSSleepObserver.observe(&notifyGPSSleep);
if (config.position.gps_enabled == false && config.position.fixed_position == false) {
setAwake(false);
}
return true;
}
GPS::~GPS()
{
// we really should unregister our sleep observer
notifySleepObserver.unobserve(&notifySleep);
notifyDeepSleepObserver.unobserve(&notifyDeepSleep);
notifyGPSSleepObserver.observe(&notifyGPSSleep);
}
// Allow defining the polarity of the WAKE output. default is active high
#ifndef GPS_WAKE_ACTIVE
#define GPS_WAKE_ACTIVE 1
#endif
void GPS::wake()
void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime)
{
#ifdef PIN_GPS_WAKE
digitalWrite(PIN_GPS_WAKE, GPS_WAKE_ACTIVE);
pinMode(PIN_GPS_WAKE, OUTPUT);
LOG_INFO("Setting GPS power=%d\n", on);
if (on) {
clearBuffer(); // drop any old data waiting in the buffer before re-enabling
if (en_gpio)
digitalWrite(en_gpio, on ? GPS_EN_ACTIVE : !GPS_EN_ACTIVE); // turn this on if defined, every time
}
isInPowersave = !on;
if (!standbyOnly && en_gpio != 0 &&
!(HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))) {
LOG_DEBUG("GPS powerdown using GPS_EN_ACTIVE\n");
digitalWrite(en_gpio, on ? GPS_EN_ACTIVE : !GPS_EN_ACTIVE);
return;
}
#ifdef HAS_PMU // We only have PMUs on the T-Beam, and that board has a tiny battery to save GPS ephemera, so treat as a standby.
if (pmu_found && PMU) {
uint8_t model = PMU->getChipModel();
if (model == XPOWERS_AXP2101) {
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// t-beam v1.2 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3);
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
// t-beam-s3-core GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4);
}
} else if (model == XPOWERS_AXP192) {
// t-beam v1.1 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_LDO3) : PMU->disablePowerOutput(XPOWERS_LDO3);
}
return;
}
#endif
}
void GPS::sleep()
{
#ifdef PIN_GPS_WAKE
digitalWrite(PIN_GPS_WAKE, GPS_WAKE_ACTIVE ? 0 : 1);
pinMode(PIN_GPS_WAKE, OUTPUT);
#ifdef PIN_GPS_STANDBY // Specifically the standby pin for L76K and clones
if (on) {
LOG_INFO("Waking GPS");
digitalWrite(PIN_GPS_STANDBY, 1);
pinMode(PIN_GPS_STANDBY, OUTPUT);
return;
} else {
LOG_INFO("GPS entering sleep");
// notifyGPSSleep.notifyObservers(NULL);
digitalWrite(PIN_GPS_STANDBY, 0);
pinMode(PIN_GPS_STANDBY, OUTPUT);
return;
}
#endif
if (!on) {
if (gnssModel == GNSS_MODEL_UBLOX) {
uint8_t msglen;
LOG_DEBUG("Sleep Time: %i\n", sleepTime);
for (int i = 0; i < 4; i++) {
gps->_message_PMREQ[0 + i] = sleepTime >> (i * 8); // Encode the sleep time in millis into the packet
}
msglen = gps->makeUBXPacket(0x02, 0x41, 0x08, gps->_message_PMREQ);
gps->_serial_gps->write(gps->UBXscratch, msglen);
}
} else {
if (gnssModel == GNSS_MODEL_UBLOX) {
gps->_serial_gps->write(0xFF);
clearBuffer(); // This often returns old data, so drop it
}
}
}
/// Record that we have a GPS
@@ -468,14 +516,6 @@ void GPS::setConnected()
}
}
void GPS::setNumSatellites(uint8_t n)
{
if (n != numSatellites) {
numSatellites = n;
shouldPublish = true;
}
}
/**
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
*
@@ -483,23 +523,38 @@ void GPS::setNumSatellites(uint8_t n)
*/
void GPS::setAwake(bool on)
{
if (!wakeAllowed && on) {
LOG_WARN("Inhibiting because !wakeAllowed\n");
on = false;
}
if (isAwake != on) {
LOG_DEBUG("WANT GPS=%d\n", on);
if (on) {
clearBuffer(); // drop any old data waiting in the buffer
lastWakeStartMsec = millis();
wake();
} else {
lastSleepStartMsec = millis();
sleep();
isAwake = on;
if (!enabled) { // short circuit if the user has disabled GPS
setGPSPower(false, false, 0);
return;
}
isAwake = on;
if (on) {
lastWakeStartMsec = millis();
} else {
lastSleepStartMsec = millis();
if (GPSCycles == 1) { // Skipping initial lock time, as it will likely be much longer than average
averageLockTime = lastSleepStartMsec - lastWakeStartMsec;
} else if (GPSCycles > 1) {
averageLockTime += ((int32_t)(lastSleepStartMsec - lastWakeStartMsec) - averageLockTime) / (int32_t)GPSCycles;
}
GPSCycles++;
LOG_DEBUG("GPS Lock took %d, average %d\n", (lastSleepStartMsec - lastWakeStartMsec) / 1000, averageLockTime / 1000);
}
if ((int32_t)getSleepTime() - averageLockTime >
15 * 60 * 1000) { // 15 minutes is probably long enough to make a complete poweroff worth it.
setGPSPower(on, false, getSleepTime() - averageLockTime);
} else if ((int32_t)getSleepTime() - averageLockTime > 10000) { // 10 seconds is enough for standby
#ifdef GPS_UC6580
setGPSPower(on, false, getSleepTime() - averageLockTime);
#else
setGPSPower(on, true, getSleepTime() - averageLockTime);
#endif
} else if (averageLockTime > 20000) {
averageLockTime -= 1000; // eventually want to sleep again.
}
}
}
@@ -519,10 +574,9 @@ uint32_t GPS::getWakeTime() const
uint32_t GPS::getSleepTime() const
{
uint32_t t = config.position.gps_update_interval;
bool gps_enabled = config.position.gps_enabled;
// We'll not need the GPS thread to wake up again after first acq. with fixed position.
if (!gps_enabled || config.position.fixed_position)
if (!config.position.gps_enabled || config.position.fixed_position)
t = UINT32_MAX; // Sleep forever now
if (t == UINT32_MAX)
@@ -537,22 +591,29 @@ void GPS::publishUpdate()
shouldPublish = false;
// In debug logs, identify position by @timestamp:stage (stage 2 = publish)
LOG_DEBUG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, hasLock());
LOG_DEBUG("publishing pos@%x:2, hasVal=%d, Sats=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, p.sats_in_view,
hasLock());
// Notify any status instances that are observing us
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
newStatus.notifyObservers(&status);
if (config.position.gps_enabled)
positionModule->handleNewPosition();
}
}
int32_t GPS::runOnce()
{
if (!GPSInitFinished) {
if (!_serial_gps)
return disable();
if (!setup())
return 2000; // Setup failed, re-run in two seconds
// We have now loaded our saved preferences from flash
if (config.position.gps_enabled == false) {
return disable();
}
// ONCE we will factory reset the GPS for bug #327
if (!devicestate.did_gps_reset) {
LOG_WARN("GPS FactoryReset requested\n");
@@ -562,17 +623,12 @@ int32_t GPS::runOnce()
}
}
GPSInitFinished = true;
if (config.position.gps_enabled == false) {
doGPSpowersave(false);
return 0;
}
}
if (config.position.gps_enabled == false)
return 0;
// Repeaters have no need for GPS
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
disable();
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
return disable();
}
if (whileIdle()) {
// if we have received valid NMEA claim we are connected
@@ -580,20 +636,27 @@ int32_t GPS::runOnce()
} else {
if ((config.position.gps_enabled == 1) && (gnssModel == GNSS_MODEL_UBLOX)) {
// reset the GPS on next bootup
if (devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
if (devicestate.did_gps_reset && (millis() - lastWakeStartMsec > 60000) && !hasFlow()) {
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
devicestate.did_gps_reset = false;
nodeDB.saveDeviceStateToDisk();
disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
}
}
}
// At least one GPS has a bad habit of losing its mind from time to time
if (rebootsSeen > 2) {
rebootsSeen = 0;
gps->factoryReset();
}
// If we are overdue for an update, turn on the GPS and at least publish the current status
uint32_t now = millis();
uint32_t timeAsleep = now - lastSleepStartMsec;
auto sleepTime = getSleepTime();
if (!isAwake && sleepTime != UINT32_MAX && (now - lastSleepStartMsec) > sleepTime) {
if (!isAwake && (sleepTime != UINT32_MAX) &&
((timeAsleep > sleepTime) || (isInPowersave && timeAsleep > (sleepTime - averageLockTime)))) {
// We now want to be awake - so wake up the GPS
setAwake(true);
}
@@ -601,11 +664,6 @@ int32_t GPS::runOnce()
// While we are awake
if (isAwake) {
// LOG_DEBUG("looking for location\n");
if ((now - lastWhileActiveMsec) > 5000) {
lastWhileActiveMsec = now;
whileActive();
}
// If we've already set time from the GPS, no need to ask the GPS
bool gotTime = (getRTCQuality() >= RTCQualityGPS);
if (!gotTime && lookForTime()) { // Note: we count on this && short-circuiting and not resetting the RTC time
@@ -620,7 +678,6 @@ int32_t GPS::runOnce()
shouldPublish = true;
}
// We've been awake too long - force sleep
now = millis();
auto wakeTime = getWakeTime();
bool tooLong = wakeTime != UINT32_MAX && (now - lastWakeStartMsec) > wakeTime;
@@ -645,26 +702,15 @@ int32_t GPS::runOnce()
// If state has changed do a publish
publishUpdate();
if (config.position.fixed_position == true && hasValidLocation)
return disable(); // This should trigger when we have a fixed position, and get that first position
// 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms
// if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake.
return isAwake ? GPS_THREAD_INTERVAL : 5000;
}
void GPS::forceWake(bool on)
{
if (on) {
LOG_DEBUG("Allowing GPS lock\n");
// lastSleepStartMsec = 0; // Force an update ASAP
wakeAllowed = true;
} else {
wakeAllowed = false;
// Note: if the gps was already awake, we DO NOT shut it down, because we want to allow it to complete its lock
// attempt even if we are in light sleep. Once the attempt succeeds (or times out) we'll then shut it down.
// setAwake(false);
}
}
// clear the GPS rx buffer as quickly as possible
void GPS::clearBuffer()
{
@@ -673,22 +719,11 @@ void GPS::clearBuffer()
_serial_gps->read();
}
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
int GPS::prepareSleep(void *unused)
{
LOG_INFO("GPS prepare sleep!\n");
forceWake(false);
return 0;
}
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
int GPS::prepareDeepSleep(void *unused)
{
LOG_INFO("GPS deep sleep!\n");
// For deep sleep we also want abandon any lock attempts (because we want minimum power)
getSleepTime();
setAwake(false);
return 0;
@@ -833,11 +868,11 @@ GnssModel_t GPS::probe(int serialSpeed)
return GNSS_MODEL_UBLOX;
}
// GPS::GPS(uint32_t _rx_gpio, uint32_t _tx_gpio) : concurrency::OSThread("GPS")
GPS *GPS::createGps()
{
int8_t _rx_gpio = config.position.rx_gpio;
int8_t _tx_gpio = config.position.tx_gpio;
int8_t _en_gpio = config.position.gps_en_gpio;
#if defined(HAS_GPS) && !defined(ARCH_ESP32)
_rx_gpio = 1; // We only specify GPS serial ports on ESP32. Otherwise, these are just flags.
_tx_gpio = 1;
@@ -850,12 +885,23 @@ GPS *GPS::createGps()
if (!_tx_gpio)
_tx_gpio = GPS_TX_PIN;
#endif
if (!_rx_gpio) // Configured to have no GPS at all
#if defined(PIN_GPS_EN)
if (!_en_gpio)
_en_gpio = PIN_GPS_EN;
#endif
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
return nullptr;
GPS *new_gps = new GPS;
new_gps->rx_gpio = _rx_gpio;
new_gps->tx_gpio = _tx_gpio;
new_gps->en_gpio = _en_gpio;
if (_en_gpio != 0) {
LOG_DEBUG("Setting %d to output.\n", _en_gpio);
digitalWrite(_en_gpio, !GPS_EN_ACTIVE);
pinMode(_en_gpio, OUTPUT);
}
#ifdef PIN_GPS_PPS
// pulse per second
@@ -871,14 +917,7 @@ GPS *GPS::createGps()
LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n");
#endif
#if defined(HAS_PMU) || defined(PIN_GPS_EN)
if (config.position.gps_enabled) {
#ifdef PIN_GPS_EN
pinMode(PIN_GPS_EN, OUTPUT);
#endif
setGPSPower(true);
}
#endif
new_gps->setGPSPower(true, false, 0);
#ifdef PIN_GPS_RESET
digitalWrite(PIN_GPS_RESET, GPS_RESET_MODE); // assert for 10ms
@@ -933,11 +972,38 @@ bool GPS::factoryReset()
digitalWrite(PIN_GPS_REINIT, 1);
#endif
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
// Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
_serial_gps->write(_message_reset, sizeof(_message_reset));
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
byte _message_reset1[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, 0xA2};
_serial_gps->write(_message_reset1, sizeof(_message_reset1));
if (getACK(0x05, 0x01, 10000)) {
LOG_INFO("Get ack success!\n");
}
delay(100);
byte _message_reset2[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA1};
_serial_gps->write(_message_reset2, sizeof(_message_reset2));
if (getACK(0x05, 0x01, 10000)) {
LOG_INFO("Get ack success!\n");
}
delay(100);
byte _message_reset3[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3};
_serial_gps->write(_message_reset3, sizeof(_message_reset3));
if (getACK(0x05, 0x01, 10000)) {
LOG_INFO("Get ack success!\n");
}
// Reset device ram to COLDSTART state
// byte _message_CFG_RST_COLDSTART[] = {0xB5, 0x62, 0x06, 0x04, 0x04, 0x00, 0xFF, 0xB9, 0x00, 0x00, 0xC6, 0x8B};
// _serial_gps->write(_message_CFG_RST_COLDSTART, sizeof(_message_CFG_RST_COLDSTART));
// delay(1000);
} else {
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's UBLOX.
// Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
_serial_gps->write(_message_reset, sizeof(_message_reset));
}
delay(1000);
return true;
}
@@ -1134,7 +1200,12 @@ bool GPS::hasFlow()
bool GPS::whileIdle()
{
int charsInBuf = 0;
bool isValid = false;
if (!isAwake) {
clearBuffer();
return isAwake;
}
#ifdef SERIAL_BUFFER_SIZE
if (_serial_gps->available() >= SERIAL_BUFFER_SIZE - 1) {
LOG_WARN("GPS Buffer full with %u bytes waiting. Flushing to avoid corruption.\n", _serial_gps->available());
@@ -1146,50 +1217,34 @@ bool GPS::whileIdle()
// First consume any chars that have piled up at the receiver
while (_serial_gps->available() > 0) {
int c = _serial_gps->read();
// LOG_DEBUG("%c", c);
UBXscratch[charsInBuf] = c;
#ifdef GPS_DEBUG
LOG_DEBUG("%c", c);
#endif
isValid |= reader.encode(c);
if (charsInBuf > sizeof(UBXscratch) - 10 || c == '\r') {
if (strnstr((char *)UBXscratch, "$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50", charsInBuf)) {
rebootsSeen++;
}
charsInBuf = 0;
} else {
charsInBuf++;
}
}
return isValid;
}
void GPS::doGPSpowersave(bool on)
void GPS::enable()
{
#if defined(HAS_PMU) || defined(PIN_GPS_EN)
if (on) {
LOG_INFO("Turning GPS back on\n");
gps->forceWake(1);
setGPSPower(1);
setAwake(1);
} else {
LOG_INFO("Turning off GPS chip\n");
notifyGPSSleep.notifyObservers(NULL);
setGPSPower(0);
}
#endif
#ifdef PIN_GPS_WAKE
if (on) {
LOG_INFO("Waking GPS");
gps->forceWake(1);
setAwake(1);
} else {
LOG_INFO("GPS entering sleep");
notifyGPSSleep.notifyObservers(NULL);
}
#endif
#if !(defined(HAS_PMU) || defined(PIN_GPS_EN) || defined(PIN_GPS_WAKE))
if (!on) {
notifyGPSSleep.notifyObservers(NULL);
if (gnssModel == GNSS_MODEL_UBLOX) {
uint8_t msglen;
msglen = gps->makeUBXPacket(0x02, 0x41, 0x08, gps->_message_PMREQ);
gps->_serial_gps->write(gps->UBXscratch, msglen);
}
setAwake(1);
} else {
gps->forceWake(1);
if (gnssModel == GNSS_MODEL_UBLOX)
gps->_serial_gps->write(0xFF);
}
#endif
enabled = true;
setInterval(GPS_THREAD_INTERVAL);
setAwake(true);
}
int32_t GPS::disable()
{
enabled = false;
setInterval(INT32_MAX);
setAwake(false);
return INT32_MAX;
}

View File

@@ -4,6 +4,14 @@
#include "Observer.h"
#include "TinyGPS++.h"
#include "concurrency/OSThread.h"
#include "input/RotaryEncoderInterruptImpl1.h"
#include "input/UpDownInterruptImpl1.h"
#include "modules/PositionModule.h"
// Allow defining the polarity of the ENABLE output. default is active high
#ifndef GPS_EN_ACTIVE
#define GPS_EN_ACTIVE 1
#endif
struct uBloxGnssModelInfo {
char swVersion[30];
@@ -48,11 +56,14 @@ class GPS : private concurrency::OSThread
uint8_t fixType = 0; // fix type from GPGSA
#endif
private:
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0;
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0;
const int serialSpeeds[6] = {9600, 4800, 38400, 57600, 115200, 9600};
uint32_t rx_gpio = 0;
uint32_t tx_gpio = 0;
uint32_t en_gpio = 0;
int32_t averageLockTime = 0;
uint32_t GPSCycles = 0;
int speedSelect = 0;
int probeTries = 2;
@@ -65,7 +76,7 @@ class GPS : private concurrency::OSThread
bool isAwake = false; // true if we want a location right now
bool wakeAllowed = true; // false if gps must be forced to sleep regardless of what time it is
bool isInPowersave = false;
bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
@@ -76,7 +87,6 @@ class GPS : private concurrency::OSThread
uint8_t numSatellites = 0;
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
@@ -84,7 +94,7 @@ class GPS : private concurrency::OSThread
/** If !NULL we will use this serial port to construct our GPS */
static HardwareSerial *_serial_gps;
static const uint8_t _message_PMREQ[];
static uint8_t _message_PMREQ[];
static const uint8_t _message_CFG_RXM_PSM[];
static const uint8_t _message_CFG_RXM_ECO[];
static const uint8_t _message_CFG_PM2[];
@@ -116,6 +126,14 @@ class GPS : private concurrency::OSThread
*/
virtual bool setup();
// re-enable the thread
void enable();
// Disable the thread
int32_t disable() override;
void setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime);
/// Returns true if we have acquired GPS lock.
virtual bool hasLock();
@@ -127,14 +145,6 @@ class GPS : private concurrency::OSThread
bool isPowerSaving() const { return !config.position.gps_enabled; }
/**
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
* called after the CPU wakes from light-sleep state
*
* Or set to false, to disallow any sort of waking
* */
void forceWake(bool on);
// Empty the input buffer as quickly as possible
void clearBuffer();
@@ -144,6 +154,8 @@ class GPS : private concurrency::OSThread
// scratch space for creating ublox packets
uint8_t UBXscratch[250] = {0};
int rebootsSeen = 0;
int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis);
GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis);
GPS_RESPONSE getACK(const char *message, uint32_t waitMillis);
@@ -154,7 +166,6 @@ class GPS : private concurrency::OSThread
* calls sleep/wake
*/
void setAwake(bool on);
void doGPSpowersave(bool on);
virtual bool factoryReset();
// Creates an instance of the GPS class.
@@ -162,20 +173,6 @@ class GPS : private concurrency::OSThread
static GPS *createGps();
protected:
/// If possible force the GPS into sleep/low power mode
virtual void sleep();
/// wake the GPS into normal operation mode
virtual void wake();
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
*/
/** Idle processing while GPS is looking for lock, called once per secondish */
virtual void whileActive() {}
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
@@ -193,8 +190,6 @@ class GPS : private concurrency::OSThread
/// Record that we have a GPS
void setConnected();
void setNumSatellites(uint8_t n);
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
@@ -218,10 +213,6 @@ class GPS : private concurrency::OSThread
virtual bool lookForLocation();
private:
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareSleep(void *unused);
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);

View File

@@ -103,9 +103,8 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
bool shouldSet;
if (q > currentQuality) {
currentQuality = q;
shouldSet = true;
LOG_DEBUG("Upgrading time to RTC %ld secs (quality %d)\n", tv->tv_sec, q);
LOG_DEBUG("Upgrading time to quality %d\n", q);
} else if (q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
// Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift
shouldSet = true;
@@ -114,12 +113,12 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
shouldSet = false;
if (shouldSet) {
currentQuality = q;
lastSetMsec = now;
// This delta value works on all platforms
timeStartMsec = now;
zeroOffsetSecs = tv->tv_sec;
// If this platform has a setable RTC, set it
#ifdef RV3028_RTC
if (rtc_found.address == RV3028_RTC) {
@@ -209,4 +208,4 @@ uint32_t getTime()
uint32_t getValidTime(RTCQuality minQuality)
{
return (currentQuality >= minQuality) ? getTime() : 0;
}
}

View File

@@ -1,4 +1,4 @@
const uint8_t GPS::_message_PMREQ[] PROGMEM = {
uint8_t GPS::_message_PMREQ[] PROGMEM = {
0x00, 0x00, // 4 bytes duration of request task
0x00, 0x00, // (milliseconds)
0x02, 0x00, // Task flag bitfield
@@ -17,7 +17,7 @@ const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = {
const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
0x01, 0x06, 0x00, 0x00, // version, Reserved
0x0e, 0x81, 0x42, 0x01, // flags
0x0E, 0x81, 0x43, 0x01, // flags
0xE8, 0x03, 0x00, 0x00, // update period 1000 ms
0x10, 0x27, 0x00, 0x00, // search period 10s
0x00, 0x00, 0x00, 0x00, // Grod offset 0
@@ -189,4 +189,4 @@ const uint8_t GPS::_message_SAVE[] = {
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
0x0F // deviceMask: BBR, Flash, EEPROM, and SPI Flash
};
};

View File

@@ -164,11 +164,28 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
// FIXME - draw serial # somewhere?
}
#ifdef ARCH_ESP32
static void drawFrameResume(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
uint16_t x_offset = display->width() / 2;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(x_offset + x, 26 + y, "Resuming...");
}
#endif
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawIconScreen(region, display, state, x, y);
#ifdef ARCH_ESP32
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) {
drawFrameResume(display, state, x, y);
} else
#endif
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawIconScreen(region, display, state, x, y);
}
}
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)

View File

@@ -1,4 +1,5 @@
#include "configuration.h"
#include "main.h"
#ifndef TFT_BACKLIGHT_ON
#define TFT_BACKLIGHT_ON HIGH
@@ -81,8 +82,16 @@ class LGFX : public lgfx::LGFX_Device
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
#ifdef ST7735_BL_V03
if (heltec_version == 3) {
cfg.pin_bl = ST7735_BL_V03;
} else {
cfg.pin_bl = ST7735_BL_V05;
}
#else
cfg.pin_bl = ST7735_BL; // Pin number to which the backlight is connected
cfg.invert = true; // true to invert the brightness of the backlight
#endif
cfg.invert = true; // true to invert the brightness of the backlight
// cfg.freq = 44100; // PWM frequency of backlight
// cfg.pwm_channel = 1; // PWM channel number to use
@@ -364,9 +373,23 @@ void TFTDisplay::sendCommand(uint8_t com)
// handle display on/off directly
switch (com) {
case DISPLAYON: {
#if defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
if (heltec_version == 3) {
digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
} else {
digitalWrite(ST7735_BACKLIGHT_EN_V05, TFT_BACKLIGHT_ON);
}
#endif
#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
#endif
#ifdef VTFT_CTRL_V03
if (heltec_version == 3) {
digitalWrite(VTFT_CTRL_V03, LOW);
} else {
digitalWrite(VTFT_CTRL_V05, LOW);
}
#endif
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, LOW);
#endif
@@ -376,9 +399,23 @@ void TFTDisplay::sendCommand(uint8_t com)
break;
}
case DISPLAYOFF: {
#if defined(ST7735_BACKLIGHT_EN_V03) && defined(TFT_BACKLIGHT_ON)
if (heltec_version == 3) {
digitalWrite(ST7735_BACKLIGHT_EN_V03, !TFT_BACKLIGHT_ON);
} else {
digitalWrite(ST7735_BACKLIGHT_EN_V05, !TFT_BACKLIGHT_ON);
}
#endif
#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON);
#endif
#ifdef VTFT_CTRL_V03
if (heltec_version == 3) {
digitalWrite(VTFT_CTRL_V03, HIGH);
} else {
digitalWrite(VTFT_CTRL_V05, HIGH);
}
#endif
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, HIGH);
#endif
@@ -436,6 +473,16 @@ bool TFTDisplay::connect()
pinMode(TFT_BL, OUTPUT);
#endif
#ifdef ST7735_BACKLIGHT_EN_V03
if (heltec_version == 3) {
digitalWrite(ST7735_BACKLIGHT_EN_V03, TFT_BACKLIGHT_ON);
pinMode(ST7735_BACKLIGHT_EN_V03, OUTPUT);
} else {
digitalWrite(ST7735_BACKLIGHT_EN_V05, TFT_BACKLIGHT_ON);
pinMode(ST7735_BACKLIGHT_EN_V05, OUTPUT);
}
#endif
tft.init();
#if defined(M5STACK)
tft.setRotation(0);

View File

@@ -5,12 +5,12 @@ RotaryEncoderInterruptImpl1 *rotaryEncoderInterruptImpl1;
RotaryEncoderInterruptImpl1::RotaryEncoderInterruptImpl1() : RotaryEncoderInterruptBase("rotEnc1") {}
void RotaryEncoderInterruptImpl1::init()
bool RotaryEncoderInterruptImpl1::init()
{
if (!moduleConfig.canned_message.rotary1_enabled) {
// Input device is disabled.
disable();
return;
return false;
}
uint8_t pinA = moduleConfig.canned_message.inputbroker_pin_a;
@@ -25,6 +25,7 @@ void RotaryEncoderInterruptImpl1::init()
RotaryEncoderInterruptImpl1::handleIntA, RotaryEncoderInterruptImpl1::handleIntB,
RotaryEncoderInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this);
return true;
}
void RotaryEncoderInterruptImpl1::handleIntA()
@@ -38,4 +39,4 @@ void RotaryEncoderInterruptImpl1::handleIntB()
void RotaryEncoderInterruptImpl1::handleIntPressed()
{
rotaryEncoderInterruptImpl1->intPressHandler();
}
}

View File

@@ -12,7 +12,7 @@ class RotaryEncoderInterruptImpl1 : public RotaryEncoderInterruptBase
{
public:
RotaryEncoderInterruptImpl1();
void init();
bool init();
static void handleIntA();
static void handleIntB();
static void handleIntPressed();

View File

@@ -5,12 +5,12 @@ UpDownInterruptImpl1 *upDownInterruptImpl1;
UpDownInterruptImpl1::UpDownInterruptImpl1() : UpDownInterruptBase("upDown1") {}
void UpDownInterruptImpl1::init()
bool UpDownInterruptImpl1::init()
{
if (!moduleConfig.canned_message.updown1_enabled) {
// Input device is disabled.
return;
return false;
}
uint8_t pinUp = moduleConfig.canned_message.inputbroker_pin_a;
@@ -24,6 +24,7 @@ void UpDownInterruptImpl1::init()
UpDownInterruptBase::init(pinDown, pinUp, pinPress, eventDown, eventUp, eventPressed, UpDownInterruptImpl1::handleIntDown,
UpDownInterruptImpl1::handleIntUp, UpDownInterruptImpl1::handleIntPressed);
inputBroker->registerSource(this);
return true;
}
void UpDownInterruptImpl1::handleIntDown()
@@ -37,4 +38,4 @@ void UpDownInterruptImpl1::handleIntUp()
void UpDownInterruptImpl1::handleIntPressed()
{
upDownInterruptImpl1->intPressHandler();
}
}

View File

@@ -5,10 +5,10 @@ class UpDownInterruptImpl1 : public UpDownInterruptBase
{
public:
UpDownInterruptImpl1();
void init();
bool init();
static void handleIntDown();
static void handleIntUp();
static void handleIntPressed();
};
extern UpDownInterruptImpl1 *upDownInterruptImpl1;
extern UpDownInterruptImpl1 *upDownInterruptImpl1;

View File

@@ -146,6 +146,25 @@ const char *getDeviceName()
return name;
}
#ifdef VEXT_ENABLE_V03
#include <soc/rtc.h>
static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char *name)
{
const uint32_t cal_count = 1000;
uint32_t cali_val;
for (int i = 0; i < 5; ++i) {
cali_val = rtc_clk_cal(cal_clk, cal_count);
}
return cali_val;
}
int heltec_version = 3;
#define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
#endif
static int32_t ledBlinker()
{
static bool ledOn;
@@ -216,12 +235,59 @@ void setup()
digitalWrite(PIN_EINK_PWR_ON, HIGH);
#endif
#ifdef VEXT_ENABLE
#ifdef ST7735_BL_V03 // Heltec Wireless Tracker PCB Change Detect/Hack
rtc_clk_32k_enable(true);
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
if (CALIBRATE_ONE(RTC_CAL_32K_XTAL) != 0) {
rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
}
if (rtc_clk_slow_freq_get() != RTC_SLOW_FREQ_32K_XTAL) {
heltec_version = 3;
} else {
heltec_version = 5;
}
#endif
#if defined(VEXT_ENABLE_V03)
if (heltec_version == 3) {
pinMode(VEXT_ENABLE_V03, OUTPUT);
digitalWrite(VEXT_ENABLE_V03, 0); // turn on the display power
LOG_DEBUG("HELTEC Detect Tracker V1.0\n");
} else {
pinMode(VEXT_ENABLE_V05, OUTPUT);
digitalWrite(VEXT_ENABLE_V05, 1); // turn on the display power
LOG_DEBUG("HELTEC Detect Tracker V1.1\n");
}
#elif defined(VEXT_ENABLE)
pinMode(VEXT_ENABLE, OUTPUT);
digitalWrite(VEXT_ENABLE, 0); // turn on the display power
#endif
#ifdef VGNSS_CTRL
#if defined(VGNSS_CTRL_V03)
if (heltec_version == 3) {
pinMode(VGNSS_CTRL_V03, OUTPUT);
digitalWrite(VGNSS_CTRL_V03, LOW);
} else {
pinMode(VGNSS_CTRL_V05, OUTPUT);
digitalWrite(VGNSS_CTRL_V05, LOW);
}
#endif
#if defined(VTFT_CTRL_V03)
if (heltec_version == 3) {
pinMode(VTFT_CTRL_V03, OUTPUT);
digitalWrite(VTFT_CTRL_V03, LOW);
} else {
pinMode(VTFT_CTRL_V05, OUTPUT);
digitalWrite(VTFT_CTRL_V05, LOW);
}
#endif
#if defined(VGNSS_CTRL)
pinMode(VGNSS_CTRL, OUTPUT);
digitalWrite(VGNSS_CTRL, LOW);
#endif

View File

@@ -64,6 +64,8 @@ extern uint32_t shutdownAtMsec;
extern uint32_t serialSinceMsec;
extern int heltec_version;
// If a thread does something that might need for it to be rescheduled ASAP it can set this flag
// This will suppress the current delay and instead try to run ASAP.
extern bool runASAP;

View File

@@ -169,6 +169,14 @@ void NodeDB::installDefaultConfig()
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST;
config.lora.hop_limit = HOP_RELIABLE;
#ifdef PIN_GPS_EN
config.position.gps_en_gpio = PIN_GPS_EN;
#endif
#ifdef GPS_POWER_TOGGLE
config.device.disable_triple_click = false;
#else
config.device.disable_triple_click = true;
#endif
config.position.gps_enabled = true;
config.position.position_broadcast_smart_enabled = true;
config.position.broadcast_smart_minimum_distance = 100;
@@ -679,8 +687,8 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
LOG_INFO("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i,
p.longitude_i, p.altitude);
setLocalPosition(p);
info->position = ConvertToPositionLite(p);
localPosition = p;
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
// (stop-gap fix for issue #900)

View File

@@ -131,6 +131,13 @@ class NodeDB
meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
size_t getNumMeshNodes() { return *numMeshNodes; }
void setLocalPosition(meshtastic_Position position)
{
LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i\n", position.latitude_i, position.longitude_i,
position.time);
localPosition = position;
}
private:
/// Find a node in our DB, create an empty NodeInfoLite if missing
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
@@ -192,7 +199,7 @@ extern NodeDB nodeDB;
#define default_sds_secs IF_ROUTER(ONE_DAY, UINT32_MAX) // Default to forever super deep sleep
#define default_ls_secs IF_ROUTER(ONE_DAY, 5 * 60)
#define default_min_wake_secs 10
#define default_screen_on_secs 60 * 10
#define default_screen_on_secs IF_ROUTER(1, 60 * 10)
#define default_mqtt_address "mqtt.meshtastic.org"
#define default_mqtt_username "meshdev"
@@ -212,6 +219,14 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d
return defaultInterval * 1000;
}
inline uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue)
{
if (configured > 0)
return configured;
return defaultValue;
}
/// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)

View File

@@ -155,11 +155,18 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// app not to send locations on our behalf.
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag;
fromRadioScratch.my_info = myNodeInfo;
state = STATE_SEND_NODEINFO;
state = STATE_SEND_METADATA;
service.refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon.
break;
case STATE_SEND_METADATA:
LOG_INFO("getFromRadio=STATE_SEND_METADATA\n");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_metadata_tag;
fromRadioScratch.metadata = getDeviceMetadata();
state = STATE_SEND_NODEINFO;
break;
case STATE_SEND_NODEINFO: {
LOG_INFO("getFromRadio=STATE_SEND_NODEINFO\n");
@@ -294,15 +301,11 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
config_state++;
// Advance when we have sent all of our ModuleConfig objects
if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) {
state = STATE_SEND_METADATA;
state = STATE_SEND_COMPLETE_ID;
config_state = 0;
}
break;
case STATE_SEND_METADATA:
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_metadata_tag;
fromRadioScratch.metadata = getDeviceMetadata();
state = STATE_SEND_COMPLETE_ID;
break;
case STATE_SEND_COMPLETE_ID:
LOG_INFO("getFromRadio=STATE_SEND_COMPLETE_ID\n");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_complete_id_tag;

View File

@@ -3,7 +3,8 @@
#include "error.h"
#include "mesh/NodeDB.h"
// Particular boards might define a different max power based on what their hardware can do
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and SX126x power config forgotten)
#ifndef SX126X_MAX_POWER
#define SX126X_MAX_POWER 22
#endif
@@ -26,20 +27,23 @@ template <typename T> bool SX126xInterface<T>::init()
pinMode(SX126X_POWER_EN, OUTPUT);
#endif
#ifndef SX126X_E22
float tcxoVoltage = 0; // None - we use an XTAL
// FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE
#if !defined(SX126X_DIO3_TCXO_VOLTAGE)
float tcxoVoltage =
0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per
// https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.h#L471C26-L471C104
// (DIO3 is free to be used as an IRQ)
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage\n");
#else
// Use DIO3 to power tcxo per https://github.com/jgromes/RadioLib/issues/12#issuecomment-520695575
float tcxoVoltage = 1.8;
float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE;
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V\n", SX126X_DIO3_TCXO_VOLTAGE);
// (DIO3 is not free to be used as an IRQ)
#endif
// FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
RadioLibInterface::init();
if (power == 0)
power = SX126X_MAX_POWER;
if (power > SX126X_MAX_POWER) // This chip has lower power limits than some
if (power > SX126X_MAX_POWER) // Clamp power to maximum defined level
power = SX126X_MAX_POWER;
limitPower();
@@ -54,49 +58,50 @@ template <typename T> bool SX126xInterface<T>::init()
LOG_INFO("Bandwidth set to %f\n", bw);
LOG_INFO("Power output set to %d\n", power);
// current limit was removed from module' ctor
// override default value (60 mA)
// Overriding current limit
// (https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.cpp#L85) using
// value in SX126xInterface.h (currently 140 mA) It may or may not be neccessary, depending on how RadioLib functions, from
// SX1261/2 datasheet: OCP after setting DeviceSel with SetPaConfig(): SX1261 - 60 mA, SX1262 - 140 mA For the SX1268 the IC
// defaults to 140mA no matter the set power level, but RadioLib set it lower, this would need further checking Default values
// are: SX1262, SX1268: 0x38 (140 mA), SX1261: 0x18 (60 mA)
// FIXME: Not ideal to increase SX1261 current limit above 60mA as it can only transmit max 15dBm, should probably only do it
// if using SX1262 or SX1268
res = lora.setCurrentLimit(currentLimit);
LOG_DEBUG("Current limit set to %f\n", currentLimit);
LOG_DEBUG("Current limit set result %d\n", res);
#if defined(SX126X_E22)
// E22 Emulation explicitly requires DIO2 as RF switch, so set it to TRUE again for good measure. In case somebody defines
// SX126X_TX for an E22 Module
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("SX126X_E22 mode enabled. Setting DIO2 as RF Switch\n");
res = lora.setDio2AsRfSwitch(true);
}
#ifdef SX126X_DIO2_AS_RF_SWITCH
LOG_DEBUG("Setting DIO2 as RF switch\n");
bool dio2AsRfSwitch = true;
#else
LOG_DEBUG("Setting DIO2 as not RF switch\n");
bool dio2AsRfSwitch = false;
#endif
if (res == RADIOLIB_ERR_NONE) {
res = lora.setDio2AsRfSwitch(dio2AsRfSwitch);
}
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
// If SX126X_TXEN is connected to the MCU, we are manually controlling RX and TX.
// But lora.begin (called above) sets Dio2 as RF switch control, which is not true here, so set it back to false.
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("SX126X_TXEN pin defined. Setting RF Switch: RXEN=%i, TXEN=%i\n", SX126X_RXEN, SX126X_TXEN);
res = lora.setDio2AsRfSwitch(false);
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
}
#elif defined(SX126X_RXEN) && (SX126X_RXEN != RADIOLIB_NC && defined(E22_TXEN_CONNECTED_TO_DIO2))
// Otherwise, if SX126X_RXEN is connected to the MCU, and E22_TXEN_CONNECTED_TO_DIO2 is defined, we are letting the
// E22 control RX and TX via DIO2. In this configuration, the E22's TXEN and DIO2 pins are connected to each other,
// but not to the MCU.
// However, we must still connect the E22's RXEN pin to the MCU, define SX126X_RXEN accordingly, and then call
// setRfSwitchPins, otherwise RX sensitivity (observed via RSSI) is greatly diminished.
LOG_DEBUG("SX126X_RXEN and E22_TXEN_CONNECTED_TO_DIO2 are defined; value of res: %d", res);
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("SX126X_TXEN is RADIOLIB_NC, but SX126X_RXEN and E22_TXEN_CONNECTED_TO_DIO2 are both defined; calling "
"lora.setRfSwitchPins.");
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
}
// If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has
// no effect
#ifndef SX126X_RXEN
#define SX126X_RXEN RADIOLIB_NC
LOG_DEBUG("SX126X_RXEN not defined, defaulting to RADIOLIB_NC\n");
#endif
#ifndef SX126X_TXEN
#define SX126X_TXEN RADIOLIB_NC
LOG_DEBUG("SX126X_TXEN not defined, defaulting to RADIOLIB_NC\n");
#endif
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching\n", SX126X_RXEN, SX126X_TXEN);
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
}
if (config.lora.sx126x_rx_boosted_gain) {
uint16_t result = lora.setRxBoostedGainMode(true);
LOG_INFO("Set Rx Boosted Gain mode; result: %d\n", result);
LOG_INFO("Set RX gain to boosted mode; result: %d\n", result);
} else {
uint16_t result = lora.setRxBoostedGainMode(false);
LOG_INFO("Set Rx Power Saving Gain mode; result: %d\n", result);
LOG_INFO("Set RX gain to power saving mode (boosted mode off); result: %d\n", result);
}
#if 0
@@ -265,7 +270,7 @@ template <typename T> bool SX126xInterface<T>::isChannelActive()
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
template <typename T> bool SX126xInterface<T>::isActivelyReceiving()
{
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
// The IRQ status will be cleared when we start our read operation. Check if we've started a header, but haven't yet
// received and handled the interrupt for reading the packet/handling errors.
uint16_t irq = lora.getIrqStatus();
@@ -296,7 +301,7 @@ template <typename T> bool SX126xInterface<T>::sleep()
{
// Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet
// \todo Display actual typename of the adapter, not just `SX126x`
LOG_DEBUG("sx126x entering sleep mode (FIXME, don't keep config)\n");
LOG_DEBUG("SX126x entering sleep mode (FIXME, don't keep config)\n");
setStandby(); // Stop any pending operations
// turn off TCXO if it was powered
@@ -312,4 +317,4 @@ template <typename T> bool SX126xInterface<T>::sleep()
#endif
return true;
}
}

View File

@@ -30,10 +30,14 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. */
meshtastic_Config_DeviceConfig_Role_REPEATER = 4,
/* Tracker device role
Position Mesh packets will be prioritized higher and sent more frequently by default. */
Position Mesh packets will be prioritized higher and sent more frequently by default.
When used in conjunction with power.is_power_saving = true, nodes will wake up,
send position, and then sleep for position.position_broadcast_secs seconds. */
meshtastic_Config_DeviceConfig_Role_TRACKER = 5,
/* Sensor device role
Telemetry Mesh packets will be prioritized higher and sent more frequently by default. */
Telemetry Mesh packets will be prioritized higher and sent more frequently by default.
When used in conjunction with power.is_power_saving = true, nodes will wake up,
send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */
meshtastic_Config_DeviceConfig_Role_SENSOR = 6
} meshtastic_Config_DeviceConfig_Role;
@@ -237,6 +241,8 @@ typedef struct _meshtastic_Config_DeviceConfig {
/* If true, device is considered to be "managed" by a mesh administrator
Clients should then limit available configuration and administrative options inside the user interface */
bool is_managed;
/* Disables the triple-press of user button to enable or disable GPS */
bool disable_triple_click;
} meshtastic_Config_DeviceConfig;
/* Position Config */
@@ -272,6 +278,8 @@ typedef struct _meshtastic_Config_PositionConfig {
uint32_t broadcast_smart_minimum_distance;
/* The minimum number of seconds (since the last send) before we can send a position to the mesh if position_broadcast_smart_enabled */
uint32_t broadcast_smart_minimum_interval_secs;
/* (Re)define PIN_GPS_EN for your board. */
uint32_t gps_en_gpio;
} meshtastic_Config_PositionConfig;
/* Power Config\
@@ -531,8 +539,8 @@ 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}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 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}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 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_IpV4Config_init_default {0, 0, 0, 0}
@@ -540,8 +548,8 @@ 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}}
#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}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 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}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 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_IpV4Config_init_zero {0, 0, 0, 0}
@@ -559,6 +567,7 @@ extern "C" {
#define meshtastic_Config_DeviceConfig_node_info_broadcast_secs_tag 7
#define meshtastic_Config_DeviceConfig_double_tap_as_button_press_tag 8
#define meshtastic_Config_DeviceConfig_is_managed_tag 9
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
#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
@@ -570,6 +579,7 @@ extern "C" {
#define meshtastic_Config_PositionConfig_tx_gpio_tag 9
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_distance_tag 10
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11
#define meshtastic_Config_PositionConfig_gps_en_gpio_tag 12
#define meshtastic_Config_PowerConfig_is_power_saving_tag 1
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
@@ -654,7 +664,8 @@ X(a, STATIC, SINGULAR, UINT32, buzzer_gpio, 5) \
X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6) \
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, is_managed, 9) \
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10)
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
@@ -669,7 +680,8 @@ X(a, STATIC, SINGULAR, UINT32, position_flags, 7) \
X(a, STATIC, SINGULAR, UINT32, rx_gpio, 8) \
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11)
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11) \
X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12)
#define meshtastic_Config_PositionConfig_CALLBACK NULL
#define meshtastic_Config_PositionConfig_DEFAULT NULL
@@ -769,12 +781,12 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
/* Maximum encoded size of messages (where known) */
#define meshtastic_Config_BluetoothConfig_size 10
#define meshtastic_Config_DeviceConfig_size 30
#define meshtastic_Config_DeviceConfig_size 32
#define meshtastic_Config_DisplayConfig_size 28
#define meshtastic_Config_LoRaConfig_size 77
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
#define meshtastic_Config_NetworkConfig_size 195
#define meshtastic_Config_PositionConfig_size 54
#define meshtastic_Config_PositionConfig_size 60
#define meshtastic_Config_PowerConfig_size 40
#define meshtastic_Config_size 198

View File

@@ -316,7 +316,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
#define meshtastic_DeviceState_size 16854
#define meshtastic_NodeInfoLite_size 151
#define meshtastic_NodeRemoteHardwarePin_size 29
#define meshtastic_OEMStore_size 3210
#define meshtastic_OEMStore_size 3218
#define meshtastic_PositionLite_size 28
#ifdef __cplusplus

View File

@@ -174,7 +174,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define meshtastic_LocalConfig_size 455
#define meshtastic_LocalConfig_size 463
#define meshtastic_LocalModuleConfig_size 609
#ifdef __cplusplus

View File

@@ -113,6 +113,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_PICOMPUTER_S3 = 52,
/* Heltec HT-CT62 with ESP32-C3 CPU and SX1262 LoRa */
meshtastic_HardwareModel_HELTEC_HT62 = 53,
/* E22-900M series modules with ESP32-S3 */
meshtastic_HardwareModel_E22_900M_S3 = 54,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */

View File

@@ -69,7 +69,8 @@ typedef enum _meshtastic_PortNum {
NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate.
This marker comes from the 'moduleConfig.audio.bitrate' enum minus one. */
meshtastic_PortNum_AUDIO_APP = 9,
/* Same as Text Message but originating from Detection Sensor Module. */
/* Same as Text Message but originating from Detection Sensor Module.
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9 */
meshtastic_PortNum_DETECTION_SENSOR_APP = 10,
/* Provides a 'ping' service that replies to any packet it receives.
Also serves as a small example module.
@@ -90,7 +91,8 @@ typedef enum _meshtastic_PortNum {
ENCODING: Protobuf */
meshtastic_PortNum_STORE_FORWARD_APP = 65,
/* Optional port for messages for the range test module.
ENCODING: ASCII Plaintext */
ENCODING: ASCII Plaintext
NOTE: This portnum traffic is not sent to the public MQTT starting at firmware version 2.2.9 */
meshtastic_PortNum_RANGE_TEST_APP = 66,
/* Provides a format to send and receive telemetry data from the Meshtastic network.
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com

View File

@@ -31,7 +31,7 @@
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)
#include "modules/ExternalNotificationModule.h"
#include "modules/RangeTestModule.h"
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2)
#include "modules/SerialModule.h"
#endif
#endif
@@ -60,9 +60,15 @@ void setupModules()
new ReplyModule();
#if HAS_BUTTON
rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1();
rotaryEncoderInterruptImpl1->init();
if (!rotaryEncoderInterruptImpl1->init()) {
delete rotaryEncoderInterruptImpl1;
rotaryEncoderInterruptImpl1 = nullptr;
}
upDownInterruptImpl1 = new UpDownInterruptImpl1();
upDownInterruptImpl1->init();
if (!upDownInterruptImpl1->init()) {
delete upDownInterruptImpl1;
upDownInterruptImpl1 = nullptr;
}
cardKbI2cImpl = new CardKbI2cImpl();
cardKbI2cImpl->init();
#ifdef INPUTBROKER_MATRIX_TYPE
@@ -86,7 +92,8 @@ void setupModules()
new AirQualityTelemetryModule();
}
#endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
!defined(CONFIG_IDF_TARGET_ESP32C3)
new SerialModule();
#endif
#ifdef ARCH_ESP32

View File

@@ -40,7 +40,9 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
meshtastic_MeshPacket *p = allocReply();
if (p) { // Check whether we didn't ignore it
p->to = dest;
p->decoded.want_response = wantReplies;
p->decoded.want_response = (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
wantReplies;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
if (channel > 0) {
LOG_DEBUG("sending ourNodeInfo to channel %d\n", channel);

View File

@@ -1,4 +1,5 @@
#include "PositionModule.h"
#include "GPS.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
@@ -7,6 +8,8 @@
#include "airtime.h"
#include "configuration.h"
#include "gps/GeoCoord.h"
#include "sleep.h"
#include "target_specific.h"
PositionModule *positionModule;
@@ -14,8 +17,22 @@ PositionModule::PositionModule()
: ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg),
concurrency::OSThread("PositionModule")
{
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)
setIntervalFromNow(60 * 1000);
// Power saving trackers should clear their position on startup to avoid waking up and sending a stale position
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER && config.power.is_power_saving) {
clearPosition();
}
}
void PositionModule::clearPosition()
{
LOG_DEBUG("Clearing position on startup for sleepy tracker (ー。ー) zzz\n");
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
node->position.latitude_i = 0;
node->position.longitude_i = 0;
}
bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Position *pptr)
@@ -27,18 +44,19 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
// FIXME this can in fact happen with packets sent from EUD (src=RX_SRC_USER)
// to set fixed location, EUD-GPS location or just the time (see also issue #900)
bool isLocal = false;
if (nodeDB.getNodeNum() == getFrom(&mp)) {
LOG_DEBUG("Incoming update from MYSELF\n");
// LOG_DEBUG("Ignored an incoming update from MYSELF\n");
// return false;
isLocal = true;
nodeDB.setLocalPosition(p);
}
// Log packet size and list of fields
LOG_INFO("POSITION node=%08x l=%d %s%s%s%s%s%s%s%s%s%s%s%s%s\n", getFrom(&mp), mp.decoded.payload.size,
p.latitude_i ? "LAT " : "", p.longitude_i ? "LON " : "", p.altitude ? "MSL " : "", p.altitude_hae ? "HAE " : "",
p.altitude_geoidal_separation ? "GEO " : "", p.PDOP ? "PDOP " : "", p.HDOP ? "HDOP " : "", p.VDOP ? "VDOP " : "",
p.sats_in_view ? "SIV " : "", p.fix_quality ? "FXQ " : "", p.fix_type ? "FXT " : "", p.timestamp ? "PTS " : "",
p.time ? "TIME " : "");
// 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);
if (p.time) {
struct timeval tv;
@@ -47,7 +65,8 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
tv.tv_sec = secs;
tv.tv_usec = 0;
perhapsSetRTC(RTCQualityFromNet, &tv);
// Set from phone RTC Quality to RTCQualityNTP since it should be approximately so
perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv);
}
nodeDB.updatePosition(getFrom(&mp), p);
@@ -77,8 +96,9 @@ meshtastic_MeshPacket *PositionModule::allocReply()
// Populate a Position struct with ONLY the requested fields
meshtastic_Position p = meshtastic_Position_init_default; // Start with an empty structure
// if localPosition is totally empty, put our last saved position (lite) in there
if (localPosition.latitude_i == 0 && localPosition.longitude_i == 0) {
localPosition = ConvertToPosition(node->position);
nodeDB.setLocalPosition(ConvertToPosition(node->position));
}
localPosition.seq_number++;
@@ -148,7 +168,7 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
}
p->to = dest;
p->decoded.want_response = wantReplies;
p->decoded.want_response = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ? false : wantReplies;
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER)
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
else
@@ -159,75 +179,142 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
p->channel = channel;
service.sendToMesh(p, RX_SRC_LOCAL, true);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER && config.power.is_power_saving) {
LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n");
sleepOnNextExecution = true;
setIntervalFromNow(5000);
}
}
#define RUNONCE_INTERVAL 5000;
int32_t PositionModule::runOnce()
{
if (sleepOnNextExecution == true) {
sleepOnNextExecution = false;
uint32_t nightyNightMs = getConfiguredOrDefaultMs(config.position.position_broadcast_secs);
LOG_DEBUG("Sleeping for %ims, then awaking to send position again.\n", nightyNightMs);
doDeepSleep(nightyNightMs, false);
}
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
// We limit our GPS broadcasts to a max rate
uint32_t now = millis();
uint32_t intervalMs = getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs);
uint32_t msSinceLastSend = now - lastGpsSend;
// Only send packets if the channel util. is less than 25% utilized or we're a tracker with less than 40% utilized.
if (!airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
return RUNONCE_INTERVAL;
}
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
// Only send packets if the channel is less than 40% utilized.
if (airTime->isTxAllowedChannelUtil()) {
if (hasValidPosition(node)) {
lastGpsSend = now;
if (hasValidPosition(node)) {
lastGpsSend = now;
lastGpsLatitude = node->position.latitude_i;
lastGpsLongitude = node->position.longitude_i;
lastGpsLatitude = node->position.latitude_i;
lastGpsLongitude = node->position.longitude_i;
// If we changed channels, ask everyone else for their latest info
// 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);
}
} else if (config.position.position_broadcast_smart_enabled) {
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
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 =
getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
auto smartPosition = getDistanceTraveledSinceLastSend(node->position);
if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) {
bool requestReplies = currentGeneration != radioGeneration;
currentGeneration = radioGeneration;
LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies);
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);
}
}
} else if (config.position.position_broadcast_smart_enabled) {
// Only send packets if the channel is less than 25% utilized or we're a tracker.
if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) {
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position
if (hasValidPosition(node2)) {
// The minimum distance to travel before we are able to send a new position packet.
const uint32_t distanceTravelThreshold =
config.position.broadcast_smart_minimum_distance > 0 ? config.position.broadcast_smart_minimum_distance : 100;
// 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;
// The minimum time (in seconds) that would pass before we are able to send a new position packet.
const uint32_t minimumTimeThreshold =
getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);
// Determine the distance in meters between two points on the globe
float distanceTraveledSinceLastSend =
GeoCoord::latLongToMeter(lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7, node->position.latitude_i * 1e-7,
node->position.longitude_i * 1e-7);
if ((abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold) && msSinceLastSend >= minimumTimeThreshold) {
bool requestReplies = currentGeneration != radioGeneration;
currentGeneration = radioGeneration;
LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, "
"minTimeInterval=%ims)\n",
localPosition.timestamp, abs(distanceTraveledSinceLastSend), distanceTravelThreshold,
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
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;
}
/* Update lastGpsSend to now. This means if the device is stationary, then
getPref_position_broadcast_secs will still apply.
*/
lastGpsSend = now;
}
}
}
return 5000; // to save power only wake for our callback occasionally
return RUNONCE_INTERVAL; // to save power only wake for our callback occasionally
}
struct SmartPosition PositionModule::getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition)
{
// The minimum distance to travel before we are able to send a new position packet.
const uint32_t distanceTravelThreshold = getConfiguredOrDefault(config.position.broadcast_smart_minimum_distance, 100);
// Determine the distance in meters between two points on the globe
float distanceTraveledSinceLastSend = GeoCoord::latLongToMeter(
lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7, currentPosition.latitude_i * 1e-7, currentPosition.longitude_i * 1e-7);
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("--------LAST POSITION------------------------------------\n");
LOG_DEBUG("lastGpsLatitude=%i, lastGpsLatitude=%i\n", lastGpsLatitude, lastGpsLongitude);
LOG_DEBUG("--------CURRENT POSITION---------------------------------\n");
LOG_DEBUG("currentPosition.latitude_i=%i, currentPosition.longitude_i=%i\n", lastGpsLatitude, lastGpsLongitude);
LOG_DEBUG("--------SMART POSITION-----------------------------------\n");
LOG_DEBUG("hasTraveledOverThreshold=%i, distanceTraveled=%d, distanceThreshold=% u\n",
abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold, abs(distanceTraveledSinceLastSend),
distanceTravelThreshold);
if (abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold) {
LOG_DEBUG("\n\n\nSMART SEEEEEEEEENDING\n\n\n");
}
#endif
return SmartPosition{.distanceTraveled = abs(distanceTraveledSinceLastSend),
.distanceThreshold = distanceTravelThreshold,
.hasTraveledOverThreshold = abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold};
}
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);
// 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;
}
}
}

View File

@@ -31,6 +31,8 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
*/
void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0);
void handleNewPosition();
protected:
/** Called to handle a particular incoming message
@@ -44,6 +46,18 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
/** Does our periodic broadcast */
virtual int32_t runOnce() override;
private:
struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition);
/** Only used in power saving trackers for now */
void clearPosition();
};
extern PositionModule *positionModule;
struct SmartPosition {
float distanceTraveled;
uint32_t distanceThreshold;
bool hasTraveledOverThreshold;
};
extern PositionModule *positionModule;

View File

@@ -44,9 +44,10 @@
*/
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
!defined(CONFIG_IDF_TARGET_ESP32C3)
#define RX_BUFFER 128
#define RX_BUFFER 256
#define TIMEOUT 250
#define BAUD 38400
#define ACK 1
@@ -141,7 +142,12 @@ int32_t SerialModule::runOnce()
}
#elif !defined(TTGO_T_ECHO)
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
#ifdef ARCH_RP2040
Serial2.setFIFOSize(RX_BUFFER);
Serial2.setPinout(moduleConfig.serial.txd, moduleConfig.serial.rxd);
#else
Serial2.setPins(moduleConfig.serial.rxd, moduleConfig.serial.txd);
#endif
Serial2.begin(baud, SERIAL_8N1);
Serial2.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT);
} else {
@@ -182,7 +188,7 @@ int32_t SerialModule::runOnce()
}
}
}
#ifndef TTGO_T_ECHO
#if !defined(TTGO_T_ECHO)
else {
while (Serial2.available()) {
serialPayloadSize = Serial2.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);

View File

@@ -8,7 +8,8 @@
#include <Arduino.h>
#include <functional>
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \
!defined(CONFIG_IDF_TARGET_ESP32C3)
class SerialModule : public StreamAPI, private concurrency::OSThread
{
@@ -74,4 +75,4 @@ class SerialModuleRadio : public MeshModule
extern SerialModuleRadio *serialModuleRadio;
#endif
#endif

View File

@@ -8,6 +8,8 @@
#include "configuration.h"
#include "main.h"
#include "power.h"
#include "sleep.h"
#include "target_specific.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
@@ -51,6 +53,13 @@ SHT31Sensor sht31Sensor;
int32_t EnvironmentTelemetryModule::runOnce()
{
if (sleepOnNextExecution == true) {
sleepOnNextExecution = false;
uint32_t nightyNightMs = getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
LOG_DEBUG("Sleeping for %ims, then awaking to send metrics again.\n", nightyNightMs);
doDeepSleep(nightyNightMs, true);
}
uint32_t result = UINT32_MAX;
/*
Uncomment the preferences below if you want to use the module
@@ -266,6 +275,12 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
} else {
LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) {
LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n");
sleepOnNextExecution = true;
setIntervalFromNow(5000);
}
}
}
return valid;

View File

@@ -455,6 +455,13 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, ChannelIndex chIndex)
{
auto &ch = channels.getByIndex(chIndex);
if (&mp.decoded && strcmp(moduleConfig.mqtt.address, default_mqtt_address) == 0 &&
(mp.decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP ||
mp.decoded.portnum == meshtastic_PortNum_DETECTION_SENSOR_APP)) {
LOG_DEBUG("MQTT onSend - Ignoring range test or detection sensor message on public mqtt\n");
return;
}
if (ch.settings.uplink_enabled) {
const char *channelId = channels.getGlobalId(chIndex); // FIXME, for now we just use the human name for the channel
@@ -509,34 +516,34 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
JSONObject msgPayload;
JSONObject jsonObj;
switch (mp->decoded.portnum) {
case meshtastic_PortNum_TEXT_MESSAGE_APP: {
msgType = "text";
// convert bytes to string
LOG_DEBUG("got text message of size %u\n", mp->decoded.payload.size);
char payloadStr[(mp->decoded.payload.size) + 1];
memcpy(payloadStr, mp->decoded.payload.bytes, mp->decoded.payload.size);
payloadStr[mp->decoded.payload.size] = 0; // null terminated string
// check if this is a JSON payload
JSONValue *json_value = JSON::Parse(payloadStr);
if (json_value != NULL) {
LOG_INFO("text message payload is of type json\n");
// if it is, then we can just use the json object
jsonObj["payload"] = json_value;
} else {
// if it isn't, then we need to create a json object
// with the string as the value
LOG_INFO("text message payload is of type plaintext\n");
msgPayload["text"] = new JSONValue(payloadStr);
jsonObj["payload"] = new JSONValue(msgPayload);
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
switch (mp->decoded.portnum) {
case meshtastic_PortNum_TEXT_MESSAGE_APP: {
msgType = "text";
// convert bytes to string
LOG_DEBUG("got text message of size %u\n", mp->decoded.payload.size);
char payloadStr[(mp->decoded.payload.size) + 1];
memcpy(payloadStr, mp->decoded.payload.bytes, mp->decoded.payload.size);
payloadStr[mp->decoded.payload.size] = 0; // null terminated string
// check if this is a JSON payload
JSONValue *json_value = JSON::Parse(payloadStr);
if (json_value != NULL) {
LOG_INFO("text message payload is of type json\n");
// if it is, then we can just use the json object
jsonObj["payload"] = json_value;
} else {
// if it isn't, then we need to create a json object
// with the string as the value
LOG_INFO("text message payload is of type plaintext\n");
msgPayload["text"] = new JSONValue(payloadStr);
jsonObj["payload"] = new JSONValue(msgPayload);
}
break;
}
break;
}
case meshtastic_PortNum_TELEMETRY_APP: {
msgType = "telemetry";
meshtastic_Telemetry scratch;
meshtastic_Telemetry *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
case meshtastic_PortNum_TELEMETRY_APP: {
msgType = "telemetry";
meshtastic_Telemetry scratch;
meshtastic_Telemetry *decoded = NULL;
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Telemetry_msg, &scratch)) {
decoded = &scratch;
@@ -557,14 +564,12 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
} else {
LOG_ERROR("Error decoding protobuf for telemetry message!\n");
}
};
break;
}
case meshtastic_PortNum_NODEINFO_APP: {
msgType = "nodeinfo";
meshtastic_User scratch;
meshtastic_User *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
break;
}
case meshtastic_PortNum_NODEINFO_APP: {
msgType = "nodeinfo";
meshtastic_User scratch;
meshtastic_User *decoded = NULL;
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_User_msg, &scratch)) {
decoded = &scratch;
@@ -576,14 +581,12 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
} else {
LOG_ERROR("Error decoding protobuf for nodeinfo message!\n");
}
};
break;
}
case meshtastic_PortNum_POSITION_APP: {
msgType = "position";
meshtastic_Position scratch;
meshtastic_Position *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
break;
}
case meshtastic_PortNum_POSITION_APP: {
msgType = "position";
meshtastic_Position scratch;
meshtastic_Position *decoded = NULL;
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Position_msg, &scratch)) {
decoded = &scratch;
@@ -620,15 +623,12 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
} else {
LOG_ERROR("Error decoding protobuf for position message!\n");
}
};
break;
}
case meshtastic_PortNum_WAYPOINT_APP: {
msgType = "position";
meshtastic_Waypoint scratch;
meshtastic_Waypoint *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
break;
}
case meshtastic_PortNum_WAYPOINT_APP: {
msgType = "position";
meshtastic_Waypoint scratch;
meshtastic_Waypoint *decoded = NULL;
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
decoded = &scratch;
@@ -643,14 +643,12 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
} else {
LOG_ERROR("Error decoding protobuf for position message!\n");
}
};
break;
}
case meshtastic_PortNum_NEIGHBORINFO_APP: {
msgType = "neighborinfo";
meshtastic_NeighborInfo scratch;
meshtastic_NeighborInfo *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
break;
}
case meshtastic_PortNum_NEIGHBORINFO_APP: {
msgType = "neighborinfo";
meshtastic_NeighborInfo scratch;
meshtastic_NeighborInfo *decoded = NULL;
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_NeighborInfo_msg,
&scratch)) {
@@ -671,12 +669,14 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
} else {
LOG_ERROR("Error decoding protobuf for neighborinfo message!\n");
}
};
break;
}
// add more packet types here if needed
default:
break;
break;
}
// add more packet types here if needed
default:
break;
}
} else {
LOG_WARN("Couldn't convert encrypted payload of MeshPacket to JSON\n");
}
jsonObj["id"] = new JSONValue((uint)mp->id);

View File

@@ -193,16 +193,12 @@ void cpuDeepSleep(uint32_t msecToWake)
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
#endif
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
// to detect wake and in normal operation the external part drives them hard.
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
// to detect wake and in normal operation the external part drives them hard.
#ifdef BUTTON_PIN
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
#if SOC_RTCIO_HOLD_SUPPORTED
uint64_t gpioMask = (1ULL << config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
uint64_t gpioMask = (1ULL << (config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
#endif
#ifdef BUTTON_NEED_PULLUP
@@ -218,6 +214,9 @@ void cpuDeepSleep(uint32_t msecToWake)
#endif
#endif
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
esp_deep_sleep_start(); // TBD mA sleep current (battery)
}

View File

@@ -180,14 +180,24 @@ void cpuDeepSleep(uint32_t msecToWake)
digitalWrite(AQ_SET_PIN, LOW);
#endif
#endif
// FIXME, use system off mode with ram retention for key state?
// FIXME, use non-init RAM per
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
auto ok = sd_power_system_off();
if (ok != NRF_SUCCESS) {
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!\n");
NRF_POWER->SYSTEMOFF = 1;
// Sleepy trackers or sensors can low power "sleep"
// Don't enter this if we're sleeping portMAX_DELAY, since that's a shutdown event
if (msecToWake != portMAX_DELAY &&
(config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR) &&
config.power.is_power_saving == true) {
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
delay(msecToWake);
NVIC_SystemReset();
} else {
// FIXME, use system off mode with ram retention for key state?
// FIXME, use non-init RAM per
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
auto ok = sd_power_system_off();
if (ok != NRF_SUCCESS) {
LOG_ERROR("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!\n");
NRF_POWER->SYSTEMOFF = 1;
}
}
// The following code should not be run, because we are off

View File

@@ -90,39 +90,34 @@ void setLed(bool ledOn)
#endif
}
void setGPSPower(bool on)
{
LOG_INFO("Setting GPS power=%d\n", on);
#ifdef PIN_GPS_EN
digitalWrite(PIN_GPS_EN, on ? 1 : 0);
#endif
#ifdef HAS_PMU
if (pmu_found && PMU) {
uint8_t model = PMU->getChipModel();
if (model == XPOWERS_AXP2101) {
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// t-beam v1.2 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO3) : PMU->disablePowerOutput(XPOWERS_ALDO3);
} else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) {
// t-beam-s3-core GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4);
}
} else if (model == XPOWERS_AXP192) {
// t-beam v1.1 GNSS power channel
on ? PMU->enablePowerOutput(XPOWERS_LDO3) : PMU->disablePowerOutput(XPOWERS_LDO3);
}
}
#endif
}
// Perform power on init that we do on each wake from deep sleep
void initDeepSleep()
{
#ifdef ARCH_ESP32
bootCount++;
const char *reason;
wakeCause = esp_sleep_get_wakeup_cause();
switch (wakeCause) {
case ESP_SLEEP_WAKEUP_EXT0:
reason = "ext0 RTC_IO";
break;
case ESP_SLEEP_WAKEUP_EXT1:
reason = "ext1 RTC_CNTL";
break;
case ESP_SLEEP_WAKEUP_TIMER:
reason = "timer";
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
reason = "touchpad";
break;
case ESP_SLEEP_WAKEUP_ULP:
reason = "ULP program";
break;
default:
reason = "reset";
break;
}
/*
Not using yet because we are using wake on all buttons being low
@@ -133,7 +128,6 @@ void initDeepSleep()
#ifdef DEBUG_PORT
// If we booted because our timer ran out or the user pressed reset, send those as fake events
const char *reason = "reset"; // our best guess
RESET_REASON hwReason = rtc_get_reset_reason(0);
if (hwReason == RTCWDT_BROWN_OUT_RESET)
@@ -145,9 +139,6 @@ void initDeepSleep()
if (hwReason == TG1WDT_SYS_RESET)
reason = "intWatchdog";
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
reason = "timeout";
LOG_INFO("Booted, wake cause %d (boot count %d), reset_reason=%s\n", wakeCause, bootCount, reason);
#endif
#endif
@@ -162,16 +153,18 @@ bool doPreflightSleep()
}
/// Tell devices we are going to sleep and wait for them to handle things
static void waitEnterSleep()
static void waitEnterSleep(bool skipPreflight = false)
{
uint32_t now = millis();
while (!doPreflightSleep()) {
delay(100); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives)
if (!skipPreflight) {
uint32_t now = millis();
while (!doPreflightSleep()) {
delay(100); // Kinda yucky - wait until radio says say we can shutdown (finished in process sends/receives)
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_SLEEP_ENTER_WAIT);
assert(0); // FIXME - for now we just restart, need to fix bug #167
break;
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_SLEEP_ENTER_WAIT);
assert(0); // FIXME - for now we just restart, need to fix bug #167
break;
}
}
}
@@ -182,7 +175,7 @@ static void waitEnterSleep()
notifySleep.notifyObservers(NULL);
}
void doDeepSleep(uint32_t msecToWake)
void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
{
if (INCLUDE_vTaskSuspend && (msecToWake == portMAX_DELAY)) {
LOG_INFO("Entering deep sleep forever\n");
@@ -192,7 +185,7 @@ void doDeepSleep(uint32_t msecToWake)
// not using wifi yet, but once we are this is needed to shutoff the radio hw
// esp_wifi_stop();
waitEnterSleep();
waitEnterSleep(skipPreflight);
notifyDeepSleep.notifyObservers(NULL);
screen->doDeepSleep(); // datasheet says this will draw only 10ua
@@ -200,7 +193,8 @@ void doDeepSleep(uint32_t msecToWake)
nodeDB.saveToDisk();
// Kill GPS power completely (even if previously we just had it in sleep mode)
setGPSPower(false);
if (gps)
gps->setGPSPower(false, false, 0);
setLed(false);
@@ -208,7 +202,13 @@ void doDeepSleep(uint32_t msecToWake)
digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power
#endif
#ifdef VEXT_ENABLE
#if defined(VEXT_ENABLE_V03)
if (heltec_version == 3) {
digitalWrite(VEXT_ENABLE_V03, 1); // turn off the display power
} else {
digitalWrite(VEXT_ENABLE_V05, 0); // turn off the display power
}
#elif defined(VEXT_ENABLE)
digitalWrite(VEXT_ENABLE, 1); // turn off the display power
#endif
@@ -254,7 +254,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
{
// LOG_DEBUG("Enter light sleep\n");
waitEnterSleep();
waitEnterSleep(false);
uint64_t sleepUsec = sleepMsec * 1000LL;

View File

@@ -4,7 +4,7 @@
#include "Observer.h"
#include "configuration.h"
void doDeepSleep(uint32_t msecToWake), cpuDeepSleep(uint32_t msecToWake);
void doDeepSleep(uint32_t msecToWake, bool skipPreflight), cpuDeepSleep(uint32_t msecToWake);
#ifdef ARCH_ESP32
#include "esp_sleep.h"
@@ -18,8 +18,6 @@ extern esp_sleep_source_t wakeCause;
extern XPowersLibInterface *PMU;
#endif
void setGPSPower(bool on);
// Perform power on init that we do on each wake from deep sleep
void initDeepSleep();

View File

@@ -47,12 +47,12 @@ extern "C" {
#define PIN_LED2 (0 + 6) // Built in Green P0.06
// Green Built in LED1
//#define PIN_LED1 (0 + 6) // LED1 P1.15
// #define PIN_LED1 (0 + 6) // LED1 P1.15
// RGB NeoPixel LED2
//#define PIN_LED1 (0 + 8) Red
//#define PIN_LED1 (32 + 9) Green
//#define PIN_LED1 (0 + 12) Blue
// #define PIN_LED1 (0 + 8) Red
// #define PIN_LED1 (32 + 9) Green
// #define PIN_LED1 (0 + 12) Blue
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
@@ -113,7 +113,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
* eink display pins
*/
//#define PIN_EINK_EN (-1)
// #define PIN_EINK_EN (-1)
#define PIN_EINK_EN (0 + 6) // Turn on the Green built in LED
#define PIN_EINK_CS (32) // EPD_CS
#define PIN_EINK_BUSY (20) // EPD_BUSY
@@ -140,7 +140,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_RESET (32 + 15) // LORA_RESET P1.15
#define SX126X_TXEN (32 + 13) // TXEN P1.13 NiceRF 868 dont use
#define SX126X_RXEN (32 + 10) // RXEN P1.10 NiceRF 868 dont use
#define SX126X_E22
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define PIN_GPS_EN (-1)
#define PIN_GPS_PPS (-1) // Pulse per second input from the GPS

View File

@@ -73,7 +73,7 @@ static const uint8_t AREF = PIN_AREF;
*/
#define SPI_INTERFACES_COUNT 2
// here
//#define SPI_INTERFACES_COUNT 1
// #define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (0 + 31) // MISO P0.31
#define PIN_SPI_MOSI (0 + 30) // MOSI P0.30
@@ -94,7 +94,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
* eink display pins
*/
//#define PIN_EINK_EN (-1)
// #define PIN_EINK_EN (-1)
#define PIN_EINK_CS (0 + 3) // EPD_CS
#define PIN_EINK_BUSY (32 + 11) // EPD_BUSY
#define PIN_EINK_DC (32 + 13) // EPD_D/C
@@ -118,8 +118,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX128X_CS (0 + 23)
#define SX128X_DIO1 (0 + 4)
#define SX128X_BUSY (0 + 7)
//#define SX128X_TXEN (32 + 9)
//#define SX128X_RXEN (0 + 12)
// #define SX128X_TXEN (32 + 9)
// #define SX128X_RXEN (0 + 12)
#define SX128X_RESET LORA_RESET
#define PIN_GPS_EN (-1)

View File

@@ -96,8 +96,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX128X_CS (0 + 23)
#define SX128X_DIO1 (0 + 4)
#define SX128X_BUSY (0 + 7)
//#define SX128X_TXEN (32 + 9)
//#define SX128X_RXEN (0 + 12)
// #define SX128X_TXEN (32 + 9)
// #define SX128X_RXEN (0 + 12)
#define SX128X_RESET LORA_RESET
#define PIN_GPS_EN (-1)

View File

@@ -23,7 +23,9 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY 10
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // use DIO2 as RF switch
#define SX126X_DIO2_AS_RF_SWITCH // use DIO2 as RF switch
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define HAS_GPS 0
#undef GPS_RX_PIN

View File

@@ -27,11 +27,11 @@ static const uint8_t SCK = 21;
static const uint8_t MOSI = 38;
static const uint8_t SS = 17;
//#define SPI_MOSI (11)
//#define SPI_SCK (14)
//#define SPI_MISO (2)
//#define SPI_CS (13)
// #define SPI_MOSI (11)
// #define SPI_SCK (14)
// #define SPI_MISO (2)
// #define SPI_CS (13)
//#define SDCARD_CS SPI_CS
// #define SDCARD_CS SPI_CS
#endif /* Pins_Arduino_h */
#endif /* Pins_Arduino_h */

View File

@@ -2,10 +2,10 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
//#define HAS_SCREEN 0
// #define HAS_SCREEN 0
//#define HAS_SDCARD
//#define SDCARD_USE_SPI1
// #define HAS_SDCARD
// #define SDCARD_USE_SPI1
#define USE_SSD1306
#define I2C_SDA 12
@@ -14,13 +14,13 @@
#define LED_PIN 46
#define LED_STATE_ON 0 // State when LED is litted
//#define BUTTON_PIN 15 // Pico OLED 1.3 User key 0 - removed User key 1 (17)
// #define BUTTON_PIN 15 // Pico OLED 1.3 User key 0 - removed User key 1 (17)
#define BUTTON_PIN 40
//#define BUTTON_PIN 0 // This is the BOOT button pad at the moment
//#define BUTTON_NEED_PULLUP
// #define BUTTON_PIN 0 // This is the BOOT button pad at the moment
// #define BUTTON_NEED_PULLUP
//#define USE_RF95 // RFM95/SX127x
// #define USE_RF95 // RFM95/SX127x
#undef RF95_SCK
#undef RF95_MISO
@@ -43,10 +43,11 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_BUSY
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
//#define USE_SX1280
// #define USE_SX1280
#ifdef USE_SX1280
#define RF95_MISO 1
#define RF95_SCK 3
@@ -61,13 +62,13 @@
#define SX128X_RESET LORA_RESET
#endif
//#define USE_EINK
// #define USE_EINK
/*
* eink display pins
*/
//#define PIN_EINK_CS
//#define PIN_EINK_BUSY
//#define PIN_EINK_DC
//#define PIN_EINK_RES (-1)
//#define PIN_EINK_SCLK 3
//#define PIN_EINK_MOSI 4
// #define PIN_EINK_CS
// #define PIN_EINK_BUSY
// #define PIN_EINK_DC
// #define PIN_EINK_RES (-1)
// #define PIN_EINK_SCLK 3
// #define PIN_EINK_MOSI 4

View File

@@ -31,10 +31,13 @@
// PINS FOR THE 900M22S
#define LORA_DIO1 26 // IRQ for SX1262/SX1268
#define LORA_DIO2 22 // BUSY for SX1262/SX1268
#define LORA_TXEN NOT_A_PIN // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level
#define LORA_RXEN 17 // Input - RF switch RX control, connecting external MCU IO, valid in high level
#define LORA_DIO1 26 // IRQ for SX1262/SX1268
#define LORA_DIO2 22 // BUSY for SX1262/SX1268
// NOT_A_PIN is treated as RADIOLIB_NC due to how they are defined, best to use RADIOLIB_NC directly
#define LORA_TXEN RADIOLIB_NC // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level
// E22_TXEN_CONNECTED_TO_DIO2 wasn't defined, so RXEN wasn't controlled. Commented it out to maintain behavior, but shouldn't be.
// Need to comment out defining SX126X_RXEN as LORA_RXEN too
// #define LORA_RXEN 17 // Input - RF switch RX control, connecting external MCU IO, valid in high level
#undef RF95_NSS
#define RF95_NSS 16
#define SX126X_BUSY 22
@@ -53,7 +56,7 @@
*/
// RX/TX for RFM95/SX127x
#define RF95_RXEN LORA_RXEN
// #define RF95_RXEN LORA_RXEN
#define RF95_TXEN LORA_TXEN
// #define RF95_TCXO <GPIO#>
@@ -61,12 +64,13 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_RESET LORA_RESET
#define SX126X_RXEN LORA_RXEN
// #define SX126X_RXEN LORA_RXEN
#define SX126X_TXEN LORA_TXEN
// supported modules list
//#define USE_RF95 // RFM95/SX127x
// #define USE_RF95 // RFM95/SX127x
#define USE_SX1262
//#define USE_SX1268
//#define USE_LLCC68
#define SX126X_E22
// #define USE_SX1268
// #define USE_LLCC68
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -37,8 +37,9 @@
#define SX126X_RESET LORA_RESET
#define SX126X_RXEN 14
#define SX126X_TXEN RADIOLIB_NC
#define E22_TXEN_CONNECTED_TO_DIO2 1
#define SX126X_DIO2_AS_RF_SWITCH
// Set lora.tx_power to 13 for Hydra or other E22 900M30S target due to PA
#define SX126X_MAX_POWER 13
#define SX126X_E22
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -52,5 +52,5 @@
#ifdef EBYTE_E22
// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
// (which is the default for the sx1262interface code)
#define SX126X_E22
#endif
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif

View File

@@ -53,5 +53,5 @@
#ifdef EBYTE_E22
// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
// (which is the default for the sx1262interface code)
#define SX126X_E22
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif

View File

@@ -105,7 +105,7 @@ extern "C" {
#ifdef EBYTE_E22
// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
// (which is the default for the sx1262interface code)
#define SX126X_E22
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
#ifdef __cplusplus

View File

@@ -33,4 +33,5 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_BUSY
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -33,4 +33,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -40,4 +40,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -5,6 +5,7 @@ upload_protocol = esp-builtin
build_flags =
${esp32s3_base.build_flags} -I variants/heltec_wireless_tracker
-DGPS_POWER_TOGGLE
lib_deps =
${esp32s3_base.lib_deps}

View File

@@ -9,9 +9,11 @@
#define ST7735_RESET 39
#define ST7735_MISO -1
#define ST7735_BUSY -1
#define ST7735_BL 45
#define ST7735_BL_V03 45
#define ST7735_BL_V05 21 /* V1.1 PCB marking */
#define ST7735_SPI_HOST SPI3_HOST
#define ST7735_BACKLIGHT_EN 45
#define ST7735_BACKLIGHT_EN_V03 45
#define ST7735_BACKLIGHT_EN_V05 21
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000
#define SCREEN_ROTATE
@@ -19,17 +21,20 @@
#define TFT_WIDTH 80
#define TFT_OFFSET_X 26
#define TFT_OFFSET_Y 0
#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT
#define VTFT_CTRL_V03 46 // Heltec Tracker needs this pulled low for TFT
#define VTFT_CTRL_V05 -1
#define SCREEN_TRANSITION_FRAMERATE 1 // fps
#define DISPLAY_FORCE_SMALL_FONTS
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define VEXT_ENABLE_V03 Vext // active low, powers the oled display and the lora antenna boost
#define VEXT_ENABLE_V05 3 // active HIGH, powers the oled display
#define BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
#define ADC_MULTIPLIER 4.9
#define ADC_CTRL 2 // active HIGH, powers the voltage divider. Only on 1.1
#undef GPS_RX_PIN
#undef GPS_TX_PIN
@@ -37,7 +42,12 @@
#define GPS_TX_PIN 34
#define PIN_GPS_RESET 35
#define PIN_GPS_PPS 36
#define VGNSS_CTRL 37 // Heltec Tracker needs this pulled low for GPS
#define VGNSS_CTRL_V03 37 // Heltec Tracker needs this pulled low for GPS
#define VGNSS_CTRL_V05 -1 // Heltec Tracker needs this pulled low for GPS
#define PIN_GPS_EN VGNSS_CTRL_V03
#define GPS_EN_ACTIVE LOW
#define GPS_RESET_MODE LOW
#define GPS_UC6580
@@ -57,4 +67,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -8,8 +8,6 @@
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0
#define PIN_GPS_EN 46 // GPS power enable pin
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
@@ -32,4 +30,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -28,7 +28,7 @@
#define USE_LFXO
//#define USE_SEGGER
// #define USE_SEGGER
// Number of pins defined in PinDescription array
#define PINS_COUNT (16)
@@ -88,6 +88,7 @@
#define BATTERY_PIN 3
#define ADC_MULTIPLIER 1.436
#define SX126X_E22 // Not really an E22 but this board clones using DIO3 for tcxo control
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8 // Not really an E22 but this board clones using DIO3 for tcxo control
#endif

View File

@@ -134,7 +134,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_TXEN (31)
#define SX126X_POWER_EN \
(15) // FIXME, see warning hre https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay/blob/master/LORA_RELAY_NRF52840.ino
#define SX126X_E22 // Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
// Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define ST7735_RESET (11) // Output
#define ST7735_CS (12)

View File

@@ -154,7 +154,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_TXEN (31)
#define SX126X_POWER_EN \
(15) // FIXME, see warning hre https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay/blob/master/LORA_RELAY_NRF52840.ino
#define SX126X_E22 // Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
// Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// ST7565 SPI
#define ST7735_RESET (11) // Output
@@ -164,8 +165,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define ST7735_SDA (39) // actually spi MOSI
#define ST7735_SCK (37) // actually spi clk
#define PIN_GPS_WAKE 36 // Just kill GPS power when we want it to sleep? FIXME
#define GPS_WAKE_ACTIVE 0 // GPS Power output is active low
#define PIN_GPS_EN 36 // Just kill GPS power when we want it to sleep? FIXME
#define GPS_EN_ACTIVE 0 // GPS Power output is active low
// #define LORA_DISABLE_SENDING // The board can brownout during lora TX if you don't have a battery connected. Disable sending
// to allow USB power only based debugging

View File

@@ -4,7 +4,7 @@
#define BUTTON_PIN 3 // M5Stack STAMP C3 built in button
#define BUTTON_NEED_PULLUP
//#define HAS_SCREEN 0
// #define HAS_SCREEN 0
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
@@ -28,45 +28,46 @@
// WaveShare Core1262-868M OK
// https://www.waveshare.com/wiki/Core1262-868M
//#define USE_SX1262
//#define RF95_SCK 4
//#define RF95_MISO 5
//#define RF95_MOSI 6
//#define RF95_NSS 7
//#define LORA_DIO0 RADIOLIB_NC
//#define LORA_RESET 8
//#define LORA_DIO1 10
//#define LORA_DIO2 RADIOLIB_NC
//#define LORA_BUSY 18
//#define SX126X_CS RF95_NSS
//#define SX126X_DIO1 LORA_DIO1
//#define SX126X_BUSY LORA_BUSY
//#define SX126X_RESET LORA_RESET
//#define SX126X_E22
// #define USE_SX1262
// #define RF95_SCK 4
// #define RF95_MISO 5
// #define RF95_MOSI 6
// #define RF95_NSS 7
// #define LORA_DIO0 RADIOLIB_NC
// #define LORA_RESET 8
// #define LORA_DIO1 10
// #define LORA_DIO2 RADIOLIB_NC
// #define LORA_BUSY 18
// #define SX126X_CS RF95_NSS
// #define SX126X_DIO1 LORA_DIO1
// #define SX126X_BUSY LORA_BUSY
// #define SX126X_RESET LORA_RESET
// #define SX126X_DIO2_AS_RF_SWITCH
// #define SX126X_DIO3_TCXO_VOLTAGE 1.8
// SX128X 2.4 Ghz LoRa module Not OK - RadioLib issue ? still to confirm
//#define USE_SX1280
//#define RF95_SCK 4
//#define RF95_MISO 5
//#define RF95_MOSI 6
//#define RF95_NSS 7
//#define LORA_DIO0 -1
//#define LORA_DIO1 10
//#define LORA_DIO2 21
//#define LORA_RESET 8
//#define LORA_BUSY 1
//#define SX128X_CS RF95_NSS
//#define SX128X_DIO1 LORA_DIO1
//#define SX128X_BUSY LORA_BUSY
//#define SX128X_RESET LORA_RESET
//#define SX128X_MAX_POWER 10
// #define USE_SX1280
// #define RF95_SCK 4
// #define RF95_MISO 5
// #define RF95_MOSI 6
// #define RF95_NSS 7
// #define LORA_DIO0 -1
// #define LORA_DIO1 10
// #define LORA_DIO2 21
// #define LORA_RESET 8
// #define LORA_BUSY 1
// #define SX128X_CS RF95_NSS
// #define SX128X_DIO1 LORA_DIO1
// #define SX128X_BUSY LORA_BUSY
// #define SX128X_RESET LORA_RESET
// #define SX128X_MAX_POWER 10
// Not yet tested
//#define USE_EINK
//#define PIN_EINK_EN -1 // N/C
//#define PIN_EINK_CS 9 // EPD_CS
//#define PIN_EINK_BUSY 18 // EPD_BUSY
//#define PIN_EINK_DC 19 // EPD_D/C
//#define PIN_EINK_RES -1 // Connected but not needed
//#define PIN_EINK_SCLK 4 // EPD_SCLK
//#define PIN_EINK_MOSI 6 // EPD_MOSI
// #define USE_EINK
// #define PIN_EINK_EN -1 // N/C
// #define PIN_EINK_CS 9 // EPD_CS
// #define PIN_EINK_BUSY 18 // EPD_BUSY
// #define PIN_EINK_DC 19 // EPD_D/C
// #define PIN_EINK_RES -1 // Connected but not needed
// #define PIN_EINK_SCLK 4 // EPD_SCLK
// #define PIN_EINK_MOSI 6 // EPD_MOSI

View File

@@ -4,7 +4,7 @@
#define I2C_SCL 22
// #define BUTTON_PIN 39 // 38, 37
//#define BUTTON_PIN 0
// #define BUTTON_PIN 0
#define BUTTON_NEED_PULLUP
// #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.

View File

@@ -3,8 +3,8 @@
#define I2C_SCL 22
// 7-07-2023 Or enable Secondary I2C Bus
//#define I2C_SDA1 32
//#define I2C_SCL1 33
// #define I2C_SDA1 32
// #define I2C_SCL1 33
#define HAS_GPS 1
#undef GPS_RX_PIN
@@ -39,7 +39,7 @@
#undef RF95_MOSI
#undef RF95_NSS
#define USE_RF95
//#define USE_SX1280
// #define USE_SX1280
#ifdef USE_RF95
#define RF95_SCK 18

View File

@@ -64,7 +64,7 @@ extern "C" {
* Buttons
*/
//#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
// #define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
#define BUTTON_NEED_PULLUP
#define PIN_BUTTON2 12
#define PIN_BUTTON3 24
@@ -191,7 +191,9 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
// #define SX126X_TXEN (39)
// #define SX126X_RXEN (37)
#define SX126X_POWER_EN (37)
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define PIN_GPS_RESET (34) // Must be P1.02
// #define PIN_GPS_EN
@@ -220,7 +222,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define ADC_MULTIPLIER VBAT_DIVIDER_COMP // REAL_VBAT_MV_PER_LSB
#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
//#define HAS_RTC 1
// #define HAS_RTC 1
#define HAS_ETHERNET 1
@@ -237,4 +239,4 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

View File

@@ -24,11 +24,11 @@ static const uint8_t SCK = 5;
static const uint8_t MOSI = 6;
static const uint8_t SS = 7;
//#define SPI_MOSI (11)
//#define SPI_SCK (14)
//#define SPI_MISO (2)
//#define SPI_CS (13)
// #define SPI_MOSI (11)
// #define SPI_SCK (14)
// #define SPI_MISO (2)
// #define SPI_CS (13)
//#define SDCARD_CS SPI_CS
// #define SDCARD_CS SPI_CS
#endif /* Pins_Arduino_h */

View File

@@ -2,22 +2,22 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
//#define HAS_SCREEN 0
//#define HAS_SDCARD
//#define SDCARD_USE_SPI1
// #define HAS_SCREEN 0
// #define HAS_SDCARD
// #define SDCARD_USE_SPI1
//#define USE_SSD1306
// #define USE_SSD1306
#define I2C_SDA 18 // 1 // I2C pins for this board
#define I2C_SCL 17 // 2
//#define LED_PIN 38 // This is a RGB LED not a standard LED
// #define LED_PIN 38 // This is a RGB LED not a standard LED
#define BUTTON_PIN 0 // This is the BOOT button
#define BUTTON_NEED_PULLUP
//#define USE_RF95 // RFM95/SX127x
//#define USE_SX1262
// #define USE_RF95 // RFM95/SX127x
// #define USE_SX1262
#define USE_SX1280
#define RF95_MISO 3

View File

@@ -24,11 +24,11 @@ static const uint8_t SCK = 5;
static const uint8_t MOSI = 6;
static const uint8_t SS = 7;
//#define SPI_MOSI (11)
//#define SPI_SCK (14)
//#define SPI_MISO (2)
//#define SPI_CS (13)
// #define SPI_MOSI (11)
// #define SPI_SCK (14)
// #define SPI_MISO (2)
// #define SPI_CS (13)
//#define SDCARD_CS SPI_CS
// #define SDCARD_CS SPI_CS
#endif /* Pins_Arduino_h */

View File

@@ -2,22 +2,22 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
//#define HAS_SCREEN 0
//#define HAS_SDCARD
//#define SDCARD_USE_SPI1
// #define HAS_SCREEN 0
// #define HAS_SDCARD
// #define SDCARD_USE_SPI1
#define USE_SSD1306
#define I2C_SDA 18 // 1 // I2C pins for this board
#define I2C_SCL 17 // 2
//#define LED_PIN 38 // This is a RGB LED not a standard LED
// #define LED_PIN 38 // This is a RGB LED not a standard LED
#define BUTTON_PIN 0 // This is the BOOT button
#define BUTTON_NEED_PULLUP
//#define USE_RF95 // RFM95/SX127x
//#define USE_SX1262
// #define USE_RF95 // RFM95/SX127x
// #define USE_SX1262
#define USE_SX1280
#define RF95_MISO 3
@@ -44,13 +44,13 @@
#define SX128X_RESET LORA_RESET
#endif
//#define USE_EINK
// #define USE_EINK
/*
* eink display pins
*/
//#define PIN_EINK_CS 13
//#define PIN_EINK_BUSY 2
//#define PIN_EINK_DC 1
//#define PIN_EINK_RES (-1)
//#define PIN_EINK_SCLK 5
//#define PIN_EINK_MOSI 6
// #define PIN_EINK_CS 13
// #define PIN_EINK_BUSY 2
// #define PIN_EINK_DC 1
// #define PIN_EINK_RES (-1)
// #define PIN_EINK_SCLK 5
// #define PIN_EINK_MOSI 6

View File

@@ -4,8 +4,8 @@
#define I2C_SCL 22
#define BUTTON_PIN 36 // The user button (information button) GPIO on the Nano G1 explorer
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented
// anywhere.
// #define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented
// anywhere.
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
// common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
@@ -13,6 +13,9 @@
#define USE_RF95
#define USE_SX1262
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 23
#define LORA_DIO1 33 // SX1262 IRQ
@@ -24,7 +27,9 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22
// Not really an E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
#endif
@@ -34,4 +39,4 @@
#define BATTERY_SENSE_SAMPLES 15 // Set the number of samples, It has an effect of increasing sensitivity.
#define ADC_MULTIPLIER 2
#define USE_SH1107_128_64
#define USE_SH1107_128_64

View File

@@ -4,8 +4,8 @@
#define I2C_SCL 22
#define BUTTON_PIN 36 // The middle button GPIO on the Nano G1
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented
// anywhere.
// #define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented
// anywhere.
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
// common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
@@ -13,6 +13,9 @@
#define USE_RF95
#define USE_SX1262
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 23
#define LORA_DIO1 33 // SX1262 IRQ
@@ -24,10 +27,12 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22
// Not really an E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
#endif
// different screen
#define USE_SH1106
#define USE_SH1106

View File

@@ -23,7 +23,7 @@
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
//#define USE_LFRC // Board uses 32khz RC for LF
// #define USE_LFRC // Board uses 32khz RC for LF
/*----------------------------------------------------------------------------
* Headers
@@ -54,7 +54,7 @@ extern "C" {
#define LED_CONN PIN_GREEN
#define LED_STATE_ON 0 // State when LED is lit
//#define LED_INVERTED 1
// #define LED_INVERTED 1
/*
* Buttons
@@ -114,11 +114,13 @@ External serial flash W25Q16JV_IQ
#define SX126X_CS (32 + 13) // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 (32 + 10)
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
//#define SX1262_DIO3 (0 + 21)
// #define SX1262_DIO3 (0 + 21)
// This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the main CPU?
#define SX126X_BUSY (32 + 11)
#define SX126X_RESET (32 + 15)
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// #define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...)
@@ -130,11 +132,11 @@ External serial flash W25Q16JV_IQ
#define GPS_L76K
#define PIN_GPS_WAKE (0 + 13) // An output to wake GPS, low means allow sleep, high means force wake
#define PIN_GPS_TX (0 + 9) // This is for bits going TOWARDS the CPU
#define PIN_GPS_RX (0 + 10) // This is for bits going TOWARDS the GPS
#define PIN_GPS_STANDBY (0 + 13) // An output to wake GPS, low means allow sleep, high means force wake STANDBY
#define PIN_GPS_TX (0 + 9) // This is for bits going TOWARDS the CPU
#define PIN_GPS_RX (0 + 10) // This is for bits going TOWARDS the GPS
//#define GPS_THREAD_INTERVAL 50
// #define GPS_THREAD_INTERVAL 50
#define PIN_SERIAL1_RX PIN_GPS_TX
#define PIN_SERIAL1_TX PIN_GPS_RX
@@ -152,7 +154,7 @@ External serial flash W25Q16JV_IQ
#define PIN_SPI_MOSI (0 + 11)
#define PIN_SPI_SCK (0 + 12)
//#define PIN_PWR_EN (0 + 6)
// #define PIN_PWR_EN (0 + 6)
// To debug via the segger JLINK console rather than the CDC-ACM serial device
// #define USE_SEGGER
@@ -193,4 +195,4 @@ External serial flash W25Q16JV_IQ
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

View File

@@ -146,6 +146,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_BUSY (32 + 4) // P1.04
#define SX126X_RESET (0 + 3) // P0.03
#define SX126X_ANT_SW (32 + 10) // P1.10
#define SX126X_DIO2_AS_RF_SWITCH
// To debug via the segger JLINK console rather than the CDC-ACM serial device
// #define USE_SEGGER

View File

@@ -20,5 +20,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
// HOPE RFM90 does not have a TCXO therefore not SX126X_E22
#endif

View File

@@ -89,8 +89,8 @@ static const uint8_t A7 = PIN_A7;
// Other pins
#define PIN_AREF (0xff)
//#define PIN_NFC1 (9)
//#define PIN_NFC2 (10)
// #define PIN_NFC1 (9)
// #define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
@@ -103,8 +103,8 @@ static const uint8_t AREF = PIN_AREF;
#define PIN_SERIAL1_TX (9)
// Connected to Jlink CDC
//#define PIN_SERIAL2_RX (8)
//#define PIN_SERIAL2_TX (6)
// #define PIN_SERIAL2_RX (8)
// #define PIN_SERIAL2_TX (6)
/*
* SPI Interfaces
@@ -138,7 +138,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
// #define SX126X_ANT_SW (32 + 10)
#define SX126X_RXEN (22)
#define SX126X_TXEN (24)
#define SX126X_E22 // Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
// Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// ERC12864-10 LCD
#define ERC12864_CS (32 + 4)

View File

@@ -89,8 +89,8 @@ static const uint8_t A7 = PIN_A7;
// Other pins
#define PIN_AREF (0xff)
//#define PIN_NFC1 (9)
//#define PIN_NFC2 (10)
// #define PIN_NFC1 (9)
// #define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
@@ -158,7 +158,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_RESET (0 + 17)
#define SX126X_TXEN (0 + 24)
#define SX126X_RXEN (0 + 22)
#define SX126X_E22 // Not really an E22 but this board clones using DIO3 for tcxo control
// Not really an E22 but this board clones using DIO3 for tcxo control
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// FIXME, to prevent burning out parts I've set the power level super low, because I don't have
// an antenna wired up

View File

@@ -81,4 +81,6 @@ static const uint8_t SCK = 33;
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_POWER_EN WB_IO3
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8

View File

@@ -48,5 +48,7 @@
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_POWER_EN 25
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#endif
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif

View File

@@ -209,7 +209,9 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
// #define SX126X_TXEN (39)
// #define SX126X_RXEN (37)
#define SX126X_POWER_EN (37)
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// enables 3.3V periphery like GPS or IO Module
#define PIN_3V3_EN (34)
@@ -275,4 +277,4 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

View File

@@ -186,7 +186,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
// #define SX126X_TXEN (39)
// #define SX126X_RXEN (37)
#define SX126X_POWER_EN (37)
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// enables 3.3V periphery like GPS or IO Module
#define PIN_3V3_EN (34)
@@ -239,4 +241,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

View File

@@ -43,7 +43,7 @@ extern "C" {
#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
#define BUTTON_NEED_PULLUP
//#define PIN_BUTTON2 12
// #define PIN_BUTTON2 12
/*
* Analog pins
@@ -69,8 +69,8 @@ static const uint8_t A7 = PIN_A7;
// Other pins
#define PIN_AREF (2)
//#define PIN_NFC1 (9)
//#define PIN_NFC2 (10)
// #define PIN_NFC1 (9)
// #define PIN_NFC2 (10)
static const uint8_t AREF = PIN_AREF;
@@ -111,7 +111,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_EINK_CS (0 + 16) // TX1
#define PIN_EINK_BUSY (0 + 15) // RX1
#define PIN_EINK_DC (0 + 17) // IO1
//#define PIN_EINK_RES (-1) //first try without RESET then connect it to AIN (AIN0 5 )
// #define PIN_EINK_RES (-1) //first try without RESET then connect it to AIN (AIN0 5 )
#define PIN_EINK_RES (0 + 5) // 2.13 BN Display needs RESET
#define PIN_EINK_SCLK (0 + 14) // SCL
#define PIN_EINK_MOSI (0 + 13) // SDA
@@ -155,7 +155,9 @@ static const uint8_t SCK = PIN_SPI_SCK;
// #define SX126X_TXEN (39)
// #define SX126X_RXEN (37)
#define SX126X_POWER_EN (37)
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// enables 3.3V periphery like GPS or IO Module
#define PIN_3V3_EN (34)
@@ -171,36 +173,36 @@ static const uint8_t SCK = PIN_SPI_SCK;
// Therefore must be 1 to keep peripherals powered
// Power is on the controllable 3V3_S rail
// #define PIN_GPS_RESET (34)
//#define PIN_GPS_EN PIN_3V3_EN
//#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
// #define PIN_GPS_EN PIN_3V3_EN
// #define PIN_GPS_PPS (17) // Pulse per second input from the GPS
//#define GPS_RX_PIN PIN_SERIAL1_RX
//#define GPS_TX_PIN PIN_SERIAL1_TX
// #define GPS_RX_PIN PIN_SERIAL1_RX
// #define GPS_TX_PIN PIN_SERIAL1_TX
// RAK12002 RTC Module
#define RV3028_RTC (uint8_t)0b1010010
// Battery
// The battery sense is hooked to pin A0 (5)
//#define BATTERY_PIN PIN_A0
// #define BATTERY_PIN PIN_A0
// and has 12 bit resolution
//#define BATTERY_SENSE_RESOLUTION_BITS 12
//#define BATTERY_SENSE_RESOLUTION 4096.0
// #define BATTERY_SENSE_RESOLUTION_BITS 12
// #define BATTERY_SENSE_RESOLUTION 4096.0
// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
//#define VBAT_MV_PER_LSB (0.73242188F)
// #define VBAT_MV_PER_LSB (0.73242188F)
// Voltage divider value => 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
//#define VBAT_DIVIDER (0.4F)
// #define VBAT_DIVIDER (0.4F)
// Compensation factor for the VBAT divider
//#define VBAT_DIVIDER_COMP (1.73)
// #define VBAT_DIVIDER_COMP (1.73)
// Fixed calculation of milliVolt from compensation value
//#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
//#undef AREF_VOLTAGE
//#define AREF_VOLTAGE 3.0
//#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
//#define ADC_MULTIPLIER VBAT_DIVIDER_COMP // REAL_VBAT_MV_PER_LSB
//#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
// #define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
// #undef AREF_VOLTAGE
// #define AREF_VOLTAGE 3.0
// #define VBAT_AR_INTERNAL AR_INTERNAL_3_0
// #define ADC_MULTIPLIER VBAT_DIVIDER_COMP // REAL_VBAT_MV_PER_LSB
// #define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
//#define HAS_RTC 1
// #define HAS_RTC 1
#ifdef __cplusplus
}
@@ -210,4 +212,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

View File

@@ -17,6 +17,10 @@
// SDA = 4
// SCL = 5
// Recommended pins for SerialModule:
// txd = 8
// rxd = 9
#define EXT_NOTIFY_OUT 22
#define BUTTON_PIN 17
@@ -49,5 +53,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#endif
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif

View File

@@ -17,6 +17,10 @@
// SDA = 4
// SCL = 5
// Recommended pins for SerialModule:
// txd = 8
// rxd = 9
#define EXT_NOTIFY_OUT 22
#define BUTTON_PIN 17
@@ -47,5 +51,6 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#endif
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif

View File

@@ -27,9 +27,7 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
// #define SX126X_E22 // Not really an E22
// Internally the module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
#define SX126X_DIO2_AS_RF_SWITCH // Internally the module hooks the SX1262-DIO2 in to control the TX/RX switch
#define SX126X_MAX_POWER \
16 // Ensure the PA does not exceed the saturation output power. More
// Info:https://uniteng.com/wiki/doku.php?id=meshtastic:station#rf_design_-_lora_station_edition_g1
@@ -49,4 +47,4 @@
// Station may not have GPS installed, but it has a labeled GPS pinout
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
#define GPS_TX_PIN 12

View File

@@ -8,6 +8,7 @@ debug_tool = esp-builtin
build_flags = ${esp32_base.build_flags}
-DT_DECK
-DBOARD_HAS_PSRAM
-DGPS_POWER_TOGGLE
-Ivariants/t-deck
lib_deps = ${esp32s3_base.lib_deps}

View File

@@ -84,6 +84,8 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
// Not really an E22 but TTGO seems to be trying to clone that
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
// code)

View File

@@ -85,9 +85,9 @@ static const uint8_t A0 = PIN_A0;
/*
No longer populated on PCB
*/
//#define PIN_SERIAL2_RX (0 + 6)
//#define PIN_SERIAL2_TX (0 + 8)
// #define PIN_SERIAL2_EN (0 + 17)
// #define PIN_SERIAL2_RX (0 + 6)
// #define PIN_SERIAL2_TX (0 + 8)
// #define PIN_SERIAL2_EN (0 + 17)
/**
Wire Interfaces
@@ -133,7 +133,9 @@ External serial flash WP25R1635FZUIL0
// CPU?
#define SX126X_BUSY (0 + 17)
#define SX126X_RESET (0 + 25)
#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
// Not really an E22 but TTGO seems to be trying to clone that
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
@@ -171,7 +173,7 @@ External serial flash WP25R1635FZUIL0
#define GPS_L76K
#define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define PIN_GPS_WAKE (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
#define PIN_GPS_STANDBY (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
// Seems to be missing on this new board
// #define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
#define PIN_GPS_TX (32 + 9) // This is for bits going TOWARDS the CPU

View File

@@ -63,6 +63,8 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for
// the sx1262interface code)
// Not really an E22 but TTGO seems to be trying to clone that
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for
// the sx1262interface code)

View File

@@ -7,9 +7,9 @@
#define I2C_SCL 18 // For QMC6310 sensors and screens
#define BUTTON_PIN 0 // The middle button GPIO on the T-Beam S3
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented
// anywhere.
// #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
// #define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented
// anywhere.
// #define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
#define LED_INVERTED 1
@@ -29,7 +29,9 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
// Not really an E22 but TTGO seems to be trying to clone that
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
#endif
@@ -64,4 +66,4 @@
// has 32768 Hz crystal
#define HAS_32768HZ
#define USE_SH1106
#define USE_SH1106

View File

@@ -28,7 +28,9 @@
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that
// Not really an E22 but TTGO seems to be trying to clone that
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
#endif
@@ -39,4 +41,5 @@
#define HAS_AXP192
#define GPS_UBLOX
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
#define GPS_TX_PIN 12
// #define GPS_DEBUG

View File

@@ -1,8 +1,3 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define PIN_GPS_EN 42 // GPS power enable pin
#define HAS_SDCARD
#define SDCARD_USE_SPI1
@@ -49,7 +44,8 @@
#define SX126X_DIO1 33
#define SX126X_BUSY 34
#define SX126X_RESET LORA_RESET
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
// per SX128x_Receive_Interrupt/utilities.h
@@ -63,4 +59,4 @@
#define SX128X_RXEN 21
#define SX128X_TXEN 10
#define SX128X_MAX_POWER 3
#endif
#endif

View File

@@ -1,6 +1,3 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define I2C_SDA 4 // I2C pins for this board
#define I2C_SCL 15
@@ -16,4 +13,4 @@
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 14
#define LORA_DIO1 33 // Must be manually wired: https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-3/18436
#define LORA_DIO2 32 // Not really used
#define LORA_DIO2 32 // Not really used

View File

@@ -1,8 +1,3 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define GPS_RX_PIN 36
#define GPS_TX_PIN 13 // per @eugene
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL

View File

@@ -1,8 +1,3 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define GPS_RX_PIN 36
#define GPS_TX_PIN 13 // per @eugene
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL

View File

@@ -1,10 +1,3 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define GPS_RX_PIN 15 // per @der_bear on the forum, 36 is incorrect for this board type and 15 is a better pick
#define GPS_TX_PIN 13
#define PIN_GPS_EN 19 // GPS power enable pin
#define BATTERY_PIN 35
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
#define BATTERY_SENSE_SAMPLES 30

View File

@@ -1,6 +1,3 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
// ratio of voltage divider = 2.0 (R42=100k, R43=100k)
#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage.

View File

@@ -5,7 +5,7 @@
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
//#define USE_LFRC // Board uses RC for LF
// #define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
@@ -125,7 +125,6 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX126X_TXEN RADIOLIB_NC
#define SX126X_RXEN D7
#define E22_TXEN_CONNECTED_TO_DIO2
// ------------------------------ OR ------------------------------
@@ -141,7 +140,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#ifdef EBYTE_E22
// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
// (which is the default for the sx1262interface code)
#define SX126X_E22
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#endif
/*
@@ -198,4 +198,4 @@ static const uint8_t SCL = PIN_WIRE_SCL;
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More