2021-06-27 17:56:28 +00:00
|
|
|
#include "configuration.h"
|
2021-03-15 02:00:20 +00:00
|
|
|
#include "GPS.h"
|
2020-03-19 02:15:51 +00:00
|
|
|
#include "MeshRadio.h"
|
2020-02-02 20:45:32 +00:00
|
|
|
#include "MeshService.h"
|
2020-02-08 04:59:21 +00:00
|
|
|
#include "NodeDB.h"
|
2020-03-19 02:15:51 +00:00
|
|
|
#include "PowerFSM.h"
|
2020-12-27 06:39:43 +00:00
|
|
|
#include "airtime.h"
|
2021-03-15 02:00:20 +00:00
|
|
|
#include "buzz.h"
|
2020-04-14 18:40:49 +00:00
|
|
|
#include "error.h"
|
2020-03-26 16:24:53 +00:00
|
|
|
#include "power.h"
|
2020-04-15 03:22:27 +00:00
|
|
|
// #include "rom/rtc.h"
|
2020-05-27 22:31:32 +00:00
|
|
|
#include "DSRRouter.h"
|
2020-07-10 02:57:55 +00:00
|
|
|
// #include "debug.h"
|
2020-11-19 01:25:02 +00:00
|
|
|
#include "FSCommon.h"
|
2020-10-07 23:28:57 +00:00
|
|
|
#include "RTC.h"
|
2020-08-29 00:38:23 +00:00
|
|
|
#include "SPILock.h"
|
2020-10-10 00:28:00 +00:00
|
|
|
#include "concurrency/OSThread.h"
|
2020-10-09 06:16:51 +00:00
|
|
|
#include "concurrency/Periodic.h"
|
2020-07-07 08:46:49 +00:00
|
|
|
#include "graphics/Screen.h"
|
2020-07-08 01:33:33 +00:00
|
|
|
#include "main.h"
|
2021-01-08 05:15:49 +00:00
|
|
|
#include "plugins/Plugins.h"
|
2021-01-09 06:25:44 +00:00
|
|
|
#include "sleep.h"
|
2020-09-06 16:24:08 +00:00
|
|
|
#include "target_specific.h"
|
2020-06-22 18:09:26 +00:00
|
|
|
#include <OneButton.h>
|
2020-07-01 17:08:38 +00:00
|
|
|
#include <Wire.h>
|
2020-04-15 03:22:27 +00:00
|
|
|
// #include <driver/rtc_io.h>
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2021-08-18 16:25:17 +00:00
|
|
|
#include "mesh/http/WiFiAPClient.h"
|
|
|
|
|
2020-04-10 19:18:48 +00:00
|
|
|
#ifndef NO_ESP32
|
2021-01-15 05:21:33 +00:00
|
|
|
#include "mesh/http/WebServer.h"
|
2020-07-22 19:08:54 +00:00
|
|
|
#include "nimble/BluetoothUtil.h"
|
2020-04-10 19:18:48 +00:00
|
|
|
#endif
|
|
|
|
|
2021-04-03 06:54:10 +00:00
|
|
|
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
2021-02-07 01:17:46 +00:00
|
|
|
#include "mesh/wifi/WiFiServerAPI.h"
|
2021-04-03 06:54:10 +00:00
|
|
|
#include "mqtt/MQTT.h"
|
2021-02-07 01:17:46 +00:00
|
|
|
#endif
|
|
|
|
|
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"
|
2021-11-17 10:28:08 +00:00
|
|
|
#include "LLCC68Interface.h"
|
2020-06-17 00:01:50 +00:00
|
|
|
|
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
using namespace concurrency;
|
|
|
|
|
2020-04-23 20:56:15 +00:00
|
|
|
// 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;
|
2020-03-15 23:47:38 +00:00
|
|
|
|
2020-06-28 04:19:49 +00:00
|
|
|
// Global power status
|
2020-06-29 01:17:52 +00:00
|
|
|
meshtastic::PowerStatus *powerStatus = new meshtastic::PowerStatus();
|
2020-06-28 04:19:49 +00:00
|
|
|
|
|
|
|
// Global GPS status
|
2020-06-29 01:17:52 +00:00
|
|
|
meshtastic::GPSStatus *gpsStatus = new meshtastic::GPSStatus();
|
2020-06-28 04:19:49 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2020-02-23 18:49:37 +00:00
|
|
|
bool axp192_found;
|
|
|
|
|
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-01 16:30:53 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Application
|
|
|
|
// -----------------------------------------------------------------------------
|
2021-03-20 01:46:11 +00:00
|
|
|
#ifndef NO_WIRE
|
2020-02-01 16:30:53 +00:00
|
|
|
void scanI2Cdevice(void)
|
|
|
|
{
|
2020-03-19 02:15:51 +00:00
|
|
|
byte err, addr;
|
|
|
|
int nDevices = 0;
|
|
|
|
for (addr = 1; addr < 127; addr++) {
|
|
|
|
Wire.beginTransmission(addr);
|
|
|
|
err = Wire.endTransmission();
|
|
|
|
if (err == 0) {
|
|
|
|
DEBUG_MSG("I2C device found at address 0x%x\n", addr);
|
|
|
|
|
|
|
|
nDevices++;
|
|
|
|
|
|
|
|
if (addr == SSD1306_ADDRESS) {
|
2020-10-23 10:00:43 +00:00
|
|
|
screen_found = addr;
|
2020-03-19 02:15:51 +00:00
|
|
|
DEBUG_MSG("ssd1306 display found\n");
|
|
|
|
}
|
2020-10-23 10:00:43 +00:00
|
|
|
if (addr == ST7567_ADDRESS) {
|
|
|
|
screen_found = addr;
|
|
|
|
DEBUG_MSG("st7567 display found\n");
|
|
|
|
}
|
2020-04-24 21:55:51 +00:00
|
|
|
#ifdef AXP192_SLAVE_ADDRESS
|
2020-03-19 02:15:51 +00:00
|
|
|
if (addr == AXP192_SLAVE_ADDRESS) {
|
|
|
|
axp192_found = true;
|
|
|
|
DEBUG_MSG("axp192 PMU found\n");
|
|
|
|
}
|
2020-02-02 00:14:34 +00:00
|
|
|
#endif
|
2020-03-19 02:15:51 +00:00
|
|
|
} else if (err == 4) {
|
|
|
|
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
|
|
|
|
}
|
2020-02-01 16:30:53 +00:00
|
|
|
}
|
2020-12-26 05:36:21 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
if (nDevices == 0)
|
|
|
|
DEBUG_MSG("No I2C devices found\n");
|
|
|
|
else
|
|
|
|
DEBUG_MSG("done\n");
|
2020-02-01 16:30:53 +00:00
|
|
|
}
|
2021-03-15 02:00:20 +00:00
|
|
|
#else
|
|
|
|
void scanI2Cdevice(void) {}
|
|
|
|
#endif
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2020-02-02 20:55:26 +00:00
|
|
|
const char *getDeviceName()
|
|
|
|
{
|
2020-03-19 02:15:51 +00:00
|
|
|
uint8_t dmac[6];
|
2020-04-15 03:22:27 +00:00
|
|
|
|
|
|
|
getMacAddr(dmac);
|
2020-02-02 20:55:26 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// Meshtastic_ab3c
|
|
|
|
static char name[20];
|
|
|
|
sprintf(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()
|
2020-04-25 17:59:40 +00:00
|
|
|
{
|
|
|
|
static bool ledOn;
|
|
|
|
ledOn ^= 1;
|
|
|
|
|
|
|
|
setLed(ledOn);
|
|
|
|
|
|
|
|
// 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);
|
2020-04-25 17:59:40 +00:00
|
|
|
}
|
|
|
|
|
2021-12-06 02:37:35 +00:00
|
|
|
uint32_t timeLastPowered = 0;
|
|
|
|
|
2020-10-11 00:12:53 +00:00
|
|
|
/// Wrapper to convert our powerFSM stuff into a 'thread'
|
|
|
|
class PowerFSMThread : public OSThread
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
|
|
|
|
PowerFSMThread() : OSThread("PowerFSM") {}
|
|
|
|
|
|
|
|
protected:
|
2022-01-24 17:24:40 +00:00
|
|
|
int32_t runOnce() override
|
2020-10-11 00:12:53 +00:00
|
|
|
{
|
|
|
|
powerFSM.run_machine();
|
|
|
|
|
|
|
|
/// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake
|
|
|
|
/// cpu for serial rx - FIXME)
|
2020-10-12 01:27:07 +00:00
|
|
|
auto state = powerFSM.getState();
|
|
|
|
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
|
2020-04-17 16:48:54 +00:00
|
|
|
|
2021-12-06 02:37:35 +00:00
|
|
|
if (powerStatus->getHasUSB()) {
|
|
|
|
timeLastPowered = millis();
|
|
|
|
} else if (radioConfig.preferences.on_battery_shutdown_after_secs > 0 &&
|
|
|
|
millis() > timeLastPowered + (1000 * radioConfig.preferences.on_battery_shutdown_after_secs)) { //shutdown after 30 minutes unpowered
|
|
|
|
powerFSM.trigger(EVENT_SHUTDOWN);
|
|
|
|
}
|
|
|
|
|
2020-10-11 00:12:53 +00:00
|
|
|
return 10;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
/**
|
|
|
|
* Watch a GPIO and if we get an IRQ, wake the main thread.
|
|
|
|
* Use to add wake on button press
|
|
|
|
*/
|
|
|
|
void wakeOnIrq(int irq, int mode)
|
|
|
|
{
|
|
|
|
attachInterrupt(
|
|
|
|
irq,
|
|
|
|
[] {
|
|
|
|
BaseType_t higherWake = 0;
|
|
|
|
mainDelay.interruptFromISR(&higherWake);
|
|
|
|
},
|
|
|
|
FALLING);
|
2020-06-22 19:03:26 +00:00
|
|
|
}
|
2020-04-29 21:54:03 +00:00
|
|
|
|
2020-10-12 00:25:17 +00:00
|
|
|
class ButtonThread : public OSThread
|
|
|
|
{
|
2020-06-22 18:09:26 +00:00
|
|
|
// Prepare for button presses
|
|
|
|
#ifdef BUTTON_PIN
|
2020-10-12 00:25:17 +00:00
|
|
|
OneButton userButton;
|
2020-06-22 18:09:26 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BUTTON_PIN_ALT
|
2020-10-12 00:25:17 +00:00
|
|
|
OneButton userButtonAlt;
|
2022-01-07 06:57:29 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BUTTON_PIN_TOUCH
|
|
|
|
OneButton userButtonTouch;
|
2020-06-22 18:09:26 +00:00
|
|
|
#endif
|
2021-03-15 02:00:20 +00:00
|
|
|
static bool shutdown_on_long_stop;
|
2021-03-24 22:15:15 +00:00
|
|
|
|
2020-10-12 00:25:17 +00:00
|
|
|
public:
|
2020-11-23 02:50:14 +00:00
|
|
|
static uint32_t longPressTime;
|
|
|
|
|
2020-10-12 00:25:17 +00:00
|
|
|
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
|
|
|
|
ButtonThread() : OSThread("Button")
|
|
|
|
{
|
|
|
|
#ifdef BUTTON_PIN
|
|
|
|
userButton = OneButton(BUTTON_PIN, true, true);
|
2020-11-13 01:33:59 +00:00
|
|
|
#ifdef INPUT_PULLUP_SENSE
|
2020-11-19 01:25:02 +00:00
|
|
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
2020-11-13 01:33:59 +00:00
|
|
|
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE);
|
|
|
|
#endif
|
2020-10-12 00:25:17 +00:00
|
|
|
userButton.attachClick(userButtonPressed);
|
|
|
|
userButton.attachDuringLongPress(userButtonPressedLong);
|
2020-10-29 01:38:27 +00:00
|
|
|
userButton.attachDoubleClick(userButtonDoublePressed);
|
2022-01-08 19:54:02 +00:00
|
|
|
userButton.attachMultiClick(userButtonMultiPressed);
|
2020-11-23 02:50:14 +00:00
|
|
|
userButton.attachLongPressStart(userButtonPressedLongStart);
|
|
|
|
userButton.attachLongPressStop(userButtonPressedLongStop);
|
2020-10-12 00:25:17 +00:00
|
|
|
wakeOnIrq(BUTTON_PIN, FALLING);
|
|
|
|
#endif
|
|
|
|
#ifdef BUTTON_PIN_ALT
|
|
|
|
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
2020-11-13 01:33:59 +00:00
|
|
|
#ifdef INPUT_PULLUP_SENSE
|
2020-11-19 01:25:02 +00:00
|
|
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
2020-11-13 01:33:59 +00:00
|
|
|
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
|
2020-11-19 01:25:02 +00:00
|
|
|
#endif
|
2020-10-12 00:25:17 +00:00
|
|
|
userButtonAlt.attachClick(userButtonPressed);
|
2020-10-24 00:44:54 +00:00
|
|
|
userButtonAlt.attachDuringLongPress(userButtonPressedLong);
|
2020-10-29 01:38:27 +00:00
|
|
|
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
2020-11-23 02:50:14 +00:00
|
|
|
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
|
|
|
|
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
|
2020-10-12 00:25:17 +00:00
|
|
|
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
|
|
|
|
#endif
|
2022-01-07 06:57:29 +00:00
|
|
|
|
|
|
|
#ifdef BUTTON_PIN_TOUCH
|
|
|
|
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
|
|
|
#ifdef INPUT_PULLUP_SENSE
|
|
|
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
|
|
|
pinMode(BUTTON_PIN_TOUCH, INPUT_PULLUP_SENSE);
|
|
|
|
#endif
|
|
|
|
userButtonTouch.attachClick(touchPressed);
|
|
|
|
userButtonTouch.attachDuringLongPress(touchPressedLong);
|
|
|
|
userButtonTouch.attachDoubleClick(touchDoublePressed);
|
|
|
|
userButtonTouch.attachLongPressStart(touchPressedLongStart);
|
|
|
|
userButtonTouch.attachLongPressStop(touchPressedLongStop);
|
|
|
|
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
|
|
|
|
#endif
|
|
|
|
|
2020-10-12 00:25:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/// If the button is pressed we suppress CPU sleep until release
|
2022-01-24 17:24:40 +00:00
|
|
|
int32_t runOnce() override
|
2020-10-12 00:25:17 +00:00
|
|
|
{
|
|
|
|
canSleep = true; // Assume we should not keep the board awake
|
|
|
|
|
|
|
|
#ifdef BUTTON_PIN
|
|
|
|
userButton.tick();
|
|
|
|
canSleep &= userButton.isIdle();
|
|
|
|
#endif
|
|
|
|
#ifdef BUTTON_PIN_ALT
|
|
|
|
userButtonAlt.tick();
|
2020-10-24 00:44:54 +00:00
|
|
|
canSleep &= userButtonAlt.isIdle();
|
2022-01-07 06:57:29 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BUTTON_PIN_TOUCH
|
|
|
|
userButtonTouch.tick();
|
|
|
|
canSleep &= userButtonTouch.isIdle();
|
2020-10-12 00:25:17 +00:00
|
|
|
#endif
|
2020-10-24 00:44:54 +00:00
|
|
|
// if (!canSleep) DEBUG_MSG("Supressing sleep!\n");
|
2020-11-19 01:25:02 +00:00
|
|
|
// else DEBUG_MSG("sleep ok\n");
|
2020-10-12 00:25:17 +00:00
|
|
|
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2022-01-07 06:57:29 +00:00
|
|
|
static void touchPressed()
|
|
|
|
{
|
|
|
|
screen->forceDisplay();
|
|
|
|
DEBUG_MSG("touch press!\n");
|
|
|
|
}
|
|
|
|
static void touchDoublePressed()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("touch double press!\n");
|
|
|
|
}
|
|
|
|
static void touchPressedLong()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("touch press long!\n");
|
|
|
|
}
|
|
|
|
static void touchDoublePressedLong()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("touch double pressed!\n");
|
|
|
|
}
|
|
|
|
static void touchPressedLongStart()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("touch long press start!\n");
|
|
|
|
}
|
|
|
|
static void touchPressedLongStop()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("touch long press stop!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-12 00:25:17 +00:00
|
|
|
static void userButtonPressed()
|
|
|
|
{
|
|
|
|
// DEBUG_MSG("press!\n");
|
|
|
|
powerFSM.trigger(EVENT_PRESS);
|
|
|
|
}
|
2020-10-24 00:44:54 +00:00
|
|
|
static void userButtonPressedLong()
|
|
|
|
{
|
2020-11-23 02:50:14 +00:00
|
|
|
// DEBUG_MSG("Long press!\n");
|
2022-01-19 23:10:02 +00:00
|
|
|
#ifndef NRF52_SERIES
|
2020-10-24 00:44:54 +00:00
|
|
|
screen->adjustBrightness();
|
2022-01-19 23:10:02 +00:00
|
|
|
#endif
|
2021-03-15 02:00:20 +00:00
|
|
|
// If user button is held down for 5 seconds, shutdown the device.
|
|
|
|
if (millis() - longPressTime > 5 * 1000) {
|
2020-11-23 03:12:11 +00:00
|
|
|
#ifdef TBEAM_V10
|
2020-11-23 02:50:14 +00:00
|
|
|
if (axp192_found == true) {
|
2020-12-12 07:03:32 +00:00
|
|
|
setLed(false);
|
2020-11-23 02:50:14 +00:00
|
|
|
power->shutdown();
|
|
|
|
}
|
2021-03-15 02:00:20 +00:00
|
|
|
#elif NRF52_SERIES
|
2021-03-24 22:15:15 +00:00
|
|
|
// Do actual shutdown when button released, otherwise the button release
|
|
|
|
// may wake the board immediatedly.
|
|
|
|
if (!shutdown_on_long_stop) {
|
2022-01-19 23:10:02 +00:00
|
|
|
screen->startShutdownScreen();
|
2021-03-24 22:15:15 +00:00
|
|
|
DEBUG_MSG("Shutdown from long press");
|
|
|
|
playBeep();
|
|
|
|
ledOff(PIN_LED1);
|
|
|
|
ledOff(PIN_LED2);
|
|
|
|
shutdown_on_long_stop = true;
|
|
|
|
}
|
2020-11-23 02:50:14 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
2020-12-12 21:54:14 +00:00
|
|
|
// DEBUG_MSG("Long press %u\n", (millis() - longPressTime));
|
2020-11-23 02:50:14 +00:00
|
|
|
}
|
2020-10-24 00:44:54 +00:00
|
|
|
}
|
2020-11-19 01:25:02 +00:00
|
|
|
|
2020-10-29 01:38:27 +00:00
|
|
|
static void userButtonDoublePressed()
|
2020-11-19 01:25:02 +00:00
|
|
|
{
|
2020-10-03 21:23:36 +00:00
|
|
|
#ifndef NO_ESP32
|
2020-11-19 01:25:02 +00:00
|
|
|
disablePin();
|
2021-12-18 20:47:54 +00:00
|
|
|
#elif defined(HAS_EINK)
|
|
|
|
digitalWrite(PIN_EINK_EN,digitalRead(PIN_EINK_EN) == LOW);
|
2020-10-03 21:23:36 +00:00
|
|
|
#endif
|
2020-11-19 01:25:02 +00:00
|
|
|
}
|
2020-11-28 00:55:56 +00:00
|
|
|
|
2022-01-08 19:54:02 +00:00
|
|
|
static void userButtonMultiPressed()
|
|
|
|
{
|
|
|
|
#ifndef NO_ESP32
|
|
|
|
clearNVS();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-28 00:55:56 +00:00
|
|
|
static void userButtonPressedLongStart()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("Long press start!\n");
|
|
|
|
longPressTime = millis();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void userButtonPressedLongStop()
|
|
|
|
{
|
|
|
|
DEBUG_MSG("Long press stop!\n");
|
|
|
|
longPressTime = 0;
|
2021-03-15 02:00:20 +00:00
|
|
|
if (shutdown_on_long_stop) {
|
|
|
|
playShutdownMelody();
|
2022-01-19 23:10:02 +00:00
|
|
|
delay(3000);
|
2021-03-15 02:00:20 +00:00
|
|
|
power->shutdown();
|
|
|
|
}
|
2020-11-28 00:55:56 +00:00
|
|
|
}
|
2020-10-12 00:25:17 +00:00
|
|
|
};
|
|
|
|
|
2021-03-15 02:00:20 +00:00
|
|
|
bool ButtonThread::shutdown_on_long_stop = false;
|
|
|
|
|
2020-10-12 00:25:17 +00:00
|
|
|
static Periodic *ledPeriodic;
|
|
|
|
static OSThread *powerFSMthread, *buttonThread;
|
2020-11-23 02:50:14 +00:00
|
|
|
uint32_t ButtonThread::longPressTime = 0;
|
2020-10-12 00:25:17 +00:00
|
|
|
|
2020-10-07 22:23:05 +00:00
|
|
|
RadioInterface *rIf = NULL;
|
2020-04-29 21:54:03 +00:00
|
|
|
|
2021-04-28 07:11:55 +00:00
|
|
|
/**
|
|
|
|
* Some platforms (nrf52) might provide an alterate version that supresses calling delay from sleep.
|
|
|
|
*/
|
|
|
|
__attribute__ ((weak, noinline)) bool loopCanSleep() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-02-02 00:14:34 +00:00
|
|
|
void setup()
|
|
|
|
{
|
2021-01-08 05:15:49 +00:00
|
|
|
concurrency::hasBeenSetup = true;
|
|
|
|
|
2020-11-12 23:48:25 +00:00
|
|
|
#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;
|
2021-03-08 09:10:48 +00:00
|
|
|
#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);
|
2020-04-24 15:06:29 +00:00
|
|
|
#endif
|
2020-04-24 15:52:49 +00:00
|
|
|
|
2020-02-02 00:14:34 +00:00
|
|
|
#ifdef DEBUG_PORT
|
2021-03-31 03:26:00 +00:00
|
|
|
if (!radioConfig.preferences.serial_disabled) {
|
2021-03-30 00:08:56 +00:00
|
|
|
consoleInit(); // Set serial baud rate and init our mesh console
|
|
|
|
}
|
2020-02-02 00:14:34 +00:00
|
|
|
#endif
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2022-01-11 23:56:58 +00:00
|
|
|
DEBUG_MSG("\n\n//\\ E S H T /\\ S T / C\n\n");
|
2022-01-10 15:57:25 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
initDeepSleep();
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2020-02-01 22:23:21 +00:00
|
|
|
#ifdef VEXT_ENABLE
|
2020-03-19 02:15:51 +00:00
|
|
|
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
|
2020-03-19 02:15:51 +00:00
|
|
|
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
|
|
|
|
2021-08-17 23:58:21 +00:00
|
|
|
bool forceSoftAP = 0;
|
2021-08-18 02:59:56 +00:00
|
|
|
|
2021-01-18 18:43:15 +00:00
|
|
|
#ifdef BUTTON_PIN
|
|
|
|
#ifndef NO_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.
|
2020-12-12 21:54:14 +00:00
|
|
|
pinMode(BUTTON_PIN, INPUT);
|
2021-02-20 08:34:25 +00:00
|
|
|
|
2021-01-18 18:43:15 +00:00
|
|
|
#ifdef BUTTON_NEED_PULLUP
|
|
|
|
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
2021-02-20 08:34:25 +00:00
|
|
|
delay(10);
|
2021-01-18 18:43:15 +00:00
|
|
|
#endif
|
2020-12-12 21:54:14 +00:00
|
|
|
|
|
|
|
// BUTTON_PIN is pulled high by a 12k resistor.
|
|
|
|
if (!digitalRead(BUTTON_PIN)) {
|
|
|
|
forceSoftAP = 1;
|
2021-01-18 18:43:15 +00:00
|
|
|
DEBUG_MSG("Setting forceSoftAP = 1\n");
|
2020-12-12 21:54:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
OSThread::setup();
|
|
|
|
|
|
|
|
ledPeriodic = new Periodic("Blink", ledBlinker);
|
|
|
|
|
2020-11-19 01:25:02 +00:00
|
|
|
fsInit();
|
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
router = new DSRRouter();
|
2020-10-10 00:28:00 +00:00
|
|
|
|
2020-02-04 15:31:32 +00:00
|
|
|
#ifdef I2C_SDA
|
2020-03-19 02:15:51 +00:00
|
|
|
Wire.begin(I2C_SDA, I2C_SCL);
|
2021-03-20 01:46:11 +00:00
|
|
|
#elif !defined(NO_WIRE)
|
2020-04-23 20:53:51 +00:00
|
|
|
Wire.begin();
|
2020-02-04 15:31:32 +00:00
|
|
|
#endif
|
2020-10-17 05:15:12 +00:00
|
|
|
|
|
|
|
#ifdef PIN_LCD_RESET
|
2020-10-23 10:00:43 +00:00
|
|
|
// FIXME - move this someplace better, LCD is at address 0x3F
|
2020-10-17 05:15:12 +00:00
|
|
|
pinMode(PIN_LCD_RESET, OUTPUT);
|
|
|
|
digitalWrite(PIN_LCD_RESET, 0);
|
2020-10-24 00:16:15 +00:00
|
|
|
delay(1);
|
2020-10-23 09:10:48 +00:00
|
|
|
digitalWrite(PIN_LCD_RESET, 1);
|
2020-10-24 00:16:15 +00:00
|
|
|
delay(1);
|
2020-06-15 21:43:16 +00:00
|
|
|
#endif
|
2020-04-23 20:53:51 +00:00
|
|
|
|
2020-10-17 05:15:12 +00:00
|
|
|
scanI2Cdevice();
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// Buttons & LED
|
2020-10-12 00:25:17 +00:00
|
|
|
buttonThread = new ButtonThread();
|
2020-10-29 01:38:27 +00:00
|
|
|
|
2020-02-01 16:30:53 +00:00
|
|
|
#ifdef LED_PIN
|
2020-03-19 02:15:51 +00:00
|
|
|
pinMode(LED_PIN, OUTPUT);
|
2020-04-15 03:22:27 +00:00
|
|
|
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
|
2020-02-01 16:30:53 +00:00
|
|
|
#endif
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// Hello
|
2021-03-14 02:37:32 +00:00
|
|
|
DEBUG_MSG("Meshtastic hwvendor=%d, swver=%s, hwver=%s\n", HW_VENDOR, optstr(APP_VERSION), optstr(HW_VERSION));
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2020-04-15 03:22:27 +00:00
|
|
|
#ifndef NO_ESP32
|
2020-03-19 02:15:51 +00:00
|
|
|
// 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
|
2020-04-24 15:52:49 +00:00
|
|
|
|
|
|
|
esp32Setup();
|
2020-04-17 16:48:54 +00:00
|
|
|
#endif
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2020-09-24 23:36:07 +00:00
|
|
|
#ifdef NRF52_SERIES
|
|
|
|
nrf52Setup();
|
|
|
|
#endif
|
2021-03-15 02:00:20 +00:00
|
|
|
playStartMelody();
|
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();
|
|
|
|
|
2020-07-01 17:08:38 +00:00
|
|
|
// Currently only the tbeam has a PMU
|
2020-06-28 04:19:49 +00:00
|
|
|
power = new Power();
|
2020-06-29 01:17:52 +00:00
|
|
|
power->setStatusHandler(powerStatus);
|
|
|
|
powerStatus->observe(&power->newStatus);
|
2020-09-21 19:41:39 +00:00
|
|
|
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2020-08-29 00:38:23 +00:00
|
|
|
// Init our SPI controller (must be before screen and lora)
|
|
|
|
initSPI();
|
2020-09-05 00:23:17 +00:00
|
|
|
#ifdef NO_ESP32
|
2020-08-29 00:38:23 +00:00
|
|
|
SPI.begin();
|
|
|
|
#else
|
|
|
|
// ESP32
|
|
|
|
SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
|
|
|
|
SPI.setFrequency(4000000);
|
|
|
|
#endif
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// 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-02-01 16:30:53 +00:00
|
|
|
|
2020-05-04 18:15:05 +00:00
|
|
|
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
|
|
|
|
2020-12-29 15:08:11 +00:00
|
|
|
#ifdef GENIEBLOCKS
|
2021-04-12 05:25:55 +00:00
|
|
|
Im intentionally breaking your build so you see this note.Feel free to revert if not correct.I think you can
|
|
|
|
remove this GPS_RESET_N code by instead defining PIN_GPS_RESET and
|
|
|
|
use the shared code in GPS.cpp instead.- geeksville
|
2021-04-11 07:17:56 +00:00
|
|
|
|
2021-04-12 05:25:55 +00:00
|
|
|
// gps setup
|
|
|
|
pinMode(GPS_RESET_N, OUTPUT);
|
2020-12-29 15:08:11 +00:00
|
|
|
pinMode(GPS_EXTINT, OUTPUT);
|
|
|
|
digitalWrite(GPS_RESET_N, HIGH);
|
|
|
|
digitalWrite(GPS_EXTINT, LOW);
|
2021-01-08 05:15:49 +00:00
|
|
|
// battery setup
|
2020-12-29 15:08:11 +00:00
|
|
|
// If we want to read battery level, we need to set BATTERY_EN_PIN pin to low.
|
|
|
|
// ToDo: For low power consumption after read battery level, set that pin to high.
|
2021-01-08 05:15:49 +00:00
|
|
|
pinMode(BATTERY_EN_PIN, OUTPUT);
|
2020-12-29 15:08:11 +00:00
|
|
|
digitalWrite(BATTERY_EN_PIN, LOW);
|
|
|
|
#endif
|
2021-03-15 02:00:20 +00:00
|
|
|
gps = createGps();
|
2020-10-13 06:43:28 +00:00
|
|
|
|
2020-09-06 21:45:43 +00:00
|
|
|
if (gps)
|
|
|
|
gpsStatus->observe(&gps->newStatus);
|
|
|
|
else
|
|
|
|
DEBUG_MSG("Warning: 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);
|
2020-03-18 22:00:17 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
service.init();
|
2020-06-21 21:11:38 +00:00
|
|
|
|
2021-01-08 05:15:49 +00:00
|
|
|
// Now that the mesh service is created, create any plugins
|
|
|
|
setupPlugins();
|
|
|
|
|
2020-12-26 05:36:21 +00:00
|
|
|
// Do this after service.init (because that clears error_code)
|
|
|
|
#ifdef AXP192_SLAVE_ADDRESS
|
2021-01-08 05:15:49 +00:00
|
|
|
if (!axp192_found)
|
2021-04-29 01:52:15 +00:00
|
|
|
RECORD_CRITICALERROR(CriticalErrorCode_NoAXP192); // Record a hardware fault for missing hardware
|
2021-01-08 05:15:49 +00:00
|
|
|
#endif
|
2020-12-26 05:36:21 +00:00
|
|
|
|
2021-01-08 05:15:49 +00:00
|
|
|
// Don't call screen setup until after nodedb is setup (because we need
|
|
|
|
// the current region name)
|
2020-10-21 09:27:13 +00:00
|
|
|
#if defined(ST7735_CS) || defined(HAS_EINK)
|
|
|
|
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
|
|
|
|
2020-08-21 17:14:03 +00:00
|
|
|
// We have now loaded our saved preferences from flash
|
|
|
|
|
|
|
|
// ONCE we will factory reset the GPS for bug #327
|
2021-03-15 02:00:20 +00:00
|
|
|
if (gps && !devicestate.did_gps_reset) {
|
|
|
|
if (gps->factoryReset()) { // If we don't succeed try again next time
|
2020-08-21 17:14:03 +00:00
|
|
|
devicestate.did_gps_reset = true;
|
|
|
|
nodeDB.saveToDisk();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 09:25:25 +00:00
|
|
|
#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
|
|
|
|
|
2020-10-07 22:23:05 +00:00
|
|
|
// radio init MUST BE AFTER service.init, so we have our radio config settings (from nodedb init)
|
2020-08-20 22:42:36 +00:00
|
|
|
|
2020-07-10 21:37:01 +00:00
|
|
|
#if defined(RF95_IRQ)
|
2020-08-20 22:42:36 +00:00
|
|
|
if (!rIf) {
|
|
|
|
rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI);
|
|
|
|
if (!rIf->init()) {
|
|
|
|
DEBUG_MSG("Warning: Failed to find RF95 radio\n");
|
|
|
|
delete rIf;
|
|
|
|
rIf = NULL;
|
2021-02-07 02:26:11 +00:00
|
|
|
} else {
|
2021-04-21 10:00:34 +00:00
|
|
|
DEBUG_MSG("RF95 Radio init succeeded, using RF95 radio\n");
|
2020-08-20 22:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-09-12 10:58:56 +00:00
|
|
|
#if defined(USE_SX1262)
|
2020-08-20 22:42:36 +00:00
|
|
|
if (!rIf) {
|
2021-09-11 21:35:16 +00:00
|
|
|
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
2020-08-20 22:42:36 +00:00
|
|
|
if (!rIf->init()) {
|
|
|
|
DEBUG_MSG("Warning: Failed to find SX1262 radio\n");
|
|
|
|
delete rIf;
|
|
|
|
rIf = NULL;
|
2021-02-07 02:26:11 +00:00
|
|
|
} else {
|
2021-04-21 10:00:34 +00:00
|
|
|
DEBUG_MSG("SX1262 Radio init succeeded, using SX1262 radio\n");
|
2020-08-20 22:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-09-12 10:58:56 +00:00
|
|
|
#if defined(USE_SX1268)
|
2021-09-03 14:15:58 +00:00
|
|
|
if (!rIf) {
|
2021-09-12 10:58:56 +00:00
|
|
|
rIf = new SX1268Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
2021-09-03 14:15:58 +00:00
|
|
|
if (!rIf->init()) {
|
|
|
|
DEBUG_MSG("Warning: Failed to find SX1268 radio\n");
|
|
|
|
delete rIf;
|
|
|
|
rIf = NULL;
|
|
|
|
} else {
|
|
|
|
DEBUG_MSG("SX1268 Radio init succeeded, using SX1268 radio\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-11-17 10:28:08 +00:00
|
|
|
#if defined(USE_LLCC68)
|
|
|
|
if (!rIf) {
|
|
|
|
rIf = new LLCC68Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
|
|
|
if (!rIf->init()) {
|
|
|
|
DEBUG_MSG("Warning: Failed to find LLCC68 radio\n");
|
|
|
|
delete rIf;
|
|
|
|
rIf = NULL;
|
|
|
|
} else {
|
|
|
|
DEBUG_MSG("LLCC68 Radio init succeeded, using LLCC68 radio\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-08-20 22:42:36 +00:00
|
|
|
#ifdef USE_SIM_RADIO
|
|
|
|
if (!rIf) {
|
|
|
|
rIf = new SimRadio;
|
|
|
|
if (!rIf->init()) {
|
|
|
|
DEBUG_MSG("Warning: Failed to find simulated radio\n");
|
|
|
|
delete rIf;
|
|
|
|
rIf = NULL;
|
2021-02-07 02:26:11 +00:00
|
|
|
} else {
|
|
|
|
DEBUG_MSG("Using SIMULATED radio!\n");
|
2020-08-20 22:42:36 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-29 21:54:03 +00:00
|
|
|
#endif
|
2020-04-14 18:40:49 +00:00
|
|
|
|
2021-08-18 02:59:56 +00:00
|
|
|
#if defined(PORTDUINO) || defined(HAS_WIFI)
|
|
|
|
mqttInit();
|
|
|
|
#endif
|
|
|
|
|
2020-09-13 04:43:41 +00:00
|
|
|
// Initialize Wifi
|
2020-12-13 02:33:52 +00:00
|
|
|
initWifi(forceSoftAP);
|
2020-09-13 04:43:41 +00:00
|
|
|
|
2021-08-17 23:58:21 +00:00
|
|
|
#ifndef NO_ESP32
|
2021-01-09 04:06:11 +00:00
|
|
|
// Start web server thread.
|
2021-01-09 04:43:51 +00:00
|
|
|
webServerThread = new WebServerThread();
|
2021-01-09 06:59:37 +00:00
|
|
|
#endif
|
2021-01-09 04:06:11 +00:00
|
|
|
|
2021-02-07 01:17:46 +00:00
|
|
|
#ifdef PORTDUINO
|
|
|
|
initApiServer();
|
|
|
|
#endif
|
|
|
|
|
2021-01-09 04:43:51 +00:00
|
|
|
// Start airtime logger thread.
|
|
|
|
airTime = new AirTime();
|
2021-01-09 04:06:11 +00:00
|
|
|
|
2020-08-20 22:42:36 +00:00
|
|
|
if (!rIf)
|
2021-04-29 01:52:15 +00:00
|
|
|
RECORD_CRITICALERROR(CriticalErrorCode_NoRadio);
|
2022-01-28 20:02:02 +00:00
|
|
|
else{
|
2020-10-10 01:57:57 +00:00
|
|
|
router->addInterface(rIf);
|
2020-04-14 18:40:49 +00:00
|
|
|
|
2022-01-28 20:02:02 +00:00
|
|
|
// Calculate and save the bit rate to myNodeInfo
|
|
|
|
// TODO: This needs to be added what ever method changes the channel from the phone.
|
|
|
|
myNodeInfo.bitrate = (float(Constants_DATA_PAYLOAD_LEN) /
|
|
|
|
(float(rIf->getPacketTime(Constants_DATA_PAYLOAD_LEN)))
|
|
|
|
) * 1000;
|
|
|
|
DEBUG_MSG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
|
|
|
|
}
|
2021-12-24 02:18:07 +00:00
|
|
|
|
2020-03-19 02:15:51 +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
|
2020-10-11 00:12:53 +00:00
|
|
|
powerFSMthread = new PowerFSMThread();
|
2020-03-18 22:00:17 +00:00
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// setBluetoothEnable(false); we now don't start bluetooth until we enter the proper state
|
|
|
|
setCPUFast(false); // 80MHz is fine for our slow peripherals
|
2020-02-01 16:30:53 +00:00
|
|
|
}
|
|
|
|
|
2020-02-17 00:03:16 +00:00
|
|
|
#if 0
|
|
|
|
// Turn off for now
|
2020-02-15 19:15:43 +00:00
|
|
|
|
2020-03-26 16:24:53 +00:00
|
|
|
uint32_t axpDebugRead()
|
2020-02-17 00:03:16 +00:00
|
|
|
{
|
|
|
|
axp.debugCharging();
|
|
|
|
DEBUG_MSG("vbus current %f\n", axp.getVbusCurrent());
|
|
|
|
DEBUG_MSG("charge current %f\n", axp.getBattChargeCurrent());
|
|
|
|
DEBUG_MSG("bat voltage %f\n", axp.getBattVoltage());
|
|
|
|
DEBUG_MSG("batt pct %d\n", axp.getBattPercentage());
|
2020-03-26 16:24:53 +00:00
|
|
|
DEBUG_MSG("is battery connected %d\n", axp.isBatteryConnect());
|
|
|
|
DEBUG_MSG("is USB connected %d\n", axp.isVBUSPlug());
|
|
|
|
DEBUG_MSG("is charging %d\n", axp.isChargeing());
|
2020-02-17 00:03:16 +00:00
|
|
|
|
|
|
|
return 30 * 1000;
|
2020-02-15 19:15:43 +00:00
|
|
|
}
|
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
Periodic axpDebugOutput(axpDebugRead);
|
2020-04-25 17:59:40 +00:00
|
|
|
axpDebugOutput.setup();
|
2020-02-21 12:57:08 +00:00
|
|
|
#endif
|
2020-02-15 19:15:43 +00:00
|
|
|
|
2021-03-27 02:19:59 +00:00
|
|
|
uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes)
|
2022-01-21 21:03:26 +00:00
|
|
|
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
|
|
|
|
2022-01-21 21:03:26 +00:00
|
|
|
void powerCommandsCheck()
|
2021-03-27 02:19:59 +00:00
|
|
|
{
|
|
|
|
if (rebootAtMsec && millis() > rebootAtMsec) {
|
|
|
|
#ifndef NO_ESP32
|
|
|
|
DEBUG_MSG("Rebooting for update\n");
|
|
|
|
ESP.restart();
|
|
|
|
#else
|
|
|
|
DEBUG_MSG("FIXME implement reboot for this platform");
|
|
|
|
#endif
|
|
|
|
}
|
2022-01-21 21:03:26 +00:00
|
|
|
|
|
|
|
#if NRF52_SERIES
|
|
|
|
if (shutdownAtMsec) {
|
|
|
|
screen->startShutdownScreen();
|
|
|
|
playBeep();
|
|
|
|
ledOff(PIN_LED1);
|
|
|
|
ledOff(PIN_LED2);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (shutdownAtMsec && millis() > shutdownAtMsec) {
|
|
|
|
DEBUG_MSG("Shutting down from admin command\n");
|
|
|
|
#ifdef TBEAM_V10
|
|
|
|
if (axp192_found == true) {
|
|
|
|
setLed(false);
|
|
|
|
power->shutdown();
|
|
|
|
}
|
|
|
|
#elif NRF52_SERIES
|
|
|
|
playShutdownMelody();
|
|
|
|
power->shutdown();
|
|
|
|
#else
|
|
|
|
DEBUG_MSG("FIXME implement shutdown for this platform");
|
|
|
|
#endif
|
|
|
|
}
|
2021-03-27 02:19:59 +00:00
|
|
|
}
|
|
|
|
|
2021-03-28 04:16:37 +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()
|
|
|
|
{
|
2021-03-28 04:16:37 +00:00
|
|
|
runASAP = false;
|
|
|
|
|
2020-03-19 02:15:51 +00:00
|
|
|
// axpDebugOutput.loop();
|
2020-04-10 19:18:48 +00:00
|
|
|
|
2020-06-13 15:28:01 +00:00
|
|
|
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
|
|
|
|
|
2020-04-10 19:18:48 +00:00
|
|
|
#ifndef NO_ESP32
|
2020-04-24 15:52:49 +00:00
|
|
|
esp32Loop();
|
2020-04-10 19:18:48 +00:00
|
|
|
#endif
|
2021-03-09 07:07:16 +00:00
|
|
|
#ifdef NRF52_SERIES
|
|
|
|
nrf52Loop();
|
|
|
|
#endif
|
2022-01-21 21:03:26 +00:00
|
|
|
powerCommandsCheck();
|
2020-02-01 16:30:53 +00:00
|
|
|
|
2020-10-07 22:23:05 +00:00
|
|
|
// For debugging
|
|
|
|
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
|
2020-03-15 23:47:38 +00:00
|
|
|
|
2020-06-12 23:37:03 +00:00
|
|
|
#ifdef DEBUG_STACK
|
|
|
|
static uint32_t lastPrint = 0;
|
2020-09-05 19:34:48 +00:00
|
|
|
if (millis() - lastPrint > 10 * 1000L) {
|
|
|
|
lastPrint = millis();
|
2020-06-12 23:37:03 +00:00
|
|
|
meshtastic::printThreadInfo("main");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
// TODO: This should go into a thread handled by FreeRTOS.
|
2021-01-09 06:25:44 +00:00
|
|
|
// handleWebResponse();
|
2020-09-16 16:22:03 +00:00
|
|
|
|
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
|
|
|
|
2020-10-11 00:12:53 +00:00
|
|
|
/* if (mainController.nextThread && delayMsec)
|
|
|
|
DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
|
2020-10-12 00:25:17 +00:00
|
|
|
mainController.nextThread->tillRun(millis())); */
|
2020-09-14 05:22:49 +00:00
|
|
|
|
2020-10-10 01:57:57 +00:00
|
|
|
// We want to sleep as long as possible here - because it saves power
|
2021-08-15 17:34:57 +00:00
|
|
|
if (!runASAP && loopCanSleep()) {
|
|
|
|
// if(delayMsec > 100) DEBUG_MSG("sleeping %ld\n", delayMsec);
|
2021-03-28 04:16:37 +00:00
|
|
|
mainDelay.delay(delayMsec);
|
2021-08-15 17:34:57 +00:00
|
|
|
}
|
2020-10-12 00:25:17 +00:00
|
|
|
// if (didWake) DEBUG_MSG("wake!\n");
|
2020-03-15 20:27:00 +00:00
|
|
|
}
|