firmware/src/main.cpp

585 lines
16 KiB
C++
Raw Normal View History

2021-03-15 02:00:20 +00:00
#include "GPS.h"
#include "MeshRadio.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
2023-01-19 02:03:10 +00:00
#include "ReliableRouter.h"
2020-12-27 06:39:43 +00:00
#include "airtime.h"
2021-03-15 02:00:20 +00:00
#include "buzz.h"
2022-05-07 10:31:21 +00:00
#include "configuration.h"
#include "error.h"
#include "power.h"
2020-07-10 02:57:55 +00:00
// #include "debug.h"
#include "FSCommon.h"
#include "RTC.h"
#include "SPILock.h"
2020-10-10 00:28:00 +00:00
#include "concurrency/OSThread.h"
#include "concurrency/Periodic.h"
#include "detect/axpDebug.h"
#include "detect/einkScan.h"
#include "detect/i2cScan.h"
2020-07-07 08:46:49 +00:00
#include "graphics/Screen.h"
2020-07-08 01:33:33 +00:00
#include "main.h"
#include "modules/Modules.h"
#include "shutdown.h"
2022-05-07 10:31:21 +00:00
#include "sleep.h"
2020-09-06 16:24:08 +00:00
#include "target_specific.h"
2020-07-01 17:08:38 +00:00
#include <Wire.h>
// #include <driver/rtc_io.h>
2022-10-22 14:29:50 +00:00
#include "mesh/eth/ethClient.h"
2023-01-19 02:03:10 +00:00
#include "mesh/http/WiFiAPClient.h"
2021-08-18 16:25:17 +00:00
#ifdef ARCH_ESP32
2022-05-07 10:31:21 +00:00
#include "mesh/http/WebServer.h"
#include "nimble/NimbleBluetooth.h"
2023-02-03 14:50:10 +00:00
NimbleBluetooth *nimbleBluetooth;
#endif
#ifdef ARCH_NRF52
#include "NRF52Bluetooth.h"
NRF52Bluetooth *nrf52Bluetooth;
#endif
2022-11-04 18:56:44 +00:00
#if HAS_WIFI
#include "mesh/api/WiFiServerAPI.h"
#include "mqtt/MQTT.h"
2021-02-07 01:17:46 +00:00
#endif
2022-10-25 22:07:02 +00:00
#if HAS_ETHERNET
#include "mesh/api/ethServerAPI.h"
2022-10-25 22:07:02 +00:00
#include "mqtt/MQTT.h"
#endif
2022-05-07 10:31:21 +00:00
#include "LLCC68Interface.h"
2020-06-17 00:01:50 +00:00
#include "RF95Interface.h"
#include "SX1262Interface.h"
2021-09-03 14:15:58 +00:00
#include "SX1268Interface.h"
2022-11-02 12:12:15 +00:00
#include "SX1280Interface.h"
2022-10-01 15:01:25 +00:00
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
#include "platform/portduino/SimRadio.h"
2022-10-01 10:03:35 +00:00
#endif
2020-06-17 00:01:50 +00:00
#if HAS_BUTTON
#include "ButtonThread.h"
#endif
#include "PowerFSMThread.h"
2020-06-17 00:01:50 +00:00
2020-10-10 01:57:57 +00:00
using namespace concurrency;
// We always create a screen object, but we only init it if we find the hardware
2020-10-10 01:57:57 +00:00
graphics::Screen *screen;
// Global power status
2020-06-29 01:17:52 +00:00
meshtastic::PowerStatus *powerStatus = new meshtastic::PowerStatus();
// Global GPS status
2020-06-29 01:17:52 +00:00
meshtastic::GPSStatus *gpsStatus = new meshtastic::GPSStatus();
// Global Node status
2020-06-29 01:17:52 +00:00
meshtastic::NodeStatus *nodeStatus = new meshtastic::NodeStatus();
2020-02-23 18:49:37 +00:00
2020-10-23 10:00:43 +00:00
/// The I2C address of our display (if found)
uint8_t screen_found;
uint8_t screen_model;
2020-10-23 10:00:43 +00:00
// The I2C address of the cardkb or RAK14004 (if found)
uint8_t cardkb_found;
2022-05-09 18:12:49 +00:00
// 0x02 for RAK14004 and 0x00 for cardkb
uint8_t kb_model;
// The I2C address of the RTC Module (if found)
uint8_t rtc_found;
// Keystore Chips
uint8_t keystore_found;
2023-01-19 01:24:18 +00:00
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
ATECCX08A atecc;
2022-10-13 11:01:24 +00:00
#endif
bool eink_found = true;
uint32_t serialSinceMsec;
bool pmu_found;
2020-02-23 18:49:37 +00:00
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
uint8_t nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {
2023-01-19 02:03:10 +00:00
0}; // one is enough, missing elements will be initialized to 0 anyway.
2020-02-23 18:49:37 +00:00
2020-10-10 01:57:57 +00:00
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
2020-04-17 18:52:20 +00:00
2020-02-02 20:55:26 +00:00
const char *getDeviceName()
{
uint8_t dmac[6];
getMacAddr(dmac);
2020-02-02 20:55:26 +00:00
2022-06-16 18:54:50 +00:00
// Meshtastic_ab3c or Shortname_abcd
static char name[20];
snprintf(name, sizeof(name), "%02x%02x", dmac[4], dmac[5]);
2022-06-16 18:54:50 +00:00
// if the shortname exists and is NOT the new default of ab3c, use it for BLE name.
2023-01-19 02:03:10 +00:00
if ((owner.short_name != NULL) && (strcmp(owner.short_name, name) != 0)) {
snprintf(name, sizeof(name), "%s_%02x%02x", owner.short_name, dmac[4], dmac[5]);
2023-01-19 02:03:10 +00:00
} else {
snprintf(name, sizeof(name), "Meshtastic_%02x%02x", dmac[4], dmac[5]);
}
return name;
2020-02-02 20:55:26 +00:00
}
2020-10-10 01:57:57 +00:00
static int32_t ledBlinker()
{
static bool ledOn;
ledOn ^= 1;
setLed(ledOn);
#ifdef ARCH_ESP32
auto newHeap = ESP.getFreeHeap();
if (newHeap < 11000) {
LOG_DEBUG("\n\n====== heap too low [11000] -> reboot in 1s ======\n\n");
#ifdef HAS_SCREEN
screen->startRebootScreen();
#endif
rebootAtMsec = millis() + 900;
}
#endif
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
2020-10-10 01:57:57 +00:00
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000);
}
uint32_t timeLastPowered = 0;
#if HAS_BUTTON
2021-03-15 02:00:20 +00:00
bool ButtonThread::shutdown_on_long_stop = false;
#endif
2021-03-15 02:00:20 +00:00
static Periodic *ledPeriodic;
static OSThread *powerFSMthread;
#if HAS_BUTTON
static OSThread *buttonThread;
2020-11-23 02:50:14 +00:00
uint32_t ButtonThread::longPressTime = 0;
#endif
RadioInterface *rIf = NULL;
/**
* Some platforms (nrf52) might provide an alterate version that supresses calling delay from sleep.
*/
2022-05-07 10:31:21 +00:00
__attribute__((weak, noinline)) bool loopCanSleep()
{
return true;
}
2020-02-02 00:14:34 +00:00
void setup()
{
concurrency::hasBeenSetup = true;
#ifdef SEGGER_STDOUT_CH
2021-03-11 02:00:08 +00:00
auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
#ifdef NRF52840_XXAA
auto buflen = 4096; // this board has a fair amount of ram
#else
auto buflen = 256; // this board has a fair amount of ram
#endif
SEGGER_RTT_ConfigUpBuffer(SEGGER_STDOUT_CH, NULL, NULL, buflen, mode);
#endif
2020-02-02 00:14:34 +00:00
#ifdef DEBUG_PORT
2023-01-19 01:24:18 +00:00
consoleInit(); // Set serial baud rate and init our mesh console
2020-02-02 00:14:34 +00:00
#endif
2022-05-07 10:31:21 +00:00
serialSinceMsec = millis();
2022-12-30 02:41:37 +00:00
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n\n");
2022-01-10 15:57:25 +00:00
initDeepSleep();
// Testing this fix für erratic T-Echo boot behaviour
#if defined(TTGO_T_ECHO) && defined(PIN_EINK_PWR_ON)
pinMode(PIN_EINK_PWR_ON, OUTPUT);
digitalWrite(PIN_EINK_PWR_ON, HIGH);
#endif
2020-02-01 22:23:21 +00:00
#ifdef VEXT_ENABLE
pinMode(VEXT_ENABLE, OUTPUT);
digitalWrite(VEXT_ENABLE, 0); // turn on the display power
2020-02-02 00:14:34 +00:00
#endif
2020-02-01 22:23:21 +00:00
#ifdef RESET_OLED
pinMode(RESET_OLED, OUTPUT);
digitalWrite(RESET_OLED, 1);
2020-02-02 00:14:34 +00:00
#endif
2020-02-01 22:23:21 +00:00
#ifdef BUTTON_PIN
#ifdef ARCH_ESP32
2021-02-20 08:34:25 +00:00
// If the button is connected to GPIO 12, don't enable the ability to use
// meshtasticAdmin on the device.
pinMode(BUTTON_PIN, INPUT);
2021-02-20 08:34:25 +00:00
#ifdef BUTTON_NEED_PULLUP
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
2021-02-20 08:34:25 +00:00
delay(10);
#endif
#endif
#endif
2020-10-10 01:57:57 +00:00
OSThread::setup();
ledPeriodic = new Periodic("Blink", ledBlinker);
fsInit();
2022-03-16 00:52:18 +00:00
router = new ReliableRouter();
2020-10-10 00:28:00 +00:00
#ifdef I2C_SDA1
Wire1.begin(I2C_SDA1, I2C_SCL1);
#endif
#ifdef I2C_SDA
Wire.begin(I2C_SDA, I2C_SCL);
#elif HAS_WIRE
Wire.begin();
#endif
#ifdef PIN_LCD_RESET
2020-10-23 10:00:43 +00:00
// FIXME - move this someplace better, LCD is at address 0x3F
pinMode(PIN_LCD_RESET, OUTPUT);
digitalWrite(PIN_LCD_RESET, 0);
2020-10-24 00:16:15 +00:00
delay(1);
digitalWrite(PIN_LCD_RESET, 1);
2020-10-24 00:16:15 +00:00
delay(1);
#endif
#ifdef RAK4630
// We need to enable 3.3V periphery in order to scan it
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
#endif
// Currently only the tbeam has a PMU
// PMU initialization needs to be placed before scanI2Cdevice
power = new Power();
power->setStatusHandler(powerStatus);
powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
#ifdef LILYGO_TBEAM_S3_CORE
// In T-Beam-S3-core, the I2C device cannot be scanned before power initialization, otherwise the device will be stuck
// PCF8563 RTC in tbeam-s3 uses Wire1 to share I2C bus
Wire1.beginTransmission(PCF8563_RTC);
2023-01-19 02:03:10 +00:00
if (Wire1.endTransmission() == 0) {
rtc_found = PCF8563_RTC;
LOG_INFO("PCF8563 RTC found\n");
}
2022-11-12 08:01:30 +00:00
#endif
// We need to scan here to decide if we have a screen for nodeDB.init()
scanI2Cdevice();
2022-11-12 07:14:13 +00:00
#ifdef HAS_SDCARD
setupSDCard();
#endif
#ifdef RAK4630
// scanEInkDevice();
#endif
#if HAS_BUTTON
// Buttons & LED
buttonThread = new ButtonThread();
#endif
2020-10-29 01:38:27 +00:00
#ifdef LED_PIN
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
#endif
// Hello
2022-12-30 02:41:37 +00:00
LOG_INFO("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
#ifdef ARCH_ESP32
// Don't init display if we don't have one or we are waking headless due to a timer event
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
2020-10-23 10:00:43 +00:00
screen_found = 0; // forget we even have the hardware
esp32Setup();
#endif
#ifdef ARCH_NRF52
nrf52Setup();
#endif
2020-12-26 05:36:21 +00:00
// We do this as early as possible because this loads preferences from flash
// but we need to do this after main cpu iniot (esp32setup), because we need the random seed set
nodeDB.init();
// If we're taking on the repeater role, use flood router
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
router = new FloodingRouter();
2022-10-25 22:07:02 +00:00
playStartMelody();
2022-11-04 18:56:44 +00:00
// fixed screen override?
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
2022-11-04 18:56:44 +00:00
screen_model = config.display.oled;
#if defined(USE_SH1107)
screen_model = Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
#endif
// Init our SPI controller (must be before screen and lora)
initSPI();
#ifndef ARCH_ESP32
SPI.begin();
#else
// ESP32
SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
SPI.setFrequency(4000000);
#endif
// Initialize the screen first so we can show the logo while we start up everything else.
2020-10-23 10:00:43 +00:00
screen = new graphics::Screen(screen_found);
2020-05-04 18:15:05 +00:00
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
2021-03-15 02:00:20 +00:00
gps = createGps();
2020-10-13 06:43:28 +00:00
if (gps)
gpsStatus->observe(&gps->newStatus);
else
2022-12-30 02:41:37 +00:00
LOG_WARN("No GPS found - running without GPS\n");
2020-10-23 10:00:43 +00:00
2020-06-29 01:17:52 +00:00
nodeStatus->observe(&nodeDB.newStatus);
service.init();
// Now that the mesh service is created, create any modules
2022-02-27 09:49:24 +00:00
setupModules();
2020-12-26 05:36:21 +00:00
// Do this after service.init (because that clears error_code)
2022-09-08 02:36:53 +00:00
#ifdef HAS_PMU
if (!pmu_found)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_NO_AXP192); // Record a hardware fault for missing hardware
#endif
2020-12-26 05:36:21 +00:00
// Don't call screen setup until after nodedb is setup (because we need
// the current region name)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER)
2020-10-21 09:27:13 +00:00
screen->setup();
#else
2020-10-23 10:00:43 +00:00
if (screen_found)
2020-10-21 09:27:13 +00:00
screen->setup();
#endif
2020-10-23 10:00:43 +00:00
screen->print("Started...\n");
2020-10-21 09:27:13 +00:00
// We have now loaded our saved preferences from flash
// ONCE we will factory reset the GPS for bug #327
2023-01-19 02:03:10 +00:00
if (gps && !devicestate.did_gps_reset) {
2022-12-30 02:41:37 +00:00
LOG_WARN("GPS FactoryReset requested\n");
2023-01-19 02:03:10 +00:00
if (gps->factoryReset()) { // If we don't succeed try again next time
devicestate.did_gps_reset = true;
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
}
}
#ifdef SX126X_ANT_SW
// make analog PA vs not PA switch on SX126x eval board work properly
pinMode(SX126X_ANT_SW, OUTPUT);
digitalWrite(SX126X_ANT_SW, 1);
2021-09-03 14:15:58 +00:00
#endif
// radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
if (!rIf) {
rIf = new SimRadio;
if (!rIf->init()) {
LOG_WARN("Failed to find simulated radio\n");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("Using SIMULATED radio!\n");
}
}
#endif
2020-07-10 21:37:01 +00:00
#if defined(RF95_IRQ)
2023-01-19 02:03:10 +00:00
if (!rIf) {
rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI);
2023-01-19 02:03:10 +00:00
if (!rIf->init()) {
2022-12-30 02:41:37 +00:00
LOG_WARN("Failed to find RF95 radio\n");
delete rIf;
rIf = NULL;
2023-01-19 02:03:10 +00:00
} else {
LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n");
}
}
#endif
#if defined(USE_SX1280)
2023-01-19 02:03:10 +00:00
if (!rIf) {
2022-11-02 12:12:15 +00:00
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
2023-01-19 02:03:10 +00:00
if (!rIf->init()) {
2022-12-30 02:41:37 +00:00
LOG_WARN("Failed to find SX1280 radio\n");
2022-10-16 17:07:58 +00:00
delete rIf;
rIf = NULL;
2023-01-19 02:03:10 +00:00
} else {
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
2022-10-16 17:07:58 +00:00
}
}
#endif
#if defined(USE_SX1262)
2023-01-19 02:03:10 +00:00
if (!rIf) {
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
2023-01-19 02:03:10 +00:00
if (!rIf->init()) {
2022-12-30 02:41:37 +00:00
LOG_WARN("Failed to find SX1262 radio\n");
delete rIf;
rIf = NULL;
2023-01-19 02:03:10 +00:00
} else {
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
}
}
#endif
#if defined(USE_SX1268)
2023-01-19 02:03:10 +00:00
if (!rIf) {
rIf = new SX1268Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
2023-01-19 02:03:10 +00:00
if (!rIf->init()) {
2022-12-30 02:41:37 +00:00
LOG_WARN("Failed to find SX1268 radio\n");
2021-09-03 14:15:58 +00:00
delete rIf;
rIf = NULL;
2023-01-19 02:03:10 +00:00
} else {
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio\n");
2021-09-03 14:15:58 +00:00
}
}
#endif
2021-11-17 10:28:08 +00:00
#if defined(USE_LLCC68)
2023-01-19 02:03:10 +00:00
if (!rIf) {
2021-11-17 10:28:08 +00:00
rIf = new LLCC68Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
2023-01-19 02:03:10 +00:00
if (!rIf->init()) {
2022-12-30 02:41:37 +00:00
LOG_WARN("Failed to find LLCC68 radio\n");
2021-11-17 10:28:08 +00:00
delete rIf;
rIf = NULL;
2023-01-19 02:03:10 +00:00
} else {
LOG_INFO("LLCC68 Radio init succeeded, using LLCC68 radio\n");
2021-11-17 10:28:08 +00:00
}
}
#endif
2023-01-19 01:24:18 +00:00
// check if the radio chip matches the selected region
if ((config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())) {
2023-01-19 01:24:18 +00:00
LOG_WARN("Radio chip does not support 2.4GHz LoRa. Reverting to unset.\n");
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_UNSET;
2023-01-19 01:24:18 +00:00
nodeDB.saveToDisk(SEGMENT_CONFIG);
2023-01-19 02:03:10 +00:00
if (!rIf->reconfigure()) {
2023-01-19 01:24:18 +00:00
LOG_WARN("Reconfigure failed, rebooting\n");
screen->startRebootScreen();
rebootAtMsec = millis() + 5000;
}
}
2022-10-25 22:07:02 +00:00
#if HAS_WIFI || HAS_ETHERNET
mqttInit();
#endif
2022-10-22 14:53:57 +00:00
#ifndef ARCH_PORTDUINO
// Initialize Wifi
2022-10-25 09:53:22 +00:00
initWifi();
2022-10-22 14:29:50 +00:00
// Initialize Ethernet
initEthernet();
2022-10-22 14:53:57 +00:00
#endif
2022-10-22 14:29:50 +00:00
#ifdef ARCH_ESP32
2021-01-09 04:06:11 +00:00
// Start web server thread.
webServerThread = new WebServerThread();
2021-01-09 06:59:37 +00:00
#endif
2021-01-09 04:06:11 +00:00
#ifdef ARCH_PORTDUINO
2022-10-01 10:02:29 +00:00
initApiServer(TCPPort);
2021-02-07 01:17:46 +00:00
#endif
// Start airtime logger thread.
airTime = new AirTime();
2021-01-09 04:06:11 +00:00
if (!rIf)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_NO_RADIO);
2023-01-19 02:03:10 +00:00
else {
2020-10-10 01:57:57 +00:00
router->addInterface(rIf);
// Calculate and save the bit rate to myNodeInfo
// TODO: This needs to be added what ever method changes the channel from the phone.
2023-01-21 17:39:58 +00:00
myNodeInfo.bitrate =
(float(meshtastic_Constants_DATA_PAYLOAD_LEN) / (float(rIf->getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN)))) *
1000;
2022-12-30 02:41:37 +00:00
LOG_DEBUG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
}
2021-12-24 02:18:07 +00:00
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
powerFSMthread = new PowerFSMThread();
// setBluetoothEnable(false); we now don't start bluetooth until we enter the proper state
setCPUFast(false); // 80MHz is fine for our slow peripherals
}
2022-05-07 10:31:21 +00:00
uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes)
uint32_t shutdownAtMsec; // If not zero we will shutdown at this time (used to shutdown from python or mobile client)
2021-03-27 02:19:59 +00:00
// If a thread does something that might need for it to be rescheduled ASAP it can set this flag
// This will supress the current delay and instead try to run ASAP.
bool runASAP;
2020-02-02 00:14:34 +00:00
void loop()
{
runASAP = false;
// axpDebugOutput.loop();
2020-06-13 15:28:01 +00:00
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
#ifdef ARCH_ESP32
esp32Loop();
#endif
#ifdef ARCH_NRF52
2021-03-09 07:07:16 +00:00
nrf52Loop();
#endif
powerCommandsCheck();
// For debugging
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
#ifdef DEBUG_STACK
static uint32_t lastPrint = 0;
2023-01-19 02:03:10 +00:00
if (millis() - lastPrint > 10 * 1000L) {
lastPrint = millis();
meshtastic::printThreadInfo("main");
}
#endif
2020-10-10 01:57:57 +00:00
// TODO: This should go into a thread handled by FreeRTOS.
// handleWebResponse();
2020-10-10 01:57:57 +00:00
service.loop();
2020-02-08 01:48:12 +00:00
2020-10-10 01:57:57 +00:00
long delayMsec = mainController.runOrDelay();
2020-02-21 12:57:08 +00:00
/* if (mainController.nextThread && delayMsec)
2022-12-30 02:41:37 +00:00
LOG_DEBUG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
mainController.nextThread->tillRun(millis())); */
2020-10-10 01:57:57 +00:00
// We want to sleep as long as possible here - because it saves power
2023-01-19 02:03:10 +00:00
if (!runASAP && loopCanSleep()) {
2022-12-30 02:41:37 +00:00
// if(delayMsec > 100) LOG_DEBUG("sleeping %ld\n", delayMsec);
mainDelay.delay(delayMsec);
2021-08-15 17:34:57 +00:00
}
2022-12-30 02:41:37 +00:00
// if (didWake) LOG_DEBUG("wake!\n");
}