diff --git a/debian/control b/debian/control index bb79d1958..b3a8eb58e 100644 --- a/debian/control +++ b/debian/control @@ -3,6 +3,7 @@ Section: misc Priority: optional Maintainer: Austin Lane Build-Depends: debhelper-compat (= 13), + lsb-release, tar, gzip, platformio, diff --git a/debian/rules b/debian/rules index a1a27c2f2..0612ba352 100755 --- a/debian/rules +++ b/debian/rules @@ -11,6 +11,15 @@ PIO_ENV:=\ PLATFORMIO_LIBDEPS_DIR=pio/libdeps \ PLATFORMIO_PACKAGES_DIR=pio/packages +# Raspbian armhf builds should be compatible with armv6-hardfloat +# https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-1/#rpi1-compiler-flags +ifneq (,$(findstring Raspbian,$(shell lsb_release -is))) +ifeq ($(DEB_BUILD_ARCH),armhf) +PIO_ENV+=\ + PLATFORMIO_BUILD_FLAGS="-mfloat-abi=hard -mfpu=vfp -march=armv6zk" +endif +endif + override_dh_auto_build: # Extract tarballs within source deb tar -xf pio.tar diff --git a/src/detect/einkScan.h b/src/detect/einkScan.h index 5bc218d00..d20c7b6e5 100644 --- a/src/detect/einkScan.h +++ b/src/detect/einkScan.h @@ -6,28 +6,28 @@ void d_writeCommand(uint8_t c) { - SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, LOW); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW); - SPI.transfer(c); + SPI1.transfer(c); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH); if (PIN_EINK_DC >= 0) digitalWrite(PIN_EINK_DC, HIGH); - SPI.endTransaction(); + SPI1.endTransaction(); } void d_writeData(uint8_t d) { - SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); + SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, LOW); - SPI.transfer(d); + SPI1.transfer(d); if (PIN_EINK_CS >= 0) digitalWrite(PIN_EINK_CS, HIGH); - SPI.endTransaction(); + SPI1.endTransaction(); } unsigned long d_waitWhileBusy(uint16_t busy_time) @@ -53,7 +53,7 @@ unsigned long d_waitWhileBusy(uint16_t busy_time) void scanEInkDevice(void) { - SPI.begin(); + SPI1.begin(); d_writeCommand(0x22); d_writeData(0x83); d_writeCommand(0x20); @@ -62,6 +62,6 @@ void scanEInkDevice(void) LOG_DEBUG("EInk display found"); else LOG_DEBUG("EInk display not found"); - SPI.end(); + SPI1.end(); } #endif \ No newline at end of file diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index f4b07664f..2989a59bd 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -48,8 +48,6 @@ HardwareSerial *GPS::_serial_gps = nullptr; GPS *gps = nullptr; -static const char *ACK_SUCCESS_MESSAGE = "Get ack success!"; - static GPSUpdateScheduling scheduling; /// Multiple GPS instances might use the same serial port (in sequence), but we can @@ -1039,14 +1037,6 @@ int32_t GPS::runOnce() if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) { return disable(); } - // ONCE we will factory reset the GPS for bug #327 - if (!devicestate.did_gps_reset) { - LOG_WARN("GPS FactoryReset requested"); - if (gps->factoryReset()) { // If we don't succeed try again next time - devicestate.did_gps_reset = true; - nodeDB->saveToDisk(SEGMENT_DEVICESTATE); - } - } GPSInitFinished = true; publishUpdate(); } @@ -1059,24 +1049,6 @@ int32_t GPS::runOnce() if (whileActive()) { // if we have received valid NMEA claim we are connected setConnected(); - } else { - if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && - IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9, - GNSS_MODEL_UBLOX10)) { - // reset the GPS on next bootup - if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) { - LOG_DEBUG("GPS is not found, try factory reset on next boot"); - devicestate.did_gps_reset = false; - nodeDB->saveToDisk(SEGMENT_DEVICESTATE); - 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; - LOG_DEBUG("Would normally factoryReset()"); - // gps->factoryReset(); } // If we're due for an update, wake the GPS @@ -1411,62 +1383,6 @@ static int32_t toDegInt(RawDegrees d) return r; } -bool GPS::factoryReset() -{ -#ifdef PIN_GPS_REINIT - // The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW - pinMode(PIN_GPS_REINIT, OUTPUT); - digitalWrite(PIN_GPS_REINIT, 0); - delay(150); // The L76K datasheet calls for at least 100MS delay - digitalWrite(PIN_GPS_REINIT, 1); -#endif - - 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_DEBUG(ACK_SUCCESS_MESSAGE); - } - 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_DEBUG(ACK_SUCCESS_MESSAGE); - } - 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_DEBUG(ACK_SUCCESS_MESSAGE); - } - } else if (gnssModel == GNSS_MODEL_MTK) { - // send the CAS10 to perform a factory restart of the device (and other device that support PCAS statements) - LOG_INFO("GNSS Factory Reset via PCAS10,3"); - _serial_gps->write("$PCAS10,3*1F\r\n"); - delay(100); - } else if (gnssModel == GNSS_MODEL_ATGM336H) { - LOG_INFO("Factory Reset via CAS-CFG-RST"); - uint8_t msglen = makeCASPacket(0x06, 0x02, sizeof(_message_CAS_CFG_RST_FACTORY), _message_CAS_CFG_RST_FACTORY); - _serial_gps->write(UBXscratch, msglen); - delay(100); - } else { - // fire this for good measure, if we have an L76B - won't harm other devices. - _serial_gps->write("$PMTK104*37\r\n"); - // No PMTK_ACK for this command. - delay(100); - // 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; -} - /** * 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 diff --git a/src/gps/GPS.h b/src/gps/GPS.h index df85b7cbf..01a4fe745 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -101,8 +101,6 @@ class GPS : private concurrency::OSThread // Empty the input buffer as quickly as possible void clearBuffer(); - virtual bool factoryReset(); - // Creates an instance of the GPS class. // Returns the new instance or null if the GPS is not present. static GPS *createGps(); diff --git a/src/main.cpp b/src/main.cpp index f4599e0e3..be498421c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -931,6 +931,7 @@ void setup() if (!sxIf->init()) { LOG_WARN("No SX1262 radio"); delete sxIf; + rIf = NULL; } else { LOG_INFO("SX1262 init success"); rIf = sxIf; @@ -947,6 +948,7 @@ void setup() if (!sxIf->init()) { LOG_WARN("No SX1262 radio with TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE); delete sxIf; + rIf = NULL; } else { LOG_INFO("SX1262 init success, TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE); rIf = sxIf; diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 6789acbb3..699e6e0e4 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -643,6 +643,11 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p) meshtastic_QueueStatus qs = router->getQueueStatus(); service->sendQueueStatusToPhone(qs, 0, p.id); return false; + } else if (p.decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP && isBroadcast(p.to) && p.hop_limit > 0) { + sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Multi-hop traceroute to broadcast address is not allowed"); + meshtastic_QueueStatus qs = router->getQueueStatus(); + service->sendQueueStatusToPhone(qs, 0, p.id); + return false; } else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] && Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) { LOG_WARN("Rate limit portnum %d", p.decoded.portnum); diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp index 04bcbe200..14901f0af 100644 --- a/src/modules/Telemetry/PowerTelemetry.cpp +++ b/src/modules/Telemetry/PowerTelemetry.cpp @@ -31,7 +31,6 @@ int32_t PowerTelemetryModule::runOnce() doDeepSleep(nightyNightMs, true, false); } - uint32_t result = UINT32_MAX; /* Uncomment the preferences below if you want to use the module without having to configure it from the PythonAPI or WebUI. @@ -46,25 +45,33 @@ int32_t PowerTelemetryModule::runOnce() return disable(); } + uint32_t sendToMeshIntervalMs = Default::getConfiguredOrDefaultMsScaled( + moduleConfig.telemetry.power_update_interval, default_telemetry_broadcast_interval_secs, numOnlineNodes); + if (firstTime) { // This is the first time the OSThread library has called this function, so do some setup firstTime = 0; + uint32_t result = UINT32_MAX; + #if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) if (moduleConfig.telemetry.power_measurement_enabled) { LOG_INFO("Power Telemetry: init"); - // it's possible to have this module enabled, only for displaying values on the screen. - // therefore, we should only enable the sensor loop if measurement is also enabled - if (ina219Sensor.hasSensor() && !ina219Sensor.isInitialized()) - result = ina219Sensor.runOnce(); - if (ina226Sensor.hasSensor() && !ina226Sensor.isInitialized()) - result = ina226Sensor.runOnce(); - if (ina260Sensor.hasSensor() && !ina260Sensor.isInitialized()) - result = ina260Sensor.runOnce(); - if (ina3221Sensor.hasSensor() && !ina3221Sensor.isInitialized()) - result = ina3221Sensor.runOnce(); - if (max17048Sensor.hasSensor() && !max17048Sensor.isInitialized()) - result = max17048Sensor.runOnce(); + // If sensor is already initialized by EnvironmentTelemetryModule, then we don't need to initialize it again, + // but we need to set the result to != UINT32_MAX to avoid it being disabled + if (ina219Sensor.hasSensor()) + result = ina219Sensor.isInitialized() ? 0 : ina219Sensor.runOnce(); + if (ina226Sensor.hasSensor()) + result = ina226Sensor.isInitialized() ? 0 : ina226Sensor.runOnce(); + if (ina260Sensor.hasSensor()) + result = ina260Sensor.isInitialized() ? 0 : ina260Sensor.runOnce(); + if (ina3221Sensor.hasSensor()) + result = ina3221Sensor.isInitialized() ? 0 : ina3221Sensor.runOnce(); + if (max17048Sensor.hasSensor()) + result = max17048Sensor.isInitialized() ? 0 : max17048Sensor.runOnce(); } + + // it's possible to have this module enabled, only for displaying values on the screen. + // therefore, we should only enable the sensor loop if measurement is also enabled return result == UINT32_MAX ? disable() : setStartDelay(); #else return disable(); @@ -74,10 +81,7 @@ int32_t PowerTelemetryModule::runOnce() if (!moduleConfig.telemetry.power_measurement_enabled) return disable(); - if (((lastSentToMesh == 0) || - !Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled( - moduleConfig.telemetry.power_update_interval, - default_telemetry_broadcast_interval_secs, numOnlineNodes))) && + if (((lastSentToMesh == 0) || !Throttle::isWithinTimespanMs(lastSentToMesh, sendToMeshIntervalMs)) && airTime->isTxAllowedAirUtil()) { sendTelemetry(); lastSentToMesh = millis(); @@ -89,8 +93,9 @@ int32_t PowerTelemetryModule::runOnce() lastSentToPhone = millis(); } } - return min(sendToPhoneIntervalMs, result); + return min(sendToPhoneIntervalMs, sendToMeshIntervalMs); } + bool PowerTelemetryModule::wantUIFrame() { return moduleConfig.telemetry.power_screen_enabled; diff --git a/src/modules/TraceRouteModule.cpp b/src/modules/TraceRouteModule.cpp index 79b14de0a..e9aaf9d30 100644 --- a/src/modules/TraceRouteModule.cpp +++ b/src/modules/TraceRouteModule.cpp @@ -150,6 +150,12 @@ meshtastic_MeshPacket *TraceRouteModule::allocReply() { assert(currentRequest); + // Ignore multi-hop broadcast requests + if (isBroadcast(currentRequest->to) && currentRequest->hop_limit < currentRequest->hop_start) { + ignoreRequest = true; + return NULL; + } + // Copy the payload of the current request auto req = *currentRequest; const auto &p = req.decoded; diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index f50f3b880..bc5541336 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -107,11 +107,15 @@ static const uint8_t AREF = PIN_AREF; /* * SPI Interfaces */ -#define SPI_INTERFACES_COUNT 1 +#define SPI_INTERFACES_COUNT 2 -#define PIN_SPI_MISO (29) -#define PIN_SPI_MOSI (30) -#define PIN_SPI_SCK (3) +#define PIN_SPI_MISO (45) +#define PIN_SPI_MOSI (44) +#define PIN_SPI_SCK (43) + +#define PIN_SPI1_MISO (29) // (0 + 29) +#define PIN_SPI1_MOSI (30) // (0 + 30) +#define PIN_SPI1_SCK (3) // (0 + 3) static const uint8_t SS = 42; static const uint8_t MOSI = PIN_SPI_MOSI; @@ -126,8 +130,8 @@ static const uint8_t SCK = PIN_SPI_SCK; #define PIN_EINK_BUSY (0 + 4) #define PIN_EINK_DC (0 + 17) #define PIN_EINK_RES (-1) -#define PIN_EINK_SCLK PIN_SPI_SCK -#define PIN_EINK_MOSI PIN_SPI_MOSI // also called SDI +#define PIN_EINK_SCLK (0 + 3) +#define PIN_EINK_MOSI (0 + 30) // also called SDI // #define USE_EINK @@ -255,7 +259,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG #define PIN_ETHERNET_RESET 21 #define PIN_ETHERNET_SS PIN_EINK_CS -#define ETH_SPI_PORT SPI +#define ETH_SPI_PORT SPI1 #define AQ_SET_PIN 10 #ifdef __cplusplus