Merge pull request #472 from cyberman54/development

v1.9.71
This commit is contained in:
Verkehrsrot 2019-10-20 21:15:27 +02:00 committed by GitHub
commit c7461e5e7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 371 additions and 173 deletions

View File

@ -351,10 +351,11 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0x09 reset functions (send this command with confirmed ack only to avoid boot loops!) 0x09 reset functions (send this command with confirmed ack only to avoid boot loops!)
0 = restart device 0 = restart device (coldstart)
1 = reset MAC counter to zero 1 = reset MAC counter to zero
2 = reset device to factory settings 2 = reset device to factory settings
3 = flush send queues 3 = flush send queues
4 = restart device (warmstart)
9 = reboot device to OTA update via Wifi mode 9 = reboot device to OTA update via Wifi mode
0x0A set LoRaWAN payload send cycle 0x0A set LoRaWAN payload send cycle

View File

@ -7,7 +7,8 @@
extern uint8_t DisplayIsOn; extern uint8_t DisplayIsOn;
void refreshTheDisplay(bool nextPage = false); void refreshTheDisplay(bool nextPage = false);
void init_display(uint8_t verbose = 0); void init_display(bool verbose = false);
void shutdown_display(void);
void draw_page(time_t t, uint8_t page); void draw_page(time_t t, uint8_t page);
void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv, void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
const char *format, ...); const char *format, ...);

View File

@ -52,6 +52,13 @@
enum sendprio_t { prio_low, prio_normal, prio_high }; enum sendprio_t { prio_low, prio_normal, prio_high };
enum timesource_t { _gps, _rtc, _lora, _unsynced }; enum timesource_t { _gps, _rtc, _lora, _unsynced };
enum runmode_t {
RUNMODE_POWERCYCLE = 0,
RUNMODE_NORMAL,
RUNMODE_WAKEUP,
RUNMODE_UPDATE
};
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
typedef struct { typedef struct {
uint8_t loradr; // 0-15, lora datarate uint8_t loradr; // 0-15, lora datarate
@ -120,6 +127,7 @@ extern TaskHandle_t irqHandlerTask, ClockTask;
extern TimerHandle_t WifiChanTimer; extern TimerHandle_t WifiChanTimer;
extern Timezone myTZ; extern Timezone myTZ;
extern time_t userUTCTime; extern time_t userUTCTime;
extern RTC_DATA_ATTR runmode_t RTC_runmode;
// application includes // application includes
#include "led.h" #include "led.h"

View File

@ -1,5 +1,5 @@
#ifndef _I2CSCAN_H #ifndef _I2C_H
#define _I2CSCAN_H #define _I2C_H
#include <Arduino.h> #include <Arduino.h>
@ -11,6 +11,8 @@
#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) #define MCP_24AA02E64_PRIMARY_ADDRESS (0x50)
#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) #define QUECTEL_GPS_PRIMARY_ADDRESS (0x10)
void i2c_init(void);
void i2c_deinit(void);
int i2c_scan(void); int i2c_scan(void);
#endif #endif

View File

@ -4,6 +4,7 @@
#include "globals.h" #include "globals.h"
#include "rcommand.h" #include "rcommand.h"
#include "timekeeper.h" #include "timekeeper.h"
#include <driver/rtc_io.h>
#if (TIME_SYNC_LORASERVER) #if (TIME_SYNC_LORASERVER)
#include "timesync.h" #include "timesync.h"
#endif #endif
@ -21,6 +22,9 @@
#endif #endif
extern TaskHandle_t lmicTask, lorasendTask; extern TaskHandle_t lmicTask, lorasendTask;
extern RTC_NOINIT_ATTR u4_t RTCnetid, RTCdevaddr;
extern RTC_NOINIT_ATTR u1_t RTCnwkKey[16], RTCartKey[16];
extern RTC_NOINIT_ATTR int RTCseqnoUp, RTCseqnoDn;
// table of LORAWAN MAC commands // table of LORAWAN MAC commands
typedef struct { typedef struct {
@ -29,7 +33,7 @@ typedef struct {
const uint8_t params; const uint8_t params;
} mac_t; } mac_t;
esp_err_t lora_stack_init(); esp_err_t lora_stack_init(bool do_join);
void lora_setupForNetwork(bool preJoin); void lora_setupForNetwork(bool preJoin);
void lmictask(void *pvParameters); void lmictask(void *pvParameters);
void gen_lora_deveui(uint8_t *pdeveui); void gen_lora_deveui(uint8_t *pdeveui);
@ -42,10 +46,10 @@ void showLoraKeys(void);
void lora_send(void *pvParameters); void lora_send(void *pvParameters);
void lora_enqueuedata(MessageBuffer_t *message); void lora_enqueuedata(MessageBuffer_t *message);
void lora_queuereset(void); void lora_queuereset(void);
void myEventCallback(void *pUserData, ev_t ev); static void IRAM_ATTR myEventCallback(void *pUserData, ev_t ev);
void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, static void IRAM_ATTR myRxCallback(void *pUserData, uint8_t port,
size_t nMsg); const uint8_t *pMsg, size_t nMsg);
void myTxCallback(void *pUserData, int fSuccess); static void IRAM_ATTR myTxCallback(void *pUserData, int fSuccess);
void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[], void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[],
const uint8_t tablesize); const uint8_t tablesize);
uint8_t getBattLevel(void); uint8_t getBattLevel(void);
@ -54,7 +58,7 @@ const char *getBwName(rps_t rps);
const char *getCrName(rps_t rps); const char *getCrName(rps_t rps);
#if (TIME_SYNC_LORAWAN) #if (TIME_SYNC_LORAWAN)
void user_request_network_time_callback(void *pVoidUserUTCTime, static void user_request_network_time_callback(void *pVoidUserUTCTime,
int flagSuccess); int flagSuccess);
#endif #endif

View File

@ -7,8 +7,8 @@
#include <esp_coexist.h> // needed for showing coex sw version #include <esp_coexist.h> // needed for showing coex sw version
#include "globals.h" #include "globals.h"
#include "power.h" #include "reset.h"
#include "i2cscan.h" #include "i2c.h"
#include "blescan.h" #include "blescan.h"
#include "wifiscan.h" #include "wifiscan.h"
#include "configmanager.h" #include "configmanager.h"
@ -16,8 +16,8 @@
#include "beacon_array.h" #include "beacon_array.h"
#include "ota.h" #include "ota.h"
#include "irqhandler.h" #include "irqhandler.h"
#include "led.h"
#include "spislave.h" #include "spislave.h"
#if (HAS_LORA) #if (HAS_LORA)
#include "lorawan.h" #include "lorawan.h"
#endif #endif

View File

@ -17,7 +17,7 @@ void start_ota_update();
int version_compare(const String v1, const String v2); int version_compare(const String v1, const String v2);
void ota_display(const uint8_t row, const std::string status, void ota_display(const uint8_t row, const std::string status,
const std::string msg); const std::string msg);
void show_progress(unsigned long current, unsigned long size); static void show_progress(unsigned long current, unsigned long size);
#endif // USE_OTA #endif // USE_OTA

View File

@ -4,7 +4,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <driver/adc.h> #include <driver/adc.h>
#include <esp_adc_cal.h> #include <esp_adc_cal.h>
#include "i2cscan.h" #include "i2c.h"
#include "reset.h"
#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate
#define NO_OF_SAMPLES 64 // we do some multisampling to get better values #define NO_OF_SAMPLES 64 // we do some multisampling to get better values
@ -14,13 +15,16 @@ void calibrate_voltage(void);
bool batt_sufficient(void); bool batt_sufficient(void);
#ifdef HAS_PMU #ifdef HAS_PMU
#include <axp20x.h> #include <axp20x.h>
void power_event_IRQ(void); enum pmu_power_t { pmu_power_on, pmu_power_off, pmu_power_sleep };
void AXP192_power(bool on); void AXP192_powerevent_IRQ(void);
void AXP192_power(pmu_power_t powerlevel);
void AXP192_init(void); void AXP192_init(void);
void AXP192_showstatus(void); void AXP192_showstatus(void);
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len); uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len); uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
#endif // HAS_PMU #endif // HAS_PMU
#endif #endif

View File

@ -24,6 +24,6 @@ typedef struct {
} cmd_t; } cmd_t;
void rcommand(const uint8_t cmd[], const uint8_t cmdlength); void rcommand(const uint8_t cmd[], const uint8_t cmdlength);
void do_reset(); void do_reset(bool warmstart);
#endif #endif

12
include/reset.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _RESET_H
#define _RESET_H
#include <driver/rtc_io.h>
#include <rom/rtc.h>
#include "i2c.h"
void do_reset(bool warmstart);
void do_after_reset(int reason);
void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio);
#endif // _RESET_H

View File

@ -8,7 +8,7 @@
#include "hash.h" #include "hash.h"
void wifi_sniffer_init(void); void wifi_sniffer_init(void);
void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); static void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
void switchWifiChannel(TimerHandle_t xTimer); void switchWifiChannel(TimerHandle_t xTimer);
#endif #endif

View File

@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.9.6 release_version = 1.9.71
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3 debug_level = 3

View File

@ -33,7 +33,6 @@ void defaultConfig() {
cfg.vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled cfg.vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled
cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
cfg.monitormode = 0; // 0=disabled, 1=enabled cfg.monitormode = 0; // 0=disabled, 1=enabled
cfg.runmode = 0; // 0=normal, 1=update
cfg.payloadmask = PAYLOADMASK; // all payload switched on cfg.payloadmask = PAYLOADMASK; // all payload switched on
cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = {
0}; // init BSEC state for BME680 sensor 0}; // init BSEC state for BME680 sensor
@ -157,10 +156,6 @@ void saveConfig() {
flash8 != cfg.monitormode) flash8 != cfg.monitormode)
nvs_set_i8(my_handle, "monitormode", cfg.monitormode); nvs_set_i8(my_handle, "monitormode", cfg.monitormode);
if (nvs_get_i8(my_handle, "runmode", &flash8) != ESP_OK ||
flash8 != cfg.runmode)
nvs_set_i8(my_handle, "runmode", cfg.runmode);
if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK ||
flash16 != cfg.rssilimit) flash16 != cfg.rssilimit)
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
@ -350,14 +345,6 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if (nvs_get_i8(my_handle, "runmode", &flash8) == ESP_OK) {
cfg.runmode = flash8;
ESP_LOGI(TAG, "Run mode = %d", flash8);
} else {
ESP_LOGI(TAG, "Run mode set to default %d", cfg.runmode);
saveConfig();
}
nvs_close(my_handle); nvs_close(my_handle);
ESP_LOGI(TAG, "Done"); ESP_LOGI(TAG, "Done");
} }

View File

@ -20,8 +20,15 @@ void doHousekeeping() {
uptime(); uptime();
// check if update mode trigger switch was set // check if update mode trigger switch was set
if (cfg.runmode == 1) if (RTC_runmode == RUNMODE_UPDATE) {
do_reset(); // check battery status if we can before doing ota
if (batt_sufficient())
do_reset(true); // warmstart to runmode update
else {
ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage);
RTC_runmode == RUNMODE_NORMAL; // keep running in normal mode
}
}
// task storage debugging // // task storage debugging //
ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d", ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d",
@ -87,7 +94,7 @@ void doHousekeeping() {
get_salt(); // get new salt for salting hashes get_salt(); // get new salt for salting hashes
if (ESP.getMinFreeHeap() <= MEM_LOW) // check again if (ESP.getMinFreeHeap() <= MEM_LOW) // check again
do_reset(); // memory leak, reset device do_reset(true); // memory leak, reset device
} }
// check free PSRAM memory // check free PSRAM memory
@ -98,7 +105,7 @@ void doHousekeeping() {
get_salt(); // get new salt for salting hashes get_salt(); // get new salt for salting hashes
if (ESP.getMinFreePsram() <= MEM_LOW) // check again if (ESP.getMinFreePsram() <= MEM_LOW) // check again
do_reset(); // memory leak, reset device do_reset(true); // memory leak, reset device
} }
#endif #endif

View File

@ -60,7 +60,7 @@ uint8_t displaybuf[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8] = {0};
QRCode qrcode; QRCode qrcode;
void init_display(uint8_t verbose) { void init_display(bool verbose) {
// block i2c bus access // block i2c bus access
if (!I2C_MUTEX_LOCK()) if (!I2C_MUTEX_LOCK())
@ -70,7 +70,7 @@ void init_display(uint8_t verbose) {
// is we have display RST line we toggle it to re-initialize display // is we have display RST line we toggle it to re-initialize display
#ifdef MY_OLED_RST #ifdef MY_OLED_RST
pinMode(MY_OLED_RST, OUTPUT); pinMode(MY_OLED_RST, OUTPUT);
digitalWrite(MY_OLED_RST, 0); // iniialization of SSD1306 chip is executed digitalWrite(MY_OLED_RST, 0); // initialization of SSD1306 chip is executed
delay(1); // keep RES low for at least 3us according to SSD1306 datasheet delay(1); // keep RES low for at least 3us according to SSD1306 datasheet
digitalWrite(MY_OLED_RST, 1); // normal operation digitalWrite(MY_OLED_RST, 1); // normal operation
#endif #endif
@ -182,6 +182,18 @@ void refreshTheDisplay(bool nextPage) {
} // mutex } // mutex
} // refreshDisplay() } // refreshDisplay()
void shutdown_display(void) {
// block i2c bus access
if (!I2C_MUTEX_LOCK())
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
else {
cfg.screenon = 0;
oledShutdown();
delay(DISPLAYREFRESH_MS / 1000 * 1.1);
I2C_MUTEX_UNLOCK(); // release i2c bus access
}
}
void draw_page(time_t t, uint8_t page) { void draw_page(time_t t, uint8_t page) {
char timeState; char timeState;

View File

@ -1,10 +1,30 @@
// Basic config // Basic config
#include "globals.h" #include "globals.h"
#include "i2cscan.h" #include "i2c.h"
// Local logging tag // Local logging tag
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
void i2c_init(void) {
#ifdef HAS_DISPLAY
Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 400000);
#else
Wire.begin(SDA, SCL, 400000);
#endif
}
void i2c_deinit(void) {
Wire.~TwoWire(); // shutdown/power off I2C hardware
#ifdef HAS_DISPLAY
// to save power, because Wire.end() enables pullups
pinMode(MY_OLED_SDA, INPUT);
pinMode(MY_OLED_SCL, INPUT);
#else
pinMode(SDA, INPUT);
pinMode(SCL, INPUT);
#endif
}
int i2c_scan(void) { int i2c_scan(void) {
int i2c_ret, addr; int i2c_ret, addr;

View File

@ -20,7 +20,15 @@ void irqHandler(void *pvParameters) {
if (InterruptStatus & UNMASK_IRQ) // interrupt handler to be enabled? if (InterruptStatus & UNMASK_IRQ) // interrupt handler to be enabled?
mask_irq = false; mask_irq = false;
else if (mask_irq) // suppress processing if interrupt handler is disabled // else if (mask_irq) // suppress processing if interrupt handler is
// disabled
#if (HAS_LORA)
else if (mask_irq || os_queryTimeCriticalJobs(ms2osticks(100)))
#else
else if (mask_irq)
#endif
// suppress processing if interrupt handler is disabled
// or time critical lmic jobs are pending in next 100ms
continue; continue;
else if (InterruptStatus & MASK_IRQ) { // interrupt handler to be disabled? else if (InterruptStatus & MASK_IRQ) { // interrupt handler to be disabled?
mask_irq = true; mask_irq = true;
@ -66,7 +74,7 @@ void irqHandler(void *pvParameters) {
// do we have a power event? // do we have a power event?
#if (HAS_PMU) #if (HAS_PMU)
if (InterruptStatus & PMU_IRQ) if (InterruptStatus & PMU_IRQ)
power_event_IRQ(); AXP192_powerevent_IRQ();
#endif #endif
// is time to send the payload? // is time to send the payload?

View File

@ -28,14 +28,14 @@
// so consuming more power. You may sharpen (reduce) this value if you are // so consuming more power. You may sharpen (reduce) this value if you are
// limited on battery. // limited on battery.
// ATTN: VALUES > 7 WILL CAUSE RECEPTION AND JOIN PROBLEMS WITH HIGH SF RATES // ATTN: VALUES > 7 WILL CAUSE RECEPTION AND JOIN PROBLEMS WITH HIGH SF RATES
//#define CLOCK_ERROR_PROCENTAGE 5 #define CLOCK_ERROR_PROCENTAGE 5
// Set this to 1 to enable some basic debug output (using printf) about // Set this to 1 to enable some basic debug output (using printf) about
// RF settings used during transmission and reception. Set to 2 to // RF settings used during transmission and reception. Set to 2 to
// enable more verbose output. Make sure that printf is actually // enable more verbose output. Make sure that printf is actually
// configured (e.g. on AVR it is not by default), otherwise using it can // configured (e.g. on AVR it is not by default), otherwise using it can
// cause crashing. // cause crashing.
//#define LMIC_DEBUG_LEVEL 1 //#define LMIC_DEBUG_LEVEL 2
// Enable this to allow using printf() to print to the given serial port // Enable this to allow using printf() to print to the given serial port
// (or any other Print object). This can be easy for debugging. The // (or any other Print object). This can be easy for debugging. The
@ -57,8 +57,7 @@
// Uncomment this to disable all code related to ping // Uncomment this to disable all code related to ping
#define DISABLE_PING #define DISABLE_PING
// Uncomment this to disable all code related to beacon tracking. // Uncomment this to disable all code related to beacon tracking.
// Requires ping to be disabled too // Requires ping to be disabled too#define DISABLE_BEACONS
#define DISABLE_BEACONS
// Uncomment these to disable the corresponding MAC commands. // Uncomment these to disable the corresponding MAC commands.
// Class A // Class A

View File

@ -18,6 +18,11 @@ static const char TAG[] = "lora";
#endif #endif
#endif #endif
// variable keep its values after restart or wakeup from sleep
RTC_NOINIT_ATTR u4_t RTCnetid, RTCdevaddr;
RTC_NOINIT_ATTR u1_t RTCnwkKey[16], RTCartKey[16];
RTC_NOINIT_ATTR int RTCseqnoUp, RTCseqnoDn;
QueueHandle_t LoraSendQueue; QueueHandle_t LoraSendQueue;
TaskHandle_t lmicTask = NULL, lorasendTask = NULL; TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
@ -86,9 +91,9 @@ void lora_setupForNetwork(bool preJoin) {
#elif CFG_LMIC_EU_like #elif CFG_LMIC_EU_like
// setting for TheThingsNetwork // setting for TheThingsNetwork
// TTN uses SF9, not SF12, for RX2 window // TTN uses SF9, not SF12, for RX2 window
LMIC.dn2Dr = EU868_DR_SF9; // LMIC.dn2Dr = EU868_DR_SF9;
// Disable link check validation // Enable link check validation
LMIC_setLinkCheckMode(0); LMIC_setLinkCheckMode(true);
#endif #endif
} else { } else {
@ -244,9 +249,9 @@ void lora_send(void *pvParameters) {
while (1) { while (1) {
// postpone until we are joined if we are not // postpone until we are joined if we are not
// while (!LMIC.devaddr) { while (!LMIC.devaddr) {
// vTaskDelay(pdMS_TO_TICKS(500)); vTaskDelay(pdMS_TO_TICKS(500));
//} }
// fetch next or wait for payload to send from queue // fetch next or wait for payload to send from queue
if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) != pdTRUE) { if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) != pdTRUE) {
@ -287,7 +292,7 @@ void lora_send(void *pvParameters) {
} }
} }
esp_err_t lora_stack_init() { esp_err_t lora_stack_init(bool do_join) {
assert(SEND_QUEUE_SIZE); assert(SEND_QUEUE_SIZE);
LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t)); LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t));
if (LoraSendQueue == 0) { if (LoraSendQueue == 0) {
@ -303,13 +308,22 @@ esp_err_t lora_stack_init() {
"lmictask", // name of task "lmictask", // name of task
4096, // stack size of task 4096, // stack size of task
(void *)1, // parameter of the task (void *)1, // parameter of the task
5, // priority of the task 2, // priority of the task
&lmicTask, // task handle &lmicTask, // task handle
1); // CPU core 1); // CPU core
// start join // Start join procedure if not already joined,
// lora_setupForNetwork(true) is called by eventhandler when joined
// else continue current session
if (do_join) {
if (!LMIC_startJoining()) if (!LMIC_startJoining())
ESP_LOGI(TAG, "Already joined"); ESP_LOGI(TAG, "Already joined");
} else {
LMIC_reset();
LMIC_setSession(RTCnetid, RTCdevaddr, RTCnwkKey, RTCartKey);
LMIC.seqnoUp = RTCseqnoUp;
LMIC.seqnoDn = RTCseqnoDn;
}
// start lmic send task // start lmic send task
xTaskCreatePinnedToCore(lora_send, // task function xTaskCreatePinnedToCore(lora_send, // task function
@ -357,7 +371,7 @@ void lora_enqueuedata(MessageBuffer_t *message) {
void lora_queuereset(void) { xQueueReset(LoraSendQueue); } void lora_queuereset(void) { xQueueReset(LoraSendQueue); }
#if (TIME_SYNC_LORAWAN) #if (TIME_SYNC_LORAWAN)
void IRAM_ATTR user_request_network_time_callback(void *pVoidUserUTCTime, static void IRAM_ATTR user_request_network_time_callback(void *pVoidUserUTCTime,
int flagSuccess) { int flagSuccess) {
// Explicit conversion from void* to uint32_t* to avoid compiler errors // Explicit conversion from void* to uint32_t* to avoid compiler errors
time_t *pUserUTCTime = (time_t *)pVoidUserUTCTime; time_t *pUserUTCTime = (time_t *)pVoidUserUTCTime;
@ -428,7 +442,7 @@ void lmictask(void *pvParameters) {
// so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE // so consuming more power. You may sharpen (reduce) CLOCK_ERROR_PERCENTAGE
// in src/lmic_config.h if you are limited on battery. // in src/lmic_config.h if you are limited on battery.
#ifdef CLOCK_ERROR_PROCENTAGE #ifdef CLOCK_ERROR_PROCENTAGE
LMIC_setClockError(CLOCK_ERROR_PROCENTAGE * MAX_CLOCK_ERROR / 100); LMIC_setClockError(CLOCK_ERROR_PROCENTAGE * MAX_CLOCK_ERROR / 1000);
#endif #endif
while (1) { while (1) {
@ -438,7 +452,7 @@ void lmictask(void *pvParameters) {
} // lmictask } // lmictask
// lmic event handler // lmic event handler
void myEventCallback(void *pUserData, ev_t ev) { static void myEventCallback(void *pUserData, ev_t ev) {
// using message descriptors from LMIC library // using message descriptors from LMIC library
static const char *const evNames[] = {LMIC_EVENT_NAME_TABLE__INIT}; static const char *const evNames[] = {LMIC_EVENT_NAME_TABLE__INIT};
@ -482,7 +496,7 @@ void myEventCallback(void *pUserData, ev_t ev) {
} }
// receive message handler // receive message handler
void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, static void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
size_t nMsg) { size_t nMsg) {
// display type of received data // display type of received data
@ -537,7 +551,7 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
} }
// transmit complete message handler // transmit complete message handler
void myTxCallback(void *pUserData, int fSuccess) { static void myTxCallback(void *pUserData, int fSuccess) {
#if (TIME_SYNC_LORASERVER) #if (TIME_SYNC_LORASERVER)
// if last packet sent was a timesync request, store TX timestamp // if last packet sent was a timesync request, store TX timestamp

View File

@ -31,7 +31,7 @@ ledloop 0 3 blinks LEDs
spiloop 0 2 reads/writes data on spi interface spiloop 0 2 reads/writes data on spi interface
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
lmictask 1 5 MCCI LMiC LORAWAN stack lmictask 1 2 MCCI LMiC LORAWAN stack
clockloop 1 4 generates realtime telegrams for external clock clockloop 1 4 generates realtime telegrams for external clock
timesync_req 1 3 processes realtime time sync requests timesync_req 1 3 processes realtime time sync requests
irqhandler 1 1 display, timesync, gps, etc. triggered by timers irqhandler 1 1 display, timesync, gps, etc. triggered by timers
@ -129,16 +129,19 @@ void setup() {
esp_log_level_set("*", ESP_LOG_NONE); esp_log_level_set("*", ESP_LOG_NONE);
#endif #endif
ESP_LOGI(TAG, "Starting Software v%s", PROGVERSION); do_after_reset(rtc_get_reset_reason(0));
// print chip information on startup if in verbose mode // print chip information on startup if in verbose mode after coldstart
#if (VERBOSE) #if (VERBOSE)
if (RTC_runmode == RUNMODE_POWERCYCLE) {
esp_chip_info_t chip_info; esp_chip_info_t chip_info;
esp_chip_info(&chip_info); esp_chip_info(&chip_info);
ESP_LOGI(TAG, ESP_LOGI(TAG,
"This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision " "This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision "
"%d, %dMB %s Flash", "%d, %dMB %s Flash",
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "", (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
@ -146,14 +149,15 @@ void setup() {
ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d",
ESP.getHeapSize(), ESP.getFreeHeap()); ESP.getHeapSize(), ESP.getFreeHeap());
#ifdef BOARD_HAS_PSRAM #ifdef BOARD_HAS_PSRAM
ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d",
ESP.getFreePsram()); ESP.getPsramSize(), ESP.getFreePsram());
#endif #endif
ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s",
ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion());
ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(),
ESP.getFlashChipSpeed()); ESP.getFlashChipSpeed());
ESP_LOGI(TAG, "Wifi/BT software coexist version %s", esp_coex_version_get()); ESP_LOGI(TAG, "Wifi/BT software coexist version %s",
esp_coex_version_get());
#if (HAS_LORA) #if (HAS_LORA)
ESP_LOGI(TAG, "IBM LMIC version %d.%d.%d", LMIC_VERSION_MAJOR, ESP_LOGI(TAG, "IBM LMIC version %d.%d.%d", LMIC_VERSION_MAJOR,
@ -169,13 +173,11 @@ void setup() {
#if (HAS_GPS) #if (HAS_GPS)
ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion());
#endif #endif
}
#endif // VERBOSE
// open i2c bus // open i2c bus
#ifdef HAS_DISPLAY i2c_init();
Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 400000);
#else
Wire.begin(SDA, SCL, 400000);
#endif
// setup power on boards with power management logic // setup power on boards with power management logic
#ifdef EXT_POWER_SW #ifdef EXT_POWER_SW
@ -188,8 +190,6 @@ void setup() {
strcat_P(features, " PMU"); strcat_P(features, " PMU");
#endif #endif
#endif // verbose
// read (and initialize on first run) runtime settings from NVRAM // read (and initialize on first run) runtime settings from NVRAM
loadConfig(); // includes initialize if necessary loadConfig(); // includes initialize if necessary
@ -197,7 +197,8 @@ void setup() {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
strcat_P(features, " OLED"); strcat_P(features, " OLED");
DisplayIsOn = cfg.screenon; DisplayIsOn = cfg.screenon;
init_display(!cfg.runmode); // note: blocking call // display verbose info only after a coldstart (note: blocking call!)
init_display(RTC_runmode == RUNMODE_POWERCYCLE ? true : false);
#endif #endif
// scan i2c bus for devices // scan i2c bus for devices
@ -266,11 +267,8 @@ void setup() {
#if (USE_OTA) #if (USE_OTA)
strcat_P(features, " OTA"); strcat_P(features, " OTA");
// reboot to firmware update mode if ota trigger switch is set // reboot to firmware update mode if ota trigger switch is set
if (cfg.runmode == 1) { if (RTC_runmode == RUNMODE_UPDATE)
cfg.runmode = 0;
saveConfig();
start_ota_update(); start_ota_update();
}
#endif #endif
// start BLE scan callback if BLE function is enabled in NVRAM configuration // start BLE scan callback if BLE function is enabled in NVRAM configuration
@ -314,7 +312,9 @@ void setup() {
// initialize LoRa // initialize LoRa
#if (HAS_LORA) #if (HAS_LORA)
strcat_P(features, " LORA"); strcat_P(features, " LORA");
assert(lora_stack_init() == ESP_OK); // kick off join, except we come from sleep
assert(lora_stack_init(RTC_runmode == RUNMODE_WAKEUP ? false : true) ==
ESP_OK);
#endif #endif
// initialize SPI // initialize SPI
@ -465,6 +465,9 @@ void setup() {
// show compiled features // show compiled features
ESP_LOGI(TAG, "Features:%s", features); ESP_LOGI(TAG, "Features:%s", features);
// set runmode to normal
RTC_runmode = RUNMODE_NORMAL;
vTaskDelete(NULL); vTaskDelete(NULL);
} // setup() } // setup()

View File

@ -40,12 +40,6 @@ inline String getHeaderValue(String header, String headerName) {
void start_ota_update() { void start_ota_update() {
// check battery status if we can before doing ota
if (!batt_sufficient()) {
ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage);
return;
}
switch_LED(LED_ON); switch_LED(LED_ON);
// init display // init display
@ -105,7 +99,7 @@ end:
ESP_LOGI(TAG, "Rebooting to %s firmware", (ret == 0) ? "new" : "current"); ESP_LOGI(TAG, "Rebooting to %s firmware", (ret == 0) ? "new" : "current");
ota_display(5, "**", ""); // mark line rebooting ota_display(5, "**", ""); // mark line rebooting
delay(5000); delay(5000);
ESP.restart(); do_reset(false);
} // start_ota_update } // start_ota_update
@ -320,7 +314,7 @@ void ota_display(const uint8_t row, const std::string status,
} }
// callback function to show download progress while streaming data // callback function to show download progress while streaming data
void show_progress(unsigned long current, unsigned long size) { static void show_progress(unsigned long current, unsigned long size) {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
char buf[17]; char buf[17];
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size); snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size);

View File

@ -7,7 +7,7 @@
// Note: After editing, before "build", use "clean" button in PlatformIO! // Note: After editing, before "build", use "clean" button in PlatformIO!
// Verbose enables serial output // Verbose enables serial output
#define VERBOSE 1 // set to 0 to silence the device, for mute use build option #define VERBOSE 0 // set to 0 to silence the device, for mute use build option
// Payload send cycle and encoding // Payload send cycle and encoding
#define SENDCYCLE 30 // payload send cycle [seconds/2], 0 .. 255 #define SENDCYCLE 30 // payload send cycle [seconds/2], 0 .. 255

View File

@ -5,11 +5,24 @@
// Local logging tag // Local logging tag
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
#ifdef HAS_PMU #ifdef BAT_MEASURE_ADC
esp_adc_cal_characteristics_t *adc_characs =
(esp_adc_cal_characteristics_t *)calloc(
1, sizeof(esp_adc_cal_characteristics_t));
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
static const adc1_channel_t adc_channel = BAT_MEASURE_ADC;
#else // ADC2
static const adc2_channel_t adc_channel = BAT_MEASURE_ADC;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;
#endif // BAT_MEASURE_ADC
#ifdef HAS_PMU
AXP20X_Class pmu; AXP20X_Class pmu;
void power_event_IRQ(void) { void AXP192_powerevent_IRQ(void) {
pmu.readIRQ(); pmu.readIRQ();
@ -34,14 +47,16 @@ void power_event_IRQ(void) {
if (pmu.isBattTempHighIRQ()) if (pmu.isBattTempHighIRQ())
ESP_LOGI(TAG, "Battery low temperature."); ESP_LOGI(TAG, "Battery low temperature.");
// display on/off // short press -> esp32 deep sleep mode, can be exited by pressing user button
// if (pmu.isPEKShortPressIRQ()) { #ifdef HAS_BUTTON
// cfg.screenon = !cfg.screenon; if (pmu.isPEKShortPressIRQ() && (RTC_runmode == RUNMODE_NORMAL)) {
//} enter_deepsleep(0, HAS_BUTTON);
}
#endif
// shutdown power // long press -> shutdown power, can be exited by another longpress
if (pmu.isPEKLongtPressIRQ()) { if (pmu.isPEKLongtPressIRQ()) {
AXP192_power(false); // switch off Lora, GPS, display AXP192_power(pmu_power_off); // switch off Lora, GPS, display
pmu.shutdown(); // switch off device pmu.shutdown(); // switch off device
} }
@ -51,18 +66,31 @@ void power_event_IRQ(void) {
read_voltage(); read_voltage();
} }
void AXP192_power(bool on) { void AXP192_power(pmu_power_t powerlevel) {
if (on) {
pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0 switch (powerlevel) {
pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0
pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // OLED on T-Beam v1.0 case pmu_power_off:
// pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
} else {
pmu.setChgLEDMode(AXP20X_LED_OFF); pmu.setChgLEDMode(AXP20X_LED_OFF);
pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF);
pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF);
pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF);
// pmu.setPowerOutPut(AXP192_DCDC3, AXP202_OFF);
break;
case pmu_power_sleep:
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
// we don't cut off DCDC1, because then display blocks i2c bus
pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // gps off
pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // lora off
break;
default: // all rails power on
pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0
pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0
pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // OLED on T-Beam v1.0
pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
break;
} }
} }
@ -103,7 +131,7 @@ void AXP192_init(void) {
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true); pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true);
// switch power rails on // switch power rails on
AXP192_power(true); AXP192_power(pmu_power_on);
#ifdef PMU_INT #ifdef PMU_INT
pinMode(PMU_INT, INPUT_PULLUP); pinMode(PMU_INT, INPUT_PULLUP);
@ -119,7 +147,7 @@ void AXP192_init(void) {
} }
} }
// helper functions for mutexing i2c access // helper functions for mutexing pmu i2c access
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) { uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
@ -170,21 +198,6 @@ uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
#endif // HAS_PMU #endif // HAS_PMU
#ifdef BAT_MEASURE_ADC
esp_adc_cal_characteristics_t *adc_characs =
(esp_adc_cal_characteristics_t *)calloc(
1, sizeof(esp_adc_cal_characteristics_t));
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
static const adc1_channel_t adc_channel = BAT_MEASURE_ADC;
#else // ADC2
static const adc2_channel_t adc_channel = BAT_MEASURE_ADC;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;
#endif // BAT_MEASURE_ADC
void calibrate_voltage(void) { void calibrate_voltage(void) {
#ifdef BAT_MEASURE_ADC #ifdef BAT_MEASURE_ADC
// configure ADC // configure ADC

View File

@ -5,21 +5,12 @@
// Local logging tag // Local logging tag
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
// helper function
void do_reset() {
ESP_LOGI(TAG, "Remote command: restart device");
#if (HAS_LORA)
LMIC_shutdown();
#endif
delay(3000);
esp_restart();
}
// set of functions that can be triggered by remote commands // set of functions that can be triggered by remote commands
void set_reset(uint8_t val[]) { void set_reset(uint8_t val[]) {
switch (val[0]) { switch (val[0]) {
case 0: // restart device case 0: // restart device with cold start (clear RTC saved variables)
do_reset(); ESP_LOGI(TAG, "Remote command: restart device cold");
do_reset(false);
break; break;
case 1: // reset MAC counter case 1: // reset MAC counter
ESP_LOGI(TAG, "Remote command: reset MAC counter"); ESP_LOGI(TAG, "Remote command: reset MAC counter");
@ -34,10 +25,14 @@ void set_reset(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: flush send queue"); ESP_LOGI(TAG, "Remote command: flush send queue");
flushQueues(); flushQueues();
break; break;
case 4: // restart device with warm start (keep RTC saved variables)
ESP_LOGI(TAG, "Remote command: restart device warm");
do_reset(true);
break;
case 9: // reset and ask for software update via Wifi OTA case 9: // reset and ask for software update via Wifi OTA
ESP_LOGI(TAG, "Remote command: software update via Wifi"); ESP_LOGI(TAG, "Remote command: software update via Wifi");
#if (USE_OTA) #if (USE_OTA)
cfg.runmode = 1; RTC_runmode = RUNMODE_UPDATE;
#endif // USE_OTA #endif // USE_OTA
break; break;
@ -346,7 +341,7 @@ static cmd_t table[] = {
{0x03, set_gps, 1, true}, {0x04, set_display, 1, true}, {0x03, set_gps, 1, true}, {0x04, set_display, 1, true},
{0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true}, {0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true},
{0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true}, {0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true},
{0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true}, {0x09, set_reset, 1, false}, {0x0a, set_sendcycle, 1, true},
{0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true}, {0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true},
{0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true}, {0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true},
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true}, {0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},

114
src/reset.cpp Normal file
View File

@ -0,0 +1,114 @@
// Basic Config
#include "globals.h"
#include "reset.h"
// Local logging tag
static const char TAG[] = __FILE__;
// variable keep its values after restart or wakeup from sleep
RTC_NOINIT_ATTR runmode_t RTC_runmode;
void do_reset(bool warmstart) {
if (warmstart) {
// store LMIC keys and counters in RTC memory
#if (HAS_LORA)
LMIC_getSessionKeys(&RTCnetid, &RTCdevaddr, RTCnwkKey, RTCartKey);
RTCseqnoUp = LMIC.seqnoUp;
RTCseqnoDn = LMIC.seqnoDn;
#endif
ESP_LOGI(TAG, "restarting device (warmstart), keeping runmode %d",
RTC_runmode);
} else {
#if (HAS_LORA)
if (RTC_runmode == RUNMODE_NORMAL)
LMIC_shutdown();
#endif
RTC_runmode = RUNMODE_POWERCYCLE;
ESP_LOGI(TAG, "restarting device (coldstart), set runmode %d", RTC_runmode);
}
esp_restart();
}
void do_after_reset(int reason) {
switch (reason) {
case POWERON_RESET: // 0x01 Vbat power on reset
case RTCWDT_BROWN_OUT_RESET: // 0x0f Reset when the vdd voltage is not
// stable
RTC_runmode = RUNMODE_POWERCYCLE;
break;
case DEEPSLEEP_RESET: // 0x05 Deep Sleep reset digital core
RTC_runmode = RUNMODE_WAKEUP;
break;
case SW_RESET: // 0x03 Software reset digital core
case OWDT_RESET: // 0x04 Legacy watch dog reset digital core
case SDIO_RESET: // 0x06 Reset by SLC module, reset digital core
case TG0WDT_SYS_RESET: // 0x07 Timer Group0 Watch dog reset digital core
case TG1WDT_SYS_RESET: // 0x08 Timer Group1 Watch dog reset digital core
case RTCWDT_SYS_RESET: // 0x09 RTC Watch dog Reset digital core
case INTRUSION_RESET: // 0x0a Instrusion tested to reset CPU
case TGWDT_CPU_RESET: // 0x0b Time Group reset CPU
case SW_CPU_RESET: // 0x0c Software reset CPU
case RTCWDT_CPU_RESET: // 0x0d RTC Watch dog Reset CPU
case EXT_CPU_RESET: // 0x0e for APP CPU, reseted by PRO CPU
case RTCWDT_RTC_RESET: // 0x10 RTC Watch dog reset digital core and rtc mode
default:
break;
}
ESP_LOGI(TAG, "Starting Software v%s, runmode %d", PROGVERSION, RTC_runmode);
}
void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio) {
if ((!wakeup_sec) && (!wakeup_gpio) && (RTC_runmode == RUNMODE_NORMAL))
return;
// set up power domains
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
// set wakeup timer
if (wakeup_sec)
esp_sleep_enable_timer_wakeup(wakeup_sec * 1000000);
// set wakeup gpio
if (wakeup_gpio != NOT_A_PIN) {
rtc_gpio_isolate(wakeup_gpio);
esp_sleep_enable_ext1_wakeup(1ULL << wakeup_gpio, ESP_EXT1_WAKEUP_ALL_LOW);
}
// store LMIC keys and counters in RTC memory
#if (HAS_LORA)
LMIC_getSessionKeys(&RTCnetid, &RTCdevaddr, RTCnwkKey, RTCartKey);
RTCseqnoUp = LMIC.seqnoUp;
RTCseqnoDn = LMIC.seqnoDn;
#endif
// halt interrupts accessing i2c bus
mask_user_IRQ();
// switch off display
#ifdef HAS_DISPLAY
shutdown_display();
#endif
// switch off wifi & ble
#if (BLECOUNTER)
stop_BLEscan();
#endif
// reduce power if has PMU
#ifdef HAS_PMU
AXP192_power(pmu_power_sleep);
#endif
// shutdown i2c bus
i2c_deinit();
// enter sleep mode
ESP_LOGI(TAG, "Going to sleep...");
esp_deep_sleep_start();
}

View File

@ -29,7 +29,7 @@ typedef struct {
} wifi_ieee80211_packet_t; } wifi_ieee80211_packet_t;
// using IRAM_:ATTR here to speed up callback function // using IRAM_:ATTR here to speed up callback function
IRAM_ATTR void wifi_sniffer_packet_handler(void *buff, static IRAM_ATTR void wifi_sniffer_packet_handler(void *buff,
wifi_promiscuous_pkt_type_t type) { wifi_promiscuous_pkt_type_t type) {
const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff; const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;