From 4cf72e7ef4fcabde230de44ba1d1ab5d57cdeee0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 8 Nov 2015 23:44:25 +0300 Subject: [PATCH] Add libc time functions Merging https://github.com/igrr/axtls-8266/pull/1 by @Juppit into the core --- cores/esp8266/Arduino.h | 4 +- cores/esp8266/libc_replacements.c | 18 ----- cores/esp8266/time.c | 128 ++++++++++++++++++++++++++++++ tests/Time/Time.ino | 35 ++++++++ 4 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 cores/esp8266/time.c create mode 100644 tests/Time/Time.ino diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 8f440f27b..6a7736634 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -153,7 +153,7 @@ void ets_intr_unlock(); // level (0-15), interrupts of the given level and above will be active // level 15 will disable ALL interrupts, // level 0 will enable ALL interrupts, -// +// #define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;})) #define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory") @@ -271,6 +271,8 @@ long random(long, long); void randomSeed(unsigned long); long map(long, long, long, long, long); +extern "C" void configTime(int timezone, int daylightOffset_sec, + const char* server1, const char* server2 = nullptr, const char* server3 = nullptr); #endif diff --git a/cores/esp8266/libc_replacements.c b/cores/esp8266/libc_replacements.c index d77d5c397..f7d1420e3 100644 --- a/cores/esp8266/libc_replacements.c +++ b/cores/esp8266/libc_replacements.c @@ -393,24 +393,6 @@ int* __errno(void) { return &errno_var; } - -char * ctime(const time_t *clock) { - return 0; -} - -time_t time(time_t * t) { - return 0; -} - -int gettimeofday(void *tp, void *tzp) { - return 0; -} - -time_t mktime(struct tm *timp) { - return 0; -} - - /* * begin newlib/string/strlcpy.c * diff --git a/cores/esp8266/time.c b/cores/esp8266/time.c new file mode 100644 index 000000000..ff407cef4 --- /dev/null +++ b/cores/esp8266/time.c @@ -0,0 +1,128 @@ +/* + * time.c - ESP8266-specific functions for SNTP + * Copyright (c) 2015 Peter Dobler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "sntp.h" + + +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED +struct timeval { + time_t tv_sec; + suseconds_t tv_usec; +}; +#endif + +extern char* sntp_asctime(const struct tm *t); +extern struct tm* sntp_localtime(const time_t *clock); + +// time gap in seconds from 01.01.1900 (NTP time) to 01.01.1970 (UNIX time) +#define DIFF1900TO1970 2208988800UL + +static int s_daylightOffset_sec = 0; +static int s_timezone_sec = 0; +static time_t s_bootTime = 0; + +// calculate offset used in gettimeofday +static void ensureBootTimeIsSet() +{ + if (!s_bootTime) + { + time_t now = sntp_get_current_timestamp(); + if (now) + { + s_bootTime = - millis() / 1000; + } + } +} + +static void setServer(int id, const char* name_or_ip) +{ + if (name_or_ip) + { + //TODO: check whether server is given by name or IP + sntp_setservername(0, (char*) name_or_ip); + } +} + +void configTime(int timezone, int daylightOffset_sec, const char* server1, const char* server2, const char* server3) +{ + sntp_stop(); + + setServer(0, server1); + setServer(1, server2); + setServer(2, server3); + + s_timezone_sec = timezone; + s_daylightOffset_sec = daylightOffset_sec; + sntp_set_timezone(timezone/3600); + sntp_init(); +} + +int clock_gettime(clockid_t unused, struct timespec *tp) +{ + tp->tv_sec = millis() / 1000; + tp->tv_nsec = micros() * 1000; + return 0; +} + +// seconds since 1970 +time_t mktime(struct tm *t) +{ + // system_mktime expects month in range 1..12 + #define START_MONTH 1 + return DIFF1900TO1970 + system_mktime(t->tm_year, t->tm_mon + START_MONTH, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); +} + +time_t time(time_t * t) +{ + time_t seconds = sntp_get_current_timestamp(); + ensureBootTimeIsSet(); + if (t) + { + *t = seconds; + } + return seconds; +} + +char* asctime(const struct tm *t) +{ + return sntp_asctime(t); +} + +struct tm* localtime(const time_t *clock) +{ + return sntp_localtime(clock); +} + +char* ctime(const time_t *t) +{ + struct tm* p_tm = localtime(t); + char* result = asctime(p_tm); + return result; +} + +int gettimeofday(struct timeval *tp, void *tzp) +{ + if (tp) + { + ensureBootTimeIsSet(); + tp->tv_sec = (s_bootTime + millis()) / 1000; + tp->tv_usec = micros() * 1000; + } +} diff --git a/tests/Time/Time.ino b/tests/Time/Time.ino new file mode 100644 index 000000000..e4078534a --- /dev/null +++ b/tests/Time/Time.ino @@ -0,0 +1,35 @@ +#include +#include + +const char* ssid = ".........."; +const char* password = ".........."; + +int timezone = 3; +int dst = 0; + +void setup() { + Serial.begin(115200); + Serial.setDebugOutput(true); + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + Serial.println("\nConnecting to WiFi"); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + + configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov"); + Serial.println("\nWaiting for time"); + while (!time(nullptr)) { + Serial.print("."); + delay(1000); + } + Serial.println(""); +} + +void loop() { + time_t now = time(nullptr); + Serial.println(ctime(&now)); + delay(1000); +}