weAut_01 / weAutSys    R 2.2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
Files | Data Structures | Defines | Functions | Variables
Time keeping (date and time)
+ + System services (threading, time keeping, communication) + +

Overview

Real time automation systems require time keeping functions

weAutSys offers all those possibilities. (For the aspect of timers see timer handling.) Its basic timing is done in milliseconds (ms) resolution and by counting ticks from start or system reset in a 32 bit internal counter. The absolute timing is done in seconds (s) resolution in terms of seconds since March 1 2008 00:00 UTC.

Some timing functions, values and types are defined for weAutSys' internals. But all may be exploited by application software.

Milliseconds timing

weAutSys internal basic timing is milliseconds based. The milliseconds since system start / reset are counted as an unsigned 32 bit number.

All periodic tasking for automation cycles and all timers with milliseconds resolution is based on that "milliseconds since start" time. It will run on until power down or next reset and never be manipulated (adjusted) by any system operation.

The 32 bit unsigned number of milliseconds since system start will wrap around after a bit more than 49 days. This will limit the maximum period or runtime of weAutSys's timers with millisecond resolution to half that period; that is 24,8 days or 2.147.483.647 ms. Hence, for longer periods than three weeks use the timers with seconds resolution — a bearable restriction in most use cases.

Timing with seconds resolution

weAutSys's relative timing is based on having the seconds since system start continuously counted. This (32 bit unsigned) value will wrap around in about 136 years giving about 68 years (unproblematic) timer periods. (At present we don't care on longer timers and do not expect a device running that long without reset or power down — but that may be too pessimistic.)

Timers with seconds (s) resolution that are duration / period oriented are based on this absolute time.

Date time oriented timing with seconds resolution

weAutSys's absolute seconds timing is measured as seconds since March 1 2008 00:00 UTC (as a 32 bit unsigned value). The offset from seconds since start is, of course, basically the systems reset / restart time.

To get the local time and date two further offsets are handled:

The time zone offset is best be set by the answer of an appropriate DHCP server. Using one DHCP server + the NTP server provided by this DHCP has the advantage of automatically having the same settings on the whole automation subnet.

Switching DST on and off is based on the currently valid EU or Northern America's summer time rules.

The reset time offset will be known at the first incoming date / time information (best by weAutSys's built in NTP client and a NTP server made known by DHCP). Till this first setting it will be preset by the software build time, and hence be more or less in the past. Applications dependent on date and time should check if this (first) time setting has occurred.

The runtime's absolute "zero date" (March 1 2008 00:00 UTC ) is 1204329600s in UNIX (1.1.1970 based) and (approximately) 3413318400s in NTP (1.1.1900 based) time. So there is just a simple offset to usual absolute time informations. The problem of leap seconds is not yet handled (but may be in future).

The wrap around of that absolute seconds time (in the year 2144) is in no way dealt with but the NTP wrap around in 2136 is.

All date time related timers with seconds (s) resolution are based on this absolute time.


Files

file  timing.h
 

weAutSys definition of timing services


Data Structures

struct  datdur_t
 "Time since" as a structure: a duration or a date/time More...
struct  date_t
 Date structure: a date in our time. More...
struct  dst_rule_year_t
 Rule structure: DST rules for a given (set of) year(s) More...

Defines

#define DEFAULT_START_TIME
 Reset (or default) start time.
#define MARCH_2008_NTP   3413318400
 March 2008 as NTP seconds.
#define MARCH_2008_UNIX   1204329600
 March 2008 as UNIX seconds.
#define OFFSET2NTPTIME
 same as MARCH_2008_NTP
#define OFFSET2UNIXTIME
 same as MARCH_2008_UNIX
#define PRESC_TRIM_FAC
 Prescaled time factor to millisecond.
#define secTime308Loc(x)
 Seconds since March 1st 2008 local time.
#define startTime308UTC
 The reset / start time in seconds since March 1st 2008 UTC.
#define VCO_DEFAULT   7
 Trimming of timing oscillator.
#define zoneOffsetSec
 The time zone offset in seconds.
#define zoneOffsetZone
 zoneOffsetSec's byte [1]

Date calculation defines

#define DAYS_IN_YEAR
 Days in a year.
#define DAYS_IN4YEARS
 Days in four years.
#define APRIL_OFF
 Offset of April.
#define MAY_OFF
 Offset of May.
#define JUNE_OFF
 Offset of June.
#define JULY_OFF
 Offset of July.
#define AUGUST_OFF
 Offset of August.
#define SEPTEMBER_OFF
 Offset of September.
#define OCTOBER_OFF
 Offset of October.
#define NOVEMBER_OFF
 Offset of November.
#define DECEMBER_OFF
 Offset of December.
#define JANUARY_OFF
 Offset of (next) January.
#define FEBRUARY_OFF
 Offset of (next) February.
#define MARCH_2012
 March 2012.
#define MARCH_2016
 March 2016.
#define MARCH_2020
 March 2020.
#define MARCH_2100
 March 2100.

Date handling functions

uint8_t setDatByDays (date_t *datStr, uint16_t ds)
 Set date structure by days since since March 2008.
uint16_t getDaysByDat (date_t *datStr)
 Get days since since March 2008 by date structure.
uint8_t getMarchYearByDays (uint16_t *daysInYear, uint16_t ds)
 Get year starting March (includes next January and February)

Functions

uint8_t cnt12u8_8 (void) __attribute__((pure))
 Get the 12.8 (16) µs tick value (8 bit)
uint32_t datdur2sec (datdur_t *timStr)
 Calculate seconds from a datdur_t structure.
const dst_rule_year_tgetDSTrule (uint8_t year)
 Get the EU, US &c DST rule data for a given year.
uint32_t getFATtime (void)
 The local time as FAT time.
uint8_t getVCOsetting (void) __attribute__((pure))
 Trimming of timing oscillator.
uint8_t isEUdstSwitchDay (date_t *datStr)
 Is date represented in date structure EU DST switching day.
void sec2datdur (datdur_t *timStr, uint32_t timSec)
 Convert seconds to a datdur_t structure.
uint32_t secClock (void) __attribute__((always_inline))
 The system's run time in seconds.
uint32_t secTime308UTC (void) __attribute__((always_inline))
 Seconds since March 1st 2008 UTC.
uint32_t secTimeNtpUTC (uint32_t secTime308UTC) __attribute__((always_inline))
 Convert to seconds since January 1st 1990 UTC (NTP time)
uint32_t secTimeUnixUTC (uint32_t secTime308UTC) __attribute__((always_inline))
 Convert to seconds since January 1st 1970 UTC (Unix time)
uint8_t setDST (uint8_t dlt)
 Set if current time is DST.
void setVCOnormal (void) __attribute__((always_inline))
 Trimming of timing oscillator.
uint8_t setZoneOffsetSec (uint32_t newOffset)
 Adjust / set zone offset.
void slowVCOdown (void) __attribute__((always_inline))
 Trimming of timing oscillator.
void speedVCOup (void) __attribute__((always_inline))
 Trimming of timing oscillator.

Variables

uint8_t adjustUTCcount
 Count of secTime308Loc adjustments.
uint8_t cn12u8
 The 12,8 µs counter summand.
uint32_t combinedOffset
 The combined offset (local - UTC)
uint8_t isDST
 Is current time DST.
uint8_t msIntTick
 The ms tick counter.

Define Documentation

#define PRESC_TRIM_FAC

Prescaled time factor to millisecond.

By this factor the processor clock period pre-scaled by 256 will be the best <= approach to one millisecond.

For a 20 MHz machine the pre-sclaled clock period will be 12.8 µs and this factor 78. That will yield 998.4 µs which cal easily be slowed down by VCO to 1ms.

On a 16 MHz machine that will be 16µs, 62 and 992µs

#define VCO_DEFAULT   7

Trimming of timing oscillator.

The higher the value the faster the oscillator for the system 1 ms ticks will be running (in the mean). The relation is non-linear.

Background: This value is used to slow down respectively lengthen every 1st .. 255th millisecond tick period a tiny bit. All others will be a wee bit too fast.

Range: 1 .. 255 (0 would act as 256)

The best value for a 16 MHz machine is 2. The best setting for weAut_01 board with a good 20 MHz Quartz for ATmega1284's processor clock is 7.

#define secTime308Loc (   x)

Seconds since March 1st 2008 local time.

This gives the local time in seconds since (Saturday) March 1st 2008 in local time — i.e. with zone offsets and summertime (DST) shifts.

See also:
secClock()
msAbsClockCount
#define startTime308UTC

The reset / start time in seconds since March 1st 2008 UTC.

This is the systems reset time in seconds in seconds since weAutSys's zero date March 1st 2008 UTC. It will be initialised by DEFAULT_START_TIME and be adjusted by the first setting of time and date (e.g. by NTP client function) after reset.

#define zoneOffsetSec

The time zone offset in seconds.

This is usually in multiples of hours (3600) and in the range of -12..+12 (*3600) — positive being east of Greenwich.

The value should usually set by DHCP, the reset / default is 3600, i.e. CET.

Reset (or default) start time.

This absolute time in seconds since March 1st 2008 that will usually be set as last compile time (in the file maketime_utc.h by utc_maketime.bat).

This time will be used as reset value for the internal seconds clock.
Of course it will be quite wrong (i.e. more or less in past) until any adjustments by human command (CLI), time server answers or else are available.

DEFAULT_START_TIME can be used as date and time of make but will usually differ from SYST_DAT, which is the "official" (sub) version date.

#define MARCH_2008_NTP   3413318400

March 2008 as NTP seconds.

This is the NTP date for March 1 2008 00:00 UTC.
In weAutSys's seconds based absolute time this is the zero date.

#define MARCH_2008_UNIX   1204329600

March 2008 as UNIX seconds.

This is the UNIX date for March 1 2008 00:00 UTC (weAutSys's zero date).

See also:
MARCH_2008_NTP
#define DAYS_IN_YEAR

Days in a year.

It is of course 365; a leap year will be 1 day longer.

This leap day, the 29th of February (29.2.leapYear), would better have been put at the end of the year by the popes. That is in effect done so by clever calendar algorithms (not invented here but heavily used in weAutSys).

#define DAYS_IN4YEARS

Days in four years.

It is of course 4 * 365 + 1.

#define APRIL_OFF

Offset of April.

Days from March 1st to April 1st (same year).

#define MAY_OFF

Offset of May.

Days from March 1st to May 1st (same year).

#define JUNE_OFF

Offset of June.

Days from March 1st to June 1st (same year).

#define JULY_OFF

Offset of July.

See also:
JUNE_OFF
#define AUGUST_OFF

Offset of August.

See also:
JUNE_OFF
#define SEPTEMBER_OFF

Offset of September.

See also:
JUNE_OFF
#define OCTOBER_OFF

Offset of October.

See also:
JUNE_OFF
#define NOVEMBER_OFF

Offset of November.

See also:
JUNE_OFF
#define DECEMBER_OFF

Offset of December.

Days from March 1st to December 1st (same year).

See also:
JUNE_OFF
#define JANUARY_OFF

Offset of (next) January.

Days from March 1st to January 1st (next year).

See also:
DECEMBER_OFF
#define FEBRUARY_OFF

Offset of (next) February.

Days from March 1st to February 1st (next year).

#define MARCH_2012

March 2012.

This is the number of days at march 1st 2012 (1.3.2012 / 2012-03-01) counted since March 1st 2008 (1.3.2008 / 2008-03-01).

#define MARCH_2016

March 2016.

This is the number of days at march 1st 2016 (1.3.2016 / 2016-03-01) counted since March 1st 2008 (1.3.2008 / 2008-03-01).

#define MARCH_2020

March 2020.

This is the number of days at march 1st 2020 (1.3.2020 / 2020-03-01) counted since March 1st 2008 (1.3.2008 / 2008-03-01).

#define MARCH_2100

March 2100.

This is the number of days at march 1st 2100 (1.3.2100 / 2100-03-01) counted since March 1st 2008 (1.3.2008 / 2008-03-01).


Function Documentation

void setVCOnormal ( void  )

Trimming of timing oscillator.

This function will set the "value controlled oscillator" for the system's 1 ms tick to normal (usually best) speed.

Note:
If weAutSys's NTP client is active this function is for its exclusive use only.
See also:
VCO_DEFAULT
uint8_t getVCOsetting ( void  )

Trimming of timing oscillator.

This function returns the current speed of the "value controlled oscillator" for the system's 1 ms tick. VCO_DEFAULT is usually normal / best setting; higher values are faster.

void speedVCOup ( void  )

Trimming of timing oscillator.

This function will speed up the "value controlled oscillator" for the system's 1 ms tick a little bit. This is for catching up quite little differences to an externally given absolute (NTP e.g.) time.

Little differences in that sense are below -200 ms.

See the note at setVCOnormal.

See also:
VCO_DEFAULT
void slowVCOdown ( void  )

Trimming of timing oscillator.

This function will slow down the "value controlled oscillator" for the system's 1 ms tick a little bit. This is for catching up quite little differences to an externally given absolute (NTP e.g.) time.

Little differences in that sense are below +100 ms.

See the note at setVCOnormal.

See also:
VCO_DEFAULT
setVCOnormal
uint8_t cnt12u8_8 ( void  )

Get the 12.8 (16) µs tick value (8 bit)

This function returns the actual 12.8 µs respectively 16 µs tick count. This value will wrap about every 3.27 ms on a 20 MHz machine and every 4 ms at 16 MHz. One tick (increment) is 256 processor clocks.

It might be used for quite exact measures of software execution times the normal milliseconds resolution is of little use for.

Hint: 12.8 µs is correct for a 20 MHz machine. For slower machines the counted period is proportionally longer. For 16 MHz it's 16 µs.

See also:
PRESC_TRIM_FAC
uint32_t secClock ( void  )

The system's run time in seconds.

The value will be handled (incremented) by system software (i.e. the system's 1s thread). Monotony is guaranteed. There may be gaps, but that is very improbable — all miss-behaving (application) software leading to this should get a watchdog reset.

Do not modify the underlying variable! See also the warning.

See also:
msClock(void)
msSystClockCount
uint32_t getFATtime ( void  )

The local time as FAT time.

The local time contains zone offsets and summertime (DST) shifts. This function returns this time in a 32 bit (uint32_t) packed structure used for the traditional FAT file systems. Note that this (old DOS) time format has a 2s resolution only. The format is:

bit 31..25: year from 1980 (0..127; 2012 is 32)
bit 24..21: month (1..12)
bit 20..16: day in month (1..31)
bit 15..11: hour (0..23)
bit 10...5:  minute (0..59)
bit  4...0:   second / 2 (0..29, 30 if leap second)

See also:
secTime308Loc
uint32_t secTime308UTC ( void  )

Seconds since March 1st 2008 UTC.

The value will be the time in seconds since weAutSys's zero date March 1st 2008 UTC.

UTC here means without any zone or DST offsets.
The returned value can easily be converted to UNIX or NTP time.

See also:
secTime308Loc()
uint32_t secTimeUnixUTC ( uint32_t  secTime308UTC)

Convert to seconds since January 1st 1970 UTC (Unix time)

The returned value will be time in seconds since the UNIX time start date.

Parameters:
secTime308UTCthe time in seconds since March 2008 UTC
See also:
secClock()
secTime308UTC()
uint32_t secTimeNtpUTC ( uint32_t  secTime308UTC)

Convert to seconds since January 1st 1990 UTC (NTP time)

The returned value is the time in seconds since the NTP time start date. Called with secClock() as parameter stamp this value would be used as a NTP server respectively indirectly adjusted by the NTP client function.

Parameters:
secTime308UTCthe time in seconds since March 2008 UTC
See also:
secClock()
secTime308UTC()
uint8_t setDST ( uint8_t  dlt)

Set if current time is DST.

Returns:
0 if no changes were made, otherwise 1
See also:
isDST
uint8_t setZoneOffsetSec ( uint32_t  newOffset)

Adjust / set zone offset.

This function sets zoneOffsetSec and handles all side effects in the case of a change.

Returns:
true if changed
void sec2datdur ( datdur_t timStr,
uint32_t  timSec 
)

Convert seconds to a datdur_t structure.

This function converts a 32 bit unsigned seconds value to a time structure of type datdur_t. Its interpretation as duration or absolute date and time depends on the parameter's semantic.

Hint: This is a quite expensive operation for an 8 bit RISC machine without divide instruction. The result timStr should be kept if usable more than once.

Parameters:
timStrpointer to the time structure to be set
timSecthe time in seconds
See also:
datdur2sec
uint32_t datdur2sec ( datdur_t timStr)

Calculate seconds from a datdur_t structure.

This function converts the content of a structure of type datdur_t to the corresponding 32 bit unsigned seconds value. It is the inverse of sec2datdur().

Hint: This function is not quite cheap for an 8 bit RISC machine with just a 8bit * 8bit = 16bit multiply instruction. The returned result should be kept if needed more than once.

Parameters:
timStrpointer to the time structure to be used
Returns:
the seconds calculated from timStr
uint8_t setDatByDays ( date_t datStr,
uint16_t  ds 
)

Set date structure by days since since March 2008.

This function sets the (16 bit unsigned) number of days since March 2008 into the structure datStr and all its other fields.

Parameters:
datStrpointer to the date structure to be set
dsdays since weAutSys's day 0
Returns:
the resulting weekday (1..7) or 0 in erroneous situations
See also:
datdur2sec
getDaysByDat
uint16_t getDaysByDat ( date_t datStr)

Get days since since March 2008 by date structure.

This calculates the (16 bit unsigned) number of days since March 2008 from the structure and returns the result. All fields of datStr except day of week (ed) are used and must have correct and consistent values.

Before March 2008 0 is returned as is for everything after about ~2177.

Parameters:
datStrpointer to the date structure to be used
Returns:
days since weAutSys's day 0
See also:
setDatByDays
datdur2sec
uint8_t getMarchYearByDays ( uint16_t *  daysInYear,
uint16_t  ds 
)

Get year starting March (includes next January and February)

Parameters:
dsdays since weAutSys's day 0
daysInYearpointer to extra result: the the days in the respective year (0 = March 1st); if NULL this information is lost
Returns:
the resulting year 8 .. = 2008 ..
See also:
datdur2sec
const dst_rule_year_t* getDSTrule ( uint8_t  year)

Get the EU, US &c DST rule data for a given year.

This function returns a pointer to the DST rule structure for the year requested in flash memory (!). Use pgm_read_byte() respectively pgm_read_dword() accordingly to get single elements. Or — to have the whole struture in RAM use

    dst_rule_year_t currentRuleValues;
    memcpy_P(&currentRuleValues, getDSTrule(year), sizeof(dst_rule_year_t));
Parameters:
year0..255 interpreted as 2000..2255
uint8_t isEUdstSwitchDay ( date_t datStr)

Is date represented in date structure EU DST switching day.

This function checks if the date is either the last Sunday in March (returns 3) or the last Sunday in October (returns 10) or non of both (returns 0).

Parameters:
datStrpointer to the date structure
Returns:
the resulting 3, 10 or 0

Variable Documentation

uint8_t msIntTick

The ms tick counter.

This variable is written, i.e. incremented, in the tick interrupt handler ISR(TIMER0_COMPA_vect) only.
This variable must never (!) be modified elsewhere.

Being just one byte reading it is atomic.

See also:
syst_threads.h
uint8_t cn12u8

The 12,8 µs counter summand.

Incremented in the 1ms interrupt by PRESC_TRIM_FAC (or PRESC_TRIM_FAC + 1 if VCO slow).

This variable is not to be used directly by user / application software. Use it idirectly by cnt12u8_8().

uint8_t adjustUTCcount

Count of secTime308Loc adjustments.

Significant local time adjustments are counted here. 0 means no time date setting since reset (hence usually incorrect).
Counting wraps from 255 to 1.

Significant means hard setting of secTime308Loc or its ms (0.999) fraction part msAbsClockCount. Adjustments by variable controlled oscillator (VCO) are not counted.

uint32_t combinedOffset

The combined offset (local - UTC)

This is the difference from local time to UTC.
In other words it is the sum zoneOffsetSec + DST offset

Do never ever modify this value directly. That may spoil timers and more.

uint8_t isDST

Is current time DST.

This is non 0 if (current) secTime308Loc() is summertime.

See also:
setDST()