Accurate UDP sync for NTP enabled instances
This commit is contained in:
parent
7cbc9d21b5
commit
bfc7f56c4d
@ -1,6 +1,7 @@
|
|||||||
#ifndef TFTS_H
|
#ifndef TFTS_H
|
||||||
#define TFTS_H
|
#define TFTS_H
|
||||||
|
|
||||||
|
#include "wled.h"
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
||||||
#include <TFT_eSPI.h>
|
#include <TFT_eSPI.h>
|
||||||
@ -92,9 +93,10 @@ private:
|
|||||||
uint16_t padding = (4 - ((w * 3) & 3)) & 3;
|
uint16_t padding = (4 - ((w * 3) & 3)) & 3;
|
||||||
uint8_t lineBuffer[w * 3 + padding];
|
uint8_t lineBuffer[w * 3 + padding];
|
||||||
|
|
||||||
|
uint8_t serviceStrip = (!realtimeMode || realtimeOverride) ? 7 : 0;
|
||||||
// row is decremented as the BMP image is drawn bottom up
|
// row is decremented as the BMP image is drawn bottom up
|
||||||
for (row = h-1; row >= 0; row--) {
|
for (row = h-1; row >= 0; row--) {
|
||||||
if (row & 0b00000111 == 7) strip.service(); //still refresh backlight to mitigate stutter every few rows
|
if ((row & 0b00000111) == serviceStrip) strip.service(); //still refresh backlight to mitigate stutter every few rows
|
||||||
bmpFS.read(lineBuffer, sizeof(lineBuffer));
|
bmpFS.read(lineBuffer, sizeof(lineBuffer));
|
||||||
uint8_t* bptr = lineBuffer;
|
uint8_t* bptr = lineBuffer;
|
||||||
|
|
||||||
|
@ -42,30 +42,24 @@ uint16_t WS2812FX::mode_static(void) {
|
|||||||
* Blink/strobe function
|
* Blink/strobe function
|
||||||
* Alternate between color1 and color2
|
* Alternate between color1 and color2
|
||||||
* if(strobe == true) then create a strobe effect
|
* if(strobe == true) then create a strobe effect
|
||||||
* NOTE: Maybe re-rework without timer
|
|
||||||
*/
|
*/
|
||||||
uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) {
|
uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) {
|
||||||
uint16_t stateTime = SEGENV.aux1;
|
|
||||||
uint32_t cycleTime = (255 - SEGMENT.speed)*20;
|
uint32_t cycleTime = (255 - SEGMENT.speed)*20;
|
||||||
uint32_t onTime = 0;
|
uint32_t onTime = FRAMETIME;
|
||||||
uint32_t offTime = cycleTime;
|
if (!strobe) onTime += ((cycleTime * SEGMENT.intensity) >> 8);
|
||||||
|
cycleTime += FRAMETIME*2;
|
||||||
if (!strobe) {
|
uint32_t it = now / cycleTime;
|
||||||
onTime = (cycleTime * SEGMENT.intensity) >> 8;
|
uint32_t rem = now % cycleTime;
|
||||||
offTime = cycleTime - onTime;
|
|
||||||
|
bool on = false;
|
||||||
|
if (it != SEGENV.step //new iteration, force on state for one frame, even if set time is too brief
|
||||||
|
|| rem <= onTime) {
|
||||||
|
on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
stateTime = ((SEGENV.aux0 & 1) == 0) ? onTime : offTime;
|
SEGENV.step = it; //save previous iteration
|
||||||
stateTime += 20;
|
|
||||||
|
|
||||||
if (now - SEGENV.step > stateTime)
|
|
||||||
{
|
|
||||||
SEGENV.aux0++;
|
|
||||||
SEGENV.aux1 = stateTime;
|
|
||||||
SEGENV.step = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t color = ((SEGENV.aux0 & 1) == 0) ? color1 : color2;
|
uint32_t color = on ? color1 : color2;
|
||||||
if (color == color1 && do_palette)
|
if (color == color1 && do_palette)
|
||||||
{
|
{
|
||||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
#define SEGENV _segment_runtimes[_segment_index]
|
#define SEGENV _segment_runtimes[_segment_index]
|
||||||
#define SEGLEN _virtualSegmentLength
|
#define SEGLEN _virtualSegmentLength
|
||||||
#define SEGACT SEGMENT.stop
|
#define SEGACT SEGMENT.stop
|
||||||
#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGLEN
|
#define SPEED_FORMULA_L 5U + (50U*(255U - SEGMENT.speed))/SEGLEN
|
||||||
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
||||||
|
|
||||||
// some common colors
|
// some common colors
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* Acquires time from NTP server
|
* Acquires time from NTP server
|
||||||
*/
|
*/
|
||||||
//#define WLED_DEBUG_NTP
|
//#define WLED_DEBUG_NTP
|
||||||
|
#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day
|
||||||
|
|
||||||
Timezone* tz;
|
Timezone* tz;
|
||||||
|
|
||||||
@ -143,6 +144,10 @@ void handleTime() {
|
|||||||
|
|
||||||
if (toki.isTick()) //true only in the first loop after a new second started
|
if (toki.isTick()) //true only in the first loop after a new second started
|
||||||
{
|
{
|
||||||
|
#ifdef WLED_DEBUG_NTP
|
||||||
|
Serial.print(F("TICK! "));
|
||||||
|
toki.printTime(toki.getTime());
|
||||||
|
#endif
|
||||||
updateLocalTime();
|
updateLocalTime();
|
||||||
checkTimers();
|
checkTimers();
|
||||||
checkCountdown();
|
checkCountdown();
|
||||||
@ -152,7 +157,7 @@ void handleTime() {
|
|||||||
|
|
||||||
void handleNetworkTime()
|
void handleNetworkTime()
|
||||||
{
|
{
|
||||||
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WLED_CONNECTED)
|
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000*NTP_SYNC_INTERVAL) && WLED_CONNECTED)
|
||||||
{
|
{
|
||||||
if (millis() - ntpPacketSentTime > 10000)
|
if (millis() - ntpPacketSentTime > 10000)
|
||||||
{
|
{
|
||||||
|
@ -103,16 +103,25 @@ class Toki {
|
|||||||
return unix;
|
return unix;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t msDifference(Time &t0, Time &t1) {
|
//gets the absolute difference between two timestamps in milliseconds
|
||||||
|
uint32_t msDifference(const Time &t0, const Time &t1) {
|
||||||
bool t1BiggerSec = (t1.sec > t0.sec);
|
bool t1BiggerSec = (t1.sec > t0.sec);
|
||||||
uint32_t secDiff = (t1BiggerSec) ? t1.sec - t0.sec : t0.sec - t1.sec;
|
uint32_t secDiff = (t1BiggerSec) ? t1.sec - t0.sec : t0.sec - t1.sec;
|
||||||
uint32_t t0ms = t0.ms, t1ms = t1.ms;
|
uint32_t t0ms = t0.ms, t1ms = t1.ms;
|
||||||
if (t1BiggerSec) t1ms += secDiff;
|
if (t1BiggerSec) t1ms += secDiff*1000;
|
||||||
else t0ms += secDiff;
|
else t0ms += secDiff*1000;
|
||||||
uint32_t msDiff = (t1ms > t0ms) ? t1ms - t0ms : t0ms - t1ms;
|
uint32_t msDiff = (t1ms > t0ms) ? t1ms - t0ms : t0ms - t1ms;
|
||||||
return msDiff;
|
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) {
|
void adjust(Time&t, int32_t offset) {
|
||||||
int32_t secs = offset /1000;
|
int32_t secs = offset /1000;
|
||||||
int32_t ms = offset - secs*1000;
|
int32_t ms = offset - secs*1000;
|
||||||
@ -139,7 +148,7 @@ class Toki {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resetTick() {
|
void resetTick() {
|
||||||
tick = TickT::inactive;
|
if (tick == TickT::active) tick = TickT::inactive;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTick() {
|
bool isTick() {
|
||||||
|
@ -245,6 +245,7 @@ void handleNotifications()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool timebaseUpdated = false;
|
||||||
//apply effects from notification
|
//apply effects from notification
|
||||||
if (version < 200 && (receiveNotificationEffects || !someSel))
|
if (version < 200 && (receiveNotificationEffects || !someSel))
|
||||||
{
|
{
|
||||||
@ -258,21 +259,32 @@ void handleNotifications()
|
|||||||
t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay
|
t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay
|
||||||
t -= millis();
|
t -= millis();
|
||||||
strip.timebase = t;
|
strip.timebase = t;
|
||||||
|
timebaseUpdated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//adjust system time, but only if sender is more accurate than self
|
//adjust system time, but only if sender is more accurate than self
|
||||||
if (version > 7 && udpIn[29] > toki.getTimeSource())
|
if (version > 7)
|
||||||
{
|
{
|
||||||
Toki::Time tm;
|
Toki::Time tm;
|
||||||
tm.sec = (udpIn[30] << 24) | (udpIn[31] << 16) | (udpIn[32] << 8) | (udpIn[33]);
|
tm.sec = (udpIn[30] << 24) | (udpIn[31] << 16) | (udpIn[32] << 8) | (udpIn[33]);
|
||||||
tm.ms = (udpIn[34] << 8) | (udpIn[35]);
|
tm.ms = (udpIn[34] << 8) | (udpIn[35]);
|
||||||
toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay
|
if (udpIn[29] > toki.getTimeSource()) { //if sender's time source is more accurate
|
||||||
uint8_t ts = TOKI_TS_UDP;
|
toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay
|
||||||
if (udpIn[29] > 99) ts = TOKI_TS_UDP_NTP;
|
uint8_t ts = TOKI_TS_UDP;
|
||||||
else if (udpIn[29] >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC;
|
if (udpIn[29] > 99) ts = TOKI_TS_UDP_NTP;
|
||||||
toki.setTime(tm, ts);
|
else if (udpIn[29] >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC;
|
||||||
//TODO: even receive this if own time source is better, to offset network delay from timebase
|
toki.setTime(tm, ts);
|
||||||
|
} else if (timebaseUpdated && toki.getTimeSource() > 99) { //if we both have good times, get a more accurate timebase
|
||||||
|
Toki::Time myTime = toki.getTime();
|
||||||
|
uint32_t diff = toki.msDifference(tm, myTime);
|
||||||
|
strip.timebase -= PRESUMED_NETWORK_DELAY; //no need to presume, use difference between NTP times at send and receive points
|
||||||
|
if (toki.isLater(tm, myTime)) {
|
||||||
|
strip.timebase += diff;
|
||||||
|
} else {
|
||||||
|
strip.timebase -= diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version > 3)
|
if (version > 3)
|
||||||
|
Loading…
Reference in New Issue
Block a user