2016-06-15 23:48:41 +02:00
# ifndef CCSDSTIME_H_
# define CCSDSTIME_H_
2018-07-12 16:29:32 +02:00
# include <framework/timemanager/Clock.h>
2016-06-15 23:48:41 +02:00
# include <framework/returnvalues/HasReturnvaluesIF.h>
# include <stdint.h>
bool operator < ( const timeval & lhs , const timeval & rhs ) ;
2018-07-12 16:29:32 +02:00
bool operator < = ( const timeval & lhs , const timeval & rhs ) ;
2016-06-15 23:48:41 +02:00
bool operator = = ( const timeval & lhs , const timeval & rhs ) ;
/**
* static helper class for CCSDS Time Code Formats
*
* as described in CCSDS 301.0 - B - 3
*
2018-07-12 16:29:32 +02:00
* Still work in progress
2016-06-15 23:48:41 +02:00
*/
class CCSDSTime : public HasReturnvaluesIF {
public :
/**
* The Time code identifications , bits 4 - 6 in the P - Field
*/
enum TimeCodeIdentification {
CCS = 0 b101 ,
CUC_LEVEL1 = 0 b001 ,
CUC_LEVEL2 = 0 b010 ,
CDS = 0 b100 ,
AGENCY_DEFINED = 0 b110
} ;
static const uint8_t P_FIELD_CUC_6B_CCSDS = ( CUC_LEVEL1 < < 4 ) + ( 3 < < 2 )
+ 2 ;
static const uint8_t P_FIELD_CUC_6B_AGENCY = ( CUC_LEVEL2 < < 4 ) + ( 3 < < 2 )
+ 2 ;
2018-07-12 16:29:32 +02:00
static const uint8_t P_FIELD_CDS_SHORT = ( CDS < < 4 ) ;
2016-06-15 23:48:41 +02:00
/**
* Struct for CDS day - segmented format .
*/
struct CDS_short {
uint8_t pField ;
uint8_t dayMSB ;
uint8_t dayLSB ;
uint8_t msDay_hh ;
uint8_t msDay_h ;
uint8_t msDay_l ;
uint8_t msDay_ll ;
} ;
/**
2018-07-12 16:29:32 +02:00
* Struct for the CCS fromat in day of month variation with max resolution
2016-06-15 23:48:41 +02:00
*/
struct Ccs_seconds {
uint8_t pField ;
uint8_t yearMSB ;
uint8_t yearLSB ;
uint8_t month ;
uint8_t day ;
uint8_t hour ;
uint8_t minute ;
uint8_t second ;
} ;
/**
* Struct for the CCS fromat in day of month variation with 10E-4 seconds resolution
*/
struct Ccs_mseconds {
uint8_t pField ;
uint8_t yearMSB ;
uint8_t yearLSB ;
uint8_t month ;
uint8_t day ;
uint8_t hour ;
uint8_t minute ;
uint8_t second ;
uint8_t secondEminus2 ;
uint8_t secondEminus4 ;
} ;
struct OBT_FLP {
uint8_t pFiled ;
uint8_t seconds_hh ;
uint8_t seconds_h ;
uint8_t seconds_l ;
uint8_t seconds_ll ;
uint8_t subsecondsMSB ;
uint8_t subsecondsLSB ;
} ;
struct TimevalLess {
bool operator ( ) ( const timeval & lhs , const timeval & rhs ) const {
return ( lhs < rhs ) ;
}
} ;
2018-07-12 16:29:32 +02:00
static const uint8_t INTERFACE_ID = CLASS_ID : : CCSDS_TIME_HELPER_CLASS ;
2016-06-15 23:48:41 +02:00
static const ReturnValue_t UNSUPPORTED_TIME_FORMAT = MAKE_RETURN_CODE ( 0 ) ;
static const ReturnValue_t NOT_ENOUGH_INFORMATION_FOR_TARGET_FORMAT =
MAKE_RETURN_CODE ( 1 ) ;
static const ReturnValue_t LENGTH_MISMATCH = MAKE_RETURN_CODE ( 2 ) ;
static const ReturnValue_t INVALID_TIME_FORMAT = MAKE_RETURN_CODE ( 3 ) ;
static const ReturnValue_t INVALID_DAY_OF_YEAR = MAKE_RETURN_CODE ( 4 ) ;
static const ReturnValue_t TIME_DOES_NOT_FIT_FORMAT = MAKE_RETURN_CODE ( 5 ) ;
/**
* convert a TimeofDay struct to ccs with seconds resolution
*
* @ param to pointer to a CCS struct
* @ param from pointer to a TimeOfDay Struct
* @ return
2018-07-12 16:29:32 +02:00
* - @ c RETURN_OK if OK
* - @ c INVALID_TIMECODE if not OK
2016-06-15 23:48:41 +02:00
*/
static ReturnValue_t convertToCcsds ( Ccs_seconds * to ,
2018-07-12 16:29:32 +02:00
Clock : : TimeOfDay_t const * from ) ;
2016-06-15 23:48:41 +02:00
/**
* Converts to CDS format from timeval .
* @ param to pointer to the CDS struct to generate
* @ param from pointer to a timeval struct which comprises a time of day since UNIX epoch .
* @ return
* - @ c RETURN_OK as it assumes a valid timeval .
*/
static ReturnValue_t convertToCcsds ( CDS_short * to , timeval const * from ) ;
static ReturnValue_t convertToCcsds ( OBT_FLP * to , timeval const * from ) ;
2018-07-12 16:29:32 +02:00
2016-06-15 23:48:41 +02:00
/**
* convert a TimeofDay struct to ccs with 10E-3 seconds resolution
*
* The 10E-4 seconds in the CCS Struct are 0 as the TimeOfDay only has ms resolution
*
* @ param to pointer to a CCS struct
* @ param from pointer to a TimeOfDay Struct
* @ return
2018-07-12 16:29:32 +02:00
* - @ c RETURN_OK if OK
* - @ c INVALID_TIMECODE if not OK
2016-06-15 23:48:41 +02:00
*/
static ReturnValue_t convertToCcsds ( Ccs_mseconds * to ,
2018-07-12 16:29:32 +02:00
Clock : : TimeOfDay_t const * from ) ;
2016-06-15 23:48:41 +02:00
/**
2018-07-12 16:29:32 +02:00
* SHOULDDO : can this be modified to recognize padding ?
2016-06-15 23:48:41 +02:00
* Tries to interpret a Level 1 CCSDS time code
*
* It assumes binary formats contain a valid P Field and recognizes the ASCII format
* by the lack of one .
*
* @ param to an empty TimeOfDay struct
* @ param from pointer to an CCSDS Time code
* @ param length length of the Time code
* @ return
* - @ c RETURN_OK if successful
2018-07-12 16:29:32 +02:00
* - @ c UNSUPPORTED_TIME_FORMAT if a ( possibly valid ) time code is not supported
2016-06-15 23:48:41 +02:00
* - @ c LENGTH_MISMATCH if the length does not match the P Field
* - @ c INVALID_TIME_FORMAT if the format or a value is invalid
*/
2018-07-12 16:29:32 +02:00
static ReturnValue_t convertFromCcsds ( Clock : : TimeOfDay_t * to , uint8_t const * from ,
2016-06-15 23:48:41 +02:00
uint32_t length ) ;
/**
* not implemented yet
*
* @ param to
* @ param from
* @ return
*/
static ReturnValue_t convertFromCcsds ( timeval * to , uint8_t const * from ,
uint32_t * foundLength , uint32_t maxLength ) ;
2018-07-12 16:29:32 +02:00
static ReturnValue_t convertFromCUC ( Clock : : TimeOfDay_t * to , uint8_t const * from ,
2016-06-15 23:48:41 +02:00
uint8_t length ) ;
static ReturnValue_t convertFromCUC ( timeval * to , uint8_t const * from ,
uint32_t * foundLength , uint32_t maxLength ) ;
static ReturnValue_t convertFromCUC ( timeval * to , uint8_t pField ,
uint8_t const * from , uint32_t * foundLength , uint32_t maxLength ) ;
static ReturnValue_t convertFromCCS ( timeval * to , uint8_t const * from ,
uint32_t * foundLength , uint32_t maxLength ) ;
static ReturnValue_t convertFromCCS ( timeval * to , uint8_t pField ,
uint8_t const * from , uint32_t * foundLength , uint32_t maxLength ) ;
2018-07-12 16:29:32 +02:00
static ReturnValue_t convertFromCDS ( Clock : : TimeOfDay_t * to , uint8_t const * from ,
2016-06-15 23:48:41 +02:00
uint8_t length ) ;
static ReturnValue_t convertFromCDS ( timeval * to , uint8_t const * from ,
uint32_t * foundLength , uint32_t maxLength ) ;
2018-07-12 16:29:32 +02:00
static ReturnValue_t convertFromCCS ( Clock : : TimeOfDay_t * to , uint8_t const * from ,
2016-06-15 23:48:41 +02:00
uint32_t * foundLength , uint32_t maxLength ) ;
2018-07-12 16:29:32 +02:00
static ReturnValue_t convertFromASCII ( Clock : : TimeOfDay_t * to , uint8_t const * from ,
2016-06-15 23:48:41 +02:00
uint8_t length ) ;
static uint32_t subsecondsToMicroseconds ( uint16_t subseconds ) ;
private :
CCSDSTime ( ) ;
virtual ~ CCSDSTime ( ) ;
/**
2018-07-12 16:29:32 +02:00
* checks a ccs time stream for validity
2016-06-15 23:48:41 +02:00
*
2018-07-12 16:29:32 +02:00
* Stream may be longer than the actual timecode
2016-06-15 23:48:41 +02:00
*
2018-07-12 16:29:32 +02:00
* @ param time pointer to an Ccs stream
* @ param length length of stream
2016-06-15 23:48:41 +02:00
* @ return
*/
2018-07-12 16:29:32 +02:00
static ReturnValue_t checkCcs ( const uint8_t * time , uint8_t length ) ;
static ReturnValue_t checkTimeOfDay ( const Clock : : TimeOfDay_t * time ) ;
2016-06-15 23:48:41 +02:00
static const uint32_t SECONDS_PER_DAY = 24 * 60 * 60 ;
static const uint32_t SECONDS_PER_NON_LEAP_YEAR = SECONDS_PER_DAY * 365 ;
static const uint32_t DAYS_CCSDS_TO_UNIX_EPOCH = 4383 ; //!< Time difference between CCSDS and POSIX epoch. This is exact, because leap-seconds where not introduced before 1972.
static const uint32_t SECONDS_CCSDS_TO_UNIX_EPOCH = DAYS_CCSDS_TO_UNIX_EPOCH
* SECONDS_PER_DAY ;
/**
* @ param dayofYear
* @ param year
* @ param month
* @ param day
*/
static ReturnValue_t convertDaysOfYear ( uint16_t dayofYear , uint16_t year ,
uint8_t * month , uint8_t * day ) ;
2018-07-12 16:29:32 +02:00
static bool isLeapYear ( uint32_t year ) ;
static ReturnValue_t convertTimevalToTimeOfDay ( Clock : : TimeOfDay_t * to ,
2016-06-15 23:48:41 +02:00
timeval * from ) ;
} ;
# endif /* CCSDSTIME_H_ */