commit
667d7210e7
4
.gitignore
vendored
4
.gitignore
vendored
@ -10,4 +10,6 @@
|
|||||||
.clang_complete
|
.clang_complete
|
||||||
.gcc-flags.json
|
.gcc-flags.json
|
||||||
src/loraconf.h
|
src/loraconf.h
|
||||||
src/ota.conf
|
src/ota.conf
|
||||||
|
src/DBtimesync.cpp
|
||||||
|
include/DBtimesync.h
|
@ -11,6 +11,9 @@
|
|||||||
#include "bme680mems.h"
|
#include "bme680mems.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern Ticker housekeeper;
|
||||||
|
|
||||||
|
void housekeeping(void);
|
||||||
void doHousekeeping(void);
|
void doHousekeeping(void);
|
||||||
uint64_t uptime(void);
|
uint64_t uptime(void);
|
||||||
void reset_counters(void);
|
void reset_counters(void);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <Time.h>
|
#include <Time.h>
|
||||||
#include <Timezone.h>
|
#include <Timezone.h>
|
||||||
#include <RtcDateTime.h>
|
#include <RtcDateTime.h>
|
||||||
|
#include <Ticker.h>
|
||||||
|
|
||||||
// std::set for unified array functions
|
// std::set for unified array functions
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -110,7 +111,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble,
|
|||||||
batt_voltage; // display values
|
batt_voltage; // display values
|
||||||
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
|
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
|
||||||
extern timesource_t timeSource;
|
extern timesource_t timeSource;
|
||||||
extern hw_timer_t *sendCycle, *displaytimer, *clockCycle;
|
extern hw_timer_t *displayIRQ, *ppsIRQ;
|
||||||
extern SemaphoreHandle_t I2Caccess, TimePulse;
|
extern SemaphoreHandle_t I2Caccess, TimePulse;
|
||||||
extern TaskHandle_t irqHandlerTask, ClockTask;
|
extern TaskHandle_t irqHandlerTask, ClockTask;
|
||||||
extern TimerHandle_t WifiChanTimer;
|
extern TimerHandle_t WifiChanTimer;
|
||||||
|
@ -16,7 +16,6 @@ extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
|
|||||||
extern gpsStatus_t
|
extern gpsStatus_t
|
||||||
gps_status; // Make struct for storing gps data globally available
|
gps_status; // Make struct for storing gps data globally available
|
||||||
extern TaskHandle_t GpsTask;
|
extern TaskHandle_t GpsTask;
|
||||||
extern TickType_t const gpsDelay_ticks; // time to NMEA arrival
|
|
||||||
|
|
||||||
int gps_init(void);
|
int gps_init(void);
|
||||||
void gps_read(void);
|
void gps_read(void);
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
#define DISPLAY_IRQ 0x01
|
#define DISPLAY_IRQ 0x01
|
||||||
#define BUTTON_IRQ 0x02
|
#define BUTTON_IRQ 0x02
|
||||||
#define SENDCOUNTER_IRQ 0x04
|
#define SENDCYCLE_IRQ 0x04
|
||||||
#define CYCLIC_IRQ 0x08
|
#define CYCLIC_IRQ 0x08
|
||||||
|
#define TIMESYNC_IRQ 0x10
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "cyclic.h"
|
#include "cyclic.h"
|
||||||
@ -12,8 +13,6 @@
|
|||||||
#include "timekeeper.h"
|
#include "timekeeper.h"
|
||||||
|
|
||||||
void irqHandler(void *pvParameters);
|
void irqHandler(void *pvParameters);
|
||||||
void IRAM_ATTR homeCycleIRQ();
|
|
||||||
void IRAM_ATTR SendCycleIRQ();
|
|
||||||
|
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "rcommand.h"
|
#include "rcommand.h"
|
||||||
#include "timekeeper.h"
|
#include "timekeeper.h"
|
||||||
|
#include "DBtimesync.h"
|
||||||
|
|
||||||
// LMIC-Arduino LoRaWAN Stack
|
// LMIC-Arduino LoRaWAN Stack
|
||||||
#include <lmic.h>
|
#include <lmic.h>
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "macsniff.h"
|
#include "macsniff.h"
|
||||||
#include <rom/rtc.h>
|
#include <rom/rtc.h>
|
||||||
#include "cyclic.h"
|
#include "cyclic.h"
|
||||||
|
#include "timekeeper.h"
|
||||||
|
#include "DBtimesync.h"
|
||||||
|
|
||||||
// table of remote commands and assigned functions
|
// table of remote commands and assigned functions
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -5,9 +5,12 @@
|
|||||||
#include "lorawan.h"
|
#include "lorawan.h"
|
||||||
#include "cyclic.h"
|
#include "cyclic.h"
|
||||||
|
|
||||||
|
extern Ticker sendcycler;
|
||||||
|
|
||||||
void SendPayload(uint8_t port, sendprio_t prio);
|
void SendPayload(uint8_t port, sendprio_t prio);
|
||||||
void sendCounter(void);
|
void sendCounter(void);
|
||||||
void checkSendQueues(void);
|
void checkSendQueues(void);
|
||||||
void flushQueues();
|
void flushQueues();
|
||||||
|
void sendcycle(void);
|
||||||
|
|
||||||
#endif // _SENDDATA_H_
|
#endif // _SENDDATA_H_
|
@ -4,6 +4,7 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "rtctime.h"
|
#include "rtctime.h"
|
||||||
#include "TimeLib.h"
|
#include "TimeLib.h"
|
||||||
|
#include "irqhandler.h"
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
#include "gpsread.h"
|
#include "gpsread.h"
|
||||||
@ -15,11 +16,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char timeSetSymbols[];
|
extern const char timeSetSymbols[];
|
||||||
|
extern Ticker timesyncer;
|
||||||
|
|
||||||
void IRAM_ATTR CLOCKIRQ(void);
|
void IRAM_ATTR CLOCKIRQ(void);
|
||||||
void clock_init(void);
|
void clock_init(void);
|
||||||
void clock_loop(void *pvParameters);
|
void clock_loop(void *pvParameters);
|
||||||
void timepulse_start(void);
|
void timepulse_start(void);
|
||||||
|
void timeSync(void);
|
||||||
uint8_t timepulse_init(void);
|
uint8_t timepulse_init(void);
|
||||||
time_t timeIsValid(time_t const t);
|
time_t timeIsValid(time_t const t);
|
||||||
time_t timeProvider(void);
|
time_t timeProvider(void);
|
||||||
@ -28,5 +31,7 @@ time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm,
|
|||||||
uint8_t ss);
|
uint8_t ss);
|
||||||
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
|
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
|
||||||
int8_t rxPin, int8_t txPins);
|
int8_t rxPin, int8_t txPins);
|
||||||
|
time_t TimeSyncAns(uint8_t seqNo, uint64_t unixTime);
|
||||||
|
void TimeSyncReq(uint8_t seqNo);
|
||||||
|
|
||||||
#endif // _timekeeper_H
|
#endif // _timekeeper_H
|
@ -260,10 +260,9 @@ time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef usePPS
|
#ifdef usePPS
|
||||||
time_t SyncToPPS() {
|
void SyncToPPS() {
|
||||||
sysTime++;
|
sysTime++;
|
||||||
prevMicros = micros();
|
prevMicros = micros();
|
||||||
return sysTime;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ time_t now(uint32_t &sysTimeMicros); // return the current time as seconds and
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef usePPS
|
#ifdef usePPS
|
||||||
time_t SyncToPPS();
|
void SyncToPPS();
|
||||||
#endif
|
#endif
|
||||||
void setTime(time_t t);
|
void setTime(time_t t);
|
||||||
void setTime(int hr, int min, int sec, int day, int month, int yr);
|
void setTime(int hr, int min, int sec, int day, int month, int yr);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
; ---> SELECT TARGET PLATFORM HERE! <---
|
; ---> SELECT TARGET PLATFORM HERE! <---
|
||||||
[platformio]
|
[platformio]
|
||||||
env_default = generic
|
;env_default = generic
|
||||||
;env_default = ebox
|
;env_default = ebox
|
||||||
;env_default = eboxtube
|
;env_default = eboxtube
|
||||||
;env_default = heltec
|
;env_default = heltec
|
||||||
@ -15,7 +15,7 @@ env_default = generic
|
|||||||
;env_default = ttgov2
|
;env_default = ttgov2
|
||||||
;env_default = ttgov21old
|
;env_default = ttgov21old
|
||||||
;env_default = ttgov21new
|
;env_default = ttgov21new
|
||||||
;env_default = ttgobeam
|
env_default = ttgobeam
|
||||||
;env_default = ttgofox
|
;env_default = ttgofox
|
||||||
;env_default = lopy
|
;env_default = lopy
|
||||||
;env_default = lopy4
|
;env_default = lopy4
|
||||||
@ -33,7 +33,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
|
|||||||
release_version = 1.7.324
|
release_version = 1.7.324
|
||||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
||||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||||
debug_level = 0
|
debug_level = 4
|
||||||
; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA
|
; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
;upload_protocol = custom
|
;upload_protocol = custom
|
||||||
|
@ -19,7 +19,7 @@ void defaultConfig() {
|
|||||||
cfg.screenon = 1; // 0=disabled, 1=enabled
|
cfg.screenon = 1; // 0=disabled, 1=enabled
|
||||||
cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
||||||
cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
|
cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
|
||||||
cfg.sendcycle = SEND_SECS; // payload send cycle [seconds/2]
|
cfg.sendcycle = SENDCYCLE; // payload send cycle [seconds/2]
|
||||||
cfg.wifichancycle =
|
cfg.wifichancycle =
|
||||||
WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
|
WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
|
||||||
cfg.blescantime =
|
cfg.blescantime =
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
|
Ticker housekeeper;
|
||||||
|
|
||||||
|
void housekeeping() { xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits); }
|
||||||
|
|
||||||
// do all housekeeping
|
// do all housekeeping
|
||||||
void doHousekeeping() {
|
void doHousekeeping() {
|
||||||
|
|
||||||
|
@ -11,10 +11,6 @@ TaskHandle_t GpsTask;
|
|||||||
|
|
||||||
#ifdef GPS_SERIAL
|
#ifdef GPS_SERIAL
|
||||||
HardwareSerial GPS_Serial(1); // use UART #1
|
HardwareSerial GPS_Serial(1); // use UART #1
|
||||||
TickType_t const gpsDelay_ticks = pdMS_TO_TICKS(1000 - NMEA_BUFFERTIME) -
|
|
||||||
tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL);
|
|
||||||
#else
|
|
||||||
TickType_t const gpsDelay_ticks = pdMS_TO_TICKS(1000 - NMEA_BUFFERTIME);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// initialize and configure GPS
|
// initialize and configure GPS
|
||||||
@ -27,13 +23,6 @@ int gps_init(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set timeout for reading recent time from GPS
|
|
||||||
#ifdef GPS_SERIAL // serial GPS
|
|
||||||
|
|
||||||
#else // I2C GPS
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined GPS_SERIAL
|
#if defined GPS_SERIAL
|
||||||
GPS_Serial.begin(GPS_SERIAL);
|
GPS_Serial.begin(GPS_SERIAL);
|
||||||
ESP_LOGI(TAG, "Using serial GPS");
|
ESP_LOGI(TAG, "Using serial GPS");
|
||||||
@ -88,18 +77,23 @@ void gps_read() {
|
|||||||
time_t get_gpstime(void) {
|
time_t get_gpstime(void) {
|
||||||
|
|
||||||
// set time to wait for arrive next recent NMEA time record
|
// set time to wait for arrive next recent NMEA time record
|
||||||
static const uint32_t gpsDelay_ms = gpsDelay_ticks / portTICK_PERIOD_MS;
|
static const uint32_t gpsDelay_ms = 500;
|
||||||
|
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
|
|
||||||
if ((gps.time.age() < gpsDelay_ms) && (gps.time.isValid()) && (gps.date.isValid())) {
|
if ((gps.time.age() < gpsDelay_ms) && gps.time.isValid() &&
|
||||||
|
gps.date.isValid() && gps.time.isUpdated()) {
|
||||||
|
|
||||||
ESP_LOGD(TAG, "GPS time age: %dms, second: %d, is valid: %s", gps.time.age(), gps.time.second(),
|
gps.time.value(); // trigger isUpdated()
|
||||||
gps.time.isValid() ? "yes" : "no");
|
|
||||||
|
|
||||||
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(),
|
ESP_LOGD(TAG, "GPS time age: %dms, is valid: %s, second: %d",
|
||||||
gps.time.hour(), gps.time.minute(), gps.time.second());
|
gps.time.age(),
|
||||||
}
|
(gps.time.isValid() && gps.date.isValid()) ? "yes" : "no",
|
||||||
|
gps.time.second());
|
||||||
|
|
||||||
|
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(),
|
||||||
|
gps.time.hour(), gps.time.minute(), gps.time.second());
|
||||||
|
}
|
||||||
return timeIsValid(t);
|
return timeIsValid(t);
|
||||||
} // get_gpstime()
|
} // get_gpstime()
|
||||||
|
|
||||||
|
@ -5,19 +5,21 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
//#define HAS_BME 0x77 // BME680 sensor on I2C bus (SDI=21/SCL=22); comment out
|
// Hardware related definitions for Heltec V2 LoRa-32 Board
|
||||||
//if not present
|
|
||||||
|
//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
|
||||||
|
//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
|
||||||
|
|
||||||
// Hardware related definitions for Heltec LoRa-32 Board
|
|
||||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||||
#define CFG_sx1276_radio 1
|
#define CFG_sx1276_radio 1
|
||||||
|
|
||||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||||
#define HAS_LED LED_BUILTIN // white LED on board
|
#define HAS_LED LED_BUILTIN // white LED on board
|
||||||
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
|
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
|
||||||
|
|
||||||
// Pins for I2C interface of OLED Display
|
// Pins for I2C interface of OLED Display
|
||||||
#define MY_OLED_SDA (4)
|
#define MY_OLED_SDA (21)
|
||||||
#define MY_OLED_SCL (15)
|
#define MY_OLED_SCL (22)
|
||||||
#define MY_OLED_RST (16)
|
#define MY_OLED_RST (16)
|
||||||
|
|
||||||
// Pins for LORA chip SPI interface come from board file, we need some
|
// Pins for LORA chip SPI interface come from board file, we need some
|
||||||
|
@ -7,16 +7,8 @@
|
|||||||
|
|
||||||
// Hardware related definitions for Heltec V2 LoRa-32 Board
|
// Hardware related definitions for Heltec V2 LoRa-32 Board
|
||||||
|
|
||||||
// BME680 sensor on I2C bus (SDI=21/SCL=22); comment out if not present
|
//#define HAS_BME GPIO_NUM_4, GPIO_NUM_15 // SDA, SCL
|
||||||
//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
|
//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
|
||||||
//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
|
|
||||||
|
|
||||||
// Of cause, by default the board has no BME680 mounted
|
|
||||||
// a BME680 sensor board maybe connected to I2C (SDA = 4 , and SLC = 15)
|
|
||||||
// second it worked if SDIO left unconnected and 0x77 as address was used
|
|
||||||
//#define HAS_BME 4, 15 // SDA, SCL
|
|
||||||
//#define BME_ADDR BME680_I2C_ADDR_SECONDARY // leave SDIO of BME680 unconnected
|
|
||||||
|
|
||||||
|
|
||||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||||
#define CFG_sx1276_radio 1
|
#define CFG_sx1276_radio 1
|
||||||
@ -26,8 +18,8 @@
|
|||||||
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
|
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
|
||||||
|
|
||||||
// Pins for I2C interface of OLED Display
|
// Pins for I2C interface of OLED Display
|
||||||
#define MY_OLED_SDA (4) // original = 21
|
#define MY_OLED_SDA (4)
|
||||||
#define MY_OLED_SCL (15) // original = 22
|
#define MY_OLED_SCL (15)
|
||||||
#define MY_OLED_RST (16)
|
#define MY_OLED_RST (16)
|
||||||
|
|
||||||
// Pins for LORA chip SPI interface come from board file, we need some
|
// Pins for LORA chip SPI interface come from board file, we need some
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
// GPS settings
|
// GPS settings
|
||||||
#define HAS_GPS 1 // use on board GPS
|
#define HAS_GPS 1 // use on board GPS
|
||||||
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M
|
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M
|
||||||
//#define GPS_INT GPIO_NUM_34 // 30ns accurary timepulse, to be external wired on pcb: NEO 6M Pin#3 -> GPIO34
|
#define GPS_INT GPIO_NUM_34 // 30ns accurary timepulse, to be external wired on pcb: NEO 6M Pin#3 -> GPIO34
|
||||||
|
|
||||||
// Settings for on board DS3231 RTC chip
|
// Settings for on board DS3231 RTC chip
|
||||||
//#define HAS_RTC MY_OLED_SDA, MY_OLED_SCL // SDA, SCL
|
//#define HAS_RTC MY_OLED_SDA, MY_OLED_SCL // SDA, SCL
|
||||||
|
@ -25,16 +25,16 @@
|
|||||||
#define RTC_INT GPIO_NUM_34 // timepulse with accuracy +/- 2*e-6 [microseconds] = 0,1728sec / day
|
#define RTC_INT GPIO_NUM_34 // timepulse with accuracy +/- 2*e-6 [microseconds] = 0,1728sec / day
|
||||||
|
|
||||||
// Settings for IF482 interface
|
// Settings for IF482 interface
|
||||||
//#define HAS_IF482 9600, SERIAL_7E1, GPIO_NUM_12, GPIO_NUM_14 // IF482 serial port parameters
|
#define HAS_IF482 9600, SERIAL_7E1, GPIO_NUM_12, GPIO_NUM_14 // IF482 serial port parameters
|
||||||
|
|
||||||
// Settings for DCF77 interface
|
// Settings for DCF77 interface
|
||||||
//#define HAS_DCF77 GPIO_NUM_14
|
//#define HAS_DCF77 GPIO_NUM_14
|
||||||
//#define DCF77_ACTIVE_LOW 1
|
//#define DCF77_ACTIVE_LOW 1
|
||||||
|
|
||||||
// Settings for external GPS chip
|
// Settings for external GPS chip
|
||||||
//#define HAS_GPS 1 // use on board GPS
|
#define HAS_GPS 1 // use on board GPS
|
||||||
//#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_17, GPIO_NUM_16 // UBlox NEO 6M or 7M with default configuration
|
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_17, GPIO_NUM_16 // UBlox NEO 6M or 7M with default configuration
|
||||||
//#define GPS_INT GPIO_NUM_13
|
#define GPS_INT GPIO_NUM_13
|
||||||
|
|
||||||
// Pins for LORA chip SPI interface, reset line and interrupt lines
|
// Pins for LORA chip SPI interface, reset line and interrupt lines
|
||||||
#define LORA_SCK (5)
|
#define LORA_SCK (5)
|
||||||
|
@ -72,7 +72,7 @@ U: UTC time (not supported by all systems),
|
|||||||
L: Local Time
|
L: Local Time
|
||||||
|
|
||||||
***) Day of week:
|
***) Day of week:
|
||||||
not evaluated by model BU-190
|
not evaluated by model BU-190, use "F" instead for this model
|
||||||
|
|
||||||
*/
|
*/
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -92,16 +92,14 @@ void IF482_Pulse(time_t t) {
|
|||||||
static const TickType_t txDelay =
|
static const TickType_t txDelay =
|
||||||
pdMS_TO_TICKS(IF482_PULSE_LENGTH - tx_Ticks(IF482_FRAME_SIZE, HAS_IF482));
|
pdMS_TO_TICKS(IF482_PULSE_LENGTH - tx_Ticks(IF482_FRAME_SIZE, HAS_IF482));
|
||||||
|
|
||||||
//TickType_t startTime = xTaskGetTickCount();
|
vTaskDelay(txDelay); // wait until moment to fire
|
||||||
//vTaskDelayUntil(&startTime, txDelay); // wait until moment to fire
|
|
||||||
vTaskDelay(txDelay); // wait until moment to fire
|
|
||||||
IF482.print(IF482_Frame(t + 1)); // note: if482 telegram for *next* second
|
IF482.print(IF482_Frame(t + 1)); // note: if482 telegram for *next* second
|
||||||
}
|
}
|
||||||
|
|
||||||
String IRAM_ATTR IF482_Frame(time_t startTime) {
|
String IRAM_ATTR IF482_Frame(time_t startTime) {
|
||||||
|
|
||||||
time_t t = myTZ.toLocal(startTime);
|
time_t t = myTZ.toLocal(startTime);
|
||||||
char mon, out[IF482_FRAME_SIZE];
|
char mon, out[IF482_FRAME_SIZE + 1];
|
||||||
|
|
||||||
switch (timeStatus()) { // indicates if time has been set and recently synced
|
switch (timeStatus()) { // indicates if time has been set and recently synced
|
||||||
case timeSet: // time is set and is synced
|
case timeSet: // time is set and is synced
|
||||||
|
@ -30,12 +30,17 @@ void irqHandler(void *pvParameters) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// are cyclic tasks due?
|
// are cyclic tasks due?
|
||||||
if (InterruptStatus & CYCLIC_IRQ) {
|
if (InterruptStatus & CYCLIC_IRQ)
|
||||||
doHousekeeping();
|
doHousekeeping();
|
||||||
}
|
|
||||||
|
#ifdef TIME_SYNC_INTERVAL
|
||||||
|
// is time to be synced?
|
||||||
|
if (InterruptStatus & TIMESYNC_IRQ)
|
||||||
|
setTime(timeProvider());
|
||||||
|
#endif
|
||||||
|
|
||||||
// is time to send the payload?
|
// is time to send the payload?
|
||||||
if (InterruptStatus & SENDCOUNTER_IRQ)
|
if (InterruptStatus & SENDCYCLE_IRQ)
|
||||||
sendCounter();
|
sendCounter();
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL); // shoud never be reached
|
vTaskDelete(NULL); // shoud never be reached
|
||||||
@ -44,26 +49,28 @@ void irqHandler(void *pvParameters) {
|
|||||||
// esp32 hardware timer triggered interrupt service routines
|
// esp32 hardware timer triggered interrupt service routines
|
||||||
// they notify the irq handler task
|
// they notify the irq handler task
|
||||||
|
|
||||||
void IRAM_ATTR homeCycleIRQ() {
|
|
||||||
xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL);
|
|
||||||
portYIELD_FROM_ISR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR SendCycleIRQ() {
|
|
||||||
xTaskNotifyFromISR(irqHandlerTask, SENDCOUNTER_IRQ, eSetBits, NULL);
|
|
||||||
portYIELD_FROM_ISR();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
void IRAM_ATTR DisplayIRQ() {
|
void IRAM_ATTR DisplayIRQ() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL);
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
portYIELD_FROM_ISR();
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits,
|
||||||
|
&xHigherPriorityTaskWoken);
|
||||||
|
|
||||||
|
if (xHigherPriorityTaskWoken)
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_BUTTON
|
#ifdef HAS_BUTTON
|
||||||
void IRAM_ATTR ButtonIRQ() {
|
void IRAM_ATTR ButtonIRQ() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits, NULL);
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
portYIELD_FROM_ISR();
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits,
|
||||||
|
&xHigherPriorityTaskWoken);
|
||||||
|
|
||||||
|
if (xHigherPriorityTaskWoken)
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,6 +224,12 @@ void onEvent(ev_t ev) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EV_TXCOMPLETE:
|
case EV_TXCOMPLETE:
|
||||||
|
|
||||||
|
#ifdef DBTIMESYNC
|
||||||
|
if (!(LMIC.txrxFlags & TXRX_ACK) && time_sync_seqNo)
|
||||||
|
time_sync_messages[time_sync_seqNo - 1] = LMIC.txend;
|
||||||
|
#endif
|
||||||
|
|
||||||
strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED_ACK")
|
strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED_ACK")
|
||||||
: PSTR("TX_COMPLETE"));
|
: PSTR("TX_COMPLETE"));
|
||||||
sprintf(display_line6, " "); // clear previous lmic status
|
sprintf(display_line6, " "); // clear previous lmic status
|
||||||
@ -465,9 +471,9 @@ void user_request_network_time_callback(void *pVoidUserUTCTime,
|
|||||||
|
|
||||||
// Update system time with time read from the network
|
// Update system time with time read from the network
|
||||||
if (timeIsValid(*pUserUTCTime)) {
|
if (timeIsValid(*pUserUTCTime)) {
|
||||||
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
|
setTime(*pUserUTCTime);
|
||||||
setTime(*pUserUTCTime + 1);
|
|
||||||
timeSource = _lora;
|
timeSource = _lora;
|
||||||
|
timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); // regular repeat
|
||||||
ESP_LOGI(TAG, "Received recent time from LoRa");
|
ESP_LOGI(TAG, "Received recent time from LoRa");
|
||||||
} else
|
} else
|
||||||
ESP_LOGI(TAG, "Invalid time received from LoRa");
|
ESP_LOGI(TAG, "Invalid time received from LoRa");
|
||||||
|
111
src/main.cpp
111
src/main.cpp
@ -23,19 +23,21 @@ licenses. Refer to LICENSE.txt file in repository for more details.
|
|||||||
|
|
||||||
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
|
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||||
|
|
||||||
Uused tasks and timers:
|
// Tasks and timers:
|
||||||
|
|
||||||
Task Core Prio Purpose
|
Task Core Prio Purpose
|
||||||
====================================================================================
|
-------------------------------------------------------------------------------
|
||||||
ledloop 0 3 blinks LEDs
|
ledloop 0 3 blinks LEDs
|
||||||
spiloop 0 2 reads/writes data on spi interface
|
spiloop 0 2 reads/writes data on spi interface
|
||||||
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||||
|
|
||||||
clockloop 1 4 generates realtime telegrams for external clock
|
clockloop 1 4 generates realtime telegrams for external clock
|
||||||
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
||||||
irqhandler 1 1 executes tasks triggered by hw irq, see table below
|
irqhandler 1 1 executes tasks triggered by timer irq
|
||||||
gpsloop 1 2 reads data from GPS via serial or i2c
|
gpsloop 1 2 reads data from GPS via serial or i2c
|
||||||
bmeloop 1 1 reads data from BME sensor via i2c
|
bmeloop 1 1 reads data from BME sensor via i2c
|
||||||
|
timesync_ans 1 0 temporary task for receiving time sync requests
|
||||||
|
timesync_req 1 0 temporary task for sending time sync requests
|
||||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||||
|
|
||||||
Low priority numbers denote low priority tasks.
|
Low priority numbers denote low priority tasks.
|
||||||
@ -43,16 +45,29 @@ Low priority numbers denote low priority tasks.
|
|||||||
Tasks using i2c bus all must have same priority, because using mutex semaphore
|
Tasks using i2c bus all must have same priority, because using mutex semaphore
|
||||||
(irqhandler, bmeloop)
|
(irqhandler, bmeloop)
|
||||||
|
|
||||||
ESP32 hardware irq timers
|
// ESP32 hardware timers
|
||||||
================================
|
-------------------------------------------------------------------------------
|
||||||
0 triggers display refresh
|
0 displayIRQ -> display refresh -> 40ms (DISPLAYREFRESH_MS in
|
||||||
1 triggers DCF77 clock signal
|
paxcounter.conf) 1 ppsIRQ -> pps clock irq -> 1sec 2 unused 3 unused
|
||||||
2 triggers send payload cycle
|
|
||||||
3 triggers housekeeping cycle
|
|
||||||
|
|
||||||
RTC hardware timer (if present)
|
|
||||||
================================
|
// Interrupt routines
|
||||||
triggers pps 1 sec impulse
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fired by hardware
|
||||||
|
DisplayIRQ -> esp32 timer 0 -> irqhandler.cpp
|
||||||
|
CLOCKIRQ -> esp32 timer 1 -> timekeeper.cpp
|
||||||
|
ButtonIRQ -> external gpio -> irqhandler.cpp
|
||||||
|
|
||||||
|
fired by software (Ticker.h)
|
||||||
|
TIMESYNC_IRQ -> timeSync() -> timerkeeper.cpp
|
||||||
|
CYLCIC_IRQ -> housekeeping() -> cyclic.cpp
|
||||||
|
SENDCYCLE_IRQ -> sendcycle() -> senddata.cpp
|
||||||
|
|
||||||
|
|
||||||
|
// External RTC timer (if present)
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
triggers pps 1 sec impulse
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -65,8 +80,7 @@ uint8_t volatile channel = 0; // channel rotation counter
|
|||||||
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
|
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
|
||||||
batt_voltage = 0; // globals for display
|
batt_voltage = 0; // globals for display
|
||||||
|
|
||||||
hw_timer_t *sendCycle = NULL, *homeCycle = NULL, *clockCycle = NULL,
|
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL;
|
||||||
*displaytimer = NULL;
|
|
||||||
|
|
||||||
TaskHandle_t irqHandlerTask, ClockTask;
|
TaskHandle_t irqHandlerTask, ClockTask;
|
||||||
SemaphoreHandle_t I2Caccess, TimePulse;
|
SemaphoreHandle_t I2Caccess, TimePulse;
|
||||||
@ -302,27 +316,8 @@ void setup() {
|
|||||||
strcat_P(features, " OLED");
|
strcat_P(features, " OLED");
|
||||||
DisplayState = cfg.screenon;
|
DisplayState = cfg.screenon;
|
||||||
init_display(PRODUCTNAME, PROGVERSION); // note: blocking call
|
init_display(PRODUCTNAME, PROGVERSION); // note: blocking call
|
||||||
|
|
||||||
// setup display refresh trigger IRQ using esp32 hardware timer
|
|
||||||
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
|
||||||
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
|
|
||||||
displaytimer = timerBegin(0, 80, true);
|
|
||||||
// interrupt handler DisplayIRQ, triggered by edge
|
|
||||||
timerAttachInterrupt(displaytimer, &DisplayIRQ, true);
|
|
||||||
// reload interrupt after each trigger of display refresh cycle
|
|
||||||
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// setup send cycle trigger IRQ using esp32 hardware timer 2
|
|
||||||
sendCycle = timerBegin(2, 8000, true);
|
|
||||||
timerAttachInterrupt(sendCycle, &SendCycleIRQ, true);
|
|
||||||
timerAlarmWrite(sendCycle, cfg.sendcycle * 2 * 10000, true);
|
|
||||||
|
|
||||||
// setup house keeping cycle trigger IRQ using esp32 hardware timer 3
|
|
||||||
homeCycle = timerBegin(3, 8000, true);
|
|
||||||
timerAttachInterrupt(homeCycle, &homeCycleIRQ, true);
|
|
||||||
timerAlarmWrite(homeCycle, HOMECYCLE * 10000, true);
|
|
||||||
|
|
||||||
// show payload encoder
|
// show payload encoder
|
||||||
#if PAYLOAD_ENCODER == 1
|
#if PAYLOAD_ENCODER == 1
|
||||||
strcat_P(features, " PLAIN");
|
strcat_P(features, " PLAIN");
|
||||||
@ -358,19 +353,6 @@ void setup() {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined HAS_IF482 || defined HAS_DCF77
|
|
||||||
// start pps timepulse
|
|
||||||
ESP_LOGI(TAG, "Starting Timekeeper...");
|
|
||||||
assert(timepulse_init()); // setup timepulse
|
|
||||||
timepulse_start();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TIME_SYNC_INTERVAL
|
|
||||||
// set time source and sync time
|
|
||||||
setSyncInterval(TIME_SYNC_INTERVAL * 60);
|
|
||||||
setSyncProvider(&timeProvider);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// start wifi in monitor mode and start channel rotation timer
|
// start wifi in monitor mode and start channel rotation timer
|
||||||
ESP_LOGI(TAG, "Starting Wifi...");
|
ESP_LOGI(TAG, "Starting Wifi...");
|
||||||
wifi_sniffer_init();
|
wifi_sniffer_init();
|
||||||
@ -404,16 +386,25 @@ void setup() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// starting timers and interrupts
|
||||||
assert(irqHandlerTask != NULL); // has interrupt handler task started?
|
assert(irqHandlerTask != NULL); // has interrupt handler task started?
|
||||||
// start timer triggered interrupts
|
ESP_LOGI(TAG, "Starting Timers...");
|
||||||
ESP_LOGI(TAG, "Starting Interrupts...");
|
|
||||||
#ifdef HAS_DISPLAY
|
|
||||||
timerAlarmEnable(displaytimer);
|
|
||||||
#endif
|
|
||||||
timerAlarmEnable(sendCycle);
|
|
||||||
timerAlarmEnable(homeCycle);
|
|
||||||
|
|
||||||
// start button interrupt
|
// display interrupt
|
||||||
|
#ifdef HAS_DISPLAY
|
||||||
|
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
||||||
|
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
|
||||||
|
displayIRQ = timerBegin(0, 80, true);
|
||||||
|
timerAttachInterrupt(displayIRQ, &DisplayIRQ, true);
|
||||||
|
timerAlarmWrite(displayIRQ, DISPLAYREFRESH_MS * 1000, true);
|
||||||
|
timerAlarmEnable(displayIRQ);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// cyclic function interrupts
|
||||||
|
sendcycler.attach(SENDCYCLE * 2, sendcycle);
|
||||||
|
housekeeper.attach(HOMECYCLE, housekeeping);
|
||||||
|
|
||||||
|
// button interrupt
|
||||||
#ifdef HAS_BUTTON
|
#ifdef HAS_BUTTON
|
||||||
#ifdef BUTTON_PULLUP
|
#ifdef BUTTON_PULLUP
|
||||||
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
|
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
|
||||||
@ -422,7 +413,19 @@ void setup() {
|
|||||||
#endif
|
#endif
|
||||||
#endif // HAS_BUTTON
|
#endif // HAS_BUTTON
|
||||||
|
|
||||||
|
#ifdef TIME_SYNC_INTERVAL
|
||||||
|
// start pps timepulse
|
||||||
|
ESP_LOGI(TAG, "Starting Timekeeper...");
|
||||||
|
assert(timepulse_init()); // setup timepulse
|
||||||
|
timepulse_start();
|
||||||
|
timeSync(); // init systime
|
||||||
|
timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined HAS_IF482 || defined HAS_DCF77
|
#if defined HAS_IF482 || defined HAS_DCF77
|
||||||
|
#ifndef TIME_SYNC_INTERVAL
|
||||||
|
#error for clock controller function TIME_SNYC_INTERVAL must be defined in paxcounter.conf
|
||||||
|
#endif
|
||||||
ESP_LOGI(TAG, "Starting Clock Controller...");
|
ESP_LOGI(TAG, "Starting Clock Controller...");
|
||||||
clock_init();
|
clock_init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
||||||
|
|
||||||
// Payload send cycle and encoding
|
// Payload send cycle and encoding
|
||||||
#define SEND_SECS 30 // payload send cycle [seconds/2] -> 60 sec.
|
#define SENDCYCLE 30 // payload send cycle [seconds/2], 0 .. 255
|
||||||
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed
|
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed
|
||||||
|
|
||||||
// Set this to include BLE counting and vendor filter functions
|
// Set this to include BLE counting and vendor filter functions
|
||||||
@ -66,8 +66,9 @@
|
|||||||
#define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds]
|
#define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds]
|
||||||
|
|
||||||
// settings for syncing time of node with external time source
|
// settings for syncing time of node with external time source
|
||||||
//#define TIME_SYNC_INTERVAL 2 // sync time attempt each .. minutes from time source (GPS/LORA/RTC) [default = 60], comment out means off
|
#define TIME_SYNC_INTERVAL 2 // sync time attempt each .. minutes from time source (GPS/LORA/RTC) [default = 60], comment out means off
|
||||||
//#define TIME_SYNC_LORA 1 // use LORA network as time source, comment out means off [default = off]
|
//#define TIME_SYNC_LORA 1 // use LORA network as time source, comment out means off [default = off]
|
||||||
|
#define DBTIMESYNC 1 // use DB LORA timeserver with patented sync algorithm [default = off]
|
||||||
|
|
||||||
// time zone, see https://github.com/JChristensen/Timezone/blob/master/examples/WorldClock/WorldClock.ino
|
// time zone, see https://github.com/JChristensen/Timezone/blob/master/examples/WorldClock/WorldClock.ino
|
||||||
#define DAYLIGHT_TIME {"CEST", Last, Sun, Mar, 2, 120} // Central European Summer Time
|
#define DAYLIGHT_TIME {"CEST", Last, Sun, Mar, 2, 120} // Central European Summer Time
|
||||||
|
@ -290,11 +290,12 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------- Cayenne LPP 2.0 format ---------- */
|
/* ---------------- Cayenne LPP 2.0 format ---------- */
|
||||||
// see specs
|
// see specs
|
||||||
// http://community.mydevices.com/t/cayenne-lpp-2-0/7510 (LPP 2.0)
|
// http://community.mydevices.com/t/cayenne-lpp-2-0/7510 (LPP 2.0)
|
||||||
// https://github.com/myDevicesIoT/cayenne-docs/blob/master/docs/LORA.md (LPP 1.0)
|
// https://github.com/myDevicesIoT/cayenne-docs/blob/master/docs/LORA.md
|
||||||
// PAYLOAD_ENCODER == 3 -> Dynamic Sensor Payload, using channels -> FPort 1
|
// (LPP 1.0) PAYLOAD_ENCODER == 3 -> Dynamic Sensor Payload, using channels ->
|
||||||
// PAYLOAD_ENCODER == 4 -> Packed Sensor Payload, not using channels -> FPort 2
|
// FPort 1 PAYLOAD_ENCODER == 4 -> Packed Sensor Payload, not using channels ->
|
||||||
|
// FPort 2
|
||||||
|
|
||||||
#elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4)
|
#elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4)
|
||||||
|
|
||||||
@ -456,7 +457,7 @@ void PayloadConvert::addButton(uint8_t value) {
|
|||||||
void PayloadConvert::addTime(time_t value) {
|
void PayloadConvert::addTime(time_t value) {
|
||||||
#if (PAYLOAD_ENCODER == 4)
|
#if (PAYLOAD_ENCODER == 4)
|
||||||
uint32_t t = (uint32_t)value;
|
uint32_t t = (uint32_t)value;
|
||||||
uint32_t tx_period = (uint32_t)SEND_SECS * 2;
|
uint32_t tx_period = (uint32_t)SENDCYCLE * 2;
|
||||||
buffer[cursor++] = 0x03; // set config mask to UTCTime + TXPeriod
|
buffer[cursor++] = 0x03; // set config mask to UTCTime + TXPeriod
|
||||||
// UTCTime in seconds
|
// UTCTime in seconds
|
||||||
buffer[cursor++] = (byte)((t & 0xFF000000) >> 24);
|
buffer[cursor++] = (byte)((t & 0xFF000000) >> 24);
|
||||||
|
@ -58,9 +58,8 @@ void set_rssi(uint8_t val[]) {
|
|||||||
|
|
||||||
void set_sendcycle(uint8_t val[]) {
|
void set_sendcycle(uint8_t val[]) {
|
||||||
cfg.sendcycle = val[0];
|
cfg.sendcycle = val[0];
|
||||||
// update send cycle interrupt
|
// update send cycle interrupt [seconds
|
||||||
timerAlarmWrite(sendCycle, cfg.sendcycle * 2 * 10000, true);
|
sendcycler.attach(cfg.sendcycle * 2, sendcycle);
|
||||||
// reload interrupt after each trigger of channel switch cycle
|
|
||||||
ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds",
|
ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds",
|
||||||
cfg.sendcycle * 2);
|
cfg.sendcycle * 2);
|
||||||
}
|
}
|
||||||
@ -283,19 +282,35 @@ void get_time(uint8_t val[]) {
|
|||||||
// format: opcode, function, #bytes params,
|
// format: opcode, function, #bytes params,
|
||||||
// flag (true = do make settings persistent / false = don't)
|
// flag (true = do make settings persistent / false = don't)
|
||||||
//
|
//
|
||||||
cmd_t table[] = {
|
cmd_t table[] = {{0x01, set_rssi, 1, true},
|
||||||
{0x01, set_rssi, 1, true}, {0x02, set_countmode, 1, true},
|
{0x02, set_countmode, 1, true},
|
||||||
{0x03, set_gps, 1, true}, {0x04, set_display, 1, true},
|
{0x03, set_gps, 1, true},
|
||||||
{0x05, set_lorasf, 1, true}, {0x06, set_lorapower, 1, true},
|
{0x04, set_display, 1, true},
|
||||||
{0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true},
|
{0x05, set_lorasf, 1, true},
|
||||||
{0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true},
|
{0x06, set_lorapower, 1, true},
|
||||||
{0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true},
|
{0x07, set_loraadr, 1, true},
|
||||||
{0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true},
|
{0x08, set_screensaver, 1, true},
|
||||||
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},
|
{0x09, set_reset, 1, true},
|
||||||
{0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false},
|
{0x0a, set_sendcycle, 1, true},
|
||||||
{0x13, set_sensor, 2, true}, {0x80, get_config, 0, false},
|
{0x0b, set_wifichancycle, 1, true},
|
||||||
{0x81, get_status, 0, false}, {0x84, get_gps, 0, false},
|
{0x0c, set_blescantime, 1, true},
|
||||||
{0x85, get_bme, 0, false}, {0x86, get_time, 0, false},
|
{0x0d, set_vendorfilter, 1, false},
|
||||||
|
{0x0e, set_blescan, 1, true},
|
||||||
|
{0x0f, set_wifiant, 1, true},
|
||||||
|
{0x10, set_rgblum, 1, true},
|
||||||
|
{0x11, set_monitor, 1, true},
|
||||||
|
{0x12, set_beacon, 7, false},
|
||||||
|
{0x13, set_sensor, 2, true},
|
||||||
|
{0x80, get_config, 0, false},
|
||||||
|
{0x81, get_status, 0, false},
|
||||||
|
{0x84, get_gps, 0, false},
|
||||||
|
{0x85, get_bme, 0, false},
|
||||||
|
{0x86, get_time, 0, false}
|
||||||
|
#ifdef DBTIMESYNC
|
||||||
|
,
|
||||||
|
{TIME_ANS_OPCODE, recv_DBtime_ans, 0, false},
|
||||||
|
{TIME_SYNC_OPCODE, force_DBtime_sync, 0, false}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t cmdtablesize =
|
const uint8_t cmdtablesize =
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
// Basic Config
|
// Basic Config
|
||||||
#include "senddata.h"
|
#include "senddata.h"
|
||||||
|
|
||||||
|
Ticker sendcycler;
|
||||||
|
|
||||||
|
void sendcycle() { xTaskNotify(irqHandlerTask, SENDCYCLE_IRQ, eSetBits); }
|
||||||
|
|
||||||
// put data to send in RTos Queues used for transmit over channels Lora and SPI
|
// put data to send in RTos Queues used for transmit over channels Lora and SPI
|
||||||
void SendPayload(uint8_t port, sendprio_t prio) {
|
void SendPayload(uint8_t port, sendprio_t prio) {
|
||||||
|
|
||||||
|
@ -6,12 +6,12 @@ static const char TAG[] = __FILE__;
|
|||||||
// symbol to display current time source
|
// symbol to display current time source
|
||||||
const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
||||||
|
|
||||||
getExternalTime TimeSourcePtr; // pointer to time source function
|
Ticker timesyncer;
|
||||||
|
|
||||||
|
void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
|
||||||
|
|
||||||
time_t timeProvider(void) {
|
time_t timeProvider(void) {
|
||||||
|
|
||||||
ESP_LOGD(TAG, "time synched");
|
|
||||||
|
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
@ -21,6 +21,7 @@ time_t timeProvider(void) {
|
|||||||
set_rtctime(t); // calibrate RTC
|
set_rtctime(t); // calibrate RTC
|
||||||
#endif
|
#endif
|
||||||
timeSource = _gps;
|
timeSource = _gps;
|
||||||
|
timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); // regular repeat
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -30,16 +31,22 @@ time_t timeProvider(void) {
|
|||||||
t = get_rtctime();
|
t = get_rtctime();
|
||||||
if (t) {
|
if (t) {
|
||||||
timeSource = _rtc;
|
timeSource = _rtc;
|
||||||
|
timesyncer.attach(60, timeSync); // short retry
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// kick off asychron lora sync if we have
|
// kick off asychronous DB timesync if we have
|
||||||
#if defined HAS_LORA && defined TIME_SYNC_LORA
|
#ifdef DBTIMESYNC
|
||||||
|
send_DBtime_req();
|
||||||
|
// kick off asychronous lora sync if we have
|
||||||
|
#elif defined HAS_LORA && defined TIME_SYNC_LORA
|
||||||
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
|
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!t)
|
if (!t) {
|
||||||
timeSource = _unsynced;
|
timeSource = _unsynced;
|
||||||
|
timesyncer.attach(60, timeSync); // short retry
|
||||||
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
@ -78,8 +85,8 @@ uint8_t timepulse_init() {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
// use ESP32 hardware timer as time base with adjustable frequency
|
// use ESP32 hardware timer as time base with adjustable frequency
|
||||||
clockCycle = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
|
ppsIRQ = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
|
||||||
timerAlarmWrite(clockCycle, 10000, true); // 1000ms
|
timerAlarmWrite(ppsIRQ, 10000, true); // 1000ms
|
||||||
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
|
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
|
||||||
return 1; // success
|
return 1; // success
|
||||||
|
|
||||||
@ -92,8 +99,8 @@ void timepulse_start(void) {
|
|||||||
#elif defined RTC_INT // start external clock rtc
|
#elif defined RTC_INT // start external clock rtc
|
||||||
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
|
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
|
||||||
#else // start internal clock esp32 hardware timer
|
#else // start internal clock esp32 hardware timer
|
||||||
timerAttachInterrupt(clockCycle, &CLOCKIRQ, true);
|
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
|
||||||
timerAlarmEnable(clockCycle);
|
timerAlarmEnable(ppsIRQ);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,12 +108,11 @@ void timepulse_start(void) {
|
|||||||
void IRAM_ATTR CLOCKIRQ(void) {
|
void IRAM_ATTR CLOCKIRQ(void) {
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken;
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
|
SyncToPPS(); // calibrates UTC systime, see Time.h
|
||||||
time_t t = SyncToPPS(); // calibrates UTC systime, see Time.h
|
|
||||||
xHigherPriorityTaskWoken = pdFALSE;
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
if (ClockTask != NULL)
|
if (ClockTask != NULL)
|
||||||
xTaskNotifyFromISR(ClockTask, uint32_t(t), eSetBits,
|
xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits,
|
||||||
&xHigherPriorityTaskWoken);
|
&xHigherPriorityTaskWoken);
|
||||||
|
|
||||||
#if defined GPS_INT || defined RTC_INT
|
#if defined GPS_INT || defined RTC_INT
|
||||||
@ -214,7 +220,7 @@ void clock_loop(void *taskparameter) { // ClockTask
|
|||||||
|
|
||||||
#if defined HAS_IF482
|
#if defined HAS_IF482
|
||||||
|
|
||||||
IF482_Pulse(t);
|
IF482_Pulse(nextsec(t));
|
||||||
|
|
||||||
#elif defined HAS_DCF77
|
#elif defined HAS_DCF77
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user