/*
Copyright 2007, Freie Universitaet Berlin. All rights reserved.

These sources were developed at the Freie Universität Berlin, Computer
Systems and Telematics group.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
 
- Neither the name of Freie Universitaet Berlin (FUB) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

This software is provided by FUB and the contributors on an "as is"
basis, without any representations or warranties of any kind, express
or implied including, but not limited to, representations or
warranties of non-infringement, merchantability or fitness for a
particular purpose. In no event shall FUB or contributors be liable
for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of
substitute goods or services; loss of use, data, or profits; or
business interruption) however caused and on any theory of liability,
whether in contract, strict liability, or tort (including negligence
or otherwise) arising in any way out of the use of this software, even
if advised of the possibility of such damage.

This implementation was developed by the CST group at the FUB.

For documentation and questions please use the web site
http://scatterweb.mi.fu-berlin.de and the mailinglist
scatterweb@lists.spline.inf.fu-berlin.de (subscription via the Website).
Berlin, 2007
*/

/**
 @file        ScatterWeb.Time.h
 @ingroup     kernel						
 @brief       The ScatterWeb.Time represents an instant in time, typically expressed as a date and time of day.
 @version     $Revision: 228 $					
 @since       1.0
 @author      Marco Hutta

 This file keeps the global time of this node in the global var currentTime.
 It contains methods for writing, reading and converting currentTime.
 To avoid concurrency problems accessing currentTime must be done with
 disabled interrupts or in interrupt routines only. This defines some macro
 for accessing Time_currentTime safely.

 $Id: ScatterWeb.Time.h 228 2007-11-09 12:31:08Z hutta@PCPOOL.MI.FU-BERLIN.DE $
 */

/**
 @ingroup kernel
 @{
 */

#ifndef ScatterWeb_Time
#define ScatterWeb_Time

/**
 @brief	Reads current time with disabled interrupts.

 @since	1.0
 */
#define CURRENT_TIME \
({ \
  extern volatile time_t currentTime; \
  time_t time;  \
  dint(); \
  _NOP(); \
  time = currentTime; \
  eint(); \
  time; \
}) 

/**
 @brief	Reads the uint32_t secs from current time with disabled interrupts.

 @since	1.0
 */
#define CURRENT_TIME_SECS \
({ \
  extern volatile time_t currentTime; \
  uint32_t secs;  \
  dint(); \
  _NOP(); \
  secs = currentTime.secs; \
  eint(); \
  secs; \
}) 

/**
 @brief	struct of time

 @see	Time_convertTime
 @see	Time_convertBtime
 @see	Time_write
 @see	Time_read

 @since	1.0
 */
typedef struct {
  uint8_t year; ///< year
  uint8_t month; ///< month
  uint8_t day; ///< day
  uint8_t hour; ///< hour
  uint8_t min; ///< min
  uint8_t sec; ///< sec
} btime_t;

/**
 @brief	struct of system time

 @see	Time_get
 @see	Time_set
 @see	Time_convertTime
 @see	Time_convertBtime

 @since	1.0
 */
typedef struct {
  uint32_t secs; ///< secs
  uint16_t millis; ///< millis
} time_t;

/// Offset from UTC 01.01.1970 00:00:00 to dawn of the ScatterWeb epoch
#define	UTC_OFFSET_SECONDS		978303600

/**
 @brief	Initialization of the Time module

 @since	1.0
 */
void Time_init();

/**
 @brief			Read currentTime or safely with disabled interrupts.

 @see			time_t
 @param[out]	time	current time to get
 @return				pointer of time

 @since			1.0

 Easier (and also faster) to use is CURRENT_TIME: time_t time = CURRENT_TIME;
 <-> time_t time; getCurrentTime(&time); 
 */
time_t* Time_get(time_t* time);

/**
 @brief		Write currentTime or safely with disabled interrupts.

 @see		time_t
 @param[in]	time	current time to set 
 @return			<code>True</code> always.

 @since		1.0
 */
bool Time_set(time_t* time);

/**
 @brief			Converts broken down time to time

 @see			time_t
 @see			btime_t
 @param[in]		src	time
 @param[out]	dst	current time 
 @return			<code>True</code> always.

 @since			1.0
 */
bool Time_convertTime(const time_t* src, btime_t* dst);

/**
 @brief Converts time to broken down time

 @see			time_t
 @see			btime_t
 @param[in]		src	current time
 @param[out]	dst	btime
 @return		<code>True</code> always.

 @since			1.0
 */
bool Time_convertBtime(const btime_t* src, time_t* dst);

/**
 @brief		Writes broken down time as a string in the form yyyy-mm-dd hh:mm:ss

 @see		btime_t
 @param[in]	writer	function to write
 @param[in]	time	time to write
 @return			<code>True</code> always.
 
 @since				1.0
 */
bool Time_write(char* buffer, btime_t* time);

/// Number of bytes produced by Time_write
#define TIME_STRING_LENGTH		20

/**
 @brief			Reads broken down time as a string.
 
 @see			btime_t
 @param[out]	c		array of time
 @param[in]		time	time to read
 @return		<code>True</code> always.

 @since			1.0

 The format is the same as in Time_writeTime, but the year must be written
 without 2000. The number of digits is not fixed like in Time_writeTime, so it
 is ok to write 03-09-07 08:31:02 or 3-9-7 8:31:2.
 */
bool Time_read(const uint8_t* c, btime_t* time);

#endif

/** @} */
