Toki 1st experiment
This commit is contained in:
parent
9b796531b2
commit
b455f432d5
6
tools/WLED_ESP32_4MB_1MB_FS.csv
Normal file
6
tools/WLED_ESP32_4MB_1MB_FS.csv
Normal file
@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x17B000,
|
||||
app1, app, ota_1, 0x18B000,0x17B000,
|
||||
spiffs, data, spiffs, 0x306000,0x0FA000,
|
|
@ -41,18 +41,14 @@ class ElekstubeIPSUsermod : public Usermod {
|
||||
tfts.begin();
|
||||
tfts.fillScreen(TFT_BLACK);
|
||||
tfts.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tfts.setCursor(0, 0, 2);
|
||||
tfts.setCursor(0, 100, 2);
|
||||
tfts.println("<STARTUP>");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (lastTime == 0) {
|
||||
tfts.fillScreen(TFT_BLACK);
|
||||
updateClockDisplay(TFTs::force);
|
||||
}
|
||||
if (millis() - lastTime > 100) {
|
||||
if (toki.isTick()) {
|
||||
updateLocalTime();
|
||||
updateClockDisplay();
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,20 +183,30 @@ bool checkNTPResponse()
|
||||
{
|
||||
int cb = ntpUdp.parsePacket();
|
||||
if (cb) {
|
||||
uint32_t ntpPacketReceivedTime = millis();
|
||||
DEBUG_PRINT(F("NTP recv, l="));
|
||||
DEBUG_PRINTLN(cb);
|
||||
byte pbuf[NTP_PACKET_SIZE];
|
||||
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
|
||||
unsigned long highWord = word(pbuf[40], pbuf[41]);
|
||||
unsigned long lowWord = word(pbuf[42], pbuf[43]);
|
||||
if (highWord == 0 && lowWord == 0) return false;
|
||||
|
||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
||||
Toki::Time arrived = toki.fromNTP(pbuf + 32);
|
||||
Toki::Time departed = toki.fromNTP(pbuf + 40);
|
||||
//basic half roundtrip estimation
|
||||
uint32_t offset = (ntpPacketReceivedTime - ntpPacketSentTime - toki.msDifference(arrived, departed)) >> 1;
|
||||
offset += millis() - ntpPacketReceivedTime +1;
|
||||
toki.adjust(departed, offset);
|
||||
toki.setTime(departed);
|
||||
Serial.print("Roundtrip: ");
|
||||
Serial.println(ntpPacketReceivedTime - ntpPacketSentTime);
|
||||
Serial.print("Offset: ");
|
||||
Serial.println(offset);
|
||||
Serial.print("Time: ");
|
||||
toki.printTime(toki.getTime());
|
||||
|
||||
DEBUG_PRINT(F("Unix time = "));
|
||||
unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
|
||||
setTime(epoch);
|
||||
uint32_t epoch = toki.second();
|
||||
if (epoch == 0) return false;
|
||||
setTime(epoch); //legacy
|
||||
DEBUG_PRINTLN(epoch);
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
// if time changed re-calculate sunrise/sunset
|
||||
@ -210,7 +220,7 @@ bool checkNTPResponse()
|
||||
void updateLocalTime()
|
||||
{
|
||||
if (currentTimezone != tzCurrent) updateTimezone();
|
||||
unsigned long tmc = now()+ utcOffsetSecs;
|
||||
unsigned long tmc = toki.second()+ utcOffsetSecs;
|
||||
localTime = tz->toLocal(tmc);
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,16 @@ void initCronixie()
|
||||
|
||||
void handleOverlays()
|
||||
{
|
||||
if (millis() - overlayRefreshedTime > overlayRefreshMs)
|
||||
if (toki.isTick())
|
||||
{
|
||||
initCronixie();
|
||||
updateLocalTime();
|
||||
checkTimers();
|
||||
checkCountdown();
|
||||
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
|
||||
if (overlayCurrent == 3) {
|
||||
_overlayCronixie();//Diamex cronixie clock kit
|
||||
strip.trigger();
|
||||
}
|
||||
overlayRefreshedTime = millis();
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
static tmElements_t tm; // a cache of time elements
|
||||
static time_t cacheTime; // the time the cache was updated
|
||||
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
|
||||
|
||||
void refreshCache(time_t t) {
|
||||
if (t != cacheTime) {
|
||||
@ -234,18 +233,9 @@ time_t makeTime(tmElements_t &tm){
|
||||
/*=====================================================*/
|
||||
/* Low level system time functions */
|
||||
|
||||
static uint32_t sysTime = 0;
|
||||
static uint32_t sysTime = 0; //seconds
|
||||
static uint16_t sysMillis = 0;
|
||||
static uint32_t prevMillis = 0;
|
||||
static uint32_t nextSyncTime = 0;
|
||||
static timeStatus_t Status = timeNotSet;
|
||||
|
||||
getExternalTime getTimePtr; // pointer to external sync function
|
||||
//setExternalTime setTimePtr; // not used in this version
|
||||
|
||||
#ifdef TIME_DRIFT_INFO // define this to get drift data
|
||||
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
|
||||
#endif
|
||||
|
||||
|
||||
time_t now() {
|
||||
// calculate number of seconds passed since last call to now()
|
||||
@ -253,33 +243,18 @@ time_t now() {
|
||||
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
|
||||
sysTime++;
|
||||
prevMillis += 1000;
|
||||
#ifdef TIME_DRIFT_INFO
|
||||
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
|
||||
#endif
|
||||
}
|
||||
if (nextSyncTime <= sysTime) {
|
||||
if (getTimePtr != 0) {
|
||||
time_t t = getTimePtr();
|
||||
if (t != 0) {
|
||||
setTime(t);
|
||||
} else {
|
||||
nextSyncTime = sysTime + syncInterval;
|
||||
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (time_t)sysTime;
|
||||
}
|
||||
|
||||
void setTime(time_t t) {
|
||||
#ifdef TIME_DRIFT_INFO
|
||||
if(sysUnsyncedTime == 0)
|
||||
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
|
||||
#endif
|
||||
uint16_t millisecond() { // the millisecond (0-999) now
|
||||
return (sysMillis - millis()) % 1000;
|
||||
}
|
||||
|
||||
sysTime = (uint32_t)t;
|
||||
nextSyncTime = (uint32_t)t + syncInterval;
|
||||
Status = timeSet;
|
||||
void setTime(time_t t, uint16_t ms) {
|
||||
sysTime = (uint32_t)t;
|
||||
sysMillis = ms;
|
||||
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
|
||||
}
|
||||
|
||||
@ -299,27 +274,10 @@ time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
||||
return makeTime(tm);
|
||||
}
|
||||
|
||||
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
||||
setTime(getUnixTime(hr,min,sec,dy,mnth,yr));
|
||||
void setTime(int hr,int min,int sec,int dy, int mnth, int yr, uint16_t ms){
|
||||
setTime(getUnixTime(hr,min,sec,dy,mnth,yr), ms);
|
||||
}
|
||||
|
||||
void adjustTime(long adjustment) {
|
||||
sysTime += adjustment;
|
||||
}
|
||||
|
||||
// indicates if time has been set and recently synchronized
|
||||
timeStatus_t timeStatus() {
|
||||
now(); // required to actually update the status
|
||||
return Status;
|
||||
}
|
||||
|
||||
void setSyncProvider( getExternalTime getTimeFunction){
|
||||
getTimePtr = getTimeFunction;
|
||||
nextSyncTime = sysTime;
|
||||
now(); // this will sync the clock
|
||||
}
|
||||
|
||||
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
|
||||
syncInterval = (uint32_t)interval;
|
||||
nextSyncTime = sysTime + syncInterval;
|
||||
}
|
||||
}
|
@ -31,8 +31,6 @@ typedef unsigned long time_t;
|
||||
// but at least this hack lets us define C++ functions as intended. Hopefully
|
||||
// nothing too terrible will result from overriding the C library header?!
|
||||
extern "C++" {
|
||||
typedef enum {timeNotSet, timeNeedsSync, timeSet
|
||||
} timeStatus_t ;
|
||||
|
||||
typedef enum {
|
||||
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
||||
@ -116,10 +114,11 @@ int month(); // the month now (Jan is month 1)
|
||||
int month(time_t t); // the month for the given time
|
||||
int year(); // the full four digit year: (2009, 2010 etc)
|
||||
int year(time_t t); // the year for the given time
|
||||
uint16_t millisecond(); // the millisecond now
|
||||
|
||||
time_t now(); // return the current time as seconds since Jan 1 1970
|
||||
void setTime(time_t t);
|
||||
void setTime(int hr,int min,int sec,int day, int month, int yr);
|
||||
void setTime(time_t t, uint16_t ms = 0);
|
||||
void setTime(int hr,int min,int sec,int day, int month, int yr, uint16_t ms = 0);
|
||||
time_t getUnixTime(int hr,int min,int sec,int day, int month, int yr); //added by Aircoookie to get epoch time
|
||||
void adjustTime(long adjustment);
|
||||
|
||||
@ -129,13 +128,8 @@ char* monthStr(uint8_t month);
|
||||
char* dayStr(uint8_t day);
|
||||
char* monthShortStr(uint8_t month);
|
||||
char* dayShortStr(uint8_t day);
|
||||
|
||||
/* time sync functions */
|
||||
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
|
||||
void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
|
||||
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
|
||||
|
||||
/* low level functions to convert to and from system time */
|
||||
/* low level functions to convert to and from system time */
|
||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
|
||||
|
||||
|
128
wled00/src/dependencies/toki/Toki.h
Normal file
128
wled00/src/dependencies/toki/Toki.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Toki.h - Minimal millisecond accurate timekeeping.
|
||||
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2021 Christian Schwinne
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define YEARS_70 2208988800UL
|
||||
|
||||
//3:13 24.05.2012 ==> 2021-4-29, 06:41:37.
|
||||
|
||||
class Toki {
|
||||
typedef enum {
|
||||
inactive, marked, active
|
||||
} TickT;
|
||||
|
||||
public:
|
||||
typedef struct {
|
||||
uint32_t sec;
|
||||
uint16_t ms;
|
||||
} Time;
|
||||
|
||||
private:
|
||||
uint32_t fullSecondMillis = 0;
|
||||
uint32_t unix = 0;
|
||||
TickT tick = TickT::inactive;
|
||||
|
||||
public:
|
||||
void setTime(Time t) {
|
||||
fullSecondMillis = millis() - t.ms;
|
||||
unix = t.sec;
|
||||
}
|
||||
|
||||
void setTime(uint32_t sec, uint16_t ms) {
|
||||
Time t = {sec, ms};
|
||||
setTime(t);
|
||||
}
|
||||
|
||||
Time fromNTP(byte *timestamp) { //ntp timestamp is 8 bytes, 4 bytes second and 4 bytes sub-second fraction
|
||||
unsigned long highWord = word(timestamp[0], timestamp[1]);
|
||||
unsigned long lowWord = word(timestamp[2], timestamp[3]);
|
||||
|
||||
unsigned long unix = highWord << 16 | lowWord;
|
||||
if (!unix) return {0,0};
|
||||
unix -= YEARS_70; //NTP begins 1900, Unix 1970
|
||||
|
||||
unsigned long frac = word(timestamp[5], timestamp[6]); //65536ths of a second
|
||||
frac = (frac*1000) >> 16; //convert to ms
|
||||
return {unix, (uint16_t)frac};
|
||||
}
|
||||
|
||||
uint16_t millisecond() {
|
||||
uint32_t ms = millis() - fullSecondMillis;
|
||||
while (ms > 999) {
|
||||
ms -= 1000;
|
||||
fullSecondMillis += 1000;
|
||||
unix++;
|
||||
if (tick == TickT::inactive) tick = TickT::marked; //marked, will be active on next loop
|
||||
}
|
||||
return ms;
|
||||
}
|
||||
|
||||
uint32_t second() {
|
||||
millisecond();
|
||||
return unix;
|
||||
}
|
||||
|
||||
uint32_t msDifference(Time &t0, Time &t1) {
|
||||
bool t1BiggerSec = (t1.sec > t0.sec);
|
||||
uint32_t secDiff = (t1BiggerSec) ? t1.sec - t0.sec : t0.sec - t1.sec;
|
||||
uint32_t t0ms = t0.ms, t1ms = t1.ms;
|
||||
if (t1BiggerSec) t1ms += secDiff;
|
||||
else t0ms += secDiff;
|
||||
uint32_t msDiff = (t1ms > t0ms) ? t1ms - t0ms : t0ms - t1ms;
|
||||
return msDiff;
|
||||
}
|
||||
|
||||
void adjust(Time&t, int32_t offset) {
|
||||
int32_t secs = offset /1000;
|
||||
int32_t ms = offset - secs*1000;
|
||||
t.sec += offset /1000;
|
||||
int32_t nms = t.ms + ms;
|
||||
if (nms > 1000) {nms -= 1000; t.sec++;}
|
||||
if (nms < 0) {nms += 1000; t.sec--;}
|
||||
t.ms += nms;
|
||||
}
|
||||
|
||||
Time getTime() {
|
||||
Time t;
|
||||
t.ms = millisecond();
|
||||
t.sec = unix;
|
||||
return t;
|
||||
}
|
||||
|
||||
void setTick() {
|
||||
if (tick == TickT::marked) tick = TickT::active;
|
||||
}
|
||||
|
||||
void resetTick() {
|
||||
tick = TickT::inactive;
|
||||
}
|
||||
|
||||
bool isTick() {
|
||||
return (tick == TickT::active);
|
||||
}
|
||||
|
||||
void printTime(const Time& t) {
|
||||
Serial.printf_P(PSTR("%u,%03u\n"),t.sec,t.ms);
|
||||
}
|
||||
};
|
@ -177,6 +177,8 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
|
||||
void WLED::loop()
|
||||
{
|
||||
toki.millisecond();
|
||||
toki.setTick();
|
||||
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
@ -287,6 +289,7 @@ void WLED::loop()
|
||||
}
|
||||
loops++;
|
||||
#endif // WLED_DEBUG
|
||||
toki.resetTick();
|
||||
}
|
||||
|
||||
void WLED::setup()
|
||||
|
@ -90,6 +90,7 @@
|
||||
#include <SPIFFSEditor.h>
|
||||
#include "src/dependencies/time/TimeLib.h"
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
#include "src/dependencies/toki/Toki.h"
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
#define ESPALEXA_ASYNC
|
||||
@ -516,6 +517,7 @@ WLED_GLOBAL float longitude _INIT(0.0);
|
||||
WLED_GLOBAL float latitude _INIT(0.0);
|
||||
WLED_GLOBAL time_t sunrise _INIT(0);
|
||||
WLED_GLOBAL time_t sunset _INIT(0);
|
||||
WLED_GLOBAL Toki toki _INIT(Toki());
|
||||
|
||||
// Temp buffer
|
||||
WLED_GLOBAL char* obuf;
|
||||
|
Loading…
Reference in New Issue
Block a user