1
0
forked from fsfw/fsfw

updating code from Flying Laptop

This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
2018-07-12 16:29:32 +02:00
parent 1d22a6c97e
commit 575f70ba03
395 changed files with 12807 additions and 8404 deletions

View File

@ -1,24 +0,0 @@
#!/bin/bash
#
# OSAL makefile
#
# Created on: Mar 04, 2010
# Author: ziemke
# Author: Claas Ziemke
# Copyright 2010, Claas Ziemke <claas.ziemke@gmx.net>
#
BASEDIR=../../
include $(BASEDIR)options.mk
OBJ = $(BUILDDIR)/SpacePacketBase.o \
$(BUILDDIR)/SpacePacket.o
all: $(OBJ)
$(BUILDDIR)/%.o: %.cpp %.h
$(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@
clean:
$(RM) *.o *.gcno *.gcda

View File

@ -1,28 +1,16 @@
/*
* SpacePacket.cpp
*
* Created on: Mar 23, 2012
* Author: baetz
*/
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/ccsds_header.h>
#include <framework/tmtcpacket/SpacePacket.h>
#include <string.h>
SpacePacket::SpacePacket( uint16_t set_packet_data_length, uint8_t set_type, uint16_t new_apid, uint16_t set_count ):
SpacePacketBase( (uint8_t*)&this->local_data ) {
//reset everything to zero:
memset(this->local_data.byteStream,0 , sizeof(this->local_data.byteStream) );
//Primary header:
this->local_data.fields.header.packet_id_h = 0b00000000 + ( (set_type & 0b1) << 4 );
this->setAPID( new_apid );
this->local_data.fields.header.sequence_control_h = 0b11000000;
this->setPacketSequenceCount(set_count);
if ( set_packet_data_length <= sizeof(this->local_data.fields.buffer) ) {
this->setPacketDataLength(set_packet_data_length);
SpacePacket::SpacePacket( uint16_t packetDataLength, bool isTelecommand, uint16_t apid, uint16_t sequenceCount ):
SpacePacketBase( (uint8_t*)&this->localData ) {
initSpacePacketHeader(isTelecommand, false, apid, sequenceCount);
this->setPacketSequenceCount(sequenceCount);
if ( packetDataLength <= sizeof(this->localData.fields.buffer) ) {
this->setPacketDataLength(packetDataLength);
} else {
this->setPacketDataLength( sizeof(this->local_data.fields.buffer) );
this->setPacketDataLength( sizeof(this->localData.fields.buffer) );
}
}
@ -31,7 +19,7 @@ SpacePacket::~SpacePacket( void ) {
bool SpacePacket::addWholeData( const uint8_t* p_Data, uint32_t packet_size ) {
if ( packet_size <= sizeof(this->data) ) {
memcpy( &this->local_data.byteStream, p_Data, packet_size );
memcpy( &this->localData.byteStream, p_Data, packet_size );
return true;
} else {
return false;

View File

@ -13,21 +13,19 @@
* so the parent's methods are reachable.
* @ingroup tmtcpackets
*/
class SpacePacket : public SpacePacketBase {
public:
static const uint16_t PACKET_MAX_SIZE = 1024;
class SpacePacket: public SpacePacketBase {
public:
static const uint16_t PACKET_MAX_SIZE = 1024;
/**
* The constructor initializes the packet and sets all header information
* according to the passed parameters.
* @param set_packet_data_length Sets the packet data length field and
* therefore specifies the size of the packet.
* @param set_type Sets the packet type field to either 0 (TM) or 1 (TC).
* @param set_apid Sets the packet's APID field. The default value
* describes an idle packet.
* @param set_sequence_count Sets the packet's Source Sequence Count
* field.
* @param packetDataLength Sets the packet data length field and therefore specifies the size of the packet.
* @param isTelecommand Sets the packet type field to either TC (true) or TM (false).
* @param apid Sets the packet's APID field. The default value describes an idle packet.
* @param sequenceCount ets the packet's Source Sequence Count field.
*/
SpacePacket( uint16_t set_packet_data_length, uint8_t set_type = 0, uint16_t set_apid = APID_IDLE_PACKET, uint16_t set_sequence_count = 0 );
SpacePacket(uint16_t packetDataLength, bool isTelecommand = false,
uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0);
/**
* The class's default destructor.
*/
@ -40,7 +38,7 @@ class SpacePacket : public SpacePacketBase {
* @return @li \c true if packet_size is smaller than \c MAX_PACKET_SIZE.
* @li \c false else.
*/
bool addWholeData( const uint8_t* p_data, uint32_t packet_size );
bool addWholeData(const uint8_t* p_data, uint32_t packet_size);
protected:
/**
* This structure defines the data structure of a Space Packet as local data.
@ -66,7 +64,7 @@ protected:
* packed in an union, so the data can be accessed as a byte stream without
* a cast.
*/
SpacePacketData local_data;
SpacePacketData localData;
};
#endif /* SPACEPACKET_H_ */

View File

@ -1,11 +1,7 @@
/*
* SpacePacketBase.cpp
*
* Created on: 21.03.2012
* Author: baetz
*/
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/SpacePacketBase.h>
#include <string.h>
SpacePacketBase::SpacePacketBase( const uint8_t* set_address ) {
this->data = (SpacePacketPointer*) set_address;
}
@ -18,6 +14,20 @@ uint8_t SpacePacketBase::getPacketVersionNumber( void ) {
return (this->data->header.packet_id_h & 0b11100000) >> 5;
}
void SpacePacketBase::initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount) {
//reset header to zero:
memset(data,0, sizeof(this->data->header) );
//Set TC/TM bit.
data->header.packet_id_h = ((isTelecommand? 1 : 0)) << 4;
//Set secondaryHeader bit
data->header.packet_id_h |= ((hasSecondaryHeader? 1 : 0)) << 3;
this->setAPID( apid );
//Always initialize as standalone packets.
data->header.sequence_control_h = 0b11000000;
setPacketSequenceCount(sequenceCount);
}
bool SpacePacketBase::isTelecommand( void ) {
return (this->data->header.packet_id_h & 0b00010000) >> 4;
}
@ -31,7 +41,7 @@ uint16_t SpacePacketBase::getPacketId() {
this->data->header.packet_id_l;
}
uint16_t SpacePacketBase::getAPID( void ) {
uint16_t SpacePacketBase::getAPID( void ) const {
return ( (this->data->header.packet_id_h & 0b00000111) << 8 ) +
this->data->header.packet_id_l;
}
@ -51,7 +61,7 @@ uint8_t SpacePacketBase::getSequenceFlags( void ) {
return (this->data->header.sequence_control_h & 0b11000000) >> 6 ;
}
uint16_t SpacePacketBase::getPacketSequenceCount( void ) {
uint16_t SpacePacketBase::getPacketSequenceCount( void ) const {
return ( (this->data->header.sequence_control_h & 0b00111111) << 8 )
+ this->data->header.sequence_control_l;
}
@ -83,3 +93,11 @@ uint8_t* SpacePacketBase::getWholeData() {
void SpacePacketBase::setData( const uint8_t* p_Data ) {
this->data = (SpacePacketPointer*)p_Data;
}
uint32_t SpacePacketBase::getApidAndSequenceCount() const {
return (getAPID() << 16) + getPacketSequenceCount();
}
uint8_t* SpacePacketBase::getPacketData() {
return &(data->packet_data);
}

View File

@ -80,6 +80,8 @@ public:
* @return Returns true if the bit is set and false if not.
*/
bool isTelecommand( void );
void initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount = 0);
/**
* The CCSDS header provides a secondary header flag (the fifth-highest bit),
* which is checked with this method.
@ -97,7 +99,7 @@ public:
* id.
* @return The CCSDS APID.
*/
uint16_t getAPID( void );
uint16_t getAPID( void ) const;
/**
* Sets the APID of a packet, which are the lowest 11 bit of the packet
* id.
@ -122,7 +124,7 @@ public:
* packet sequence control field.
* @return The CCSDS sequence count.
*/
uint16_t getPacketSequenceCount( void );
uint16_t getPacketSequenceCount( void ) const;
/**
* Sets the packet sequence count, which are the lowest 14 bit of the
* packet sequence control field.
@ -153,6 +155,8 @@ public:
* @return A \c uint8_t pointer to the first byte of the CCSDS primary header.
*/
virtual uint8_t* getWholeData( void );
uint8_t* getPacketData();
/**
* With this method, the packet data pointer can be redirected to another
* location.
@ -165,6 +169,8 @@ public:
*/
uint32_t getFullSize();
uint32_t getApidAndSequenceCount() const;
};
#endif /* SPACEPACKETBASE_H_ */

View File

@ -1,10 +1,3 @@
/*
* ApidMatcher.h
*
* Created on: 09.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_
#define FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_
@ -19,6 +12,9 @@ public:
ApidMatcher(uint16_t setApid) :
apid(setApid) {
}
ApidMatcher(TmPacketMinimal* test) :
apid(test->getAPID()) {
}
bool match(TmPacketMinimal* packet) {
if (packet->getAPID() == apid) {
return true;

View File

@ -1,10 +1,3 @@
/*
* PacketMatchTree.cpp
*
* Created on: 10.03.2015
* Author: baetz
*/
#include <framework/tmtcpacket/packetmatcher/ApidMatcher.h>
#include <framework/tmtcpacket/packetmatcher/PacketMatchTree.h>
#include <framework/tmtcpacket/packetmatcher/ServiceMatcher.h>
@ -31,116 +24,148 @@ PacketMatchTree::~PacketMatchTree() {
ReturnValue_t PacketMatchTree::addMatch(uint16_t apid, uint8_t type,
uint8_t subtype) {
//We assume adding APID is always requested.
uint8_t expectedHierarchy = 0;
if (type != 0) {
expectedHierarchy++;
if (subtype != 0) {
expectedHierarchy++;
}
}
TmPacketMinimal::TmPacketMinimalPointer data;
data.data_field.service_type = type;
data.data_field.service_subtype = subtype;
TmPacketMinimal testPacket((uint8_t*)&data);
TmPacketMinimal testPacket((uint8_t*) &data);
testPacket.setAPID(apid);
uint8_t realHierarchy = 0;
iterator lastMatch;
bool isInTree = matchesTree(&testPacket, &lastMatch, &realHierarchy);
if (isInTree) {
//Matches somehow.
//TODO: Are we interested in details?
iterator lastTest;
iterator rollback;
ReturnValue_t result = findOrInsertMatch<TmPacketMinimal*, ApidMatcher>(
this->begin(), &testPacket, &lastTest);
if (result == NEW_NODE_CREATED) {
rollback = lastTest;
} else if (result != RETURN_OK) {
return result;
}
if (type == 0) {
//Check if lastTest has no children, otherwise, delete them,
//as a more general check is requested.
if (lastTest.left() != this->end()) {
removeElementAndAllChildren(lastTest.left());
}
return RETURN_OK;
}
if (expectedHierarchy == realHierarchy) {
//Add another element (of correct type) at the OR branch.
lastMatch = addElement(OR, realHierarchy, lastMatch, &testPacket);
if (lastMatch == this->end()) {
return FULL;
//Type insertion required.
result = findOrInsertMatch<TmPacketMinimal*, ServiceMatcher>(
lastTest.left(), &testPacket, &lastTest);
if (result == NEW_NODE_CREATED) {
if (rollback == this->end()) {
rollback = lastTest;
}
} else if (expectedHierarchy > realHierarchy) {
//A certain amount of downward structure does not exist. Add first element as OR, rest as AND.
lastMatch = addElement(OR, realHierarchy, lastMatch, &testPacket);
if (lastMatch == end()) {
return FULL;
} else if (result != RETURN_OK) {
if (rollback != this->end()) {
removeElementAndAllChildren(rollback);
}
iterator firstOfList = lastMatch;
while (lastMatch != end() && realHierarchy < expectedHierarchy) {
realHierarchy++;
lastMatch = addElement(AND, realHierarchy, lastMatch, &testPacket);
return result;
}
if (subtype == 0) {
if (lastTest.left() != this->end()) {
//See above
removeElementAndAllChildren(lastTest.left());
}
if (lastMatch == end()) {
//At least one element could not be inserted. So delete everything.
removeElementAndAllChildren(firstOfList);
return FULL;
return RETURN_OK;
}
//Subtype insertion required.
result = findOrInsertMatch<TmPacketMinimal*, SubServiceMatcher>(
lastTest.left(), &testPacket, &lastTest);
if (result == NEW_NODE_CREATED) {
return RETURN_OK;
} else if (result != RETURN_OK) {
if (rollback != this->end()) {
removeElementAndAllChildren(rollback);
}
} else {
//Might work like that.
//Too detailed match, delete the last element and all its children.
while (lastMatch.up() != end() && lastMatch.up().left() != lastMatch) {
lastMatch = lastMatch.up();
}
removeElementAndAllChildren(lastMatch);
return result;
}
return RETURN_OK;
}
ReturnValue_t PacketMatchTree::removeMatch(uint16_t apid, uint8_t type,
uint8_t subtype) {
//We assume APID is always in request.
uint8_t expectedHierarchy = 1;
if (type != 0) {
expectedHierarchy++;
if (subtype != 0) {
expectedHierarchy++;
}
}
TmPacketMinimal::TmPacketMinimalPointer data;
data.data_field.service_type = type;
data.data_field.service_subtype = subtype;
TmPacketMinimal testPacket((uint8_t*)&data);
testPacket.setAPID(apid);
uint8_t realHierarchy = 0;
iterator lastMatch;
bool isInTree = matchesTree(&testPacket, &lastMatch, &realHierarchy);
if (isInTree) {
if (expectedHierarchy == realHierarchy) {
return removeElementAndReconnectChildren(lastMatch);
template<typename VALUE_T, typename INSERTION_T>
ReturnValue_t PacketMatchTree::findOrInsertMatch(iterator startAt, VALUE_T test,
iterator* lastTest) {
bool attachToBranch = AND;
iterator iter = startAt;
while (iter != this->end()) {
bool isMatch = iter->match(test);
attachToBranch = OR;
*lastTest = iter;
if (isMatch) {
return RETURN_OK;
} else {
return TOO_DETAILED_REQUEST;
//Go down OR branch.
iter = iter.right();
}
} else {
//TODO: Maybe refine this a bit.
return NO_MATCH;
}
}
PacketMatchTree::iterator PacketMatchTree::addElement(bool andBranch,
uint8_t level, PacketMatchTree::iterator position,
TmPacketMinimal* content) {
SerializeableMatcherIF<TmPacketMinimal*>* newContent = NULL;
switch (level) {
case 0:
newContent = factory.generate<ApidMatcher>(content->getAPID());
break;
case 1:
newContent = factory.generate<ServiceMatcher>(content->getService());
break;
case 2:
newContent = factory.generate<SubServiceMatcher>(
content->getSubService());
break;
default:
break;
}
//Only reached if nothing was found.
SerializeableMatcherIF<VALUE_T>* newContent = factory.generate<INSERTION_T>(
test);
if (newContent == NULL) {
return end();
return FULL;
}
Node* newNode = factory.generate<Node>(newContent);
if (newNode == NULL) {
return end();
//Need to make sure partially generated content is deleted, otherwise, that's a leak.
factory.destroy<INSERTION_T>(static_cast<INSERTION_T*>(newContent));
return FULL;
}
return insert(andBranch, position, newNode);
*lastTest = insert(attachToBranch, *lastTest, newNode);
if (*lastTest == end()) {
//This actaully never fails, so creating a dedicated returncode seems an overshoot.
return RETURN_FAILED;
}
return NEW_NODE_CREATED;
}
ReturnValue_t PacketMatchTree::removeMatch(uint16_t apid, uint8_t type,
uint8_t subtype) {
TmPacketMinimal::TmPacketMinimalPointer data;
data.data_field.service_type = type;
data.data_field.service_subtype = subtype;
TmPacketMinimal testPacket((uint8_t*) &data);
testPacket.setAPID(apid);
iterator foundElement = findMatch(begin(), &testPacket);
if (foundElement == this->end()) {
return NO_MATCH;
}
if (type == 0) {
if (foundElement.left() == end()) {
return removeElementAndReconnectChildren(foundElement);
} else {
return TOO_GENERAL_REQUEST;
}
}
//Go down AND branch. Will abort if empty.
foundElement = findMatch(foundElement.left(), &testPacket);
if (foundElement == this->end()) {
return NO_MATCH;
}
if (subtype == 0) {
if (foundElement.left() == end()) {
return removeElementAndReconnectChildren(foundElement);
} else {
return TOO_GENERAL_REQUEST;
}
}
//Again, go down AND branch.
foundElement = findMatch(foundElement.left(), &testPacket);
if (foundElement == end()) {
return NO_MATCH;
}
return removeElementAndReconnectChildren(foundElement);
}
PacketMatchTree::iterator PacketMatchTree::findMatch(iterator startAt,
TmPacketMinimal* test) {
iterator iter = startAt;
while (iter != end()) {
bool isMatch = iter->match(test);
if (isMatch) {
break;
} else {
iter = iter.right(); //next OR element
}
}
return iter;
}
ReturnValue_t PacketMatchTree::initialize() {
@ -150,7 +175,7 @@ ReturnValue_t PacketMatchTree::initialize() {
const uint16_t PacketMatchTree::POOL_SIZES[N_POOLS] = { sizeof(ServiceMatcher),
sizeof(SubServiceMatcher), sizeof(ApidMatcher),
sizeof(PacketMatchTree::Node) };
//TODO: Rather arbitrary. Adjust!
//Maximum number of types and subtypes to filter should be more than sufficient.
const uint16_t PacketMatchTree::N_ELEMENTS[N_POOLS] = { 10, 20, 2, 40 };
ReturnValue_t PacketMatchTree::changeMatch(bool addToMatch, uint16_t apid,
@ -163,7 +188,8 @@ ReturnValue_t PacketMatchTree::changeMatch(bool addToMatch, uint16_t apid,
}
ReturnValue_t PacketMatchTree::cleanUpElement(iterator position) {
//TODO: What if first deletion fails?
factory.destroy(position.element->value);
//Go on anyway, there's nothing we can do.
//SHOULDDO: Throw event, or write debug message?
return factory.destroy(position.element);
}

View File

@ -1,10 +1,3 @@
/*
* PacketMatchTree.h
*
* Created on: 10.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_
#define FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_
@ -34,7 +27,9 @@ private:
PlacementFactory factory;
static const uint16_t POOL_SIZES[N_POOLS];
static const uint16_t N_ELEMENTS[N_POOLS];
iterator addElement(bool andBranch, uint8_t level, iterator position, TmPacketMinimal* content);
template<typename VALUE_T, typename INSERTION_T>
ReturnValue_t findOrInsertMatch(iterator startAt, VALUE_T test, iterator* lastTest);
iterator findMatch(iterator startAt, TmPacketMinimal* test);
};
#endif /* FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ */

View File

@ -1,10 +1,3 @@
/*
* ServiceMatcher.h
*
* Created on: 09.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_SERVICEMATCHER_H_
#define FRAMEWORK_TMTCPACKET_PACKETMATCHER_SERVICEMATCHER_H_
@ -19,6 +12,9 @@ public:
ServiceMatcher(uint8_t setService) :
service(setService) {
}
ServiceMatcher(TmPacketMinimal* test) :
service(test->getService()) {
}
bool match(TmPacketMinimal* packet) {
if (packet->getService() == service) {
return true;

View File

@ -1,10 +1,3 @@
/*
* SubserviceMatcher.h
*
* Created on: 09.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_
#define FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_
@ -17,6 +10,9 @@ public:
SubServiceMatcher(uint8_t subService) :
subService(subService) {
}
SubServiceMatcher(TmPacketMinimal* test) :
subService(test->getSubService()) {
}
bool match(TmPacketMinimal* packet) {
if (packet->getSubService() == subService) {
return true;

View File

@ -0,0 +1,16 @@
#ifndef FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_
#define FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
class TmPacketMinimal;
class PacketTimestampInterpreterIF {
public:
virtual ~PacketTimestampInterpreterIF() {}
virtual ReturnValue_t getPacketTime(TmPacketMinimal* packet, timeval* timestamp) const = 0;
virtual ReturnValue_t getPacketTimeRaw(TmPacketMinimal* packet, const uint8_t** timePtr, uint32_t* size) const = 0;
};
#endif /* FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ */

View File

@ -1,74 +0,0 @@
/*
* TcPacket.cpp
*
* Created on: 18.06.2012
* Author: baetz
*/
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/pus/TcPacket.h>
#include <string.h>
template <uint32_t byte_size>
TcPacket<byte_size>::TcPacket() : TcPacketBase( (uint8_t*)&this->local_data ) {
memset( &this->local_data, 0, sizeof(this->local_data) );
//Set all constant elements in header according to ECSS E-70-41A (2003)
//Primary header:
//Set APID to idle packet
this->local_data.primary.packet_id_h = 0b00011000;
this->setAPID( APID_IDLE_PACKET );
//Set Sequence Flags to "stand-alone packet"
this->local_data.primary.sequence_control_h = 0b11000000;
//Set packet size to size of data field header + CRC
this->setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE );
//Data Field Header:
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
this->local_data.data_field.version_type_ack = 0b00010000;
}
template <uint32_t byte_size>
TcPacket<byte_size>::TcPacket( uint16_t new_apid, uint8_t new_ack, uint8_t new_service, uint8_t new_subservice, uint16_t new_sequence_count) : TcPacketBase( (uint8_t*)&this->local_data ) {
memset( &this->local_data, 0, sizeof(this->local_data) );
//Set all constant elements in header according to ECSS E-70-41A (2003)
//Primary header:
//Set APID to idle packet
this->local_data.primary.packet_id_h = 0b00011000;
this->setAPID( new_apid );
//Set Sequence Flags to "stand-alone packet"
this->local_data.primary.sequence_control_h = 0b11000000;
this->setPacketSequenceCount( new_sequence_count );
this->setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE );
//Data Field Header:
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
this->local_data.data_field.version_type_ack = 0b00010000;
this->local_data.data_field.version_type_ack |= ( new_ack & 0x0F);
this->local_data.data_field.service_type = new_service;
this->local_data.data_field.service_subtype = new_subservice;
this->setErrorControl();
}
template <uint32_t byte_size>
TcPacket< byte_size >::~TcPacket() {
}
template <uint32_t byte_size>
bool TcPacket<byte_size>::addApplicationData( uint8_t* newData, uint32_t amount ) {
if ( amount <= ( sizeof(this->local_data.application_data) - CRC_SIZE ) ) {
memcpy( this->local_data.application_data, newData, amount );
this->setPacketDataLength( amount + sizeof(this->local_data.data_field) + CRC_SIZE - 1 );
this->setErrorControl();
return true;
} else {
return false;
}
}
template class TcPacket<TC_PACKET_MIN_SIZE>;
template class TcPacket<32>;
template class TcPacket<64>;
template class TcPacket<128>;
template class TcPacket<256>;
template class TcPacket<1024>;

View File

@ -1,83 +0,0 @@
#ifndef TCPACKET_H_
#define TCPACKET_H_
#include <framework/tmtcpacket/pus/TcPacketBase.h>
/**
* This constant defines the minimum size of a valid PUS Telecommand Packet.
*/
#define TC_PACKET_MIN_SIZE (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + 2)
/**
* The TcPacket class is a representation of a ECSS PUS Telecommand packet.
* The template parameter is used to instantiate the class with different
* maximum Application Data sizes (to avoid wasting stack size).
* Telecommand packets are mainly created on ground, which are accessed with
* the TcPacketBase class. However, there are occasions when command packets
* are created on-board, for example when commanding another PUS compatible
* device such as the star trackers.
* These packets can be created with the TcPacket class.
* A pointer to \c local_data is passed to the \c TcPacketBase parent class,
* so the parent's methods are reachable.
* @t_param byte_size The maximum size of the complete packet (including CRC
* and headers)
* @ingroup tmtcpackets
*/
template<uint32_t byte_size>
class TcPacket : public TcPacketBase {
private:
/**
* This structure defines the data structure of a Telecommand Packet as
* local data.
*
* There's a buffer which corresponds to the Telecommand Application Data
* Field with a maximum size of \c byte_size.
*/
struct TcPacketData {
CCSDSPrimaryHeader primary;
PUSTcDataFieldHeader data_field;
uint8_t application_data[byte_size - sizeof(CCSDSPrimaryHeader) - sizeof(PUSTcDataFieldHeader)];
};
/**
* This is the data representation of the class.
*/
TcPacketData local_data;
public:
/**
* This is the default constructor of the class.
*
* It sets all values to default for a CCSDS Idle Packet (i.e. APID is 2047).
*/
TcPacket( void );
/**
* A constructor which directly sets all relevant header information.
* @param apid Sets the packet's APID field.
* @param ack Set's the packet's Ack field,
* which specifies number and size of verification packets returned
* for this command.
* @param service Sets the packet's Service ID field.
* This specifies the destination service.
* @param subservice Sets the packet's Service Subtype field.
* This specifies the destination sub-service.
* @param sequence_count Sets the packet's Source Sequence Count field.
*/
TcPacket( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, uint16_t sequence_count = 0 );
/**
* This is the empty default destructor of the class.
*/
~TcPacket( void );
/**
* With this call, application data can be added to the Application Data
* buffer.
* The Error Control Field is updated automatically.
* @param data The data to add to the Application Data field.
* @param size The size of the data to add.
* @return @li \c true if \c size is smaller than the Application Data
* buffer.
* @li \c false else.
*/
bool addApplicationData( uint8_t* data, uint32_t size );
};
#endif /* TCPACKET_H_ */

View File

@ -1,16 +1,11 @@
/*
* TcPacketBase.cpp
*
* Created on: 18.06.2012
* Author: baetz
*/
#include <framework/globalfunctions/crc_ccitt.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/pus/TcPacketBase.h>
#include <string.h>
TcPacketBase::TcPacketBase( const uint8_t* set_data ) : SpacePacketBase( set_data ) {
this->tc_data = (TcPacketPointer*)set_data;
TcPacketBase::TcPacketBase(const uint8_t* set_data) :
SpacePacketBase(set_data) {
tcData = (TcPacketPointer*) set_data;
}
TcPacketBase::~TcPacketBase() {
@ -18,57 +13,70 @@ TcPacketBase::~TcPacketBase() {
}
uint8_t TcPacketBase::getService() {
return this->tc_data->data_field.service_type;
return tcData->data_field.service_type;
}
uint8_t TcPacketBase::getSubService() {
return this->tc_data->data_field.service_subtype;
return tcData->data_field.service_subtype;
}
uint8_t TcPacketBase::getAcknowledgeFlags() {
return this->tc_data->data_field.version_type_ack & 0b00001111;
return tcData->data_field.version_type_ack & 0b00001111;
}
const uint8_t* TcPacketBase::getApplicationData() const {
return &this->tc_data->data;
return &tcData->data;
}
uint16_t TcPacketBase::getApplicationDataSize() {
return this->getPacketDataLength() - sizeof(this->tc_data->data_field) - CRC_SIZE + 1;
return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1;
}
uint16_t TcPacketBase::getErrorControl() {
uint16_t size = this->getApplicationDataSize() + CRC_SIZE;
uint8_t* p_to_buffer = &this->tc_data->data;
return ( p_to_buffer[size - 2] << 8 ) + p_to_buffer[size - 1];
uint16_t size = getApplicationDataSize() + CRC_SIZE;
uint8_t* p_to_buffer = &tcData->data;
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
}
void TcPacketBase::setErrorControl() {
uint32_t full_size = this->getFullSize();
uint16_t crc = ::Calculate_CRC ( this->getWholeData(), full_size - CRC_SIZE );
uint32_t size = this->getApplicationDataSize();
(&tc_data->data)[ size ] = ( crc & 0XFF00) >> 8; // CRCH
(&tc_data->data)[ size + 1 ] = ( crc ) & 0X00FF; // CRCL
uint32_t full_size = getFullSize();
uint16_t crc = ::Calculate_CRC(getWholeData(), full_size - CRC_SIZE);
uint32_t size = getApplicationDataSize();
(&tcData->data)[size] = (crc & 0XFF00) >> 8; // CRCH
(&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL
}
void TcPacketBase::setData(const uint8_t* p_Data) {
this->SpacePacketBase::setData( p_Data );
this->tc_data = (TcPacketPointer*)p_Data;
SpacePacketBase::setData(p_Data);
tcData = (TcPacketPointer*) p_Data;
}
uint8_t TcPacketBase::getSecondaryHeaderFlag() {
return (this->tc_data->data_field.version_type_ack & 0b10000000) >> 7;
return (tcData->data_field.version_type_ack & 0b10000000) >> 7;
}
uint8_t TcPacketBase::getPusVersionNumber() {
return (this->tc_data->data_field.version_type_ack & 0b01110000) >> 4;
return (tcData->data_field.version_type_ack & 0b01110000) >> 4;
}
void TcPacketBase::print() {
uint8_t * wholeData = this->getWholeData();
uint8_t * wholeData = getWholeData();
debug << "TcPacket contains: " << std::endl;
for (uint8_t count = 0; count < this->getFullSize(); ++count ) {
debug << std::hex << (uint16_t)wholeData[count] << " ";
for (uint8_t count = 0; count < getFullSize(); ++count) {
debug << std::hex << (uint16_t) wholeData[count] << " ";
}
debug << std::dec << std::endl;
}
void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount,
uint8_t ack, uint8_t service, uint8_t subservice) {
initSpacePacketHeader(true, true, apid, sequenceCount);
memset(&tcData->data_field, 0, sizeof(tcData->data_field));
setPacketDataLength(sizeof(tcData->data_field) + CRC_SIZE);
//Data Field Header:
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
tcData->data_field.version_type_ack = 0b00010000;
tcData->data_field.version_type_ack |= (ack & 0x0F);
tcData->data_field.service_type = service;
tcData->data_field.service_subtype = subservice;
}

View File

@ -46,8 +46,9 @@ protected:
*
* To be hardware-safe, all elements are of byte size.
*/
TcPacketPointer* tc_data;
TcPacketPointer* tcData;
public:
static const uint16_t TC_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + 2);
/**
* With this constant for the acknowledge field responses on all levels are expected.
*/
@ -83,6 +84,22 @@ public:
* This is the empty default destructor.
*/
virtual ~TcPacketBase();
/**
* Initializes the Tc Packet header.
* @param apid APID used.
* @param service PUS Service
* @param subservice PUS Subservice
* @param packetSubcounter Additional subcounter used.
*/
/**
* Initializes the Tc Packet header.
* @param apid APID used.
* @param sequenceCount Sequence Count in the primary header.
* @param ack Which acknowledeges are expected from the receiver.
* @param service PUS Service
* @param subservice PUS Subservice
*/
void initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service, uint8_t subservice);
/**
* This command returns the CCSDS Secondary Header Flag.
* It shall always be zero for PUS Packets. This is the

View File

@ -1,56 +1,57 @@
/*
* TcPacketStored.cpp
*
* Created on: 20.11.2012
* Author: baetz
*/
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/pus/TcPacket.h>
#include <framework/tmtcpacket/pus/TcPacketStored.h>
#include <string.h>
TcPacketStored::TcPacketStored( store_address_t setAddress) : TcPacketBase(NULL), storeAddress(setAddress) {
this->setStoreAddress( this->storeAddress );
TcPacketStored::TcPacketStored(store_address_t setAddress) :
TcPacketBase(NULL), storeAddress(setAddress) {
this->setStoreAddress(this->storeAddress);
}
TcPacketStored::TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice,
uint8_t sequence_count, const uint8_t* data, uint32_t size) : TcPacketBase(NULL) {
TcPacketStored::TcPacketStored(uint16_t apid, uint8_t ack, uint8_t service,
uint8_t subservice, uint8_t sequence_count, const uint8_t* data,
uint32_t size) :
TcPacketBase(NULL) {
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
if ( this->checkAndSetStore() ) {
TcPacket<TC_PACKET_MIN_SIZE> temp_packet( apid, ack, service, subservice, sequence_count);
uint8_t* p_data = NULL;
ReturnValue_t returnValue = this->store->getFreeElement( &this->storeAddress, (TC_PACKET_MIN_SIZE + size), &p_data );
if ( returnValue == this->store->RETURN_OK ) {
memcpy(p_data, temp_packet.getWholeData(), temp_packet.getFullSize() );
this->setData( p_data );
memcpy( &tc_data->data, data, size );
this->setPacketDataLength( size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1 );
this->setErrorControl();
}
if (!this->checkAndSetStore()) {
return;
}
uint8_t* p_data = NULL;
ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress,
(TC_PACKET_MIN_SIZE + size), &p_data);
if (returnValue != this->store->RETURN_OK) {
return;
}
this->setData(p_data);
initializeTcPacket(apid, sequence_count, ack, service, subservice);
memcpy(&tcData->data, data, size);
this->setPacketDataLength(
size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1);
this->setErrorControl();
}
TcPacketStored::TcPacketStored() : TcPacketBase(NULL) {
TcPacketStored::TcPacketStored() :
TcPacketBase(NULL) {
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
this->checkAndSetStore();
}
//TODO: return code?
void TcPacketStored::deletePacket() {
this->store->deleteData( this->storeAddress );
ReturnValue_t TcPacketStored::deletePacket() {
ReturnValue_t result = this->store->deleteData(this->storeAddress);
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
this->setData( NULL );
this->setData( NULL);
return result;
}
bool TcPacketStored::checkAndSetStore() {
if (this->store == NULL) {
this->store = objectManager->get<StorageManagerIF>( objects::TC_STORE );
if ( this->store == NULL ) {
error << "TcPacketStored::TcPacketStored: TC Store not found!" << std::endl;
this->store = objectManager->get<StorageManagerIF>(objects::TC_STORE);
if (this->store == NULL) {
error << "TcPacketStored::TcPacketStored: TC Store not found!"
<< std::endl;
return false;
}
}
@ -62,8 +63,9 @@ void TcPacketStored::setStoreAddress(store_address_t setAddress) {
const uint8_t* temp_data = NULL;
uint32_t temp_size;
ReturnValue_t status = StorageManagerIF::RETURN_FAILED;
if ( this->checkAndSetStore() ) {
status = this->store->getData(this->storeAddress, &temp_data, &temp_size );
if (this->checkAndSetStore()) {
status = this->store->getData(this->storeAddress, &temp_data,
&temp_size);
}
if (status == StorageManagerIF::RETURN_OK) {
this->setData(temp_data);
@ -80,9 +82,10 @@ store_address_t TcPacketStored::getStoreAddress() {
bool TcPacketStored::isSizeCorrect() {
const uint8_t* temp_data = NULL;
uint32_t temp_size;
ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size );
ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data,
&temp_size);
if (status == StorageManagerIF::RETURN_OK) {
if (this->getFullSize() == temp_size ) {
if (this->getFullSize() == temp_size) {
return true;
}
}
@ -91,11 +94,12 @@ bool TcPacketStored::isSizeCorrect() {
StorageManagerIF* TcPacketStored::store = NULL;
TcPacketStored::TcPacketStored(const uint8_t* data, uint32_t size) : TcPacketBase(data) {
TcPacketStored::TcPacketStored(const uint8_t* data, uint32_t size) :
TcPacketBase(data) {
if (getFullSize() != size) {
return;
}
if ( this->checkAndSetStore() ) {
if (this->checkAndSetStore()) {
ReturnValue_t status = store->addData(&storeAddress, data, size);
if (status != HasReturnvaluesIF::RETURN_OK) {
this->setData(NULL);

View File

@ -81,8 +81,9 @@ public:
/**
* With this call, the packet is deleted.
* It removes itself from the store and sets its data pointer to NULL.
* @return returncode from deleting the data.
*/
void deletePacket();
ReturnValue_t deletePacket();
/**
* With this call, a packet can be linked to another store. This is useful
* if the packet is a class member and used for more than one packet.

View File

@ -1,80 +0,0 @@
/*
* TmPacket.cpp
*
* Created on: 18.06.2012
* Author: baetz
*/
#include <framework/tmtcpacket/pus/TmPacket.h>
#include <string.h>
template <uint32_t byte_size>
TmPacket<byte_size>::TmPacket() : TmPacketBase( (uint8_t*)&this->local_data ) {
memset( &this->local_data, 0, sizeof(this->local_data) );
//Set all constant elements in header according to ECSS E-70-41A (2003)
//Primary header:
//Set APID to idle packet
local_data.primary.packet_id_h = 0b00001000;
setAPID( APID_IDLE_PACKET );
//Set Sequence Flags to "stand-alone packet"
local_data.primary.sequence_control_h = 0b11000000;
//Set packet size to size of data field header + CRC
setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE );
if (checkAndSetStamper()) {
timeStamper->addTimeStamp(local_data.data_field.time, sizeof(local_data.data_field.time));
}
//Data Field Header:
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
this->local_data.data_field.version_type_ack = 0b00010000;
}
template <uint32_t byte_size>
TmPacket<byte_size>::TmPacket( uint16_t new_apid, uint8_t new_service, uint8_t new_subservice, uint8_t new_packet_counter ) : TmPacketBase( (uint8_t*)&this->local_data ) {
memset( &this->local_data, 0, sizeof(this->local_data) );
//Set all constant elements in header according to ECSS E-70-41A (2003)
//Primary header:
//Set APID to idle packet
this->local_data.primary.packet_id_h = 0b00001000;
this->setAPID( new_apid );
//Set Sequence Flags to "stand-alone packet"
this->local_data.primary.sequence_control_h = 0b11000000;
//Set Data Length to minimum size (Data Field Header + CRC size)
this->setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE );
//Data Field Header:
//Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000
this->local_data.data_field.version_type_ack = 0b00010000;
this->local_data.data_field.service_type = new_service;
this->local_data.data_field.service_subtype = new_subservice;
this->local_data.data_field.subcounter = new_packet_counter;
if (checkAndSetStamper()) {
timeStamper->addTimeStamp(local_data.data_field.time, sizeof(local_data.data_field.time));
}
// this->local_data.data_field.destination = new_destination;
this->setErrorControl();
}
template <uint32_t byte_size>
TmPacket< byte_size >::~TmPacket() {
}
template <uint32_t byte_size>
bool TmPacket<byte_size>::addSourceData( uint8_t* newData, uint32_t amount ) {
if ( amount <= ( sizeof(this->local_data.source_data) - CRC_SIZE ) ) {
memcpy( this->local_data.source_data, newData, amount );
this->setPacketDataLength( amount + sizeof(this->local_data.data_field) + CRC_SIZE - 1 );
this->setErrorControl();
return true;
} else {
return false;
}
}
template class TmPacket<TmPacketBase::TM_PACKET_MIN_SIZE>;
template class TmPacket<64>;
template class TmPacket<128>;
template class TmPacket<256>;
template class TmPacket<512>;
template class TmPacket<1024>;

View File

@ -1,72 +0,0 @@
#ifndef TMPACKET_H_
#define TMPACKET_H_
#include <framework/tmtcpacket/pus/TmPacketBase.h>
/**
* The TmPacket class is a representation of a ECSS PUS Telemetry packet.
* The template parameter is used to instantiate the class with different
* maximum Application Data sizes (to avoid wasting stack size). Almost every
* on-board service is a source of telemetry packets. These packets are created
* with the TmPacket class, which is instantiated similar to the TcPacket
* class.
* A pointer to \c local_data is passed to the \c TmPacketBase parent class,
* so the parent's methods are reachable.
* @t_param byte_size The maximum size of the complete packet (including CRC
* and headers)
* @ingroup tmtcpackets
*/
template<uint32_t byte_size>
class TmPacket : public TmPacketBase {
public:
/**
* This is the default constructor of the class.
*
* It sets all values to default for a CCSDS Idle Packet (i.e. APID is 2047).
*/
TmPacket( void );
/**
* A constructor which directly sets all relevant header information.
* @param apid Sets the packet's APID field.
* @param service Sets the packet's Service ID field.
* This specifies the source service.
* @param subservice Sets the packet's Service Subtype field.
* This specifies the source sub-service.
* @param packet_counter Sets the Packet counter field of this packet.
*/
TmPacket( uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packet_counter = 0 );
/**
* This is the empty default destructor of the class.
*/
~TmPacket( void );
/**
* With this call, application data can be added to the Source Data
* buffer.
* The Error Control Field is updated automatically.
* @param data The data to add to the Source Data field.
* @param size The size of the data to add.
* @return @li \c true if \c size is smaller than the Source Data buffer.
* @li \c false else.
*/
bool addSourceData( uint8_t*, uint32_t );
private:
/**
* This structure defines the data structure of a Telemetry Packet as
* local data.
*
* There's a buffer which corresponds to the Telemetry Source Data Field
* with a maximum size of \c byte_size.
*/
struct TmPacketData {
CCSDSPrimaryHeader primary;
PUSTmDataFieldHeader data_field;
uint8_t source_data[byte_size - sizeof(CCSDSPrimaryHeader) - sizeof(PUSTmDataFieldHeader)];
};
/**
* This is the data representation of the class.
*/
TmPacketData local_data;
};
#endif /* TMPACKET_H_ */

View File

@ -1,17 +1,13 @@
/*
* TmPacketBase.cpp
*
* Created on: 18.06.2012
* Author: baetz
*/
#include <framework/globalfunctions/crc_ccitt.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/pus/TmPacketBase.h>
#include <framework/timemanager/CCSDSTime.h>
#include <string.h>
TmPacketBase::TmPacketBase( uint8_t* set_data ) : SpacePacketBase( set_data ) {
this->tm_data = (TmPacketPointer*)set_data;
TmPacketBase::TmPacketBase(uint8_t* set_data) :
SpacePacketBase(set_data) {
tm_data = (TmPacketPointer*) set_data;
}
TmPacketBase::~TmPacketBase() {
@ -19,60 +15,97 @@ TmPacketBase::~TmPacketBase() {
}
uint8_t TmPacketBase::getService() {
return this->tm_data->data_field.service_type;
return tm_data->data_field.service_type;
}
uint8_t TmPacketBase::getSubService() {
return this->tm_data->data_field.service_subtype;
return tm_data->data_field.service_subtype;
}
uint8_t* TmPacketBase::getSourceData() {
return &this->tm_data->data;
return &tm_data->data;
}
uint16_t TmPacketBase::getSourceDataSize() {
return this->getPacketDataLength() - sizeof(this->tm_data->data_field) - CRC_SIZE + 1;
return getPacketDataLength() - sizeof(tm_data->data_field)
- CRC_SIZE + 1;
}
uint16_t TmPacketBase::getErrorControl() {
uint32_t size = this->getSourceDataSize() + CRC_SIZE;
uint8_t* p_to_buffer = &this->tm_data->data;
return ( p_to_buffer[size - 2] << 8 ) + p_to_buffer[size - 1];
uint32_t size = getSourceDataSize() + CRC_SIZE;
uint8_t* p_to_buffer = &tm_data->data;
return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1];
}
void TmPacketBase::setErrorControl() {
uint32_t full_size = this->getFullSize();
uint16_t crc = ::Calculate_CRC ( this->getWholeData(), full_size - CRC_SIZE );
uint32_t size = this->getSourceDataSize();
this->getSourceData()[ size ] = ( crc & 0XFF00) >> 8; // CRCH
this->getSourceData()[ size + 1 ] = ( crc ) & 0X00FF; // CRCL
uint32_t full_size = getFullSize();
uint16_t crc = ::Calculate_CRC(getWholeData(), full_size - CRC_SIZE);
uint32_t size = getSourceDataSize();
getSourceData()[size] = (crc & 0XFF00) >> 8; // CRCH
getSourceData()[size + 1] = (crc) & 0X00FF; // CRCL
}
void TmPacketBase::setData(const uint8_t* p_Data) {
this->SpacePacketBase::setData( p_Data );
this->tm_data = (TmPacketPointer*)p_Data;
SpacePacketBase::setData(p_Data);
tm_data = (TmPacketPointer*) p_Data;
}
void TmPacketBase::print() {
/*uint8_t * wholeData = this->getWholeData();
debug << "TmPacket contains: " << std::endl;
for (uint8_t count = 0; count < this->getFullSize(); ++count ) {
debug << std::hex << (uint16_t)wholeData[count] << " ";
}
debug << std::dec << std::endl;*/
/*uint8_t * wholeData = getWholeData();
debug << "TmPacket contains: " << std::endl;
for (uint8_t count = 0; count < getFullSize(); ++count ) {
debug << std::hex << (uint16_t)wholeData[count] << " ";
}
debug << std::dec << std::endl;*/
}
bool TmPacketBase::checkAndSetStamper() {
if (timeStamper == NULL) {
//TODO: Adjust name?
timeStamper = objectManager->get<TimeStamperIF>( objects::TIME_MANAGER );
if ( timeStamper == NULL ) {
error << "TmPacketBase::checkAndSetStamper: Stamper not found!" << std::endl;
timeStamper = objectManager->get<TimeStamperIF>(timeStamperId);
if (timeStamper == NULL) {
error << "TmPacketBase::checkAndSetStamper: Stamper not found!"
<< std::endl;
return false;
}
}
return true;
}
ReturnValue_t TmPacketBase::getPacketTime(timeval* timestamp) const {
uint32_t tempSize = 0;
return CCSDSTime::convertFromCcsds(timestamp, tm_data->data_field.time,
&tempSize, sizeof(tm_data->data_field.time));
}
uint8_t* TmPacketBase::getPacketTimeRaw() const{
return tm_data->data_field.time;
}
void TmPacketBase::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packetSubcounter) {
//Set primary header:
initSpacePacketHeader(false, true, apid);
//Set data Field Header:
//First, set to zero.
memset(&tm_data->data_field, 0, sizeof(tm_data->data_field));
//Set CCSDS_secondary header flag to 0, version number to 001 and ack to 0000
tm_data->data_field.version_type_ack = 0b00010000;
tm_data->data_field.service_type = service;
tm_data->data_field.service_subtype = subservice;
tm_data->data_field.subcounter = packetSubcounter;
//Timestamp packet
if (checkAndSetStamper()) {
timeStamper->addTimeStamp(tm_data->data_field.time, sizeof(tm_data->data_field.time));
}
}
void TmPacketBase::setSourceDataSize(uint16_t size) {
setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
}
uint32_t TmPacketBase::getTimestampSize() const {
return sizeof(tm_data->data_field.time);
}
TimeStamperIF* TmPacketBase::timeStamper = NULL;
object_id_t TmPacketBase::timeStamperId = 0;

View File

@ -3,6 +3,12 @@
#include <framework/timemanager/TimeStamperIF.h>
#include <framework/tmtcpacket/SpacePacketBase.h>
#include <framework/timemanager/Clock.h>
#include <framework/objectmanager/SystemObjectIF.h>
namespace Factory{
void setStaticFrameworkObjectIds();
}
/**
* This struct defines a byte-wise structured PUS TM Data Field Header.
@ -31,8 +37,6 @@ struct TmPacketPointer {
uint8_t data;
};
//TODO: add getTime, getSubcounter, getDestionation (if required)
/**
* This class is the basic data handler for any ECSS PUS Telemetry packet.
*
@ -45,7 +49,14 @@ struct TmPacketPointer {
* @ingroup tmtcpackets
*/
class TmPacketBase : public SpacePacketBase {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
/**
* This constant defines the minimum size of a valid PUS Telemetry Packet.
*/
static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTmDataFieldHeader) + 2); //!< Minimum size of a valid PUS Telemetry Packet.
static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048; //!< Maximum size of a TM Packet in this mission.
static const uint8_t VERSION_NUMBER_BYTE_PUS_A = 0b00010000; //!< First byte of secondary header for PUS-A packets.
/**
* This is the default constructor.
* It sets its internal data pointer to the address passed and also
@ -57,6 +68,15 @@ public:
* This is the empty default destructor.
*/
virtual ~TmPacketBase();
/**
* Initializes the Tm Packet header.
* Does set the timestamp (to now), but not the error control field.
* @param apid APID used.
* @param service PUS Service
* @param subservice PUS Subservice
* @param packetSubcounter Additional subcounter used.
*/
void initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packetSubcounter);
/**
* This is a getter for the packet's PUS Service ID, which is the second
* byte of the Data Field Header.
@ -85,6 +105,12 @@ public:
* @return The size of the PUS Source Data (without Error Control field)
*/
uint16_t getSourceDataSize();
/**
* In case data was filled manually (almost never the case).
* @param size Size of source data (without CRC and data filed header!).
*/
void setSourceDataSize(uint16_t size);
/**
* This getter returns the Error Control Field of the packet.
*
@ -115,10 +141,18 @@ public:
*/
void print();
/**
* This constant defines the minimum size of a valid PUS Telemetry Packet.
* Interprets the "time"-field in the secondary header and returns it in timeval format.
* @return Converted timestamp of packet.
*/
static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTmDataFieldHeader) + 2);
static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048; //!< Maximum size of a TM Packet in this mission.
ReturnValue_t getPacketTime(timeval* timestamp) const;
/**
* Returns a raw pointer to the beginning of the time field.
* @return Raw pointer to time field.
*/
uint8_t* getPacketTimeRaw() const;
uint32_t getTimestampSize() const;
protected:
/**
* A pointer to a structure which defines the data structure of
@ -132,6 +166,8 @@ protected:
* It is initialized lazy.
*/
static TimeStamperIF* timeStamper;
static object_id_t timeStamperId; //!< The ID to use when looking for a time stamper.
/**
* Checks if a time stamper is available and tries to set it if not.
* @return Returns false if setting failed.

View File

@ -1,5 +1,7 @@
#include <framework/tmtcpacket/pus/TmPacketMinimal.h>
#include <stddef.h>
#include <time.h>
#include <framework/tmtcpacket/pus/PacketTimestampInterpreterIF.h>
TmPacketMinimal::TmPacketMinimal(const uint8_t* set_data) : SpacePacketBase( set_data ) {
this->tm_data = (TmPacketMinimalPointer*)set_data;
@ -19,3 +21,25 @@ uint8_t TmPacketMinimal::getSubService() {
uint8_t TmPacketMinimal::getPacketSubcounter() {
return tm_data->data_field.subcounter;
}
ReturnValue_t TmPacketMinimal::getPacketTime(timeval* timestamp) {
if (timestampInterpreter == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return timestampInterpreter->getPacketTime(this, timestamp);
}
ReturnValue_t TmPacketMinimal::getPacketTimeRaw(const uint8_t** timePtr, uint32_t* size) {
if (timestampInterpreter == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return timestampInterpreter->getPacketTimeRaw(this, timePtr, size);
}
void TmPacketMinimal::setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter) {
if (TmPacketMinimal::timestampInterpreter == NULL) {
TmPacketMinimal::timestampInterpreter = interpreter;
}
}
PacketTimestampInterpreterIF* TmPacketMinimal::timestampInterpreter = NULL;

View File

@ -1,16 +1,12 @@
/*
* TmPacketMinimal.h
*
* Created on: 09.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_
#define FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_
#include <framework/tmtcpacket/SpacePacketBase.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
struct timeval;
class PacketTimestampInterpreterIF;
/**
* This is a minimal version of a PUS TmPacket without any variable field, or,
* in other words with Service Type, Subtype and subcounter only.
@ -54,6 +50,11 @@ public:
uint8_t subcounter;
};
ReturnValue_t getPacketTime(timeval* timestamp);
ReturnValue_t getPacketTimeRaw(const uint8_t** timePtr, uint32_t* size);
static void setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter);
/**
* This struct defines the data structure of a PUS Telecommand Packet when
* accessed via a pointer.
@ -64,7 +65,8 @@ public:
PUSTmMinimalHeader data_field;
uint8_t rest;
};
static const uint16_t MINIMUM_SIZE = sizeof(TmPacketMinimalPointer) -1;
//Must include a checksum and is therefore at least one larger than the above struct.
static const uint16_t MINIMUM_SIZE = sizeof(TmPacketMinimalPointer) +1;
protected:
/**
* A pointer to a structure which defines the data structure of
@ -73,6 +75,8 @@ protected:
* To be hardware-safe, all elements are of byte size.
*/
TmPacketMinimalPointer* tm_data;
static PacketTimestampInterpreterIF* timestampInterpreter;
};

View File

@ -1,101 +1,105 @@
/*
* TmPacketStored.cpp
*
* Created on: 19.11.2012
* Author: baetz
*/
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tmtcpacket/pus/TmPacket.h>
#include <framework/tmtcpacket/pus/TmPacketStored.h>
#include <framework/tmtcservices/TmTcMessage.h>
#include <string.h>
TmPacketStored::TmPacketStored( store_address_t setAddress ) : TmPacketBase(NULL), storeAddress(setAddress) {
this->setStoreAddress( this->storeAddress );
}
TmPacketStored::TmPacketStored( uint16_t apid, uint8_t service,
uint8_t subservice, uint8_t packet_counter, const uint8_t* data, uint32_t size,const uint8_t* headerData, uint32_t headerSize) : TmPacketBase(NULL) {
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
if ( this->checkAndSetStore() ) {
TmPacket<TmPacketBase::TM_PACKET_MIN_SIZE> temp_packet( apid, service, subservice, packet_counter );
uint8_t* p_data = NULL;
ReturnValue_t returnValue = this->store->getFreeElement( &this->storeAddress, (TmPacketBase::TM_PACKET_MIN_SIZE + size + headerSize), &p_data );
if ( returnValue == this->store->RETURN_OK ) {
memcpy(p_data, temp_packet.getWholeData(), temp_packet.getFullSize() );
this->setData( p_data );
memcpy( this->getSourceData(), headerData, headerSize );
memcpy( this->getSourceData() + headerSize, data, size );
this->setPacketDataLength( size + headerSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1 );
this->setErrorControl();
}
}
TmPacketStored::TmPacketStored(store_address_t setAddress) :
TmPacketBase(NULL), storeAddress(setAddress) {
setStoreAddress(storeAddress);
}
TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service,
uint8_t subservice, uint8_t packet_counter, SerializeIF* content,
SerializeIF* header) : TmPacketBase(NULL) {
uint8_t subservice, uint8_t packetSubcounter, const uint8_t* data,
uint32_t size, const uint8_t* headerData, uint32_t headerSize) :
TmPacketBase(NULL) {
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
if ( checkAndSetStore() ) {
TmPacket<TmPacketBase::TM_PACKET_MIN_SIZE> temp_packet( apid, service, subservice, packet_counter );
uint32_t sourceDataSize = 0;
if (content != NULL) {
sourceDataSize += content->getSerializedSize();
}
if (header != NULL) {
sourceDataSize += header->getSerializedSize();
}
uint8_t* p_data = NULL;
ReturnValue_t returnValue = this->store->getFreeElement( &this->storeAddress, (TmPacketBase::TM_PACKET_MIN_SIZE + sourceDataSize), &p_data );
if ( returnValue == store->RETURN_OK ) {
memcpy(p_data, temp_packet.getWholeData(), temp_packet.getFullSize() );
this->setData( p_data );
uint8_t* putDataHere = getSourceData();
uint32_t size = 0;
if (header != NULL) {
header->serialize(&putDataHere, &size, sourceDataSize, true);
}
if (content != NULL) {
content->serialize(&putDataHere, &size, sourceDataSize, true);
}
this->setPacketDataLength( sourceDataSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1 );
this->setErrorControl();
}
if (!checkAndSetStore()) {
return;
}
uint8_t* pData = NULL;
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
(TmPacketBase::TM_PACKET_MIN_SIZE + size + headerSize), &pData);
if (returnValue != store->RETURN_OK) {
checkAndReportLostTm();
return;
}
setData(pData);
initializeTmPacket(apid, service, subservice, packetSubcounter);
memcpy(getSourceData(), headerData, headerSize);
memcpy(getSourceData() + headerSize, data, size);
setPacketDataLength(
size + headerSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
}
TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service,
uint8_t subservice, uint8_t packetSubcounter, SerializeIF* content,
SerializeIF* header) :
TmPacketBase(NULL) {
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
if (!checkAndSetStore()) {
return;
}
uint32_t sourceDataSize = 0;
if (content != NULL) {
sourceDataSize += content->getSerializedSize();
}
if (header != NULL) {
sourceDataSize += header->getSerializedSize();
}
uint8_t* p_data = NULL;
ReturnValue_t returnValue = store->getFreeElement(&storeAddress,
(TmPacketBase::TM_PACKET_MIN_SIZE + sourceDataSize), &p_data);
if (returnValue != store->RETURN_OK) {
checkAndReportLostTm();
}
setData(p_data);
initializeTmPacket(apid, service, subservice, packetSubcounter);
uint8_t* putDataHere = getSourceData();
uint32_t size = 0;
if (header != NULL) {
header->serialize(&putDataHere, &size, sourceDataSize, true);
}
if (content != NULL) {
content->serialize(&putDataHere, &size, sourceDataSize, true);
}
setPacketDataLength(
sourceDataSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1);
}
store_address_t TmPacketStored::getStoreAddress() {
return this->storeAddress;
return storeAddress;
}
void TmPacketStored::deletePacket() {
this->store->deleteData( this->storeAddress );
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
this->setData( NULL );
store->deleteData(storeAddress);
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
setData(NULL);
}
void TmPacketStored::setStoreAddress(store_address_t setAddress) {
this->storeAddress = setAddress;
storeAddress = setAddress;
const uint8_t* temp_data = NULL;
uint32_t temp_size;
if (!checkAndSetStore()) {
return;
}
ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size );
ReturnValue_t status = store->getData(storeAddress, &temp_data, &temp_size);
if (status == StorageManagerIF::RETURN_OK) {
this->setData(temp_data);
setData(temp_data);
} else {
this->setData(NULL);
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
setData(NULL);
storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
}
}
bool TmPacketStored::checkAndSetStore() {
if (this->store == NULL) {
this->store = objectManager->get<StorageManagerIF>( objects::TM_STORE );
if ( this->store == NULL ) {
error << "TmPacketStored::TmPacketStored: TM Store not found!" << std::endl;
if (store == NULL) {
store = objectManager->get<StorageManagerIF>(objects::TM_STORE);
if (store == NULL) {
error << "TmPacketStored::TmPacketStored: TM Store not found!"
<< std::endl;
return false;
}
}
@ -103,3 +107,34 @@ bool TmPacketStored::checkAndSetStore() {
}
StorageManagerIF* TmPacketStored::store = NULL;
InternalErrorReporterIF* TmPacketStored::internalErrorReporter = NULL;
ReturnValue_t TmPacketStored::sendPacket(MessageQueueId_t destination,
MessageQueueId_t sentFrom, bool doErrorReporting) {
if (getWholeData() == NULL) {
//SHOULDDO: More decent code.
return HasReturnvaluesIF::RETURN_FAILED;
}
TmTcMessage tmMessage(getStoreAddress());
ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination, &tmMessage, sentFrom);
if (result != HasReturnvaluesIF::RETURN_OK) {
deletePacket();
if (doErrorReporting) {
checkAndReportLostTm();
}
return result;
}
//SHOULDDO: In many cases, some counter is incremented for successfully sent packets. The check is often not done, but just incremented.
return HasReturnvaluesIF::RETURN_OK;
}
void TmPacketStored::checkAndReportLostTm() {
if (internalErrorReporter == NULL) {
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
}
if (internalErrorReporter != NULL) {
internalErrorReporter->lostTm();
}
}

View File

@ -4,6 +4,8 @@
#include <framework/serialize/SerializeIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/tmtcpacket/pus/TmPacketBase.h>
#include <framework/internalError/InternalErrorReporterIF.h>
#include <framework/ipc/MessageQueueSenderIF.h>
/**
* This class generates a ECSS PUS Telemetry packet within a given
@ -24,6 +26,9 @@ private:
* The default store is objects::TM_STORE.
*/
static StorageManagerIF* store;
static InternalErrorReporterIF *internalErrorReporter;
/**
* The address where the packet data of the object instance is stored.
*/
@ -36,6 +41,8 @@ private:
* @li \c false otherwise.
*/
bool checkAndSetStore();
void checkAndReportLostTm();
public:
/**
* This is a default constructor which does not set the data pointer.
@ -81,6 +88,8 @@ public:
* @param setAddress The new packet id to link to.
*/
void setStoreAddress( store_address_t setAddress );
ReturnValue_t sendPacket( MessageQueueId_t destination, MessageQueueId_t sentFrom, bool doErrorReporting = true );
};