1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/mirrors_trending-WLED

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Toki.h 5.4 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
cschwinne Отправлено 4 лет назад bfc7f56
/*
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
#define TOKI_NO_MS_ACCURACY 1000
//Time source. Sub-100 is second accuracy, higher ms accuracy. Higher value generally means more accurate
#define TOKI_TS_NONE 0 //unsynced (e.g. just after boot)
#define TOKI_TS_UDP 5 //synced via UDP from an instance whose time source is unsynced
#define TOKI_TS_BAD 10 //synced from a time source less than about +- 2s accurate
#define TOKI_TS_UDP_SEC 20 //synced via UDP from an instance whose time source is set from RTC/JSON
#define TOKI_TS_SEC 40 //general second-accurate time source
#define TOKI_TS_RTC 60 //second-accurate real time clock
#define TOKI_TS_JSON 70 //synced second-accurate from a client via JSON-API
#define TOKI_TS_UDP_NTP 110 //synced via UDP from an instance whose time source is NTP
#define TOKI_TS_MS 120 //general better-than-second accuracy time source
#define TOKI_TS_NTP 150 //NTP time, simple round trip estimation. Depending on network, mostly +- 50ms accurate
#define TOKI_TS_NTP_P 170 //NTP time with multi-step sync, higher accuracy. Not implemented in WLED
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;
uint8_t timeSrc = TOKI_TS_NONE;
public:
void setTime(Time t, uint8_t timeSource = TOKI_TS_MS) {
fullSecondMillis = millis() - t.ms;
unix = t.sec;
timeSrc = timeSource;
}
void setTime(uint32_t sec, uint16_t ms=TOKI_NO_MS_ACCURACY, uint8_t timeSource = TOKI_TS_MS) {
if (ms >= TOKI_NO_MS_ACCURACY) {
ms = millisecond(); //just keep current ms if not provided
if (timeSource > 99) timeSource = TOKI_TS_SEC; //lies
}
Time t = {sec, ms};
setTime(t, timeSource);
}
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[4], timestamp[5]); //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;
}
//gets the absolute difference between two timestamps in milliseconds
uint32_t msDifference(const Time &t0, const 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*1000;
else t0ms += secDiff*1000;
uint32_t msDiff = (t1ms > t0ms) ? t1ms - t0ms : t0ms - t1ms;
return msDiff;
}
//return true if t1 is later than t0
bool isLater(const Time &t0, const Time &t1) {
if (t1.sec > t0.sec) return true;
if (t1.sec < t0.sec) return false;
if (t1.ms > t0.ms) return true;
return false;
}
void adjust(Time&t, int32_t offset) {
int32_t secs = offset /1000;
int32_t ms = offset - secs*1000;
t.sec += secs;
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;
}
uint8_t getTimeSource() {
return timeSrc;
}
void setTick() {
if (tick == TickT::marked) tick = TickT::active;
}
void resetTick() {
if (tick == TickT::active) 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);
}
};

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/mirrors_trending-WLED.git
git@gitlife.ru:oschina-mirror/mirrors_trending-WLED.git
oschina-mirror
mirrors_trending-WLED
mirrors_trending-WLED
v0.13.3