commit
60c6e3c2e8
@ -30,11 +30,6 @@
|
|||||||
// length of display buffer for lmic event messages
|
// length of display buffer for lmic event messages
|
||||||
#define LMIC_EVENTMSG_LEN 17
|
#define LMIC_EVENTMSG_LEN 17
|
||||||
|
|
||||||
// I2C bus access control
|
|
||||||
#define I2C_MUTEX_LOCK() \
|
|
||||||
(xSemaphoreTake(I2Caccess, pdMS_TO_TICKS(DISPLAYREFRESH_MS)) == pdTRUE)
|
|
||||||
#define I2C_MUTEX_UNLOCK() (xSemaphoreGive(I2Caccess))
|
|
||||||
|
|
||||||
// pseudo system halt function, useful to prevent writeloops to NVRAM
|
// pseudo system halt function, useful to prevent writeloops to NVRAM
|
||||||
#ifndef _ASSERT
|
#ifndef _ASSERT
|
||||||
#define _ASSERT(cond) \
|
#define _ASSERT(cond) \
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
#include "dcf77.h"
|
#include "dcf77.h"
|
||||||
#include "esp_sntp.h"
|
#include "esp_sntp.h"
|
||||||
|
|
||||||
#define HAS_LORA_TIME ((HAS_LORA) && ((TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN)))
|
#define HAS_LORA_TIME \
|
||||||
|
((HAS_LORA) && ((TIME_SYNC_LORASERVER) || (TIME_SYNC_LORAWAN)))
|
||||||
|
|
||||||
#define SECS_YR_2000 (946684800UL) // the time at the start of y2k
|
#define SECS_YR_2000 (946684800UL) // the time at the start of y2k
|
||||||
#define GPS_UTC_DIFF 315964800UL // seconds diff between gps and utc epoch
|
#define GPS_UTC_DIFF 315964800UL // seconds diff between gps and utc epoch
|
||||||
@ -26,16 +27,14 @@ extern DRAM_ATTR bool TimePulseTick; // 1sec pps flag set by GPS or RTC
|
|||||||
extern DRAM_ATTR unsigned long lastPPS;
|
extern DRAM_ATTR unsigned long lastPPS;
|
||||||
extern hw_timer_t *ppsIRQ;
|
extern hw_timer_t *ppsIRQ;
|
||||||
|
|
||||||
void IRAM_ATTR CLOCKIRQ(void);
|
//void IRAM_ATTR CLOCKIRQ(void);
|
||||||
void IRAM_ATTR GPSIRQ(void);
|
//void IRAM_ATTR GPSIRQ(void);
|
||||||
void clock_init(void);
|
//void clock_loop(void *pvParameters);
|
||||||
void clock_loop(void *pvParameters);
|
|
||||||
void setTimeSyncIRQ(void);
|
void setTimeSyncIRQ(void);
|
||||||
uint8_t timepulse_init(void);
|
void time_init(void);
|
||||||
bool timeIsValid(time_t const t);
|
bool timeIsValid(time_t const t);
|
||||||
void calibrateTime(void);
|
void calibrateTime(void);
|
||||||
bool setMyTime(uint32_t t_sec, uint16_t t_msec,
|
bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource);
|
||||||
timesource_t mytimesource);
|
|
||||||
time_t compileTime(void);
|
time_t compileTime(void);
|
||||||
time_t mkgmtime(const struct tm *ptm);
|
time_t mkgmtime(const struct tm *ptm);
|
||||||
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,
|
||||||
|
@ -52,42 +52,28 @@ int bme_init(void) {
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
#ifdef HAS_BME680
|
#ifdef HAS_BME680
|
||||||
// block i2c bus access
|
Wire.begin(HAS_BME680);
|
||||||
if (I2C_MUTEX_LOCK()) {
|
iaqSensor.begin(BME680_ADDR, Wire);
|
||||||
|
|
||||||
Wire.begin(HAS_BME680);
|
ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major,
|
||||||
iaqSensor.begin(BME680_ADDR, Wire);
|
iaqSensor.version.minor, iaqSensor.version.major_bugfix,
|
||||||
|
iaqSensor.version.minor_bugfix);
|
||||||
|
|
||||||
ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major,
|
iaqSensor.setConfig(bsec_config_iaq);
|
||||||
iaqSensor.version.minor, iaqSensor.version.major_bugfix,
|
loadState();
|
||||||
iaqSensor.version.minor_bugfix);
|
iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET);
|
||||||
|
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
|
||||||
|
|
||||||
iaqSensor.setConfig(bsec_config_iaq);
|
rc = checkIaqSensorStatus();
|
||||||
loadState();
|
|
||||||
iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET);
|
|
||||||
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
|
|
||||||
|
|
||||||
rc = checkIaqSensorStatus();
|
|
||||||
|
|
||||||
} else
|
|
||||||
ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error");
|
|
||||||
|
|
||||||
#elif defined HAS_BME280
|
#elif defined HAS_BME280
|
||||||
if (I2C_MUTEX_LOCK()) {
|
rc = bme.begin(BME280_ADDR);
|
||||||
rc = bme.begin(BME280_ADDR);
|
|
||||||
} else
|
|
||||||
ESP_LOGE(TAG, "I2c bus busy - BME280 initialization error");
|
|
||||||
|
|
||||||
#elif defined HAS_BMP180
|
#elif defined HAS_BMP180
|
||||||
if (I2C_MUTEX_LOCK()) {
|
// Wire.begin(21, 22);
|
||||||
// Wire.begin(21, 22);
|
rc = bmp.begin();
|
||||||
rc = bmp.begin();
|
|
||||||
} else
|
|
||||||
ESP_LOGE(TAG, "I2c bus busy - BMP180 initialization error");
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
if (rc)
|
if (rc)
|
||||||
bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit
|
bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit
|
||||||
return rc;
|
return rc;
|
||||||
@ -123,8 +109,7 @@ int checkIaqSensorStatus(void) {
|
|||||||
// store current BME sensor data in struct
|
// store current BME sensor data in struct
|
||||||
void bme_storedata(bmeStatus_t *bme_store) {
|
void bme_storedata(bmeStatus_t *bme_store) {
|
||||||
|
|
||||||
if ((cfg.payloadmask & MEMS_DATA) &&
|
if (cfg.payloadmask & MEMS_DATA)
|
||||||
(I2C_MUTEX_LOCK())) { // block i2c bus access
|
|
||||||
|
|
||||||
#ifdef HAS_BME680
|
#ifdef HAS_BME680
|
||||||
if (iaqSensor.run()) { // if new data is available
|
if (iaqSensor.run()) { // if new data is available
|
||||||
@ -143,20 +128,17 @@ void bme_storedata(bmeStatus_t *bme_store) {
|
|||||||
}
|
}
|
||||||
#elif defined HAS_BME280
|
#elif defined HAS_BME280
|
||||||
bme_store->temperature = bme.readTemperature();
|
bme_store->temperature = bme.readTemperature();
|
||||||
bme_store->pressure = (bme.readPressure() / 100.0); // conversion Pa -> hPa
|
bme_store->pressure = (bme.readPressure() / 100.0); // conversion Pa -> hPa
|
||||||
// bme.readAltitude(SEALEVELPRESSURE_HPA);
|
// bme.readAltitude(SEALEVELPRESSURE_HPA);
|
||||||
bme_store->humidity = bme.readHumidity();
|
bme_store->humidity = bme.readHumidity();
|
||||||
bme_store->iaq = 0; // IAQ feature not present with BME280
|
bme_store->iaq = 0; // IAQ feature not present with BME280
|
||||||
#elif defined HAS_BMP180
|
#elif defined HAS_BMP180
|
||||||
bme_store->temperature = bmp.readTemperature();
|
bme_store->temperature = bmp.readTemperature();
|
||||||
bme_store->pressure = (bmp.readPressure() / 100.0); // conversion Pa -> hPa
|
bme_store->pressure = (bmp.readPressure() / 100.0); // conversion Pa -> hPa
|
||||||
// bme.readAltitude(SEALEVELPRESSURE_HPA);
|
// bme.readAltitude(SEALEVELPRESSURE_HPA);
|
||||||
bme_store->iaq = 0; // IAQ feature not present with BME280
|
bme_store->iaq = 0; // IAQ feature not present with BME280
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
}
|
|
||||||
|
|
||||||
} // bme_storedata()
|
} // bme_storedata()
|
||||||
|
|
||||||
#ifdef HAS_BME680
|
#ifdef HAS_BME680
|
||||||
|
@ -18,10 +18,6 @@ void doHousekeeping() {
|
|||||||
if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE))
|
if ((RTC_runmode == RUNMODE_UPDATE) || (RTC_runmode == RUNMODE_MAINTENANCE))
|
||||||
do_reset(true); // warmstart
|
do_reset(true); // warmstart
|
||||||
|
|
||||||
// try to get time if we don't yet have a recent timesource
|
|
||||||
if (timeSource == _unsynced || timeSource == _set)
|
|
||||||
calibrateTime();
|
|
||||||
|
|
||||||
// print heap and task storage information
|
// print heap and task storage information
|
||||||
ESP_LOGD(TAG, "Heap: Free:%d, Min:%d, Size:%d, Alloc:%d, StackHWM:%d",
|
ESP_LOGD(TAG, "Heap: Free:%d, Min:%d, Size:%d, Alloc:%d, StackHWM:%d",
|
||||||
ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(),
|
ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(),
|
||||||
|
146
src/display.cpp
146
src/display.cpp
@ -90,85 +90,72 @@ void dp_setup(int contrast) {
|
|||||||
|
|
||||||
void dp_init(bool verbose) {
|
void dp_init(bool verbose) {
|
||||||
|
|
||||||
#if (HAS_DISPLAY) == 1 // i2c
|
dp_setup(DISPLAYCONTRAST);
|
||||||
// block i2c bus access
|
|
||||||
if (!I2C_MUTEX_LOCK())
|
|
||||||
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds());
|
|
||||||
else {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dp_setup(DISPLAYCONTRAST);
|
if (verbose) {
|
||||||
|
|
||||||
if (verbose) {
|
// show startup screen
|
||||||
|
// to come -> display .bmp file with logo
|
||||||
// show startup screen
|
|
||||||
// to come -> display .bmp file with logo
|
|
||||||
|
|
||||||
// show chip information
|
// show chip information
|
||||||
#if (VERBOSE)
|
#if (VERBOSE)
|
||||||
esp_chip_info_t chip_info;
|
esp_chip_info_t chip_info;
|
||||||
esp_chip_info(&chip_info);
|
esp_chip_info(&chip_info);
|
||||||
|
|
||||||
dp_setFont(MY_FONT_NORMAL);
|
dp_setFont(MY_FONT_NORMAL);
|
||||||
dp_printf("** PAXCOUNTER **");
|
dp_printf("** PAXCOUNTER **");
|
||||||
dp_println();
|
dp_println();
|
||||||
dp_printf("Software v%s", PROGVERSION);
|
dp_printf("Software v%s", PROGVERSION);
|
||||||
dp_println();
|
dp_println();
|
||||||
dp_printf("ESP32 %d cores", chip_info.cores);
|
dp_printf("ESP32 %d cores", chip_info.cores);
|
||||||
dp_println();
|
dp_println();
|
||||||
dp_printf("Chip Rev.%d", chip_info.revision);
|
dp_printf("Chip Rev.%d", chip_info.revision);
|
||||||
dp_println();
|
dp_println();
|
||||||
dp_printf("WiFi%s%s", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
dp_printf("WiFi%s%s", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||||
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
||||||
dp_println();
|
dp_println();
|
||||||
dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024),
|
dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024),
|
||||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int."
|
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext.");
|
||||||
: "ext.");
|
|
||||||
|
|
||||||
// give user some time to read or take picture
|
// give user some time to read or take picture
|
||||||
dp_dump(displaybuf);
|
dp_dump(displaybuf);
|
||||||
delay(2000);
|
delay(2000);
|
||||||
dp_clear();
|
dp_clear();
|
||||||
#endif // VERBOSE
|
#endif // VERBOSE
|
||||||
|
|
||||||
#if (HAS_LORA)
|
#if (HAS_LORA)
|
||||||
// generate DEVEUI as QR code and text
|
// generate DEVEUI as QR code and text
|
||||||
uint8_t buf[8], *p = buf;
|
uint8_t buf[8], *p = buf;
|
||||||
char deveui[17];
|
char deveui[17];
|
||||||
os_getDevEui((u1_t *)buf);
|
os_getDevEui((u1_t *)buf);
|
||||||
snprintf(deveui, 17, "%016llX", (*(uint64_t *)(p)));
|
snprintf(deveui, 17, "%016llX", (*(uint64_t *)(p)));
|
||||||
|
|
||||||
// display DEVEUI as QR code on the left
|
// display DEVEUI as QR code on the left
|
||||||
dp_contrast(30);
|
dp_contrast(30);
|
||||||
dp_printqr(3, 3, deveui);
|
dp_printqr(3, 3, deveui);
|
||||||
|
|
||||||
// display DEVEUI as plain text on the right
|
// display DEVEUI as plain text on the right
|
||||||
const int x_offset = QR_SCALEFACTOR * 29 + 14;
|
const int x_offset = QR_SCALEFACTOR * 29 + 14;
|
||||||
dp_setTextCursor(x_offset, 0);
|
dp_setTextCursor(x_offset, 0);
|
||||||
dp_setFont(MY_FONT_NORMAL);
|
dp_setFont(MY_FONT_NORMAL);
|
||||||
dp_printf("DEVEUI");
|
dp_printf("DEVEUI");
|
||||||
dp_println();
|
dp_println();
|
||||||
for (uint8_t i = 0; i <= 3; i++) {
|
for (uint8_t i = 0; i <= 3; i++) {
|
||||||
dp_setTextCursor(x_offset, i + 3);
|
dp_setTextCursor(x_offset, i + 3);
|
||||||
dp_printf("%4.4s", deveui + i * 4);
|
dp_printf("%4.4s", deveui + i * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// give user some time to read or take picture
|
// give user some time to read or take picture
|
||||||
dp_dump(displaybuf);
|
dp_dump(displaybuf);
|
||||||
#if !(BOOTMENU)
|
#if !(BOOTMENU)
|
||||||
delay(8000);
|
delay(8000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // HAS_LORA
|
#endif // HAS_LORA
|
||||||
|
|
||||||
} // verbose
|
} // verbose
|
||||||
|
|
||||||
dp_power(cfg.screenon); // set display off if disabled
|
dp_power(cfg.screenon); // set display off if disabled
|
||||||
|
|
||||||
#if (HAS_DISPLAY) == 1 // i2c
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
} // mutex
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // dp_init
|
} // dp_init
|
||||||
|
|
||||||
@ -182,29 +169,22 @@ void dp_refresh(bool nextPage) {
|
|||||||
if (!DisplayIsOn && (DisplayIsOn == cfg.screenon))
|
if (!DisplayIsOn && (DisplayIsOn == cfg.screenon))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// block i2c bus access
|
// set display on/off according to current device configuration
|
||||||
if (!I2C_MUTEX_LOCK())
|
if (DisplayIsOn != cfg.screenon) {
|
||||||
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds());
|
DisplayIsOn = cfg.screenon;
|
||||||
else {
|
dp_power(cfg.screenon);
|
||||||
// set display on/off according to current device configuration
|
}
|
||||||
if (DisplayIsOn != cfg.screenon) {
|
|
||||||
DisplayIsOn = cfg.screenon;
|
|
||||||
dp_power(cfg.screenon);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef HAS_BUTTON
|
#ifndef HAS_BUTTON
|
||||||
// auto flip page if we are in unattended mode
|
// auto flip page if we are in unattended mode
|
||||||
if ((++framecounter) > (DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS)) {
|
if ((++framecounter) > (DISPLAYCYCLE * 1000 / DISPLAYREFRESH_MS)) {
|
||||||
framecounter = 0;
|
framecounter = 0;
|
||||||
nextPage = true;
|
nextPage = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dp_drawPage(nextPage);
|
dp_drawPage(nextPage);
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
|
|
||||||
} // mutex
|
|
||||||
} // refreshDisplay()
|
} // refreshDisplay()
|
||||||
|
|
||||||
void dp_drawPage(bool nextpage) {
|
void dp_drawPage(bool nextpage) {
|
||||||
@ -600,14 +580,8 @@ void dp_power(uint8_t screenon) {
|
|||||||
|
|
||||||
void dp_shutdown(void) {
|
void dp_shutdown(void) {
|
||||||
#if (HAS_DISPLAY) == 1
|
#if (HAS_DISPLAY) == 1
|
||||||
// block i2c bus access
|
obdPower(&ssoled, false);
|
||||||
if (!I2C_MUTEX_LOCK())
|
delay(DISPLAYREFRESH_MS / 1000 * 1.1);
|
||||||
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", _seconds());
|
|
||||||
else {
|
|
||||||
obdPower(&ssoled, false);
|
|
||||||
delay(DISPLAYREFRESH_MS / 1000 * 1.1);
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
}
|
|
||||||
#elif (HAS_DISPLAY) == 2
|
#elif (HAS_DISPLAY) == 2
|
||||||
// to come
|
// to come
|
||||||
#endif
|
#endif
|
||||||
|
123
src/i2c.cpp
123
src/i2c.cpp
@ -12,7 +12,7 @@ void i2c_init(void) {
|
|||||||
Wire.begin();
|
Wire.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
//void i2c_deinit(void) { Wire.end(); }
|
// void i2c_deinit(void) { Wire.end(); }
|
||||||
void i2c_deinit(void) { Wire.~TwoWire(); }
|
void i2c_deinit(void) { Wire.~TwoWire(); }
|
||||||
|
|
||||||
void i2c_scan(void) {
|
void i2c_scan(void) {
|
||||||
@ -49,90 +49,71 @@ void i2c_scan(void) {
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "Starting I2C bus scan...");
|
ESP_LOGI(TAG, "Starting I2C bus scan...");
|
||||||
|
|
||||||
// block i2c bus access
|
memset(&bbi2c, 0, sizeof(bbi2c));
|
||||||
if (I2C_MUTEX_LOCK()) {
|
bbi2c.bWire = 0;
|
||||||
|
bbi2c.iSDA = MY_DISPLAY_SDA;
|
||||||
|
bbi2c.iSCL = MY_DISPLAY_SCL;
|
||||||
|
I2CInit(&bbi2c, 100000L); // Scan at 100KHz low speed
|
||||||
|
delay(100); // allow devices to power up
|
||||||
|
|
||||||
memset(&bbi2c, 0, sizeof(bbi2c));
|
uint8_t map[16];
|
||||||
bbi2c.bWire = 0;
|
uint8_t i;
|
||||||
bbi2c.iSDA = MY_DISPLAY_SDA;
|
int iDevice, iCount;
|
||||||
bbi2c.iSCL = MY_DISPLAY_SCL;
|
|
||||||
I2CInit(&bbi2c, 100000L); // Scan at 100KHz low speed
|
|
||||||
delay(100); // allow devices to power up
|
|
||||||
|
|
||||||
uint8_t map[16];
|
I2CScan(&bbi2c, map); // get bitmap of connected I2C devices
|
||||||
uint8_t i;
|
if (map[0] == 0xfe) // something is wrong with the I2C bus
|
||||||
int iDevice, iCount;
|
{
|
||||||
|
ESP_LOGI(TAG, "I2C pins are not correct or the bus is being pulled low "
|
||||||
I2CScan(&bbi2c, map); // get bitmap of connected I2C devices
|
"by a bad device; unable to run scan");
|
||||||
if (map[0] == 0xfe) // something is wrong with the I2C bus
|
} else {
|
||||||
|
iCount = 0;
|
||||||
|
for (i = 1; i < 128; i++) // skip address 0 (general call address) since
|
||||||
|
// more than 1 device can respond
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "I2C pins are not correct or the bus is being pulled low "
|
if (map[i >> 3] & (1 << (i & 7))) // device found
|
||||||
"by a bad device; unable to run scan");
|
|
||||||
} else {
|
|
||||||
iCount = 0;
|
|
||||||
for (i = 1; i < 128; i++) // skip address 0 (general call address) since
|
|
||||||
// more than 1 device can respond
|
|
||||||
{
|
{
|
||||||
if (map[i >> 3] & (1 << (i & 7))) // device found
|
iCount++;
|
||||||
{
|
iDevice = I2CDiscoverDevice(&bbi2c, i);
|
||||||
iCount++;
|
ESP_LOGI(TAG, "Device found at 0x%X, type = %s", i,
|
||||||
iDevice = I2CDiscoverDevice(&bbi2c, i);
|
szNames[iDevice]); // show the device name as a string
|
||||||
ESP_LOGI(TAG, "Device found at 0x%X, type = %s", i,
|
}
|
||||||
szNames[iDevice]); // show the device name as a string
|
} // for i
|
||||||
}
|
ESP_LOGI(TAG, "%u I2C device(s) found", iCount);
|
||||||
} // for i
|
}
|
||||||
ESP_LOGI(TAG, "%u I2C device(s) found", iCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
} else
|
|
||||||
ESP_LOGE(TAG, "I2C bus busy - scan error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutexed functions for i2c r/w access
|
// functions for i2c r/w access, mutexing is done by Wire.cpp
|
||||||
int i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
int i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||||
if (I2C_MUTEX_LOCK()) {
|
|
||||||
|
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
Wire.beginTransmission(addr);
|
Wire.beginTransmission(addr);
|
||||||
Wire.write(reg);
|
Wire.write(reg);
|
||||||
Wire.endTransmission(false);
|
Wire.endTransmission(false);
|
||||||
uint8_t cnt = Wire.requestFrom(addr, (uint8_t)len, (uint8_t)1);
|
uint8_t cnt = Wire.requestFrom(addr, (uint8_t)len, (uint8_t)1);
|
||||||
if (!cnt)
|
if (!cnt)
|
||||||
|
ret = 0xFF;
|
||||||
|
uint16_t index = 0;
|
||||||
|
while (Wire.available()) {
|
||||||
|
if (index > len) {
|
||||||
ret = 0xFF;
|
ret = 0xFF;
|
||||||
uint16_t index = 0;
|
goto finish;
|
||||||
while (Wire.available()) {
|
|
||||||
if (index > len) {
|
|
||||||
ret = 0xFF;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
data[index++] = Wire.read();
|
|
||||||
}
|
}
|
||||||
|
data[index++] = Wire.read();
|
||||||
finish:
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", _seconds());
|
|
||||||
return 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
return ret ? ret : 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
int i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||||
if (I2C_MUTEX_LOCK()) {
|
|
||||||
|
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
Wire.beginTransmission(addr);
|
Wire.beginTransmission(addr);
|
||||||
Wire.write(reg);
|
Wire.write(reg);
|
||||||
for (uint16_t i = 0; i < len; i++) {
|
for (uint16_t i = 0; i < len; i++) {
|
||||||
Wire.write(data[i]);
|
Wire.write(data[i]);
|
||||||
}
|
|
||||||
ret = Wire.endTransmission();
|
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
|
||||||
return ret ? ret : 0xFF;
|
|
||||||
} else {
|
|
||||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", _seconds());
|
|
||||||
return 0xFF;
|
|
||||||
}
|
}
|
||||||
|
ret = Wire.endTransmission();
|
||||||
|
|
||||||
|
return ret ? ret : 0xFF;
|
||||||
}
|
}
|
||||||
|
19
src/main.cpp
19
src/main.cpp
@ -87,11 +87,6 @@ void setup() {
|
|||||||
|
|
||||||
char features[100] = "";
|
char features[100] = "";
|
||||||
|
|
||||||
// create some semaphores for syncing / mutexing tasks
|
|
||||||
I2Caccess = xSemaphoreCreateMutex(); // for access management of i2c bus
|
|
||||||
_ASSERT(I2Caccess != NULL);
|
|
||||||
I2C_MUTEX_UNLOCK();
|
|
||||||
|
|
||||||
// disable brownout detection
|
// disable brownout detection
|
||||||
#ifdef DISABLE_BROWNOUT
|
#ifdef DISABLE_BROWNOUT
|
||||||
// register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4
|
// register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4
|
||||||
@ -481,20 +476,8 @@ void setup() {
|
|||||||
|
|
||||||
// only if we have a timesource we do timesync
|
// only if we have a timesource we do timesync
|
||||||
#if ((HAS_LORA_TIME) || (HAS_GPS) || (HAS_RTC))
|
#if ((HAS_LORA_TIME) || (HAS_GPS) || (HAS_RTC))
|
||||||
|
time_init();
|
||||||
#if (defined HAS_IF482 || defined HAS_DCF77)
|
|
||||||
ESP_LOGI(TAG, "Starting Clock Controller...");
|
|
||||||
clock_init();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (HAS_LORA_TIME)
|
|
||||||
timesync_init(); // create loraserver time sync task
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting Timekeeper...");
|
|
||||||
_ASSERT(timepulse_init()); // starts pps and cyclic time sync
|
|
||||||
strcat_P(features, " TIME");
|
strcat_P(features, " TIME");
|
||||||
|
|
||||||
#endif // timesync
|
#endif // timesync
|
||||||
|
|
||||||
// show compiled features
|
// show compiled features
|
||||||
|
107
src/rtctime.cpp
107
src/rtctime.cpp
@ -10,88 +10,75 @@ RtcDS3231<TwoWire> Rtc(Wire); // RTC hardware i2c interface
|
|||||||
// initialize RTC
|
// initialize RTC
|
||||||
uint8_t rtc_init(void) {
|
uint8_t rtc_init(void) {
|
||||||
|
|
||||||
if (I2C_MUTEX_LOCK()) { // block i2c bus access
|
Wire.begin(HAS_RTC);
|
||||||
|
Rtc.Begin(MY_DISPLAY_SDA, MY_DISPLAY_SCL);
|
||||||
|
|
||||||
Wire.begin(HAS_RTC);
|
// configure RTC chip
|
||||||
Rtc.Begin(MY_DISPLAY_SDA, MY_DISPLAY_SCL);
|
Rtc.Enable32kHzPin(false);
|
||||||
|
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
||||||
|
|
||||||
// configure RTC chip
|
if (!Rtc.GetIsRunning()) {
|
||||||
Rtc.Enable32kHzPin(false);
|
ESP_LOGI(TAG, "RTC not running, starting now");
|
||||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
|
Rtc.SetIsRunning(true);
|
||||||
|
}
|
||||||
if (!Rtc.GetIsRunning()) {
|
|
||||||
ESP_LOGI(TAG, "RTC not running, starting now");
|
|
||||||
Rtc.SetIsRunning(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (TIME_SYNC_COMPILEDATE)
|
#if (TIME_SYNC_COMPILEDATE)
|
||||||
// initialize a blank RTC without battery backup with build time
|
// initialize a blank RTC without battery backup with build time
|
||||||
RtcDateTime tt = Rtc.GetDateTime();
|
RtcDateTime tt = Rtc.GetDateTime();
|
||||||
time_t t = tt.Epoch32Time(); // sec2000 -> epoch
|
time_t t = tt.Epoch32Time(); // sec2000 -> epoch
|
||||||
|
|
||||||
if (!Rtc.IsDateTimeValid() || !timeIsValid(t)) {
|
if (!Rtc.IsDateTimeValid() || !timeIsValid(t)) {
|
||||||
ESP_LOGW(TAG, "RTC has no recent time, setting to compiletime");
|
ESP_LOGW(TAG, "RTC has no recent time, setting to compiletime");
|
||||||
Rtc.SetDateTime(RtcDateTime(mkgmtime(compileTime()) -
|
Rtc.SetDateTime(RtcDateTime(mkgmtime(compileTime()) -
|
||||||
SECS_YR_2000)); // epoch -> sec2000
|
SECS_YR_2000)); // epoch -> sec2000
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
ESP_LOGI(TAG, "RTC initialized");
|
||||||
ESP_LOGI(TAG, "RTC initialized");
|
return 1; // success
|
||||||
return 1; // success
|
|
||||||
} else {
|
// failure
|
||||||
ESP_LOGE(TAG, "RTC initialization error, I2C bus busy");
|
// return 0
|
||||||
return 0; // failure
|
|
||||||
}
|
|
||||||
|
|
||||||
} // rtc_init()
|
} // rtc_init()
|
||||||
|
|
||||||
uint8_t set_rtctime(time_t t) { // t is sec epoch time
|
uint8_t set_rtctime(time_t t) { // t is sec epoch time
|
||||||
if (I2C_MUTEX_LOCK()) {
|
|
||||||
#ifdef RTC_INT // sync rtc 1Hz pulse on top of second
|
#ifdef RTC_INT // sync rtc 1Hz pulse on top of second
|
||||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); // off
|
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); // off
|
||||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); // start
|
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock); // start
|
||||||
#endif
|
#endif
|
||||||
Rtc.SetDateTime(RtcDateTime(t - SECS_YR_2000)); // epoch -> sec2000
|
Rtc.SetDateTime(RtcDateTime(t - SECS_YR_2000)); // epoch -> sec2000
|
||||||
I2C_MUTEX_UNLOCK();
|
ESP_LOGI(TAG, "RTC time synced");
|
||||||
ESP_LOGI(TAG, "RTC time synced");
|
return 1; // success
|
||||||
return 1; // success
|
|
||||||
} else {
|
// failure
|
||||||
ESP_LOGE(TAG, "RTC set time failure");
|
// return 0
|
||||||
return 0; // failure
|
|
||||||
}
|
|
||||||
} // set_rtctime()
|
} // set_rtctime()
|
||||||
|
|
||||||
time_t get_rtctime(uint16_t *msec) {
|
time_t get_rtctime(uint16_t *msec) {
|
||||||
|
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
*msec = 0;
|
*msec = 0;
|
||||||
if (I2C_MUTEX_LOCK()) {
|
if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) {
|
||||||
if (Rtc.IsDateTimeValid() && Rtc.GetIsRunning()) {
|
RtcDateTime tt = Rtc.GetDateTime();
|
||||||
RtcDateTime tt = Rtc.GetDateTime();
|
t = tt.Epoch32Time(); // sec2000 -> epoch
|
||||||
t = tt.Epoch32Time(); // sec2000 -> epoch
|
|
||||||
}
|
|
||||||
I2C_MUTEX_UNLOCK();
|
|
||||||
#ifdef RTC_INT
|
|
||||||
// adjust time to top of next second by waiting TimePulseTick to flip
|
|
||||||
bool lastTick = TimePulseTick;
|
|
||||||
while (TimePulseTick == lastTick) {
|
|
||||||
};
|
|
||||||
t++;
|
|
||||||
#endif
|
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "RTC get time failure");
|
|
||||||
return 0; // failure
|
|
||||||
}
|
}
|
||||||
|
#ifdef RTC_INT
|
||||||
|
// adjust time to top of next second by waiting TimePulseTick to flip
|
||||||
|
bool lastTick = TimePulseTick;
|
||||||
|
while (TimePulseTick == lastTick) {
|
||||||
|
};
|
||||||
|
t++;
|
||||||
|
#endif
|
||||||
|
return t;
|
||||||
|
|
||||||
} // get_rtctime()
|
} // get_rtctime()
|
||||||
|
|
||||||
float get_rtctemp(void) {
|
float get_rtctemp(void) {
|
||||||
if (I2C_MUTEX_LOCK()) {
|
RtcTemperature temp = Rtc.GetTemperature();
|
||||||
RtcTemperature temp = Rtc.GetTemperature();
|
return temp.AsFloatDegC();
|
||||||
I2C_MUTEX_UNLOCK();
|
|
||||||
return temp.AsFloatDegC();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} // get_rtctemp()
|
} // get_rtctemp()
|
||||||
|
|
||||||
#endif // HAS_RTC
|
#endif // HAS_RTC
|
@ -31,6 +31,40 @@ Ticker timesyncer;
|
|||||||
|
|
||||||
void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
|
void setTimeSyncIRQ() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
|
||||||
|
|
||||||
|
// interrupt service routine triggered by GPS PPS
|
||||||
|
void IRAM_ATTR GPSIRQ(void) {
|
||||||
|
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
// take timestamp
|
||||||
|
lastPPS = millis(); // last time of pps
|
||||||
|
|
||||||
|
// yield only if we should
|
||||||
|
if (xHigherPriorityTaskWoken)
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
|
|
||||||
|
// interrupt service routine triggered by esp32 hardware timer
|
||||||
|
void IRAM_ATTR CLOCKIRQ(void) {
|
||||||
|
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
// advance wall clock, if we have
|
||||||
|
#if (defined HAS_IF482 || defined HAS_DCF77)
|
||||||
|
xTaskNotifyFromISR(ClockTask, uint32_t(time(NULL)), eSetBits,
|
||||||
|
&xHigherPriorityTaskWoken);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// flip time pulse ticker, if needed
|
||||||
|
#ifdef HAS_DISPLAY
|
||||||
|
TimePulseTick = !TimePulseTick; // flip global variable pulse ticker
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// yield only if we should
|
||||||
|
if (xHigherPriorityTaskWoken)
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
|
|
||||||
void calibrateTime(void) {
|
void calibrateTime(void) {
|
||||||
|
|
||||||
// kick off asynchronous lora timesync if we have
|
// kick off asynchronous lora timesync if we have
|
||||||
@ -63,8 +97,7 @@ void calibrateTime(void) {
|
|||||||
} // calibrateTime()
|
} // calibrateTime()
|
||||||
|
|
||||||
// set system time (UTC), calibrate RTC and RTC_INT pps
|
// set system time (UTC), calibrate RTC and RTC_INT pps
|
||||||
bool setMyTime(uint32_t t_sec, uint16_t t_msec,
|
bool setMyTime(uint32_t t_sec, uint16_t t_msec, timesource_t mytimesource) {
|
||||||
timesource_t mytimesource) {
|
|
||||||
|
|
||||||
struct timeval tv = {0};
|
struct timeval tv = {0};
|
||||||
|
|
||||||
@ -126,7 +159,7 @@ bool setMyTime(uint32_t t_sec, uint16_t t_msec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// helper function to setup a pulse per second for time synchronisation
|
// helper function to setup a pulse per second for time synchronisation
|
||||||
uint8_t timepulse_init() {
|
void timepulse_init(void) {
|
||||||
|
|
||||||
// set esp-idf API sntp sync mode
|
// set esp-idf API sntp sync mode
|
||||||
// sntp_init();
|
// sntp_init();
|
||||||
@ -141,22 +174,12 @@ uint8_t timepulse_init() {
|
|||||||
|
|
||||||
// if we have, use pulse from on board RTC chip as time base for calendar time
|
// if we have, use pulse from on board RTC chip as time base for calendar time
|
||||||
#if defined RTC_INT
|
#if defined RTC_INT
|
||||||
|
|
||||||
// setup external rtc 1Hz clock pulse
|
// setup external rtc 1Hz clock pulse
|
||||||
if (I2C_MUTEX_LOCK()) {
|
Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz);
|
||||||
Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz);
|
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock);
|
||||||
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock);
|
pinMode(RTC_INT, INPUT_PULLUP);
|
||||||
I2C_MUTEX_UNLOCK();
|
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
|
||||||
pinMode(RTC_INT, INPUT_PULLUP);
|
ESP_LOGI(TAG, "Timepulse: external (RTC)");
|
||||||
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
|
|
||||||
ESP_LOGI(TAG, "Timepulse: external (RTC)");
|
|
||||||
return 1; // success
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "RTC initialization error, I2C bus busy");
|
|
||||||
return 0; // failure
|
|
||||||
}
|
|
||||||
return 1; // success
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// use ESP32 hardware timer as time base for calendar time
|
// use ESP32 hardware timer as time base for calendar time
|
||||||
ppsIRQ = 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
|
||||||
@ -164,53 +187,17 @@ uint8_t timepulse_init() {
|
|||||||
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, false);
|
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, false);
|
||||||
timerAlarmEnable(ppsIRQ);
|
timerAlarmEnable(ppsIRQ);
|
||||||
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
|
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
|
||||||
return 1; // success
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// start cyclic time sync
|
|
||||||
timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
|
|
||||||
|
|
||||||
// get time if we don't have one
|
// get time if we don't have one
|
||||||
if (timeSource != _set)
|
if (timeSource != _set)
|
||||||
setTimeSyncIRQ(); // init systime by RTC or GPS or LORA
|
setTimeSyncIRQ(); // init systime by RTC or GPS or LORA
|
||||||
|
|
||||||
|
// start cyclic time sync
|
||||||
|
timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
|
||||||
|
|
||||||
} // timepulse_init
|
} // timepulse_init
|
||||||
|
|
||||||
// interrupt service routine triggered by GPS PPS
|
|
||||||
void IRAM_ATTR GPSIRQ(void) {
|
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
|
|
||||||
// take timestamp
|
|
||||||
lastPPS = millis(); // last time of pps
|
|
||||||
|
|
||||||
// yield only if we should
|
|
||||||
if (xHigherPriorityTaskWoken)
|
|
||||||
portYIELD_FROM_ISR();
|
|
||||||
}
|
|
||||||
|
|
||||||
// interrupt service routine triggered by esp32 hardware timer
|
|
||||||
void IRAM_ATTR CLOCKIRQ(void) {
|
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
|
|
||||||
// advance wall clock, if we have
|
|
||||||
#if (defined HAS_IF482 || defined HAS_DCF77)
|
|
||||||
xTaskNotifyFromISR(ClockTask, uint32_t(time(NULL)), eSetBits,
|
|
||||||
&xHigherPriorityTaskWoken);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// flip time pulse ticker, if needed
|
|
||||||
#ifdef HAS_DISPLAY
|
|
||||||
TimePulseTick = !TimePulseTick; // flip global variable pulse ticker
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// yield only if we should
|
|
||||||
if (xHigherPriorityTaskWoken)
|
|
||||||
portYIELD_FROM_ISR();
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function to check plausibility of a given epoch time
|
// helper function to check plausibility of a given epoch time
|
||||||
bool timeIsValid(time_t const t) {
|
bool timeIsValid(time_t const t) {
|
||||||
// is t a time in the past? we use compile time to guess
|
// is t a time in the past? we use compile time to guess
|
||||||
@ -231,26 +218,6 @@ TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
|
|||||||
return round(txTime);
|
return round(txTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_init(void) {
|
|
||||||
|
|
||||||
// setup clock output interface
|
|
||||||
#ifdef HAS_IF482
|
|
||||||
IF482.begin(HAS_IF482);
|
|
||||||
#elif defined HAS_DCF77
|
|
||||||
pinMode(HAS_DCF77, OUTPUT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(clock_loop, // task function
|
|
||||||
"clockloop", // name of task
|
|
||||||
3072, // stack size of task
|
|
||||||
(void *)1, // task parameter
|
|
||||||
6, // priority of the task
|
|
||||||
&ClockTask, // task handle
|
|
||||||
1); // CPU core
|
|
||||||
|
|
||||||
_ASSERT(ClockTask != NULL); // has clock task started?
|
|
||||||
} // clock_init
|
|
||||||
|
|
||||||
void clock_loop(void *taskparameter) { // ClockTask
|
void clock_loop(void *taskparameter) { // ClockTask
|
||||||
|
|
||||||
uint32_t current_time = 0, previous_time = 0;
|
uint32_t current_time = 0, previous_time = 0;
|
||||||
@ -333,6 +300,26 @@ void clock_loop(void *taskparameter) { // ClockTask
|
|||||||
} // for
|
} // for
|
||||||
} // clock_loop()
|
} // clock_loop()
|
||||||
|
|
||||||
|
void clock_init(void) {
|
||||||
|
|
||||||
|
// setup clock output interface
|
||||||
|
#ifdef HAS_IF482
|
||||||
|
IF482.begin(HAS_IF482);
|
||||||
|
#elif defined HAS_DCF77
|
||||||
|
pinMode(HAS_DCF77, OUTPUT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(clock_loop, // task function
|
||||||
|
"clockloop", // name of task
|
||||||
|
3072, // stack size of task
|
||||||
|
(void *)1, // task parameter
|
||||||
|
6, // priority of the task
|
||||||
|
&ClockTask, // task handle
|
||||||
|
1); // CPU core
|
||||||
|
|
||||||
|
_ASSERT(ClockTask != NULL); // has clock task started?
|
||||||
|
} // clock_init
|
||||||
|
|
||||||
// we use compile date to create a time_t reference "in the past"
|
// we use compile date to create a time_t reference "in the past"
|
||||||
time_t compileTime(void) {
|
time_t compileTime(void) {
|
||||||
|
|
||||||
@ -391,4 +378,16 @@ time_t mkgmtime(const struct tm *ptm) {
|
|||||||
secs += ptm->tm_min * SecondsPerMinute;
|
secs += ptm->tm_min * SecondsPerMinute;
|
||||||
secs += ptm->tm_sec;
|
secs += ptm->tm_sec;
|
||||||
return secs;
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void time_init(void) {
|
||||||
|
#if (HAS_LORA_TIME)
|
||||||
|
timesync_init(); // create loraserver time sync task
|
||||||
|
#endif
|
||||||
|
ESP_LOGI(TAG, "Starting time pulse...");
|
||||||
|
timepulse_init(); // starts pps and cyclic time sync
|
||||||
|
#if (defined HAS_IF482 || defined HAS_DCF77)
|
||||||
|
ESP_LOGI(TAG, "Starting clock controller...");
|
||||||
|
clock_init();
|
||||||
|
#endif
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user