updating code from Flying Laptop

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

202
LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

21
NOTICE Normal file
View File

@ -0,0 +1,21 @@
Flight Software Framework
The initial version of the Flight Software Framework was developed during
the Flying Laptop Project by the Universität Stuttgart in coorporation
with Airbus Defence and Space GmbH.
Copyrights in the Flight Software Framework are retained by their contributors.
No copyright assignment is required to contribute to the Flight Software Framework.
Some files include explicit copyright notices and/or license notices.
For full authorship information, see the version control history.
Except as otherwise noted (below and/or in individual files), the
Flight Software Framework is licensed under the Apache License, Version 2.0.
The Flight Software Framework includes modules written by third parties.
The following third party modules are included, and carry
their own copyright notices and license terms:
under contrib/:
* sgp4: sgp4 code developed by david vallado under public domain, see https://www.celestrak.com/publications/AIAA/2006-6753/

View File

@ -1,5 +0,0 @@
Besides Bastian Bätz and Ulrich Mohr, who were the main developers for Flying Laptop's Onboard Software, the following PhD Students contributed to the project:
Rouven Witt, who developed the FDIR concept and kept morale high as the team's Spaßbeauftragter.
Marek Dittmar, who started work on the ACS code and later tried to keep the development in time.
Nico Bucher, who performed software tests and as such was invaluable during the development.

View File

@ -1,8 +1,7 @@
#include <framework/action/ActionHelper.h>
#include <framework/action/HasActionsIF.h>
#include <framework/objectmanager/ObjectManagerIF.h>
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue) :
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :
owner(setOwner), queueToUse(useThisQueue), ipcStore(
NULL) {
}
@ -41,6 +40,10 @@ void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, Retur
queueToUse->sendMessage(reportTo, &reply);
}
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
queueToUse = queue;
}
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
const uint8_t* dataPtr = NULL;
@ -62,31 +65,38 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
}
}
void ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data) {
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender) {
CommandMessage reply;
store_address_t storeAddress;
uint8_t *dataPtr;
uint32_t maxSize = data->getSerializedSize();
if (maxSize == 0) {
return;
//No error, there's simply nothing to report.
return HasReturnvaluesIF::RETURN_OK;
}
uint32_t size = 0;
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
&dataPtr);
if (result != HasReturnvaluesIF::RETURN_OK) {
//TODO event?
return;
return result;
}
result = data->serialize(&dataPtr, &size, maxSize, true);
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeAddress);
//TODO event?
return;
return result;
}
//We don't need to report the objectId, as we receive REQUESTED data before the completion success message.
//True aperiodic replies need to be reported with another dedicated message.
ActionMessage::setDataReply(&reply, replyId, storeAddress);
if (queueToUse->sendMessage(reportTo, &reply) != HasReturnvaluesIF::RETURN_OK){
//TODO Service Implementation sucks at the moment
if (hideSender){
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
} else {
result = queueToUse->sendMessage(reportTo, &reply);
}
if ( result != HasReturnvaluesIF::RETURN_OK){
ipcStore->deleteData(storeAddress);
}
//We don't neeed the objectId, as we receive REQUESTED data before the completion success message.
//True aperiodic replies need to be reported with dedicated DH message.
return result;
}

View File

@ -1,25 +1,26 @@
#ifndef ACTIONHELPER_H_
#define ACTIONHELPER_H_
#include <framework/action/ActionMessage.h>
#include <framework/serialize/SerializeIF.h>
#include <framework/ipc/MessageQueueIF.h>
class HasActionsIF;
//TODO: Change MessageQueueId usage.
class ActionHelper {
public:
ActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue);
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
virtual ~ActionHelper();
ReturnValue_t handleActionMessage(CommandMessage* command);
ReturnValue_t initialize();
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
void reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data);
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false);
void setQueueToUse(MessageQueueIF *queue);
protected:
static const uint8_t STEP_OFFSET = 1;
HasActionsIF* owner;
MessageQueue* queueToUse;
MessageQueueIF* queueToUse;
StorageManagerIF* ipcStore;
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
void resetHelper();

View File

@ -1,4 +1,3 @@
#include <framework/action/ActionMessage.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/storagemanager/StorageManagerIF.h>

View File

@ -1,4 +1,3 @@
#ifndef ACTIONMESSAGE_H_
#define ACTIONMESSAGE_H_
@ -11,7 +10,7 @@ class ActionMessage {
private:
ActionMessage();
public:
static const uint8_t MESSAGE_ID = FUNCTION_MESSAGE_ID;
static const uint8_t MESSAGE_ID = MESSAGE_TYPE::ACTION;
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);

View File

@ -1,4 +1,3 @@
#include <framework/action/ActionMessage.h>
#include <framework/action/CommandActionHelper.h>
#include <framework/action/CommandsActionsIF.h>

View File

@ -1,13 +1,12 @@
#ifndef COMMANDACTIONHELPER_H_
#define COMMANDACTIONHELPER_H_
#include <framework/action/ActionMessage.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/serialize/SerializeIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/ipc/MessageQueueIF.h>
class CommandsActionsIF;
@ -25,7 +24,7 @@ public:
uint8_t getCommandCount() const;
private:
CommandsActionsIF* owner;
MessageQueue* queueToUse;
MessageQueueIF* queueToUse;
StorageManagerIF* ipcStore;
uint8_t commandCount;
MessageQueueId_t lastTarget;

View File

@ -1,10 +1,9 @@
#ifndef COMMANDSACTIONSIF_H_
#define COMMANDSACTIONSIF_H_
#include <framework/action/CommandActionHelper.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueIF.h>
/**
* Interface to separate commanding actions of other objects.
@ -18,11 +17,11 @@
class CommandsActionsIF {
friend class CommandActionHelper;
public:
static const uint8_t INTERFACE_ID = COMMANDS_ACTIONS_IF;
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
virtual ~CommandsActionsIF() {}
virtual MessageQueue* getCommandQueuePtr() = 0;
virtual MessageQueueIF* getCommandQueuePtr() = 0;
protected:
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) = 0;

View File

@ -1,21 +1,14 @@
/*
* HasActionsIF.h
*
* Created on: 20.02.2014
* Author: baetz
*/
#ifndef HASACTIONSIF_H_
#define HASACTIONSIF_H_
#include <framework/action/ActionHelper.h>
#include <framework/action/ActionMessage.h>
#include <framework/action/SimpleActionHelper.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueIF.h>
class HasActionsIF {
public:
static const uint8_t INTERFACE_ID = HAS_ACTIONS_IF;
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);

View File

@ -1,8 +1,7 @@
#include <framework/action/HasActionsIF.h>
#include <framework/action/SimpleActionHelper.h>
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
MessageQueue* useThisQueue) :
MessageQueueIF* useThisQueue) :
ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander(
0), lastAction(0), stepCount(0) {
}
@ -24,8 +23,8 @@ void SimpleActionHelper::finish(ReturnValue_t result) {
resetHelper();
}
void SimpleActionHelper::reportData(SerializeIF* data) {
ActionHelper::reportData(lastCommander, lastAction, data);
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
return ActionHelper::reportData(lastCommander, lastAction, data);
}
void SimpleActionHelper::resetHelper() {

View File

@ -1,4 +1,3 @@
#ifndef SIMPLEACTIONHELPER_H_
#define SIMPLEACTIONHELPER_H_
@ -6,11 +5,11 @@
class SimpleActionHelper: public ActionHelper {
public:
SimpleActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue);
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
virtual ~SimpleActionHelper();
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
void reportData(SerializeIF* data);
ReturnValue_t reportData(SerializeIF* data);
void resetHelper();
protected:
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);

View File

@ -17,7 +17,7 @@ template<typename T, typename count_t = uint8_t>
class ArrayList {
template<typename U, typename count> friend class SerialArrayListAdapter;
public:
static const uint8_t INTERFACE_ID = ARRAY_LIST;
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/**
@ -80,13 +80,17 @@ public:
return value;
}
const T *operator->() const{
return value;
}
//SHOULDDO this should be implemented as non-member
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) {
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) const{
return (value == other.value);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) {
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other);
}
}
@ -116,9 +120,10 @@ public:
*
* @param storage the array to use as backend
* @param maxSize size of storage
* @param size size of data already present in storage
*/
ArrayList(T *storage, count_t maxSize) :
size(0), entries(storage), maxSize_(maxSize), allocated(false) {
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
}
/**
@ -170,6 +175,12 @@ public:
*/
T *back() {
return &entries[size - 1];
//Alternative solution
//return const_cast<T*>(static_cast<const T*>(*this).back());
}
const T* back() const{
return &entries[size-1];
}
/**
@ -212,11 +223,6 @@ public:
count_t remaining() {
return (maxSize_ - size);
}
protected:
/**
* pointer to the array in which the entries are stored
*/
T *entries;
private:
/**
* This is the copy constructor
@ -230,7 +236,11 @@ private:
size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated(
false) {
}
private:
protected:
/**
* pointer to the array in which the entries are stored
*/
T *entries;
/**
* remembering the maximum size
*/

View File

@ -1,10 +1,3 @@
/*
* BinaryTree.h
*
* Created on: 09.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_CONTAINER_BINARYTREE_H_
#define FRAMEWORK_CONTAINER_BINARYTREE_H_
@ -99,9 +92,6 @@ public:
}
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
newNode->parent = parentNode.element;
//TODO: Why do I delete the child references of the node? This kills reconnection :-p
// newNode->left = NULL;
// newNode->right = NULL;
if (parentNode.element != NULL) {
if (insertLeft) {
parentNode.element->left = newNode;

View File

@ -54,7 +54,7 @@ public:
return HasReturnvaluesIF::RETURN_OK;
}
}
static const uint8_t INTERFACE_ID = FIFO_CLASS;
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
};

View File

@ -9,7 +9,7 @@
template<typename key_t, typename T>
class FixedMap: public SerializeIF {
public:
static const uint8_t INTERFACE_ID = FIXED_MAP;
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);

View File

@ -1,10 +1,3 @@
/*
* FixedOrderedMultimap.h
*
* Created on: 22.01.2015
* Author: baetz
*/
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
@ -15,7 +8,7 @@
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
class FixedOrderedMultimap {
public:
static const uint8_t INTERFACE_ID = FIXED_MAP;
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);

View File

@ -0,0 +1,700 @@
#ifndef FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_
#define FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_
#include <framework/container/ArrayList.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/serialize/SerialArrayListAdapter.h>
#include <framework/globalfunctions/crc_ccitt.h>
#include <cmath>
template<typename T>
class Index: public SerializeIF{
/**
* Index is the Type used for the list of indices. The template parameter is the type which describes the index, it needs to be a child of SerializeIF to be able to make it persistent
*/
static_assert(std::is_base_of<SerializeIF,T>::value,"Wrong Type for Index, Type must implement SerializeIF");
public:
Index():blockStartAddress(0),size(0),storedPackets(0){}
Index(uint32_t startAddress):blockStartAddress(startAddress),size(0),storedPackets(0){
}
void setBlockStartAddress(uint32_t newAddress){
this->blockStartAddress = newAddress;
}
uint32_t getBlockStartAddress() const {
return blockStartAddress;
}
const T* getIndexType() const {
return &indexType;
}
T* modifyIndexType(){
return &indexType;
}
/**
* Updates the index Type. Uses = operator
* @param indexType Type to copy from
*/
void setIndexType(T* indexType) {
this->indexType = *indexType;
}
uint32_t getSize() const {
return size;
}
void setSize(uint32_t size) {
this->size = size;
}
void addSize(uint32_t size){
this->size += size;
}
void setStoredPackets(uint32_t newStoredPackets){
this->storedPackets = newStoredPackets;
}
void addStoredPackets(uint32_t packets){
this->storedPackets += packets;
}
uint32_t getStoredPackets() const{
return this->storedPackets;
}
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
ReturnValue_t result = AutoSerializeAdapter::serialize(&blockStartAddress,buffer,size,max_size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = indexType.serialize(buffer,size,max_size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = AutoSerializeAdapter::serialize(&this->storedPackets,buffer,size,max_size,bigEndian);
return result;
}
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian){
ReturnValue_t result = AutoSerializeAdapter::deSerialize(&blockStartAddress,buffer,size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = indexType.deSerialize(buffer,size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = AutoSerializeAdapter::deSerialize(&this->size,buffer,size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = AutoSerializeAdapter::deSerialize(&this->storedPackets,buffer,size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
return result;
}
uint32_t getSerializedSize() const {
uint32_t size = AutoSerializeAdapter::getSerializedSize(&blockStartAddress);
size += indexType.getSerializedSize();
size += AutoSerializeAdapter::getSerializedSize(&this->size);
size += AutoSerializeAdapter::getSerializedSize(&this->storedPackets);
return size;
}
bool operator==(const Index<T>& other){
return ((blockStartAddress == other.getBlockStartAddress()) && (size==other.getSize())) && (indexType == *(other.getIndexType()));
}
private:
uint32_t blockStartAddress;
uint32_t size;
uint32_t storedPackets;
T indexType;
};
template<typename T>
class IndexedRingMemoryArray: public SerializeIF, public ArrayList<Index<T>, uint32_t>{
/**
* Indexed Ring Memory Array is a class for a ring memory with indices. It assumes that the newest data comes in last
* It uses the currentWriteBlock as pointer to the current writing position
* The currentReadBlock must be set manually
*/
public:
IndexedRingMemoryArray(uint32_t startAddress, uint32_t size, uint32_t bytesPerBlock, SerializeIF* additionalInfo,
bool overwriteOld) :ArrayList<Index<T>,uint32_t>(NULL,(uint32_t)10,(uint32_t)0),totalSize(size),indexAddress(startAddress),currentReadSize(0),currentReadBlockSizeCached(0),lastBlockToReadSize(0), additionalInfo(additionalInfo),overwriteOld(overwriteOld){
//Calculate the maximum number of indices needed for this blocksize
uint32_t maxNrOfIndices = floor(static_cast<double>(size)/static_cast<double>(bytesPerBlock));
//Calculate the Size needeed for the index itself
uint32_t serializedSize = 0;
if(additionalInfo!=NULL){
serializedSize += additionalInfo->getSerializedSize();
}
//Size of current iterator type
Index<T> tempIndex;
serializedSize += tempIndex.getSerializedSize();
//Add Size of Array
serializedSize += sizeof(uint32_t); //size of array
serializedSize += (tempIndex.getSerializedSize() * maxNrOfIndices); //size of elements
serializedSize += sizeof(uint16_t); //size of crc
//Calculate new size after index
if(serializedSize > totalSize){
error << "IndexedRingMemory: Store is too small for index" << std::endl;
}
uint32_t useableSize = totalSize - serializedSize;
//Update the totalSize for calculations
totalSize = useableSize;
//True StartAddress
uint32_t trueStartAddress = indexAddress + serializedSize;
//Calculate True number of Blocks and reset size of true Number of Blocks
uint32_t trueNumberOfBlocks = floor(static_cast<double>(totalSize) / static_cast<double>(bytesPerBlock));
//allocate memory now
this->entries = new Index<T>[trueNumberOfBlocks];
this->size = trueNumberOfBlocks;
this->maxSize_ = trueNumberOfBlocks;
this->allocated = true;
//Check trueNumberOfBlocks
if(trueNumberOfBlocks<1){
error << "IndexedRingMemory: Invalid Number of Blocks: " << trueNumberOfBlocks;
}
//Fill address into index
uint32_t address = trueStartAddress;
for (typename IndexedRingMemoryArray<T>::Iterator it = this->begin();it!=this->end();++it) {
it->setBlockStartAddress(address);
it->setSize(0);
it->setStoredPackets(0);
address += bytesPerBlock;
}
//Initialize iterators
currentWriteBlock = this->begin();
currentReadBlock = this->begin();
lastBlockToRead = this->begin();
//Check last blockSize
uint32_t lastBlockSize = (trueStartAddress + useableSize) - (this->back()->getBlockStartAddress());
if((lastBlockSize<bytesPerBlock) && (this->size > 1)){
//remove the last Block so the second last block has more size
this->size -= 1;
debug << "IndexedRingMemory: Last Block is smaller than bytesPerBlock, removed last block" << std::endl;
}
}
/**
* Resets the whole index, the iterators and executes the given reset function on every index type
* @param typeResetFnc static reset function which accepts a pointer to the index Type
*/
void reset(void (*typeResetFnc)(T*)){
currentReadBlock = this->begin();
currentWriteBlock = this->begin();
lastBlockToRead = this->begin();
currentReadSize = 0;
currentReadBlockSizeCached = 0;
lastBlockToReadSize = 0;
for(typename IndexedRingMemoryArray<T>::Iterator it = this->begin();it!=this->end();++it){
it->setSize(0);
it->setStoredPackets(0);
(*typeResetFnc)(it->modifyIndexType());
}
}
void resetBlock(typename IndexedRingMemoryArray<T>::Iterator it,void (*typeResetFnc)(T*)){
it->setSize(0);
it->setStoredPackets(0);
(*typeResetFnc)(it->modifyIndexType());
}
/*
* Reading
*/
void setCurrentReadBlock(typename IndexedRingMemoryArray<T>::Iterator it){
currentReadBlock = it;
currentReadBlockSizeCached = it->getSize();
}
void resetRead(){
currentReadBlock = this->begin();
currentReadSize = 0;
currentReadBlockSizeCached = this->begin()->getSize();
lastBlockToRead = currentWriteBlock;
lastBlockToReadSize = currentWriteBlock->getSize();
}
/**
* Sets the last block to read to this iterator.
* Can be used to dump until block x
* @param it The iterator for the last read block
*/
void setLastBlockToRead(typename IndexedRingMemoryArray<T>::Iterator it){
lastBlockToRead = it;
lastBlockToReadSize = it->getSize();
}
/**
* Set the read pointer to the first written Block, which is the first non empty block in front of the write block
* Can be the currentWriteBlock as well
*/
void readOldest(){
resetRead();
currentReadBlock = getNextNonEmptyBlock();
currentReadBlockSizeCached = currentReadBlock->getSize();
}
/**
* Sets the current read iterator to the next Block and resets the current read size
* The current size of the block will be cached to avoid race condition between write and read
* If the end of the ring is reached the read pointer will be set to the begin
*/
void readNext(){
currentReadSize = 0;
if((this->size != 0) && (currentReadBlock.value ==this->back())){
currentReadBlock = this->begin();
}else{
currentReadBlock++;
}
currentReadBlockSizeCached = currentReadBlock->getSize();
}
/**
* Returns the address which is currently read from
* @return Address to read from
*/
uint32_t getCurrentReadAddress() const {
return getAddressOfCurrentReadBlock() + currentReadSize;
}
/**
* Adds readSize to the current size and checks if the read has no more data left and advances the read block
* @param readSize The size that was read
* @return Returns true if the read can go on
*/
bool addReadSize(uint32_t readSize) {
if(currentReadBlock == lastBlockToRead){
//The current read block is the last to read
if((currentReadSize+readSize)<lastBlockToReadSize){
//the block has more data -> return true
currentReadSize += readSize;
return true;
}else{
//Reached end of read -> return false
currentReadSize = lastBlockToReadSize;
return false;
}
}else{
//We are not in the last Block
if((currentReadSize + readSize)<currentReadBlockSizeCached){
//The current Block has more data
currentReadSize += readSize;
return true;
}else{
//The current block is written completely
readNext();
if(currentReadBlockSizeCached==0){
//Next block is empty
typename IndexedRingMemoryArray<T>::Iterator it(currentReadBlock);
//Search if any block between this and the last block is not empty
for(;it!=lastBlockToRead;++it){
if(it == this->end()){
//This is the end, next block is the begin
it = this->begin();
if(it == lastBlockToRead){
//Break if the begin is the lastBlockToRead
break;
}
}
if(it->getSize()!=0){
//This is a non empty block. Go on reading with this block
currentReadBlock = it;
currentReadBlockSizeCached = it->getSize();
return true;
}
}
//reached lastBlockToRead and every block was empty, check if the last block is also empty
if(lastBlockToReadSize!=0){
//go on with last Block
currentReadBlock = lastBlockToRead;
currentReadBlockSizeCached = lastBlockToReadSize;
return true;
}
//There is no non empty block left
return false;
}
//Size is larger than 0
return true;
}
}
}
uint32_t getRemainigSizeOfCurrentReadBlock() const{
if(currentReadBlock == lastBlockToRead){
return (lastBlockToReadSize - currentReadSize);
}else{
return (currentReadBlockSizeCached - currentReadSize);
}
}
uint32_t getAddressOfCurrentReadBlock() const {
return currentReadBlock->getBlockStartAddress();
}
/**
* Gets the next non empty Block after the current write block,
* @return Returns the iterator to the block. If there is non, the current write block is returned
*/
typename IndexedRingMemoryArray<T>::Iterator getNextNonEmptyBlock() const {
for(typename IndexedRingMemoryArray<T>::Iterator it = getNextWrite();it!=currentWriteBlock;++it){
if(it == this->end()){
it = this->begin();
if(it == currentWriteBlock){
break;
}
}
if(it->getSize()!=0){
return it;
}
}
return currentWriteBlock;
}
/**
* Returns a copy of the oldest Index type
* @return Type of Index
*/
T* getOldest(){
return (getNextNonEmptyBlock()->modifyIndexType());
}
/*
* Writing
*/
uint32_t getAddressOfCurrentWriteBlock() const{
return currentWriteBlock->getBlockStartAddress();
}
uint32_t getSizeOfCurrentWriteBlock() const{
return currentWriteBlock->getSize();
}
uint32_t getCurrentWriteAddress() const{
return getAddressOfCurrentWriteBlock() + getSizeOfCurrentWriteBlock();
}
void clearCurrentWriteBlock(){
currentWriteBlock->setSize(0);
currentWriteBlock->setStoredPackets(0);
}
void addCurrentWriteBlock(uint32_t size, uint32_t storedPackets){
currentWriteBlock->addSize(size);
currentWriteBlock->addStoredPackets(storedPackets);
}
T* modifyCurrentWriteBlockIndexType(){
return currentWriteBlock->modifyIndexType();
}
void updatePreviousWriteSize(uint32_t size, uint32_t storedPackets){
typename IndexedRingMemoryArray<T>::Iterator it = getPreviousBlock(currentWriteBlock);
it->addSize(size);
it->addStoredPackets(storedPackets);
}
/**
* Checks if the block has enough space for sizeToWrite
* @param sizeToWrite The data to be written in the Block
* @return Returns true if size to write is smaller the remaining size of the block
*/
bool hasCurrentWriteBlockEnoughSpace(uint32_t sizeToWrite){
typename IndexedRingMemoryArray<T>::Iterator next = getNextWrite();
uint32_t addressOfNextBlock = next->getBlockStartAddress();
uint32_t availableSize = ((addressOfNextBlock+totalSize) - (getAddressOfCurrentWriteBlock()+getSizeOfCurrentWriteBlock()))%totalSize;
return (sizeToWrite < availableSize);
}
/**
* Checks if the store is full if overwrite old is false
* @return Returns true if it is writeable and false if not
*/
bool isNextBlockWritable(){
//First check if this is the end of the list
typename IndexedRingMemoryArray<T>::Iterator next;
next = getNextWrite();
if((next->getSize()!=0) && (!overwriteOld)){
return false;
}
return true;
}
/**
* Updates current write Block Index Type
* @param infoOfNewBlock
*/
void updateCurrentBlock(T* infoOfNewBlock){
currentWriteBlock->setIndexType(infoOfNewBlock);
}
/**
* Succeed to next block, returns FAILED if overwrite is false and the store is full
* @return
*/
ReturnValue_t writeNext(){
//Check Next Block
if(!isNextBlockWritable()){
//The Index is full and does not overwrite old
return HasReturnvaluesIF::RETURN_FAILED;
}
//Next block can be written, update Metadata
currentWriteBlock = getNextWrite();
currentWriteBlock->setSize(0);
currentWriteBlock->setStoredPackets(0);
return HasReturnvaluesIF::RETURN_OK;
}
/**
* Serializes the Index and calculates the CRC.
* Parameters according to HasSerializeIF
* @param buffer
* @param size
* @param max_size
* @param bigEndian
* @return
*/
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const{
uint8_t* crcBuffer = *buffer;
uint32_t oldSize = *size;
if(additionalInfo!=NULL){
additionalInfo->serialize(buffer,size,max_size,bigEndian);
}
ReturnValue_t result = currentWriteBlock->serialize(buffer,size,max_size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) {
result = SerializeAdapter<Index<T> >::serialize(&this->entries[i], buffer, size,
max_size, bigEndian);
++i;
}
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
uint16_t crc = Calculate_CRC(crcBuffer,(*size-oldSize));
result = AutoSerializeAdapter::serialize(&crc,buffer,size,max_size,bigEndian);
return result;
}
/**
* Get the serialized Size of the index
* @return The serialized size of the index
*/
uint32_t getSerializedSize() const {
uint32_t size = 0;
if(additionalInfo!=NULL){
size += additionalInfo->getSerializedSize();
}
size += currentWriteBlock->getSerializedSize();
size += AutoSerializeAdapter::getSerializedSize(&this->size);
size += (this->entries[0].getSerializedSize()) * this->size;
uint16_t crc = 0;
size += AutoSerializeAdapter::getSerializedSize(&crc);
return size;
}
/**
* DeSerialize the Indexed Ring from a buffer, deSerializes the current write iterator
* CRC Has to be checked before!
* @param buffer
* @param size
* @param bigEndian
* @return
*/
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian){
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(additionalInfo!=NULL){
result = additionalInfo->deSerialize(buffer,size,bigEndian);
}
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
Index<T> tempIndex;
result = tempIndex.deSerialize(buffer,size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
uint32_t tempSize = 0;
result = AutoSerializeAdapter::deSerialize(&tempSize,buffer,size,bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
if(this->size != tempSize){
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) {
result = SerializeAdapter<Index<T> >::deSerialize(
&this->entries[i], buffer, size,
bigEndian);
++i;
}
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
typename IndexedRingMemoryArray<T>::Iterator cmp(&tempIndex);
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
if(*(cmp.value) == *(it.value)){
currentWriteBlock = it;
return HasReturnvaluesIF::RETURN_OK;
}
}
//Reached if current write block iterator is not found
return HasReturnvaluesIF::RETURN_FAILED;
}
uint32_t getIndexAddress() const {
return indexAddress;
}
/*
* Statistics
*/
uint32_t getStoredPackets() const {
uint32_t size = 0;
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
size += it->getStoredPackets();
}
return size;
}
uint32_t getTotalSize() const {
return totalSize;
}
uint32_t getCurrentSize() const{
uint32_t size = 0;
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
size += it->getSize();
}
return size;
}
bool isEmpty() const{
return getCurrentSize()==0;
}
double getPercentageFilled() const{
uint32_t filledSize = 0;
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
filledSize += it->getSize();
}
return (double)filledSize/(double)this->totalSize;
}
typename IndexedRingMemoryArray<T>::Iterator getCurrentWriteBlock() const{
return currentWriteBlock;
}
/**
* Get the next block of the currentWriteBlock.
* Returns the first one if currentWriteBlock is the last one
* @return Iterator pointing to the next block after currentWriteBlock
*/
typename IndexedRingMemoryArray<T>::Iterator getNextWrite() const{
typename IndexedRingMemoryArray<T>::Iterator next(currentWriteBlock);
if((this->size != 0) && (currentWriteBlock.value == this->back())){
next = this->begin();
}else{
++next;
}
return next;
}
/**
* Get the block in front of the Iterator
* Returns the last block if it is the first block
* @param it iterator which you want the previous block from
* @return pointing to the block before it
*/
typename IndexedRingMemoryArray<T>::Iterator getPreviousBlock(typename IndexedRingMemoryArray<T>::Iterator it) {
if(this->begin() == it){
typename IndexedRingMemoryArray<T>::Iterator next((this->back()));
return next;
}
typename IndexedRingMemoryArray<T>::Iterator next(it);
--next;
return next;
}
private:
//The total size used by the blocks (without index)
uint32_t totalSize;
//The address of the index
const uint32_t indexAddress;
//The iterators for writing and reading
typename IndexedRingMemoryArray<T>::Iterator currentWriteBlock;
typename IndexedRingMemoryArray<T>::Iterator currentReadBlock;
//How much of the current read block is read already
uint32_t currentReadSize;
//Cached Size of current read block
uint32_t currentReadBlockSizeCached;
//Last block of current write (should be write block)
typename IndexedRingMemoryArray<T>::Iterator lastBlockToRead;
//current size of last Block to read
uint32_t lastBlockToReadSize;
//Additional Info to be serialized with the index
SerializeIF* additionalInfo;
//Does it overwrite old blocks?
const bool overwriteOld;
};
#endif /* FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ */

View File

@ -1,27 +0,0 @@
/**
* @file LinkedElementDecorator.h
* @brief This file defines the LinkedElementDecorator class.
* @date 22.07.2014
* @author baetz
*/
#ifndef LINKEDELEMENTDECORATOR_H_
#define LINKEDELEMENTDECORATOR_H_
#include <framework/container/SinglyLinkedList.h>
#include <utility>
//TODO: This generates multiple inheritance from non-IF parents.
template<typename T, typename IF_T>
class LinkedElementDecorator : public LinkedElement<IF_T>, public T {
public:
template<typename... Args>
LinkedElementDecorator(Args... args) : LinkedElement<IF_T>(this), T(std::forward<Args>(args)...) {
}
virtual ~LinkedElementDecorator() {
}
};
#endif /* LINKEDELEMENTDECORATOR_H_ */

View File

@ -1,10 +1,3 @@
/*
* PlacementFactory.h
*
* Created on: 10.03.2015
* Author: baetz
*/
#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
#define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
@ -30,7 +23,8 @@ public:
}
template<typename T>
ReturnValue_t destroy(T* thisElement) {
//TODO: Shouldn't we call the destructor here first, in case something was allocated by the object (shouldn't do that, however).
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
thisElement->~T();
uint8_t* pointer = (uint8_t*) (thisElement);
return dataBackend->deleteData(pointer, sizeof(T));
}

View File

@ -1,10 +1,3 @@
/*
* RingBufferBase.h
*
* Created on: 06.02.2015
* Author