Merge pull request #338 from cyberman54/development
New feature display pages & flip by button
This commit is contained in:
commit
fc60ade4d2
@ -46,7 +46,7 @@ Depending on board hardware following features are supported:
|
|||||||
- LED (shows power & status)
|
- LED (shows power & status)
|
||||||
- OLED Display (shows detailed status)
|
- OLED Display (shows detailed status)
|
||||||
- RGB LED (shows colorized status)
|
- RGB LED (shows colorized status)
|
||||||
- Button
|
- Button (used to flip display pages if device has display, else sends alarm message)
|
||||||
- Silicon unique ID
|
- Silicon unique ID
|
||||||
- Battery voltage monitoring
|
- Battery voltage monitoring
|
||||||
- GPS (Generic serial NMEA, or Quectel L76 I2C)
|
- GPS (Generic serial NMEA, or Quectel L76 I2C)
|
||||||
@ -140,6 +140,10 @@ Paxcounter generates identifiers for sniffed MAC adresses and collects them temp
|
|||||||
- Red long blink: LoRaWAN stack error
|
- Red long blink: LoRaWAN stack error
|
||||||
- White long blink: Known Beacon detected
|
- White long blink: Known Beacon detected
|
||||||
|
|
||||||
|
# Display
|
||||||
|
|
||||||
|
If you're using a device with OLED display, or if you add such one to the I2C bus, the device shows live data on the display. You can flip between pages showing pax, time and gps data by pressing the button of the device.
|
||||||
|
|
||||||
# Sensors and Peripherals
|
# Sensors and Peripherals
|
||||||
|
|
||||||
You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable *flag lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options.
|
You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable *flag lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef _BUTTON_H
|
#ifndef _BUTTON_H
|
||||||
#define _BUTTON_H
|
#define _BUTTON_H
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
#include "senddata.h"
|
#include "senddata.h"
|
||||||
|
|
||||||
void readButton();
|
void readButton();
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
#include <U8x8lib.h>
|
#include <U8x8lib.h>
|
||||||
#include "cyclic.h"
|
#include "cyclic.h"
|
||||||
|
|
||||||
extern uint8_t DisplayState;
|
extern uint8_t DisplayIsOn;
|
||||||
|
|
||||||
extern HAS_DISPLAY u8x8;
|
extern HAS_DISPLAY u8x8;
|
||||||
|
|
||||||
void init_display(const char *Productname, const char *Version);
|
void init_display(const char *Productname, const char *Version);
|
||||||
void refreshtheDisplay(void);
|
void refreshtheDisplay(void);
|
||||||
|
void refreshtheDisplay(bool nextPage);
|
||||||
|
void draw_page(time_t t, uint8_t page);
|
||||||
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
|
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -7,9 +7,13 @@
|
|||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
void readButton() {
|
void readButton() {
|
||||||
ESP_LOGI(TAG, "Button pressed");
|
ESP_LOGI(TAG, "Button pressed");
|
||||||
payload.reset();
|
#ifdef HAS_DISPLAY
|
||||||
payload.addButton(0x01);
|
refreshtheDisplay(true); // switch to next display page
|
||||||
SendPayload(BUTTONPORT, prio_normal);
|
#else
|
||||||
|
payload.reset();
|
||||||
|
payload.addButton(0x01);
|
||||||
|
SendPayload(BUTTONPORT, prio_normal);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
118
src/display.cpp
118
src/display.cpp
@ -26,6 +26,8 @@ line 7: y = Text for LMIC status; ab = payload queue
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
||||||
|
|
||||||
|
#define DISPLAY_PAGES (3) // number of display pages
|
||||||
|
|
||||||
HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA);
|
HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA);
|
||||||
|
|
||||||
// helper string for converting LoRa spread factor values
|
// helper string for converting LoRa spread factor values
|
||||||
@ -45,7 +47,7 @@ const char lora_datarate[] = {"121110090807FSNA"};
|
|||||||
const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
|
|
||||||
uint8_t DisplayState = 0;
|
uint8_t DisplayIsOn = 0;
|
||||||
|
|
||||||
// helper function, prints a hex key on display
|
// helper function, prints a hex key on display
|
||||||
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
|
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
|
||||||
@ -127,28 +129,53 @@ void init_display(const char *Productname, const char *Version) {
|
|||||||
} // mutex
|
} // mutex
|
||||||
} // init_display
|
} // init_display
|
||||||
|
|
||||||
void refreshtheDisplay() {
|
void refreshtheDisplay(bool nextPage) {
|
||||||
|
|
||||||
uint8_t msgWaiting;
|
static uint8_t DisplayPage = 0;
|
||||||
char timeState, buff[16];
|
|
||||||
const time_t t =
|
const time_t t =
|
||||||
myTZ.toLocal(now()); // note: call now() here *before* locking mutex!
|
myTZ.toLocal(now()); // note: call now() here *before* locking mutex!
|
||||||
|
|
||||||
|
// if display is switched off we don't refresh it to relax cpu
|
||||||
|
if (!DisplayIsOn && (DisplayIsOn == cfg.screenon))
|
||||||
|
return;
|
||||||
|
|
||||||
// block i2c bus access
|
// block i2c bus access
|
||||||
if (I2C_MUTEX_LOCK()) {
|
if (I2C_MUTEX_LOCK()) {
|
||||||
|
|
||||||
// set display on/off according to current device configuration
|
// set display on/off according to current device configuration
|
||||||
if (DisplayState != cfg.screenon) {
|
if (DisplayIsOn != cfg.screenon) {
|
||||||
DisplayState = cfg.screenon;
|
DisplayIsOn = cfg.screenon;
|
||||||
u8x8.setPowerSave(!cfg.screenon);
|
u8x8.setPowerSave(!cfg.screenon);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if display is switched off we don't refresh it to relax cpu
|
if (nextPage) {
|
||||||
if (!DisplayState) {
|
DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
u8x8.clear();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
draw_page(t, DisplayPage);
|
||||||
|
|
||||||
|
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||||
|
|
||||||
|
} // mutex
|
||||||
|
} // refreshDisplay()
|
||||||
|
|
||||||
|
void refreshtheDisplay() { refreshtheDisplay(false); }
|
||||||
|
|
||||||
|
void draw_page(time_t t, uint8_t page) {
|
||||||
|
|
||||||
|
char timeState, buff[16];
|
||||||
|
uint8_t msgWaiting;
|
||||||
|
static bool wasnofix = true;
|
||||||
|
|
||||||
|
switch (page % DISPLAY_PAGES) {
|
||||||
|
|
||||||
|
// page 0: parameters overview
|
||||||
|
// page 1: time
|
||||||
|
// page 2: GPS
|
||||||
|
// page 3: BME280/680
|
||||||
|
|
||||||
|
case 0:
|
||||||
// update counter (lines 0-1)
|
// update counter (lines 0-1)
|
||||||
snprintf(
|
snprintf(
|
||||||
buff, sizeof(buff), "PAX:%-4d",
|
buff, sizeof(buff), "PAX:%-4d",
|
||||||
@ -218,7 +245,7 @@ void refreshtheDisplay() {
|
|||||||
TimePulseTick = false;
|
TimePulseTick = false;
|
||||||
// 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)
|
||||||
u8x8.printf("%02d:%02d:%02d", hour(t), minute(t), second(t), timeState);
|
u8x8.printf("%02d:%02d:%02d", hour(t), minute(t), second(t));
|
||||||
u8x8.setInverseFont(1);
|
u8x8.setInverseFont(1);
|
||||||
u8x8.printf("%c", timeState);
|
u8x8.printf("%c", timeState);
|
||||||
u8x8.setInverseFont(0);
|
u8x8.setInverseFont(0);
|
||||||
@ -251,8 +278,71 @@ void refreshtheDisplay() {
|
|||||||
|
|
||||||
#endif // HAS_LORA
|
#endif // HAS_LORA
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
break; // page0
|
||||||
} // mutex
|
|
||||||
} // refreshDisplay()
|
case 1:
|
||||||
|
// update counter (lines 0-1)
|
||||||
|
snprintf(
|
||||||
|
buff, sizeof(buff), "PAX:%-4d",
|
||||||
|
(int)
|
||||||
|
macs.size()); // convert 16-bit MAC counter to decimal counter value
|
||||||
|
u8x8.draw2x2String(0, 0,
|
||||||
|
buff); // display number on unique macs total Wifi + BLE
|
||||||
|
|
||||||
|
// line 4-5: update time-of-day
|
||||||
|
snprintf(buff, sizeof(buff), "%02d:%02d:%02d", hour(t), minute(t),
|
||||||
|
second(t));
|
||||||
|
u8x8.draw2x2String(0, 4, buff);
|
||||||
|
|
||||||
|
break; // page1
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// update counter (lines 0-1)
|
||||||
|
snprintf(
|
||||||
|
buff, sizeof(buff), "PAX:%-4d",
|
||||||
|
(int)
|
||||||
|
macs.size()); // convert 16-bit MAC counter to decimal counter value
|
||||||
|
u8x8.draw2x2String(0, 0,
|
||||||
|
buff); // display number on unique macs total Wifi + BLE
|
||||||
|
|
||||||
|
#if (HAS_GPS)
|
||||||
|
if (gps.location.age() < 1500) {
|
||||||
|
// line 5: clear "No fix"
|
||||||
|
if (wasnofix) {
|
||||||
|
snprintf(buff, sizeof(buff), " ");
|
||||||
|
u8x8.draw2x2String(2, 5, buff);
|
||||||
|
wasnofix = false;
|
||||||
|
}
|
||||||
|
// line 3-4: GPS latitude
|
||||||
|
snprintf(buff, sizeof(buff), "%c%-07.4f",
|
||||||
|
gps.location.rawLat().negative ? 'S' : 'N', gps.location.lat());
|
||||||
|
u8x8.draw2x2String(0, 3, buff);
|
||||||
|
|
||||||
|
// line 6-7: GPS longitude
|
||||||
|
snprintf(buff, sizeof(buff), "%c%-07.4f",
|
||||||
|
gps.location.rawLat().negative ? 'W' : 'E', gps.location.lng());
|
||||||
|
u8x8.draw2x2String(0, 6, buff);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
snprintf(buff, sizeof(buff), "No fix");
|
||||||
|
u8x8.setInverseFont(1);
|
||||||
|
u8x8.draw2x2String(2, 5, buff);
|
||||||
|
u8x8.setInverseFont(0);
|
||||||
|
wasnofix = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
snprintf(buff, sizeof(buff), "No GPS");
|
||||||
|
u8x8.draw2x2String(2, 5, buff);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
break; // page2
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; // default
|
||||||
|
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
} // draw_page
|
||||||
|
|
||||||
#endif // HAS_DISPLAY
|
#endif // HAS_DISPLAY
|
@ -314,7 +314,7 @@ void setup() {
|
|||||||
// initialize display
|
// initialize display
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
strcat_P(features, " OLED");
|
strcat_P(features, " OLED");
|
||||||
DisplayState = cfg.screenon;
|
DisplayIsOn = cfg.screenon;
|
||||||
init_display(PRODUCTNAME, PROGVERSION); // note: blocking call
|
init_display(PRODUCTNAME, PROGVERSION); // note: blocking call
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user