commit
						c23c6f60da
					
				@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
Tutorial (in german language): https://www.heise.de/select/make/2019/1/1551099236518668
 | 
			
		||||
 | 
			
		||||
[](https://www.codefactor.io/repository/github/cyberman54/esp32-paxcounter)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<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*:
 | 
			
		||||
 | 
			
		||||
- **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
 | 
			
		||||
- 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
 | 
			
		||||
- 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),
 | 
			
		||||
 | 
			
		||||
@ -9,8 +9,10 @@
 | 
			
		||||
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
#include <OneBitDisplay.h>
 | 
			
		||||
extern ONE_BIT_DISPLAY *dp;
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
#include <TFT_eSPI.h>
 | 
			
		||||
extern TFT_eSPI *dp;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define DISPLAY_PAGES (7) // number of paxcounter display pages
 | 
			
		||||
@ -40,10 +42,10 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef MY_DISPLAY_FGCOLOR
 | 
			
		||||
#define MY_DISPLAY_FGCOLOR OLED_WHITE
 | 
			
		||||
#define MY_DISPLAY_FGCOLOR 1 // OLED_WHITE
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MY_DISPLAY_BGCOLOR
 | 
			
		||||
#define MY_DISPLAY_BGCOLOR OLED_BLACK
 | 
			
		||||
#define MY_DISPLAY_BGCOLOR 0 // OLED_BLACK
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// settings for TFT display library
 | 
			
		||||
@ -57,10 +59,10 @@
 | 
			
		||||
#define MY_DISPLAY_FIRSTLINE 30
 | 
			
		||||
 | 
			
		||||
#ifndef MY_DISPLAY_FGCOLOR
 | 
			
		||||
#define MY_DISPLAY_FGCOLOR TFT_WHITE
 | 
			
		||||
#define MY_DISPLAY_FGCOLOR 0xFFFF // TFT_WHITE
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MY_DISPLAY_BGCOLOR
 | 
			
		||||
#define MY_DISPLAY_BGCOLOR TFT_BLACK
 | 
			
		||||
#define MY_DISPLAY_BGCOLOR 0x0000 // TFT_BLACK
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef TOUCH_CS
 | 
			
		||||
@ -103,17 +105,12 @@ void dp_refresh(bool nextPage = false);
 | 
			
		||||
void dp_init(bool verbose = false);
 | 
			
		||||
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_dump(uint8_t *pBuffer = NULL);
 | 
			
		||||
void dp_setTextCursor(int col = 0, int row = MY_DISPLAY_FIRSTLINE);
 | 
			
		||||
void dp_contrast(uint8_t contrast);
 | 
			
		||||
void dp_clear(void);
 | 
			
		||||
void dp_power(uint8_t screenon);
 | 
			
		||||
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,
 | 
			
		||||
                         const uint16_t height, bool left = true);
 | 
			
		||||
void dp_scrollVertical(uint8_t *buf, const uint16_t width,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										343
									
								
								src/display.cpp
									
									
									
									
									
								
							
							
						
						
									
										343
									
								
								src/display.cpp
									
									
									
									
									
								
							@ -45,11 +45,12 @@ uint8_t DisplayIsOn = 0;
 | 
			
		||||
hw_timer_t *displayIRQ = NULL;
 | 
			
		||||
static QRCode qrcode;
 | 
			
		||||
 | 
			
		||||
// select display driver
 | 
			
		||||
#ifdef HAS_DISPLAY
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
static ONE_BIT_DISPLAY oled;
 | 
			
		||||
ONE_BIT_DISPLAY *dp = NULL;
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
static TFT_eSPI tft = TFT_eSPI(MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT);
 | 
			
		||||
TFT_eSPI *dp = NULL;
 | 
			
		||||
#else
 | 
			
		||||
#error Unknown display type specified in hal file
 | 
			
		||||
#endif
 | 
			
		||||
@ -58,20 +59,21 @@ static TFT_eSPI tft = TFT_eSPI(MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT);
 | 
			
		||||
void dp_setup(int contrast) {
 | 
			
		||||
 | 
			
		||||
#if (HAS_DISPLAY) == 1 // I2C OLED
 | 
			
		||||
  oled.setI2CPins(MY_DISPLAY_SDA, MY_DISPLAY_SCL, MY_DISPLAY_RST);
 | 
			
		||||
  oled.setBitBang(false);
 | 
			
		||||
  oled.I2Cbegin(OLED_TYPE, OLED_ADDR, OLED_FREQUENCY);
 | 
			
		||||
  oled.allocBuffer(); // render all outputs to lib internal backbuffer
 | 
			
		||||
  oled.setTextWrap(false);
 | 
			
		||||
  oled.setRotation(
 | 
			
		||||
  dp = new ONE_BIT_DISPLAY;
 | 
			
		||||
  dp->setI2CPins(MY_DISPLAY_SDA, MY_DISPLAY_SCL, MY_DISPLAY_RST);
 | 
			
		||||
  dp->setBitBang(false);
 | 
			
		||||
  dp->I2Cbegin(OLED_TYPE, OLED_ADDR, OLED_FREQUENCY);
 | 
			
		||||
  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°
 | 
			
		||||
 | 
			
		||||
#elif (HAS_DISPLAY) == 2 // SPI TFT
 | 
			
		||||
 | 
			
		||||
  tft.init();
 | 
			
		||||
  tft.setRotation(MY_DISPLAY_FLIP ? 3 : 1);
 | 
			
		||||
  tft.invertDisplay(MY_DISPLAY_INVERT ? true : false);
 | 
			
		||||
  tft.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
 | 
			
		||||
  dp = new TFT_eSPI(MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT);
 | 
			
		||||
  dp->init();
 | 
			
		||||
  dp->setRotation(MY_DISPLAY_FLIP ? 3 : 1);
 | 
			
		||||
  dp->invertDisplay(MY_DISPLAY_INVERT ? true : false);
 | 
			
		||||
  dp->setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -96,13 +98,14 @@ void dp_init(bool verbose) {
 | 
			
		||||
    esp_chip_info(&chip_info);
 | 
			
		||||
 | 
			
		||||
    dp_setFont(MY_FONT_NORMAL);
 | 
			
		||||
    dp_printf("** PAXCOUNTER **\r\n");
 | 
			
		||||
    dp_printf("Software v%s\r\n", PROGVERSION);
 | 
			
		||||
    dp_printf("ESP32 %d cores\r\n", chip_info.cores);
 | 
			
		||||
    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("** PAXCOUNTER **\r\n");
 | 
			
		||||
    dp->printf("Software v%s\r\n", PROGVERSION);
 | 
			
		||||
    dp->printf("ESP32 %d cores\r\n", chip_info.cores);
 | 
			
		||||
    dp->printf("Chip Rev.%d\r\n", chip_info.revision);
 | 
			
		||||
    dp->printf("WiFi%s%s\r\n",
 | 
			
		||||
               (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
 | 
			
		||||
               (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
 | 
			
		||||
    dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024),
 | 
			
		||||
    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
 | 
			
		||||
@ -125,11 +128,11 @@ void dp_init(bool verbose) {
 | 
			
		||||
    // display DEVEUI as plain text on the right
 | 
			
		||||
    const int x_offset = QR_SCALEFACTOR * 29 + 14;
 | 
			
		||||
    dp_setFont(MY_FONT_NORMAL);
 | 
			
		||||
    dp_setTextCursor(x_offset, 0);
 | 
			
		||||
    dp_printf("DEVEUI:\r\n");
 | 
			
		||||
    dp->setCursor(x_offset, 0);
 | 
			
		||||
    dp->printf("DEVEUI:\r\n");
 | 
			
		||||
    for (uint8_t i = 0; i <= 3; i++) {
 | 
			
		||||
      dp_setTextCursor(x_offset, i * 8 + 20);
 | 
			
		||||
      dp_printf("%4.4s", deveui + i * 4);
 | 
			
		||||
      dp->setCursor(x_offset, i * 8 + 20);
 | 
			
		||||
      dp->printf("%4.4s", deveui + i * 4);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // give user some time to read or take picture
 | 
			
		||||
@ -146,10 +149,18 @@ void dp_init(bool verbose) {
 | 
			
		||||
 | 
			
		||||
} // dp_init
 | 
			
		||||
 | 
			
		||||
// write display content to display buffer
 | 
			
		||||
// nextpage = true -> flip 1 page
 | 
			
		||||
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
 | 
			
		||||
  static uint32_t framecounter = 0;
 | 
			
		||||
  const uint32_t flip_threshold = DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // if display is switched off we don't refresh it to relax cpu
 | 
			
		||||
@ -164,103 +175,81 @@ void dp_refresh(bool nextPage) {
 | 
			
		||||
 | 
			
		||||
#ifndef HAS_BUTTON
 | 
			
		||||
  // auto flip page if we are in unattended mode
 | 
			
		||||
  if ((++framecounter) > (DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS)) {
 | 
			
		||||
  if (++framecounter > flip_threshold) {
 | 
			
		||||
    framecounter = 0;
 | 
			
		||||
    nextPage = true;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  dp_drawPage(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) {
 | 
			
		||||
  if (nextPage) {
 | 
			
		||||
    DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
 | 
			
		||||
    dp_clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 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);
 | 
			
		||||
  }
 | 
			
		||||
  } else
 | 
			
		||||
    dp->setCursor(0, 0);
 | 
			
		||||
 | 
			
		||||
  switch (DisplayPage) {
 | 
			
		||||
 | 
			
		||||
    // page 0: parameters overview
 | 
			
		||||
    // page 1: lorawan parameters
 | 
			
		||||
    // page 2: GPS
 | 
			
		||||
    // page 3: BME280/680
 | 
			
		||||
    // page 4: time
 | 
			
		||||
    // page 0: pax + parameters overview
 | 
			
		||||
    // page 1: pax + lorawan parameters
 | 
			
		||||
    // page 2: pax + GPS lat/lon
 | 
			
		||||
    // page 3: BME280/680 values
 | 
			
		||||
    // page 4: timeofday
 | 
			
		||||
    // page 5: pax graph
 | 
			
		||||
    // page 6: blank screen
 | 
			
		||||
 | 
			
		||||
    // ---------- page 0: parameters overview ----------
 | 
			
		||||
  case 0:
 | 
			
		||||
 | 
			
		||||
    // show pax
 | 
			
		||||
    libpax_counter_count(&count);
 | 
			
		||||
    dp_setFont(MY_FONT_LARGE);
 | 
			
		||||
    dp->printf("%-8d", count.pax);
 | 
			
		||||
 | 
			
		||||
    dp_setFont(MY_FONT_SMALL);
 | 
			
		||||
    dp_setTextCursor();
 | 
			
		||||
    dp->setCursor(0, MY_DISPLAY_FIRSTLINE);
 | 
			
		||||
 | 
			
		||||
    // line 3: wifi + bluetooth counters
 | 
			
		||||
    // WIFI:abcde BLTH:abcde
 | 
			
		||||
 | 
			
		||||
#if ((WIFICOUNTER) && (BLECOUNTER))
 | 
			
		||||
    if (cfg.wifiscan)
 | 
			
		||||
      dp_printf("WIFI:%-5d", count.wifi_count);
 | 
			
		||||
      dp->printf("WIFI:%-5d", count.wifi_count);
 | 
			
		||||
    else
 | 
			
		||||
      dp_printf("WIFI:off");
 | 
			
		||||
      dp->printf("WIFI:off");
 | 
			
		||||
    if (cfg.blescan)
 | 
			
		||||
      dp_printf("BLTH:%-5d", count.ble_count);
 | 
			
		||||
      dp->printf("BLTH:%-5d", count.ble_count);
 | 
			
		||||
    else
 | 
			
		||||
      dp_printf(" BLTH:off");
 | 
			
		||||
      dp->printf(" BLTH:off");
 | 
			
		||||
#elif ((WIFICOUNTER) && (!BLECOUNTER))
 | 
			
		||||
    if (cfg.wifiscan)
 | 
			
		||||
      dp_printf("WIFI:%-5d", count.wifi_count);
 | 
			
		||||
      dp->printf("WIFI:%-5d", count.wifi_count);
 | 
			
		||||
    else
 | 
			
		||||
      dp_printf("WIFI:off");
 | 
			
		||||
      dp->printf("WIFI:off");
 | 
			
		||||
#elif ((!WIFICOUNTER) && (BLECOUNTER))
 | 
			
		||||
    if (cfg.blescan)
 | 
			
		||||
      dp_printf("BLTH:%-5d", count.ble_count);
 | 
			
		||||
    dp_printf("BLTH:off");
 | 
			
		||||
      dp->printf("BLTH:%-5d", count.ble_count);
 | 
			
		||||
    dp->printf("BLTH:off");
 | 
			
		||||
#else
 | 
			
		||||
    dp_printf("Sniffer disabled");
 | 
			
		||||
    dp->printf("Sniffer disabled");
 | 
			
		||||
#endif
 | 
			
		||||
    dp_printf("\r\n");
 | 
			
		||||
    dp->printf("\r\n");
 | 
			
		||||
 | 
			
		||||
    // line 4: Battery + GPS status + Wifi channel
 | 
			
		||||
    // B:a.bcV Sats:ab ch:ab
 | 
			
		||||
#if (defined BAT_MEASURE_ADC || defined HAS_PMU || defined HAS_IP5306)
 | 
			
		||||
    if (batt_level == 0)
 | 
			
		||||
      dp_printf("No batt   ");
 | 
			
		||||
      dp->printf("No batt   ");
 | 
			
		||||
    else
 | 
			
		||||
      dp_printf("Batt:%3u%% ", batt_level);
 | 
			
		||||
      dp->printf("Batt:%3u%% ", batt_level);
 | 
			
		||||
#else
 | 
			
		||||
    dp_printf("          ");
 | 
			
		||||
    dp->printf("          ");
 | 
			
		||||
#endif
 | 
			
		||||
    dp_printf("chan:%02u\r\n", channel);
 | 
			
		||||
    dp->printf("chan:%02u\r\n", channel);
 | 
			
		||||
 | 
			
		||||
    // line 5: RSSI limiter + free memory
 | 
			
		||||
    // RLIM:abcd  Mem:abcdKB
 | 
			
		||||
    dp_printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
 | 
			
		||||
    dp_printf("  Mem:%4dKB\r\n", getFreeRAM() / 1024);
 | 
			
		||||
    dp->printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
 | 
			
		||||
    dp->printf("  Mem:%4dKB\r\n", getFreeRAM() / 1024);
 | 
			
		||||
 | 
			
		||||
    // line 6: time + date
 | 
			
		||||
    // Wed Jan 12 21:49:08 *
 | 
			
		||||
@ -270,15 +259,15 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
    time(&now);
 | 
			
		||||
    localtime_r(&now, &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
 | 
			
		||||
#if (defined HAS_DCF77) || (defined HAS_IF482)
 | 
			
		||||
    dp_setFont(MY_FONT_SMALL, 1);
 | 
			
		||||
    dp_printf("%c\r\n", timeState);
 | 
			
		||||
    dp->printf("%c\r\n", timeState);
 | 
			
		||||
    dp_setFont(MY_FONT_SMALL, 0);
 | 
			
		||||
#else
 | 
			
		||||
    dp_printf("%c\r\n", timeState);
 | 
			
		||||
    dp->printf("%c\r\n", timeState);
 | 
			
		||||
#endif
 | 
			
		||||
#endif // TIME_SYNC_INTERVAL
 | 
			
		||||
 | 
			
		||||
@ -287,10 +276,10 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
 | 
			
		||||
#if (HAS_LORA)
 | 
			
		||||
    // LMiC event display
 | 
			
		||||
    dp_printf("%-16s ", lmic_event_msg);
 | 
			
		||||
    dp->printf("%-16s ", lmic_event_msg);
 | 
			
		||||
    // LORA datarate, display inverse if ADR disabled
 | 
			
		||||
    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);
 | 
			
		||||
#endif // HAS_LORA
 | 
			
		||||
 | 
			
		||||
@ -308,19 +297,26 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
    // 6|fUp:000000 fDn:000000
 | 
			
		||||
    // 7|SNR:-0000  RSSI:-0000
 | 
			
		||||
 | 
			
		||||
    // show pax
 | 
			
		||||
    libpax_counter_count(&count);
 | 
			
		||||
    dp_setFont(MY_FONT_LARGE);
 | 
			
		||||
    dp->printf("%-8d", count.pax);
 | 
			
		||||
 | 
			
		||||
    dp_setFont(MY_FONT_SMALL);
 | 
			
		||||
    dp_setTextCursor();
 | 
			
		||||
    dp_printf("Net:%06X   Pwr:%-2d\r\n", LMIC.netid & 0x001FFFFF, LMIC.radio_txpow);
 | 
			
		||||
    dp_printf("Dev:%08X DR:%1d\r\n", LMIC.devaddr, LMIC.datarate);
 | 
			
		||||
    dp_printf("ChMsk:%04X Nonce:%04X\r\n", LMIC.channelMap, LMIC.devNonce);
 | 
			
		||||
    dp_printf("fUp:%-6d fDn:%-6d\r\n", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
 | 
			
		||||
    dp->setCursor(0, MY_DISPLAY_FIRSTLINE);
 | 
			
		||||
    dp->printf("Net:%06X   Pwr:%-2d\r\n", LMIC.netid & 0x001FFFFF,
 | 
			
		||||
               LMIC.radio_txpow);
 | 
			
		||||
    dp->printf("Dev:%08X DR:%1d\r\n", LMIC.devaddr, LMIC.datarate);
 | 
			
		||||
    dp->printf("ChMsk:%04X Nonce:%04X\r\n", LMIC.channelMap, LMIC.devNonce);
 | 
			
		||||
    dp->printf("fUp:%-6d fDn:%-6d\r\n", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
 | 
			
		||||
               LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0);
 | 
			
		||||
    dp_printf("SNR:%-5d  RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi);
 | 
			
		||||
    dp->printf("SNR:%-5d  RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi);
 | 
			
		||||
 | 
			
		||||
    dp_dump();
 | 
			
		||||
    break;
 | 
			
		||||
#else  // flip page if we are unattended
 | 
			
		||||
#else  // skip this page
 | 
			
		||||
    DisplayPage++;
 | 
			
		||||
    break;
 | 
			
		||||
#endif // HAS_LORA
 | 
			
		||||
 | 
			
		||||
  // ---------- page 2: GPS ----------
 | 
			
		||||
@ -328,23 +324,29 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
 | 
			
		||||
#if (HAS_GPS)
 | 
			
		||||
 | 
			
		||||
    // show pax
 | 
			
		||||
    libpax_counter_count(&count);
 | 
			
		||||
    dp_setFont(MY_FONT_LARGE);
 | 
			
		||||
    dp->printf("%-8d", count.pax);
 | 
			
		||||
 | 
			
		||||
    // show satellite status at bottom line
 | 
			
		||||
    dp_setFont(MY_FONT_SMALL);
 | 
			
		||||
    dp_setTextCursor(0, 56);
 | 
			
		||||
    dp_printf("%u Sats", gps.satellites.value());
 | 
			
		||||
    dp_printf(gps_hasfix() ? "         " : " - No fix");
 | 
			
		||||
    dp->setCursor(0, 56);
 | 
			
		||||
    dp->printf("%u Sats", gps.satellites.value());
 | 
			
		||||
    dp->printf(gps_hasfix() ? "         " : " - No fix");
 | 
			
		||||
 | 
			
		||||
    // show latitude and longitude
 | 
			
		||||
    dp_setFont(MY_FONT_STRETCHED);
 | 
			
		||||
    dp_setTextCursor();
 | 
			
		||||
    dp_printf("%c%09.6f\r\n", gps.location.rawLat().negative ? 'S' : 'N',
 | 
			
		||||
    dp->setCursor(0, MY_DISPLAY_FIRSTLINE);
 | 
			
		||||
    dp->printf("%c%09.6f\r\n", gps.location.rawLat().negative ? 'S' : 'N',
 | 
			
		||||
               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());
 | 
			
		||||
    dp_dump();
 | 
			
		||||
    break;
 | 
			
		||||
#else // flip page if we are unattended
 | 
			
		||||
#else // skip this page
 | 
			
		||||
    DisplayPage++;
 | 
			
		||||
    break;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // ---------- page 3: BME280/680 ----------
 | 
			
		||||
@ -352,17 +354,18 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
 | 
			
		||||
#if (HAS_BME)
 | 
			
		||||
    dp_setFont(MY_FONT_STRETCHED);
 | 
			
		||||
    dp_setTextCursor(0, 0);
 | 
			
		||||
    dp_printf("TMP: %-6.1f\r\n", bme_status.temperature);
 | 
			
		||||
    dp_printf("HUM: %-6.1f\r\n", bme_status.humidity);
 | 
			
		||||
    dp_printf("PRE: %-6.1f\r\n", bme_status.pressure);
 | 
			
		||||
    dp->setCursor(0, 0);
 | 
			
		||||
    dp->printf("TMP: %-6.1f\r\n", bme_status.temperature);
 | 
			
		||||
    dp->printf("HUM: %-6.1f\r\n", bme_status.humidity);
 | 
			
		||||
    dp->printf("PRE: %-6.1f\r\n", bme_status.pressure);
 | 
			
		||||
#ifdef HAS_BME680
 | 
			
		||||
    dp_printf("IAQ: %-6.0f", bme_status.iaq);
 | 
			
		||||
    dp->printf("IAQ: %-6.0f", bme_status.iaq);
 | 
			
		||||
#endif
 | 
			
		||||
    dp_dump();
 | 
			
		||||
    break; // page 3
 | 
			
		||||
#else      // flip page if we are unattended
 | 
			
		||||
    break;
 | 
			
		||||
#else  // skip this page
 | 
			
		||||
    DisplayPage++;
 | 
			
		||||
    break;
 | 
			
		||||
#endif // HAS_BME
 | 
			
		||||
 | 
			
		||||
  // ---------- page 4: time ----------
 | 
			
		||||
@ -370,16 +373,16 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
 | 
			
		||||
    time(&now);
 | 
			
		||||
    localtime_r(&now, &timeinfo);
 | 
			
		||||
    strftime(strftime_buf, sizeof(strftime_buf), "%T", &timeinfo);
 | 
			
		||||
 | 
			
		||||
    dp_setFont(MY_FONT_STRETCHED);
 | 
			
		||||
    dp_setTextCursor(0, 0);
 | 
			
		||||
    dp_printf("Timeofday:");
 | 
			
		||||
    dp_setTextCursor(0, 26);
 | 
			
		||||
    dp->setCursor(0, 0);
 | 
			
		||||
    dp->printf("Timeofday:");
 | 
			
		||||
    dp->setCursor(0, 26);
 | 
			
		||||
    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_printf("%21.1f", uptime() / 1000.0);
 | 
			
		||||
    dp->printf("%21.1f", uptime() / 1000.0);
 | 
			
		||||
    dp_dump();
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
@ -397,115 +400,69 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
#ifdef HAS_BUTTON
 | 
			
		||||
    dp_clear();
 | 
			
		||||
    break;
 | 
			
		||||
#else // flip page if we are unattended
 | 
			
		||||
#else // skip this page
 | 
			
		||||
    DisplayPage++;
 | 
			
		||||
    break;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  } // switch (page)
 | 
			
		||||
} // dp_drawPage
 | 
			
		||||
} // dp_refresh
 | 
			
		||||
 | 
			
		||||
// ------------- 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) {
 | 
			
		||||
 | 
			
		||||
  // handle invers printing
 | 
			
		||||
  if (inv)
 | 
			
		||||
    dp->setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR);
 | 
			
		||||
  else
 | 
			
		||||
    dp->setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
 | 
			
		||||
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
  // handle invers printing
 | 
			
		||||
  if (inv)
 | 
			
		||||
    oled.setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR);
 | 
			
		||||
  else
 | 
			
		||||
    oled.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
 | 
			
		||||
 | 
			
		||||
  // set desired font
 | 
			
		||||
  oled.setFont(font);
 | 
			
		||||
 | 
			
		||||
  dp->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
 | 
			
		||||
    dp->setTextFont(4);   // 26px
 | 
			
		||||
    break;
 | 
			
		||||
  case MY_FONT_SMALL:  // 6x8 on OLED
 | 
			
		||||
  case MY_FONT_NORMAL: // 8x8 on OLED
 | 
			
		||||
  default:
 | 
			
		||||
    tft.setTextFont(2); // 16px
 | 
			
		||||
    dp->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) {
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
  if (pBuffer)
 | 
			
		||||
    memcpy(oled.getBuffer(), pBuffer, PLOTBUFFERSIZE);
 | 
			
		||||
  oled.display();
 | 
			
		||||
    memcpy(dp->getBuffer(), pBuffer, PLOTBUFFERSIZE);
 | 
			
		||||
  dp->display();
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
  if (pBuffer)
 | 
			
		||||
    tft.drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT,
 | 
			
		||||
    dp->drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT,
 | 
			
		||||
                   MY_DISPLAY_FGCOLOR);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dp_clear(void) {
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
  oled.fillScreen(MY_DISPLAY_BGCOLOR);
 | 
			
		||||
  oled.display();
 | 
			
		||||
  dp->fillScreen(MY_DISPLAY_BGCOLOR);
 | 
			
		||||
  dp->display();
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
  tft.fillScreen(MY_DISPLAY_BGCOLOR);
 | 
			
		||||
  dp->fillScreen(MY_DISPLAY_BGCOLOR);
 | 
			
		||||
#endif
 | 
			
		||||
  dp_setTextCursor(0, 0);
 | 
			
		||||
  dp->setCursor(0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dp_contrast(uint8_t contrast) {
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
  oled.setContrast(contrast);
 | 
			
		||||
  dp->setContrast(contrast);
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
  // to do: gamma correction for TFT
 | 
			
		||||
#endif
 | 
			
		||||
@ -513,7 +470,7 @@ void dp_contrast(uint8_t contrast) {
 | 
			
		||||
 | 
			
		||||
void dp_power(uint8_t screenon) {
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
  oled.setPower(screenon);
 | 
			
		||||
  dp->setPower(screenon);
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
  // to come
 | 
			
		||||
#endif
 | 
			
		||||
@ -521,7 +478,7 @@ void dp_power(uint8_t screenon) {
 | 
			
		||||
 | 
			
		||||
void dp_shutdown(void) {
 | 
			
		||||
#if (HAS_DISPLAY) == 1
 | 
			
		||||
  oled.setPower(false);
 | 
			
		||||
  dp->setPower(false);
 | 
			
		||||
  delay(DISPLAYREFRESH_MS / 1000 * 1.1);
 | 
			
		||||
#elif (HAS_DISPLAY) == 2
 | 
			
		||||
  // to come
 | 
			
		||||
@ -531,8 +488,8 @@ void dp_shutdown(void) {
 | 
			
		||||
// 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->setCursor(0, line * 8);
 | 
			
		||||
  dp->printf("%-16s", msg);
 | 
			
		||||
  dp_dump();
 | 
			
		||||
} // dp_message
 | 
			
		||||
 | 
			
		||||
@ -546,32 +503,24 @@ 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 x = 0; x < qrcode.size; x++)
 | 
			
		||||
      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,
 | 
			
		||||
                    QR_SCALEFACTOR, false);
 | 
			
		||||
                     QR_SCALEFACTOR, MY_DISPLAY_FGCOLOR);
 | 
			
		||||
  // draw horizontal frame lines
 | 
			
		||||
  dp_fillRect(0, 0, qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y,
 | 
			
		||||
              false);
 | 
			
		||||
  dp_fillRect(0, qrcode.size * QR_SCALEFACTOR + offset_y,
 | 
			
		||||
              qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y, false);
 | 
			
		||||
  dp->fillRect(0, 0, qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y,
 | 
			
		||||
               MY_DISPLAY_FGCOLOR);
 | 
			
		||||
  dp->fillRect(0, qrcode.size * QR_SCALEFACTOR + offset_y,
 | 
			
		||||
               qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y,
 | 
			
		||||
               MY_DISPLAY_FGCOLOR);
 | 
			
		||||
  // draw vertical frame lines
 | 
			
		||||
  dp_fillRect(0, 0, offset_x, qrcode.size * QR_SCALEFACTOR + 2 * offset_y,
 | 
			
		||||
              false);
 | 
			
		||||
  dp_fillRect(qrcode.size * QR_SCALEFACTOR + offset_x, 0, offset_x,
 | 
			
		||||
              qrcode.size * QR_SCALEFACTOR + 2 * offset_y, false);
 | 
			
		||||
  dp->fillRect(0, 0, offset_x, qrcode.size * QR_SCALEFACTOR + 2 * offset_y,
 | 
			
		||||
               MY_DISPLAY_FGCOLOR);
 | 
			
		||||
  dp->fillRect(qrcode.size * QR_SCALEFACTOR + offset_x, 0, offset_x,
 | 
			
		||||
               qrcode.size * QR_SCALEFACTOR + 2 * offset_y, MY_DISPLAY_FGCOLOR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------- 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,
 | 
			
		||||
                 const uint8_t dot) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -87,7 +87,6 @@ byte CFG_CFG[] = {
 | 
			
		||||
// helper functions to send UBX commands to ublox gps chip
 | 
			
		||||
 | 
			
		||||
void sendPacket(byte *packet, byte len) {
 | 
			
		||||
 | 
			
		||||
  uint8_t CK_A = 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 disableNmea() {
 | 
			
		||||
 | 
			
		||||
  // tinygps++ processes only $GPGGA/$GNGGA and $GPRMC/$GNRMC
 | 
			
		||||
  // thus, we disable all other NMEA messages
 | 
			
		||||
 | 
			
		||||
@ -128,7 +126,6 @@ void disableNmea() {
 | 
			
		||||
 | 
			
		||||
// initialize and configure GPS
 | 
			
		||||
int gps_init(void) {
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Opening serial GPS");
 | 
			
		||||
 | 
			
		||||
  GPS_Serial.begin(GPS_SERIAL);
 | 
			
		||||
@ -144,7 +141,6 @@ int gps_init(void) {
 | 
			
		||||
  disableNmea();
 | 
			
		||||
 | 
			
		||||
  return 1;
 | 
			
		||||
 | 
			
		||||
} // gps_init()
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
time_t get_gpstime(uint16_t *msec = 0) {
 | 
			
		||||
 | 
			
		||||
  const uint16_t txDelay =
 | 
			
		||||
      70U * 1000 / (GPS_BAUDRATE / 9); // serial tx of 70 NMEA chars
 | 
			
		||||
 | 
			
		||||
  // did we get a current date & time?
 | 
			
		||||
  if (gps.time.age() < 1000) {
 | 
			
		||||
 | 
			
		||||
    // convert tinygps time format to struct tm format
 | 
			
		||||
    struct tm gps_tm = {0};
 | 
			
		||||
    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");
 | 
			
		||||
  return 0;
 | 
			
		||||
 | 
			
		||||
} // get_gpstime()
 | 
			
		||||
 | 
			
		||||
// GPS serial feed FreeRTos Task
 | 
			
		||||
void gps_loop(void *pvParameters) {
 | 
			
		||||
 | 
			
		||||
  _ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
 | 
			
		||||
 | 
			
		||||
  // feed GPS decoder with serial NMEA data from GPS device
 | 
			
		||||
  while (1) {
 | 
			
		||||
    while (cfg.payloadmask & GPS_DATA) {
 | 
			
		||||
 | 
			
		||||
      while (GPS_Serial.available())
 | 
			
		||||
        gps.encode(GPS_Serial.read());
 | 
			
		||||
 | 
			
		||||
@ -228,7 +219,6 @@ void gps_loop(void *pvParameters) {
 | 
			
		||||
    }
 | 
			
		||||
    delay(1000);
 | 
			
		||||
  } // infinite while loop
 | 
			
		||||
 | 
			
		||||
} // gps_loop()
 | 
			
		||||
 | 
			
		||||
#endif // HAS_GPS
 | 
			
		||||
 | 
			
		||||
@ -70,7 +70,6 @@ void refreshTheMatrixDisplay(bool nextPage) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (DisplayPage % MATRIX_DISPLAY_PAGES) {
 | 
			
		||||
 | 
			
		||||
    // page 0: number of current pax OR footfall line diagram
 | 
			
		||||
    // page 1: time of day
 | 
			
		||||
 | 
			
		||||
@ -89,18 +88,14 @@ void refreshTheMatrixDisplay(bool nextPage) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else { // cyclic counter mode -> plot a line diagram
 | 
			
		||||
 | 
			
		||||
      if (ulLastNumMacs != count.pax) {
 | 
			
		||||
 | 
			
		||||
        // next count cycle?
 | 
			
		||||
        if (count.pax == 0) {
 | 
			
		||||
 | 
			
		||||
          // matrix full? then scroll left 1 dot, else increment column
 | 
			
		||||
          if (col < (LED_MATRIX_WIDTH - 1))
 | 
			
		||||
            col++;
 | 
			
		||||
          else
 | 
			
		||||
            ScrollMatrixLeft(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT);
 | 
			
		||||
 | 
			
		||||
        } else
 | 
			
		||||
          matrix.drawPoint(col, row, 0); // clear current dot
 | 
			
		||||
 | 
			
		||||
@ -124,7 +119,6 @@ void refreshTheMatrixDisplay(bool nextPage) {
 | 
			
		||||
      // DrawNumber(myTZ.dateTime("H:i:s").c_str());
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  } // switch page
 | 
			
		||||
 | 
			
		||||
  matrix.scan();
 | 
			
		||||
 | 
			
		||||
@ -21,18 +21,17 @@ TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
 | 
			
		||||
char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer for LMIC event message
 | 
			
		||||
 | 
			
		||||
class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  MyHalConfig_t(){};
 | 
			
		||||
 | 
			
		||||
  // 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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 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{};
 | 
			
		||||
@ -50,9 +49,7 @@ static const lmic_pinmap myPinmap = {
 | 
			
		||||
    .pConfig = &myHalConfig};
 | 
			
		||||
 | 
			
		||||
void lora_setupForNetwork(bool preJoin) {
 | 
			
		||||
 | 
			
		||||
  if (preJoin) {
 | 
			
		||||
 | 
			
		||||
#if CFG_LMIC_US_like
 | 
			
		||||
    // 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
 | 
			
		||||
@ -196,7 +193,6 @@ void lora_send(void *pvParameters) {
 | 
			
		||||
  MessageBuffer_t SendBuffer;
 | 
			
		||||
 | 
			
		||||
  while (1) {
 | 
			
		||||
 | 
			
		||||
    // postpone until we are joined if we are not
 | 
			
		||||
    while (!LMIC.devaddr) {
 | 
			
		||||
      vTaskDelay(pdMS_TO_TICKS(500));
 | 
			
		||||
@ -213,7 +209,6 @@ void lora_send(void *pvParameters) {
 | 
			
		||||
    switch (LMIC_setTxData2_strict(SendBuffer.MessagePort, SendBuffer.Message,
 | 
			
		||||
                                   SendBuffer.MessageSize,
 | 
			
		||||
                                   (cfg.countermode & 0x02))) {
 | 
			
		||||
 | 
			
		||||
    case LMIC_ERROR_SUCCESS:
 | 
			
		||||
#if (TIME_SYNC_LORASERVER)
 | 
			
		||||
      // if last packet sent was a timesync request, store TX timestamp
 | 
			
		||||
@ -237,7 +232,6 @@ void lora_send(void *pvParameters) {
 | 
			
		||||
      break;
 | 
			
		||||
    default: // other LMIC return code
 | 
			
		||||
      ESP_LOGE(TAG, "LMIC error, message not sent and deleted");
 | 
			
		||||
 | 
			
		||||
    }         // switch
 | 
			
		||||
    delay(2); // yield to CPU
 | 
			
		||||
  }           // while(1)
 | 
			
		||||
@ -351,7 +345,6 @@ void lmictask(void *pvParameters) {
 | 
			
		||||
 | 
			
		||||
// lmic event handler
 | 
			
		||||
void myEventCallback(void *pUserData, ev_t ev) {
 | 
			
		||||
 | 
			
		||||
  // using message descriptors from LMIC library
 | 
			
		||||
  static const char *const evNames[] = {LMIC_EVENT_NAME_TABLE__INIT};
 | 
			
		||||
  // get current length of lora send queue
 | 
			
		||||
@ -366,7 +359,6 @@ void myEventCallback(void *pUserData, ev_t ev) {
 | 
			
		||||
 | 
			
		||||
  // process current event message
 | 
			
		||||
  switch (ev) {
 | 
			
		||||
 | 
			
		||||
  case EV_TXCOMPLETE:
 | 
			
		||||
    // -> processed in lora_send()
 | 
			
		||||
    break;
 | 
			
		||||
@ -411,7 +403,6 @@ void myEventCallback(void *pUserData, ev_t ev) {
 | 
			
		||||
// event EV_RXCOMPLETE message handler
 | 
			
		||||
void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
 | 
			
		||||
                  size_t nMsg) {
 | 
			
		||||
 | 
			
		||||
  // display amount of received data
 | 
			
		||||
  if (nMsg)
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
  switch (port) {
 | 
			
		||||
 | 
			
		||||
  // rcommand received -> call interpreter
 | 
			
		||||
  case RCMDPORT:
 | 
			
		||||
    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);
 | 
			
		||||
    break;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  } // switch
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -513,7 +502,6 @@ bool ttn_rtc_restore() {
 | 
			
		||||
// https://github.com/JackGruber/ESP32-LMIC-DeepSleep-example/blob/master/src/main.cpp
 | 
			
		||||
 | 
			
		||||
void SaveLMICToRTC(int deepsleep_sec) {
 | 
			
		||||
 | 
			
		||||
  // ESP32 can't track millis during DeepSleep and no option to advance
 | 
			
		||||
  // millis after DeepSleep. Therefore reset DutyCyles before saving LMIC struct
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -185,7 +185,7 @@ void setup() {
 | 
			
		||||
 | 
			
		||||
// initialize display
 | 
			
		||||
#ifdef HAS_DISPLAY
 | 
			
		||||
  strcat_P(features, " OLED");
 | 
			
		||||
  strcat_P(features, " DISP");
 | 
			
		||||
  DisplayIsOn = cfg.screenon;
 | 
			
		||||
  // display verbose info only after a coldstart (note: blocking call!)
 | 
			
		||||
  dp_init(RTC_runmode == RUNMODE_POWERCYCLE ? true : false);
 | 
			
		||||
@ -213,7 +213,7 @@ void setup() {
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_TWO_LED
 | 
			
		||||
  pinMode(HAS_TWO_LED, OUTPUT);
 | 
			
		||||
  strcat_P(features, " LED1");
 | 
			
		||||
  strcat_P(features, " LED2");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// use LED for power display if we have additional RGB LED, else for status
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								src/ota.cpp
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/ota.cpp
									
									
									
									
									
								
							@ -41,7 +41,6 @@ inline String getHeaderValue(String header, String headerName) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void start_ota_update() {
 | 
			
		||||
 | 
			
		||||
  const char *host = clientId;
 | 
			
		||||
 | 
			
		||||
  switch_LED(LED_ON);
 | 
			
		||||
@ -51,12 +50,12 @@ void start_ota_update() {
 | 
			
		||||
 | 
			
		||||
  dp_setup();
 | 
			
		||||
  dp_setFont(MY_FONT_NORMAL);
 | 
			
		||||
  dp_printf("SOFTWARE UPDATE\r\n");
 | 
			
		||||
  dp_printf("WiFi connect  ..\r\n");
 | 
			
		||||
  dp_printf("Has Update?   ..\r\n");
 | 
			
		||||
  dp_printf("Fetching      ..\r\n");
 | 
			
		||||
  dp_printf("Downloading   ..\r\n");
 | 
			
		||||
  dp_printf("Rebooting     ..\r\n");
 | 
			
		||||
  dp->printf("SOFTWARE UPDATE\r\n");
 | 
			
		||||
  dp->printf("WiFi connect  ..\r\n");
 | 
			
		||||
  dp->printf("Has Update?   ..\r\n");
 | 
			
		||||
  dp->printf("Fetching      ..\r\n");
 | 
			
		||||
  dp->printf("Downloading   ..\r\n");
 | 
			
		||||
  dp->printf("Rebooting     ..\r\n");
 | 
			
		||||
  dp_dump();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -121,13 +120,11 @@ end:
 | 
			
		||||
  ota_display(5, "**", ""); // mark line rebooting
 | 
			
		||||
  delay(5000);
 | 
			
		||||
  do_reset(false);
 | 
			
		||||
 | 
			
		||||
} // start_ota_update
 | 
			
		||||
 | 
			
		||||
// Reads data vom wifi client and flashes it to ota partition
 | 
			
		||||
// returns: 0 = finished, 1 = retry, -1 = abort
 | 
			
		||||
int do_ota_update() {
 | 
			
		||||
 | 
			
		||||
  char buf[17];
 | 
			
		||||
  bool redirect = true;
 | 
			
		||||
  size_t written = 0;
 | 
			
		||||
@ -319,18 +316,17 @@ abort:
 | 
			
		||||
 | 
			
		||||
retry:
 | 
			
		||||
  return 1;
 | 
			
		||||
 | 
			
		||||
} // do_ota_update
 | 
			
		||||
 | 
			
		||||
void ota_display(const uint8_t row, const std::string status,
 | 
			
		||||
                 const std::string msg) {
 | 
			
		||||
#ifdef HAS_DISPLAY
 | 
			
		||||
  dp_setTextCursor(14 * 8, row * 8);
 | 
			
		||||
  dp_printf(status.substr(0, 2).c_str());
 | 
			
		||||
  dp->setCursor(14 * 8, row * 8);
 | 
			
		||||
  dp->printf(status.substr(0, 2).c_str());
 | 
			
		||||
  if (!msg.empty()) {
 | 
			
		||||
    dp_printf("                ");
 | 
			
		||||
    dp_printf(msg.substr(0, 16).c_str());
 | 
			
		||||
    // dp_printf("\r\n");
 | 
			
		||||
    dp->printf("                ");
 | 
			
		||||
    dp->printf(msg.substr(0, 16).c_str());
 | 
			
		||||
    // dp->printf("\r\n");
 | 
			
		||||
  }
 | 
			
		||||
  dp_dump();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,6 @@ static const adc_unit_t unit = ADC_UNIT_1;
 | 
			
		||||
AXP20X_Class pmu;
 | 
			
		||||
 | 
			
		||||
void AXP192_powerevent_IRQ(void) {
 | 
			
		||||
 | 
			
		||||
  pmu.readIRQ();
 | 
			
		||||
 | 
			
		||||
  if (pmu.isVbusOverVoltageIRQ())
 | 
			
		||||
@ -83,9 +82,7 @@ void AXP192_powerevent_IRQ(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AXP192_power(pmu_power_t powerlevel) {
 | 
			
		||||
 | 
			
		||||
  switch (powerlevel) {
 | 
			
		||||
 | 
			
		||||
  case pmu_power_off:
 | 
			
		||||
    pmu.shutdown();
 | 
			
		||||
    break;
 | 
			
		||||
@ -119,7 +116,6 @@ void AXP192_power(pmu_power_t powerlevel) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AXP192_showstatus(void) {
 | 
			
		||||
 | 
			
		||||
  if (pmu.isBatteryConnect())
 | 
			
		||||
    if (pmu.isChargeing())
 | 
			
		||||
      ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh",
 | 
			
		||||
@ -137,12 +133,10 @@ void AXP192_showstatus(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AXP192_init(void) {
 | 
			
		||||
 | 
			
		||||
  if (pmu.begin(i2c_readBytes, i2c_writeBytes, AXP192_PRIMARY_ADDRESS) ==
 | 
			
		||||
      AXP_FAIL)
 | 
			
		||||
    ESP_LOGI(TAG, "AXP192 PMU initialization failed");
 | 
			
		||||
  else {
 | 
			
		||||
 | 
			
		||||
    // configure voltages
 | 
			
		||||
    pmu.setDCDC1Voltage(3300); // for external OLED display
 | 
			
		||||
    pmu.setLDO2Voltage(3300);  // LORA VDD 3v3
 | 
			
		||||
 | 
			
		||||
@ -234,7 +234,6 @@ void set_loradr(uint8_t val[]) {
 | 
			
		||||
             getSfName(updr2rps(LMIC.datarate)),
 | 
			
		||||
             getBwName(updr2rps(LMIC.datarate)),
 | 
			
		||||
             getCrName(updr2rps(LMIC.datarate)));
 | 
			
		||||
 | 
			
		||||
  } else
 | 
			
		||||
    ESP_LOGI(
 | 
			
		||||
        TAG,
 | 
			
		||||
@ -430,14 +429,12 @@ static const uint8_t cmdtablesize =
 | 
			
		||||
 | 
			
		||||
// check and execute remote command
 | 
			
		||||
void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) {
 | 
			
		||||
 | 
			
		||||
  if (cmdlength == 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  uint8_t foundcmd[cmdlength], cursor = 0;
 | 
			
		||||
 | 
			
		||||
  while (cursor < cmdlength) {
 | 
			
		||||
 | 
			
		||||
    int i = cmdtablesize;
 | 
			
		||||
    while (i--) {
 | 
			
		||||
      if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table
 | 
			
		||||
@ -462,7 +459,6 @@ void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  } // command parsing loop
 | 
			
		||||
 | 
			
		||||
} //  rcmd_execute()
 | 
			
		||||
 | 
			
		||||
// remote command processing task
 | 
			
		||||
@ -485,9 +481,7 @@ void rcmd_process(void *pvParameters) {
 | 
			
		||||
 | 
			
		||||
// enqueue remote command
 | 
			
		||||
void rcommand(const uint8_t *cmd, const size_t cmdlength) {
 | 
			
		||||
 | 
			
		||||
  RcmdBuffer_t rcmd = {0};
 | 
			
		||||
 | 
			
		||||
  rcmd.cmdLen = cmdlength;
 | 
			
		||||
  memcpy(rcmd.cmd, cmd, cmdlength);
 | 
			
		||||
 | 
			
		||||
@ -505,7 +499,6 @@ void rcmd_deinit(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
esp_err_t rcmd_init(void) {
 | 
			
		||||
 | 
			
		||||
  _ASSERT(RCMD_QUEUE_SIZE > 0);
 | 
			
		||||
  RcmdQueue = xQueueCreate(RCMD_QUEUE_SIZE, sizeof(RcmdBuffer_t));
 | 
			
		||||
  if (RcmdQueue == 0) {
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,6 @@ void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
 | 
			
		||||
#ifdef GPS_INT
 | 
			
		||||
// interrupt service routine triggered by GPS PPS
 | 
			
		||||
void IRAM_ATTR GPSIRQ(void) {
 | 
			
		||||
 | 
			
		||||
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 | 
			
		||||
 | 
			
		||||
  // take timestamp
 | 
			
		||||
@ -54,7 +53,6 @@ void IRAM_ATTR GPSIRQ(void) {
 | 
			
		||||
 | 
			
		||||
// interrupt service routine triggered by esp32 hardware timer
 | 
			
		||||
void IRAM_ATTR CLOCKIRQ(void) {
 | 
			
		||||
 | 
			
		||||
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 | 
			
		||||
 | 
			
		||||
// advance wall clock, if we have
 | 
			
		||||
@ -79,7 +77,6 @@ void IRAM_ATTR CLOCKIRQ(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void calibrateTime(void) {
 | 
			
		||||
 | 
			
		||||
  // kick off asynchronous lora timesync if we have
 | 
			
		||||
#if (HAS_LORA_TIME)
 | 
			
		||||
  timesync_request();
 | 
			
		||||
@ -106,12 +103,10 @@ void calibrateTime(void) {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // calibrateTime()
 | 
			
		||||
 | 
			
		||||
// set system time (UTC), calibrate RTC and RTC_INT pps
 | 
			
		||||
bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
 | 
			
		||||
 | 
			
		||||
  struct timeval tv = {0};
 | 
			
		||||
 | 
			
		||||
  // 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?
 | 
			
		||||
  if (timeIsValid(time_to_set)) {
 | 
			
		||||
 | 
			
		||||
    // if we have msec fraction, then wait until top of second with
 | 
			
		||||
    // millisecond precision
 | 
			
		||||
    if (t_msec % 1000) {
 | 
			
		||||
@ -160,7 +154,6 @@ bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
 | 
			
		||||
    return true;
 | 
			
		||||
 | 
			
		||||
  } else {
 | 
			
		||||
 | 
			
		||||
    timesyncer.attach(TIME_SYNC_INTERVAL_RETRY * 60, setTimeSyncIRQ);
 | 
			
		||||
    ESP_LOGV(TAG,
 | 
			
		||||
             "[%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
 | 
			
		||||
void timepulse_init(void) {
 | 
			
		||||
 | 
			
		||||
  // set esp-idf API sntp sync mode
 | 
			
		||||
  // sntp_init();
 | 
			
		||||
  sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED);
 | 
			
		||||
@ -210,7 +202,6 @@ void timepulse_init(void) {
 | 
			
		||||
 | 
			
		||||
  // start cyclic time sync
 | 
			
		||||
  timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
 | 
			
		||||
 | 
			
		||||
} // timepulse_init
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
 | 
			
		||||
                    int8_t rxPin, int8_t txPins) {
 | 
			
		||||
 | 
			
		||||
  uint32_t databits = ((config & 0x0c) >> 2) + 5;
 | 
			
		||||
  uint32_t stopbits = ((config & 0x20) >> 5) + 1;
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
  uint32_t current_time = 0, previous_time = 0;
 | 
			
		||||
  time_t tt;
 | 
			
		||||
  struct tm t = {0};
 | 
			
		||||
@ -248,7 +237,6 @@ void clock_loop(void *taskparameter) { // ClockTask
 | 
			
		||||
 | 
			
		||||
  // output the next second's pulse/telegram after pps arrived
 | 
			
		||||
  for (;;) {
 | 
			
		||||
 | 
			
		||||
    // wait for timepulse and store UTC time
 | 
			
		||||
    xTaskNotifyWait(0x00, ULONG_MAX, ¤t_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(),
 | 
			
		||||
               t.tm_min);
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
      // generate impulse
 | 
			
		||||
      if (t.tm_min == ClockMinute) { // ensure frame is recent
 | 
			
		||||
        DCF77_Pulse(ClockPulse & 1); // output next second
 | 
			
		||||
@ -311,12 +298,10 @@ void clock_loop(void *taskparameter) { // ClockTask
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    previous_time = current_time;
 | 
			
		||||
 | 
			
		||||
  } // for
 | 
			
		||||
} // clock_loop()
 | 
			
		||||
 | 
			
		||||
void clock_init(void) {
 | 
			
		||||
 | 
			
		||||
// setup clock output interface
 | 
			
		||||
#ifdef 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"
 | 
			
		||||
time_t compileTime(void) {
 | 
			
		||||
 | 
			
		||||
  char s_month[5];
 | 
			
		||||
  int year;
 | 
			
		||||
  struct tm t = {0};
 | 
			
		||||
@ -347,7 +331,6 @@ time_t compileTime(void) {
 | 
			
		||||
  static time_t secs = -1;
 | 
			
		||||
 | 
			
		||||
  if (secs == -1) {
 | 
			
		||||
 | 
			
		||||
    // determine date
 | 
			
		||||
    sscanf(__DATE__, "%s %d %d", s_month, &t.tm_mday, &year);
 | 
			
		||||
    t.tm_mon = (strstr(month_names, s_month) - month_names) / 3;
 | 
			
		||||
@ -396,7 +379,6 @@ time_t mkgmtime(const struct tm *ptm) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void time_init(void) {
 | 
			
		||||
 | 
			
		||||
#if (defined HAS_IF482 || defined HAS_DCF77)
 | 
			
		||||
  ESP_LOGI(TAG, "Starting clock controller...");
 | 
			
		||||
  clock_init();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user