mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-07 10:27:43 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ef2cc8623 | ||
|
|
b41a32c6b6 | ||
|
|
1ebd7b0c3e | ||
|
|
5457541244 | ||
|
|
ef325289eb | ||
|
|
40c63c0615 | ||
|
|
a9de8b9bb3 | ||
|
|
66a7f896c8 | ||
|
|
45a36f5571 | ||
|
|
62493efc40 | ||
|
|
2848b76cc9 | ||
|
|
ef8bea478d | ||
|
|
a8e4bbbe65 | ||
|
|
9a414d9c77 |
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
export VERSION=1.1.3
|
export VERSION=1.1.5
|
||||||
@@ -42,7 +42,6 @@ Expected sequence for initial download:
|
|||||||
- Read a RadioConfig from "radio" - used to get the channel and radio settings
|
- Read a RadioConfig from "radio" - used to get the channel and radio settings
|
||||||
- Read a User from "user" - to get the username for this node
|
- Read a User from "user" - to get the username for this node
|
||||||
- Read a MyNodeInfo from "mynode" to get information about this local device
|
- Read a MyNodeInfo from "mynode" to get information about this local device
|
||||||
- Write an empty record to "nodeinfo" to restart the nodeinfo reading state machine
|
|
||||||
- Read a series of NodeInfo packets to build the phone's copy of the current NodeDB for the mesh
|
- Read a series of NodeInfo packets to build the phone's copy of the current NodeDB for the mesh
|
||||||
- Read a endConfig packet that indicates that the entire state you need has been sent.
|
- Read a endConfig packet that indicates that the entire state you need has been sent.
|
||||||
- Read a series of MeshPackets until it returns empty to get any messages that arrived for this node while the phone was away
|
- Read a series of MeshPackets until it returns empty to get any messages that arrived for this node while the phone was away
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ debug_tool = jlink
|
|||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||||
1260 ; OneButton library for non-blocking button debounce
|
https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce
|
||||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||||
https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39
|
https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39
|
||||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
||||||
|
|||||||
@@ -138,38 +138,39 @@ int32_t Power::runOnce()
|
|||||||
{
|
{
|
||||||
readPowerStatus();
|
readPowerStatus();
|
||||||
|
|
||||||
#ifdef PMU_IRQ
|
#ifdef TBEAM_V10
|
||||||
if (pmu_irq) {
|
// WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll
|
||||||
pmu_irq = false;
|
// the IRQ status by reading the registers over I2C
|
||||||
axp.readIRQ();
|
axp.readIRQ();
|
||||||
|
|
||||||
DEBUG_MSG("pmu irq!\n");
|
if (axp.isVbusRemoveIRQ()) {
|
||||||
|
DEBUG_MSG("USB unplugged\n");
|
||||||
if (axp.isChargingIRQ()) {
|
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||||
DEBUG_MSG("Battery start charging\n");
|
|
||||||
}
|
|
||||||
if (axp.isChargingDoneIRQ()) {
|
|
||||||
DEBUG_MSG("Battery fully charged\n");
|
|
||||||
}
|
|
||||||
if (axp.isVbusRemoveIRQ()) {
|
|
||||||
DEBUG_MSG("USB unplugged\n");
|
|
||||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
|
||||||
}
|
|
||||||
if (axp.isVbusPlugInIRQ()) {
|
|
||||||
DEBUG_MSG("USB plugged In\n");
|
|
||||||
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
|
||||||
}
|
|
||||||
if (axp.isBattPlugInIRQ()) {
|
|
||||||
DEBUG_MSG("Battery inserted\n");
|
|
||||||
}
|
|
||||||
if (axp.isBattRemoveIRQ()) {
|
|
||||||
DEBUG_MSG("Battery removed\n");
|
|
||||||
}
|
|
||||||
if (axp.isPEKShortPressIRQ()) {
|
|
||||||
DEBUG_MSG("PEK short button press\n");
|
|
||||||
}
|
|
||||||
axp.clearIRQ();
|
|
||||||
}
|
}
|
||||||
|
if (axp.isVbusPlugInIRQ()) {
|
||||||
|
DEBUG_MSG("USB plugged In\n");
|
||||||
|
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Other things we could check if we cared...
|
||||||
|
|
||||||
|
if (axp.isChargingIRQ()) {
|
||||||
|
DEBUG_MSG("Battery start charging\n");
|
||||||
|
}
|
||||||
|
if (axp.isChargingDoneIRQ()) {
|
||||||
|
DEBUG_MSG("Battery fully charged\n");
|
||||||
|
}
|
||||||
|
if (axp.isBattPlugInIRQ()) {
|
||||||
|
DEBUG_MSG("Battery inserted\n");
|
||||||
|
}
|
||||||
|
if (axp.isBattRemoveIRQ()) {
|
||||||
|
DEBUG_MSG("Battery removed\n");
|
||||||
|
}
|
||||||
|
if (axp.isPEKShortPressIRQ()) {
|
||||||
|
DEBUG_MSG("PEK short button press\n");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
axp.clearIRQ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Only read once every 20 seconds once the power status for the app has been initialized
|
// Only read once every 20 seconds once the power status for the app has been initialized
|
||||||
|
|||||||
@@ -118,12 +118,21 @@ static void serialEnter()
|
|||||||
{
|
{
|
||||||
setBluetoothEnable(false);
|
setBluetoothEnable(false);
|
||||||
screen->setOn(true);
|
screen->setOn(true);
|
||||||
|
screen->print("Using API...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void powerEnter()
|
static void powerEnter()
|
||||||
{
|
{
|
||||||
screen->setOn(true);
|
screen->setOn(true);
|
||||||
setBluetoothEnable(true);
|
setBluetoothEnable(true);
|
||||||
|
screen->print("Powered...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void powerExit()
|
||||||
|
{
|
||||||
|
screen->setOn(true);
|
||||||
|
setBluetoothEnable(true);
|
||||||
|
screen->print("Unpowered...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onEnter()
|
static void onEnter()
|
||||||
@@ -156,7 +165,7 @@ State stateDARK(darkEnter, NULL, NULL, "DARK");
|
|||||||
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
|
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
|
||||||
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
|
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
|
||||||
State stateON(onEnter, NULL, NULL, "ON");
|
State stateON(onEnter, NULL, NULL, "ON");
|
||||||
State statePOWER(powerEnter, NULL, NULL, "POWER");
|
State statePOWER(powerEnter, NULL, powerExit, "POWER");
|
||||||
Fsm powerFSM(&stateBOOT);
|
Fsm powerFSM(&stateBOOT);
|
||||||
|
|
||||||
void PowerFSM_setup()
|
void PowerFSM_setup()
|
||||||
|
|||||||
@@ -20,6 +20,6 @@
|
|||||||
#define EVENT_POWER_DISCONNECTED 14
|
#define EVENT_POWER_DISCONNECTED 14
|
||||||
|
|
||||||
extern Fsm powerFSM;
|
extern Fsm powerFSM;
|
||||||
extern State statePOWER;
|
extern State statePOWER, stateSERIAL;
|
||||||
|
|
||||||
void PowerFSM_setup();
|
void PowerFSM_setup();
|
||||||
|
|||||||
@@ -4,30 +4,22 @@
|
|||||||
namespace concurrency
|
namespace concurrency
|
||||||
{
|
{
|
||||||
|
|
||||||
InterruptableDelay::InterruptableDelay()
|
InterruptableDelay::InterruptableDelay() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
InterruptableDelay::~InterruptableDelay()
|
InterruptableDelay::~InterruptableDelay() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns false if we were interrupted
|
* Returns false if we were interrupted
|
||||||
*/
|
*/
|
||||||
bool InterruptableDelay::delay(uint32_t msec)
|
bool InterruptableDelay::delay(uint32_t msec)
|
||||||
{
|
{
|
||||||
if (msec) {
|
// DEBUG_MSG("delay %u ", msec);
|
||||||
// DEBUG_MSG("delay %u ", msec);
|
|
||||||
|
|
||||||
// sem take will return false if we timed out (i.e. were not interrupted)
|
// sem take will return false if we timed out (i.e. were not interrupted)
|
||||||
bool r = semaphore.take(msec);
|
bool r = semaphore.take(msec);
|
||||||
|
|
||||||
// DEBUG_MSG("interrupt=%d\n", r);
|
// DEBUG_MSG("interrupt=%d\n", r);
|
||||||
return !r;
|
return !r;
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterruptableDelay::interrupt()
|
void InterruptableDelay::interrupt()
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ class Screen : public concurrency::OSThread
|
|||||||
return true; // claim success if our display is not in use
|
return true; // claim success if our display is not in use
|
||||||
else {
|
else {
|
||||||
bool success = cmdQueue.enqueue(cmd, 0);
|
bool success = cmdQueue.enqueue(cmd, 0);
|
||||||
setInterval(0); // handle ASAP
|
enabled = true; // handle ASAP (we are the registered reader for cmdQueue, but might have been disabled)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/main.cpp
109
src/main.cpp
@@ -128,31 +128,13 @@ class PowerFSMThread : public OSThread
|
|||||||
|
|
||||||
/// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake
|
/// 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)
|
/// cpu for serial rx - FIXME)
|
||||||
canSleep = (powerFSM.getState() != &statePOWER);
|
auto state = powerFSM.getState();
|
||||||
|
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
|
||||||
|
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Periodic *ledPeriodic;
|
|
||||||
static OSThread *powerFSMthread;
|
|
||||||
|
|
||||||
// Prepare for button presses
|
|
||||||
#ifdef BUTTON_PIN
|
|
||||||
OneButton userButton;
|
|
||||||
#endif
|
|
||||||
#ifdef BUTTON_PIN_ALT
|
|
||||||
OneButton userButtonAlt;
|
|
||||||
#endif
|
|
||||||
void userButtonPressed()
|
|
||||||
{
|
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
|
||||||
}
|
|
||||||
void userButtonPressedLong()
|
|
||||||
{
|
|
||||||
screen->adjustBrightness();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watch a GPIO and if we get an IRQ, wake the main thread.
|
* Watch a GPIO and if we get an IRQ, wake the main thread.
|
||||||
* Use to add wake on button press
|
* Use to add wake on button press
|
||||||
@@ -168,6 +150,65 @@ void wakeOnIrq(int irq, int mode)
|
|||||||
FALLING);
|
FALLING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ButtonThread : public OSThread
|
||||||
|
{
|
||||||
|
// Prepare for button presses
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
|
OneButton userButton;
|
||||||
|
#endif
|
||||||
|
#ifdef BUTTON_PIN_ALT
|
||||||
|
OneButton userButtonAlt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 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);
|
||||||
|
userButton.attachClick(userButtonPressed);
|
||||||
|
userButton.attachDuringLongPress(userButtonPressedLong);
|
||||||
|
wakeOnIrq(BUTTON_PIN, FALLING);
|
||||||
|
#endif
|
||||||
|
#ifdef BUTTON_PIN_ALT
|
||||||
|
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
||||||
|
userButtonAlt.attachClick(userButtonPressed);
|
||||||
|
userButton.attachDuringLongPress(userButtonPressedLong);
|
||||||
|
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// If the button is pressed we suppress CPU sleep until release
|
||||||
|
int32_t runOnce()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
canSleep &= userButton.isIdle();
|
||||||
|
#endif
|
||||||
|
// if(!canSleep) DEBUG_MSG("Supressing sleep!\n");
|
||||||
|
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void userButtonPressed()
|
||||||
|
{
|
||||||
|
// DEBUG_MSG("press!\n");
|
||||||
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
|
}
|
||||||
|
static void userButtonPressedLong() { screen->adjustBrightness(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static Periodic *ledPeriodic;
|
||||||
|
static OSThread *powerFSMthread, *buttonThread;
|
||||||
|
|
||||||
RadioInterface *rIf = NULL;
|
RadioInterface *rIf = NULL;
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
@@ -210,18 +251,7 @@ void setup()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Buttons & LED
|
// Buttons & LED
|
||||||
#ifdef BUTTON_PIN
|
buttonThread = new ButtonThread();
|
||||||
userButton = OneButton(BUTTON_PIN, true, true);
|
|
||||||
userButton.attachClick(userButtonPressed);
|
|
||||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
|
||||||
wakeOnIrq(BUTTON_PIN, FALLING);
|
|
||||||
#endif
|
|
||||||
#ifdef BUTTON_PIN_ALT
|
|
||||||
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
|
||||||
userButtonAlt.attachClick(userButtonPressed);
|
|
||||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
|
||||||
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
|
|
||||||
#endif
|
|
||||||
#ifdef LED_PIN
|
#ifdef LED_PIN
|
||||||
pinMode(LED_PIN, OUTPUT);
|
pinMode(LED_PIN, OUTPUT);
|
||||||
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
|
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
|
||||||
@@ -410,13 +440,6 @@ void loop()
|
|||||||
esp32Loop();
|
esp32Loop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BUTTON_PIN
|
|
||||||
userButton.tick();
|
|
||||||
#endif
|
|
||||||
#ifdef BUTTON_PIN_ALT
|
|
||||||
userButtonAlt.tick();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// For debugging
|
// For debugging
|
||||||
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
|
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
|
||||||
|
|
||||||
@@ -437,9 +460,9 @@ void loop()
|
|||||||
|
|
||||||
/* if (mainController.nextThread && delayMsec)
|
/* if (mainController.nextThread && delayMsec)
|
||||||
DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
|
DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
|
||||||
mainController.nextThread->tillRun(millis()));
|
mainController.nextThread->tillRun(millis())); */
|
||||||
*/
|
|
||||||
|
|
||||||
// We want to sleep as long as possible here - because it saves power
|
// We want to sleep as long as possible here - because it saves power
|
||||||
mainDelay.delay(delayMsec);
|
mainDelay.delay(delayMsec);
|
||||||
|
// if (didWake) DEBUG_MSG("wake!\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,11 +144,18 @@ const char *getChannelName();
|
|||||||
|
|
||||||
PREF_GET(send_owner_interval, 4)
|
PREF_GET(send_owner_interval, 4)
|
||||||
PREF_GET(position_broadcast_secs, 15 * 60)
|
PREF_GET(position_broadcast_secs, 15 * 60)
|
||||||
PREF_GET(wait_bluetooth_secs, 120)
|
|
||||||
|
// Each time we wake into the DARK state allow 1 minute to send and receive BLE packets to the phone
|
||||||
|
PREF_GET(wait_bluetooth_secs, 60)
|
||||||
|
|
||||||
PREF_GET(screen_on_secs, 60)
|
PREF_GET(screen_on_secs, 60)
|
||||||
PREF_GET(mesh_sds_timeout_secs, 2 * 60 * 60)
|
PREF_GET(mesh_sds_timeout_secs, 2 * 60 * 60)
|
||||||
PREF_GET(phone_sds_timeout_sec, 2 * 60 * 60)
|
PREF_GET(phone_sds_timeout_sec, 2 * 60 * 60)
|
||||||
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
|
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
|
||||||
PREF_GET(ls_secs, 60 * 60)
|
|
||||||
|
// We default to sleeping (with bluetooth off for 5 minutes at a time). This seems to be a good tradeoff between
|
||||||
|
// latency for the user sending messages and power savings because of not having to run (expensive) ESP32 bluetooth
|
||||||
|
PREF_GET(ls_secs, 5 * 60)
|
||||||
|
|
||||||
PREF_GET(phone_timeout_secs, 15 * 60)
|
PREF_GET(phone_timeout_secs, 15 * 60)
|
||||||
PREF_GET(min_wake_secs, 10)
|
PREF_GET(min_wake_secs, 10)
|
||||||
|
|||||||
@@ -121,7 +121,14 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
|
|
||||||
case STATE_SEND_RADIO:
|
case STATE_SEND_RADIO:
|
||||||
fromRadioScratch.which_variant = FromRadio_radio_tag;
|
fromRadioScratch.which_variant = FromRadio_radio_tag;
|
||||||
|
|
||||||
fromRadioScratch.variant.radio = radioConfig;
|
fromRadioScratch.variant.radio = radioConfig;
|
||||||
|
|
||||||
|
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
|
||||||
|
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||||
|
// using to the app (so that even old phone apps work with new device loads).
|
||||||
|
fromRadioScratch.variant.radio.preferences.ls_secs = getPref_ls_secs();
|
||||||
|
|
||||||
state = STATE_SEND_NODEINFO;
|
state = STATE_SEND_NODEINFO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user