Merge pull request #587 from cyberman54/development

New features:
- M5 display support
- Battery level display in %
Bugfixes:
- disable lmic interrupts for pycom boards (not supported)
This commit is contained in:
Verkehrsrot 2020-04-12 19:41:08 +02:00 committed by GitHub
commit 8a426531b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 630 additions and 474 deletions

View File

@ -1,9 +1,12 @@
#ifndef _BMESENSOR_H
#define _BMESENSOR_H
#include "globals.h"
#include <Wire.h>
#include "globals.h"
#include "irqhandler.h"
#include "configmanager.h"
#ifdef HAS_BME680
#include <bsec.h>
#elif defined HAS_BME280

View File

@ -2,6 +2,10 @@
#define _BUTTON_H
#include <SimpleButton.h>
#include "irqhandler.h"
#include "senddata.h"
#include "display.h"
#include "payload.h"
void button_init(int pin);
void readButton();

View File

@ -5,27 +5,10 @@
#include "senddata.h"
#include "rcommand.h"
#include "spislave.h"
#if(HAS_LORA)
#include <lmic.h>
#endif
#if (HAS_BME)
#include "bmesensor.h"
#endif
#ifdef HAS_DISPLAY
#include "display.h"
#endif
#if (HAS_SDS011)
#include "sds011read.h"
#endif
#if (HAS_SDCARD)
#include "sdcard.h"
#endif
extern Ticker housekeeper;

View File

@ -7,33 +7,55 @@
#if (HAS_DISPLAY) == 1
#include <ss_oled.h>
#elif (HAS_DISPLAY) == 2
#include <bb_spi_lcd.h>
#else
#error Unknown display type
#include <TFT_eSPI.h>
#endif
#define DISPLAY_PAGES (7) // number of paxcounter display pages
// settings for display library
// settings for OLED display library
#if (HAS_DISPLAY) == 1
#define MY_FONT_SMALL FONT_SMALL
#define MY_FONT_NORMAL FONT_NORMAL
#define MY_FONT_LARGE FONT_LARGE
#define MY_FONT_STRETCHED FONT_STRETCHED
#define USE_BACKBUFFER 1
// setup display hardware type, default is OLED 128x64
#ifndef MY_DISPLAY_TYPE
#define MY_DISPLAY_TYPE OLED_128x64
#endif
#ifdef MY_DISPLAY_ADDR
#define OLED_ADDR MY_DISPLAY_ADDR
#else
#define OLED_ADDR -1
#endif
#ifndef MY_DISPLAY_INVERT
#define MY_DISPLAY_INVERT 0
#endif
#ifndef USW_HW_I2C
#define USE_HW_I2C 1
#endif
#ifndef OLED_FREQUENCY
#define OLED_FREQUENCY 400000L
#endif
// settings for TFT display library
#elif (HAS_DISPLAY == 2)
#define MY_FONT_SMALL 1
#define MY_FONT_NORMAL 2
#define MY_FONT_LARGE 4
#define MY_FONT_STRETCHED 6
#ifndef MY_DISPLAY_FGCOLOR
#define MY_DISPLAY_FGCOLOR TFT_WHITE
#endif
#ifndef MY_DISPLAY_BGCOLOR
#define MY_DISPLAY_BGCOLOR TFT_BLACK
#endif
#endif
// setup display hardware type, default is OLED 128x64
#ifndef OLED_TYPE
#define OLED_TYPE OLED_128x64
#endif
#ifndef MY_DISPLAY_INVERT
#define MY_DISPLAY_INVERT 0
#endif
#ifndef MY_DISPLAY_FLIP
#define MY_DISPLAY_FLIP 0
@ -46,38 +68,10 @@
#define MY_DISPLAY_HEIGHT 64 // Height in pixels of OLED-display, must be 64X
#endif
// some RGB color definitions
#define Black 0x0000 /* 0, 0, 0 */
#define Navy 0x000F /* 0, 0, 128 */
#define DarkGreen 0x03E0 /* 0, 128, 0 */
#define DarkCyan 0x03EF /* 0, 128, 128 */
#define Maroon 0x7800 /* 128, 0, 0 */
#define Purple 0x780F /* 128, 0, 128 */
#define Olive 0x7BE0 /* 128, 128, 0 */
#define LightGrey 0xC618 /* 192, 192, 192 */
#define DarkGrey 0x7BEF /* 128, 128, 128 */
#define Blue 0x001F /* 0, 0, 255 */
#define Green 0x07E0 /* 0, 255, 0 */
#define Cyan 0x07FF /* 0, 255, 255 */
#define Red 0xF800 /* 255, 0, 0 */
#define Magenta 0xF81F /* 255, 0, 255 */
#define Yellow 0xFFE0 /* 255, 255, 0 */
#define White 0xFFFF /* 255, 255, 255 */
#define Orange 0xFD20 /* 255, 165, 0 */
#define GreenYellow 0xAFE5 /* 173, 255, 47 */
#define Pink 0xF81F
#ifndef MY_DISPLAY_FGCOLOR
#define MY_DISPLAY_FGCOLOR White
#endif
#ifndef MY_DISPLAY_BGCOLOR
#define MY_DISPLAY_BGCOLOR Black
#endif
// settings for qr code generator
#define QR_VERSION 3 // 29 x 29px
#define QR_SCALEFACTOR 2 // 29 -> 58x < 64px
#define QR_VERSION 3 // 29 x 29px
const uint8_t QR_SCALEFACTOR = (MY_DISPLAY_HEIGHT - 4) / 29; // 4px borderlines
extern uint8_t DisplayIsOn, displaybuf[];
void dp_setup(int contrast = 0);
@ -85,9 +79,11 @@ void dp_refresh(bool nextPage = false);
void dp_init(bool verbose = false);
void dp_shutdown(void);
void dp_drawPage(time_t t, bool nextpage);
void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
const char *format, ...);
void dp_println(int lines = 1);
void dp_printf(const char *format, ...);
void dp_setFont(int font, int inv = 0);
void dp_dump(uint8_t *pBuffer);
void dp_setTextCursor(int col, int row);
void dp_contrast(uint8_t contrast);
void dp_clear(void);
void dp_power(uint8_t screenon);

View File

@ -123,8 +123,8 @@ extern std::array<uint64_t, 0xff> beacons;
extern configData_t cfg; // current device configuration
extern char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer
extern uint8_t volatile channel; // wifi channel rotation counter
extern uint16_t volatile macs_total, macs_wifi, macs_ble,
batt_voltage; // display values
extern uint8_t batt_level; // display value
extern uint16_t volatile macs_total, macs_wifi, macs_ble; // display values
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
extern timesource_t timeSource;
extern hw_timer_t *displayIRQ, *matrixDisplayIRQ, *ppsIRQ;
@ -134,42 +134,4 @@ extern TimerHandle_t WifiChanTimer;
extern Timezone myTZ;
extern RTC_DATA_ATTR runmode_t RTC_runmode;
// application includes
#include "led.h"
#include "payload.h"
#include "blescan.h"
#include "power.h"
#if (HAS_GPS)
#include "gpsread.h"
#endif
#if (HAS_LORA)
#include "lorawan.h"
#endif
#ifdef HAS_DISPLAY
#include "display.h"
#endif
#ifdef HAS_MATRIX_DISPLAY
#include "ledmatrixdisplay.h"
#endif
#ifdef HAS_BUTTON
#include "button.h"
#endif
#ifdef HAS_ANTENNA_SWITCH
#include "antenna.h"
#endif
#if (HAS_SENSORS)
#include "sensor.h"
#endif
#if (HAS_BME)
#include "bmesensor.h"
#endif
#endif

View File

@ -13,11 +13,13 @@
#define PMU_IRQ 0x200
#include "globals.h"
#include "button.h"
#include "cyclic.h"
#include "senddata.h"
#include "timekeeper.h"
#include "bmesensor.h"
#include "power.h"
#include "ledmatrixdisplay.h"
void irqHandler(void *pvParameters);
void mask_user_IRQ();

View File

@ -1,15 +1,13 @@
#ifndef _LED_H
#define _LED_H
#ifdef HAS_RGB_LED
#include <SmartLeds.h>
#include "lorawan.h"
#ifndef RGB_LED_COUNT
#define RGB_LED_COUNT 1
#endif
#endif
// value for HSL color
// see http://www.workwithcolor.com/blue-color-hue-range-01.htm
#define COLOR_RED 0

View File

@ -3,6 +3,7 @@
#include "LEDMatrix.h"
#include "ledmatrixfonts.h"
#include "ledmatrixdisplay.h"
extern uint8_t MatrixDisplayIsOn;

View File

@ -8,6 +8,7 @@
#include "hash.h"
#include "senddata.h"
#include "cyclic.h"
#include "led.h"
#define MAC_SNIFF_WIFI 0
#define MAC_SNIFF_BLE 1

View File

@ -17,9 +17,8 @@
#include "ota.h"
#include "irqhandler.h"
#include "spislave.h"
#if (HAS_LORA)
#include "sensor.h"
#include "lorawan.h"
#endif
#include "timekeeper.h"
#endif

View File

@ -4,7 +4,9 @@
#ifdef USE_OTA
#include "globals.h"
#include <ss_oled.h>
#include "led.h"
#include "display.h"
#include <Update.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>

View File

@ -1,11 +1,7 @@
#ifndef _PAYLOAD_H_
#define _PAYLOAD_H_
#include "paxcounter.conf"
#if (HAS_SDS011)
#include "sds011read.h"
#endif
// MyDevices CayenneLPP 1.0 channels for Synamic sensor payload format
// all payload goes out on LoRa FPort 1

View File

@ -4,13 +4,22 @@
#include <Arduino.h>
#include <driver/adc.h>
#include <esp_adc_cal.h>
#include "i2c.h"
#include "reset.h"
#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate
#define NO_OF_SAMPLES 64 // we do some multisampling to get better values
#ifndef BAT_MAX_VOLTAGE
#define BAT_MAX_VOLTAGE 4300 // millivolts
#endif
#ifndef BAT_MIN_VOLTAGE
#define BAT_MIN_VOLTAGE 3200 // millivolts
#endif
uint16_t read_voltage(void);
uint8_t read_battlevel(void);
void calibrate_voltage(void);
bool batt_sufficient(void);

View File

@ -1,20 +1,19 @@
#ifndef _RCOMMAND_H
#define _RCOMMAND_H
#include <rom/rtc.h>
#include "senddata.h"
#include "cyclic.h"
#include "configmanager.h"
#if(HAS_LORA)
#include "lorawan.h"
#endif
#include "sensor.h"
#include "macsniff.h"
#include "wifiscan.h"
#include <rom/rtc.h>
#include "cyclic.h"
#include "timekeeper.h"
#if(TIME_SYNC_LORASERVER)
#include "timesync.h"
#endif
#include "blescan.h"
// table of remote commands and assigned functions
typedef struct {

View File

@ -3,7 +3,11 @@
#include <driver/rtc_io.h>
#include <rom/rtc.h>
#include "i2c.h"
#include "lorawan.h"
#include "display.h"
#include "power.h"
void do_reset(bool warmstart);
void do_after_reset(int reason);

View File

@ -1,11 +1,12 @@
#ifndef _RTCTIME_H
#define _RTCTIME_H
#include "globals.h"
#include "timekeeper.h"
#include <Wire.h> // must be included here so that Arduino library object file references work
#include <RtcDS3231.h>
#include "globals.h"
#include "timekeeper.h"
extern RtcDS3231<TwoWire> Rtc; // make RTC instance globally available
uint8_t rtc_init(void);

View File

@ -3,10 +3,11 @@
#include <globals.h>
#include <stdio.h>
#include <SPI.h>
#include <mySD.h>
#include "sds011read.h"
#define SDCARD_FILE_NAME "paxcount.%02d"
#define SDCARD_FILE_HEADER "date, time, wifi, bluet"

View File

@ -1,8 +1,8 @@
#ifndef _SDS011READ_H
#define _SDS011READ_H
#include "globals.h"
#include <SDS011.h>
#include "globals.h"
#define SDCARD_FILE_HEADER_SDS011 ", PM10,PM25"

View File

@ -3,18 +3,10 @@
#include "spislave.h"
#include "cyclic.h"
#if(HAS_LORA)
#include "sensor.h"
#include "lorawan.h"
#endif
#ifdef HAS_DISPLAY
#include "display.h"
#endif
#ifdef HAS_SDCARD
#include "sdcard.h"
#endif
extern Ticker sendcycler;

View File

@ -25,6 +25,7 @@ licenses. Refer to LICENSE.txt file in repository for more details.
#define _SPISLAVE_H
#include "globals.h"
#include "rcommand.h"
esp_err_t spi_init();

View File

@ -6,16 +6,9 @@
#include "TimeLib.h"
#include "irqhandler.h"
#include "timesync.h"
#if (HAS_GPS)
#include "gpsread.h"
#endif
#ifdef HAS_IF482
#include "if482.h"
#elif defined HAS_DCF77
#include "dcf77.h"
#endif
extern const char timeSetSymbols[];
extern Ticker timesyncer;

View File

@ -3,13 +3,17 @@
// ESP32 Functions
#include <esp_wifi.h>
#include <esp_coexist.h>
#include "coexist_internal.h"
// Hash function for scrambling MAC addresses
#include "hash.h"
#include "hash.h" // Hash function for scrambling MAC addresses
#include "antenna.h" // code for switching wifi antennas
#include "macsniff.h"
void wifi_sniffer_init(void);
void switch_wifi_sniffer (uint8_t state);
void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
void switch_wifi_sniffer(uint8_t state);
void IRAM_ATTR wifi_sniffer_packet_handler(void *buff,
wifi_promiscuous_pkt_type_t type);
void switchWifiChannel(TimerHandle_t xTimer);
#endif

View File

@ -45,7 +45,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
[common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.9.982
release_version = 1.9.984
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3
@ -56,14 +56,13 @@ lmicconfigfile = lmic_config.h
platform_espressif32 = espressif32@1.12.0
monitor_speed = 115200
upload_speed = 115200
;upload_port = COM9
lib_deps_lora =
MCCI LoRaWAN LMIC library@>=3.1.0 ; MCCI LMIC by Terrill Moore
lib_deps_display =
ss_oled@4.1.2 ; simple and small OLED lib by Larry Bank
BitBang_I2C@2.0.2
QRCode@>=0.0.1
bb_spi_lcd@1.1.0 ; LCD TFT driver lib by Larry Bank
TFT_eSPI@>=2.2.0
lib_deps_matrix_display =
Ultrathin_LED_Matrix@>=1.0.0
lib_deps_rgbled =
@ -111,7 +110,7 @@ framework = arduino
board = esp32dev
board_build.partitions = min_spiffs.csv
upload_speed = ${common.upload_speed}
;upload_port = ${common.upload_port}
;upload_port = COM5
platform = ${common.platform_espressif32}
lib_deps = ${common.lib_deps_all}
build_flags = ${common.build_flags_all}

View File

@ -1,6 +1,5 @@
/* code snippets taken from
https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner
*/
// some code snippets taken from
// https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner
#include "blescan.h"

View File

@ -1,6 +1,7 @@
/* configmanager persists runtime configuration using NVRAM of ESP32*/
#include "globals.h"
#include "configmanager.h"
// Local logging tag
static const char TAG[] = "flash";

View File

@ -28,7 +28,7 @@ void doHousekeeping() {
if (batt_sufficient()) {
do_reset(true); // warmstart to runmode update
} else {
ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage);
ESP_LOGE(TAG, "Battery level %d%% is too low for OTA", batt_level);
RTC_runmode = RUNMODE_NORMAL; // keep running in normal mode
}
}
@ -66,11 +66,17 @@ void doHousekeeping() {
// read battery voltage into global variable
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
batt_voltage = read_voltage();
if (batt_voltage == 0xffff)
batt_level = read_battlevel();
switch (batt_level) {
case MCMD_DEVS_EXT_POWER:
ESP_LOGI(TAG, "Battery: external power");
else
ESP_LOGI(TAG, "Battery: %dmV", batt_voltage);
break;
case MCMD_DEVS_BATT_NOINFO :
ESP_LOGI(TAG, "Battery: unknown state");
break;
default:
ESP_LOGI(TAG, "Battery: %d%%", batt_level);
}
#ifdef HAS_PMU
AXP192_showstatus();
#endif
@ -116,14 +122,13 @@ void doHousekeeping() {
#endif
#if (HAS_SDS011)
if ( isSDS011Active ) {
ESP_LOGD(TAG, "SDS011: go to sleep");
sds011_loop();
}
else {
ESP_LOGD(TAG, "SDS011: wakeup");
sds011_wakeup();
}
if (isSDS011Active) {
ESP_LOGD(TAG, "SDS011: go to sleep");
sds011_loop();
} else {
ESP_LOGD(TAG, "SDS011: wakeup");
sds011_wakeup();
}
#endif
} // doHousekeeping()

View File

@ -11,8 +11,8 @@ Display-Mask (128 x 64 pixel):
0|PAX:aabbccdd STRETCHED
1|PAX:aabbccdd STRETCHED
2|
3|B:a.bcV Sats:ab ch:ab SMALL
4|WIFI:abcde BLTH:abcde SMALL
3|WIFI:abcde BLTH:abcde SMALL
4|B:a.bcV Sats:ab ch:ab SMALL
5|RLIM:abcd Mem:abcdKB SMALL
6|27.Feb 2019 20:27:00* SMALL
7|yyyyyyyyyyyyy xx SFab SMALL
@ -25,15 +25,16 @@ y = LMIC event message
xx = payload sendqueue length
ab = LMIC spread factor
FONT_SMALL: 6x8px = 21 chars / line
FONT_NORMAL: 8x8px = 16 chars / line
FONT_STRETCHED: 16x32px = 8 chars / line
MY_FONT_SMALL: 6x8px = 21 chars / line
MY_FONT_NORMAL: 8x8px = 16 chars / line
MY_FONT_STRETCHED: 16x32px = 8 chars / line
*/
// Basic Config
#include "globals.h"
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
#include "globals.h"
#include "display.h"
// local Tag for logging
static const char TAG[] = __FILE__;
@ -44,36 +45,36 @@ const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
uint8_t DisplayIsOn = 0;
uint8_t displaybuf[MY_DISPLAY_WIDTH * MY_DISPLAY_HEIGHT / 8] = {0};
static uint8_t plotbuf[MY_DISPLAY_WIDTH * MY_DISPLAY_HEIGHT / 8] = {0};
static int dp_row = 0, dp_col = 0, dp_font = 0;
QRCode qrcode;
#if (HAS_DISPLAY) == 1
SSOLED ssoled;
#elif (HAS_DISPLAY) == 2
TFT_eSPI tft = TFT_eSPI();
#endif
void dp_setup(int contrast) {
#if (HAS_DISPLAY) == 1
int rc = oledInit(&ssoled, MY_DISPLAY_TYPE, OLED_ADDR, MY_DISPLAY_FLIP,
#if (HAS_DISPLAY) == 1 // I2C OLED
int rc = oledInit(&ssoled, OLED_TYPE, OLED_ADDR, MY_DISPLAY_FLIP,
MY_DISPLAY_INVERT, USE_HW_I2C, MY_DISPLAY_SDA,
MY_DISPLAY_SCL, MY_DISPLAY_RST,
400000L); // use standard I2C bus at 400Khz
OLED_FREQUENCY); // use standard I2C bus at 400Khz
assert(rc != OLED_NOT_FOUND);
// set display buffer
oledSetBackBuffer(&ssoled, displaybuf);
oledSetTextWrap(&ssoled, true);
dp_font = MY_FONT_NORMAL;
#elif (HAS_DISPLAY) == 2
#elif (HAS_DISPLAY) == 2 // SPI TFT
int rc = spilcdInit(MY_DISPLAY_TYPE, 0, MY_DISPLAY_INVERT, MY_DISPLAY_FLIP,
32000000, MY_DISPLAY_CS, MY_DISPLAY_DC, MY_DISPLAY_RST,
MY_DISPLAY_BL, MY_DISPLAY_MISO, MY_DISPLAY_MOSI,
MY_DISPLAY_CLK);
assert(rc == 0);
// set display buffer
spilcdAllocBackbuffer();
tft.init();
tft.setRotation(MY_DISPLAY_FLIP ? 3 : 1);
tft.invertDisplay(MY_DISPLAY_INVERT ? true : false);
tft.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
#endif
@ -85,10 +86,12 @@ void dp_setup(int contrast) {
void dp_init(bool verbose) {
#if (HAS_DISPLAY) == 1 // i2c
// block i2c bus access
if (!I2C_MUTEX_LOCK())
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
else {
#endif
dp_setup(DISPLAYCONTRAST);
@ -101,15 +104,20 @@ void dp_init(bool verbose) {
#if (VERBOSE)
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
dp_printf(0, 0, 0, 0, "** PAXCOUNTER **");
dp_printf(0, 1, 0, 0, "Software v%s", PROGVERSION);
dp_printf(0, 3, 0, 0, "ESP32 %d cores", chip_info.cores);
dp_printf(0, 4, 0, 0, "Chip Rev.%d", chip_info.revision);
dp_printf(0, 5, 0, 0, "WiFi%s%s",
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
dp_setFont(MY_FONT_NORMAL);
dp_printf("** PAXCOUNTER **");
dp_println();
dp_printf("Software v%s", PROGVERSION);
dp_println();
dp_printf("ESP32 %d cores", chip_info.cores);
dp_println();
dp_printf("Chip Rev.%d", chip_info.revision);
dp_println();
dp_printf("WiFi%s%s", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
dp_printf(0, 6, 0, 0, "%dMB %s Flash",
spi_flash_get_chip_size() / (1024 * 1024),
dp_println();
dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int."
: "ext.");
@ -131,10 +139,15 @@ void dp_init(bool verbose) {
dp_printqr(3, 3, deveui);
// display DEVEUI as plain text on the right
dp_printf(72, 0, FONT_NORMAL, 0, "LORAWAN");
dp_printf(72, 1, FONT_NORMAL, 0, "DEVEUI:");
for (uint8_t i = 0; i <= 3; i++)
dp_printf(80, i + 3, FONT_NORMAL, 0, "%4.4s", deveui + i * 4);
const int x_offset = QR_SCALEFACTOR * 29 + 14;
dp_setTextCursor(x_offset, 0);
dp_setFont(MY_FONT_NORMAL);
dp_printf("DEVEUI");
dp_println();
for (uint8_t i = 0; i <= 3; i++) {
dp_setTextCursor(x_offset, i + 3);
dp_printf("%4.4s", deveui + i * 4);
}
// give user some time to read or take picture
dp_dump(displaybuf);
@ -147,8 +160,11 @@ void dp_init(bool verbose) {
dp_power(cfg.screenon); // set display off if disabled
#if (HAS_DISPLAY) == 1 // i2c
I2C_MUTEX_UNLOCK(); // release i2c bus access
} // mutex
#endif
} // dp_init
void dp_refresh(bool nextPage) {
@ -204,207 +220,307 @@ void dp_drawPage(time_t t, bool nextpage) {
static bool wasnofix = true;
#endif
// line 1/2: pax counter
dp_printf(0, 0, FONT_STRETCHED, 0, "PAX:%-4d",
macs.size()); // display number of unique macs total Wifi + BLE
start:
if (nextpage) {
DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
dp_clear();
}
// cursor home
dp_setTextCursor(0, 0);
// line 1/2: pax counter
// display number of unique macs total Wifi + BLE
if (DisplayPage < 5) {
dp_setFont(MY_FONT_STRETCHED);
dp_printf("PAX:%-4d", macs.size());
}
switch (DisplayPage) {
// page 0: parameters overview
// page 1: pax graph
// page 1: lorawan parameters
// page 2: GPS
// page 3: BME280/680
// page 4: time
// page 5: lorawan parameters
// page 5: pax graph
// page 6: blank screen
// page 0: parameters overview
// ---------- page 0: parameters overview ----------
case 0:
dp_setTextCursor(0, 3);
dp_setFont(MY_FONT_SMALL);
// line 3: wifi + bluetooth counters
// WIFI:abcde BLTH:abcde
#if ((WIFICOUNTER) && (BLECOUNTER))
if (cfg.wifiscan)
dp_printf(0, 3, FONT_SMALL, 0, "WIFI:%-5d", macs_wifi);
dp_printf("WIFI:%-5d", macs_wifi);
else
dp_printf(0, 3, FONT_SMALL, 0, "%s", "WIFI:off");
dp_printf("WIFI:off");
if (cfg.blescan)
dp_printf(66, 3, FONT_SMALL, 0, "BLTH:%-5d", macs_ble);
dp_printf(" BLTH:%-5d", macs_ble);
else
dp_printf(66, 3, FONT_SMALL, 0, "%s", "BLTH:off");
dp_printf(" BLTH:off");
#elif ((WIFICOUNTER) && (!BLECOUNTER))
if (cfg.wifiscan)
dp_printf(0, 3, FONT_SMALL, 0, "WIFI:%-5d", macs_wifi);
dp_printf("WIFI:%-5d", macs_wifi);
else
dp_printf(0, 3, FONT_SMALL, 0, "%s", "WIFI:off");
dp_printf("WIFI:off");
#elif ((!WIFICOUNTER) && (BLECOUNTER))
if (cfg.blescan)
dp_printf(0, 3, FONT_SMALL, 0, "BLTH:%-5d", macs_ble);
dp_printf("BLTH:%-5d", macs_ble);
else
dp_printf(0, 3, FONT_SMALL, 0, "%s", "BLTH:off");
dp_printf("BLTH:off");
#else
dp_printf(0, 3, FONT_SMALL, 0, "%s", "Sniffer disabled");
dp_printf("Sniffer disabled");
#endif
dp_println();
// line 4: Battery + GPS status + Wifi channel
// line 4: Battery + GPS status + Wifi channel
// B:a.bcV Sats:ab ch:ab
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
if (batt_voltage == 0xffff)
dp_printf(0, 4, FONT_SMALL, 0, "%s", "USB ");
else if (batt_voltage == 0)
dp_printf(0, 4, FONT_SMALL, 0, "%s", "No batt");
else
dp_printf(0, 4, FONT_SMALL, 0, "B:%.2fV", batt_voltage / 1000.0);
switch (batt_level) {
case MCMD_DEVS_EXT_POWER:
dp_printf("ext.Pwr ");
break;
case MCMD_DEVS_BATT_NOINFO:
dp_printf("No batt ");
break;
default:
dp_printf("B:%3d%% ", batt_level);
}
#else
dp_printf(" ");
#endif
#if (HAS_GPS)
if (gps_hasfix())
dp_printf(48, 4, FONT_SMALL, 0, "Sats:%.2d", gps.satellites.value());
else // if no fix then display Sats value inverse
dp_printf(48, 4, FONT_SMALL, 1, "Sats:%.2d", gps.satellites.value());
dp_setFont(MY_FONT_SMALL, !gps_hasfix());
dp_printf("Sats:%.2d", gps.satellites.value());
dp_setFont(MY_FONT_SMALL);
#else
dp_printf(" ");
#endif
dp_printf(96, 4, FONT_SMALL, 0, "ch:%02d", channel);
dp_printf(" ch:%02d", channel);
dp_println();
// line 5: RSSI limiter + free memory
dp_printf(0, 5, FONT_SMALL, 0, !cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d",
cfg.rssilimit);
dp_printf(66, 5, FONT_SMALL, 0, "Mem:%4dKB", getFreeRAM() / 1024);
// RLIM:abcd Mem:abcdKB
dp_printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
dp_printf(" Mem:%4dKB", getFreeRAM() / 1024);
dp_println();
// line 6: time + date
// 27.Feb 2019 20:27:00*
#if (TIME_SYNC_INTERVAL)
timeState = TimePulseTick ? ' ' : timeSetSymbols[timeSource];
TimePulseTick = false;
dp_printf(0, 6, FONT_SMALL, 0, "%02d.%3s %4d", day(t), printmonth[month(t)],
year(t));
dp_printf(72, 6, FONT_SMALL, 0, "%02d:%02d:%02d", hour(t), minute(t),
second(t));
dp_printf("%02d.%3s %4d", day(t), printmonth[month(t)], year(t));
dp_printf(" %02d:%02d:%02d", hour(t), minute(t), second(t));
// display inverse timeState if clock controller is enabled
#if (defined HAS_DCF77) || (defined HAS_IF482)
dp_printf(120, 6, FONT_SMALL, 1, "%c", timeState);
dp_setFont(MY_FONT_SMALL, 1);
dp_printf("%c", timeState);
dp_setFont(MY_FONT_SMALL, 0);
#else
dp_printf(120, 6, FONT_SMALL, 0, "%c", timeState);
dp_printf("%c", timeState);
#endif
dp_println();
#endif // TIME_SYNC_INTERVAL
// line 7: LORA network status
// yyyyyyyyyyyyy xx SFab
#if (HAS_LORA)
// LMiC event display
dp_printf(0, 7, FONT_SMALL, 0, "%-16s", lmic_event_msg);
dp_printf("%-16s", lmic_event_msg);
// LORA datarate, display inverse if ADR disabled
dp_printf(102, 7, FONT_SMALL, !cfg.adrmode, "%-4s",
getSfName(updr2rps(LMIC.datarate)));
#endif // HAS_LORA
break; // page0
// page 1: pax graph
case 1:
dp_dump(plotbuf);
break; // page1
// page 2: GPS
case 2:
#if (HAS_GPS)
if (gps_hasfix()) {
// line 5: clear "No fix"
if (wasnofix) {
dp_printf(16, 5, FONT_STRETCHED, 0, " ");
wasnofix = false;
}
// line 3-4: GPS latitude
dp_printf(0, 3, FONT_STRETCHED, 0, "%c%07.4f",
gps.location.rawLat().negative ? 'S' : 'N', gps.location.lat());
// line 6-7: GPS longitude
dp_printf(0, 6, FONT_STRETCHED, 0, "%c%07.4f",
gps.location.rawLat().negative ? 'W' : 'E', gps.location.lng());
} else {
dp_printf(16, 5, FONT_STRETCHED, 1, "No fix");
wasnofix = true;
}
break; // page2
#else
DisplayPage++; // next page
#endif
// page 3: BME280/680
case 3:
#if (HAS_BME)
// line 2-3: Temp
dp_printf(0, 2, FONT_STRETCHED, 0, "TMP:%-2.1f", bme_status.temperature);
// line 4-5: Hum
dp_printf(0, 4, FONT_STRETCHED, 0, "HUM:%-2.1f", bme_status.humidity);
#ifdef HAS_BME680
// line 6-7: IAQ
dp_printf(0, 6, FONT_STRETCHED, 0, "IAQ:%-3.0f", bme_status.iaq);
#else // is BME280 or BMP180
// line 6-7: Pre
dp_printf(0, 6, FONT_STRETCHED, 0, "PRE:%-2.1f", bme_status.pressure);
#endif // HAS_BME680
break; // page 3
#else
DisplayPage++; // next page
#endif // HAS_BME
// page 4: time
case 4:
dp_printf(0, 4, FONT_LARGE, 0, "%02d:%02d:%02d", hour(t), minute(t),
second(t));
dp_setFont(MY_FONT_SMALL, !cfg.adrmode);
dp_printf(" %-4s", getSfName(updr2rps(LMIC.datarate)));
dp_setFont(MY_FONT_SMALL, 0);
dp_println();
#endif // HAS_LORA
break;
// page 5: lorawan parameters
case 5:
// ---------- page 1: lorawan parameters ----------
case 1:
#if (HAS_LORA)
// 3|NtwkID:000000 TXpw:aa
// 4|DevAdd:00000000 DR:0
// 5|CHMsk:0000 Nonce:0000
// 6|CUp:000000 CDn:000000
// 7|SNR:-0000 RSSI:-0000
dp_printf(0, 3, FONT_SMALL, 0, "NetwID:%06X TXpw:%-2d",
LMIC.netid & 0x001FFFFF, LMIC.radio_txpow);
dp_printf(0, 4, FONT_SMALL, 0, "DevAdd:%08X DR:%1d", LMIC.devaddr,
LMIC.datarate);
dp_printf(0, 5, FONT_SMALL, 0, "ChMsk:%04X Nonce:%04X", LMIC.channelMap,
LMIC.devNonce);
dp_printf(0, 6, FONT_SMALL, 0, "fUp:%-6d fDn:%-6d",
LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0);
dp_printf(0, 7, FONT_SMALL, 0, "SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4,
LMIC.rssi);
break; // page5
#else // don't show blank page if we are unattended
DisplayPage++; // next page
#endif // HAS_LORA
// page 6: blank screen
dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(0, 3);
dp_printf("NetwID:%06X TXpw:%-2d", LMIC.netid & 0x001FFFFF,
LMIC.radio_txpow);
dp_println();
dp_printf("DevAdd:%08X DR:%1d", LMIC.devaddr, LMIC.datarate);
dp_println();
dp_printf("ChMsk:%04X Nonce:%04X", LMIC.channelMap, LMIC.devNonce);
dp_println();
dp_printf("fUp:%-6d fDn:%-6d", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0);
dp_println();
dp_printf("SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi);
break;
#else // flip page if we are unattended
DisplayPage++;
#endif // HAS_LORA
// ---------- page 2: GPS ----------
case 2:
#if (HAS_GPS)
dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 3);
if (gps_hasfix()) {
// line 5: clear "No fix"
if (wasnofix) {
dp_setTextCursor(2, 4);
dp_printf(" ");
wasnofix = false;
}
// line 3-4: GPS latitude
dp_printf("%c%07.4f", gps.location.rawLat().negative ? 'S' : 'N',
gps.location.lat());
// line 6-7: GPS longitude
dp_printf("%c%07.4f", gps.location.rawLat().negative ? 'W' : 'E',
gps.location.lng());
} else {
dp_setTextCursor(2, 4);
dp_setFont(MY_FONT_STRETCHED, 1);
dp_printf("No fix");
wasnofix = true;
}
break;
#else // flip page if we are unattended
DisplayPage++;
#endif
// ---------- page 3: BME280/680 ----------
case 3:
#if (HAS_BME)
dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 2);
// line 2-3: Temp
dp_printf("TMP:%-2.1f", bme_status.temperature);
dp_println(2);
// line 4-5: Hum
dp_printf("HUM:%-2.1f", bme_status.humidity);
dp_println(2);
#ifdef HAS_BME680
// line 6-7: IAQ
dp_printf("IAQ:%-3.0f", bme_status.iaq);
#else // is BME280 or BMP180
// line 6-7: Pre
dp_printf("PRE:%-2.1f", bme_status.pressure);
#endif // HAS_BME680
break; // page 3
#else // flip page if we are unattended
DisplayPage++;
#endif // HAS_BME
// ---------- page 4: time ----------
case 4:
dp_setFont(MY_FONT_LARGE);
dp_setTextCursor(0, 4);
dp_printf("%02d:%02d:%02d", hour(t), minute(t), second(t));
break;
// ---------- page 5: pax graph ----------
case 5:
dp_setFont(MY_FONT_NORMAL);
dp_setTextCursor(0, 0);
dp_printf("Pax graph");
dp_dump(plotbuf);
break;
// ---------- page 6: blank screen ----------
case 6:
#ifdef HAS_BUTTON
dp_clear();
break;
#else // don't show blank page if we are unattended
DisplayPage++; // next page
#else // flip page if we are unattended
DisplayPage++;
#endif
default:
goto start; // start over
} // switch
} // switch (page)
} // dp_drawPage
// display helper functions
void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
const char *format, ...) {
// ------------- display helper functions -----------------
void dp_setTextCursor(int x, int y) {
// x represents the pixel column
// y represents the text row
dp_col = x;
#if (HAS_DISPLAY) == 1
dp_row = y;
oledSetCursor(&ssoled, dp_col, dp_row);
#elif (HAS_DISPLAY) == 2
switch (dp_font >> 1) {
case MY_FONT_STRETCHED:
case MY_FONT_LARGE:
dp_row = y * 26;
break;
case MY_FONT_SMALL:
case MY_FONT_NORMAL:
default:
dp_row = y * 16;
break;
}
tft.setCursor(dp_col, dp_row);
#endif
}
void dp_setFont(int font, int inv) {
#if (HAS_DISPLAY) == 1
dp_font = (font << 1) | (inv & 0x01);
#elif (HAS_DISPLAY) == 2
// map font oled -> tft
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;
}
// to do: invers printing
#endif
}
void dp_println(int lines) {
dp_col = 0;
dp_row += lines;
#if (HAS_DISPLAY) == 1
dp_setTextCursor(dp_col, dp_row);
#elif (HAS_DISPLAY) == 2
for (int i = 1; i <= lines; i++)
tft.println();
#endif
};
void dp_printf(const char *format, ...) {
char loc_buf[64];
char *temp = loc_buf;
va_list arg;
@ -423,20 +539,14 @@ void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
va_end(arg);
return;
}
len = vsnprintf(temp, len + 1, format, arg);
vsnprintf(temp, len + 1, format, arg);
}
va_end(arg);
#if (HAS_DISPLAY) == 1
oledWriteString(&ssoled, 0, x, y, temp, font, inv, false);
oledWriteString(&ssoled, 0, -1, dp_row, temp, dp_font >> 1, dp_font & 0x01,
false);
#elif (HAS_DISPLAY) == 2
/*
if (font = 0 || font == 1)
spilcdWriteStringFast(x, y, temp, MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR,
font);
else
*/
spilcdWriteString(x, y, temp, MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR, font,
1);
tft.printf(temp);
#endif
if (temp != loc_buf) {
free(temp);
@ -447,16 +557,18 @@ void dp_dump(uint8_t *pBuffer) {
#if (HAS_DISPLAY) == 1
oledDumpBuffer(&ssoled, pBuffer);
#elif (HAS_DISPLAY) == 2
spilcdShowBuffer(0, 0, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT);
// probably oled buffer stucture is not suitable for tft -> to be checked
tft.drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT,
MY_DISPLAY_FGCOLOR);
#endif
}
void dp_clear() {
void dp_clear(void) {
dp_setTextCursor(0, 0);
#if (HAS_DISPLAY) == 1
oledFill(&ssoled, 0, 1);
#elif (HAS_DISPLAY) == 2
spilcdFill(0, 1);
spilcdScrollReset();
tft.fillScreen(MY_DISPLAY_BGCOLOR);
#endif
}
@ -464,7 +576,7 @@ void dp_contrast(uint8_t contrast) {
#if (HAS_DISPLAY) == 1
oledSetContrast(&ssoled, contrast);
#elif (HAS_DISPLAY) == 2
// to come
// to do: gamma correction for TFT
#endif
}
@ -488,18 +600,19 @@ void dp_shutdown(void) {
I2C_MUTEX_UNLOCK(); // release i2c bus access
}
#elif (HAS_DISPLAY) == 2
spilcdShutdown();
spilcdFreeBackbuffer();
// to come
#endif
}
// ------------- QR code plotter -----------------
void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) {
uint8_t qrcodeData[qrcode_getBufferSize(QR_VERSION)];
qrcode_initText(&qrcode, qrcodeData, QR_VERSION, ECC_HIGH, Message);
// draw QR code
for (uint16_t y = 0; y < qrcode.size; y++)
for (uint16_t x = 0; x < qrcode.size; x++)
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,
y * QR_SCALEFACTOR + offset_y, QR_SCALEFACTOR,
@ -516,14 +629,15 @@ void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) {
qrcode.size * QR_SCALEFACTOR + 2 * offset_y, false);
}
// ------------- graphics primitives -----------------
void dp_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
uint8_t bRender) {
#if (HAS_DISPLAY) == 1
for (uint16_t xi = x; xi < x + width; xi++)
oledDrawLine(&ssoled, xi, y, xi, y + height - 1, bRender);
#elif (HAS_DISPLAY) == 2
spilcdRectangle(x, y, width, height, MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR,
1, 1);
tft.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR);
#endif
}
@ -543,6 +657,8 @@ int dp_drawPixel(uint8_t *buf, const uint16_t x, const uint16_t y,
return 0;
}
// ------------- buffer scroll functions -----------------
void dp_scrollHorizontal(uint8_t *buf, const uint16_t width,
const uint16_t height, bool left) {
@ -588,6 +704,8 @@ void dp_scrollVertical(uint8_t *buf, const uint16_t width,
}
}
// ------------- curve plotter -----------------
void dp_plotCurve(uint16_t count, bool reset) {
static uint16_t last_count = 0, col = 0, row = 0;

View File

@ -1,6 +1,7 @@
#if (HAS_GPS)
#include "globals.h"
#include "gpsread.h"
// Local logging tag
static const char TAG[] = __FILE__;

View File

@ -32,7 +32,7 @@
#define BOARD_HAS_PSRAM // use if board has external PSRAM
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
//#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet
#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet
//#define MY_DISPLAY_FLIP 1 // use if display is rotated
//#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
//#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board
@ -45,13 +45,36 @@
#define GPS_SERIAL 9600, SERIAL_8N1, RXD2, TXD2 // UBlox NEO 6M RX, TX
#define GPS_INT GPIO_NUM_35 // 30ns accurary timepulse, to be external wired on pcb: shorten R12!
// Pins for interface of LC Display
#define MY_DISPLAY_CS GPIO_NUM_14
#define MY_DISPLAY_DC GPIO_NUM_27
#define MY_DISPLAY_CLK GPIO_NUM_18
#define MY_DISPLAY_RST GPIO_NUM_33
#define MY_DISPLAY_BL GPIO_NUM_32
#define MY_DISPLAY_MOSI GPIO_NUM_23
#define MY_DISPLAY_MISO GPIO_NUM_19
// Display Settings
#define MY_DISPLAY_WIDTH 320
#define MY_DISPLAY_HEIGHT 240
#define MY_DISPLAY_INVERT 1
// setting for M5 display
#define USER_SETUP_LOADED 1
#define ILI9341_DRIVER 1
#define M5STACK // needed for TFT driver
#define TFT_MISO MISO // SPI
#define TFT_MOSI MOSI // SPI
#define TFT_SCLK SCK // SPI
#define TFT_CS GPIO_NUM_14 // Chip select control
#define TFT_DC GPIO_NUM_27 // Data Command control
#define TFT_RST GPIO_NUM_33 // Reset
#define TFT_BL GPIO_NUM_32 // LED back-light
#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
#endif

View File

@ -32,13 +32,14 @@
#define BOARD_HAS_PSRAM // use if board has external PSRAM
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
//#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet
#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet
//#define MY_DISPLAY_FLIP 1 // use if display is rotated
//#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
//#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board
#define HAS_LED NOT_A_PIN // no on board LED
#define RGB_LED_COUNT 5 // we use 5 of 10 LEDs (1 side)
#define HAS_LED NOT_A_PIN // no on board LED (?)
#define RGB_LED_COUNT 10
#define HAS_RGB_LED SmartLed rgb_led(LED_SK6812, RGB_LED_COUNT, GPIO_NUM_15) // LED_SK6812 RGB LED on GPIO15
#define HAS_BUTTON (39) // on board button A
@ -50,13 +51,33 @@
// Display Settings
#define MY_DISPLAY_WIDTH 320
#define MY_DISPLAY_HEIGHT 240
#define MY_DISPLAY_TYPE LCD_ILI9341
#define MY_DISPLAY_CS GPIO_NUM_14 // Display CS pin
#define MY_DISPLAY_CLK GPIO_NUM_18 // SPI CLOCK pin
#define MY_DISPLAY_DC GPIO_NUM_27 // Display command/data pin
#define MY_DISPLAY_MOSI GPIO_NUM_23 // SPI MOSI
#define MY_DISPLAY_MISO GPIO_NUM_19 // SPI MISO
#define MY_DISPLAY_BL GPIO_NUM_32 // backlight control
#define MY_DISPLAY_RST GPIO_NUM_33 // RESET control
#define MY_DISPLAY_INVERT 1
// setting for M5 display
#define USER_SETUP_LOADED 1
#define ILI9341_DRIVER 1
#define M5STACK // needed for TFT driver
#define TFT_MISO MISO // SPI
#define TFT_MOSI MOSI // SPI
#define TFT_SCLK SCK // SPI
#define TFT_CS GPIO_NUM_14 // Chip select control
#define TFT_DC GPIO_NUM_27 // Data Command control
#define TFT_RST GPIO_NUM_33 // Reset
#define TFT_BL GPIO_NUM_32 // LED back-light
#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
#endif

View File

@ -65,8 +65,8 @@ RGBColor rgb_hsl2rgb(float h, float s, float l) {
void rgb_set_color(uint16_t hue) {
int i = RGB_LED_COUNT;
if (hue == COLOR_NONE) {
// Off
while (i--)
// set Off
for (int i = 0; i < RGB_LED_COUNT; i++)
rgb_led[i] = Rgb(0, 0, 0);
} else {
// see http://www.workwithcolor.com/blue-color-hue-range-01.htm
@ -76,7 +76,7 @@ void rgb_set_color(uint16_t hue) {
// cfg.rgblum is between 0 and 100 (percent)
RGBColor target = rgb_hsl2rgb(hue / 360.0f, 1.0f, 0.005f * cfg.rgblum);
// uint32_t color = target.R<<16 | target.G<<8 | target.B;
while (i--)
for (int i = 0; i < RGB_LED_COUNT; i++)
rgb_led[i] = Rgb(target.R, target.G, target.B);
}
// Show

View File

@ -1,6 +1,7 @@
#ifdef HAS_MATRIX_DISPLAY
#include "globals.h"
#include "ledmatrixdisplay.h"
#define MATRIX_DISPLAY_PAGES (2) // number of display pages
#define LINE_DIAGRAM_DIVIDER (2) // scales pax numbers to led rows
@ -205,7 +206,7 @@ uint8_t GetCharWidth(char cChar) {
}
void ScrollMatrixLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows) {
uint32_t i, k, idx;
uint32_t i, k, idx = 0;
const uint32_t x = cols / 8;
for (k = 0; k < rows; k++) {

View File

@ -17,8 +17,16 @@
// --> adapt to your device only if necessary
// use interrupts only if LORA_IRQ and LORA_DIO are connected to interrupt
// capable GPIO pins on your board, if not disable interrupts
// capable and separate GPIO pins on your board, if not don't enable
#if (LORA_IRQ) != (LORA_IO1)
#define LMIC_USE_INTERRUPTS 1
#endif
// avoid lmic warning if we don't configure radio because we don't have one
#define CFG_sx1276_radio 1
#if ! (defined(CFG_sx1272_radio) || defined(CFG_sx1276_radio))
#define CFG_sx1276_radio 1
#endif
// time sync via LoRaWAN network, note: not supported by TTNv2
#define LMIC_ENABLE_DeviceTimeReq 1
@ -96,3 +104,6 @@
#define USE_IDEETRON_AES
//
//#define USE_MBEDTLS_AES
// Define this for devices with external power.
//#define LMIC_MCMD_DEVS_BATT_DEFAULT MCMD_DEVS_EXT_POWER

View File

@ -306,30 +306,30 @@ esp_err_t lora_stack_init(bool do_join) {
&lmicTask, // task handle
1); // CPU core
#ifdef LORA_ABP
// Pass ABP parameters to LMIC_setSession
#ifdef LORA_ABP
// Pass ABP parameters to LMIC_setSession
LMIC_reset();
uint8_t appskey[sizeof(APPSKEY)];
uint8_t nwkskey[sizeof(NWKSKEY)];
memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
LMIC_setSession(NETID, DEVADDR, nwkskey, appskey);
// These parameters are defined as macro in loraconf.h
setABPParamaters();
#else
// Start join procedure if not already joined,
// lora_setupForNetwork(true) is called by eventhandler when joined
// else continue current session
if (do_join) {
if (!LMIC_startJoining())
ESP_LOGI(TAG, "Already joined");
} else {
LMIC_reset();
uint8_t appskey[sizeof(APPSKEY)];
uint8_t nwkskey[sizeof(NWKSKEY)];
memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
LMIC_setSession (NETID, DEVADDR, nwkskey, appskey);
// These parameters are defined as macro in loraconf.h
setABPParamaters();
#else
// Start join procedure if not already joined,
// lora_setupForNetwork(true) is called by eventhandler when joined
// else continue current session
if (do_join) {
if (!LMIC_startJoining())
ESP_LOGI(TAG, "Already joined");
} else {
LMIC_reset();
LMIC_setSession(RTCnetid, RTCdevaddr, RTCnwkKey, RTCartKey);
LMIC.seqnoUp = RTCseqnoUp;
LMIC.seqnoDn = RTCseqnoDn;
}
#endif
LMIC_setSession(RTCnetid, RTCdevaddr, RTCnwkKey, RTCartKey);
LMIC.seqnoUp = RTCseqnoUp;
LMIC.seqnoDn = RTCseqnoDn;
}
#endif
// start lmic send task
xTaskCreatePinnedToCore(lora_send, // task function
"lorasendtask", // name of task
@ -538,32 +538,6 @@ const char *getCrName(rps_t rps) {
return t[getCr(rps)];
}
/*
u1_t os_getBattLevel() {
//return values:
//MCMD_DEVS_EXT_POWER = 0x00, // external power supply
//MCMD_DEVS_BATT_MIN = 0x01, // min battery value
//MCMD_DEVS_BATT_MAX = 0xFE, // max battery value
//MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level
#if (defined HAS_PMU || defined BAT_MEASURE_ADC)
uint16_t voltage = read_voltage();
switch (voltage) {
case 0:
return MCMD_DEVS_BATT_NOINFO;
case 0xffff:
return MCMD_DEVS_EXT_POWER;
default:
return (voltage > OTA_MIN_BATT ? MCMD_DEVS_BATT_MAX : MCMD_DEVS_BATT_MIN);
}
#else // we don't have any info on battery level
return MCMD_DEVS_BATT_NOINFO;
#endif
} // getBattLevel()
*/
#if (VERBOSE)
// decode LORAWAN MAC message
void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, bool is_down) {

View File

@ -1,6 +1,7 @@
// Basic Config
#include "globals.h"
#include "macsniff.h"
#if (VENDORFILTER)
#include "vendor_array.h"

View File

@ -79,8 +79,9 @@ triggers pps 1 sec impulse
configData_t cfg; // struct holds current device configuration
char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer for LMIC event message
uint8_t volatile channel = 0; // channel rotation counter
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
batt_voltage = 0; // globals for display
uint8_t batt_level = 0; // display value
uint16_t volatile macs_total = 0, macs_wifi = 0,
macs_ble = 0; // globals for display
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *matrixDisplayIRQ = NULL;
@ -260,7 +261,7 @@ void setup() {
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
strcat_P(features, " BATT");
calibrate_voltage();
batt_voltage = read_voltage();
batt_level = read_battlevel();
#endif
#if (USE_OTA)
@ -328,9 +329,9 @@ void setup() {
#endif
#if (HAS_SDS011)
ESP_LOGI(TAG, "init fine-dust-sensor");
if ( sds011_init() )
strcat_P(features, " SDS");
ESP_LOGI(TAG, "init fine-dust-sensor");
if (sds011_init())
strcat_P(features, " SDS");
#endif
#if (VENDORFILTER)

View File

@ -47,12 +47,17 @@ void start_ota_update() {
dp_setup();
dp_printf(0, 0, 0, 1, "SOFTWARE UPDATE");
dp_printf(0, 1, 0, 0, "WiFi connect ..");
dp_printf(0, 2, 0, 0, "Has Update? ..");
dp_printf(0, 3, 0, 0, "Fetching ..");
dp_printf(0, 4, 0, 0, "Downloading ..");
dp_printf(0, 5, 0, 0, "Rebooting ..");
dp_printf("SOFTWARE UPDATE");
dp_println();
dp_printf("WiFi connect ..");
dp_println();
dp_printf("Has Update? ..");
dp_println();
dp_printf("Fetching ..");
dp_println();
dp_printf("Downloading ..");
dp_println();
dp_printf("Rebooting ..");
dp_dump(displaybuf);
#endif
@ -301,10 +306,13 @@ retry:
void ota_display(const uint8_t row, const std::string status,
const std::string msg) {
#ifdef HAS_DISPLAY
dp_printf(112, row, 0, 0, status.substr(0, 2).c_str());
dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(14, row);
dp_printf(status.substr(0, 2).c_str());
if (!msg.empty()) {
dp_printf(0, 7, 0, 0, " ");
dp_printf(0, 7, 0, 0, msg.substr(0, 16).c_str());
dp_printf(" ");
dp_printf(msg.substr(0, 16).c_str());
dp_println();
}
dp_dump(displaybuf);
#endif

View File

@ -333,19 +333,21 @@ void PayloadConvert::addSDS(sdsStatus_t sds) {
#if (HAS_SDS011)
// value of PM10
#if (PAYLOAD_ENCODER == 3) // Cayenne LPP dynamic
buffer[cursor++] = LPP_PARTMATTER10_CHANNEL; // for PM10
buffer[cursor++] = LPP_PARTMATTER10_CHANNEL; // for PM10
#endif
buffer[cursor++] = LPP_LUMINOSITY; // workaround since cayenne has no data type meter
buffer[cursor++] = highByte((uint16_t)(sds.pm10 * 10));
buffer[cursor++] = lowByte((uint16_t)(sds.pm10 * 10));
buffer[cursor++] =
LPP_LUMINOSITY; // workaround since cayenne has no data type meter
buffer[cursor++] = highByte((uint16_t)(sds.pm10 * 10));
buffer[cursor++] = lowByte((uint16_t)(sds.pm10 * 10));
// value of PM2.5
#if (PAYLOAD_ENCODER == 3) // Cayenne LPP dynamic
buffer[cursor++] = LPP_PARTMATTER25_CHANNEL; // for PM2.5
buffer[cursor++] = LPP_PARTMATTER25_CHANNEL; // for PM2.5
#endif
buffer[cursor++] = LPP_LUMINOSITY; // workaround since cayenne has no data type meter
buffer[cursor++] = highByte((uint16_t)(sds.pm25 * 10));
buffer[cursor++] = lowByte((uint16_t)(sds.pm25 * 10));
#endif // HAS_SDS011
buffer[cursor++] =
LPP_LUMINOSITY; // workaround since cayenne has no data type meter
buffer[cursor++] = highByte((uint16_t)(sds.pm25 * 10));
buffer[cursor++] = lowByte((uint16_t)(sds.pm25 * 10));
#endif // HAS_SDS011
}
void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) {

View File

@ -63,7 +63,7 @@ void AXP192_powerevent_IRQ(void) {
pmu.clearIRQ();
// refresh stored voltage value
read_voltage();
read_battlevel();
}
void AXP192_power(pmu_power_t powerlevel) {
@ -175,21 +175,11 @@ void calibrate_voltage(void) {
#endif
}
bool batt_sufficient() {
#if (defined HAS_PMU || defined BAT_MEASURE_ADC)
uint16_t volts = read_voltage();
return ((volts < 1000) ||
(volts > OTA_MIN_BATT)); // no battery or battery sufficient
#else
return true;
#endif
}
uint16_t read_voltage() {
uint16_t read_voltage(void) {
uint16_t voltage = 0;
#ifdef HAS_PMU
voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage();
voltage = pmu.getBattVoltage();
#else
#ifdef BAT_MEASURE_ADC
@ -219,3 +209,58 @@ uint16_t read_voltage() {
return voltage;
}
uint8_t read_battlevel() {
// return the battery value as sent in MAC Command
// DevStatusAns. Available defines in lorabase.h:
// MCMD_DEVS_EXT_POWER = 0x00, // external power supply
// MCMD_DEVS_BATT_MIN = 0x01, // min battery value
// MCMD_DEVS_BATT_MAX = 0xFE, // max battery value
// MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level
// we calculate the applicable value from MCMD_DEVS_BATT_MIN to
// MCMD_DEVS_BATT_MAX from bat_percent value
const uint16_t batt_voltage_range = BAT_MAX_VOLTAGE - BAT_MIN_VOLTAGE;
const uint8_t batt_level_range = MCMD_DEVS_BATT_MAX - MCMD_DEVS_BATT_MIN + 1;
const int batt_voltage = read_voltage() - BAT_MIN_VOLTAGE;
const uint8_t batt_percent = (batt_voltage > 0)
? (float)batt_voltage / (float)batt_voltage_range * 100.0
: MCMD_DEVS_BATT_NOINFO;
uint8_t lmic_batt_level;
ESP_LOGD(TAG, "batt_voltage = %d mV / batt_level = %u%%", batt_voltage,
batt_percent);
if (batt_percent != MCMD_DEVS_BATT_NOINFO)
#ifdef HAS_PMU
lmic_batt_level = pmu.isVBUSPlug() ? MCMD_DEVS_EXT_POWER
: (float)batt_percent / (float)batt_level_range * 100.0;
#else
lmic_batt_level = (float)batt_percent / (float)batt_level_range * 100.0;
#endif // HAS_PMU
else
lmic_batt_level = MCMD_DEVS_BATT_NOINFO;
// set battery level value for lmic stack
#if (HAS_LORA)
// LMIC_setBattLevel(lmic_batt_level);
#endif
return batt_percent;
}
bool batt_sufficient() {
#if (defined HAS_PMU || defined BAT_MEASURE_ADC)
switch (batt_level) {
case MCMD_DEVS_EXT_POWER:
return true;
case MCMD_DEVS_BATT_NOINFO:
return true;
default:
return (batt_level > OTA_MIN_BATT);
}
#else
return true; // we don't know batt level
#endif
}

View File

@ -1,5 +1,6 @@
// Basic Config
#include "globals.h"
#include "sensor.h"
// Local logging tag
static const char TAG[] = __FILE__;

View File

@ -1,5 +1,4 @@
#include "timekeeper.h"
#include "paxcounter.conf"
#if !(HAS_LORA)
#if (TIME_SYNC_LORASERVER)

View File

@ -13,8 +13,6 @@ accept this.
*/
#if (HAS_LORA)
#if (TIME_SYNC_LORASERVER) && (TIME_SYNC_LORAWAN)
#error Duplicate timesync method selected. You must select either LORASERVER or LORAWAN timesync.
#endif
@ -48,7 +46,7 @@ void timesync_request(void) {
return;
// start timesync handshake
else {
ESP_LOGI(TAG, "[%0.3f] Timeserver sync request seqNo#%d started",
ESP_LOGI(TAG, "[%0.3f] Timeserver sync request started, seqNo#%d",
millis() / 1000.0, time_sync_seqNo);
xTaskNotifyGive(timeSyncProcTask); // unblock timesync task
}
@ -172,13 +170,12 @@ void timesync_store(uint32_t timestamp, timesync_t timestamp_type) {
// callback function to receive time answer from network or answer
void IRAM_ATTR timesync_serverAnswer(void *pUserData, int flag) {
#if (TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN)
// if no timesync handshake is pending then exit
if (!timeSyncPending)
return;
// store LMIC time when we received the timesync answer
ostime_t rxTime = osticks2ms(os_getTime());
// mask application irq to ensure accurate timing
mask_user_IRQ();
@ -194,7 +191,7 @@ void IRAM_ATTR timesync_serverAnswer(void *pUserData, int flag) {
// flag: length of buffer
// Store the instant the time request of the node was received on the gateway
timesync_store(rxTime, timesync_rx);
timesync_store(osticks2ms(os_getTime(), timesync_rx);
// parse pUserData:
// p type meaning
@ -274,6 +271,6 @@ Exit:
// inform processing task
xTaskNotify(timeSyncProcTask, (rc ? rcv_seqNo : TIME_SYNC_END_FLAG),
eSetBits);
}
#endif // HAS_LORA
#endif // (TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN)
}

View File

@ -1,8 +1,6 @@
// Basic Config
#include "globals.h"
#include "wifiscan.h"
#include <esp_coexist.h>
#include "coexist_internal.h"
// Local logging tag
static const char TAG[] = "wifi";