2018-02-06 10:44 AM
For an embedded project with micro STM8, would be very useful to me to have the mathematical formula to calculate the 'timestamp' (epoch) in 'C' without using libraries because, unlike the STM32, for this family of microcontrollers does not exist. Does anyone have any suggestions?
#timestamp2018-02-06 10:59 AM
I have this, and an implementation for gmtime()
https://community.st.com/0D70X000006SmDJSA0
https://www.cise.ufl.edu/class/cop4600/minix/src/lib/ansi/gmtime.c
2018-02-06 12:38 PM
https://www.cise.ufl.edu/class/cop4600/minix/src/lib/ansi/gmtime.c
// Keil implementation flawed/empty, this has been tested
#define YEAR0 1900 /* the first year */
#define EPOCH_YR 1970 /* EPOCH = Jan 1 1970 00:00:00 */
#define SECS_DAY (24L * 60L * 60L)
#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
#define FIRSTSUNDAY(timp) (((timp)->tm_yday - (timp)->tm_wday + 420) % 7)
#define FIRSTDAYOF(timp) (((timp)->tm_wday - (timp)->tm_yday + 420) % 7)
// http://www.cise.ufl.edu/~cop4600/cgi-bin/lxr/http/source.cgi/lib/ansi/gmtime.c
// https://www.cise.ufl.edu/class/cop4600/minix/src/lib/ansi/gmtime.c
const int _ytab[2][12] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
struct tm * __gmtime(const time_t *timer)
{
static struct tm br_time;
struct tm *timep = &br_time;
time_t time = *timer;
unsigned long dayclock, dayno;
int year = EPOCH_YR;
dayclock = (unsigned long)time % SECS_DAY;
dayno = (unsigned long)time / SECS_DAY;
timep->tm_sec = dayclock % 60;
timep->tm_min = (dayclock % 3600) / 60;
timep->tm_hour = dayclock / 3600;
timep->tm_wday = (dayno + 4) % 7; /* day 0 was a thursday */
{ // fold so it iterates less - sourcer32@gmail.com
unsigned long zz = dayno / 1461; // 365+365+365+366 Breaks beyond 2100
if (zz > 32) zz = 32; // fix 2101-2106
year += zz * 4;
dayno -= zz * 1461;
}
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
timep->tm_year = year - YEAR0;
timep->tm_yday = dayno;
timep->tm_mon = 0;
while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) {
dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon];
timep->tm_mon++;
}
timep->tm_mday = dayno + 1;
timep->tm_isdst = 0;
return timep;
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
I modified it so it 'ages' more gracefully, and doesn't cause execution time to creep out of control
2018-02-07 02:59 PM
It is often included as part of the library.
If you like to roll your own, you can easily find it on the net. I often start with clock_t and clockspersec, to yield a 32bit time_t, thus maximizing compatibility.
2018-02-07 04:22 PM
>>
It is often included as part of the library.
That's certainly my experience, although in embedded how the clock actually ticks tends to be something punted to the user.
I've got another library I wrote doing an emulation of Win32's SYSTEMTIME, to aid portability and cross-development.
Testing of routines is highly recommend, especially for 2038 rollover (32-bit signed), and correct behaviour in the 1901-2099 era.
For support beyond that significantly more rigor is required. And frankly a lot of iterative solutions have ever increasing run time, so if called frequently one needs to be particularly conscious of task dead-lines if the device is expected to function for decades.