Compare commits

...

51 Commits

Author SHA1 Message Date
github-actions[bot]
3bcab0e223 [create-pull-request] automated change (#2768)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-09-04 18:38:58 -05:00
GUVWAF
17617ce031 Fix possible memory leak in NeighborInfo Module (#2765)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-09-04 18:38:16 -05:00
Jonathan Bennett
97f0c734e0 Fix Neighborinfo crash
neighbors object wasn't initialized when module disabled, this
initializes it to a safe, empty object.
2023-09-04 18:15:27 -05:00
Jonathan Bennett
e943fffe8c GPS fixes
Work aroung Serial reset issue on ESP32
Don't send unsupported command to G60xx GPS
2023-09-04 15:00:05 -05:00
tropho23
ffcb131171 GPS toggle for RAK4631 (patch 2 of 2) (#2764)
* Added triple-press GPS toggle button changes

* Revert edits to extensions.json

* comma'd

* Update variant.h

Added the line:

// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
#define PIN_GPS_EN 34 // GPS power enable pin

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: code8buster <communismisgreat@national.shitposting.agency>
2023-09-04 13:17:01 -05:00
tropho23
bb1fe7cad3 GPS toggle for RAK4631 (patch 1 of 2) (#2763)
* Added triple-press GPS toggle button changes

* Revert edits to extensions.json

* comma'd

* Update platformio.ini

Added line:

-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: code8buster <communismisgreat@national.shitposting.agency>
2023-09-04 13:16:39 -05:00
Ben Meadors
ad40493a39 Add speed, heading, and DOP to default position flags (#2759)
* Add speed and heading

* Add DOP
2023-09-04 06:46:27 -05:00
Jonathan Bennett
ac62330e1c Found lost byte dropped from moduleinfo
Attempt to fix CFG-GNSS for neo-6m
2023-09-03 22:38:03 -05:00
code8buster
53f6a43661 Merge pull request #2752 from meshtastic/nmea-rate
Adds GPS Serial Speed scanning, fixes ublox GNSS setup errors
2023-09-03 21:57:51 +00:00
Jonathan Bennett
7ad94da1c6 Add more to GPS_DEBUG and fix ubx7 CFG-GNSS 2023-09-03 16:20:01 -05:00
Jonathan Bennett
ecdb75aae0 Correct UBX-CFG-PMS message 2023-09-03 02:16:29 -05:00
Jonathan Bennett
7c98445ca3 Cleanup in prep for commiting
Fix some compilation warnings
gate debug code behind GPS_DEBUG
minor fix in u-blox protocol detection
Begin to gate GPS messages based on protover
2023-09-03 01:50:11 -05:00
Jonathan Bennett
b21368ecfa Add delay and debug code for GPS probe 2023-09-02 20:35:38 -05:00
Jonathan Bennett
1a178c7d33 Add check for GPS Frame Errors message 2023-09-02 04:29:48 -05:00
Jonathan Bennett
5d6f0ea6c4 Fix possible edge case in GPS detection 2023-09-01 16:24:28 -05:00
Ben Meadors
5bd861f3d8 Merge branch 'master' into nmea-rate 2023-09-01 15:08:32 -05:00
GUVWAF
6d93fab495 Add neighbor IDs to MQTT JSON (#2756)
* Add neighbor IDs to JSON

* Limit #neighbors to what we can actually save

* Put neighbor IDs in an array

* Add SNR to neighbors in nested objects
2023-09-01 14:35:57 -05:00
Jonathan Bennett
6803fd7949 More fixes for GPS chips with unexpected baud 2023-09-01 12:11:39 -05:00
Jonathan Bennett
a61f969773 Increase GPS detection timeout slightly 2023-08-31 22:19:50 -05:00
Jonathan Bennett
79cfc4b725 Avoid Serial output mangling with RTOS. 2023-08-31 20:40:01 -05:00
Jonathan Bennett
cf762bbd42 Cut down delay times for GPS probe and init 2023-08-31 20:39:23 -05:00
code8buster
3d2c419d0d Remove leftover debug msg 2023-08-30 16:24:56 -04:00
Jonathan Bennett
903f619609 Add GPS serial speed scan 2023-08-28 19:01:14 -05:00
Jonathan Bennett
2e3f762d3d Catch a nullptr return rather than crash 2023-08-28 04:05:45 -05:00
Jonathan Bennett
a42266f74b GPS: Fix checksum and remove spurious returns 2023-08-28 04:05:45 -05:00
github-actions[bot]
a605c69eb4 [create-pull-request] automated change (#2748)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-26 07:36:04 -05:00
Thomas Göttgens
282cc0b16a Merge pull request #2737 from meshtastic/BBQ10Kb-Fix
Bbq10 kb fix
2023-08-26 11:22:35 +02:00
Thomas Göttgens
4ab67f3668 IGOR! Fetch me the brain! 2023-08-25 16:44:39 +02:00
Thomas Göttgens
312028b161 Possble fix ESC 2023-08-25 09:27:09 +02:00
Ben Meadors
ecd48db69c Merge branch 'master' into BBQ10Kb-Fix 2023-08-24 19:57:49 -05:00
Ben Meadors
03dc36ea12 Use fixed position regardless of gps lock (#2744) 2023-08-24 10:55:49 -05:00
Mark Trevor Birss
c2ae38405e Update architecture.h (#2746) 2023-08-24 07:58:24 -05:00
Thomas Göttgens
2a1d8c40b4 add TAB and ESC handling 2023-08-24 14:24:26 +02:00
Ben Meadors
e2441c425a Merge branch 'master' into BBQ10Kb-Fix 2023-08-24 07:06:42 -05:00
Mark Trevor Birss
00ffe73ebd Heltec ESP32-C3 HT-CT62 support (#2741)
* Add files via upload

* Update platformio.ini

* Update variant.h

* Update platformio.ini

* Switch to our new HW_MODEL

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Ben Meadors <thebentern@tuta.io>
2023-08-23 07:59:21 -05:00
Thomas Göttgens
3355019de3 Merge branch 'master' into BBQ10Kb-Fix 2023-08-23 09:45:06 +02:00
Thomas Göttgens
5bb207d88b reset sym after second keypress
also remove debug print and non-working scancodes.
2023-08-23 09:44:20 +02:00
github-actions[bot]
5453e4d123 [create-pull-request] automated change (#2742)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2023-08-22 17:11:22 -05:00
Thomas Göttgens
7f1b58a222 trunk fmt 2023-08-22 21:23:37 +02:00
Thomas Göttgens
39357b2686 Merge branch 'BBQ10Kb-Fix' of github.com:meshtastic/firmware into BBQ10Kb-Fix 2023-08-22 21:23:00 +02:00
Thomas Göttgens
d6b629ae04 update SYM Scancode 2023-08-22 21:19:51 +02:00
Thomas Göttgens
7b1aeb60cd Try manual scancode for SYM 2023-08-22 21:19:51 +02:00
Thomas Göttgens
5c7c1cd253 silence compiler warnings 2023-08-22 21:19:51 +02:00
Thomas Göttgens
8cfe130df3 update SYM Scancode 2023-08-22 21:11:19 +02:00
Thomas Göttgens
feef86942d Merge pull request #2738 from meshtastic/neighbourinfo-fix
fix crash and Debug logging in NeighbourInfo
2023-08-22 16:27:52 +02:00
Thomas Göttgens
5f3a8b4924 fix crash and Debug logging in NeighbourInfo 2023-08-22 15:43:21 +02:00
Thomas Göttgens
0fcaaf39b0 Try manual scancode for SYM 2023-08-22 11:23:19 +02:00
Thomas Göttgens
a55eac5c20 silence compiler warnings 2023-08-22 10:58:54 +02:00
github-actions[bot]
b47c9c165a [create-pull-request] automated change (#2733)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2023-08-19 18:06:33 -05:00
Thomas Göttgens
ecceb10910 different debug print 2023-08-19 21:28:02 +02:00
Thomas Göttgens
6fc76103a0 temporarily Enable debug print 2023-08-19 20:55:50 +02:00
28 changed files with 571 additions and 213 deletions

View File

@@ -18,6 +18,12 @@ NoopPrint noopPrint;
#if HAS_WIFI || HAS_ETHERNET #if HAS_WIFI || HAS_ETHERNET
extern Syslog syslog; extern Syslog syslog;
#endif #endif
void RedirectablePrint::rpInit()
{
#ifdef HAS_FREE_RTOS
inDebugPrint = xSemaphoreCreateMutexStatic(&this->_MutexStorageSpace);
#endif
}
void RedirectablePrint::setDestination(Print *_dest) void RedirectablePrint::setDestination(Print *_dest)
{ {
@@ -66,9 +72,12 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
return 0; return 0;
} }
size_t r = 0; size_t r = 0;
#ifdef HAS_FREE_RTOS
if (inDebugPrint != nullptr && xSemaphoreTake(inDebugPrint, portMAX_DELAY) == pdTRUE) {
#else
if (!inDebugPrint) { if (!inDebugPrint) {
inDebugPrint = true; inDebugPrint = true;
#endif
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
@@ -141,7 +150,11 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
va_end(arg); va_end(arg);
isContinuationMessage = !hasNewline; isContinuationMessage = !hasNewline;
#ifdef HAS_FREE_RTOS
xSemaphoreGive(inDebugPrint);
#else
inDebugPrint = false; inDebugPrint = false;
#endif
} }
return r; return r;

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "../freertosinc.h"
#include <Print.h> #include <Print.h>
#include <stdarg.h> #include <stdarg.h>
#include <string> #include <string>
@@ -16,14 +17,19 @@ class RedirectablePrint : public Print
/// Used to allow multiple logDebug messages to appear on a single log line /// Used to allow multiple logDebug messages to appear on a single log line
bool isContinuationMessage = false; bool isContinuationMessage = false;
#ifdef HAS_FREE_RTOS
SemaphoreHandle_t inDebugPrint = nullptr;
StaticSemaphore_t _MutexStorageSpace;
#else
volatile bool inDebugPrint = false; volatile bool inDebugPrint = false;
#endif
public: public:
explicit RedirectablePrint(Print *_dest) : dest(_dest) {} explicit RedirectablePrint(Print *_dest) : dest(_dest) {}
/** /**
* Set a new destination * Set a new destination
*/ */
void rpInit();
void setDestination(Print *dest); void setDestination(Print *dest);
virtual size_t write(uint8_t c); virtual size_t write(uint8_t c);

View File

@@ -12,6 +12,7 @@ SerialConsole *console;
void consoleInit() void consoleInit()
{ {
new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread
DEBUG_PORT.rpInit(); // Simply sets up semaphore
} }
void consolePrintf(const char *format, ...) void consolePrintf(const char *format, ...)

View File

@@ -4,6 +4,10 @@
#include "configuration.h" #include "configuration.h"
#include "sleep.h" #include "sleep.h"
#ifdef ARCH_PORTDUINO
#include "meshUtils.h"
#endif
#ifndef GPS_RESET_MODE #ifndef GPS_RESET_MODE
#define GPS_RESET_MODE HIGH #define GPS_RESET_MODE HIGH
#endif #endif
@@ -43,13 +47,50 @@ void GPS::UBXChecksum(byte *message, size_t length)
message[length - 1] = CK_B; message[length - 1] = CK_B;
} }
bool GPS::getACK(uint8_t class_id, uint8_t msg_id) GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis)
{
uint8_t buffer[768] = {0};
uint8_t b;
int bytesRead = 0;
uint32_t startTimeout = millis() + waitMillis;
while (millis() < startTimeout) {
if (_serial_gps->available()) {
b = _serial_gps->read();
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);
#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);
#endif
return GNSS_RESPONSE_NONE;
}
GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis)
{ {
uint8_t b; uint8_t b;
uint8_t ack = 0; uint8_t ack = 0;
const uint8_t ackP[2] = {class_id, msg_id}; const uint8_t ackP[2] = {class_id, msg_id};
uint8_t buf[10] = {0xB5, 0x62, 0x05, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t buf[10] = {0xB5, 0x62, 0x05, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned long startTime = millis(); uint32_t startTime = millis();
const char frame_errors[] = "More than 100 frame errors";
int sCounter = 0;
for (int j = 2; j < 6; j++) { for (int j = 2; j < 6; j++) {
buf[8] += buf[j]; buf[8] += buf[j];
@@ -62,28 +103,46 @@ bool GPS::getACK(uint8_t class_id, uint8_t msg_id)
buf[9] += buf[8]; buf[9] += buf[8];
} }
while (1) { while (millis() - startTime < waitMillis) {
if (ack > 9) { if (ack > 9) {
// LOG_INFO("Got ACK for class %02X message %02X\n", class_id, msg_id); #ifdef GPS_DEBUG
return true; // ACK received LOG_DEBUG("\n");
} LOG_INFO("Got ACK for class %02X message %02X in %d millis.\n", class_id, msg_id, millis() - startTime);
if (millis() - startTime > 3000) { #endif
LOG_WARN("No response for class %02X message %02X\n", class_id, msg_id); return GNSS_RESPONSE_OK; // ACK received
return false; // No response received within 3 seconds
} }
if (_serial_gps->available()) { if (_serial_gps->available()) {
b = _serial_gps->read(); b = _serial_gps->read();
if (b == frame_errors[sCounter]) {
sCounter++;
if (sCounter == 26) {
return GNSS_RESPONSE_FRAME_ERRORS;
}
} else {
sCounter = 0;
}
#ifdef GPS_DEBUG
LOG_DEBUG("%02X", b);
#endif
if (b == buf[ack]) { if (b == buf[ack]) {
ack++; ack++;
} else { } else {
ack = 0; // Reset the acknowledgement counter if (ack == 3 && b == 0x00) { // UBX-ACK-NAK message
if (buf[3] == 0x00) { // UBX-ACK-NAK message #ifdef GPS_DEBUG
LOG_DEBUG("\n");
#endif
LOG_WARN("Got NAK for class %02X message %02X\n", class_id, msg_id); LOG_WARN("Got NAK for class %02X message %02X\n", class_id, msg_id);
return false; // NAK received return GNSS_RESPONSE_NAK; // NAK received
} }
ack = 0; // Reset the acknowledgement counter
} }
} }
} }
#ifdef GPS_DEBUG
LOG_DEBUG("\n");
LOG_WARN("No response for class %02X message %02X\n", class_id, msg_id);
#endif
return GNSS_RESPONSE_NONE; // No response received within timeout
} }
/** /**
@@ -95,14 +154,14 @@ bool GPS::getACK(uint8_t class_id, uint8_t msg_id)
* @param requestedID: request message ID constant * @param requestedID: request message ID constant
* @retval length of payload message * @retval length of payload message
*/ */
int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID) int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis)
{ {
uint16_t ubxFrameCounter = 0; uint16_t ubxFrameCounter = 0;
uint32_t startTime = millis(); uint32_t startTime = millis();
uint16_t needRead; uint16_t needRead;
while (millis() - startTime < 1200) { while (millis() - startTime < waitMillis) {
while (_serial_gps->available()) { if (_serial_gps->available()) {
int c = _serial_gps->read(); int c = _serial_gps->read();
switch (ubxFrameCounter) { switch (ubxFrameCounter) {
case 0: case 0:
@@ -144,8 +203,6 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
// Payload length msb // Payload length msb
needRead |= (c << 8); needRead |= (c << 8);
ubxFrameCounter++; ubxFrameCounter++;
break;
case 6:
// Check for buffer overflow // Check for buffer overflow
if (needRead >= size) { if (needRead >= size) {
ubxFrameCounter = 0; ubxFrameCounter = 0;
@@ -155,6 +212,10 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
ubxFrameCounter = 0; ubxFrameCounter = 0;
} else { } else {
// return payload length // return payload length
#ifdef GPS_DEBUG
LOG_INFO("Got ACK for class %02X message %02X in %d millis.\n", requestedClass, requestedID,
millis() - startTime);
#endif
return needRead; return needRead;
} }
break; break;
@@ -164,6 +225,7 @@ int GPS::getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t
} }
} }
} }
// LOG_WARN("No response for class %02X message %02X\n", requestedClass, requestedID);
return 0; return 0;
} }
@@ -188,8 +250,8 @@ bool GPS::setupGPS()
config.position.tx_gpio = GPS_TX_PIN; config.position.tx_gpio = GPS_TX_PIN;
#endif #endif
//#define BAUD_RATE 115200 // #define BAUD_RATE 115200
// ESP32 has a special set of parameters vs other arduino ports // ESP32 has a special set of parameters vs other arduino ports
#if defined(ARCH_ESP32) #if defined(ARCH_ESP32)
if (config.position.rx_gpio) { if (config.position.rx_gpio) {
LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio); LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio);
@@ -203,7 +265,21 @@ bool GPS::setupGPS()
/* /*
* T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first * T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first
*/ */
gnssModel = probe(); #if defined(GPS_UC6580)
_serial_gps->updateBaudRate(115200);
gnssModel = GNSS_MODEL_UC6850;
#else
for (int serialSpeed : {9600, 4800, 38400, 57600, 115200}) {
LOG_DEBUG("Probing for GPS at %d \n", serialSpeed);
gnssModel = probe(serialSpeed);
if (gnssModel != GNSS_MODEL_UNKNOWN)
break;
}
if (gnssModel == GNSS_MODEL_UNKNOWN) {
LOG_DEBUG("No GPS found, retrying at 9600 baud.\n");
gnssModel = probe(9600);
}
#endif
if (gnssModel == GNSS_MODEL_MTK) { if (gnssModel == GNSS_MODEL_MTK) {
/* /*
@@ -228,46 +304,88 @@ bool GPS::setupGPS()
_serial_gps->write("$CFGSYS,h15\r\n"); _serial_gps->write("$CFGSYS,h15\r\n");
delay(250); delay(250);
} else if (gnssModel == GNSS_MODEL_UBLOX) { } else if (gnssModel == GNSS_MODEL_UBLOX) {
/*
uint8_t buffer[768] = {0};
byte _message_GNSS[8] = {0xb5, 0x62, // Sync message for UBX protocol
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
0x00, 0x00, // Length of payload (28 bytes)
0x00, 0x00};
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
// Send the message to the module
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
int ackLen = getACK(buffer, sizeof(buffer), 0x06, 0x3e, 2000);
LOG_DEBUG("monver reply size = %d\n", ackLen);
LOG_DEBUG("Ack: ");
for (int i = 0; i < ackLen; i++) {
LOG_DEBUG("%02X", buffer[i]);
}
LOG_DEBUG("\n"); */
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command) // Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
// We need set it because by default it is GPS only, and we want to use GLONASS too // We need set it because by default it is GPS only, and we want to use GLONASS too
// Also we need SBAS for better accuracy and extra features // Also we need SBAS for better accuracy and extra features
// ToDo: Dynamic configure GNSS systems depending of LoRa region // ToDo: Dynamic configure GNSS systems depending of LoRa region
byte _message_GNSS[36] = {
0xb5, 0x62, // Sync message for UBX protocol
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
0x1c, 0x00, // Length of payload (28 bytes)
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01, // GLONASS
0x00, 0x00 // Checksum (to be calculated below)
};
// Calculate the checksum and update the message. if (strncmp(info.hwVersion, "00040007", 8) !=
UBXChecksum(_message_GNSS, sizeof(_message_GNSS)); 0) { // The original ublox 6 is GPS only and doesn't support the UBX-CFG-GNSS message
if (strncmp(info.hwVersion, "00070000", 8) == 0) { // Max7 seems to only support GPS *or* GLONASS
LOG_DEBUG("Setting GPS+SBAS\n");
byte _message_GNSS[28] = {
0xb5, 0x62, // Sync message for UBX protocol
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
0x14, 0x00, // Length of payload (28 bytes)
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
0x02, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, // GPS
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, // SBAS
0x00, 0x00 // Checksum (to be calculated below)
};
// Calculate the checksum and update the message.
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
// Send the message to the module
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
} else {
byte _message_GNSS[36] = {
0xb5, 0x62, // Sync message for UBX protocol
0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS)
0x1c, 0x00, // Length of payload (28 bytes)
0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
0xff, // numTrkChUse (max number of channels to use, 0xff = max available)
0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems
// GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags
0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS
0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01, // GLONASS
0x00, 0x00 // Checksum (to be calculated below)
};
// Calculate the checksum and update the message.
UBXChecksum(_message_GNSS, sizeof(_message_GNSS));
// Send the message to the module
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS));
}
// Send the message to the module if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) {
_serial_gps->write(_message_GNSS, sizeof(_message_GNSS)); // It's not critical if the module doesn't acknowledge this configuration.
// The module should operate adequately with its factory or previously saved settings.
if (!getACK(0x06, 0x3e)) { // It appears that there is a firmware bug in some GPS modules: When an attempt is made
// It's not critical if the module doesn't acknowledge this configuration. // to overwrite a saved state with identical values, no ACK/NAK is received, contrary to
// The module should operate adequately with its factory or previously saved settings. // what is specified in the Ublox documentation.
// It appears that there is a firmware bug in some GPS modules: When an attempt is made // There is also a possibility that the module may be GPS-only.
// to overwrite a saved state with identical values, no ACK/NAK is received, contrary to LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n");
// what is specified in the Ublox documentation. } else {
// There is also a possibility that the module may be GPS-only. if (strncmp(info.hwVersion, "00070000", 8) == 0) {
LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n"); LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n");
return true; } else {
} else { LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n");
LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n"); }
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next commands // Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
delay(750); // commands
return true; delay(750);
}
} }
// Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board, // Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board,
@@ -296,9 +414,8 @@ bool GPS::setupGPS()
// Send the message to the module // Send the message to the module
_serial_gps->write(_message_JAM, sizeof(_message_JAM)); _serial_gps->write(_message_JAM, sizeof(_message_JAM));
if (!getACK(0x06, 0x39)) { if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n"); LOG_WARN("Unable to enable interference resistance.\n");
return true;
} }
// Configure navigation engine expert settings: // Configure navigation engine expert settings:
@@ -342,25 +459,10 @@ bool GPS::setupGPS()
// Send the message to the module // Send the message to the module
_serial_gps->write(_message_NAVX5, sizeof(_message_NAVX5)); _serial_gps->write(_message_NAVX5, sizeof(_message_NAVX5));
if (!getACK(0x06, 0x23)) { if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure extra settings.\n"); LOG_WARN("Unable to configure extra settings.\n");
return true;
} }
/*
tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after
setting will not output command messages in UART1, resulting in unrecognized module information
// Set the UART port to output NMEA only
byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
if (!getACK(0x06, 0x00)) {
LOG_WARN("Unable to enable NMEA Mode.\n");
return true;
}
*/
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid // ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid
// Set GPS update rate to 1Hz // Set GPS update rate to 1Hz
@@ -383,9 +485,8 @@ bool GPS::setupGPS()
// Send the message to the module // Send the message to the module
_serial_gps->write(_message_1Hz, sizeof(_message_1Hz)); _serial_gps->write(_message_1Hz, sizeof(_message_1Hz));
if (!getACK(0x06, 0x08)) { if (getACK(0x06, 0x08, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to set GPS update rate.\n"); LOG_WARN("Unable to set GPS update rate.\n");
return true;
} }
// Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical // Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical
@@ -407,9 +508,8 @@ bool GPS::setupGPS()
// Send the message to the module // Send the message to the module
_serial_gps->write(_message_GGL, sizeof(_message_GGL)); _serial_gps->write(_message_GGL, sizeof(_message_GGL));
if (!getACK(0x06, 0x01)) { if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GGL.\n"); LOG_WARN("Unable to disable NMEA GGL.\n");
return true;
} }
// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and // Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and
@@ -426,9 +526,8 @@ bool GPS::setupGPS()
}; };
UBXChecksum(_message_GSA, sizeof(_message_GSA)); UBXChecksum(_message_GSA, sizeof(_message_GSA));
_serial_gps->write(_message_GSA, sizeof(_message_GSA)); _serial_gps->write(_message_GSA, sizeof(_message_GSA));
if (!getACK(0x06, 0x01)) { if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to Enable NMEA GSA.\n"); LOG_WARN("Unable to Enable NMEA GSA.\n");
return true;
} }
// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view. // Disable GSV. GSV - Satellites in view, details the number and location of satellites in view.
@@ -444,9 +543,8 @@ bool GPS::setupGPS()
}; };
UBXChecksum(_message_GSV, sizeof(_message_GSV)); UBXChecksum(_message_GSV, sizeof(_message_GSV));
_serial_gps->write(_message_GSV, sizeof(_message_GSV)); _serial_gps->write(_message_GSV, sizeof(_message_GSV));
if (!getACK(0x06, 0x01)) { if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GSV.\n"); LOG_WARN("Unable to disable NMEA GSV.\n");
return true;
} }
// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to // Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to
@@ -463,9 +561,8 @@ bool GPS::setupGPS()
}; };
UBXChecksum(_message_VTG, sizeof(_message_VTG)); UBXChecksum(_message_VTG, sizeof(_message_VTG));
_serial_gps->write(_message_VTG, sizeof(_message_VTG)); _serial_gps->write(_message_VTG, sizeof(_message_VTG));
if (!getACK(0x06, 0x01)) { if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA VTG.\n"); LOG_WARN("Unable to disable NMEA VTG.\n");
return true;
} }
// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data. // Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data.
@@ -481,9 +578,8 @@ bool GPS::setupGPS()
}; };
UBXChecksum(_message_RMC, sizeof(_message_RMC)); UBXChecksum(_message_RMC, sizeof(_message_RMC));
_serial_gps->write(_message_RMC, sizeof(_message_RMC)); _serial_gps->write(_message_RMC, sizeof(_message_RMC));
if (!getACK(0x06, 0x01)) { if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA RMC.\n"); LOG_WARN("Unable to enable NMEA RMC.\n");
return true;
} }
// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data. // Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data.
@@ -499,9 +595,8 @@ bool GPS::setupGPS()
}; };
UBXChecksum(_message_GGA, sizeof(_message_GGA)); UBXChecksum(_message_GGA, sizeof(_message_GGA));
_serial_gps->write(_message_GGA, sizeof(_message_GGA)); _serial_gps->write(_message_GGA, sizeof(_message_GGA));
if (!getACK(0x06, 0x01)) { if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA GGA.\n"); LOG_WARN("Unable to enable NMEA GGA.\n");
return true;
} }
// The Power Management configuration allows the GPS module to operate in different power modes for optimized power // The Power Management configuration allows the GPS module to operate in different power modes for optimized power
@@ -517,27 +612,28 @@ bool GPS::setupGPS()
// set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase and // set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase and
// must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, it must // must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, it must
// be set to '0'. // be set to '0'.
byte UBX_CFG_PMS[14] = { if (uBloxProtocolVersion >= 18) {
0xB5, 0x62, // UBX sync characters byte UBX_CFG_PMS[16] = {
0x06, 0x86, // Message class and ID (UBX-CFG-PMS) 0xB5, 0x62, // UBX sync characters
0x06, 0x00, // Length of payload (6 bytes) 0x06, 0x86, // Message class and ID (UBX-CFG-PMS)
0x00, // Version (0) 0x08, 0x00, // Length of payload (6 bytes)
0x03, // Power setup value 0x00, // Version (0)
0x00, 0x00, // period: not applicable, set to 0 0x03, // Power setup value
0x00, 0x00, // onTime: not applicable, set to 0 0x00, 0x00, // period: not applicable, set to 0
0x00, 0x00 // Placeholder for checksum, will be calculated next 0x00, 0x00, // onTime: not applicable, set to 0
}; 0x97, 0x6F, // reserved, generated by u-center
0x00, 0x00 // Placeholder for checksum, will be calculated next
};
// Calculate the checksum and update the message // Calculate the checksum and update the message
UBXChecksum(UBX_CFG_PMS, sizeof(UBX_CFG_PMS)); UBXChecksum(UBX_CFG_PMS, sizeof(UBX_CFG_PMS));
// Send the message to the module // Send the message to the module
_serial_gps->write(UBX_CFG_PMS, sizeof(UBX_CFG_PMS)); _serial_gps->write(UBX_CFG_PMS, sizeof(UBX_CFG_PMS));
if (!getACK(0x06, 0x86)) { if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for GPS.\n"); LOG_WARN("Unable to enable powersaving for GPS.\n");
return true; }
} }
// We need save configuration to flash to make our config changes persistent // We need save configuration to flash to make our config changes persistent
byte _message_SAVE[21] = { byte _message_SAVE[21] = {
0xB5, 0x62, // UBX protocol header 0xB5, 0x62, // UBX protocol header
@@ -556,12 +652,10 @@ bool GPS::setupGPS()
// Send the message to the module // Send the message to the module
_serial_gps->write(_message_SAVE, sizeof(_message_SAVE)); _serial_gps->write(_message_SAVE, sizeof(_message_SAVE));
if (!getACK(0x06, 0x09)) { if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to save GNSS module configuration.\n"); LOG_WARN("Unable to save GNSS module configuration.\n");
return true;
} else { } else {
LOG_INFO("GNSS module configuration saved!\n"); LOG_INFO("GNSS module configuration saved!\n");
return true;
} }
} }
} }
@@ -675,6 +769,7 @@ void GPS::setAwake(bool on)
if (isAwake != on) { if (isAwake != on) {
LOG_DEBUG("WANT GPS=%d\n", on); LOG_DEBUG("WANT GPS=%d\n", on);
if (on) { if (on) {
clearBuffer(); // drop any old data waiting in the buffer
lastWakeStartMsec = millis(); lastWakeStartMsec = millis();
wake(); wake();
} else { } else {
@@ -854,50 +949,72 @@ int GPS::prepareDeepSleep(void *unused)
return 0; return 0;
} }
GnssModel_t GPS::probe() GnssModel_t GPS::probe(int serialSpeed)
{ {
memset(&info, 0, sizeof(struct uBloxGnssModelInfo)); #if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040)
// return immediately if the model is set by the variant.h file _serial_gps->end();
//#ifdef GPS_UBLOX (unless it's a ublox, because we might want to know the module info! _serial_gps->begin(serialSpeed);
// return GNSS_MODEL_UBLOX; think about removing this macro and return)
#if defined(GPS_L76K)
return GNSS_MODEL_MTK;
#elif defined(GPS_UC6580)
_serial_gps->updateBaudRate(115200);
return GNSS_MODEL_UC6850;
#else #else
uint8_t buffer[384] = {0}; if (_serial_gps->baudRate() != serialSpeed) {
LOG_DEBUG("Setting Baud to %i\n", serialSpeed);
_serial_gps->updateBaudRate(serialSpeed);
}
#endif
#ifdef GPS_DEBUG
for (int i = 0; i < 20; i++) {
getACK("$GP", 200);
}
#endif
memset(&info, 0, sizeof(struct uBloxGnssModelInfo));
uint8_t buffer[768] = {0};
delay(100);
// Close all NMEA sentences , Only valid for MTK platform // Close all NMEA sentences , Only valid for MTK platform
_serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n"); _serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n");
delay(20); delay(20);
// Get version information // Get version information
clearBuffer();
_serial_gps->write("$PCAS06,0*1B\r\n"); _serial_gps->write("$PCAS06,0*1B\r\n");
uint32_t startTimeout = millis() + 500; if (getACK("$GPTXT,01,01,02,SW=", 500) == GNSS_RESPONSE_OK) {
while (millis() < startTimeout) { LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
if (_serial_gps->available()) { return GNSS_MODEL_MTK;
String ver = _serial_gps->readStringUntil('\r');
// Get module info , If the correct header is returned,
// it can be determined that it is the MTK chip
int index = ver.indexOf("$");
if (index != -1) {
ver = ver.substring(index);
if (ver.startsWith("$GPTXT,01,01,02,SW=")) {
LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
return GNSS_MODEL_MTK;
}
}
}
} }
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30}; uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
UBXChecksum(cfg_rate, sizeof(cfg_rate));
clearBuffer();
_serial_gps->write(cfg_rate, sizeof(cfg_rate)); _serial_gps->write(cfg_rate, sizeof(cfg_rate));
// Check that the returned response class and message ID are correct // Check that the returned response class and message ID are correct
if (!getAck(buffer, 384, 0x06, 0x08)) { GPS_RESPONSE response = getACK(0x06, 0x08, 750);
LOG_WARN("Failed to find UBlox & MTK GNSS Module\n"); if (response == GNSS_RESPONSE_NONE) {
LOG_WARN("Failed to find UBlox & MTK GNSS Module using baudrate %d\n", serialSpeed);
return GNSS_MODEL_UNKNOWN; return GNSS_MODEL_UNKNOWN;
} else if (response == GNSS_RESPONSE_FRAME_ERRORS) {
LOG_INFO("UBlox Frame Errors using baudrate %d\n", serialSpeed);
} else if (response == GNSS_RESPONSE_OK) {
LOG_INFO("Found a UBlox Module using baudrate %d\n", serialSpeed);
} }
// tips: NMEA Only should not be set here, otherwise initializing Ublox gnss module again after
// setting will not output command messages in UART1, resulting in unrecognized module information
if (serialSpeed != 9600) {
// Set the UART port to 9600
byte _message_prt[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00,
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
UBXChecksum(_message_prt, sizeof(_message_prt));
_serial_gps->write(_message_prt, sizeof(_message_prt));
delay(500);
serialSpeed = 9600;
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO) || defined(ARCH_RP2040)
_serial_gps->end();
_serial_gps->begin(serialSpeed);
#else
_serial_gps->updateBaudRate(serialSpeed);
#endif
delay(200);
}
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
byte _message_MONVER[8] = { byte _message_MONVER[8] = {
0xB5, 0x62, // Sync message for UBX protocol 0xB5, 0x62, // Sync message for UBX protocol
@@ -907,9 +1024,10 @@ GnssModel_t GPS::probe()
}; };
// Get Ublox gnss module hardware and software info // Get Ublox gnss module hardware and software info
UBXChecksum(_message_MONVER, sizeof(_message_MONVER)); UBXChecksum(_message_MONVER, sizeof(_message_MONVER));
clearBuffer();
_serial_gps->write(_message_MONVER, sizeof(_message_MONVER)); _serial_gps->write(_message_MONVER, sizeof(_message_MONVER));
uint16_t len = getAck(buffer, 384, 0x0A, 0x04); uint16_t len = getACK(buffer, sizeof(buffer), 0x0A, 0x04, 1200);
if (len) { if (len) {
// LOG_DEBUG("monver reply size = %d\n", len); // LOG_DEBUG("monver reply size = %d\n", len);
uint16_t position = 0; uint16_t position = 0;
@@ -918,13 +1036,13 @@ GnssModel_t GPS::probe()
position++; position++;
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
info.hwVersion[i] = buffer[position - 1]; info.hwVersion[i] = buffer[position];
position++; position++;
} }
while (len >= position + 30) { while (len >= position + 30) {
for (int i = 0; i < 30; i++) { for (int i = 0; i < 30; i++) {
info.extension[info.extensionNo][i] = buffer[position - 1]; info.extension[info.extensionNo][i] = buffer[position];
position++; position++;
} }
info.extensionNo++; info.extensionNo++;
@@ -934,7 +1052,6 @@ GnssModel_t GPS::probe()
LOG_DEBUG("Module Info : \n"); LOG_DEBUG("Module Info : \n");
LOG_DEBUG("Soft version: %s\n", info.swVersion); LOG_DEBUG("Soft version: %s\n", info.swVersion);
LOG_DEBUG("first char is %c\n", (char)info.swVersion[0]);
LOG_DEBUG("Hard version: %s\n", info.hwVersion); LOG_DEBUG("Hard version: %s\n", info.hwVersion);
LOG_DEBUG("Extensions:%d\n", info.extensionNo); LOG_DEBUG("Extensions:%d\n", info.extensionNo);
for (int i = 0; i < info.extensionNo; i++) { for (int i = 0; i < info.extensionNo; i++) {
@@ -953,7 +1070,7 @@ GnssModel_t GPS::probe()
} else { } else {
LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n"); LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
} }
} else if (!strncmp(info.extension[i], "PROTVER=", 8)) { } else if (!strncmp(info.extension[i], "PROTVER", 7)) {
char *ptr = nullptr; char *ptr = nullptr;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer)); strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer));
@@ -969,7 +1086,6 @@ GnssModel_t GPS::probe()
} }
return GNSS_MODEL_UBLOX; return GNSS_MODEL_UBLOX;
#endif
} }
#if HAS_GPS #if HAS_GPS

View File

@@ -18,6 +18,13 @@ typedef enum {
GNSS_MODEL_UNKNOWN, GNSS_MODEL_UNKNOWN,
} GnssModel_t; } GnssModel_t;
typedef enum {
GNSS_RESPONSE_NONE,
GNSS_RESPONSE_NAK,
GNSS_RESPONSE_FRAME_ERRORS,
GNSS_RESPONSE_OK,
} GPS_RESPONSE;
// Generate a string representation of DOP // Generate a string representation of DOP
const char *getDOPString(uint32_t dop); const char *getDOPString(uint32_t dop);
@@ -161,8 +168,6 @@ class GPS : private concurrency::OSThread
*/ */
uint32_t getSleepTime() const; uint32_t getSleepTime() const;
bool getACK(uint8_t c, uint8_t i);
/** /**
* Tell users we have new GPS readings * Tell users we have new GPS readings
*/ */
@@ -172,10 +177,11 @@ class GPS : private concurrency::OSThread
// Get GNSS model // Get GNSS model
String getNMEA(); String getNMEA();
GnssModel_t probe(); GnssModel_t probe(int serialSpeed);
int getAck(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID);
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);
// delay counter to allow more sats before fixed position stops GPS thread // delay counter to allow more sats before fixed position stops GPS thread
uint8_t fixeddelayCtr = 0; uint8_t fixeddelayCtr = 0;

View File

@@ -22,6 +22,8 @@
#define CFG_NUMLOCK_INT (1 << 3) #define CFG_NUMLOCK_INT (1 << 3)
#define CFG_KEY_INT (1 << 4) #define CFG_KEY_INT (1 << 4)
#define CFG_PANIC_INT (1 << 5) #define CFG_PANIC_INT (1 << 5)
#define CFG_REPORT_MODS (1 << 6)
#define CFG_USE_MODS (1 << 7)
#define INT_OVERFLOW (1 << 0) #define INT_OVERFLOW (1 << 0)
#define INT_CAPSLOCK (1 << 1) #define INT_CAPSLOCK (1 << 1)
@@ -33,7 +35,7 @@
#define KEY_NUMLOCK (1 << 6) #define KEY_NUMLOCK (1 << 6)
#define KEY_COUNT_MASK (0x1F) #define KEY_COUNT_MASK (0x1F)
BBQ10Keyboard::BBQ10Keyboard() : m_wire(nullptr), m_addr(NULL), writeCallback(nullptr), readCallback(nullptr) {} BBQ10Keyboard::BBQ10Keyboard() : m_wire(nullptr), m_addr(0), readCallback(nullptr), writeCallback(nullptr) {}
void BBQ10Keyboard::begin(uint8_t addr, TwoWire *wire) void BBQ10Keyboard::begin(uint8_t addr, TwoWire *wire)
{ {
@@ -66,6 +68,8 @@ void BBQ10Keyboard::reset()
writeCallback(m_addr, _REG_RST, &data, 0); writeCallback(m_addr, _REG_RST, &data, 0);
} }
delay(100); delay(100);
writeRegister(_REG_CFG, readRegister8(_REG_CFG) | CFG_REPORT_MODS);
delay(100);
} }
void BBQ10Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const void BBQ10Keyboard::attachInterrupt(uint8_t pin, void (*func)(void)) const

View File

@@ -3,6 +3,11 @@
#include "configuration.h" #include "configuration.h"
#include <Wire.h> #include <Wire.h>
#define KEY_MOD_ALT (0x1A)
#define KEY_MOD_SHL (0x1B)
#define KEY_MOD_SHR (0x1C)
#define KEY_MOD_SYM (0x1D)
class BBQ10Keyboard class BBQ10Keyboard
{ {
public: public:

View File

@@ -71,30 +71,74 @@ int32_t KbI2cBase::runOnce()
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName; e.source = this->_originName;
switch (key.key) { switch (key.key) {
case 0x1b: // ESC case 'p': // TAB
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL; case 't': // TAB as well
if (is_sym) {
e.inputEvent = ANYKEY;
e.kbchar = 0x09; // TAB Scancode
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 'q': // ESC
if (is_sym) {
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
e.kbchar = 0x1b;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break; break;
case 0x08: // Back case 0x08: // Back
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
e.kbchar = key.key; e.kbchar = key.key;
break; break;
case 0x12: // sym shift+2 case 'e': // sym e
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP; if (is_sym) {
e.kbchar = 0xb5; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
e.kbchar = 0xb5;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break; break;
case 0x18: // sym shift+8 case 'x': // sym x
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN; if (is_sym) {
e.kbchar = 0xb6; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
e.kbchar = 0xb6;
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break; break;
case 0x14: // Left (sym shift+4) case 's': // sym s
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT; if (is_sym) {
e.kbchar = 0x00; // tweak for destSelect e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = 0x00; // tweak for destSelect
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break; break;
case 0x16: // Right (sym shift+6) case 'f': // sym f
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT; if (is_sym) {
e.kbchar = 0x00; // tweak for destSelect e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = 0x00; // tweak for destSelect
is_sym = false; // reset sym state after second keypress
} else {
e.inputEvent = ANYKEY;
e.kbchar = key.key;
}
break;
case 0x13: // Code scanner says the SYM key is 0x13
is_sym = !is_sym;
break; break;
case 0x0d: // Enter
case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return case 0x0a: // apparently Enter on Q10 is a line feed instead of carriage return
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break; break;
@@ -104,6 +148,7 @@ int32_t KbI2cBase::runOnce()
default: // all other keys default: // all other keys
e.inputEvent = ANYKEY; e.inputEvent = ANYKEY;
e.kbchar = key.key; e.kbchar = key.key;
is_sym = false; // reset sym state after second keypress
break; break;
} }

View File

@@ -19,4 +19,5 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
TwoWire *i2cBus = 0; TwoWire *i2cBus = 0;
BBQ10Keyboard Q10keyboard; BBQ10Keyboard Q10keyboard;
bool is_sym = false;
}; };

View File

@@ -327,15 +327,15 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
// load data from GPS object, will add timestamp + battery further down // load data from GPS object, will add timestamp + battery further down
pos = gps->p; pos = gps->p;
} else { } else {
// The GPS has lost lock, if we are fixed position we should just keep using // The GPS has lost lock
// the old position
#ifdef GPS_EXTRAVERBOSE #ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("onGPSchanged() - lost validLocation\n"); LOG_DEBUG("onGPSchanged() - lost validLocation\n");
#endif #endif
if (config.position.fixed_position) { }
LOG_WARN("Using fixed position\n"); // Used fixed position if configured regalrdless of GPS lock
pos = ConvertToPosition(node->position); if (config.position.fixed_position) {
} LOG_WARN("Using fixed position\n");
pos = ConvertToPosition(node->position);
} }
// Finally add a fresh timestamp and battery level reading // Finally add a fresh timestamp and battery level reading

View File

@@ -190,7 +190,9 @@ void NodeDB::installDefaultConfig()
: meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN; : meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN;
// for backward compat, default position flags are ALT+MSL // for backward compat, default position flags are ALT+MSL
config.position.position_flags = config.position.position_flags =
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL); (meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE_MSL |
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
meshtastic_Config_PositionConfig_PositionFlags_DOP);
#ifdef T_WATCH_S3 #ifdef T_WATCH_S3
config.display.screen_on_secs = 30; config.display.screen_on_secs = 30;

View File

@@ -51,8 +51,9 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
} meshtastic_Config_DeviceConfig_RebroadcastMode; } meshtastic_Config_DeviceConfig_RebroadcastMode;
/* Bit field of boolean configuration options, indicating which optional /* Bit field of boolean configuration options, indicating which optional
fields to include when assembling POSITION messages fields to include when assembling POSITION messages.
Longitude and latitude are always included (also time if GPS-synced) Longitude, latitude, altitude, speed, heading, and DOP
are always included (also time if GPS-synced)
NOTE: the more fields are included, the larger the message will be - NOTE: the more fields are included, the larger the message will be -
leading to longer airtime and a higher risk of packet loss */ leading to longer airtime and a higher risk of packet loss */
typedef enum _meshtastic_Config_PositionConfig_PositionFlags { typedef enum _meshtastic_Config_PositionConfig_PositionFlags {

View File

@@ -111,6 +111,8 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_T_WATCH_S3 = 51, meshtastic_HardwareModel_T_WATCH_S3 = 51,
/* Bobricius Picomputer with ESP32-S3 CPU, Keyboard and IPS display */ /* Bobricius Picomputer with ESP32-S3 CPU, Keyboard and IPS display */
meshtastic_HardwareModel_PICOMPUTER_S3 = 52, meshtastic_HardwareModel_PICOMPUTER_S3 = 52,
/* Heltec HT-CT62 with ESP32-C3 CPU and SX1262 LoRa */
meshtastic_HardwareModel_HELTEC_HT62 = 53,
/* ------------------------------------------------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------------------------------------------------
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. 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.
------------------------------------------------------------------------------------------------------------------------------------------ */ ------------------------------------------------------------------------------------------------------------------------------------------ */

58
src/meshUtils.cpp Normal file
View File

@@ -0,0 +1,58 @@
#include "meshUtils.h"
#include <string.h>
/*
* Find the first occurrence of find in s, where the search is limited to the
* first slen characters of s.
* -
* Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
char *strnstr(const char *s, const char *find, size_t slen)
{
char c, sc;
size_t len;
if ((c = *find++) != '\0') {
len = strlen(find);
do {
do {
if (slen-- < 1 || (sc = *s++) == '\0')
return (NULL);
} while (sc != c);
if (len > slen)
return (NULL);
} while (strncmp(s, find, len) != 0);
s--;
}
return ((char *)s);
}

View File

@@ -5,3 +5,8 @@ template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi
{ {
return (v < lo) ? lo : (hi < v) ? hi : v; return (v < lo) ? lo : (hi < v) ? hi : v;
} }
#if (defined(ARCH_PORTDUINO) && !defined(STRNSTR))
#define STRNSTR
char *strnstr(const char *s, const char *find, size_t slen);
#endif

View File

@@ -171,7 +171,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) || (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) { (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
// LOG_DEBUG("Canned message event (%x)\n", event->kbchar); // LOG_DEBUG("Canned message event (%x)\n", event->kbchar);
// tweak for left/right events generated via trackball/touch with empty kbchar // tweak for left/right events generated via trackball/touch with empty kbchar
if (!event->kbchar) { if (!event->kbchar) {
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) { if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
this->payload = 0xb4; this->payload = 0xb4;
@@ -195,6 +195,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT; this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
} }
// pass the pressed key // pass the pressed key
// LOG_DEBUG("Canned message ANYKEY (%x)\n", event->kbchar);
this->payload = event->kbchar; this->payload = event->kbchar;
this->lastTouchMillis = millis(); this->lastTouchMillis = millis();
validEvent = true; validEvent = true;

View File

@@ -15,12 +15,12 @@ NOTE: For debugging only
*/ */
void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np) void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np)
{ {
LOG_DEBUG("%s NEIGHBORINFO PACKET from Node %d to Node %d (last sent by %d)\n", header, np->node_id, nodeDB.getNodeNum(), LOG_DEBUG("%s NEIGHBORINFO PACKET from Node 0x%x to Node 0x%x (last sent by 0x%x)\n", header, np->node_id,
np->last_sent_by_id); nodeDB.getNodeNum(), np->last_sent_by_id);
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count); LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count);
for (int i = 0; i < np->neighbors_count; i++) { for (int i = 0; i < np->neighbors_count; i++) {
LOG_DEBUG("Neighbor %d: node_id=%d, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr); LOG_DEBUG("Neighbor %d: node_id=0x%x, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr);
} }
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
} }
@@ -31,12 +31,12 @@ NOTE: for debugging only
void NeighborInfoModule::printNodeDBNodes(const char *header) void NeighborInfoModule::printNodeDBNodes(const char *header)
{ {
int num_nodes = nodeDB.getNumMeshNodes(); int num_nodes = nodeDB.getNumMeshNodes();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
LOG_DEBUG("DB contains %d nodes\n", num_nodes); LOG_DEBUG("DB contains %d nodes\n", num_nodes);
for (int i = 0; i < num_nodes; i++) { for (int i = 0; i < num_nodes; i++) {
const meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i); const meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->num, dbEntry->snr); LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->num, dbEntry->snr);
} }
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
} }
@@ -48,12 +48,12 @@ NOTE: for debugging only
void NeighborInfoModule::printNodeDBNeighbors(const char *header) void NeighborInfoModule::printNodeDBNeighbors(const char *header)
{ {
int num_neighbors = getNumNeighbors(); int num_neighbors = getNumNeighbors();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
LOG_DEBUG("DB contains %d neighbors\n", num_neighbors); LOG_DEBUG("DB contains %d neighbors\n", num_neighbors);
for (int i = 0; i < num_neighbors; i++) { for (int i = 0; i < num_neighbors; i++) {
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
} }
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
} }
@@ -66,7 +66,7 @@ NOTE: For debugging only
void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np) void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np)
{ {
int num_neighbors = getNumNeighbors(); int num_neighbors = getNumNeighbors();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum()); LOG_DEBUG("%s NODEDB SELECTION from Node 0x%x:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors); LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors);
for (int i = 0; i < num_neighbors; i++) { for (int i = 0; i < num_neighbors; i++) {
@@ -78,9 +78,9 @@ void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtast
} }
} }
if (!chosen) { if (!chosen) {
LOG_DEBUG(" Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); LOG_DEBUG(" Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
} else { } else {
LOG_DEBUG("---> Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); LOG_DEBUG("---> Node %d: neighbor=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
} }
} }
LOG_DEBUG("----------------\n"); LOG_DEBUG("----------------\n");
@@ -99,20 +99,11 @@ NeighborInfoModule::NeighborInfoModule()
setIntervalFromNow(35 * 1000); setIntervalFromNow(35 * 1000);
} else { } else {
LOG_DEBUG("NeighborInfoModule is disabled\n"); LOG_DEBUG("NeighborInfoModule is disabled\n");
neighborState = meshtastic_NeighborInfo_init_zero;
disable(); disable();
} }
} }
/*
Allocate a zeroed neighbor info packet
*/
meshtastic_NeighborInfo *NeighborInfoModule::allocateNeighborInfoPacket()
{
meshtastic_NeighborInfo *neighborInfo = (meshtastic_NeighborInfo *)malloc(sizeof(meshtastic_NeighborInfo));
memset(neighborInfo, 0, sizeof(meshtastic_NeighborInfo));
return neighborInfo;
}
/* /*
Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
Assumes that the neighborInfo packet has been allocated Assumes that the neighborInfo packet has been allocated
@@ -184,14 +175,14 @@ size_t NeighborInfoModule::cleanUpNeighbors()
/* Send neighbor info to the mesh */ /* Send neighbor info to the mesh */
void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies) void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
{ {
meshtastic_NeighborInfo *neighborInfo = allocateNeighborInfoPacket(); meshtastic_NeighborInfo neighborInfo = meshtastic_NeighborInfo_init_zero;
collectNeighborInfo(neighborInfo); collectNeighborInfo(&neighborInfo);
meshtastic_MeshPacket *p = allocDataProtobuf(*neighborInfo); meshtastic_MeshPacket *p = allocDataProtobuf(neighborInfo);
// send regardless of whether or not we have neighbors in our DB, // send regardless of whether or not we have neighbors in our DB,
// because we want to get neighbors for the next cycle // because we want to get neighbors for the next cycle
p->to = dest; p->to = dest;
p->decoded.want_response = wantReplies; p->decoded.want_response = wantReplies;
printNeighborInfo("SENDING", neighborInfo); printNeighborInfo("SENDING", &neighborInfo);
service.sendToMesh(p, RX_SRC_LOCAL, true); service.sendToMesh(p, RX_SRC_LOCAL, true);
} }
@@ -255,7 +246,7 @@ void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const
} }
meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n, meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n,
uint32_t node_broadcast_interval_secs, int snr) uint32_t node_broadcast_interval_secs, float snr)
{ {
// our node and the phone are the same node (not neighbors) // our node and the phone are the same node (not neighbors)
if (n == 0) { if (n == 0) {
@@ -277,7 +268,7 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
} }
// otherwise, allocate one and assign data to it // otherwise, allocate one and assign data to it
// TODO: max memory for the database should take neighbors into account, but currently doesn't // TODO: max memory for the database should take neighbors into account, but currently doesn't
if (*numNeighbors < MAX_NUM_NODES) { if (*numNeighbors < MAX_NUM_NEIGHBORS) {
(*numNeighbors)++; (*numNeighbors)++;
} }
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)]; meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)];

View File

@@ -49,7 +49,7 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
meshtastic_NeighborInfo *allocateNeighborInfoPacket(); meshtastic_NeighborInfo *allocateNeighborInfoPacket();
// Find a neighbor in our DB, create an empty neighbor if missing // Find a neighbor in our DB, create an empty neighbor if missing
meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, int snr); meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, float snr);
/* /*
* Send info on our node's neighbors into the mesh * Send info on our node's neighbors into the mesh

View File

@@ -11,8 +11,8 @@
PositionModule *positionModule; PositionModule *positionModule;
PositionModule::PositionModule() PositionModule::PositionModule()
: ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg), concurrency::OSThread( : ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg),
"PositionModule") concurrency::OSThread("PositionModule")
{ {
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others 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) setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
@@ -65,7 +65,7 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
meshtastic_MeshPacket *PositionModule::allocReply() meshtastic_MeshPacket *PositionModule::allocReply()
{ {
if (ignoreRequest) { if (ignoreRequest) {
return NULL; return nullptr;
} }
meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position
@@ -142,6 +142,11 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
service.cancelSending(prevPacketId); service.cancelSending(prevPacketId);
meshtastic_MeshPacket *p = allocReply(); meshtastic_MeshPacket *p = allocReply();
if (p == nullptr) {
LOG_WARN("allocReply returned a nullptr");
return;
}
p->to = dest; p->to = dest;
p->decoded.want_response = wantReplies; p->decoded.want_response = wantReplies;
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER) if (config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER)

View File

@@ -656,8 +656,18 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
&scratch)) { &scratch)) {
decoded = &scratch; decoded = &scratch;
msgPayload["node_id"] = new JSONValue((uint)decoded->node_id); msgPayload["node_id"] = new JSONValue((uint)decoded->node_id);
msgPayload["node_broadcast_interval_secs"] = new JSONValue((uint)decoded->node_broadcast_interval_secs);
msgPayload["last_sent_by_id"] = new JSONValue((uint)decoded->last_sent_by_id);
msgPayload["neighbors_count"] = new JSONValue(decoded->neighbors_count); msgPayload["neighbors_count"] = new JSONValue(decoded->neighbors_count);
msgPayload["neighbors"] = new JSONValue(decoded->neighbors); JSONArray neighbors;
for (uint8_t i = 0; i < decoded->neighbors_count; i++) {
JSONObject neighborObj;
neighborObj["node_id"] = new JSONValue((uint)decoded->neighbors[i].node_id);
neighborObj["snr"] = new JSONValue((int)decoded->neighbors[i].snr);
neighbors.push_back(new JSONValue(neighborObj));
}
msgPayload["neighbors"] = new JSONValue(neighbors);
jsonObj["payload"] = new JSONValue(msgPayload);
} else { } else {
LOG_ERROR("Error decoding protobuf for neighborinfo message!\n"); LOG_ERROR("Error decoding protobuf for neighborinfo message!\n");
} }

View File

@@ -119,6 +119,8 @@
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX #define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX
#elif defined(PICOMPUTER_S3) #elif defined(PICOMPUTER_S3)
#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3 #define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3
#elif defined(HELTEC_HT62)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
#endif #endif
// //

View File

@@ -0,0 +1,32 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define EXTERNAL_NUM_INTERRUPTS 22
#define NUM_DIGITAL_PINS 22
#define NUM_ANALOG_INPUTS 6
#define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (esp32_adc2gpio[(p)]) : -1)
#define digitalPinToInterrupt(p) (((p) < NUM_DIGITAL_PINS) ? (p) : -1)
#define digitalPinHasPWM(p) (p < EXTERNAL_NUM_INTERRUPTS)
static const uint8_t TX = 21;
static const uint8_t RX = 20;
static const uint8_t SDA = 1;
static const uint8_t SCL = 0;
static const uint8_t SS = 8;
static const uint8_t MOSI = 7;
static const uint8_t MISO = 6;
static const uint8_t SCK = 10;
static const uint8_t A0 = 0;
static const uint8_t A1 = 1;
static const uint8_t A2 = 2;
static const uint8_t A3 = 3;
static const uint8_t A4 = 4;
static const uint8_t A5 = 5;
#endif /* Pins_Arduino_h */

View File

@@ -0,0 +1,12 @@
[env:heltec-ht62-esp32c3-sx1262]
extends = esp32c3_base
board = esp32-c3-devkitm-1
board_level = extra
build_flags =
${esp32_base.build_flags}
-D HELTEC_HT62
-I variants/heltec_esp32c3
monitor_speed = 115200
upload_protocol = esptool
upload_port = /dev/ttyUSB0
upload_speed = 921600

View File

@@ -0,0 +1,36 @@
#define I2C_SDA 1
#define I2C_SCL 0
#define BUTTON_PIN 9
#define BUTTON_NEED_PULLUP
// LED flashes brighter
// https://resource.heltec.cn/download/HT-CT62/HT-CT62_Reference_Design.pdf
#define LED_PIN 18 // LED
#define LED_INVERTED 1
#define HAS_SCREEN 0
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#undef RF95_SCK
#undef RF95_MISO
#undef RF95_MOSI
#undef RF95_NSS
#define USE_SX1262
#define RF95_SCK 10
#define RF95_MISO 6
#define RF95_MOSI 7
#define RF95_NSS 8
#define LORA_DIO0 RADIOLIB_NC
#define LORA_RESET 5
#define LORA_DIO1 3
#define LORA_DIO2 RADIOLIB_NC
#define LORA_BUSY 4
#define SX126X_CS RF95_NSS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_BUSY
#define SX126X_RESET LORA_RESET
#define SX126X_E22

View File

@@ -4,6 +4,7 @@ extends = nrf52840_base
board = wiscore_rak4631 board = wiscore_rak4631
build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631 build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m4/fpv4-sp-d16-hard" -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m4/fpv4-sp-d16-hard"
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}

View File

@@ -227,6 +227,9 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define GPS_RX_PIN PIN_SERIAL1_RX #define GPS_RX_PIN PIN_SERIAL1_RX
#define GPS_TX_PIN PIN_SERIAL1_TX #define GPS_TX_PIN PIN_SERIAL1_TX
// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
#define PIN_GPS_EN 34 // GPS power enable pin
// RAK12002 RTC Module // RAK12002 RTC Module
#define RV3028_RTC (uint8_t)0b1010010 #define RV3028_RTC (uint8_t)0b1010010

View File

@@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 2 major = 2
minor = 2 minor = 2
build = 2 build = 4