Merge branch 'master' into S3-usb-stick

This commit is contained in:
cyberman54 2022-10-29 19:05:18 +02:00
commit ef68179b85
44 changed files with 374 additions and 625 deletions

56
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,56 @@
name: PlatformIO CI
on:
pull_request:
push:
branches:
- master
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
path: ~/.cache/pip
platformio-path: ~/.platformio
- os: macos-latest
path: ~/Library/Caches/pip
platformio-path: ~/Library/Caches/platformio
- os: windows-latest
path: ~\AppData\Local\pip\Cache
platformio-path: ~\AppData\Local\platformio\Cache
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Cache pip
uses: actions/cache@v3
with:
path: ${{ matrix.path }}
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v3
with:
path: ${{ matrix.platformio-path }}
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9.13"
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio
- name: Copy of necessary files
run: |
cp platformio_orig.ini platformio.ini
cp src/loraconf_sample.h src/loraconf.h
cp src/ota_sample.conf src/ota.conf
cp src/paxcounter_orig.conf src/paxcounter.conf
- name: Run PlatformIO
run: pio run

View File

@ -3,6 +3,7 @@
Tutorial (in german language): https://www.heise.de/select/make/2019/1/1551099236518668 Tutorial (in german language): https://www.heise.de/select/make/2019/1/1551099236518668
[![CodeFactor](https://www.codefactor.io/repository/github/cyberman54/esp32-paxcounter/badge)](https://www.codefactor.io/repository/github/cyberman54/esp32-paxcounter)
<img src="img/Paxcounter-title.jpg"> <img src="img/Paxcounter-title.jpg">
@ -32,8 +33,9 @@ You can build this project battery powered using ESP32 deep sleep mode and reach
*LoRa & SPI*: *LoRa & SPI*:
- **LilyGo: [Paxcounter-Board*](https://www.aliexpress.com/item/32915894264.html?spm=a2g0o.productlist.0.0.3d656325QrcfQc&algo_pvid=4a150199-63e7-4d21-bdb1-b48164537744&algo_exp_id=4a150199-63e7-4d21-bdb1-b48164537744-2&pdp_ext_f=%7B%22sku_id%22%3A%2212000023374441919%22%7D)**
- TTGO: T1*, T2*, T3*, T-Beam, T-Fox
- Heltec: LoRa-32 v1 and v2 - Heltec: LoRa-32 v1 and v2
- TTGO: [Paxcounter-Board*](https://www.aliexpress.com/item/32915894264.html?spm=a2g0o.productlist.0.0.3d656325QrcfQc&algo_pvid=4a150199-63e7-4d21-bdb1-b48164537744&algo_exp_id=4a150199-63e7-4d21-bdb1-b48164537744-2&pdp_ext_f=%7B%22sku_id%22%3A%2212000023374441919%22%7D), T1*, T2*, T3*, T-Beam, T-Fox
- Pycom: LoPy, LoPy4, FiPy - Pycom: LoPy, LoPy4, FiPy
- Radioshuttle.de: [ECO Power Board](https://www.radioshuttle.de/esp32-eco-power/esp32-eco-power-board/) - Radioshuttle.de: [ECO Power Board](https://www.radioshuttle.de/esp32-eco-power/esp32-eco-power-board/)
- WeMos: LoLin32 + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora), - WeMos: LoLin32 + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora),
@ -574,9 +576,9 @@ Send for example `83` `86` as Downlink on Port 2 to get battery status and time/
# License # License
Copyright 2018-2020 Oliver Brandmueller <ob@sysadm.in> Copyright 2018-2022 Oliver Brandmueller <ob@sysadm.in>
Copyright 2018-2020 Klaus Wilting <verkehrsrot@arcor.de> Copyright 2018-2022 Klaus Wilting <verkehrsrot@arcor.de>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -2,6 +2,7 @@
#define _DISPLAY_H #define _DISPLAY_H
#include <libpax_api.h> #include <libpax_api.h>
#include <Wire.h>
#include "cyclic.h" #include "cyclic.h"
#include "qrcode.h" #include "qrcode.h"
#include "power.h" #include "power.h"
@ -9,8 +10,10 @@
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
#include <OneBitDisplay.h> #include <OneBitDisplay.h>
extern ONE_BIT_DISPLAY *dp;
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
#include <TFT_eSPI.h> #include <bb_spi_lcd.h>
extern BB_SPI_LCD *dp;
#endif #endif
#define DISPLAY_PAGES (7) // number of paxcounter display pages #define DISPLAY_PAGES (7) // number of paxcounter display pages
@ -22,7 +25,6 @@
#define MY_FONT_NORMAL FONT_8x8 #define MY_FONT_NORMAL FONT_8x8
#define MY_FONT_LARGE FONT_16x32 #define MY_FONT_LARGE FONT_16x32
#define MY_FONT_STRETCHED FONT_12x16 #define MY_FONT_STRETCHED FONT_12x16
#define MY_DISPLAY_FIRSTLINE 30 #define MY_DISPLAY_FIRSTLINE 30
#ifndef MY_DISPLAY_RST #ifndef MY_DISPLAY_RST
@ -40,33 +42,32 @@
#endif #endif
#ifndef MY_DISPLAY_FGCOLOR #ifndef MY_DISPLAY_FGCOLOR
#define MY_DISPLAY_FGCOLOR OLED_WHITE #define MY_DISPLAY_FGCOLOR 1 // OLED_WHITE
#endif #endif
#ifndef MY_DISPLAY_BGCOLOR #ifndef MY_DISPLAY_BGCOLOR
#define MY_DISPLAY_BGCOLOR OLED_BLACK #define MY_DISPLAY_BGCOLOR 0 // OLED_BLACK
#endif #endif
// settings for TFT display library // settings for TFT display library
#elif (HAS_DISPLAY == 2) #elif (HAS_DISPLAY) == 2
#define MY_FONT_SMALL 1 #define MY_FONT_SMALL 2
#define MY_FONT_NORMAL 2 #define MY_FONT_NORMAL 2
#define MY_FONT_LARGE 4 #define MY_FONT_LARGE 2
#define MY_FONT_STRETCHED 6 #define MY_FONT_STRETCHED 2
#define MY_DISPLAY_FIRSTLINE 30 #define MY_DISPLAY_FIRSTLINE 30
#ifndef TFT_FREQUENCY
#define TFT_FREQUENCY 400000L
#endif
#ifndef MY_DISPLAY_FGCOLOR #ifndef MY_DISPLAY_FGCOLOR
#define MY_DISPLAY_FGCOLOR TFT_WHITE #define MY_DISPLAY_FGCOLOR TFT_YELLOW
#endif #endif
#ifndef MY_DISPLAY_BGCOLOR #ifndef MY_DISPLAY_BGCOLOR
#define MY_DISPLAY_BGCOLOR TFT_BLACK #define MY_DISPLAY_BGCOLOR TFT_BLACK
#endif #endif
#ifndef TOUCH_CS
#define TOUCH_CS NOT_A_PIN
#endif
#endif #endif
// setup display hardware type, default is OLED 128x64 // setup display hardware type, default is OLED 128x64
@ -74,10 +75,6 @@
#define OLED_TYPE OLED_128x64 #define OLED_TYPE OLED_128x64
#endif #endif
#ifndef MY_DISPLAY_INVERT
#define MY_DISPLAY_INVERT 0
#endif
#ifndef MY_DISPLAY_FLIP #ifndef MY_DISPLAY_FLIP
#define MY_DISPLAY_FLIP 0 #define MY_DISPLAY_FLIP 0
#endif #endif
@ -106,18 +103,12 @@ void dp_setup(int contrast = 0);
void dp_refresh(bool nextPage = false); void dp_refresh(bool nextPage = false);
void dp_init(bool verbose = false); void dp_init(bool verbose = false);
void dp_shutdown(void); void dp_shutdown(void);
void dp_message(const char *msg, int line, bool invers);
void dp_drawPage(bool nextpage);
void dp_printf(const char *format, ...);
void dp_setFont(int font, int inv = 0); void dp_setFont(int font, int inv = 0);
void dp_dump(uint8_t *pBuffer = NULL); void dp_dump(uint8_t *pBuffer = NULL);
void dp_setTextCursor(int col = 0, int row = MY_DISPLAY_FIRSTLINE);
void dp_contrast(uint8_t contrast); void dp_contrast(uint8_t contrast);
void dp_clear(void); void dp_clear(void);
void dp_power(uint8_t screenon); void dp_power(uint8_t screenon);
void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message); void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message);
void dp_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
uint8_t bRender);
void dp_scrollHorizontal(uint8_t *buf, const uint16_t width, void dp_scrollHorizontal(uint8_t *buf, const uint16_t width,
const uint16_t height, bool left = true); const uint16_t height, bool left = true);
void dp_scrollVertical(uint8_t *buf, const uint16_t width, void dp_scrollVertical(uint8_t *buf, const uint16_t width,

View File

@ -12,7 +12,10 @@
#include <set> #include <set>
#include <array> #include <array>
#include <algorithm> #include <algorithm>
//#include <bsec.h>
#ifdef HAS_BME680
#include <bsec.h>
#endif
#define _bit(b) (1U << (b)) #define _bit(b) (1U << (b))
#define _bitl(b) (1UL << (b)) #define _bitl(b) (1UL << (b))

View File

@ -2,6 +2,7 @@
#define _I2C_H #define _I2C_H
#include <Arduino.h> #include <Arduino.h>
#include <Wire.h>
#include <BitBang_I2C.h> #include <BitBang_I2C.h>
#include <Wire.h> #include <Wire.h>

View File

@ -1,8 +1,12 @@
#ifndef _LED_H #ifndef _LED_H
#define _LED_H #define _LED_H
//#include <SmartLeds.h> #ifdef RGB_LED_COUNT
//#include "lorawan.h" #include <SmartLeds.h>
#endif
#ifdef HAS_LORA
#include "lorawan.h"
#endif
#ifndef RGB_LED_COUNT #ifndef RGB_LED_COUNT
#define RGB_LED_COUNT 1 #define RGB_LED_COUNT 1

View File

@ -39,7 +39,6 @@
#endif #endif
class PayloadConvert { class PayloadConvert {
public: public:
PayloadConvert(uint8_t size); PayloadConvert(uint8_t size);
~PayloadConvert(); ~PayloadConvert();
@ -59,6 +58,7 @@ public:
void addSensor(uint8_t[]); void addSensor(uint8_t[]);
void addTime(time_t value); void addTime(time_t value);
void addSDS(sdsStatus_t value); void addSDS(sdsStatus_t value);
private: private:
void addChars( char* string, int len); void addChars( char* string, int len);
@ -100,6 +100,6 @@ private:
}; };
extern PayloadConvert payload; extern PayloadConvert payload;
extern uint8_t batt_level; extern int8_t batt_level;
#endif // _PAYLOAD_H_ #endif // _PAYLOAD_H_

View File

@ -20,7 +20,7 @@
#ifndef PMU_CHG_CUTOFF #ifndef PMU_CHG_CUTOFF
#ifdef HAS_PMU #ifdef HAS_PMU
#define PMU_CHG_CUTOFF AXP202_TARGET_VOL_4_2V #define PMU_CHG_CUTOFF XPOWERS_CHG_VOL_4V2
#elif defined HAS_IP5306 #elif defined HAS_IP5306
#define PMU_CHG_CUTOFF 0 #define PMU_CHG_CUTOFF 0
#endif #endif
@ -28,7 +28,7 @@
#ifndef PMU_CHG_CURRENT #ifndef PMU_CHG_CURRENT
#ifdef HAS_PMU #ifdef HAS_PMU
#define PMU_CHG_CURRENT AXP1XX_CHARGE_CUR_450MA #define PMU_CHG_CURRENT XPOWERS_CHG_CUR_450MA
#elif defined HAS_IP5306 #elif defined HAS_IP5306
#define PMU_CHG_CURRENT 2 #define PMU_CHG_CURRENT 2
#endif #endif
@ -55,8 +55,8 @@ void calibrate_voltage(void);
bool batt_sufficient(void); bool batt_sufficient(void);
#ifdef HAS_PMU #ifdef HAS_PMU
#include <axp20x.h> #include <XPowersLib.h>
extern AXP20X_Class pmu; extern XPowersPMU pmu;
enum pmu_power_t { pmu_power_on, pmu_power_off, pmu_power_sleep }; enum pmu_power_t { pmu_power_on, pmu_power_off, pmu_power_sleep };
void AXP192_powerevent_IRQ(void); void AXP192_powerevent_IRQ(void);
void AXP192_power(pmu_power_t powerlevel); void AXP192_power(pmu_power_t powerlevel);
@ -131,6 +131,6 @@ static inline uint8_t linear(uint16_t voltage, uint16_t minVoltage,
(maxVoltage - minVoltage); (maxVoltage - minVoltage);
} }
uint8_t read_battlevel(mapFn_t mapFunction = &sigmoidal); int8_t read_battlevel(mapFn_t mapFunction = &sigmoidal);
#endif #endif

View File

@ -2,7 +2,7 @@
#define _RESET_H #define _RESET_H
#include <driver/rtc_io.h> #include <driver/rtc_io.h>
#include <rom/rtc.h> #include <soc/reset_reasons.h>
#include "i2c.h" #include "i2c.h"
#include "lorawan.h" #include "lorawan.h"

View File

@ -23,7 +23,6 @@
#include <WString.h> #include <WString.h>
class BintrayClient { class BintrayClient {
public: public:
BintrayClient(const String& user, const String& repository, const String& package); BintrayClient(const String& user, const String& repository, const String& package);
String getUser() const; String getUser() const;

0
platformio_orig.ini Normal file
View File

View File

@ -48,7 +48,6 @@ void setBMEIRQ() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); }
// initialize MEMS sensor // initialize MEMS sensor
// return = 0 -> error / return = 1 -> success // return = 0 -> error / return = 1 -> success
int bme_init(void) { int bme_init(void) {
int rc = 0; int rc = 0;
#ifdef HAS_BME680 #ifdef HAS_BME680
@ -77,7 +76,6 @@ int bme_init(void) {
if (rc) if (rc)
bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit
return rc; return rc;
} // bme_init() } // bme_init()
#ifdef HAS_BME680 #ifdef HAS_BME680
@ -108,7 +106,6 @@ int checkIaqSensorStatus(void) {
// store current BME sensor data in struct // store current BME sensor data in struct
void bme_storedata(bmeStatus_t *bme_store) { void bme_storedata(bmeStatus_t *bme_store) {
if (cfg.payloadmask & MEMS_DATA) if (cfg.payloadmask & MEMS_DATA)
#ifdef HAS_BME680 #ifdef HAS_BME680
@ -138,7 +135,6 @@ void bme_storedata(bmeStatus_t *bme_store) {
// bme.readAltitude(SEALEVELPRESSURE_HPA); // bme.readAltitude(SEALEVELPRESSURE_HPA);
bme_store->iaq = 0; // IAQ feature not present with BME280 bme_store->iaq = 0; // IAQ feature not present with BME280
#endif #endif
} // bme_storedata() } // bme_storedata()
#ifdef HAS_BME680 #ifdef HAS_BME680
@ -165,7 +161,6 @@ void updateState(void) {
stateUpdateCounter++; stateUpdateCounter++;
} }
} else { } else {
/* Update every STATE_SAVE_PERIOD minutes */ /* Update every STATE_SAVE_PERIOD minutes */
if ((long)(millis() - stateUpdateCounter * STATE_SAVE_PERIOD) >= 0) { if ((long)(millis() - stateUpdateCounter * STATE_SAVE_PERIOD) >= 0) {
update = true; update = true;

View File

@ -75,7 +75,6 @@ void IRAM_ATTR watchdog() { xTaskResumeFromISR(RestartHandle); }
// used for manually uploading a firmware file via wifi // used for manually uploading a firmware file via wifi
void start_boot_menu(void) { void start_boot_menu(void) {
const char *host = clientId; const char *host = clientId;
const char *ssid = WIFI_SSID; const char *ssid = WIFI_SSID;
const char *password = WIFI_PASS; const char *password = WIFI_PASS;
@ -150,9 +149,7 @@ void start_boot_menu(void) {
// did we get a file name? // did we get a file name?
if (upload.filename != NULL) { if (upload.filename != NULL) {
switch (upload.status) { switch (upload.status) {
case UPLOAD_FILE_START: case UPLOAD_FILE_START:
// start file transfer // start file transfer
ESP_LOGI(TAG, "Uploading %s", upload.filename.c_str()); ESP_LOGI(TAG, "Uploading %s", upload.filename.c_str());
@ -177,7 +174,6 @@ void start_boot_menu(void) {
case UPLOAD_FILE_ABORTED: case UPLOAD_FILE_ABORTED:
default: default:
break; break;
} // switch } // switch
// don't boot to production if update failed // don't boot to production if update failed

View File

@ -26,7 +26,6 @@ static uint8_t buffer[cfgLen + cfgLen2];
// 3. magicByte [cfgLen2 bytes, containing a fixed identifier] // 3. magicByte [cfgLen2 bytes, containing a fixed identifier]
static void defaultConfig(configData_t *myconfig) { static void defaultConfig(configData_t *myconfig) {
strncpy(myconfig->version, PROGVERSION, strncpy(myconfig->version, PROGVERSION,
sizeof(myconfig->version) - 1); // Firmware version sizeof(myconfig->version) - 1); // Firmware version
@ -92,7 +91,6 @@ void saveConfig(bool erase) {
// load configuration from NVRAM into RAM and make it current // load configuration from NVRAM into RAM and make it current
void loadConfig(void) { void loadConfig(void) {
int readBytes = 0; int readBytes = 0;
ESP_LOGI(TAG, "Loading device configuration from NVRAM..."); ESP_LOGI(TAG, "Loading device configuration from NVRAM...");
@ -144,7 +142,6 @@ bool comp(char s1, char s2) { return (tolower(s1) < tolower(s2)); }
// helper function to lexicographically compare two versions. Returns 1 if v2 // helper function to lexicographically compare two versions. Returns 1 if v2
// is smaller, -1 if v1 is smaller, 0 if equal // is smaller, -1 if v1 is smaller, 0 if equal
int version_compare(const String v1, const String v2) { int version_compare(const String v1, const String v2) {
if (v1 == v2) if (v1 == v2)
return 0; return 0;

View File

@ -13,7 +13,6 @@ void setCyclicIRQ() { xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits); }
// do all housekeeping // do all housekeeping
void doHousekeeping() { void doHousekeeping() {
// check if update or maintenance mode trigger switch was set by rcommand // check if update or maintenance mode trigger switch was set by rcommand
if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE)) if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE))
do_reset(true); // warmstart do_reset(true); // warmstart
@ -125,7 +124,6 @@ void doHousekeeping() {
#if (HAS_SDCARD) #if (HAS_SDCARD)
sdcard_flush(); sdcard_flush();
#endif #endif
} // doHousekeeping() } // doHousekeeping()
uint32_t getFreeRAM() { uint32_t getFreeRAM() {

View File

@ -18,41 +18,33 @@ static const char TAG[] = __FILE__;
// triggered by second timepulse to ticker out DCF signal // triggered by second timepulse to ticker out DCF signal
void DCF77_Pulse(uint8_t bit) { void DCF77_Pulse(uint8_t bit) {
TickType_t startTime; TickType_t startTime;
// induce a DCF Pulse // induce a DCF Pulse
for (uint8_t pulseLength = 0; pulseLength <= 2; pulseLength++) { for (uint8_t pulseLength = 0; pulseLength <= 2; pulseLength++) {
startTime = xTaskGetTickCount(); // reference time pulse start startTime = xTaskGetTickCount(); // reference time pulse start
switch (pulseLength) { switch (pulseLength) {
case 0: // 0ms = start of pulse case 0: // 0ms = start of pulse
digitalWrite(HAS_DCF77, dcf_low); digitalWrite(HAS_DCF77, dcf_low);
break; break;
case 1: // 100ms = logic 0 case 1: // 100ms = logic 0
if (bit == 0) if (bit == 0)
digitalWrite(HAS_DCF77, dcf_high); digitalWrite(HAS_DCF77, dcf_high);
break; break;
case 2: // 200ms = logic 1 case 2: // 200ms = logic 1
digitalWrite(HAS_DCF77, dcf_high); digitalWrite(HAS_DCF77, dcf_high);
break; break;
} // switch } // switch
// delay to genrate pulseLength // delay to genrate pulseLength
vTaskDelayUntil(&startTime, pdMS_TO_TICKS(100)); vTaskDelayUntil(&startTime, pdMS_TO_TICKS(100));
} // for } // for
} // DCF77_Pulse() } // DCF77_Pulse()
// helper function to convert decimal to bcd digit // helper function to convert decimal to bcd digit
uint64_t dec2bcd(uint8_t const dec, uint8_t const startpos, uint64_t dec2bcd(uint8_t const dec, uint8_t const startpos,
uint8_t const endpos, uint8_t *parity) { uint8_t const endpos, uint8_t *parity) {
uint8_t data = dec < 10 ? dec : ((dec / 10) << 4) + dec % 10; uint8_t data = dec < 10 ? dec : ((dec / 10) << 4) + dec % 10;
uint64_t bcd = 0; uint64_t bcd = 0;
@ -68,7 +60,6 @@ uint64_t dec2bcd(uint8_t const dec, uint8_t const startpos,
// generates a 1 minute dcf pulse frame for calendar time t // generates a 1 minute dcf pulse frame for calendar time t
uint64_t DCF77_Frame(const struct tm t) { uint64_t DCF77_Frame(const struct tm t) {
uint8_t parity = 0, parity_sum = 0; uint8_t parity = 0, parity_sum = 0;
uint64_t frame = 0; // start with all bits 0 uint64_t frame = 0; // start with all bits 0
@ -105,7 +96,6 @@ uint64_t DCF77_Frame(const struct tm t) {
frame += parity_sum ? set_dcfbit(58) : 0; frame += parity_sum ? set_dcfbit(58) : 0;
return frame; return frame;
} // DCF77_Frame() } // DCF77_Frame()
#endif // HAS_DCF77 #endif // HAS_DCF77

View File

@ -12,8 +12,8 @@ Display-Mask (128 x 64 pixel):
1|PAX:aabbccdd LARGE 1|PAX:aabbccdd LARGE
2| 2|
3|WIFI:abcde BLTH:abcde SMALL 3|WIFI:abcde BLTH:abcde SMALL
4|Batt:abc% chan:ab SMALL 4|Batt:abc% chan:ab SMALL
5|RLIM:abcd Mem:abcdKB SMALL 5|RLIM:abcd Mem:abcdeKB SMALL
6|27.Feb 2019 20:27:00* SMALL 6|27.Feb 2019 20:27:00* SMALL
7|yyyyyyyyyyyyy xx SFab SMALL 7|yyyyyyyyyyyyy xx SFab SMALL
@ -45,67 +45,63 @@ uint8_t DisplayIsOn = 0;
hw_timer_t *displayIRQ = NULL; hw_timer_t *displayIRQ = NULL;
static QRCode qrcode; static QRCode qrcode;
// select display driver
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
static ONE_BIT_DISPLAY oled; ONE_BIT_DISPLAY *dp = NULL;
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
static TFT_eSPI tft = TFT_eSPI(MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT); BB_SPI_LCD *dp = NULL;
#else #else
#error Unknown display type specified in hal file #error Unknown display type specified in hal file
#endif #endif
#endif #endif
void dp_setup(int contrast) { void dp_setup(int contrast) {
#if (HAS_DISPLAY) == 1 // I2C OLED #if (HAS_DISPLAY) == 1 // I2C OLED
oled.setI2CPins(MY_DISPLAY_SDA, MY_DISPLAY_SCL, MY_DISPLAY_RST);
oled.setBitBang(false); dp = new ONE_BIT_DISPLAY;
oled.I2Cbegin(OLED_TYPE, OLED_ADDR, OLED_FREQUENCY); dp->setI2CPins(MY_DISPLAY_SDA, MY_DISPLAY_SCL, MY_DISPLAY_RST);
oled.allocBuffer(); // render all outputs to lib internal backbuffer dp->setBitBang(false);
oled.setTextWrap(false); dp->I2Cbegin(OLED_TYPE, OLED_ADDR, OLED_FREQUENCY);
oled.setRotation( dp->allocBuffer(); // render all outputs to lib internal backbuffer
dp->setTextWrap(false);
dp->setRotation(
MY_DISPLAY_FLIP ? 2 : 0); // 0 = no rotation, 1 = 90°, 2 = 180°, 3 = 280° MY_DISPLAY_FLIP ? 2 : 0); // 0 = no rotation, 1 = 90°, 2 = 180°, 3 = 280°
#elif (HAS_DISPLAY) == 2 // SPI TFT #elif (HAS_DISPLAY) == 2 // TFT LCD
tft.init(); dp = new BB_SPI_LCD;
tft.setRotation(MY_DISPLAY_FLIP ? 3 : 1); dp->begin(TFT_TYPE);
tft.invertDisplay(MY_DISPLAY_INVERT ? true : false); dp->allocBuffer(); // render all outputs to lib internal backbuffer
tft.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR); dp->setRotation(
MY_DISPLAY_FLIP ? 1 : 3); // 0 = no rotation, 1 = 90°, 2 = 180°, 3 = 280°
dp->setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
#endif #endif
// clear display
dp_clear(); dp_clear();
if (contrast) if (contrast)
dp_contrast(contrast); dp_contrast(contrast);
} }
void dp_init(bool verbose) { void dp_init(bool verbose) {
dp_setup(DISPLAYCONTRAST); dp_setup(DISPLAYCONTRAST);
// show chip information
if (verbose) { if (verbose) {
// show startup screen
// to come -> display .bmp file with logo
// show chip information
#if (VERBOSE) #if (VERBOSE)
esp_chip_info_t chip_info; esp_chip_info_t chip_info;
esp_chip_info(&chip_info); esp_chip_info(&chip_info);
dp_setFont(MY_FONT_NORMAL); dp_setFont(MY_FONT_NORMAL);
dp_printf("** PAXCOUNTER **\r\n"); dp->printf("** PAXCOUNTER **\r\n");
dp_printf("Software v%s\r\n", PROGVERSION); dp->printf("Software v%s\r\n", PROGVERSION);
dp_printf("ESP32 %d cores\r\n", chip_info.cores); dp->printf("ESP32 %d cores\r\n", chip_info.cores);
dp_printf("Chip Rev.%d\r\n", chip_info.revision); dp->printf("Chip Rev.%d\r\n", chip_info.revision);
dp_printf("WiFi%s%s\r\n", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", dp->printf("WiFi%s%s\r\n",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024), (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext."); dp->printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext.");
// give user some time to read or take picture
dp_dump(); dp_dump();
delay(2000); delay(2000);
dp_clear(); dp_clear();
@ -125,11 +121,11 @@ void dp_init(bool verbose) {
// display DEVEUI as plain text on the right // display DEVEUI as plain text on the right
const int x_offset = QR_SCALEFACTOR * 29 + 14; const int x_offset = QR_SCALEFACTOR * 29 + 14;
dp_setFont(MY_FONT_NORMAL); dp_setFont(MY_FONT_NORMAL);
dp_setTextCursor(x_offset, 0); dp->setCursor(x_offset, 0);
dp_printf("DEVEUI:\r\n"); dp->printf("DEVEUI:\r\n");
for (uint8_t i = 0; i <= 3; i++) { for (uint8_t i = 0; i <= 3; i++) {
dp_setTextCursor(x_offset, i * 8 + 20); dp->setCursor(x_offset, i * 8 + 20);
dp_printf("%4.4s", deveui + i * 4); dp->printf("%4.4s", deveui + i * 4);
} }
// give user some time to read or take picture // give user some time to read or take picture
@ -139,17 +135,22 @@ void dp_init(bool verbose) {
#endif #endif
#endif // HAS_LORA #endif // HAS_LORA
} // verbose
} // verbose
dp_power(cfg.screenon); // set display off if disabled dp_power(cfg.screenon); // set display off if disabled
} // dp_init } // dp_init
// write display content to display buffer
// nextpage = true -> flip 1 page
void dp_refresh(bool nextPage) { void dp_refresh(bool nextPage) {
struct count_payload_t count; // libpax count storage
static uint8_t DisplayPage = 0;
char timeState, strftime_buf[64];
time_t now;
struct tm timeinfo = {0};
#ifndef HAS_BUTTON #ifndef HAS_BUTTON
static uint32_t framecounter = 0; static uint32_t framecounter = 0;
const uint32_t flip_threshold = DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS;
#endif #endif
// if display is switched off we don't refresh it to relax cpu // if display is switched off we don't refresh it to relax cpu
@ -164,103 +165,80 @@ void dp_refresh(bool nextPage) {
#ifndef HAS_BUTTON #ifndef HAS_BUTTON
// auto flip page if we are in unattended mode // auto flip page if we are in unattended mode
if ((++framecounter) > (DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS)) { if (++framecounter > flip_threshold) {
framecounter = 0; framecounter = 0;
nextPage = true; nextPage = true;
} }
#endif #endif
dp_drawPage(nextPage); if (nextPage) {
} // refreshDisplay()
void dp_drawPage(bool nextpage) {
// write display content to display buffer
// nextpage = true -> flip 1 page
struct count_payload_t count; // libpax count storage
static uint8_t DisplayPage = 0;
char timeState, strftime_buf[64];
time_t now;
struct tm timeinfo = {0};
if (nextpage) {
DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1); DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
dp_clear(); dp_clear();
} } else
dp->setCursor(0, 0);
// update counter values from libpax
libpax_counter_count(&count);
// cursor home
dp_setTextCursor(0, 0);
// line 1/2: pax counter
// display number of unique macs total Wifi + BLE
if (DisplayPage < 3) {
dp_setFont(MY_FONT_LARGE);
dp_printf("%-8d", count.pax);
}
switch (DisplayPage) { switch (DisplayPage) {
// page 0: pax + parameters overview
// page 0: parameters overview // page 1: pax + lorawan parameters
// page 1: lorawan parameters // page 2: pax + GPS lat/lon
// page 2: GPS // page 3: BME280/680 values
// page 3: BME280/680 // page 4: timeofday
// page 4: time
// page 5: pax graph // page 5: pax graph
// page 6: blank screen // page 6: blank screen
// ---------- page 0: parameters overview ---------- // ---------- page 0: parameters overview ----------
case 0: case 0:
// show pax
libpax_counter_count(&count);
dp_setFont(MY_FONT_LARGE);
dp->printf("%-8u", count.pax);
dp_setFont(MY_FONT_SMALL); dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(); dp->setCursor(0, MY_DISPLAY_FIRSTLINE);
// line 3: wifi + bluetooth counters // line 3: wifi + bluetooth counters
// WIFI:abcde BLTH:abcde // WIFI:abcde BLTH:abcde
#if ((WIFICOUNTER) && (BLECOUNTER)) #if ((WIFICOUNTER) && (BLECOUNTER))
if (cfg.wifiscan) if (cfg.wifiscan)
dp_printf("WIFI:%-5d", count.wifi_count); dp->printf("WIFI:%-5u", count.wifi_count);
else else
dp_printf("WIFI:off"); dp->printf("WIFI:off ");
if (cfg.blescan) if (cfg.blescan)
dp_printf("BLTH:%-5d", count.ble_count); dp->printf("BLTH:%-5u", count.ble_count);
else else
dp_printf(" BLTH:off"); dp->printf(" BLTH:off");
#elif ((WIFICOUNTER) && (!BLECOUNTER)) #elif ((WIFICOUNTER) && (!BLECOUNTER))
if (cfg.wifiscan) if (cfg.wifiscan)
dp_printf("WIFI:%-5d", count.wifi_count); dp->printf("WIFI:%-5u", count.wifi_count);
else else
dp_printf("WIFI:off"); dp->printf("WIFI:off ");
#elif ((!WIFICOUNTER) && (BLECOUNTER)) #elif ((!WIFICOUNTER) && (BLECOUNTER))
if (cfg.blescan) if (cfg.blescan)
dp_printf("BLTH:%-5d", count.ble_count); dp->printf("BLTH:%-5u", count.ble_count);
dp_printf("BLTH:off"); dp->printf("BLTH:off");
#else #else
dp_printf("Sniffer disabled"); dp->printf("Sniffer disabled");
#endif #endif
dp_printf("\r\n"); dp->printf("\r\n");
// line 4: Battery + GPS status + Wifi channel // line 4: Battery + GPS status + Wifi channel
// B:a.bcV Sats:ab ch:ab // B:a.bcV Sats:ab ch:ab
#if (defined BAT_MEASURE_ADC || defined HAS_PMU || defined HAS_IP5306) #if (defined BAT_MEASURE_ADC || defined HAS_PMU || defined HAS_IP5306)
if (batt_level == 0) if (batt_level > 0)
dp_printf("No batt "); dp->printf("Batt:%3u%% ", batt_level);
else else
dp_printf("Batt:%3u%% ", batt_level); dp->printf("No batt ");
#else #else
dp_printf(" "); dp->printf(" ");
#endif #endif
dp_printf("chan:%02u\r\n", channel); dp->printf("chan:%02u\r\n", channel);
// line 5: RSSI limiter + free memory // line 5: RSSI limiter + free memory
// RLIM:abcd Mem:abcdKB // RLIM:abcd Mem:abcdKB
dp_printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); dp->printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
dp_printf(" Mem:%4dKB\r\n", getFreeRAM() / 1024); dp->printf(" Mem:%uKB\r\n", getFreeRAM() / 1024);
// line 6: time + date // line 6: time + date
// Wed Jan 12 21:49:08 * // Wed Jan 12 21:49:08 *
@ -270,15 +248,15 @@ void dp_drawPage(bool nextpage) {
time(&now); time(&now);
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
dp_printf("%.20s", strftime_buf); dp->printf("%.20s", strftime_buf);
// display inverse timeState if clock controller is enabled // display inverse timeState if clock controller is enabled
#if (defined HAS_DCF77) || (defined HAS_IF482) #if (defined HAS_DCF77) || (defined HAS_IF482)
dp_setFont(MY_FONT_SMALL, 1); dp_setFont(MY_FONT_SMALL, 1);
dp_printf("%c\r\n", timeState); dp->printf("%c\r\n", timeState);
dp_setFont(MY_FONT_SMALL, 0); dp_setFont(MY_FONT_SMALL, 0);
#else #else
dp_printf("%c\r\n", timeState); dp->printf("%c\r\n", timeState);
#endif #endif
#endif // TIME_SYNC_INTERVAL #endif // TIME_SYNC_INTERVAL
@ -287,10 +265,10 @@ void dp_drawPage(bool nextpage) {
#if (HAS_LORA) #if (HAS_LORA)
// LMiC event display // LMiC event display
dp_printf("%-16s ", lmic_event_msg); dp->printf("%-16s ", lmic_event_msg);
// LORA datarate, display inverse if ADR disabled // LORA datarate, display inverse if ADR disabled
dp_setFont(MY_FONT_SMALL, !cfg.adrmode); dp_setFont(MY_FONT_SMALL, !cfg.adrmode);
dp_printf("%-4s", getSfName(updr2rps(LMIC.datarate))); dp->printf("%-4s", getSfName(updr2rps(LMIC.datarate)));
dp_setFont(MY_FONT_SMALL, 0); dp_setFont(MY_FONT_SMALL, 0);
#endif // HAS_LORA #endif // HAS_LORA
@ -308,19 +286,26 @@ void dp_drawPage(bool nextpage) {
// 6|fUp:000000 fDn:000000 // 6|fUp:000000 fDn:000000
// 7|SNR:-0000 RSSI:-0000 // 7|SNR:-0000 RSSI:-0000
// show pax
libpax_counter_count(&count);
dp_setFont(MY_FONT_LARGE);
dp->printf("%-8u", count.pax);
dp_setFont(MY_FONT_SMALL); dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(); dp->setCursor(0, MY_DISPLAY_FIRSTLINE);
dp_printf("Net:%06X Pwr:%-2d\r\n", LMIC.netid & 0x001FFFFF, LMIC.radio_txpow); dp->printf("Net:%06X Pwr:%2u\r\n", LMIC.netid & 0x001FFFFF,
dp_printf("Dev:%08X DR:%1d\r\n", LMIC.devaddr, LMIC.datarate); LMIC.radio_txpow);
dp_printf("ChMsk:%04X Nonce:%04X\r\n", LMIC.channelMap, LMIC.devNonce); dp->printf("Dev:%08X DR:%1u\r\n", LMIC.devaddr, LMIC.datarate);
dp_printf("fUp:%-6d fDn:%-6d\r\n", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0, dp->printf("ChMsk:%04X Nonce:%04X\r\n", LMIC.channelMap, LMIC.devNonce);
LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0); dp->printf("fUp:%-6u fDn:%-6u\r\n", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
dp_printf("SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi); LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0);
dp->printf("SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi);
dp_dump(); dp_dump();
break; break;
#else // flip page if we are unattended #else // skip this page
DisplayPage++; DisplayPage++;
break;
#endif // HAS_LORA #endif // HAS_LORA
// ---------- page 2: GPS ---------- // ---------- page 2: GPS ----------
@ -328,23 +313,29 @@ void dp_drawPage(bool nextpage) {
#if (HAS_GPS) #if (HAS_GPS)
// show pax
libpax_counter_count(&count);
dp_setFont(MY_FONT_LARGE);
dp->printf("%-8u", count.pax);
// show satellite status at bottom line // show satellite status at bottom line
dp_setFont(MY_FONT_SMALL); dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(0, 56); dp->setCursor(0, 56);
dp_printf("%u Sats", gps.satellites.value()); dp->printf("%u Sats", gps.satellites.value());
dp_printf(gps_hasfix() ? " " : " - No fix"); dp->printf(gps_hasfix() ? " " : " - No fix");
// show latitude and longitude // show latitude and longitude
dp_setFont(MY_FONT_STRETCHED); dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(); dp->setCursor(0, MY_DISPLAY_FIRSTLINE);
dp_printf("%c%09.6f\r\n", gps.location.rawLat().negative ? 'S' : 'N', dp->printf("%c%09.6f\r\n", gps.location.rawLat().negative ? 'S' : 'N',
gps.location.lat()); gps.location.lat());
dp_printf("%c%09.6f", gps.location.rawLng().negative ? 'W' : 'E', dp->printf("%c%09.6f", gps.location.rawLng().negative ? 'W' : 'E',
gps.location.lng()); gps.location.lng());
dp_dump(); dp_dump();
break; break;
#else // flip page if we are unattended #else // skip this page
DisplayPage++; DisplayPage++;
break;
#endif #endif
// ---------- page 3: BME280/680 ---------- // ---------- page 3: BME280/680 ----------
@ -352,34 +343,35 @@ void dp_drawPage(bool nextpage) {
#if (HAS_BME) #if (HAS_BME)
dp_setFont(MY_FONT_STRETCHED); dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 0); dp->setCursor(0, 0);
dp_printf("TMP: %-6.1f\r\n", bme_status.temperature); dp->printf("TMP: %-6.1f\r\n", bme_status.temperature);
dp_printf("HUM: %-6.1f\r\n", bme_status.humidity); dp->printf("HUM: %-6.1f\r\n", bme_status.humidity);
dp_printf("PRE: %-6.1f\r\n", bme_status.pressure); dp->printf("PRE: %-6.1f\r\n", bme_status.pressure);
#ifdef HAS_BME680 #ifdef HAS_BME680
dp_printf("IAQ: %-6.0f", bme_status.iaq); dp->printf("IAQ: %-6.0f", bme_status.iaq);
#endif #endif
dp_dump(); dp_dump();
break; // page 3 break;
#else // flip page if we are unattended #else // skip this page
DisplayPage++; DisplayPage++;
#endif // HAS_BME break;
#endif // HAS_BME
// ---------- page 4: time ---------- // ---------- page 4: time ----------
case 4: case 4:
time(&now); time(&now);
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%T", &timeinfo);
dp_setFont(MY_FONT_STRETCHED); dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 0); dp->setCursor(0, 0);
dp_printf("Timeofday:"); dp->printf("Timeofday:");
dp_setTextCursor(0, 26); dp->setCursor(0, 26);
dp_setFont(MY_FONT_LARGE); dp_setFont(MY_FONT_LARGE);
dp_printf("%.8s\r\n", strftime_buf); strftime(strftime_buf, sizeof(strftime_buf), "%T", &timeinfo);
dp->printf("%.8s\r\n", strftime_buf);
dp_setFont(MY_FONT_SMALL); dp_setFont(MY_FONT_SMALL);
dp_printf("%21.1f", uptime() / 1000.0); dp->printf("%-12.1f", uptime() / 1000.0);
dp_dump(); dp_dump();
break; break;
@ -397,115 +389,38 @@ void dp_drawPage(bool nextpage) {
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
dp_clear(); dp_clear();
break; break;
#else // flip page if we are unattended #else // skip this page
DisplayPage++; DisplayPage++;
break;
#endif #endif
} // switch (page) } // switch (page)
} // dp_drawPage } // dp_refresh
// ------------- display helper functions ----------------- // ------------- display helper functions -----------------
void dp_setTextCursor(int x, int y) {
#if (HAS_DISPLAY) == 1
oled.setCursor(x, y);
#elif (HAS_DISPLAY) == 2
tft.setCursor(x, y);
#endif
}
void dp_setFont(int font, int inv) { void dp_setFont(int font, int inv) {
dp->setFont(font);
#if (HAS_DISPLAY) == 1
// handle invers printing
if (inv) if (inv)
oled.setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR); dp->setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR);
else else
oled.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR); dp->setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
// set desired font
oled.setFont(font);
#elif (HAS_DISPLAY) == 2
// handle invers printing
if (inv)
tft.setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR);
else
tft.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
// map desired oled font to tft font
switch (font) {
case MY_FONT_STRETCHED: // 16x16 on OLED
case MY_FONT_LARGE: // 16x32 on OLED
tft.setTextFont(4); // 26px
break;
case MY_FONT_SMALL: // 6x8 on OLED
case MY_FONT_NORMAL: // 8x8 on OLED
default:
tft.setTextFont(2); // 16px
break;
}
#endif
}
void dp_printf(const char *format, ...) {
char loc_buf[64];
char *temp = loc_buf;
va_list arg;
va_list copy;
va_start(arg, format);
va_copy(copy, arg);
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
va_end(copy);
if (len < 0) {
va_end(arg);
return;
};
if (len >= sizeof(loc_buf)) {
temp = (char *)malloc(len + 1);
if (temp == NULL) {
va_end(arg);
return;
}
vsnprintf(temp, len + 1, format, arg);
}
va_end(arg);
#if (HAS_DISPLAY) == 1
oled.write(temp);
#elif (HAS_DISPLAY) == 2
tft.printf(temp);
#endif
if (temp != loc_buf) {
free(temp);
}
} }
void dp_dump(uint8_t *pBuffer) { void dp_dump(uint8_t *pBuffer) {
#if (HAS_DISPLAY) == 1
if (pBuffer) if (pBuffer)
memcpy(oled.getBuffer(), pBuffer, PLOTBUFFERSIZE); memcpy(dp->getBuffer(), pBuffer, PLOTBUFFERSIZE);
oled.display(); dp->display();
#elif (HAS_DISPLAY) == 2
if (pBuffer)
tft.drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT,
MY_DISPLAY_FGCOLOR);
#endif
} }
void dp_clear(void) { void dp_clear(void) {
#if (HAS_DISPLAY) == 1 dp->fillScreen(MY_DISPLAY_BGCOLOR);
oled.fillScreen(MY_DISPLAY_BGCOLOR); dp->display();
oled.display(); dp->setCursor(0, 0);
#elif (HAS_DISPLAY) == 2
tft.fillScreen(MY_DISPLAY_BGCOLOR);
#endif
dp_setTextCursor(0, 0);
} }
void dp_contrast(uint8_t contrast) { void dp_contrast(uint8_t contrast) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
oled.setContrast(contrast); dp->setContrast(contrast);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// to do: gamma correction for TFT // to do: gamma correction for TFT
#endif #endif
@ -513,7 +428,7 @@ void dp_contrast(uint8_t contrast) {
void dp_power(uint8_t screenon) { void dp_power(uint8_t screenon) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
oled.setPower(screenon); dp->setPower(screenon);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// to come // to come
#endif #endif
@ -521,21 +436,13 @@ void dp_power(uint8_t screenon) {
void dp_shutdown(void) { void dp_shutdown(void) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
oled.setPower(false); dp->setPower(false);
delay(DISPLAYREFRESH_MS / 1000 * 1.1); delay(DISPLAYREFRESH_MS / 1000 * 1.1);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// to come // to come
#endif #endif
} }
// print static message on display
void dp_message(const char *msg, int line, bool invers) {
dp_setFont(MY_FONT_SMALL, invers ? 1 : 0);
dp_setTextCursor(0, line * 8);
dp_printf("%-16s", msg);
dp_dump();
} // dp_message
// ------------- QR code plotter ----------------- // ------------- QR code plotter -----------------
void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) { void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) {
@ -546,35 +453,26 @@ void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) {
for (uint8_t y = 0; y < qrcode.size; y++) for (uint8_t y = 0; y < qrcode.size; y++)
for (uint8_t x = 0; x < qrcode.size; x++) for (uint8_t x = 0; x < qrcode.size; x++)
if (!qrcode_getModule(&qrcode, x, y)) // "black" if (!qrcode_getModule(&qrcode, x, y)) // "black"
dp_fillRect(x * QR_SCALEFACTOR + offset_x, dp->fillRect(x * QR_SCALEFACTOR + offset_x,
y * QR_SCALEFACTOR + offset_y, QR_SCALEFACTOR, y * QR_SCALEFACTOR + offset_y, QR_SCALEFACTOR,
QR_SCALEFACTOR, false); QR_SCALEFACTOR, MY_DISPLAY_FGCOLOR);
// draw horizontal frame lines // draw horizontal frame lines
dp_fillRect(0, 0, qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y, dp->fillRect(0, 0, qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y,
false); MY_DISPLAY_FGCOLOR);
dp_fillRect(0, qrcode.size * QR_SCALEFACTOR + offset_y, dp->fillRect(0, qrcode.size * QR_SCALEFACTOR + offset_y,
qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y, false); qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y,
MY_DISPLAY_FGCOLOR);
// draw vertical frame lines // draw vertical frame lines
dp_fillRect(0, 0, offset_x, qrcode.size * QR_SCALEFACTOR + 2 * offset_y, dp->fillRect(0, 0, offset_x, qrcode.size * QR_SCALEFACTOR + 2 * offset_y,
false); MY_DISPLAY_FGCOLOR);
dp_fillRect(qrcode.size * QR_SCALEFACTOR + offset_x, 0, offset_x, dp->fillRect(qrcode.size * QR_SCALEFACTOR + offset_x, 0, offset_x,
qrcode.size * QR_SCALEFACTOR + 2 * offset_y, false); qrcode.size * QR_SCALEFACTOR + 2 * offset_y, MY_DISPLAY_FGCOLOR);
} }
// ------------- graphics primitives ----------------- // ------------- graphics primitives -----------------
void dp_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
uint8_t bRender) {
#if (HAS_DISPLAY) == 1
oled.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR);
#elif (HAS_DISPLAY) == 2
tft.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR);
#endif
}
int dp_drawPixel(uint8_t *buf, const uint16_t x, const uint16_t y, int dp_drawPixel(uint8_t *buf, const uint16_t x, const uint16_t y,
const uint8_t dot) { const uint8_t dot) {
if (x > MY_DISPLAY_WIDTH || y > MY_DISPLAY_HEIGHT) if (x > MY_DISPLAY_WIDTH || y > MY_DISPLAY_HEIGHT)
return -1; return -1;
@ -592,7 +490,6 @@ int dp_drawPixel(uint8_t *buf, const uint16_t x, const uint16_t y,
void dp_scrollHorizontal(uint8_t *buf, const uint16_t width, void dp_scrollHorizontal(uint8_t *buf, const uint16_t width,
const uint16_t height, bool left) { const uint16_t height, bool left) {
uint16_t col, page, idx = 0; uint16_t col, page, idx = 0;
for (page = 0; page < height / 8; page++) { for (page = 0; page < height / 8; page++) {
@ -615,7 +512,6 @@ void dp_scrollHorizontal(uint8_t *buf, const uint16_t width,
void dp_scrollVertical(uint8_t *buf, const uint16_t width, void dp_scrollVertical(uint8_t *buf, const uint16_t width,
const uint16_t height, int offset) { const uint16_t height, int offset) {
uint64_t buf_col; uint64_t buf_col;
if (!offset) if (!offset)
@ -638,7 +534,6 @@ void dp_scrollVertical(uint8_t *buf, const uint16_t width,
// ------------- curve plotter ----------------- // ------------- curve plotter -----------------
void dp_plotCurve(uint16_t count, bool reset) { void dp_plotCurve(uint16_t count, bool reset) {
static uint16_t last_count = 0, col = 0, row = 0; static uint16_t last_count = 0, col = 0, row = 0;
uint16_t v_scroll = 0; uint16_t v_scroll = 0;

View File

@ -87,7 +87,6 @@ byte CFG_CFG[] = {
// helper functions to send UBX commands to ublox gps chip // helper functions to send UBX commands to ublox gps chip
void sendPacket(byte *packet, byte len) { void sendPacket(byte *packet, byte len) {
uint8_t CK_A = 0; uint8_t CK_A = 0;
uint8_t CK_B = 0; uint8_t CK_B = 0;
@ -107,7 +106,6 @@ void restoreDefaults() { sendPacket(CFG_CFG, sizeof(CFG_CFG)); }
void changeBaudrate() { sendPacket(CFG_PRT, sizeof(CFG_PRT)); } void changeBaudrate() { sendPacket(CFG_PRT, sizeof(CFG_PRT)); }
void disableNmea() { void disableNmea() {
// tinygps++ processes only $GPGGA/$GNGGA and $GPRMC/$GNRMC // tinygps++ processes only $GPGGA/$GNGGA and $GPRMC/$GNRMC
// thus, we disable all other NMEA messages // thus, we disable all other NMEA messages
@ -128,7 +126,6 @@ void disableNmea() {
// initialize and configure GPS // initialize and configure GPS
int gps_init(void) { int gps_init(void) {
ESP_LOGI(TAG, "Opening serial GPS"); ESP_LOGI(TAG, "Opening serial GPS");
GPS_Serial.begin(GPS_SERIAL); GPS_Serial.begin(GPS_SERIAL);
@ -144,7 +141,6 @@ int gps_init(void) {
disableNmea(); disableNmea();
return 1; return 1;
} // gps_init() } // gps_init()
// store current GPS location data in struct // store current GPS location data in struct
@ -170,13 +166,11 @@ bool gps_hasfix() {
// function to poll UTC time from GPS NMEA data; note: this is costly // function to poll UTC time from GPS NMEA data; note: this is costly
time_t get_gpstime(uint16_t *msec = 0) { time_t get_gpstime(uint16_t *msec = 0) {
const uint16_t txDelay = const uint16_t txDelay =
70U * 1000 / (GPS_BAUDRATE / 9); // serial tx of 70 NMEA chars 70U * 1000 / (GPS_BAUDRATE / 9); // serial tx of 70 NMEA chars
// did we get a current date & time? // did we get a current date & time?
if (gps.time.age() < 1000) { if (gps.time.age() < 1000) {
// convert tinygps time format to struct tm format // convert tinygps time format to struct tm format
struct tm gps_tm = {0}; struct tm gps_tm = {0};
gps_tm.tm_sec = gps.time.second(); gps_tm.tm_sec = gps.time.second();
@ -209,18 +203,15 @@ time_t get_gpstime(uint16_t *msec = 0) {
ESP_LOGD(TAG, "no valid GPS time"); ESP_LOGD(TAG, "no valid GPS time");
return 0; return 0;
} // get_gpstime() } // get_gpstime()
// GPS serial feed FreeRTos Task // GPS serial feed FreeRTos Task
void gps_loop(void *pvParameters) { void gps_loop(void *pvParameters) {
_ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check _ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
// feed GPS decoder with serial NMEA data from GPS device // feed GPS decoder with serial NMEA data from GPS device
while (1) { while (1) {
while (cfg.payloadmask & GPS_DATA) { while (cfg.payloadmask & GPS_DATA) {
while (GPS_Serial.available()) while (GPS_Serial.available())
gps.encode(GPS_Serial.read()); gps.encode(GPS_Serial.read());
@ -228,7 +219,6 @@ void gps_loop(void *pvParameters) {
} }
delay(1000); delay(1000);
} // infinite while loop } // infinite while loop
} // gps_loop() } // gps_loop()
#endif // HAS_GPS #endif // HAS_GPS

0
src/hal/m5core.h Normal file
View File

0
src/hal/m5fire.h Normal file
View File

0
src/hal/ttgobeam10.h Normal file
View File

View File

@ -2,54 +2,23 @@
// upload_speed 1500000 // upload_speed 1500000
// board ESP32-S3-DevKitC-1 // board ESP32-S3-DevKitC-1
#ifndef _TTGOTDISPLAY_H #ifndef _TTGOTDISPLAYS3_H
#define _TTGOTDISPLAY_H #define _TTGOTDISPLAYS3_H
#include <stdint.h> #include <stdint.h>
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #define HAS_LED NOT_A_PIN
#define HAS_BUTTON 14 // on board button (right side)
//#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet
#define MY_DISPLAY_FLIP 1 // use if display is rotated
#define HAS_LED NOT_A_PIN // no on board LED (?)
#define HAS_BUTTON (14) // on board button A
// power management settings // power management settings
//#define BAT_MEASURE_ADC ADC1_GPIO34_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_6 //#define BAT_MEASURE_ADC ADC1_GPIO4_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_6
//#define BAT_VOLTAGE_DIVIDER 2.605f // voltage divider //#define BAT_VOLTAGE_DIVIDER 2.605f // voltage divider
// Display Settings // Display Settings
#define MY_DISPLAY_WIDTH 135 #define HAS_DISPLAY 2 // TFT-LCD parallel
#define MY_DISPLAY_HEIGHT 240 #define TFT_TYPE DISPLAY_T_DISPLAY_S3
#define MY_DISPLAY_INVERT 1 #define MY_DISPLAY_FLIP 1 // use if display is rotated
#define MY_DISPLAY_WIDTH 172
#define MY_DISPLAY_HEIGHT 320
// setting for TTGO T-display #endif
#define USER_SETUP_LOADED 1
#define ST7789_DRIVER 1
#define CGRAM_OFFSET
#define TFT_CS GPIO_NUM_6 // Chip select control
#define TFT_DC GPIO_NUM_7 // Data Command control
#define TFT_RST GPIO_NUM_5 // Reset
#define TFT_BL GPIO_NUM_38 // LED back-light
#define TOUCH_CS NOT_A_PIN
#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
#define SMOOTH_FONT
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 6000000
#endif

0
src/hal/ttgotwristband.h Normal file
View File

View File

@ -15,7 +15,6 @@ void i2c_init(void) {
void i2c_deinit(void) { Wire.end(); } void i2c_deinit(void) { Wire.end(); }
void i2c_scan(void) { void i2c_scan(void) {
// parts of the code in this function were taken from: // parts of the code in this function were taken from:
// //
// Copyright (c) 2019 BitBank Software, Inc. // Copyright (c) 2019 BitBank Software, Inc.
@ -78,7 +77,6 @@ void i2c_scan(void) {
// functions for i2c r/w access, mutexing is done by Wire.cpp // functions for i2c r/w access, mutexing is done by Wire.cpp
int i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) { int i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
uint8_t ret = 0; uint8_t ret = 0;
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
Wire.write(reg); Wire.write(reg);
@ -100,7 +98,6 @@ finish:
} }
int i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) { int i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
uint8_t ret = 0; uint8_t ret = 0;
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
Wire.write(reg); Wire.write(reg);
@ -110,4 +107,4 @@ int i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
ret = Wire.endTransmission(); ret = Wire.endTransmission();
return ret ? ret : 0xFF; return ret ? ret : 0xFF;
} }

View File

@ -85,7 +85,6 @@ not evaluated by model BU-190, use "F" instead for this model
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
String IF482_Frame(time_t t) { String IF482_Frame(time_t t) {
char mon, out[IF482_FRAME_SIZE + 1], buf[IF482_FRAME_SIZE - 3]; char mon, out[IF482_FRAME_SIZE + 1], buf[IF482_FRAME_SIZE - 3];
if (sntp_get_sync_status() == SNTP_SYNC_STATUS_IN_PROGRESS) if (sntp_get_sync_status() == SNTP_SYNC_STATUS_IN_PROGRESS)

View File

@ -7,7 +7,6 @@ TaskHandle_t irqHandlerTask = NULL;
// irq handler task, handles all our application level interrupts // irq handler task, handles all our application level interrupts
void irqHandler(void *pvParameters) { void irqHandler(void *pvParameters) {
_ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check _ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
uint32_t irqSource; uint32_t irqSource;

View File

@ -158,7 +158,6 @@ void ledLoop(void *parameter) {
} }
// No custom blink, check LoRaWAN state // No custom blink, check LoRaWAN state
} else { } else {
#if (HAS_LORA) #if (HAS_LORA)
// LED indicators for viusalizing LoRaWAN state // LED indicators for viusalizing LoRaWAN state
if (LMIC.opmode & (OP_JOINING | OP_REJOIN)) { if (LMIC.opmode & (OP_JOINING | OP_REJOIN)) {

View File

@ -70,7 +70,6 @@ void refreshTheMatrixDisplay(bool nextPage) {
} }
switch (DisplayPage % MATRIX_DISPLAY_PAGES) { switch (DisplayPage % MATRIX_DISPLAY_PAGES) {
// page 0: number of current pax OR footfall line diagram // page 0: number of current pax OR footfall line diagram
// page 1: time of day // page 1: time of day
@ -89,18 +88,14 @@ void refreshTheMatrixDisplay(bool nextPage) {
} }
else { // cyclic counter mode -> plot a line diagram else { // cyclic counter mode -> plot a line diagram
if (ulLastNumMacs != count.pax) { if (ulLastNumMacs != count.pax) {
// next count cycle? // next count cycle?
if (count.pax == 0) { if (count.pax == 0) {
// matrix full? then scroll left 1 dot, else increment column // matrix full? then scroll left 1 dot, else increment column
if (col < (LED_MATRIX_WIDTH - 1)) if (col < (LED_MATRIX_WIDTH - 1))
col++; col++;
else else
ScrollMatrixLeft(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT); ScrollMatrixLeft(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT);
} else } else
matrix.drawPoint(col, row, 0); // clear current dot matrix.drawPoint(col, row, 0); // clear current dot
@ -124,7 +119,6 @@ void refreshTheMatrixDisplay(bool nextPage) {
// DrawNumber(myTZ.dateTime("H:i:s").c_str()); // DrawNumber(myTZ.dateTime("H:i:s").c_str());
} }
break; break;
} // switch page } // switch page
matrix.scan(); matrix.scan();

View File

@ -14,7 +14,6 @@
*********************************************************************/ *********************************************************************/
void setABPParameters() { void setABPParameters() {
/** ************************************************************** /** **************************************************************
* ************************************************************* */ * ************************************************************* */
#if defined(CFG_eu868) #if defined(CFG_eu868)

View File

@ -21,18 +21,17 @@ TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer for LMIC event message char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer for LMIC event message
class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t { class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {
public: public:
MyHalConfig_t(){}; MyHalConfig_t(){};
// set SPI pins to board configuration, pins may come from pins_arduino.h // set SPI pins to board configuration, pins may come from pins_arduino.h
virtual void begin(void) override { void begin(void) override {
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
} }
// virtual void end(void) override // void end(void) override
// virtual ostime_t setModuleActive(bool state) override // ostime_t setModuleActive(bool state) override
}; };
static MyHalConfig_t myHalConfig{}; static MyHalConfig_t myHalConfig{};
@ -50,9 +49,7 @@ static const lmic_pinmap myPinmap = {
.pConfig = &myHalConfig}; .pConfig = &myHalConfig};
void lora_setupForNetwork(bool preJoin) { void lora_setupForNetwork(bool preJoin) {
if (preJoin) { if (preJoin) {
#if CFG_LMIC_US_like #if CFG_LMIC_US_like
// in the US, with TTN, it saves join time if we start on subband 1 // in the US, with TTN, it saves join time if we start on subband 1
// (channels 8-15). This will get overridden after the join by // (channels 8-15). This will get overridden after the join by
@ -196,7 +193,6 @@ void lora_send(void *pvParameters) {
MessageBuffer_t SendBuffer; MessageBuffer_t SendBuffer;
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));
@ -213,7 +209,6 @@ void lora_send(void *pvParameters) {
switch (LMIC_setTxData2_strict(SendBuffer.MessagePort, SendBuffer.Message, switch (LMIC_setTxData2_strict(SendBuffer.MessagePort, SendBuffer.Message,
SendBuffer.MessageSize, SendBuffer.MessageSize,
(cfg.countermode & 0x02))) { (cfg.countermode & 0x02))) {
case LMIC_ERROR_SUCCESS: case LMIC_ERROR_SUCCESS:
#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
@ -237,7 +232,6 @@ void lora_send(void *pvParameters) {
break; break;
default: // other LMIC return code default: // other LMIC return code
ESP_LOGE(TAG, "LMIC error, message not sent and deleted"); ESP_LOGE(TAG, "LMIC error, message not sent and deleted");
} // switch } // switch
delay(2); // yield to CPU delay(2); // yield to CPU
} // while(1) } // while(1)
@ -351,7 +345,6 @@ void lmictask(void *pvParameters) {
// lmic event handler // lmic event handler
void myEventCallback(void *pUserData, ev_t ev) { 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};
// get current length of lora send queue // get current length of lora send queue
@ -366,7 +359,6 @@ void myEventCallback(void *pUserData, ev_t ev) {
// process current event message // process current event message
switch (ev) { switch (ev) {
case EV_TXCOMPLETE: case EV_TXCOMPLETE:
// -> processed in lora_send() // -> processed in lora_send()
break; break;
@ -411,7 +403,6 @@ void myEventCallback(void *pUserData, ev_t ev) {
// event EV_RXCOMPLETE message handler // event EV_RXCOMPLETE message handler
void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg, void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
size_t nMsg) { size_t nMsg) {
// display amount of received data // display amount of received data
if (nMsg) if (nMsg)
ESP_LOGI(TAG, "Received %u byte(s) of payload on port %u", nMsg, port); ESP_LOGI(TAG, "Received %u byte(s) of payload on port %u", nMsg, port);
@ -419,7 +410,6 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
ESP_LOGI(TAG, "Received empty message on port %u", port); ESP_LOGI(TAG, "Received empty message on port %u", port);
switch (port) { switch (port) {
// rcommand received -> call interpreter // rcommand received -> call interpreter
case RCMDPORT: case RCMDPORT:
rcommand(pMsg, nMsg); rcommand(pMsg, nMsg);
@ -432,7 +422,6 @@ void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
timesync_serverAnswer(const_cast<uint8_t *>(pMsg), nMsg); timesync_serverAnswer(const_cast<uint8_t *>(pMsg), nMsg);
break; break;
#endif #endif
} // switch } // switch
} }
@ -513,7 +502,6 @@ bool ttn_rtc_restore() {
// https://github.com/JackGruber/ESP32-LMIC-DeepSleep-example/blob/master/src/main.cpp // https://github.com/JackGruber/ESP32-LMIC-DeepSleep-example/blob/master/src/main.cpp
void SaveLMICToRTC(int deepsleep_sec) { void SaveLMICToRTC(int deepsleep_sec) {
// ESP32 can't track millis during DeepSleep and no option to advance // ESP32 can't track millis during DeepSleep and no option to advance
// millis after DeepSleep. Therefore reset DutyCyles before saving LMIC struct // millis after DeepSleep. Therefore reset DutyCyles before saving LMIC struct

View File

@ -84,7 +84,6 @@ static const char TAG[] = __FILE__;
char clientId[20] = {0}; // unique ClientID char clientId[20] = {0}; // unique ClientID
void setup() { void setup() {
char features[100] = ""; char features[100] = "";
// disable brownout detection // disable brownout detection
@ -185,7 +184,7 @@ void setup() {
// initialize display // initialize display
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
strcat_P(features, " OLED"); strcat_P(features, " DISP");
DisplayIsOn = cfg.screenon; DisplayIsOn = cfg.screenon;
// display verbose info only after a coldstart (note: blocking call!) // display verbose info only after a coldstart (note: blocking call!)
dp_init(RTC_runmode == RUNMODE_POWERCYCLE ? true : false); dp_init(RTC_runmode == RUNMODE_POWERCYCLE ? true : false);
@ -213,7 +212,7 @@ void setup() {
#ifdef HAS_TWO_LED #ifdef HAS_TWO_LED
pinMode(HAS_TWO_LED, OUTPUT); pinMode(HAS_TWO_LED, OUTPUT);
strcat_P(features, " LED1"); strcat_P(features, " LED2");
#endif #endif
// use LED for power display if we have additional RGB LED, else for status // use LED for power display if we have additional RGB LED, else for status
@ -277,6 +276,7 @@ void setup() {
libpax_default_config(&configuration); libpax_default_config(&configuration);
// configure WIFI sniffing // configure WIFI sniffing
strcpy(configuration.wifi_my_country_str, WIFI_MY_COUNTRY);
configuration.wificounter = cfg.wifiscan; configuration.wificounter = cfg.wifiscan;
configuration.wifi_channel_map = WIFI_CHANNEL_ALL; configuration.wifi_channel_map = WIFI_CHANNEL_ALL;
configuration.wifi_channel_switch_interval = cfg.wifichancycle; configuration.wifi_channel_switch_interval = cfg.wifichancycle;
@ -487,7 +487,6 @@ void setup() {
RTC_runmode = RUNMODE_NORMAL; RTC_runmode = RUNMODE_NORMAL;
vTaskDelete(NULL); vTaskDelete(NULL);
} // setup() } // setup()
void loop() { vTaskDelete(NULL); } void loop() { vTaskDelete(NULL); }

View File

@ -19,7 +19,6 @@ void mqtt_deinit(void) {
} }
esp_err_t mqtt_init(void) { esp_err_t mqtt_init(void) {
// setup network connection and MQTT client // setup network connection and MQTT client
ETH.begin(); ETH.begin();
ETH.setHostname(clientId); ETH.setHostname(clientId);
@ -43,7 +42,6 @@ esp_err_t mqtt_init(void) {
} }
int mqtt_connect(const char *my_host, const uint16_t my_port) { int mqtt_connect(const char *my_host, const uint16_t my_port) {
IPAddress mqtt_server_ip; IPAddress mqtt_server_ip;
ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME); ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME);
@ -75,13 +73,10 @@ int mqtt_connect(const char *my_host, const uint16_t my_port) {
} }
void mqtt_client_task(void *param) { void mqtt_client_task(void *param) {
MessageBuffer_t msg; MessageBuffer_t msg;
while (1) { while (1) {
if (mqttClient.connected()) { if (mqttClient.connected()) {
// check for incoming messages // check for incoming messages
mqttClient.loop(); mqttClient.loop();
@ -124,11 +119,10 @@ void mqtt_client_task(void *param) {
// process incoming MQTT messages // process incoming MQTT messages
void mqtt_callback(MQTTClient *client, char *topic, char *payload, int length) { void mqtt_callback(MQTTClient *client, char *topic, char *payload, int length) {
if (strcmp(topic, MQTT_INTOPIC) == 0) { if (strcmp(topic, MQTT_INTOPIC) == 0) {
// get length of base64 encoded message // get length of base64 encoded message
size_t out_len = 0; size_t out_len = 0;
mbedtls_base64_decode(NULL, 0, &out_len, (unsigned char *)payload, length); mbedtls_base64_decode(NULL, 0, &out_len, (unsigned char *)payload, length);
// decode the base64 message // decode the base64 message
unsigned char decoded[out_len]; unsigned char decoded[out_len];
mbedtls_base64_decode(decoded, out_len, &out_len, (unsigned char *)payload, mbedtls_base64_decode(decoded, out_len, &out_len, (unsigned char *)payload,

View File

@ -41,7 +41,6 @@ inline String getHeaderValue(String header, String headerName) {
} }
void start_ota_update() { void start_ota_update() {
const char *host = clientId; const char *host = clientId;
switch_LED(LED_ON); switch_LED(LED_ON);
@ -51,12 +50,12 @@ void start_ota_update() {
dp_setup(); dp_setup();
dp_setFont(MY_FONT_NORMAL); dp_setFont(MY_FONT_NORMAL);
dp_printf("SOFTWARE UPDATE\r\n"); dp->printf("SOFTWARE UPDATE\r\n");
dp_printf("WiFi connect ..\r\n"); dp->printf("WiFi connect ..\r\n");
dp_printf("Has Update? ..\r\n"); dp->printf("Has Update? ..\r\n");
dp_printf("Fetching ..\r\n"); dp->printf("Fetching ..\r\n");
dp_printf("Downloading ..\r\n"); dp->printf("Downloading ..\r\n");
dp_printf("Rebooting ..\r\n"); dp->printf("Rebooting ..\r\n");
dp_dump(); dp_dump();
#endif #endif
@ -121,13 +120,11 @@ end:
ota_display(5, "**", ""); // mark line rebooting ota_display(5, "**", ""); // mark line rebooting
delay(5000); delay(5000);
do_reset(false); do_reset(false);
} // start_ota_update } // start_ota_update
// Reads data vom wifi client and flashes it to ota partition // Reads data vom wifi client and flashes it to ota partition
// returns: 0 = finished, 1 = retry, -1 = abort // returns: 0 = finished, 1 = retry, -1 = abort
int do_ota_update() { int do_ota_update() {
char buf[17]; char buf[17];
bool redirect = true; bool redirect = true;
size_t written = 0; size_t written = 0;
@ -319,18 +316,17 @@ abort:
retry: retry:
return 1; return 1;
} // do_ota_update } // do_ota_update
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) {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
dp_setTextCursor(14 * 8, row * 8); dp->setCursor(14 * 8, row * 8);
dp_printf(status.substr(0, 2).c_str()); dp->printf(status.substr(0, 2).c_str());
if (!msg.empty()) { if (!msg.empty()) {
dp_printf(" "); dp->printf(" ");
dp_printf(msg.substr(0, 16).c_str()); dp->printf(msg.substr(0, 16).c_str());
// dp_printf("\r\n"); // dp->printf("\r\n");
} }
dp_dump(); dp_dump();
#endif #endif

View File

@ -48,9 +48,7 @@
*/ */
// WiFi scan parameters // WiFi scan parameters
#define WIFI_CHANNEL_MIN 1 // start channel number where scan begings #define WIFI_MY_COUNTRY "01" // select 2-letter locale for Wifi RF settings, e.g. "DE"; use "01" for world safe mode
#define WIFI_CHANNEL_MAX 13 // total channel number to scan
#define WIFI_MY_COUNTRY "EU" // select locale for Wifi RF settings
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec. #define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
// LoRa payload default parameters // LoRa payload default parameters

View File

@ -58,7 +58,6 @@ void PayloadConvert::addConfig(configData_t value) {
void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp, void PayloadConvert::addStatus(uint16_t voltage, uint64_t uptime, float cputemp,
uint32_t mem, uint8_t reset0, uint32_t mem, uint8_t reset0,
uint32_t restarts) { uint32_t restarts) {
buffer[cursor++] = highByte(voltage); buffer[cursor++] = highByte(voltage);
buffer[cursor++] = lowByte(voltage); buffer[cursor++] = lowByte(voltage);
buffer[cursor++] = (byte)((uptime & 0xFF00000000000000) >> 56); buffer[cursor++] = (byte)((uptime & 0xFF00000000000000) >> 56);

View File

@ -5,7 +5,7 @@
// Local logging tag // Local logging tag
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
uint8_t batt_level = 0; // display value int8_t batt_level = -1; // percent batt level, global variable, -1 means no batt
#ifdef BAT_MEASURE_ADC #ifdef BAT_MEASURE_ADC
esp_adc_cal_characteristics_t *adc_characs = esp_adc_cal_characteristics_t *adc_characs =
@ -23,113 +23,82 @@ static const adc_unit_t unit = ADC_UNIT_1;
#endif // BAT_MEASURE_ADC #endif // BAT_MEASURE_ADC
#ifdef HAS_PMU #ifdef HAS_PMU
AXP20X_Class pmu; XPowersPMU pmu;
void AXP192_powerevent_IRQ(void) { void AXP192_powerevent_IRQ(void) {
pmu.getIrqStatus();
pmu.readIRQ(); if (pmu.isVbusOverVoltageIrq())
if (pmu.isVbusOverVoltageIRQ())
ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000); ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000);
if (pmu.isVbusPlugInIRQ()) if (pmu.isVbusInsertIrq())
ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000, ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000,
pmu.getVbusCurrent()); pmu.getVbusCurrent());
if (pmu.isVbusRemoveIRQ()) if (pmu.isVbusRemoveIrq())
ESP_LOGI(TAG, "USB unplugged."); ESP_LOGI(TAG, "USB unplugged.");
if (pmu.isBatInsertIrq())
if (pmu.isBattPlugInIRQ())
ESP_LOGI(TAG, "Battery is connected."); ESP_LOGI(TAG, "Battery is connected.");
if (pmu.isBattRemoveIRQ()) if (pmu.isBatRemoveIrq())
ESP_LOGI(TAG, "Battery was removed."); ESP_LOGI(TAG, "Battery was removed.");
if (pmu.isChargingIRQ()) if (pmu.isBatChagerStartIrq())
ESP_LOGI(TAG, "Battery charging."); ESP_LOGI(TAG, "Battery charging started.");
if (pmu.isChargingDoneIRQ()) { if (pmu.isBatChagerDoneIrq())
ESP_LOGI(TAG, "Battery charging done."); ESP_LOGI(TAG, "Battery charging done.");
#ifdef PMU_LED_RUN_MODE if (pmu.isBattTempLowIrq())
pmu.setChgLEDMode(PMU_LED_RUN_MODE);
#else
pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
#endif
}
if (pmu.isBattTempLowIRQ())
ESP_LOGI(TAG, "Battery high temperature."); ESP_LOGI(TAG, "Battery high temperature.");
if (pmu.isBattTempHighIRQ()) if (pmu.isBattTempHighIrq())
ESP_LOGI(TAG, "Battery low temperature."); ESP_LOGI(TAG, "Battery low temperature.");
if (pmu.isLowVoltageLevel1IRQ()) {
ESP_LOGI(TAG, "Battery has reached voltage level 1.");
pmu.setChgLEDMode(AXP20X_LED_BLINK_4HZ);
}
if (pmu.isLowVoltageLevel2IRQ()) {
ESP_LOGI(TAG, "Battery has reached voltage level 2.");
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
}
// PEK button handling:
// long press -> shutdown power, must be exited by another longpress
if (pmu.isPekeyLongPressIrq())
AXP192_power(pmu_power_off); // switch off Lora, GPS, display
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
// short press -> esp32 deep sleep mode, can be exited by pressing user button // short press -> esp32 deep sleep mode, must be exited by user button
if (pmu.isPEKShortPressIRQ()) { if (pmu.isPekeyShortPressIrq())
enter_deepsleep(0, HAS_BUTTON); enter_deepsleep(0, HAS_BUTTON);
}
#endif #endif
// long press -> shutdown power, can be exited by another longpress pmu.clearIrqStatus();
if (pmu.isPEKLongtPressIRQ()) {
AXP192_power(pmu_power_off); // switch off Lora, GPS, display
}
pmu.clearIRQ();
// refresh stored voltage value // refresh stored voltage value
read_battlevel(); read_battlevel();
} }
void AXP192_power(pmu_power_t powerlevel) { void AXP192_power(pmu_power_t powerlevel) {
switch (powerlevel) { switch (powerlevel) {
case pmu_power_off: case pmu_power_off:
pmu.setChargingLedMode(XPOWERS_CHG_LED_OFF);
pmu.shutdown(); pmu.shutdown();
break; break;
case pmu_power_sleep: case pmu_power_sleep:
#ifdef PMU_LED_SLEEP_MODE pmu.setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
pmu.setChgLEDMode(PMU_LED_SLEEP_MODE);
#else
pmu.setChgLEDMode(AXP20X_LED_OFF);
#endif
// we don't cut off DCDC1, because OLED display will then block i2c bus // we don't cut off DCDC1, because OLED display will then block i2c bus
// pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); // OLED off // pmu.disableDC1(); // OLED off
pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // gps off pmu.disableLDO3(); // gps off
pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // lora off pmu.disableLDO2(); // lora off
pmu.enableSleep();
break; break;
case pmu_power_on: case pmu_power_on:
default: default:
pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0/1.1 pmu.enableLDO2(); // Lora on T-Beam V1.0/1.1
pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0/1.1 pmu.enableLDO3(); // Gps on T-Beam V1.0/1.1
pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // OLED on T-Beam v1.0/1.1 pmu.enableDC1(); // OLED on T-Beam v1.0/1.1
pmu.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); // unused on T-Beam v1.0/1.1 pmu.setChargingLedMode(XPOWERS_CHG_LED_ON);
pmu.setPowerOutPut(AXP192_EXTEN, AXP202_OFF); // unused on T-Beam v1.0/1.1
#ifdef PMU_LED_RUN_MODE
pmu.setChgLEDMode(PMU_LED_RUN_MODE);
#else
pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
#endif
break; break;
} }
} }
void AXP192_showstatus(void) { void AXP192_showstatus(void) {
if (pmu.isBatteryConnect()) if (pmu.isBatteryConnect())
if (pmu.isChargeing()) if (pmu.isCharging())
ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh", ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh",
pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent()); pmu.getBattVoltage() / 1000.0, pmu.getBatteryChargeCurrent());
else else
ESP_LOGI(TAG, "Battery not charging"); ESP_LOGI(TAG, "Battery not charging");
else else
ESP_LOGI(TAG, "No Battery"); ESP_LOGI(TAG, "Battery not present");
if (pmu.isVBUSPlug()) if (pmu.isVbusIn())
ESP_LOGI(TAG, "USB powered, %.0fmW", ESP_LOGI(TAG, "USB powered, %.0fmW",
pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent()); pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent());
else else
@ -137,60 +106,62 @@ void AXP192_showstatus(void) {
} }
void AXP192_init(void) { void AXP192_init(void) {
if (!pmu.begin(Wire, AXP192_PRIMARY_ADDRESS, SCL, SDA))
if (pmu.begin(i2c_readBytes, i2c_writeBytes, AXP192_PRIMARY_ADDRESS) ==
AXP_FAIL)
ESP_LOGI(TAG, "AXP192 PMU initialization failed"); ESP_LOGI(TAG, "AXP192 PMU initialization failed");
else { else {
ESP_LOGD(TAG, "AXP192 ChipID:0x%x", pmu.getChipID());
// configure voltages // set pmu operating voltages
pmu.setDCDC1Voltage(3300); // for external OLED display pmu.setSysPowerDownVoltage(2700);
pmu.setLDO2Voltage(3300); // LORA VDD 3v3 pmu.setVbusVoltageLimit(XPOWERS_AXP192_VBUS_VOL_LIM_4V5);
pmu.setLDO3Voltage(3300); // GPS VDD 3v3 pmu.setVbusCurrentLimit(XPOWERS_AXP192_VBUS_CUR_LIM_OFF);
// configure voltage warning levels // set device operating voltages
pmu.setVWarningLevel1(3600); pmu.setDC1Voltage(3300); // for external OLED display
pmu.setVWarningLevel2(3800); pmu.setLDO2Voltage(3300); // LORA VDD 3v3
pmu.setPowerDownVoltage(3300); pmu.setLDO3Voltage(3300); // GPS VDD 3v3
// configure PEK button settings // configure PEK button settings
pmu.setTimeOutShutdown(false); // forced shutdown by PEK enabled pmu.setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
pmu.setShutdownTime( pmu.setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
AXP_POWER_OFF_TIME_6S); // 6 sec button press for shutdown
pmu.setlongPressTime(
AXP_LONGPRESS_TIME_1S5); // 1.5 sec button press for long press
pmu.setStartupTime(
AXP192_STARTUP_TIME_1S); // 1 sec button press for startup
// set battery temperature sensing pin off to save power // set battery temperature sensing pin off to save power
pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); pmu.disableTSPinMeasure();
// switch ADCs on // Enable internal ADC detection
pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true); pmu.enableBattDetection();
pmu.adc1Enable(AXP202_BATT_CUR_ADC1, true); pmu.enableVbusVoltageMeasure();
pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true); pmu.enableBattVoltageMeasure();
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true); pmu.enableSystemVoltageMeasure();
#ifdef PMU_INT #ifdef PMU_INT
pinMode(PMU_INT, INPUT_PULLUP); pinMode(PMU_INT, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING); attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING);
pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | // disable all interrupts
AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ | pmu.disableIRQ(XPOWERS_AXP192_ALL_IRQ);
AXP202_CHARGING_FINISHED_IRQ | AXP202_PEK_SHORTPRESS_IRQ, // clear all interrupt flags
1); pmu.clearIrqStatus();
pmu.clearIRQ(); // enable the required interrupt function
pmu.enableIRQ(XPOWERS_AXP192_BAT_INSERT_IRQ |
XPOWERS_AXP192_BAT_REMOVE_IRQ | // BATTERY
XPOWERS_AXP192_VBUS_INSERT_IRQ |
XPOWERS_AXP192_VBUS_REMOVE_IRQ | // VBUS
XPOWERS_AXP192_PKEY_SHORT_IRQ |
XPOWERS_AXP192_PKEY_LONG_IRQ | // POWER KEY
XPOWERS_AXP192_BAT_CHG_DONE_IRQ |
XPOWERS_AXP192_BAT_CHG_START_IRQ // CHARGE
);
#endif // PMU_INT #endif // PMU_INT
// set charging parameterss according to user settings if we have (see power.h) // set charging parameters according to user settings if we have (see power.h)
#ifdef PMU_CHG_CURRENT #ifdef PMU_CHG_CURRENT
pmu.setChargeControlCur(PMU_CHG_CURRENT); pmu.setChargerConstantCurr(PMU_CHG_CURRENT);
pmu.setChargingTargetVoltage(PMU_CHG_CUTOFF); pmu.setChargeTargetVoltage(PMU_CHG_CUTOFF);
pmu.enableChargeing(true); pmu.enableCharge();
#endif #endif
// switch power rails on // switch power rails on
AXP192_power(pmu_power_on); AXP192_power(pmu_power_on);
ESP_LOGI(TAG, "AXP192 PMU initialized"); ESP_LOGI(TAG, "AXP192 PMU initialized");
} }
} }
@ -264,11 +235,13 @@ uint16_t read_voltage(void) {
return voltage; return voltage;
} }
uint8_t read_battlevel(mapFn_t mapFunction) { int8_t read_battlevel(mapFn_t mapFunction) {
// returns the estimated battery level in values 0 ... 100 [percent] // returns the estimated battery level in values 0 ... 100 [percent]
uint8_t batt_percent = 0; uint8_t batt_percent = 0;
#ifdef HAS_IP5306 #ifdef HAS_IP5306
batt_percent = IP5306_GetBatteryLevel(); batt_percent = IP5306_GetBatteryLevel();
#elif defined HAS_PMU
batt_percent = pmu.getBatteryPercent();
#else #else
const uint16_t batt_voltage = read_voltage(); const uint16_t batt_voltage = read_voltage();
if (batt_voltage <= BAT_MIN_VOLTAGE) if (batt_voltage <= BAT_MIN_VOLTAGE)
@ -290,7 +263,7 @@ uint8_t read_battlevel(mapFn_t mapFunction) {
// we calculate the applicable value from MCMD_DEVS_BATT_MIN to // we calculate the applicable value from MCMD_DEVS_BATT_MIN to
// MCMD_DEVS_BATT_MAX from batt_percent value // MCMD_DEVS_BATT_MAX from batt_percent value
if (batt_percent == 0) if (batt_percent == -1)
LMIC_setBatteryLevel(MCMD_DEVS_BATT_NOINFO); LMIC_setBatteryLevel(MCMD_DEVS_BATT_NOINFO);
else else
LMIC_setBatteryLevel(batt_percent / 100.0 * LMIC_setBatteryLevel(batt_percent / 100.0 *
@ -298,7 +271,7 @@ uint8_t read_battlevel(mapFn_t mapFunction) {
// overwrite calculated value if we have external power // overwrite calculated value if we have external power
#ifdef HAS_PMU #ifdef HAS_PMU
if (pmu.isVBUSPlug()) if (pmu.isVbusIn())
LMIC_setBatteryLevel(MCMD_DEVS_EXT_POWER); LMIC_setBatteryLevel(MCMD_DEVS_EXT_POWER);
#elif defined HAS_IP5306 #elif defined HAS_IP5306
if (IP5306_GetPowerSource()) if (IP5306_GetPowerSource())
@ -312,7 +285,7 @@ uint8_t read_battlevel(mapFn_t mapFunction) {
bool batt_sufficient() { bool batt_sufficient() {
#if (defined HAS_PMU || defined BAT_MEASURE_ADC || defined HAS_IP5306) #if (defined HAS_PMU || defined BAT_MEASURE_ADC || defined HAS_IP5306)
if (batt_level) // we have a battery voltage if (batt_level > 0) // we have a battery percent value
return (batt_level > OTA_MIN_BATT); return (batt_level > OTA_MIN_BATT);
else else
#endif #endif

View File

@ -234,7 +234,6 @@ void set_loradr(uint8_t val[]) {
getSfName(updr2rps(LMIC.datarate)), getSfName(updr2rps(LMIC.datarate)),
getBwName(updr2rps(LMIC.datarate)), getBwName(updr2rps(LMIC.datarate)),
getCrName(updr2rps(LMIC.datarate))); getCrName(updr2rps(LMIC.datarate)));
} else } else
ESP_LOGI( ESP_LOGI(
TAG, TAG,
@ -325,9 +324,15 @@ void get_config(uint8_t val[]) {
void get_status(uint8_t val[]) { void get_status(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: get device status"); ESP_LOGI(TAG, "Remote command: get device status");
payload.reset(); payload.reset();
#ifdef CONFIG_IDF_TARGET_ESP32S3
payload.addStatus(read_voltage(), (uint64_t)(uptime() / 1000ULL), 0,
// temperatureRead(),
getFreeRAM(), rtc_get_reset_reason(0), RTC_restarts);
#else
payload.addStatus(read_voltage(), (uint64_t)(uptime() / 1000ULL), payload.addStatus(read_voltage(), (uint64_t)(uptime() / 1000ULL),
temperatureRead(), getFreeRAM(), rtc_get_reset_reason(0), temperatureRead(), getFreeRAM(), rtc_get_reset_reason(0),
RTC_restarts); RTC_restarts);
#endif
SendPayload(STATUSPORT); SendPayload(STATUSPORT);
}; };
@ -430,14 +435,12 @@ static const uint8_t cmdtablesize =
// check and execute remote command // check and execute remote command
void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) { void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) {
if (cmdlength == 0) if (cmdlength == 0)
return; return;
uint8_t foundcmd[cmdlength], cursor = 0; uint8_t foundcmd[cmdlength], cursor = 0;
while (cursor < cmdlength) { while (cursor < cmdlength) {
int i = cmdtablesize; int i = cmdtablesize;
while (i--) { while (i--) {
if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table
@ -462,7 +465,6 @@ void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) {
break; break;
} }
} // command parsing loop } // command parsing loop
} // rcmd_execute() } // rcmd_execute()
// remote command processing task // remote command processing task
@ -485,9 +487,7 @@ void rcmd_process(void *pvParameters) {
// enqueue remote command // enqueue remote command
void rcommand(const uint8_t *cmd, const size_t cmdlength) { void rcommand(const uint8_t *cmd, const size_t cmdlength) {
RcmdBuffer_t rcmd = {0}; RcmdBuffer_t rcmd = {0};
rcmd.cmdLen = cmdlength; rcmd.cmdLen = cmdlength;
memcpy(rcmd.cmd, cmd, cmdlength); memcpy(rcmd.cmd, cmd, cmdlength);
@ -505,7 +505,6 @@ void rcmd_deinit(void) {
} }
esp_err_t rcmd_init(void) { esp_err_t rcmd_init(void) {
_ASSERT(RCMD_QUEUE_SIZE > 0); _ASSERT(RCMD_QUEUE_SIZE > 0);
RcmdQueue = xQueueCreate(RCMD_QUEUE_SIZE, sizeof(RcmdBuffer_t)); RcmdQueue = xQueueCreate(RCMD_QUEUE_SIZE, sizeof(RcmdBuffer_t));
if (RcmdQueue == 0) { if (RcmdQueue == 0) {

View File

@ -11,7 +11,6 @@ static const char TAG[] = __FILE__;
// RTC_NOINIT_ATTR -> keep value after a software restart or system crash // RTC_NOINIT_ATTR -> keep value after a software restart or system crash
RTC_NOINIT_ATTR runmode_t RTC_runmode; RTC_NOINIT_ATTR runmode_t RTC_runmode;
RTC_NOINIT_ATTR uint32_t RTC_restarts; RTC_NOINIT_ATTR uint32_t RTC_restarts;
// RTC_DATA_ATTR -> keep values after a wakeup from sleep // RTC_DATA_ATTR -> keep values after a wakeup from sleep
RTC_DATA_ATTR struct timeval RTC_sleep_start_time; RTC_DATA_ATTR struct timeval RTC_sleep_start_time;
RTC_DATA_ATTR unsigned long long RTC_millis = 0; RTC_DATA_ATTR unsigned long long RTC_millis = 0;
@ -39,7 +38,6 @@ void do_reset(bool warmstart) {
} }
void do_after_reset(void) { void do_after_reset(void) {
struct timeval sleep_stop_time; struct timeval sleep_stop_time;
uint64_t sleep_time_ms; uint64_t sleep_time_ms;
@ -54,19 +52,17 @@ void do_after_reset(void) {
#endif #endif
switch (rtc_get_reset_reason(0)) { switch (rtc_get_reset_reason(0)) {
case RESET_REASON_CHIP_POWER_ON:
case POWERON_RESET: // 0x01 Vbat power on reset case RESET_REASON_SYS_BROWN_OUT:
case RTCWDT_BROWN_OUT_RESET: // 0x0f Reset when the vdd voltage is not
// stable
reset_rtc_vars(); reset_rtc_vars();
break; break;
case RTC_SW_CPU_RESET: // 0x0c Software reset CPU case RESET_REASON_CPU0_SW:
// keep previous set runmode (update / normal / maintenance) // keep previous set runmode (update / normal / maintenance)
RTC_restarts++; RTC_restarts++;
break; break;
case DEEPSLEEP_RESET: // 0x05 Deep Sleep reset digital core case RESET_REASON_CORE_DEEP_SLEEP:
// calculate time spent in deep sleep // calculate time spent in deep sleep
gettimeofday(&sleep_stop_time, NULL); gettimeofday(&sleep_stop_time, NULL);
sleep_time_ms = sleep_time_ms =
@ -74,26 +70,13 @@ void do_after_reset(void) {
(sleep_stop_time.tv_usec - RTC_sleep_start_time.tv_usec) / 1000; (sleep_stop_time.tv_usec - RTC_sleep_start_time.tv_usec) / 1000;
RTC_millis += sleep_time_ms; // increment system monotonic time RTC_millis += sleep_time_ms; // increment system monotonic time
ESP_LOGI(TAG, "Time spent in deep sleep: %d ms", sleep_time_ms); ESP_LOGI(TAG, "Time spent in deep sleep: %d ms", sleep_time_ms);
// do we have a valid time? -> set global variable // do we have a valid time? -> set global variable
timeSource = timeIsValid(sleep_stop_time.tv_sec) ? _set : _unsynced; timeSource = timeIsValid(sleep_stop_time.tv_sec) ? _set : _unsynced;
// set wakeup state, not if we have pending OTA update // set wakeup state, not if we have pending OTA update
if (RTC_runmode == RUNMODE_SLEEP) if (RTC_runmode == RUNMODE_SLEEP)
RTC_runmode = RUNMODE_WAKEUP; RTC_runmode = RUNMODE_WAKEUP;
break; 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 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: default:
RTC_runmode = RUNMODE_POWERCYCLE; RTC_runmode = RUNMODE_POWERCYCLE;
RTC_restarts++; RTC_restarts++;
@ -102,26 +85,18 @@ void do_after_reset(void) {
} }
void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) { void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
ESP_LOGI(TAG, "Preparing to sleep..."); ESP_LOGI(TAG, "Preparing to sleep...");
RTC_runmode = RUNMODE_SLEEP; RTC_runmode = RUNMODE_SLEEP;
int i; int i;
// show message on display
#ifdef HAS_DISPLAY
dp_message("-GOING TO SLEEP-", 7, true);
#endif
// validate wake up pin, if we have // validate wake up pin, if we have
if (!GPIO_IS_VALID_GPIO(wakeup_gpio)) if (!GPIO_IS_VALID_GPIO(wakeup_gpio))
wakeup_gpio = GPIO_NUM_MAX; wakeup_gpio = GPIO_NUM_MAX;
// stop further enqueuing of senddata and MAC processing
libpax_counter_stop();
// stop further enqueuing of senddata and MAC processing // switch off any power consuming hardware
// -> skipped, because shutting down bluedroid stack tends to crash
// libpax_counter_stop();
// switch off any power consuming hardware
#if (HAS_SDS011) #if (HAS_SDS011)
sds011_sleep(); sds011_sleep();
#endif #endif
@ -205,4 +180,6 @@ void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
esp_deep_sleep_start(); esp_deep_sleep_start();
} }
unsigned long long uptime() { return (RTC_millis + esp_timer_get_time() / 1000); } unsigned long long uptime() {
return (RTC_millis + esp_timer_get_time() / 1000);
}

View File

@ -9,7 +9,6 @@ RtcDS3231<TwoWire> Rtc(Wire); // RTC hardware i2c interface
// initialize RTC // initialize RTC
uint8_t rtc_init(void) { uint8_t rtc_init(void) {
Wire.begin(HAS_RTC); Wire.begin(HAS_RTC);
Rtc.Begin(MY_DISPLAY_SDA, MY_DISPLAY_SCL); Rtc.Begin(MY_DISPLAY_SDA, MY_DISPLAY_SCL);
@ -39,11 +38,9 @@ uint8_t rtc_init(void) {
// failure // failure
// return 0 // return 0
} // rtc_init() } // rtc_init()
uint8_t set_rtctime(time_t t) { // t is sec epoch time uint8_t set_rtctime(time_t t) { // t is sec epoch time
#ifdef RTC_INT // sync rtc 1Hz pulse on top of second #ifdef RTC_INT // sync rtc 1Hz pulse on top of second
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); // off Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); // off
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); // start Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); // start
@ -51,11 +48,9 @@ uint8_t set_rtctime(time_t t) { // t is sec epoch time
Rtc.SetDateTime(RtcDateTime(t - SECS_YR_2000)); // epoch -> sec2000 Rtc.SetDateTime(RtcDateTime(t - SECS_YR_2000)); // epoch -> sec2000
ESP_LOGI(TAG, "RTC time synced"); ESP_LOGI(TAG, "RTC time synced");
return 1; // success return 1; // success
} // set_rtctime() } // set_rtctime()
time_t get_rtctime(uint16_t *msec) { time_t get_rtctime(uint16_t *msec) {
time_t t = 0; time_t t = 0;
*msec = 0; *msec = 0;
if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) { if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) {
@ -75,7 +70,6 @@ time_t get_rtctime(uint16_t *msec) {
#endif #endif
return t; return t;
} // get_rtctime() } // get_rtctime()
float get_rtctemp(void) { float get_rtctemp(void) {

View File

@ -67,7 +67,6 @@ int print_to_sd_card(const char *fmt, va_list args) {
#endif #endif
bool openFile(FILE **fd, const char *filename) { bool openFile(FILE **fd, const char *filename) {
char _filename[50]; char _filename[50];
sprintf(_filename, "%s%s", MOUNT_POINT, filename); sprintf(_filename, "%s%s", MOUNT_POINT, filename);
@ -81,7 +80,6 @@ bool openFile(FILE **fd, const char *filename) {
} // openfile } // openfile
bool sdcard_init(bool create) { bool sdcard_init(bool create) {
esp_err_t ret; esp_err_t ret;
// for usage of SD drivers on ESP32 platform see // for usage of SD drivers on ESP32 platform see
@ -171,7 +169,6 @@ bool sdcard_init(bool create) {
snprintf(bufferFilename, sizeof(bufferFilename), "/%s.csv", SDCARD_FILE_NAME); snprintf(bufferFilename, sizeof(bufferFilename), "/%s.csv", SDCARD_FILE_NAME);
if (openFile(&data_file, bufferFilename)) { if (openFile(&data_file, bufferFilename)) {
fpos_t position; fpos_t position;
fgetpos(data_file, &position); fgetpos(data_file, &position);
@ -207,7 +204,6 @@ bool sdcard_init(bool create) {
#endif #endif
return useSDCard; return useSDCard;
} // sdcard_init } // sdcard_init
void sdcard_flush(void) { void sdcard_flush(void) {
@ -236,7 +232,6 @@ void sdcard_close(void) {
void sdcardWriteData(uint16_t noWifi, uint16_t noBle, void sdcardWriteData(uint16_t noWifi, uint16_t noBle,
__attribute__((unused)) uint16_t voltage) { __attribute__((unused)) uint16_t voltage) {
if (!useSDCard) if (!useSDCard)
return; return;
@ -264,4 +259,4 @@ void sdcardWriteData(uint16_t noWifi, uint16_t noBle,
fprintf(data_file, "\n"); fprintf(data_file, "\n");
} }
#endif // (HAS_SDCARD) #endif // (HAS_SDCARD)

View File

@ -25,7 +25,6 @@ void initSendDataTimer(uint8_t sendcycle) {
// put data to send in RTos Queues used for transmit over channels Lora and SPI // put data to send in RTos Queues used for transmit over channels Lora and SPI
void SendPayload(uint8_t port) { void SendPayload(uint8_t port) {
ESP_LOGD(TAG, "sending Payload for Port %d", port); ESP_LOGD(TAG, "sending Payload for Port %d", port);
MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, Message[] MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, Message[]
@ -69,12 +68,10 @@ void SendPayload(uint8_t port) {
#ifdef HAS_MQTT #ifdef HAS_MQTT
mqtt_enqueuedata(&SendBuffer); mqtt_enqueuedata(&SendBuffer);
#endif #endif
} // SendPayload } // SendPayload
// timer triggered function to prepare payload to send // timer triggered function to prepare payload to send
void sendData() { void sendData() {
uint8_t bitmask = cfg.payloadmask; uint8_t bitmask = cfg.payloadmask;
uint8_t mask = 1; uint8_t mask = 1;
@ -93,7 +90,6 @@ void sendData() {
while (bitmask) { while (bitmask) {
switch (bitmask & mask) { switch (bitmask & mask) {
#if ((WIFICOUNTER) || (BLECOUNTER)) #if ((WIFICOUNTER) || (BLECOUNTER))
case COUNT_DATA: case COUNT_DATA:
payload.reset(); payload.reset();
@ -199,7 +195,6 @@ void sendData() {
SendPayload(BATTPORT); SendPayload(BATTPORT);
break; break;
#endif #endif
} // switch } // switch
bitmask &= ~mask; bitmask &= ~mask;
mask <<= 1; mask <<= 1;

View File

@ -9,7 +9,6 @@ static const char TAG[] = __FILE__;
10 // max. size of user sensor data buffer in bytes [default=20] 10 // max. size of user sensor data buffer in bytes [default=20]
void sensor_init(void) { void sensor_init(void) {
// this function is called during device startup // this function is called during device startup
// put your user sensor initialization routines here // put your user sensor initialization routines here
} }
@ -38,14 +37,11 @@ uint8_t sensor_mask(uint8_t sensor_no) {
} }
uint8_t *sensor_read(uint8_t sensor) { uint8_t *sensor_read(uint8_t sensor) {
static uint8_t buf[SENSORBUFFER] = {0}; static uint8_t buf[SENSORBUFFER] = {0};
uint8_t length = 3; uint8_t length = 3;
switch (sensor) { switch (sensor) {
case 1: case 1:
// insert user specific sensor data frames here // insert user specific sensor data frames here
buf[0] = length; buf[0] = length;
buf[1] = 0x01; buf[1] = 0x01;
@ -53,15 +49,12 @@ uint8_t *sensor_read(uint8_t sensor) {
buf[3] = 0x03; buf[3] = 0x03;
break; break;
case 2: case 2:
buf[0] = length; buf[0] = length;
buf[1] = 0x01; buf[1] = 0x01;
buf[2] = 0x02; buf[2] = 0x02;
buf[3] = 0x03; buf[3] = 0x03;
break; break;
case 3: case 3:
buf[0] = length; buf[0] = length;
buf[1] = 0x01; buf[1] = 0x01;
buf[2] = 0x02; buf[2] = 0x02;
@ -70,4 +63,4 @@ uint8_t *sensor_read(uint8_t sensor) {
} }
return buf; return buf;
} }

View File

@ -40,7 +40,6 @@ void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
#ifdef GPS_INT #ifdef GPS_INT
// interrupt service routine triggered by GPS PPS // interrupt service routine triggered by GPS PPS
void IRAM_ATTR GPSIRQ(void) { void IRAM_ATTR GPSIRQ(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// take timestamp // take timestamp
@ -54,7 +53,6 @@ void IRAM_ATTR GPSIRQ(void) {
// interrupt service routine triggered by esp32 hardware timer // interrupt service routine triggered by esp32 hardware timer
void IRAM_ATTR CLOCKIRQ(void) { void IRAM_ATTR CLOCKIRQ(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
// advance wall clock, if we have // advance wall clock, if we have
@ -79,7 +77,6 @@ void IRAM_ATTR CLOCKIRQ(void) {
} }
void calibrateTime(void) { void calibrateTime(void) {
// kick off asynchronous lora timesync if we have // kick off asynchronous lora timesync if we have
#if (HAS_LORA_TIME) #if (HAS_LORA_TIME)
timesync_request(); timesync_request();
@ -106,12 +103,10 @@ void calibrateTime(void) {
#endif #endif
#endif #endif
} // calibrateTime() } // calibrateTime()
// set system time (UTC), calibrate RTC and RTC_INT pps // set system time (UTC), calibrate RTC and RTC_INT pps
bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) { bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
struct timeval tv = {0}; struct timeval tv = {0};
// called with invalid timesource? // called with invalid timesource?
@ -123,7 +118,6 @@ bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
// do we have a valid time? // do we have a valid time?
if (timeIsValid(time_to_set)) { if (timeIsValid(time_to_set)) {
// if we have msec fraction, then wait until top of second with // if we have msec fraction, then wait until top of second with
// millisecond precision // millisecond precision
if (t_msec % 1000) { if (t_msec % 1000) {
@ -160,7 +154,6 @@ bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
return true; return true;
} else { } else {
timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ); timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ);
ESP_LOGV(TAG, ESP_LOGV(TAG,
"[%0.3f] Failed to synchronise time from source %c | unix sec " "[%0.3f] Failed to synchronise time from source %c | unix sec "
@ -173,7 +166,6 @@ bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
// helper function to setup a pulse per second for time synchronisation // helper function to setup a pulse per second for time synchronisation
void timepulse_init(void) { void timepulse_init(void) {
// set esp-idf API sntp sync mode // set esp-idf API sntp sync mode
// sntp_init(); // sntp_init();
sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED);
@ -210,7 +202,6 @@ void timepulse_init(void) {
// start cyclic time sync // start cyclic time sync
timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ); timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
} // timepulse_init } // timepulse_init
// helper function to check plausibility of a given epoch time // helper function to check plausibility of a given epoch time
@ -224,7 +215,6 @@ bool timeIsValid(time_t const t) {
// helper function to calculate serial transmit time // helper function to calculate serial transmit time
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config, TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
int8_t rxPin, int8_t txPins) { int8_t rxPin, int8_t txPins) {
uint32_t databits = ((config & 0x0c) >> 2) + 5; uint32_t databits = ((config & 0x0c) >> 2) + 5;
uint32_t stopbits = ((config & 0x20) >> 5) + 1; uint32_t stopbits = ((config & 0x20) >> 5) + 1;
uint32_t txTime = (databits + stopbits + 1) * framesize * 1000.0 / baud; uint32_t txTime = (databits + stopbits + 1) * framesize * 1000.0 / baud;
@ -234,7 +224,6 @@ TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
} }
void clock_loop(void *taskparameter) { // ClockTask void clock_loop(void *taskparameter) { // ClockTask
uint32_t current_time = 0, previous_time = 0; uint32_t current_time = 0, previous_time = 0;
time_t tt; time_t tt;
struct tm t = {0}; struct tm t = {0};
@ -248,7 +237,6 @@ void clock_loop(void *taskparameter) { // ClockTask
// output the next second's pulse/telegram after pps arrived // output the next second's pulse/telegram after pps arrived
for (;;) { for (;;) {
// wait for timepulse and store UTC time // wait for timepulse and store UTC time
xTaskNotifyWait(0x00, ULONG_MAX, &current_time, portMAX_DELAY); xTaskNotifyWait(0x00, ULONG_MAX, &current_time, portMAX_DELAY);
@ -291,7 +279,6 @@ void clock_loop(void *taskparameter) { // ClockTask
ESP_LOGD(TAG, "[%0.3f] DCF77: new frame for min %d", _seconds(), ESP_LOGD(TAG, "[%0.3f] DCF77: new frame for min %d", _seconds(),
t.tm_min); t.tm_min);
} else { } else {
// generate impulse // generate impulse
if (t.tm_min == ClockMinute) { // ensure frame is recent if (t.tm_min == ClockMinute) { // ensure frame is recent
DCF77_Pulse(ClockPulse & 1); // output next second DCF77_Pulse(ClockPulse & 1); // output next second
@ -311,12 +298,10 @@ void clock_loop(void *taskparameter) { // ClockTask
#endif #endif
previous_time = current_time; previous_time = current_time;
} // for } // for
} // clock_loop() } // clock_loop()
void clock_init(void) { void clock_init(void) {
// setup clock output interface // setup clock output interface
#ifdef HAS_IF482 #ifdef HAS_IF482
IF482.begin(HAS_IF482); IF482.begin(HAS_IF482);
@ -337,7 +322,6 @@ void clock_init(void) {
// we use compile date to create a time_t reference "in the past" // we use compile date to create a time_t reference "in the past"
time_t compileTime(void) { time_t compileTime(void) {
char s_month[5]; char s_month[5];
int year; int year;
struct tm t = {0}; struct tm t = {0};
@ -347,9 +331,8 @@ time_t compileTime(void) {
static time_t secs = -1; static time_t secs = -1;
if (secs == -1) { if (secs == -1) {
// determine date // determine date
sscanf(__DATE__, "%s %d %d", s_month, &t.tm_mday, &year); sscanf(__DATE__, "%4s %d %d", s_month, &t.tm_mday, &year);
t.tm_mon = (strstr(month_names, s_month) - month_names) / 3; t.tm_mon = (strstr(month_names, s_month) - month_names) / 3;
t.tm_year = year - 1900; t.tm_year = year - 1900;
// determine time // determine time
@ -396,7 +379,6 @@ time_t mkgmtime(const struct tm *ptm) {
} }
void time_init(void) { void time_init(void) {
#if (defined HAS_IF482 || defined HAS_DCF77) #if (defined HAS_IF482 || defined HAS_DCF77)
ESP_LOGI(TAG, "Starting clock controller..."); ESP_LOGI(TAG, "Starting clock controller...");
clock_init(); clock_init();

View File

@ -56,7 +56,6 @@ void timesync_request(void) {
// task for processing time sync request // task for processing time sync request
void timesync_processReq(void *taskparameter) { void timesync_processReq(void *taskparameter) {
uint32_t rcv_seqNo = TIME_SYNC_END_FLAG; uint32_t rcv_seqNo = TIME_SYNC_END_FLAG;
uint32_t time_offset_sec = 0, time_offset_ms = 0; uint32_t time_offset_sec = 0, time_offset_ms = 0;
@ -68,7 +67,6 @@ void timesync_processReq(void *taskparameter) {
// --- asnychronous part: generate and collect timestamps from gateway --- // --- asnychronous part: generate and collect timestamps from gateway ---
while (1) { while (1) {
// wait for kickoff // wait for kickoff
ulTaskNotifyTake(pdFALSE, portMAX_DELAY); ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
@ -85,7 +83,6 @@ void timesync_processReq(void *taskparameter) {
// collect timestamp samples in timestamp array // collect timestamp samples in timestamp array
for (int8_t i = 0; i < TIME_SYNC_SAMPLES; i++) { for (int8_t i = 0; i < TIME_SYNC_SAMPLES; i++) {
// send timesync request // send timesync request
#if (TIME_SYNC_LORASERVER) // ask user's timeserver (for LoRAWAN < 1.0.3) #if (TIME_SYNC_LORASERVER) // ask user's timeserver (for LoRAWAN < 1.0.3)
payload.reset(); payload.reset();
@ -122,7 +119,6 @@ void timesync_processReq(void *taskparameter) {
// if we are not in last cycle, pause until next cycle // if we are not in last cycle, pause until next cycle
if (i < TIME_SYNC_SAMPLES - 1) if (i < TIME_SYNC_SAMPLES - 1)
vTaskDelay(pdMS_TO_TICKS(TIME_SYNC_CYCLE * 1000)); vTaskDelay(pdMS_TO_TICKS(TIME_SYNC_CYCLE * 1000));
} // for i } // for i
// --- time critial part: evaluate timestamps and calculate time --- // --- time critial part: evaluate timestamps and calculate time ---
@ -161,7 +157,6 @@ void timesync_processReq(void *taskparameter) {
// end of time critical section: release app irq lock // end of time critical section: release app irq lock
timeSyncPending = false; timeSyncPending = false;
unmask_user_IRQ(); unmask_user_IRQ();
} // infinite while(1) } // infinite while(1)
} }
@ -174,7 +169,6 @@ void timesync_store(uint32_t timestamp, timesync_t timestamp_type) {
// callback function to receive time answer from network or answer // callback function to receive time answer from network or answer
void timesync_serverAnswer(void *pUserData, int flag) { void timesync_serverAnswer(void *pUserData, int flag) {
#if (HAS_LORA_TIME) #if (HAS_LORA_TIME)
// if no timesync handshake is pending then exit // if no timesync handshake is pending then exit