updating code from Flying Laptop
This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
@ -1,11 +1,3 @@
|
||||
/*
|
||||
* CCSDSTime.cpp
|
||||
*
|
||||
* Created on: 22.03.2013
|
||||
* Author: tod
|
||||
*/
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/timemanager/CCSDSTime.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
@ -17,7 +9,12 @@ CCSDSTime::~CCSDSTime() {
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to,
|
||||
const TimeOfDay_t* from) {
|
||||
const Clock::TimeOfDay_t* from) {
|
||||
ReturnValue_t result = checkTimeOfDay(from);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
to->pField = (CCS << 4);
|
||||
|
||||
to->yearMSB = (from->year >> 8);
|
||||
@ -32,7 +29,12 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to,
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to,
|
||||
const TimeOfDay_t* from) {
|
||||
const Clock::TimeOfDay_t* from) {
|
||||
ReturnValue_t result = checkTimeOfDay(from);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
to->pField = (CCS << 4) + 2;
|
||||
|
||||
to->yearMSB = (from->year >> 8);
|
||||
@ -48,7 +50,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to,
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCcsds(TimeOfDay_t* to, const uint8_t* from,
|
||||
ReturnValue_t CCSDSTime::convertFromCcsds(Clock::TimeOfDay_t* to, const uint8_t* from,
|
||||
uint32_t length) {
|
||||
ReturnValue_t result;
|
||||
if (length > 0xFF) {
|
||||
@ -62,12 +64,11 @@ ReturnValue_t CCSDSTime::convertFromCcsds(TimeOfDay_t* to, const uint8_t* from,
|
||||
//Seems to be no ascii, try the other formats
|
||||
uint8_t codeIdentification = (*from >> 4);
|
||||
switch (codeIdentification) {
|
||||
case CUC_LEVEL1: //CUC_LEVEL2 can not be converted to TimeOfDay (ToD is Level 1) <- Well, if we know the epoch, we can...
|
||||
case CUC_LEVEL1: //CUC_LEVEL2 can not be converted to TimeOfDay (ToD is Level 1) <- Well, if we know the epoch, we can... <- see bug 1133
|
||||
return convertFromCUC(to, from, length);
|
||||
case CDS:
|
||||
return convertFromCDS(to, from, length);
|
||||
case CCS: {
|
||||
//SHOULDDO: Returning the actual found length is the right way to go, but for now, keep it.
|
||||
uint32_t temp = 0;
|
||||
return convertFromCCS(to, from, &temp, length);
|
||||
}
|
||||
@ -77,12 +78,12 @@ ReturnValue_t CCSDSTime::convertFromCcsds(TimeOfDay_t* to, const uint8_t* from,
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCUC(TimeOfDay_t* to, const uint8_t* from,
|
||||
ReturnValue_t CCSDSTime::convertFromCUC(Clock::TimeOfDay_t* to, const uint8_t* from,
|
||||
uint8_t length) {
|
||||
return UNSUPPORTED_TIME_FORMAT;
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCDS(TimeOfDay_t* to, const uint8_t* from,
|
||||
ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const uint8_t* from,
|
||||
uint8_t length) {
|
||||
timeval time;
|
||||
ReturnValue_t result = convertFromCDS(&time, from, NULL, length);
|
||||
@ -92,26 +93,30 @@ ReturnValue_t CCSDSTime::convertFromCDS(TimeOfDay_t* to, const uint8_t* from,
|
||||
return convertTimevalToTimeOfDay(to, &time);
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCCS(TimeOfDay_t* to, const uint8_t* from,
|
||||
ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from,
|
||||
uint32_t* foundLength, uint32_t maxLength) {
|
||||
uint8_t subsecondsLength = *from & 0b111;
|
||||
uint32_t totalLength = subsecondsLength + 8;
|
||||
if (maxLength < totalLength) {
|
||||
return LENGTH_MISMATCH;
|
||||
}
|
||||
//TODO: Check this!
|
||||
Ccs_mseconds *temp = (Ccs_mseconds *) from;
|
||||
|
||||
if (checkCcs((Ccs_seconds *) from) != RETURN_OK) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
*foundLength = totalLength;
|
||||
|
||||
ReturnValue_t result = checkCcs(from, maxLength);
|
||||
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Ccs_mseconds *temp = (Ccs_mseconds *) from;
|
||||
|
||||
to->year = (temp->yearMSB << 8) + temp->yearLSB;
|
||||
to->hour = temp->hour;
|
||||
to->minute = temp->minute;
|
||||
to->second = temp->second;
|
||||
|
||||
if (*from & (1 << 3)) { //day of year variation
|
||||
if (temp->pField & (1 << 3)) { //day of year variation
|
||||
uint16_t tempDay = (temp->month << 8) + temp->day;
|
||||
ReturnValue_t result = convertDaysOfYear(tempDay, to->year,
|
||||
&(temp->month), &(temp->day));
|
||||
@ -124,7 +129,6 @@ ReturnValue_t CCSDSTime::convertFromCCS(TimeOfDay_t* to, const uint8_t* from,
|
||||
to->day = temp->day;
|
||||
|
||||
to->ticks = 0;
|
||||
*foundLength = sizeof(Ccs_seconds);
|
||||
if (subsecondsLength > 0) {
|
||||
*foundLength += 1;
|
||||
if (temp->secondEminus2 >= 100) {
|
||||
@ -145,7 +149,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(TimeOfDay_t* to, const uint8_t* from,
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromASCII(TimeOfDay_t* to, const uint8_t* from,
|
||||
ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* from,
|
||||
uint8_t length) {
|
||||
if (length < 19) {
|
||||
return RETURN_FAILED;
|
||||
@ -175,8 +179,8 @@ ReturnValue_t CCSDSTime::convertFromASCII(TimeOfDay_t* to, const uint8_t* from,
|
||||
&hour, &minute, &second);
|
||||
if (count == 5) {
|
||||
uint8_t tempDay;
|
||||
ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year,
|
||||
&month, &tempDay);
|
||||
ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, &month,
|
||||
&tempDay);
|
||||
if (result != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
@ -193,29 +197,44 @@ ReturnValue_t CCSDSTime::convertFromASCII(TimeOfDay_t* to, const uint8_t* from,
|
||||
return UNSUPPORTED_TIME_FORMAT;
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::checkCcs(Ccs_seconds* time) {
|
||||
if (time->pField & (1 << 3)) { //day of year variation
|
||||
uint16_t day = (time->month << 8) + time->day;
|
||||
ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) {
|
||||
Ccs_mseconds *time_struct = (Ccs_mseconds *) time;
|
||||
|
||||
uint8_t additionalBytes = time_struct->pField & 0b111;
|
||||
if ((additionalBytes == 0b111) || (length < (additionalBytes + 8))) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
if (time_struct->pField & (1 << 3)) { //day of year variation
|
||||
uint16_t day = (time_struct->month << 8) + time_struct->day;
|
||||
if (day > 366) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
} else {
|
||||
if (time->month > 12) {
|
||||
if (time_struct->month > 12) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
if (time->day > 31) {
|
||||
if (time_struct->day > 31) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
}
|
||||
if (time->hour > 23) {
|
||||
if (time_struct->hour > 23) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
if (time->minute > 59) {
|
||||
if (time_struct->minute > 59) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
if (time->second > 59) {
|
||||
if (time_struct->second > 59) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
uint8_t *additionalByte = &time_struct->secondEminus2;
|
||||
|
||||
for (; additionalBytes != 0; additionalBytes--) {
|
||||
if (*additionalByte++ > 99) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
@ -260,6 +279,10 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year,
|
||||
*month += 1;
|
||||
dayofYear -= 31;
|
||||
|
||||
if (*month == 8) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dayofYear <= 30) {
|
||||
*day = dayofYear;
|
||||
return RETURN_OK;
|
||||
@ -270,7 +293,7 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year,
|
||||
return INVALID_DAY_OF_YEAR;
|
||||
}
|
||||
|
||||
bool CCSDSTime::isLeapYear(uint16_t year) {
|
||||
bool CCSDSTime::isLeapYear(uint32_t year) {
|
||||
if ((year % 400) == 0) {
|
||||
return true;
|
||||
}
|
||||
@ -322,11 +345,12 @@ ReturnValue_t CCSDSTime::convertToCcsds(OBT_FLP* to, const timeval* from) {
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCcsds(timeval* to, const uint8_t* from,
|
||||
uint32_t* foundLength, uint32_t maxLength) {
|
||||
//We don't expect ascii here.
|
||||
//We don't expect ascii here. SHOULDDO
|
||||
uint8_t codeIdentification = (*from >> 4);
|
||||
switch (codeIdentification) {
|
||||
case CUC_LEVEL1:
|
||||
return convertFromCUC(to, from, foundLength, maxLength);
|
||||
//unsupported, as Leap second correction would have to be applied
|
||||
// case CUC_LEVEL1:
|
||||
// return convertFromCUC(to, from, foundLength, maxLength);
|
||||
case CDS:
|
||||
return convertFromCDS(to, from, foundLength, maxLength);
|
||||
case CCS:
|
||||
@ -335,7 +359,6 @@ ReturnValue_t CCSDSTime::convertFromCcsds(timeval* to, const uint8_t* from,
|
||||
return UNSUPPORTED_TIME_FORMAT;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from,
|
||||
@ -345,7 +368,8 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from,
|
||||
}
|
||||
uint8_t pField = *from;
|
||||
from++;
|
||||
ReturnValue_t result = convertFromCUC(to, pField, from, foundLength, maxLength-1 );
|
||||
ReturnValue_t result = convertFromCUC(to, pField, from, foundLength,
|
||||
maxLength - 1);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (foundLength != NULL) {
|
||||
*foundLength += 1;
|
||||
@ -354,9 +378,64 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from,
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(TimeOfDay_t* to,
|
||||
ReturnValue_t CCSDSTime::checkTimeOfDay(const Clock::TimeOfDay_t* time) {
|
||||
if ((time->month > 12) || (time->month == 0)) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
if (time->day == 0) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
switch (time->month) {
|
||||
case 2:
|
||||
if (isLeapYear(time->year)) {
|
||||
if (time->day > 29) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
} else {
|
||||
if (time->day > 28) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
if (time->day > 30) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (time->day > 31) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (time->hour > 23) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
if (time->minute > 59) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
if (time->second > 59) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
if (time->ticks > 999) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to,
|
||||
timeval* from) {
|
||||
//TODO: This is rather tricky. Implement only if needed. Also, if so, move to OSAL.
|
||||
//This is rather tricky. Implement only if needed. Also, if so, move to OSAL.
|
||||
return UNSUPPORTED_TIME_FORMAT;
|
||||
}
|
||||
|
||||
@ -364,11 +443,11 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from,
|
||||
uint32_t* foundLength, uint32_t maxLength) {
|
||||
uint8_t pField = *from;
|
||||
from++;
|
||||
//Check epoch
|
||||
//Check epoch
|
||||
if (pField & 0b1000) {
|
||||
return NOT_ENOUGH_INFORMATION_FOR_TARGET_FORMAT;
|
||||
}
|
||||
//Check length
|
||||
//Check length
|
||||
uint8_t expectedLength = 7; //Including p-Field.
|
||||
bool extendedDays = pField & 0b100;
|
||||
if (extendedDays) {
|
||||
@ -385,34 +464,36 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from,
|
||||
if (expectedLength > maxLength) {
|
||||
return LENGTH_MISMATCH;
|
||||
}
|
||||
//Check and count days
|
||||
//Check and count days
|
||||
uint32_t days = 0;
|
||||
if (extendedDays) {
|
||||
days = (from[0] << 16) + (from[1] << 8) + from[2];
|
||||
from +=3;
|
||||
from += 3;
|
||||
} else {
|
||||
days = (from[0] << 8) + from[1];
|
||||
from +=2;
|
||||
from += 2;
|
||||
}
|
||||
//Move to POSIX epoch.
|
||||
//Move to POSIX epoch.
|
||||
if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
days -= DAYS_CCSDS_TO_UNIX_EPOCH;
|
||||
to->tv_sec = days * SECONDS_PER_DAY;
|
||||
uint32_t msDay = (from[0] << 24) + (from[1] << 16) + (from[2] << 8) + from[3];
|
||||
from +=4;
|
||||
uint32_t msDay = (from[0] << 24) + (from[1] << 16) + (from[2] << 8)
|
||||
+ from[3];
|
||||
from += 4;
|
||||
to->tv_sec += (msDay / 1000);
|
||||
to->tv_usec = (msDay%1000)*1000;
|
||||
if ((pField & 0b11) == 0b01 ) {
|
||||
to->tv_usec = (msDay % 1000) * 1000;
|
||||
if ((pField & 0b11) == 0b01) {
|
||||
uint16_t usecs = (from[0] << 16) + from[1];
|
||||
from += 2;
|
||||
if (usecs > 999) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
}
|
||||
to->tv_usec += usecs;
|
||||
} else if ((pField & 0b11) == 0b10 ) {
|
||||
uint32_t picosecs = (from[0] << 24) + (from[1] << 16) + (from[2] << 8) + from[3];
|
||||
} else if ((pField & 0b11) == 0b10) {
|
||||
uint32_t picosecs = (from[0] << 24) + (from[1] << 16) + (from[2] << 8)
|
||||
+ from[3];
|
||||
from += 4;
|
||||
if (picosecs > 999999) {
|
||||
return INVALID_TIME_FORMAT;
|
||||
@ -429,7 +510,7 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField,
|
||||
uint32_t subSeconds = 0;
|
||||
uint8_t nCoarse = ((pField & 0b1100) >> 2) + 1;
|
||||
uint8_t nFine = (pField & 0b11);
|
||||
uint32_t totalLength = nCoarse+nFine;
|
||||
uint32_t totalLength = nCoarse + nFine;
|
||||
if (foundLength != NULL) {
|
||||
*foundLength = totalLength;
|
||||
}
|
||||
@ -437,11 +518,11 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField,
|
||||
return LENGTH_MISMATCH;
|
||||
}
|
||||
for (int count = 0; count < nCoarse; count++) {
|
||||
secs += *from << ((nCoarse*8-8)*(1+count));
|
||||
secs += *from << ((nCoarse * 8 - 8) * (1 + count));
|
||||
from++;
|
||||
}
|
||||
for (int count = 0; count < nFine; count++) {
|
||||
subSeconds += *from << ((nFine*8-8)*(1+count));
|
||||
subSeconds += *from << ((nFine * 8 - 8) * (1 + count));
|
||||
from++;
|
||||
}
|
||||
//Move to POSIX epoch.
|
||||
@ -450,22 +531,25 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField,
|
||||
//CCSDS-Epoch
|
||||
to->tv_sec -= (DAYS_CCSDS_TO_UNIX_EPOCH * SECONDS_PER_DAY);
|
||||
}
|
||||
to->tv_usec = subsecondsToMicroseconds(subSeconds);
|
||||
to->tv_usec = subsecondsToMicroseconds(subSeconds);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
uint32_t CCSDSTime::subsecondsToMicroseconds(uint16_t subseconds) {
|
||||
uint64_t temp = (uint64_t)subseconds * 1000000 / (1 << (sizeof(subseconds)*8));
|
||||
uint64_t temp = (uint64_t) subseconds * 1000000
|
||||
/ (1 << (sizeof(subseconds) * 8));
|
||||
return temp;
|
||||
}
|
||||
|
||||
ReturnValue_t CCSDSTime::convertFromCCS(timeval* to, const uint8_t* from,
|
||||
uint32_t* foundLength, uint32_t maxLength) {
|
||||
TimeOfDay_t tempTime;
|
||||
ReturnValue_t result = convertFromCCS(&tempTime,from, foundLength, maxLength);
|
||||
Clock::TimeOfDay_t tempTime;
|
||||
ReturnValue_t result = convertFromCCS(&tempTime, from, foundLength,
|
||||
maxLength);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return OSAL::convertTimeOfDayToTimeval(&tempTime, to);
|
||||
|
||||
return Clock::convertTimeOfDayToTimeval(&tempTime, to);
|
||||
|
||||
}
|
||||
|
@ -1,25 +1,19 @@
|
||||
/*
|
||||
* CCSDSTimeHelper.h
|
||||
*
|
||||
* Created on: 22.03.2013
|
||||
* Author: tod
|
||||
*/
|
||||
|
||||
#ifndef CCSDSTIME_H_
|
||||
#define CCSDSTIME_H_
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool operator<(const timeval& lhs, const timeval& rhs);
|
||||
bool operator<=(const timeval& lhs, const timeval& rhs);
|
||||
bool operator==(const timeval& lhs, const timeval& rhs);
|
||||
/**
|
||||
* static helper class for CCSDS Time Code Formats
|
||||
*
|
||||
* as described in CCSDS 301.0-B-3
|
||||
*
|
||||
* Still work in progress thus TODO finishme
|
||||
* Still work in progress
|
||||
*/
|
||||
class CCSDSTime: public HasReturnvaluesIF {
|
||||
public:
|
||||
@ -37,6 +31,7 @@ public:
|
||||
+ 2;
|
||||
static const uint8_t P_FIELD_CUC_6B_AGENCY = (CUC_LEVEL2 << 4) + (3 << 2)
|
||||
+ 2;
|
||||
static const uint8_t P_FIELD_CDS_SHORT = (CDS << 4);
|
||||
/**
|
||||
* Struct for CDS day-segmented format.
|
||||
*/
|
||||
@ -50,7 +45,7 @@ public:
|
||||
uint8_t msDay_ll;
|
||||
};
|
||||
/**
|
||||
* Struct for the CCS fromat in day of month variation with seconds resolution
|
||||
* Struct for the CCS fromat in day of month variation with max resolution
|
||||
*/
|
||||
struct Ccs_seconds {
|
||||
uint8_t pField;
|
||||
@ -95,7 +90,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static const uint8_t INTERFACE_ID = CCSDS_TIME_HELPER_CLASS;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_TIME_HELPER_CLASS;
|
||||
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);
|
||||
@ -107,15 +102,14 @@ public:
|
||||
/**
|
||||
* convert a TimeofDay struct to ccs with seconds resolution
|
||||
*
|
||||
* Assumes a valid TimeOfDay. TODO: maybe check it anyway?
|
||||
*
|
||||
* @param to pointer to a CCS struct
|
||||
* @param from pointer to a TimeOfDay Struct
|
||||
* @return
|
||||
* - @c RETURN_OK as it assumes a valid TimeOfDay
|
||||
* - @c RETURN_OK if OK
|
||||
* - @c INVALID_TIMECODE if not OK
|
||||
*/
|
||||
static ReturnValue_t convertToCcsds(Ccs_seconds *to,
|
||||
TimeOfDay_t const *from);
|
||||
Clock::TimeOfDay_t const *from);
|
||||
|
||||
/**
|
||||
* Converts to CDS format from timeval.
|
||||
@ -127,23 +121,23 @@ public:
|
||||
static ReturnValue_t convertToCcsds(CDS_short* to, timeval const *from);
|
||||
|
||||
static ReturnValue_t convertToCcsds(OBT_FLP* to, timeval const *from);
|
||||
|
||||
/**
|
||||
* convert a TimeofDay struct to ccs with 10E-3 seconds resolution
|
||||
*
|
||||
* Assumes a valid TimeOfDay. TODO: maybe check it anyway?
|
||||
*
|
||||
* 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
|
||||
* - @c RETURN_OK as it assumes a valid TimeOfDay
|
||||
* - @c RETURN_OK if OK
|
||||
* - @c INVALID_TIMECODE if not OK
|
||||
*/
|
||||
static ReturnValue_t convertToCcsds(Ccs_mseconds *to,
|
||||
TimeOfDay_t const *from);
|
||||
Clock::TimeOfDay_t const *from);
|
||||
|
||||
/**
|
||||
* TODO: can this be modified to recognize padding?
|
||||
* SHOULDDO: can this be modified to recognize padding?
|
||||
* Tries to interpret a Level 1 CCSDS time code
|
||||
*
|
||||
* It assumes binary formats contain a valid P Field and recognizes the ASCII format
|
||||
@ -154,11 +148,11 @@ public:
|
||||
* @param length length of the Time code
|
||||
* @return
|
||||
* - @c RETURN_OK if successful
|
||||
* - @c UNSUPPORTED_TIME_FORMAT if a (possibly valid) time code is not supported TODO: the missing codes should be implemented...
|
||||
* - @c UNSUPPORTED_TIME_FORMAT if a (possibly valid) time code is not supported
|
||||
* - @c LENGTH_MISMATCH if the length does not match the P Field
|
||||
* - @c INVALID_TIME_FORMAT if the format or a value is invalid
|
||||
*/
|
||||
static ReturnValue_t convertFromCcsds(TimeOfDay_t *to, uint8_t const *from,
|
||||
static ReturnValue_t convertFromCcsds(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||
uint32_t length);
|
||||
|
||||
/**
|
||||
@ -171,7 +165,7 @@ public:
|
||||
static ReturnValue_t convertFromCcsds(timeval *to, uint8_t const *from,
|
||||
uint32_t* foundLength, uint32_t maxLength);
|
||||
|
||||
static ReturnValue_t convertFromCUC(TimeOfDay_t *to, uint8_t const *from,
|
||||
static ReturnValue_t convertFromCUC(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||
uint8_t length);
|
||||
|
||||
static ReturnValue_t convertFromCUC(timeval *to, uint8_t const *from,
|
||||
@ -186,16 +180,16 @@ public:
|
||||
static ReturnValue_t convertFromCCS(timeval *to, uint8_t pField,
|
||||
uint8_t const *from, uint32_t* foundLength, uint32_t maxLength);
|
||||
|
||||
static ReturnValue_t convertFromCDS(TimeOfDay_t *to, uint8_t const *from,
|
||||
static ReturnValue_t convertFromCDS(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||
uint8_t length);
|
||||
|
||||
static ReturnValue_t convertFromCDS(timeval *to, uint8_t const *from,
|
||||
uint32_t* foundLength, uint32_t maxLength);
|
||||
|
||||
static ReturnValue_t convertFromCCS(TimeOfDay_t *to, uint8_t const *from,
|
||||
static ReturnValue_t convertFromCCS(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||
uint32_t* foundLength, uint32_t maxLength);
|
||||
|
||||
static ReturnValue_t convertFromASCII(TimeOfDay_t *to, uint8_t const *from,
|
||||
static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||
uint8_t length);
|
||||
|
||||
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
|
||||
@ -203,14 +197,17 @@ private:
|
||||
CCSDSTime();
|
||||
virtual ~CCSDSTime();
|
||||
/**
|
||||
* checks a ccs time struct for validity
|
||||
* checks a ccs time stream for validity
|
||||
*
|
||||
* only checks year to second, subseconds must be checked elsewhere
|
||||
* Stream may be longer than the actual timecode
|
||||
*
|
||||
* @param time pointer to an Ccs struct (should be cast to Ccs_seconds as subseconds are not checked. Cast is save as subseconds are at the end of the struct)
|
||||
* @param time pointer to an Ccs stream
|
||||
* @param length length of stream
|
||||
* @return
|
||||
*/
|
||||
static ReturnValue_t checkCcs(Ccs_seconds *time);
|
||||
static ReturnValue_t checkCcs(const uint8_t* time, uint8_t length);
|
||||
|
||||
static ReturnValue_t checkTimeOfDay(const Clock::TimeOfDay_t *time);
|
||||
|
||||
static const uint32_t SECONDS_PER_DAY = 24 * 60 * 60;
|
||||
static const uint32_t SECONDS_PER_NON_LEAP_YEAR = SECONDS_PER_DAY * 365;
|
||||
@ -226,8 +223,8 @@ private:
|
||||
static ReturnValue_t convertDaysOfYear(uint16_t dayofYear, uint16_t year,
|
||||
uint8_t *month, uint8_t *day);
|
||||
|
||||
static bool isLeapYear(uint16_t year);
|
||||
static ReturnValue_t convertTimevalToTimeOfDay(TimeOfDay_t* to,
|
||||
static bool isLeapYear(uint32_t year);
|
||||
static ReturnValue_t convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to,
|
||||
timeval* from);
|
||||
};
|
||||
|
||||
|
145
timemanager/Clock.h
Normal file
145
timemanager/Clock.h
Normal file
@ -0,0 +1,145 @@
|
||||
#ifndef FRAMEWORK_TIMEMANAGER_CLOCK_H_
|
||||
#define FRAMEWORK_TIMEMANAGER_CLOCK_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
#include <framework/globalfunctions/timevalOperations.h>
|
||||
|
||||
|
||||
|
||||
class Clock {
|
||||
public:
|
||||
typedef struct {
|
||||
uint32_t year; //!< Year, A.D.
|
||||
uint32_t month; //!< Month, 1 .. 12.
|
||||
uint32_t day; //!< Day, 1 .. 31.
|
||||
uint32_t hour; //!< Hour, 0 .. 23.
|
||||
uint32_t minute; //!< Minute, 0 .. 59.
|
||||
uint32_t second; //!< Second, 0 .. 59.
|
||||
uint32_t ticks; //!< Elapsed ticks between seconds.
|
||||
} TimeOfDay_t;
|
||||
|
||||
/**static Clock* TimeOfDay_t();
|
||||
* This method returns the number of clock ticks per second.
|
||||
* In RTEMS, this is typically 1000.
|
||||
* @return The number of ticks.
|
||||
*/
|
||||
static uint32_t getTicksPerSecond(void);
|
||||
/**
|
||||
* This system call sets the system time.
|
||||
* To set the time, it uses a TimeOfDay_t struct.
|
||||
* @param time The struct with the time settings to set.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t setClock(const TimeOfDay_t* time);
|
||||
/**
|
||||
* This system call sets the system time.
|
||||
* To set the time, it uses a timeval struct.
|
||||
* @param time The struct with the time settings to set.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t setClock(const timeval* time);
|
||||
/**
|
||||
* This system call returns the current system clock in timeval format.
|
||||
* The timval format has the fields \c tv_sec with seconds and \c tv_usec with
|
||||
* microseconds since an OS-defined epoch.
|
||||
* @param time A pointer to a timeval struct where the current time is stored.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getClock_timeval(timeval* time);
|
||||
|
||||
/**
|
||||
* Get the time since boot in a timeval struct
|
||||
*
|
||||
* @param[out] time A pointer to a timeval struct where the uptime is stored.
|
||||
* @return\c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getUptime(timeval* uptime);
|
||||
|
||||
/**
|
||||
* Get the time since boot in milliseconds
|
||||
*
|
||||
* This value can overflow! Still, it can be used to calculate time intervalls
|
||||
* between two calls up to 49 days by always using uint32_t in the calculation
|
||||
*
|
||||
* @param ms uptime in ms
|
||||
* @return RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getUptime(uint32_t* uptimeMs);
|
||||
|
||||
/**
|
||||
* Returns the time in microseconds since an OS-defined epoch.
|
||||
* The time is returned in a 64 bit unsigned integer.
|
||||
* @param time A pointer to a 64 bit unisigned integer where the data is stored.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getClock_usecs(uint64_t* time);
|
||||
/**
|
||||
* Returns the time in a TimeOfDay_t struct.
|
||||
* @param time A pointer to a TimeOfDay_t struct.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getDateAndTime(TimeOfDay_t* time);
|
||||
|
||||
/**
|
||||
* Converts a time of day struct to POSIX seconds.
|
||||
* @param time The time of day as input
|
||||
* @param timeval The corresponding seconds since the epoch.
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t convertTimeOfDayToTimeval(const TimeOfDay_t* from,
|
||||
timeval* to);
|
||||
|
||||
/**
|
||||
* Converts a time represented as seconds and subseconds since unix epoch to days since J2000
|
||||
*
|
||||
* @param time seconds since unix epoch
|
||||
* @param[out] JD2000 days since J2000
|
||||
* @return \c RETURN_OK
|
||||
*/
|
||||
static ReturnValue_t convertTimevalToJD2000(timeval time, double* JD2000);
|
||||
|
||||
/**
|
||||
* Calculates and adds the offset between UTC and TT
|
||||
*
|
||||
* Depends on the leap seconds to be set correctly.
|
||||
*
|
||||
* @param utc timeval, corresponding to UTC time
|
||||
* @param[out] tt timeval, corresponding to Terrestial Time
|
||||
* @return \c RETURN_OK on success, \c RETURN_FAILED if leapSeconds are not set
|
||||
*/
|
||||
static ReturnValue_t convertUTCToTT(timeval utc, timeval* tt);
|
||||
|
||||
/**
|
||||
* Set the Leap Seconds since 1972
|
||||
*
|
||||
* @param leapSeconds_
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t setLeapSeconds(const uint16_t leapSeconds_);
|
||||
|
||||
/**
|
||||
* Get the Leap Seconds since 1972
|
||||
*
|
||||
* Must be set before!
|
||||
*
|
||||
* @param[out] leapSeconds_
|
||||
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned.
|
||||
*/
|
||||
static ReturnValue_t getLeapSeconds(uint16_t *leapSeconds_);
|
||||
|
||||
/**
|
||||
* Function to check and create the Mutex for the clock
|
||||
* @return \c RETURN_OK on success. Otherwise \c RETURN_FAILED if not able to create one
|
||||
*/
|
||||
static ReturnValue_t checkOrCreateClockMutex();
|
||||
|
||||
private:
|
||||
static MutexIF* timeMutex;
|
||||
static uint16_t leapSeconds;
|
||||
};
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_TIMEMANAGER_CLOCK_H_ */
|
@ -15,14 +15,14 @@ Countdown::~Countdown() {
|
||||
}
|
||||
|
||||
ReturnValue_t Countdown::setTimeout(uint32_t miliseconds) {
|
||||
ReturnValue_t return_value = OSAL::getUptime( &startTime );
|
||||
ReturnValue_t return_value = Clock::getUptime( &startTime );
|
||||
timeout = miliseconds;
|
||||
return return_value;
|
||||
}
|
||||
|
||||
bool Countdown::hasTimedOut() const {
|
||||
uint32_t current_time;
|
||||
OSAL::getUptime( ¤t_time );
|
||||
Clock::getUptime( ¤t_time );
|
||||
if ( uint32_t(current_time - startTime) >= timeout) {
|
||||
return true;
|
||||
} else {
|
||||
@ -37,3 +37,9 @@ bool Countdown::isBusy() const {
|
||||
ReturnValue_t Countdown::resetTimer() {
|
||||
return setTimeout(timeout);
|
||||
}
|
||||
|
||||
void Countdown::timeOut() {
|
||||
uint32_t current_time;
|
||||
Clock::getUptime( ¤t_time );
|
||||
startTime= current_time - timeout;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#ifndef COUNTDOWN_H_
|
||||
#define COUNTDOWN_H_
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
|
||||
class Countdown {
|
||||
private:
|
||||
@ -24,6 +24,8 @@ public:
|
||||
bool isBusy() const;
|
||||
|
||||
ReturnValue_t resetTimer(); //!< Use last set timeout value and restart timer.
|
||||
|
||||
void timeOut(); //!< Make hasTimedOut() return true
|
||||
};
|
||||
|
||||
#endif /* COUNTDOWN_H_ */
|
||||
|
@ -8,7 +8,6 @@
|
||||
#ifndef RECEIVESTIMEINFOIF_H_
|
||||
#define RECEIVESTIMEINFOIF_H_
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
/**
|
||||
* This is a Interface for classes that receive timing information
|
||||
* with the help of a dedicated message queue.
|
||||
@ -19,7 +18,7 @@ public:
|
||||
* Returns the id of the queue which receives the timing information.
|
||||
* @return Queue id of the timing queue.
|
||||
*/
|
||||
virtual MessageQueueId_t getTimeReceptionQueue() = 0;
|
||||
virtual MessageQueueId_t getTimeReceptionQueue() const = 0;
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
|
@ -8,12 +8,13 @@
|
||||
#include <framework/timemanager/TimeMessage.h>
|
||||
|
||||
TimeMessage::TimeMessage() {
|
||||
this->messageSize += sizeof(timeval);
|
||||
this->messageSize += sizeof(timeval) + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
TimeMessage::TimeMessage(timeval setTime) {
|
||||
TimeMessage::TimeMessage(timeval setTime, uint32_t CounterValue) {
|
||||
memcpy (this->getData(), &setTime, sizeof(timeval));
|
||||
this->messageSize += sizeof(timeval);
|
||||
this->messageSize += sizeof(timeval) + sizeof(uint32_t);
|
||||
memcpy (this->getData() + sizeof(timeval), &CounterValue, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
TimeMessage::~TimeMessage() {
|
||||
@ -25,6 +26,12 @@ timeval TimeMessage::getTime() {
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint32_t TimeMessage::getCounterValue() {
|
||||
uint32_t temp;
|
||||
memcpy ( &temp, this->getData() + sizeof(timeval), sizeof(uint32_t));
|
||||
return temp;
|
||||
}
|
||||
|
||||
size_t TimeMessage::getMinimumMessageSize() {
|
||||
return this->MAX_SIZE;
|
||||
}
|
||||
|
@ -9,12 +9,14 @@
|
||||
#define TIMEMESSAGE_H_
|
||||
|
||||
#include <framework/ipc/MessageQueueMessage.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
#include <cstring>
|
||||
|
||||
class TimeMessage : public MessageQueueMessage {
|
||||
protected:
|
||||
/**
|
||||
* @brief This call always returns the same fixed size of the message.
|
||||
* @return Returns HEADER_SIZE + \c sizeof(timeval).
|
||||
* @return Returns HEADER_SIZE + \c sizeof(timeval) + sizeof(uint32_t).
|
||||
*/
|
||||
size_t getMinimumMessageSize();
|
||||
public:
|
||||
@ -22,7 +24,7 @@ public:
|
||||
/**
|
||||
* @ brief the size of a TimeMessage
|
||||
*/
|
||||
static const uint32_t MAX_SIZE = HEADER_SIZE + sizeof(timeval);
|
||||
static const uint32_t MAX_SIZE = HEADER_SIZE + sizeof(timeval) + sizeof(uint32_t);
|
||||
|
||||
/**
|
||||
* @brief In the default constructor, only the message_size is set.
|
||||
@ -31,9 +33,10 @@ public:
|
||||
/**
|
||||
* @brief With this constructor, the passed time information is directly put
|
||||
* into the message.
|
||||
* @param setTime The time information to put into the message.
|
||||
* @param setTime The time information to put into the message.
|
||||
* @param counterValue The counterValue to put into the message (GPS PPS).
|
||||
*/
|
||||
TimeMessage( timeval setTime );
|
||||
TimeMessage( timeval setTime, uint32_t counterValue = 0 );
|
||||
/**
|
||||
* @brief The class's destructor is empty.
|
||||
*/
|
||||
@ -43,6 +46,11 @@ public:
|
||||
* @return Returns the time stored in this packet.
|
||||
*/
|
||||
timeval getTime();
|
||||
/**
|
||||
* @brief This getter returns the CounterValue in uint32_t format.
|
||||
* @return Returns the CounterValue stored in this packet.
|
||||
*/
|
||||
uint32_t getCounterValue();
|
||||
};
|
||||
|
||||
#endif /* TIMEMESSAGE_H_ */
|
||||
|
@ -1,17 +1,19 @@
|
||||
/*
|
||||
* TimeStamperIF.h
|
||||
*
|
||||
* Created on: 31.03.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_TIMEMANAGER_TIMESTAMPERIF_H_
|
||||
#define FRAMEWORK_TIMEMANAGER_TIMESTAMPERIF_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
/**
|
||||
* A class implementing this IF provides facilities to add a time stamp to the
|
||||
* buffer provided.
|
||||
* Implementors need to ensure that calling the method is thread-safe, i.e.
|
||||
* addTimeStamp may be called in parallel from a different context.
|
||||
*/
|
||||
class TimeStamperIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::TIME_STAMPER_IF;
|
||||
static const ReturnValue_t BAD_TIMESTAMP = MAKE_RETURN_CODE(1);
|
||||
|
||||
static const uint8_t MISSION_TIMESTAMP_SIZE = 8; //!< This is a mission-specific constant and determines the total size reserved for timestamps.
|
||||
virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize) = 0;
|
||||
virtual ~TimeStamperIF() {}
|
||||
|
Reference in New Issue
Block a user