Added NTP time (overrules RDS CT)

This commit is contained in:
Sjef Verhoeven PE5PVB
2025-01-09 21:49:11 +01:00
parent 525593d6c4
commit dc69f72951
9 changed files with 158 additions and 132 deletions

View File

@@ -1,58 +1,84 @@
#include "NTPupdate.h"
// send an NTP request to the time server at the given address
// Sends an NTP request packet to the specified server address
void sendNTPpacket(IPAddress &address) {
byte packetBuffer[NTP_PACKET_SIZE];
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
byte packetBuffer[NTP_PACKET_SIZE] = {0}; // Initialize buffer with zeros
// Set NTP packet header fields as per NTP protocol
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[2] = 6; // Polling interval
packetBuffer[3] = 0xEC; // Peer clock precision
// Root Delay & Root Dispersion fields
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
// Send the NTP request to port 123 (NTP standard port)
Udp.beginPacket(address, 123);
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
// Retrieves the current time from an NTP server
time_t getNtpTime() {
IPAddress ntpServerIP; // NTP server's ip address
IPAddress ntpServerIP;
byte packetBuffer[NTP_PACKET_SIZE];
while (Udp.parsePacket() > 0) ; // discard any previously received packets
WiFi.hostByName(ntpServerName, ntpServerIP);
// Clear any previously received UDP packets
while (Udp.parsePacket() > 0);
// Resolve the NTP server's hostname to its IP address
if (!WiFi.hostByName(ntpServerName, ntpServerIP)) {
return 0; // Return 0 if hostname resolution fails
}
// Send an NTP request
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
// Wait for a response with a 1500ms timeout
uint32_t startWait = millis();
while (millis() - startWait < 1500) {
if (Udp.parsePacket() >= NTP_PACKET_SIZE) { // Check if a valid packet is received
Udp.read(packetBuffer, NTP_PACKET_SIZE);
// Extract "seconds since 1900" from the packet (bytes 40-43)
unsigned long secsSince1900 =
((unsigned long)packetBuffer[40] << 24) |
((unsigned long)packetBuffer[41] << 16) |
((unsigned long)packetBuffer[42] << 8) |
(unsigned long)packetBuffer[43];
// Convert to UNIX epoch time (seconds since 1970)
return secsSince1900 - 2208988800UL;
}
}
return 0; // return 0 if unable to get the time
// Return 0 if no valid response is received
return 0;
}
// Updates the RTC with the time from an NTP server
void NTPupdate() {
if (!wifi) { return; }
time_t time = getNtpTime();
if (time) {
rtc.setTime(time);
// Abort if Wi-Fi is not connected
if (!wifi) {
NTPupdated = false;
return;
}
}
// Retrieve the current time from the NTP server
time_t currentTime = getNtpTime();
if (currentTime) {
// Set the RTC if valid time is received
rtc.setTime(currentTime);
rtcset = true;
NTPupdated = true;
radio.rds.ctupdate = false;
} else {
// Indicate that the update failed
NTPupdated = false;
radio.rds.ctupdate = true;
}
}

View File

@@ -7,6 +7,7 @@
#include <WiFiUdp.h>
#include <ESP32Time.h>
#include <TimeLib.h>
#include "TEF6686.h"
static const char ntpServerName[] = "0.pool.ntp.org";
static const int localPort = 8944;
@@ -15,7 +16,11 @@ const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
extern ESP32Time rtc;
extern WiFiClient RemoteClient;
extern WiFiUDP Udp;
extern TEF6686 radio;
extern bool wifi;
extern bool NTPupdated;
extern bool rtcset;
void sendNTPpacket(IPAddress &address);
void NTPupdate();

View File

@@ -1340,7 +1340,7 @@ void TEF6686::readRDS(byte showrdserrors) {
} break;
case RDS_GROUP_4A: {
if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) {
if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold && rds.ctupdate) {
// CT
uint32_t mjd;
mjd = (rds.rdsB & 0x03);

View File

@@ -621,6 +621,7 @@ typedef struct _rds_ {
bool filter;
bool rdsreset;
bool pierrors;
bool ctupdate = true;
bool sortaf;
bool rtbuffer = true;
bool afreg;

View File

@@ -912,6 +912,7 @@ void tryWiFi() {
Server.begin();
Udp.begin(9031);
webserver.begin();
NTPupdate();
remoteip = IPAddress (WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], subnetclient);
if (!setupmode) tftPrint(0, myLanguage[language][57], 155, 128, InsignificantColor, InsignificantColorSmooth, 28);
} else {

View File

@@ -149,4 +149,5 @@ extern void ShowStepSize();
extern void startFMDXScan();
extern void cancelDXScan();
extern void printLogbookCSV();
extern void NTPupdate();
#endif

View File

@@ -787,89 +787,70 @@ void showCT() {
char str[6];
time_t t;
// Check if screen is not muted and the clock should be displayed
if (!screenmute && showclock) {
// Determine the current time source
if (radio.rds.hasCT && !dropout && !NTPupdated) {
t = radio.rds.time + radio.rds.offset;
} else {
t = rtc.getEpoch() + (NTPupdated ? 0 : radio.rds.offset);
// If RDS CT (Clock Time) is available and no dropout, use RDS time
if (radio.rds.hasCT && !dropout) {
t = radio.rds.time + radio.rds.offset;
// Update RDS time during dropout
if (dropout) {
radio.rds.time = static_cast<time_t>(rtc.getEpoch());
}
// If no RDS CT or there is a dropout, fall back to RTC time
else {
t = rtc.getEpoch() + radio.rds.offset;
// Update RDS time in case of dropout
if (dropout) {
radio.rds.time = static_cast<time_t>(rtc.getEpoch());
}
}
// Check if USA region, use 12-hour AM/PM format
if (radio.rds.region == 1) {
// Format time in 24-hour format first
strftime(str, sizeof(str), "%I:%M", localtime(&t));
// Manually determine AM/PM and add it
int hour = localtime(&t)->tm_hour;
String ampm = (hour >= 12) ? "PM" : "AM";
// Adjust the hour to 12-hour format, taking care of 12 AM and 12 PM
if (hour == 0) {
hour = 12; // Midnight case
} else if (hour > 12) {
hour -= 12; // Convert PM to 12-hour format
}
// Construct the final time string manually
rds_clock = String(hour) + ":" + String(localtime(&t)->tm_min) + " " + ampm;
} else {
// For other regions, use 24-hour format
strftime(str, sizeof(str), "%H:%M", localtime(&t));
rds_clock = String(str);
}
// If the clock has changed or RDS CT status has changed, update the display
if (rds_clock != rds_clockold || hasCTold != radio.rds.hasCT) {
// If RDS CT is available and RDS status is active, set RTC time
if (radio.rds.hasCT && RDSstatus) {
rtcset = true;
rtc.setTime(radio.rds.time);
// Display the new time with different coordinates based on advancedRDS setting
if (advancedRDS) {
tftReplace(1, rds_clockold, rds_clock, 208, 109, RDSColor, RDSColorSmooth, BackgroundColor, 16);
} else {
tftReplace(1, rds_clockold, rds_clock, 208, 163, RDSColor, RDSColorSmooth, BackgroundColor, 16);
}
}
// If no RDS CT available or status is inactive, handle dropout scenarios
else {
// If RTC was previously set, show dropout message
if (rtcset) {
if (advancedRDS) {
tftReplace(1, rds_clockold, rds_clock, 208, 109, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 16);
} else {
tftReplace(1, rds_clockold, rds_clock, 208, 163, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 16);
}
}
// If RTC is not set, just print the clock with no background (clear the display)
else {
if (advancedRDS) {
tftPrint(1, rds_clockold, 208, 109, BackgroundColor, BackgroundColor, 16);
tftPrint(1, rds_clock, 208, 109, BackgroundColor, BackgroundColor, 16);
} else {
tftPrint(1, rds_clockold, 208, 163, BackgroundColor, BackgroundColor, 16);
tftPrint(1, rds_clock, 208, 163, BackgroundColor, BackgroundColor, 16);
}
}
}
}
// Update the previous clock and RDS CT status to detect future changes
rds_clockold = rds_clock;
hasCTold = radio.rds.hasCT;
}
// Apply the GMT offset only if NTPupdated is true
if (NTPupdated) {
t += NTPoffset * 3600; // Convert offset from hours to seconds
}
// Format the time based on region
if (radio.rds.region == 1) { // USA region: 12-hour AM/PM format
strftime(str, sizeof(str), "%I:%M", localtime(&t));
// Determine AM/PM and adjust hour format
int hour = localtime(&t)->tm_hour;
String ampm = (hour >= 12) ? "PM" : "AM";
if (hour == 0) {
hour = 12; // Midnight case
} else if (hour > 12) {
hour -= 12; // Convert PM hours
}
rds_clock = String(hour) + ":" + String(localtime(&t)->tm_min) + " " + ampm;
} else { // Other regions: 24-hour format
strftime(str, sizeof(str), "%H:%M", localtime(&t));
rds_clock = String(str);
}
// Check if the clock or RDS CT status has changed
if (!screenmute && showclock && (rds_clock != rds_clockold || hasCTold != radio.rds.hasCT)) {
// Update RTC if RDS CT is available or NTP was updated
if ((radio.rds.hasCT && RDSstatus) || NTPupdated) {
rtcset = true;
if (!NTPupdated) {
rtc.setTime(radio.rds.time);
}
// Display the updated time
int yCoord = advancedRDS ? 109 : 163;
tftReplace(1, rds_clockold, rds_clock, 208, yCoord, RDSColor, RDSColorSmooth, BackgroundColor, 16);
} else { // Handle dropout scenarios
int yCoord = advancedRDS ? 109 : 163;
if (rtcset) { // Display dropout message if RTC was set
tftReplace(1, rds_clockold, rds_clock, 208, yCoord, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 16);
} else { // Clear and reprint the clock
tftPrint(1, rds_clockold, 208, yCoord, BackgroundColor, BackgroundColor, 16);
tftPrint(1, rds_clock, 208, yCoord, BackgroundColor, BackgroundColor, 16);
}
}
}
// Update previous clock and RDS CT status
rds_clockold = rds_clock;
hasCTold = radio.rds.hasCT;
}
void showRadioText() {

View File

@@ -26,6 +26,7 @@ extern bool haseonold;
extern bool hasrtplusold;
extern bool hastmcold;
extern bool memreset;
extern bool NTPupdated;
extern bool rdsreset;
extern bool RDSSPYTCP;
extern bool RDSSPYUSB;
@@ -51,6 +52,7 @@ extern byte ECCold;
extern byte language;
extern byte licold;
extern byte MSold;
extern byte NTPoffset;
extern byte eonptyold[20];
extern byte rdsblockold;
extern byte rdsqualityold;