Merge branch 'mueller/master' of https://egit.irs.uni-stuttgart.de/KSat/fsfw into mueller/master
This commit is contained in:
commit
2f53a3fb1b
@ -1,110 +1,110 @@
|
||||
#include <framework/action/ActionHelper.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
|
||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :
|
||||
owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) {
|
||||
}
|
||||
|
||||
ActionHelper::~ActionHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||
prepareExecution(command->getSender(), currentAction,
|
||||
ActionMessage::getStoreId(command));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return CommandMessage::UNKNOWN_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if(queueToUse_ != nullptr) {
|
||||
setQueueToUse(queueToUse_);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, commandId, result);
|
||||
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;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||
CommandMessage reply;
|
||||
store_address_t storeAddress;
|
||||
uint8_t *dataPtr;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
if (maxSize == 0) {
|
||||
//No error, there's simply nothing to report.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||
&dataPtr);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
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);
|
||||
|
||||
//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);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActionHelper::resetHelper() {
|
||||
}
|
||||
#include "../action/ActionHelper.h"
|
||||
#include "../action/HasActionsIF.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :
|
||||
owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) {
|
||||
}
|
||||
|
||||
ActionHelper::~ActionHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||
prepareExecution(command->getSender(), currentAction,
|
||||
ActionMessage::getStoreId(command));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return CommandMessage::UNKNOWN_COMMAND;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
if(queueToUse_ != nullptr) {
|
||||
setQueueToUse(queueToUse_);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, commandId, result);
|
||||
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;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||
CommandMessage reply;
|
||||
store_address_t storeAddress;
|
||||
uint8_t *dataPtr;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
if (maxSize == 0) {
|
||||
//No error, there's simply nothing to report.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||
&dataPtr);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
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);
|
||||
|
||||
//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);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActionHelper::resetHelper() {
|
||||
}
|
||||
|
@ -1,93 +1,93 @@
|
||||
#ifndef ACTIONHELPER_H_
|
||||
#define ACTIONHELPER_H_
|
||||
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
/**
|
||||
* \brief Action Helper is a helper class which handles action messages
|
||||
*
|
||||
* Components which use the HasActionIF this helper can be used to handle the action messages.
|
||||
* It does handle step messages as well as other answers to action calls. It uses the executeAction function
|
||||
* of its owner as callback. The call of the initialize function is mandatory and it needs a valid messageQueueIF pointer!
|
||||
*/
|
||||
class HasActionsIF;
|
||||
|
||||
class ActionHelper {
|
||||
public:
|
||||
/**
|
||||
* Constructor of the action helper
|
||||
* @param setOwner Pointer to the owner of the interface
|
||||
* @param useThisQueue messageQueue to be used, can be set during initialize function as well.
|
||||
*/
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
|
||||
virtual ~ActionHelper();
|
||||
/**
|
||||
* Function to be called from the owner with a new command message
|
||||
*
|
||||
* If the message is a valid action message the helper will use the executeAction function from HasActionsIF.
|
||||
* If the message is invalid or the callback fails a message reply will be send to the sender of the message automatically.
|
||||
*
|
||||
* @param command Pointer to a command message received by the owner
|
||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message, CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||
*/
|
||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||
/**
|
||||
* Helper initialize function. Must be called before use of any other helper function
|
||||
* @param queueToUse_ Pointer to the messageQueue to be used
|
||||
* @return Returns RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||
/**
|
||||
* Function to be called from the owner to send a step message. Success or failure will be determined by the result value.
|
||||
*
|
||||
* @param step Number of steps already done
|
||||
* @param reportTo The messageQueueId to report the step message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner to send a action completion message
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner if an action does report data
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param replyId ID of the executed command
|
||||
* @param data Pointer to the data
|
||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||
*/
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false);
|
||||
/**
|
||||
* Function to setup the MessageQueueIF* of the helper. Can be used to set the messageQueueIF* if
|
||||
* message queue is unavailable at construction and initialize but must be setup before first call of other functions.
|
||||
* @param queue Queue to be used by the helper
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
protected:
|
||||
static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step
|
||||
HasActionsIF* owner;//!< Pointer to the owner
|
||||
MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with
|
||||
StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue)
|
||||
/**
|
||||
*Internal function called by handleActionMessage(CommandMessage* command)
|
||||
*
|
||||
* @param commandedBy MessageQueueID of Commander
|
||||
* @param actionId ID of action to be done
|
||||
* @param dataAddress Address of additional data in IPC Store
|
||||
*/
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual void resetHelper();
|
||||
};
|
||||
|
||||
#endif /* ACTIONHELPER_H_ */
|
||||
#ifndef ACTIONHELPER_H_
|
||||
#define ACTIONHELPER_H_
|
||||
|
||||
#include "../action/ActionMessage.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
/**
|
||||
* \brief Action Helper is a helper class which handles action messages
|
||||
*
|
||||
* Components which use the HasActionIF this helper can be used to handle the action messages.
|
||||
* It does handle step messages as well as other answers to action calls. It uses the executeAction function
|
||||
* of its owner as callback. The call of the initialize function is mandatory and it needs a valid messageQueueIF pointer!
|
||||
*/
|
||||
class HasActionsIF;
|
||||
|
||||
class ActionHelper {
|
||||
public:
|
||||
/**
|
||||
* Constructor of the action helper
|
||||
* @param setOwner Pointer to the owner of the interface
|
||||
* @param useThisQueue messageQueue to be used, can be set during initialize function as well.
|
||||
*/
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
|
||||
virtual ~ActionHelper();
|
||||
/**
|
||||
* Function to be called from the owner with a new command message
|
||||
*
|
||||
* If the message is a valid action message the helper will use the executeAction function from HasActionsIF.
|
||||
* If the message is invalid or the callback fails a message reply will be send to the sender of the message automatically.
|
||||
*
|
||||
* @param command Pointer to a command message received by the owner
|
||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message, CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||
*/
|
||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||
/**
|
||||
* Helper initialize function. Must be called before use of any other helper function
|
||||
* @param queueToUse_ Pointer to the messageQueue to be used
|
||||
* @return Returns RETURN_OK if successful
|
||||
*/
|
||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||
/**
|
||||
* Function to be called from the owner to send a step message. Success or failure will be determined by the result value.
|
||||
*
|
||||
* @param step Number of steps already done
|
||||
* @param reportTo The messageQueueId to report the step message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner to send a action completion message
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param commandId ID of the executed command
|
||||
* @param result Result of the execution
|
||||
*/
|
||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
/**
|
||||
* Function to be called by the owner if an action does report data
|
||||
*
|
||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||
* @param replyId ID of the executed command
|
||||
* @param data Pointer to the data
|
||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||
*/
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false);
|
||||
/**
|
||||
* Function to setup the MessageQueueIF* of the helper. Can be used to set the messageQueueIF* if
|
||||
* message queue is unavailable at construction and initialize but must be setup before first call of other functions.
|
||||
* @param queue Queue to be used by the helper
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
protected:
|
||||
static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step
|
||||
HasActionsIF* owner;//!< Pointer to the owner
|
||||
MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with
|
||||
StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue)
|
||||
/**
|
||||
*Internal function called by handleActionMessage(CommandMessage* command)
|
||||
*
|
||||
* @param commandedBy MessageQueueID of Commander
|
||||
* @param actionId ID of action to be done
|
||||
* @param dataAddress Address of additional data in IPC Store
|
||||
*/
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual void resetHelper();
|
||||
};
|
||||
|
||||
#endif /* ACTIONHELPER_H_ */
|
||||
|
@ -1,79 +1,79 @@
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
|
||||
ActionMessage::ActionMessage() {
|
||||
}
|
||||
|
||||
ActionMessage::~ActionMessage() {
|
||||
}
|
||||
|
||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||
store_address_t parameters) {
|
||||
message->setCommand(EXECUTE_ACTION);
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(parameters.raw);
|
||||
}
|
||||
|
||||
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
||||
return ActionId_t(message->getParameter());
|
||||
}
|
||||
|
||||
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
||||
store_address_t temp;
|
||||
temp.raw = message->getParameter2();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||
ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
message->setCommand(STEP_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(STEP_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2((step << 16) + result);
|
||||
}
|
||||
|
||||
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
||||
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
||||
return message->getParameter2() & 0xFFFF;
|
||||
}
|
||||
|
||||
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||
store_address_t data) {
|
||||
message->setCommand(DATA_REPLY);
|
||||
message->setParameter(actionId);
|
||||
message->setParameter2(data.raw);
|
||||
}
|
||||
|
||||
void ActionMessage::setCompletionReply(CommandMessage* message,
|
||||
ActionId_t fid, ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
message->setCommand(COMPLETION_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(COMPLETION_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(result);
|
||||
}
|
||||
|
||||
void ActionMessage::clear(CommandMessage* message) {
|
||||
switch(message->getCommand()) {
|
||||
case EXECUTE_ACTION:
|
||||
case DATA_REPLY: {
|
||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
||||
objects::IPC_STORE);
|
||||
if (ipcStore != NULL) {
|
||||
ipcStore->deleteData(getStoreId(message));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#include "../action/ActionMessage.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
|
||||
ActionMessage::ActionMessage() {
|
||||
}
|
||||
|
||||
ActionMessage::~ActionMessage() {
|
||||
}
|
||||
|
||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||
store_address_t parameters) {
|
||||
message->setCommand(EXECUTE_ACTION);
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(parameters.raw);
|
||||
}
|
||||
|
||||
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
||||
return ActionId_t(message->getParameter());
|
||||
}
|
||||
|
||||
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
||||
store_address_t temp;
|
||||
temp.raw = message->getParameter2();
|
||||
return temp;
|
||||
}
|
||||
|
||||
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||
ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
message->setCommand(STEP_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(STEP_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2((step << 16) + result);
|
||||
}
|
||||
|
||||
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
||||
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
||||
return message->getParameter2() & 0xFFFF;
|
||||
}
|
||||
|
||||
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||
store_address_t data) {
|
||||
message->setCommand(DATA_REPLY);
|
||||
message->setParameter(actionId);
|
||||
message->setParameter2(data.raw);
|
||||
}
|
||||
|
||||
void ActionMessage::setCompletionReply(CommandMessage* message,
|
||||
ActionId_t fid, ReturnValue_t result) {
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
message->setCommand(COMPLETION_SUCCESS);
|
||||
} else {
|
||||
message->setCommand(COMPLETION_FAILED);
|
||||
}
|
||||
message->setParameter(fid);
|
||||
message->setParameter2(result);
|
||||
}
|
||||
|
||||
void ActionMessage::clear(CommandMessage* message) {
|
||||
switch(message->getCommand()) {
|
||||
case EXECUTE_ACTION:
|
||||
case DATA_REPLY: {
|
||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
||||
objects::IPC_STORE);
|
||||
if (ipcStore != NULL) {
|
||||
ipcStore->deleteData(getStoreId(message));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
#ifndef ACTIONMESSAGE_H_
|
||||
#define ACTIONMESSAGE_H_
|
||||
|
||||
#include <framework/ipc/CommandMessage.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
typedef uint32_t ActionId_t;
|
||||
|
||||
class ActionMessage {
|
||||
private:
|
||||
ActionMessage();
|
||||
public:
|
||||
static const uint8_t MESSAGE_ID = messagetypes::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);
|
||||
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||
virtual ~ActionMessage();
|
||||
static void setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters);
|
||||
static ActionId_t getActionId(const CommandMessage* message );
|
||||
static store_address_t getStoreId(const CommandMessage* message );
|
||||
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static uint8_t getStep(const CommandMessage* message );
|
||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||
static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data);
|
||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static void clear(CommandMessage* message);
|
||||
};
|
||||
|
||||
#endif /* ACTIONMESSAGE_H_ */
|
||||
#ifndef ACTIONMESSAGE_H_
|
||||
#define ACTIONMESSAGE_H_
|
||||
|
||||
#include "../ipc/CommandMessage.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
typedef uint32_t ActionId_t;
|
||||
|
||||
class ActionMessage {
|
||||
private:
|
||||
ActionMessage();
|
||||
public:
|
||||
static const uint8_t MESSAGE_ID = messagetypes::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);
|
||||
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||
virtual ~ActionMessage();
|
||||
static void setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters);
|
||||
static ActionId_t getActionId(const CommandMessage* message );
|
||||
static store_address_t getStoreId(const CommandMessage* message );
|
||||
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static uint8_t getStep(const CommandMessage* message );
|
||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||
static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data);
|
||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
static void clear(CommandMessage* message);
|
||||
};
|
||||
|
||||
#endif /* ACTIONMESSAGE_H_ */
|
||||
|
@ -1,127 +1,127 @@
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/action/CommandActionHelper.h>
|
||||
#include <framework/action/CommandsActionsIF.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
|
||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||
NULL), commandCount(0), lastTarget(0) {
|
||||
}
|
||||
|
||||
CommandActionHelper::~CommandActionHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF *data) {
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
uint8_t *storePointer;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
||||
&storePointer);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
size_t size = 0;
|
||||
result = data->serialize(&storePointer, &size, maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
||||
// if (commandCount != 0) {
|
||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||
// }
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
||||
ActionId_t actionId, store_address_t storeId) {
|
||||
CommandMessage command;
|
||||
ActionMessage::setCommand(&command, actionId, storeId);
|
||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
lastTarget = queueId;
|
||||
commandCount++;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::initialize() {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
queueToUse = owner->getCommandQueuePtr();
|
||||
if (queueToUse == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||
if (reply->getSender() != lastTarget) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
switch (reply->getCommand()) {
|
||||
case ActionMessage::COMPLETION_SUCCESS:
|
||||
commandCount--;
|
||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::COMPLETION_FAILED:
|
||||
commandCount--;
|
||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_SUCCESS:
|
||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_FAILED:
|
||||
commandCount--;
|
||||
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::DATA_REPLY:
|
||||
extractDataForOwner(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStoreId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CommandActionHelper::getCommandCount() const {
|
||||
return commandCount;
|
||||
}
|
||||
|
||||
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
||||
const uint8_t * data = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
owner->dataReceived(actionId, data, size);
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
#include "../action/ActionMessage.h"
|
||||
#include "../action/CommandActionHelper.h"
|
||||
#include "../action/CommandsActionsIF.h"
|
||||
#include "../action/HasActionsIF.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||
NULL), commandCount(0), lastTarget(0) {
|
||||
}
|
||||
|
||||
CommandActionHelper::~CommandActionHelper() {
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF *data) {
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
uint8_t *storePointer;
|
||||
size_t maxSize = data->getSerializedSize();
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
||||
&storePointer);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
size_t size = 0;
|
||||
result = data->serialize(&storePointer, &size, maxSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
||||
// if (commandCount != 0) {
|
||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||
// }
|
||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
||||
ActionId_t actionId, store_address_t storeId) {
|
||||
CommandMessage command;
|
||||
ActionMessage::setCommand(&command, actionId, storeId);
|
||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
lastTarget = queueId;
|
||||
commandCount++;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::initialize() {
|
||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
queueToUse = owner->getCommandQueuePtr();
|
||||
if (queueToUse == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||
if (reply->getSender() != lastTarget) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
switch (reply->getCommand()) {
|
||||
case ActionMessage::COMPLETION_SUCCESS:
|
||||
commandCount--;
|
||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::COMPLETION_FAILED:
|
||||
commandCount--;
|
||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_SUCCESS:
|
||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::STEP_FAILED:
|
||||
commandCount--;
|
||||
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
case ActionMessage::DATA_REPLY:
|
||||
extractDataForOwner(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStoreId(reply));
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CommandActionHelper::getCommandCount() const {
|
||||
return commandCount;
|
||||
}
|
||||
|
||||
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
||||
const uint8_t * data = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
owner->dataReceived(actionId, data, size);
|
||||
ipcStore->deleteData(storeId);
|
||||
}
|
||||
|
@ -1,36 +1,36 @@
|
||||
#ifndef COMMANDACTIONHELPER_H_
|
||||
#define COMMANDACTIONHELPER_H_
|
||||
|
||||
#include <framework/action/ActionMessage.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;
|
||||
|
||||
class CommandActionHelper {
|
||||
friend class CommandsActionsIF;
|
||||
public:
|
||||
CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
uint8_t getCommandCount() const;
|
||||
private:
|
||||
CommandsActionsIF* owner;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
uint8_t commandCount;
|
||||
MessageQueueId_t lastTarget;
|
||||
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
||||
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
||||
store_address_t storeId);
|
||||
};
|
||||
|
||||
#endif /* COMMANDACTIONHELPER_H_ */
|
||||
#ifndef COMMANDACTIONHELPER_H_
|
||||
#define COMMANDACTIONHELPER_H_
|
||||
|
||||
#include "../action/ActionMessage.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
|
||||
class CommandsActionsIF;
|
||||
|
||||
class CommandActionHelper {
|
||||
friend class CommandsActionsIF;
|
||||
public:
|
||||
CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||
ReturnValue_t commandAction(object_id_t commandTo,
|
||||
ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
uint8_t getCommandCount() const;
|
||||
private:
|
||||
CommandsActionsIF* owner;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
uint8_t commandCount;
|
||||
MessageQueueId_t lastTarget;
|
||||
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
||||
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
||||
store_address_t storeId);
|
||||
};
|
||||
|
||||
#endif /* COMMANDACTIONHELPER_H_ */
|
||||
|
@ -1,34 +1,34 @@
|
||||
#ifndef COMMANDSACTIONSIF_H_
|
||||
#define COMMANDSACTIONSIF_H_
|
||||
|
||||
#include <framework/action/CommandActionHelper.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
/**
|
||||
* Interface to separate commanding actions of other objects.
|
||||
* In next iteration, IF should be shortened to three calls:
|
||||
* - dataReceived(data)
|
||||
* - successReceived(id, step)
|
||||
* - failureReceived(id, step, cause)
|
||||
* or even
|
||||
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
||||
*/
|
||||
class CommandsActionsIF {
|
||||
friend class CommandActionHelper;
|
||||
public:
|
||||
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 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;
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) = 0;
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||
virtual void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* COMMANDSACTIONSIF_H_ */
|
||||
#ifndef COMMANDSACTIONSIF_H_
|
||||
#define COMMANDSACTIONSIF_H_
|
||||
|
||||
#include "../action/CommandActionHelper.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
|
||||
/**
|
||||
* Interface to separate commanding actions of other objects.
|
||||
* In next iteration, IF should be shortened to three calls:
|
||||
* - dataReceived(data)
|
||||
* - successReceived(id, step)
|
||||
* - failureReceived(id, step, cause)
|
||||
* or even
|
||||
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
||||
*/
|
||||
class CommandsActionsIF {
|
||||
friend class CommandActionHelper;
|
||||
public:
|
||||
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 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;
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) = 0;
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||
virtual void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* COMMANDSACTIONSIF_H_ */
|
||||
|
@ -1,60 +1,60 @@
|
||||
#ifndef FRAMEWORK_ACTION_HASACTIONSIF_H_
|
||||
#define FRAMEWORK_ACTION_HASACTIONSIF_H_
|
||||
|
||||
#include <framework/action/ActionHelper.h>
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
/**
|
||||
* @brief
|
||||
* Interface for component which uses actions
|
||||
*
|
||||
* @details
|
||||
* This interface is used to execute actions in the component. Actions, in the
|
||||
* sense of this interface, are activities with a well-defined beginning and
|
||||
* end in time. They may adjust sub-states of components, but are not supposed
|
||||
* to change the main mode of operation, which is handled with the HasModesIF
|
||||
* described below.
|
||||
*
|
||||
* The HasActionsIF allows components to define such actions and make them
|
||||
* available for other components to use. Implementing the interface is
|
||||
* straightforward: There’s a single executeAction call, which provides an
|
||||
* identifier for the action to execute, as well as arbitrary parameters for
|
||||
* input.
|
||||
* Aside from direct, software-based actions, it is used in device handler
|
||||
* components as an interface to forward commands to devices.
|
||||
* Implementing components of the interface are supposed to check identifier
|
||||
* (ID) and parameters and immediately start execution of the action.
|
||||
* It is, however, not required to immediately finish execution.
|
||||
* Instead, this may be deferred to a later point in time, at which the
|
||||
* component needs to inform the caller about finished or failed execution.
|
||||
*
|
||||
* @ingroup interfaces
|
||||
*/
|
||||
class HasActionsIF {
|
||||
public:
|
||||
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);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
virtual ~HasActionsIF() { }
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
* Returning #EXECUTION_FINISHED or a failure code, nothing else needs to
|
||||
* be done. When needing more steps, return RETURN_OK and issue steps and
|
||||
* completion manually.
|
||||
* One "step failed" or completion report must be issued!
|
||||
*/
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_ACTION_HASACTIONSIF_H_ */
|
||||
#ifndef FRAMEWORK_ACTION_HASACTIONSIF_H_
|
||||
#define FRAMEWORK_ACTION_HASACTIONSIF_H_
|
||||
|
||||
#include "../action/ActionHelper.h"
|
||||
#include "../action/ActionMessage.h"
|
||||
#include "../action/SimpleActionHelper.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
/**
|
||||
* @brief
|
||||
* Interface for component which uses actions
|
||||
*
|
||||
* @details
|
||||
* This interface is used to execute actions in the component. Actions, in the
|
||||
* sense of this interface, are activities with a well-defined beginning and
|
||||
* end in time. They may adjust sub-states of components, but are not supposed
|
||||
* to change the main mode of operation, which is handled with the HasModesIF
|
||||
* described below.
|
||||
*
|
||||
* The HasActionsIF allows components to define such actions and make them
|
||||
* available for other components to use. Implementing the interface is
|
||||
* straightforward: There’s a single executeAction call, which provides an
|
||||
* identifier for the action to execute, as well as arbitrary parameters for
|
||||
* input.
|
||||
* Aside from direct, software-based actions, it is used in device handler
|
||||
* components as an interface to forward commands to devices.
|
||||
* Implementing components of the interface are supposed to check identifier
|
||||
* (ID) and parameters and immediately start execution of the action.
|
||||
* It is, however, not required to immediately finish execution.
|
||||
* Instead, this may be deferred to a later point in time, at which the
|
||||
* component needs to inform the caller about finished or failed execution.
|
||||
*
|
||||
* @ingroup interfaces
|
||||
*/
|
||||
class HasActionsIF {
|
||||
public:
|
||||
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);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
virtual ~HasActionsIF() { }
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*/
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
* Returning #EXECUTION_FINISHED or a failure code, nothing else needs to
|
||||
* be done. When needing more steps, return RETURN_OK and issue steps and
|
||||
* completion manually.
|
||||
* One "step failed" or completion report must be issued!
|
||||
*/
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_ACTION_HASACTIONSIF_H_ */
|
||||
|
@ -1,74 +1,74 @@
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||
MessageQueueIF* useThisQueue) :
|
||||
ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander(
|
||||
0), lastAction(0), stepCount(0) {
|
||||
}
|
||||
|
||||
SimpleActionHelper::~SimpleActionHelper() {
|
||||
}
|
||||
|
||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||
//STEP_OFFESET is subtracted to compensate for adding offset in base method, which is not necessary here.
|
||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||
result);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
resetHelper();
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleActionHelper::finish(ReturnValue_t result) {
|
||||
ActionHelper::finish(lastCommander, lastAction, result);
|
||||
resetHelper();
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||
}
|
||||
|
||||
void SimpleActionHelper::resetHelper() {
|
||||
stepCount = 0;
|
||||
isExecuting = false;
|
||||
lastAction = 0;
|
||||
lastCommander = 0;
|
||||
}
|
||||
|
||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||
ActionId_t actionId, store_address_t dataAddress) {
|
||||
CommandMessage reply;
|
||||
if (isExecuting) {
|
||||
ipcStore->deleteData(dataAddress);
|
||||
ActionMessage::setStepReply(&reply, actionId, 0,
|
||||
HasActionsIF::IS_BUSY);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
const uint8_t* dataPtr = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
lastCommander = commandedBy;
|
||||
lastAction = actionId;
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
switch (result) {
|
||||
case HasReturnvaluesIF::RETURN_OK:
|
||||
isExecuting = true;
|
||||
stepCount++;
|
||||
break;
|
||||
case HasActionsIF::EXECUTION_FINISHED:
|
||||
ActionMessage::setCompletionReply(&reply, actionId,
|
||||
HasReturnvaluesIF::RETURN_OK);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
default:
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
#include "../action/HasActionsIF.h"
|
||||
#include "../action/SimpleActionHelper.h"
|
||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||
MessageQueueIF* useThisQueue) :
|
||||
ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander(
|
||||
0), lastAction(0), stepCount(0) {
|
||||
}
|
||||
|
||||
SimpleActionHelper::~SimpleActionHelper() {
|
||||
}
|
||||
|
||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||
//STEP_OFFESET is subtracted to compensate for adding offset in base method, which is not necessary here.
|
||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||
result);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
resetHelper();
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleActionHelper::finish(ReturnValue_t result) {
|
||||
ActionHelper::finish(lastCommander, lastAction, result);
|
||||
resetHelper();
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||
}
|
||||
|
||||
void SimpleActionHelper::resetHelper() {
|
||||
stepCount = 0;
|
||||
isExecuting = false;
|
||||
lastAction = 0;
|
||||
lastCommander = 0;
|
||||
}
|
||||
|
||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||
ActionId_t actionId, store_address_t dataAddress) {
|
||||
CommandMessage reply;
|
||||
if (isExecuting) {
|
||||
ipcStore->deleteData(dataAddress);
|
||||
ActionMessage::setStepReply(&reply, actionId, 0,
|
||||
HasActionsIF::IS_BUSY);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
const uint8_t* dataPtr = NULL;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
lastCommander = commandedBy;
|
||||
lastAction = actionId;
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
switch (result) {
|
||||
case HasReturnvaluesIF::RETURN_OK:
|
||||
isExecuting = true;
|
||||
stepCount++;
|
||||
break;
|
||||
case HasActionsIF::EXECUTION_FINISHED:
|
||||
ActionMessage::setCompletionReply(&reply, actionId,
|
||||
HasReturnvaluesIF::RETURN_OK);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
default:
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
#ifndef SIMPLEACTIONHELPER_H_
|
||||
#define SIMPLEACTIONHELPER_H_
|
||||
|
||||
#include <framework/action/ActionHelper.h>
|
||||
|
||||
class SimpleActionHelper: public ActionHelper {
|
||||
public:
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~SimpleActionHelper();
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
virtual void resetHelper();
|
||||
private:
|
||||
bool isExecuting;
|
||||
MessageQueueId_t lastCommander;
|
||||
ActionId_t lastAction;
|
||||
uint8_t stepCount;
|
||||
};
|
||||
|
||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||
#ifndef SIMPLEACTIONHELPER_H_
|
||||
#define SIMPLEACTIONHELPER_H_
|
||||
|
||||
#include "../action/ActionHelper.h"
|
||||
|
||||
class SimpleActionHelper: public ActionHelper {
|
||||
public:
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~SimpleActionHelper();
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
virtual void resetHelper();
|
||||
private:
|
||||
bool isExecuting;
|
||||
MessageQueueId_t lastCommander;
|
||||
ActionId_t lastAction;
|
||||
uint8_t stepCount;
|
||||
};
|
||||
|
||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||
|
@ -1,247 +1,247 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_
|
||||
#define FRAMEWORK_CONTAINER_ARRAYLIST_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
|
||||
/**
|
||||
* @brief A List that stores its values in an array.
|
||||
* @details
|
||||
* The underlying storage is an array that can be allocated by the class
|
||||
* itself or supplied via ctor.
|
||||
*
|
||||
* @ingroup container
|
||||
*/
|
||||
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 = CLASS_ID::ARRAY_LIST;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||
|
||||
/**
|
||||
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
||||
* It is too ambigous in this case.
|
||||
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
||||
*/
|
||||
ArrayList(const ArrayList& other) = delete;
|
||||
const ArrayList& operator=(const ArrayList& other) = delete;
|
||||
|
||||
/**
|
||||
* Number of Elements stored in this List
|
||||
*/
|
||||
count_t size;
|
||||
|
||||
/**
|
||||
* This is the allocating constructor;
|
||||
*
|
||||
* It allocates an array of the specified size.
|
||||
*
|
||||
* @param maxSize
|
||||
*/
|
||||
ArrayList(count_t maxSize) :
|
||||
size(0), maxSize_(maxSize), allocated(true) {
|
||||
entries = new T[maxSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the non-allocating constructor
|
||||
*
|
||||
* It expects a pointer to an array of a certain size and initializes itself to it.
|
||||
*
|
||||
* @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, count_t size = 0) :
|
||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor, if the allocating constructor was used, it deletes the array.
|
||||
*/
|
||||
virtual ~ArrayList() {
|
||||
if (allocated) {
|
||||
delete[] entries;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An Iterator to go trough an ArrayList
|
||||
*
|
||||
* It stores a pointer to an element and increments the
|
||||
* pointer when incremented itself.
|
||||
*/
|
||||
class Iterator {
|
||||
public:
|
||||
/**
|
||||
* Empty ctor, points to NULL
|
||||
*/
|
||||
Iterator(): value(0) {}
|
||||
|
||||
/**
|
||||
* Initializes the Iterator to point to an element
|
||||
*
|
||||
* @param initialize
|
||||
*/
|
||||
Iterator(T *initialize) {
|
||||
value = initialize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current element the iterator points to
|
||||
*/
|
||||
T *value;
|
||||
|
||||
Iterator& operator++() {
|
||||
value++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Iterator& operator--() {
|
||||
value--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator--(int) {
|
||||
Iterator tmp(*this);
|
||||
operator--();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return *value;
|
||||
}
|
||||
|
||||
T *operator->() {
|
||||
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) const{
|
||||
return (value == other.value);
|
||||
}
|
||||
|
||||
//SHOULDDO this should be implemented as non-member
|
||||
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator pointing to the first stored elmement
|
||||
*
|
||||
* @return Iterator to the first element
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(&entries[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an Iterator pointing to the element after the last stored entry
|
||||
*
|
||||
* @return Iterator to the element after the last entry
|
||||
*/
|
||||
Iterator end() const {
|
||||
return Iterator(&entries[size]);
|
||||
}
|
||||
|
||||
T & operator[](count_t i) const {
|
||||
return entries[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* The first element
|
||||
*
|
||||
* @return pointer to the first stored element
|
||||
*/
|
||||
T *front() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* The last element
|
||||
*
|
||||
* does not return a valid pointer if called on an empty list.
|
||||
*
|
||||
* @return pointer to the last stored element
|
||||
*/
|
||||
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];
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of elements this List can contain
|
||||
*
|
||||
* @return maximum number of elements
|
||||
*/
|
||||
uint32_t maxSize() const {
|
||||
return this->maxSize_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new element into the list.
|
||||
*
|
||||
* The new element is inserted after the last stored element.
|
||||
*
|
||||
* @param entry
|
||||
* @return
|
||||
* -@c FULL if the List is full
|
||||
* -@c RETURN_OK else
|
||||
*/
|
||||
ReturnValue_t insert(T entry) {
|
||||
if (size >= maxSize_) {
|
||||
return FULL;
|
||||
}
|
||||
entries[size] = entry;
|
||||
++size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear the List
|
||||
*
|
||||
* This does not actually clear all entries, it only sets the size to 0.
|
||||
*/
|
||||
void clear() {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
count_t remaining() {
|
||||
return (maxSize_ - size);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* pointer to the array in which the entries are stored
|
||||
*/
|
||||
T *entries;
|
||||
/**
|
||||
* remembering the maximum size
|
||||
*/
|
||||
uint32_t maxSize_;
|
||||
|
||||
/**
|
||||
* true if the array was allocated and needs to be deleted in the destructor.
|
||||
*/
|
||||
bool allocated;
|
||||
};
|
||||
|
||||
#endif /* ARRAYLIST_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_
|
||||
#define FRAMEWORK_CONTAINER_ARRAYLIST_H_
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
|
||||
/**
|
||||
* @brief A List that stores its values in an array.
|
||||
* @details
|
||||
* The underlying storage is an array that can be allocated by the class
|
||||
* itself or supplied via ctor.
|
||||
*
|
||||
* @ingroup container
|
||||
*/
|
||||
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 = CLASS_ID::ARRAY_LIST;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||
|
||||
/**
|
||||
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
||||
* It is too ambigous in this case.
|
||||
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
||||
*/
|
||||
ArrayList(const ArrayList& other) = delete;
|
||||
const ArrayList& operator=(const ArrayList& other) = delete;
|
||||
|
||||
/**
|
||||
* Number of Elements stored in this List
|
||||
*/
|
||||
count_t size;
|
||||
|
||||
/**
|
||||
* This is the allocating constructor;
|
||||
*
|
||||
* It allocates an array of the specified size.
|
||||
*
|
||||
* @param maxSize
|
||||
*/
|
||||
ArrayList(count_t maxSize) :
|
||||
size(0), maxSize_(maxSize), allocated(true) {
|
||||
entries = new T[maxSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the non-allocating constructor
|
||||
*
|
||||
* It expects a pointer to an array of a certain size and initializes itself to it.
|
||||
*
|
||||
* @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, count_t size = 0) :
|
||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor, if the allocating constructor was used, it deletes the array.
|
||||
*/
|
||||
virtual ~ArrayList() {
|
||||
if (allocated) {
|
||||
delete[] entries;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An Iterator to go trough an ArrayList
|
||||
*
|
||||
* It stores a pointer to an element and increments the
|
||||
* pointer when incremented itself.
|
||||
*/
|
||||
class Iterator {
|
||||
public:
|
||||
/**
|
||||
* Empty ctor, points to NULL
|
||||
*/
|
||||
Iterator(): value(0) {}
|
||||
|
||||
/**
|
||||
* Initializes the Iterator to point to an element
|
||||
*
|
||||
* @param initialize
|
||||
*/
|
||||
Iterator(T *initialize) {
|
||||
value = initialize;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current element the iterator points to
|
||||
*/
|
||||
T *value;
|
||||
|
||||
Iterator& operator++() {
|
||||
value++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Iterator& operator--() {
|
||||
value--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator--(int) {
|
||||
Iterator tmp(*this);
|
||||
operator--();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return *value;
|
||||
}
|
||||
|
||||
T *operator->() {
|
||||
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) const{
|
||||
return (value == other.value);
|
||||
}
|
||||
|
||||
//SHOULDDO this should be implemented as non-member
|
||||
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator pointing to the first stored elmement
|
||||
*
|
||||
* @return Iterator to the first element
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(&entries[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an Iterator pointing to the element after the last stored entry
|
||||
*
|
||||
* @return Iterator to the element after the last entry
|
||||
*/
|
||||
Iterator end() const {
|
||||
return Iterator(&entries[size]);
|
||||
}
|
||||
|
||||
T & operator[](count_t i) const {
|
||||
return entries[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* The first element
|
||||
*
|
||||
* @return pointer to the first stored element
|
||||
*/
|
||||
T *front() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* The last element
|
||||
*
|
||||
* does not return a valid pointer if called on an empty list.
|
||||
*
|
||||
* @return pointer to the last stored element
|
||||
*/
|
||||
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];
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of elements this List can contain
|
||||
*
|
||||
* @return maximum number of elements
|
||||
*/
|
||||
uint32_t maxSize() const {
|
||||
return this->maxSize_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new element into the list.
|
||||
*
|
||||
* The new element is inserted after the last stored element.
|
||||
*
|
||||
* @param entry
|
||||
* @return
|
||||
* -@c FULL if the List is full
|
||||
* -@c RETURN_OK else
|
||||
*/
|
||||
ReturnValue_t insert(T entry) {
|
||||
if (size >= maxSize_) {
|
||||
return FULL;
|
||||
}
|
||||
entries[size] = entry;
|
||||
++size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear the List
|
||||
*
|
||||
* This does not actually clear all entries, it only sets the size to 0.
|
||||
*/
|
||||
void clear() {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
count_t remaining() {
|
||||
return (maxSize_ - size);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* pointer to the array in which the entries are stored
|
||||
*/
|
||||
T *entries;
|
||||
/**
|
||||
* remembering the maximum size
|
||||
*/
|
||||
uint32_t maxSize_;
|
||||
|
||||
/**
|
||||
* true if the array was allocated and needs to be deleted in the destructor.
|
||||
*/
|
||||
bool allocated;
|
||||
};
|
||||
|
||||
#endif /* ARRAYLIST_H_ */
|
||||
|
@ -1,42 +1,42 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
|
||||
#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
|
||||
|
||||
#include <framework/container/FIFOBase.h>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||
* can be set in the constructor.
|
||||
* @details
|
||||
* The maximum capacity can be determined at run-time, so this container
|
||||
* performs dynamic memory allocation!
|
||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||
* @tparam T Entry Type
|
||||
* @tparam capacity Maximum capacity
|
||||
*/
|
||||
template<typename T>
|
||||
class DynamicFIFO: public FIFOBase<T> {
|
||||
public:
|
||||
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
||||
fifoVector(maxCapacity) {
|
||||
// trying to pass the pointer of the uninitialized vector
|
||||
// to the FIFOBase constructor directly lead to a super evil bug.
|
||||
// So we do it like this now.
|
||||
this->setData(fifoVector.data());
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Custom copy constructor which prevents setting the
|
||||
* underlying pointer wrong.
|
||||
*/
|
||||
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
||||
fifoVector(other.maxCapacity) {
|
||||
this->setData(fifoVector.data());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<T> fifoVector;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
|
||||
#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
|
||||
|
||||
#include "../container/FIFOBase.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||
* can be set in the constructor.
|
||||
* @details
|
||||
* The maximum capacity can be determined at run-time, so this container
|
||||
* performs dynamic memory allocation!
|
||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||
* @tparam T Entry Type
|
||||
* @tparam capacity Maximum capacity
|
||||
*/
|
||||
template<typename T>
|
||||
class DynamicFIFO: public FIFOBase<T> {
|
||||
public:
|
||||
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
||||
fifoVector(maxCapacity) {
|
||||
// trying to pass the pointer of the uninitialized vector
|
||||
// to the FIFOBase constructor directly lead to a super evil bug.
|
||||
// So we do it like this now.
|
||||
this->setData(fifoVector.data());
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Custom copy constructor which prevents setting the
|
||||
* underlying pointer wrong.
|
||||
*/
|
||||
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
||||
fifoVector(other.maxCapacity) {
|
||||
this->setData(fifoVector.data());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::vector<T> fifoVector;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */
|
||||
|
@ -1,34 +1,34 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_FIFO_H_
|
||||
#define FRAMEWORK_CONTAINER_FIFO_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/container/FIFOBase.h>
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||
* compile time
|
||||
* @details
|
||||
* Performs no dynamic memory allocation.
|
||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||
* @tparam T Entry Type
|
||||
* @tparam capacity Maximum capacity
|
||||
*/
|
||||
template<typename T, size_t capacity>
|
||||
class FIFO: public FIFOBase<T> {
|
||||
public:
|
||||
FIFO(): FIFOBase<T>(fifoArray.data(), capacity) {};
|
||||
|
||||
/**
|
||||
* @brief Custom copy constructor to set pointer correctly.
|
||||
* @param other
|
||||
*/
|
||||
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
||||
this->setData(fifoArray.data());
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<T, capacity> fifoArray;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_FIFO_H_
|
||||
#define FRAMEWORK_CONTAINER_FIFO_H_
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../container/FIFOBase.h"
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||
* compile time
|
||||
* @details
|
||||
* Performs no dynamic memory allocation.
|
||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||
* @tparam T Entry Type
|
||||
* @tparam capacity Maximum capacity
|
||||
*/
|
||||
template<typename T, size_t capacity>
|
||||
class FIFO: public FIFOBase<T> {
|
||||
public:
|
||||
FIFO(): FIFOBase<T>(fifoArray.data(), capacity) {};
|
||||
|
||||
/**
|
||||
* @brief Custom copy constructor to set pointer correctly.
|
||||
* @param other
|
||||
*/
|
||||
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
||||
this->setData(fifoArray.data());
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<T, capacity> fifoArray;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */
|
||||
|
@ -1,65 +1,65 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_
|
||||
#define FRAMEWORK_CONTAINER_FIFOBASE_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
template <typename T>
|
||||
class FIFOBase {
|
||||
public:
|
||||
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);
|
||||
|
||||
/** Default ctor, takes pointer to first entry of underlying container
|
||||
* and maximum capacity */
|
||||
FIFOBase(T* values, const size_t maxCapacity);
|
||||
|
||||
/**
|
||||
* Insert value into FIFO
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t insert(T value);
|
||||
/**
|
||||
* Retrieve item from FIFO. This removes the item from the FIFO.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t retrieve(T *value);
|
||||
/**
|
||||
* Retrieve item from FIFO without removing it from FIFO.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t peek(T * value);
|
||||
/**
|
||||
* Remove item from FIFO.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t pop();
|
||||
|
||||
bool empty();
|
||||
bool full();
|
||||
size_t size();
|
||||
|
||||
|
||||
size_t getMaxCapacity() const;
|
||||
|
||||
protected:
|
||||
void setData(T* data);
|
||||
size_t maxCapacity = 0;
|
||||
|
||||
T* values;
|
||||
|
||||
size_t readIndex = 0;
|
||||
size_t writeIndex = 0;
|
||||
size_t currentSize = 0;
|
||||
|
||||
size_t next(size_t current);
|
||||
};
|
||||
|
||||
#include <framework/container/FIFOBase.tpp>
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_
|
||||
#define FRAMEWORK_CONTAINER_FIFOBASE_H_
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
template <typename T>
|
||||
class FIFOBase {
|
||||
public:
|
||||
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);
|
||||
|
||||
/** Default ctor, takes pointer to first entry of underlying container
|
||||
* and maximum capacity */
|
||||
FIFOBase(T* values, const size_t maxCapacity);
|
||||
|
||||
/**
|
||||
* Insert value into FIFO
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t insert(T value);
|
||||
/**
|
||||
* Retrieve item from FIFO. This removes the item from the FIFO.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t retrieve(T *value);
|
||||
/**
|
||||
* Retrieve item from FIFO without removing it from FIFO.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t peek(T * value);
|
||||
/**
|
||||
* Remove item from FIFO.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t pop();
|
||||
|
||||
bool empty();
|
||||
bool full();
|
||||
size_t size();
|
||||
|
||||
|
||||
size_t getMaxCapacity() const;
|
||||
|
||||
protected:
|
||||
void setData(T* data);
|
||||
size_t maxCapacity = 0;
|
||||
|
||||
T* values;
|
||||
|
||||
size_t readIndex = 0;
|
||||
size_t writeIndex = 0;
|
||||
size_t currentSize = 0;
|
||||
|
||||
size_t next(size_t current);
|
||||
};
|
||||
|
||||
#include "../container/FIFOBase.tpp"
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */
|
||||
|
@ -1,57 +1,57 @@
|
||||
#ifndef FIXEDARRAYLIST_H_
|
||||
#define FIXEDARRAYLIST_H_
|
||||
|
||||
#include <framework/container/ArrayList.h>
|
||||
|
||||
/**
|
||||
* @brief Array List with a fixed maximum size
|
||||
* @ingroup container
|
||||
*/
|
||||
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t>
|
||||
class FixedArrayList: public ArrayList<T, count_t> {
|
||||
private:
|
||||
T data[MAX_SIZE];
|
||||
public:
|
||||
/**
|
||||
* (Robin) Maybe we should also implement move assignment and move ctor.
|
||||
* Or at least delete them.
|
||||
*/
|
||||
FixedArrayList() :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
}
|
||||
|
||||
// (Robin): We could create a constructor to initialize the fixed array list
|
||||
// with data and the known size field
|
||||
// so it can be used for serialization too (with SerialFixedArrrayListAdapter)
|
||||
// is this feasible?
|
||||
/**
|
||||
* Initialize a fixed array list with data and number of data fields.
|
||||
* Endianness of entries can be swapped optionally.
|
||||
* @param data_
|
||||
* @param count
|
||||
* @param swapArrayListEndianess
|
||||
*/
|
||||
FixedArrayList(T * data_, count_t count):
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
memcpy(this->data, data_, count * sizeof(T));
|
||||
this->size = count;
|
||||
}
|
||||
|
||||
FixedArrayList(const FixedArrayList& other) :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
}
|
||||
|
||||
FixedArrayList& operator=(FixedArrayList other) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~FixedArrayList() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* FIXEDARRAYLIST_H_ */
|
||||
#ifndef FIXEDARRAYLIST_H_
|
||||
#define FIXEDARRAYLIST_H_
|
||||
|
||||
#include "../container/ArrayList.h"
|
||||
|
||||
/**
|
||||
* @brief Array List with a fixed maximum size
|
||||
* @ingroup container
|
||||
*/
|
||||
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t>
|
||||
class FixedArrayList: public ArrayList<T, count_t> {
|
||||
private:
|
||||
T data[MAX_SIZE];
|
||||
public:
|
||||
/**
|
||||
* (Robin) Maybe we should also implement move assignment and move ctor.
|
||||
* Or at least delete them.
|
||||
*/
|
||||
FixedArrayList() :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
}
|
||||
|
||||
// (Robin): We could create a constructor to initialize the fixed array list
|
||||
// with data and the known size field
|
||||
// so it can be used for serialization too (with SerialFixedArrrayListAdapter)
|
||||
// is this feasible?
|
||||
/**
|
||||
* Initialize a fixed array list with data and number of data fields.
|
||||
* Endianness of entries can be swapped optionally.
|
||||
* @param data_
|
||||
* @param count
|
||||
* @param swapArrayListEndianess
|
||||
*/
|
||||
FixedArrayList(T * data_, count_t count):
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
memcpy(this->data, data_, count * sizeof(T));
|
||||
this->size = count;
|
||||
}
|
||||
|
||||
FixedArrayList(const FixedArrayList& other) :
|
||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
}
|
||||
|
||||
FixedArrayList& operator=(FixedArrayList other) {
|
||||
memcpy(this->data, other.data, sizeof(this->data));
|
||||
this->entries = data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ~FixedArrayList() {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* FIXEDARRAYLIST_H_ */
|
||||
|
@ -1,225 +1,225 @@
|
||||
#ifndef FIXEDMAP_H_
|
||||
#define FIXEDMAP_H_
|
||||
|
||||
#include <framework/container/ArrayList.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @brief Map implementation for maps with a pre-defined size.
|
||||
* @details Can be initialized with desired maximum size.
|
||||
* Iterator is used to access <key,value> pair and
|
||||
* iterate through map entries. Complexity O(n).
|
||||
* @ingroup container
|
||||
*/
|
||||
template<typename key_t, typename T>
|
||||
class FixedMap: public SerializeIF {
|
||||
public:
|
||||
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);
|
||||
|
||||
private:
|
||||
static const key_t EMPTY_SLOT = -1;
|
||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||
uint32_t _size;
|
||||
|
||||
uint32_t findIndex(key_t key) const {
|
||||
if (_size == 0) {
|
||||
return 1;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (theMap[i].first == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
public:
|
||||
FixedMap(uint32_t maxSize) :
|
||||
theMap(maxSize), _size(0) {
|
||||
}
|
||||
|
||||
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
||||
public:
|
||||
Iterator() :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
||||
}
|
||||
|
||||
Iterator(std::pair<key_t, T> *pair) :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
|
||||
}
|
||||
|
||||
// -> operator overloaded, can be used to access value
|
||||
T *operator->() {
|
||||
return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
|
||||
}
|
||||
|
||||
// Can be used to access the key of the iterator
|
||||
key_t first() {
|
||||
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->first;
|
||||
}
|
||||
|
||||
// Alternative to access value, similar to std::map implementation
|
||||
T second() {
|
||||
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Iterator begin() const {
|
||||
return Iterator(&theMap[0]);
|
||||
}
|
||||
|
||||
Iterator end() const {
|
||||
return Iterator(&theMap[_size]);
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) {
|
||||
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
||||
return FixedMap::KEY_ALREADY_EXISTS;
|
||||
}
|
||||
if (_size == theMap.maxSize()) {
|
||||
return FixedMap::MAP_FULL;
|
||||
}
|
||||
theMap[_size].first = key;
|
||||
theMap[_size].second = value;
|
||||
if (storedValue != NULL) {
|
||||
*storedValue = Iterator(&theMap[_size]);
|
||||
}
|
||||
++_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
||||
return insert(pair.first, pair.second);
|
||||
}
|
||||
|
||||
ReturnValue_t exists(key_t key) const {
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t erase(Iterator *iter) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
--((*iter).value);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t erase(key_t key) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
T *findValue(key_t key) const {
|
||||
return &theMap[findIndex(key)].second;
|
||||
}
|
||||
|
||||
Iterator find(key_t key) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return end();
|
||||
}
|
||||
return Iterator(&theMap[findIndex(key)]);
|
||||
}
|
||||
|
||||
ReturnValue_t find(key_t key, T **value) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
uint32_t maxSize() const {
|
||||
return theMap.maxSize();
|
||||
}
|
||||
|
||||
|
||||
bool full() {
|
||||
if(_size == theMap.maxSize()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
||||
buffer, size, maxSize, streamEndianness);
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
||||
size, maxSize, streamEndianness);
|
||||
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
uint32_t printSize = sizeof(_size);
|
||||
uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < _size; ++i) {
|
||||
printSize += SerializeAdapter::getSerializedSize(
|
||||
&theMap[i].first);
|
||||
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
||||
}
|
||||
|
||||
return printSize;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
||||
buffer, size, streamEndianness);
|
||||
if (this->_size > theMap.maxSize()) {
|
||||
return SerializeIF::TOO_MANY_ELEMENTS;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
||||
size, streamEndianness);
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
||||
streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* FIXEDMAP_H_ */
|
||||
#ifndef FIXEDMAP_H_
|
||||
#define FIXEDMAP_H_
|
||||
|
||||
#include "../container/ArrayList.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @brief Map implementation for maps with a pre-defined size.
|
||||
* @details Can be initialized with desired maximum size.
|
||||
* Iterator is used to access <key,value> pair and
|
||||
* iterate through map entries. Complexity O(n).
|
||||
* @ingroup container
|
||||
*/
|
||||
template<typename key_t, typename T>
|
||||
class FixedMap: public SerializeIF {
|
||||
public:
|
||||
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);
|
||||
|
||||
private:
|
||||
static const key_t EMPTY_SLOT = -1;
|
||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||
uint32_t _size;
|
||||
|
||||
uint32_t findIndex(key_t key) const {
|
||||
if (_size == 0) {
|
||||
return 1;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (theMap[i].first == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
public:
|
||||
FixedMap(uint32_t maxSize) :
|
||||
theMap(maxSize), _size(0) {
|
||||
}
|
||||
|
||||
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
||||
public:
|
||||
Iterator() :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
||||
}
|
||||
|
||||
Iterator(std::pair<key_t, T> *pair) :
|
||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
|
||||
}
|
||||
|
||||
// -> operator overloaded, can be used to access value
|
||||
T *operator->() {
|
||||
return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
|
||||
}
|
||||
|
||||
// Can be used to access the key of the iterator
|
||||
key_t first() {
|
||||
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->first;
|
||||
}
|
||||
|
||||
// Alternative to access value, similar to std::map implementation
|
||||
T second() {
|
||||
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Iterator begin() const {
|
||||
return Iterator(&theMap[0]);
|
||||
}
|
||||
|
||||
Iterator end() const {
|
||||
return Iterator(&theMap[_size]);
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) {
|
||||
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
||||
return FixedMap::KEY_ALREADY_EXISTS;
|
||||
}
|
||||
if (_size == theMap.maxSize()) {
|
||||
return FixedMap::MAP_FULL;
|
||||
}
|
||||
theMap[_size].first = key;
|
||||
theMap[_size].second = value;
|
||||
if (storedValue != NULL) {
|
||||
*storedValue = Iterator(&theMap[_size]);
|
||||
}
|
||||
++_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
||||
return insert(pair.first, pair.second);
|
||||
}
|
||||
|
||||
ReturnValue_t exists(key_t key) const {
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t erase(Iterator *iter) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
--((*iter).value);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t erase(key_t key) {
|
||||
uint32_t i;
|
||||
if ((i = findIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
theMap[i] = theMap[_size - 1];
|
||||
--_size;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
T *findValue(key_t key) const {
|
||||
return &theMap[findIndex(key)].second;
|
||||
}
|
||||
|
||||
Iterator find(key_t key) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return end();
|
||||
}
|
||||
return Iterator(&theMap[findIndex(key)]);
|
||||
}
|
||||
|
||||
ReturnValue_t find(key_t key, T **value) const {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
uint32_t maxSize() const {
|
||||
return theMap.maxSize();
|
||||
}
|
||||
|
||||
|
||||
bool full() {
|
||||
if(_size == theMap.maxSize()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
||||
buffer, size, maxSize, streamEndianness);
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
||||
size, maxSize, streamEndianness);
|
||||
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
uint32_t printSize = sizeof(_size);
|
||||
uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < _size; ++i) {
|
||||
printSize += SerializeAdapter::getSerializedSize(
|
||||
&theMap[i].first);
|
||||
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
||||
}
|
||||
|
||||
return printSize;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
||||
buffer, size, streamEndianness);
|
||||
if (this->_size > theMap.maxSize()) {
|
||||
return SerializeIF::TOO_MANY_ELEMENTS;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
||||
size, streamEndianness);
|
||||
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
||||
streamEndianness);
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* FIXEDMAP_H_ */
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
|
||||
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
|
||||
|
||||
#include <framework/container/ArrayList.h>
|
||||
#include "../container/ArrayList.h"
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
|
||||
@ -166,6 +166,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
#include <framework/container/FixedOrderedMultimap.tpp>
|
||||
#include "FixedOrderedMultimap.tpp"
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */
|
||||
|
@ -1,90 +1,90 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
|
||||
#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
|
||||
|
||||
#include <framework/container/ArrayList.h>
|
||||
#include <framework/container/SinglyLinkedList.h>
|
||||
|
||||
template<typename T, typename count_t = uint8_t>
|
||||
class HybridIterator: public LinkedElement<T>::Iterator,
|
||||
public ArrayList<T, count_t>::Iterator {
|
||||
public:
|
||||
HybridIterator() {}
|
||||
|
||||
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
||||
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
||||
linked(true) {
|
||||
|
||||
}
|
||||
|
||||
HybridIterator(LinkedElement<T> *start) :
|
||||
LinkedElement<T>::Iterator(start), value(start->value),
|
||||
linked(true) {
|
||||
|
||||
}
|
||||
|
||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||
typename ArrayList<T, count_t>::Iterator end) :
|
||||
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
||||
linked(false), end(end.value) {
|
||||
if (value == this->end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(T *firstElement, T *lastElement) :
|
||||
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
||||
linked(false), end(++lastElement) {
|
||||
if (value == end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator& operator++() {
|
||||
if (linked) {
|
||||
LinkedElement<T>::Iterator::operator++();
|
||||
if (LinkedElement<T>::Iterator::value != nullptr) {
|
||||
value = LinkedElement<T>::Iterator::value->value;
|
||||
} else {
|
||||
value = nullptr;
|
||||
}
|
||||
} else {
|
||||
ArrayList<T, count_t>::Iterator::operator++();
|
||||
value = ArrayList<T, count_t>::Iterator::value;
|
||||
|
||||
if (value == end) {
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
HybridIterator operator++(int) {
|
||||
HybridIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const HybridIterator& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
bool operator!=(const HybridIterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return *value;
|
||||
}
|
||||
|
||||
T *operator->() {
|
||||
return value;
|
||||
}
|
||||
|
||||
T* value = nullptr;
|
||||
|
||||
private:
|
||||
bool linked = false;
|
||||
T *end = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
|
||||
#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
|
||||
|
||||
#include "../container/ArrayList.h"
|
||||
#include "../container/SinglyLinkedList.h"
|
||||
|
||||
template<typename T, typename count_t = uint8_t>
|
||||
class HybridIterator: public LinkedElement<T>::Iterator,
|
||||
public ArrayList<T, count_t>::Iterator {
|
||||
public:
|
||||
HybridIterator() {}
|
||||
|
||||
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
||||
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
||||
linked(true) {
|
||||
|
||||
}
|
||||
|
||||
HybridIterator(LinkedElement<T> *start) :
|
||||
LinkedElement<T>::Iterator(start), value(start->value),
|
||||
linked(true) {
|
||||
|
||||
}
|
||||
|
||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||
typename ArrayList<T, count_t>::Iterator end) :
|
||||
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
||||
linked(false), end(end.value) {
|
||||
if (value == this->end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(T *firstElement, T *lastElement) :
|
||||
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
||||
linked(false), end(++lastElement) {
|
||||
if (value == end) {
|
||||
value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator& operator++() {
|
||||
if (linked) {
|
||||
LinkedElement<T>::Iterator::operator++();
|
||||
if (LinkedElement<T>::Iterator::value != nullptr) {
|
||||
value = LinkedElement<T>::Iterator::value->value;
|
||||
} else {
|
||||
value = nullptr;
|
||||
}
|
||||
} else {
|
||||
ArrayList<T, count_t>::Iterator::operator++();
|
||||
value = ArrayList<T, count_t>::Iterator::value;
|
||||
|
||||
if (value == end) {
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
HybridIterator operator++(int) {
|
||||
HybridIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const HybridIterator& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
bool operator!=(const HybridIterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
T operator*() {
|
||||
return *value;
|
||||
}
|
||||
|
||||
T *operator->() {
|
||||
return value;
|
||||
}
|
||||
|
||||
T* value = nullptr;
|
||||
|
||||
private:
|
||||
bool linked = false;
|
||||
T *end = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,35 +1,35 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
|
||||
#define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
|
||||
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <utility>
|
||||
|
||||
class PlacementFactory {
|
||||
public:
|
||||
PlacementFactory(StorageManagerIF* backend) :
|
||||
dataBackend(backend) {
|
||||
}
|
||||
template<typename T, typename ... Args>
|
||||
T* generate(Args&&... args) {
|
||||
store_address_t tempId;
|
||||
uint8_t* pData = NULL;
|
||||
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
||||
&pData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return NULL;
|
||||
}
|
||||
T* temp = new (pData) T(std::forward<Args>(args)...);
|
||||
return temp;
|
||||
}
|
||||
template<typename T>
|
||||
ReturnValue_t destroy(T* thisElement) {
|
||||
//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));
|
||||
}
|
||||
private:
|
||||
StorageManagerIF* dataBackend;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
|
||||
#define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
|
||||
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
#include <utility>
|
||||
|
||||
class PlacementFactory {
|
||||
public:
|
||||
PlacementFactory(StorageManagerIF* backend) :
|
||||
dataBackend(backend) {
|
||||
}
|
||||
template<typename T, typename ... Args>
|
||||
T* generate(Args&&... args) {
|
||||
store_address_t tempId;
|
||||
uint8_t* pData = NULL;
|
||||
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
||||
&pData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return NULL;
|
||||
}
|
||||
T* temp = new (pData) T(std::forward<Args>(args)...);
|
||||
return temp;
|
||||
}
|
||||
template<typename T>
|
||||
ReturnValue_t destroy(T* thisElement) {
|
||||
//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));
|
||||
}
|
||||
private:
|
||||
StorageManagerIF* dataBackend;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
||||
|
@ -1,113 +1,113 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
|
||||
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <cstddef>
|
||||
|
||||
template<uint8_t N_READ_PTRS = 1>
|
||||
class RingBufferBase {
|
||||
public:
|
||||
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
||||
start(startAddress), write(startAddress), size(size),
|
||||
overwriteOld(overwriteOld) {
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = startAddress;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~RingBufferBase() {}
|
||||
|
||||
bool isFull(uint8_t n = 0) {
|
||||
return (availableWriteSpace(n) == 0);
|
||||
}
|
||||
bool isEmpty(uint8_t n = 0) {
|
||||
return (availableReadData(n) == 0);
|
||||
}
|
||||
|
||||
size_t availableReadData(uint8_t n = 0) const {
|
||||
return ((write + size) - read[n]) % size;
|
||||
}
|
||||
size_t availableWriteSpace(uint8_t n = 0) const {
|
||||
//One less to avoid ambiguous full/empty problem.
|
||||
return (((read[n] + size) - write - 1) % size);
|
||||
}
|
||||
|
||||
bool overwritesOld() const {
|
||||
return overwriteOld;
|
||||
}
|
||||
|
||||
size_t maxSize() const {
|
||||
return size - 1;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
write = start;
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = start;
|
||||
}
|
||||
}
|
||||
|
||||
size_t writeTillWrap() {
|
||||
return (start + size) - write;
|
||||
}
|
||||
|
||||
size_t readTillWrap(uint8_t n = 0) {
|
||||
return (start + size) - read[n];
|
||||
}
|
||||
|
||||
size_t getStart() const {
|
||||
return start;
|
||||
}
|
||||
|
||||
protected:
|
||||
const size_t start;
|
||||
size_t write;
|
||||
size_t read[N_READ_PTRS];
|
||||
const size_t size;
|
||||
const bool overwriteOld;
|
||||
void incrementWrite(uint32_t amount) {
|
||||
write = ((write + amount - start) % size) + start;
|
||||
}
|
||||
void incrementRead(uint32_t amount, uint8_t n = 0) {
|
||||
read[n] = ((read[n] + amount - start) % size) + start;
|
||||
}
|
||||
|
||||
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
||||
if (availableReadData(n) >= amount) {
|
||||
incrementRead(amount, n);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t writeData(uint32_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t getRead(uint8_t n = 0) const {
|
||||
return read[n];
|
||||
}
|
||||
|
||||
void setRead(uint32_t read, uint8_t n = 0) {
|
||||
if (read >= start && read < (start+size)) {
|
||||
this->read[n] = read;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getWrite() const {
|
||||
return write;
|
||||
}
|
||||
|
||||
void setWrite(uint32_t write) {
|
||||
this->write = write;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
|
||||
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include <cstddef>
|
||||
|
||||
template<uint8_t N_READ_PTRS = 1>
|
||||
class RingBufferBase {
|
||||
public:
|
||||
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
||||
start(startAddress), write(startAddress), size(size),
|
||||
overwriteOld(overwriteOld) {
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = startAddress;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~RingBufferBase() {}
|
||||
|
||||
bool isFull(uint8_t n = 0) {
|
||||
return (availableWriteSpace(n) == 0);
|
||||
}
|
||||
bool isEmpty(uint8_t n = 0) {
|
||||
return (getAvailableReadData(n) == 0);
|
||||
}
|
||||
|
||||
size_t getAvailableReadData(uint8_t n = 0) const {
|
||||
return ((write + size) - read[n]) % size;
|
||||
}
|
||||
size_t availableWriteSpace(uint8_t n = 0) const {
|
||||
//One less to avoid ambiguous full/empty problem.
|
||||
return (((read[n] + size) - write - 1) % size);
|
||||
}
|
||||
|
||||
bool overwritesOld() const {
|
||||
return overwriteOld;
|
||||
}
|
||||
|
||||
size_t getMaxSize() const {
|
||||
return size - 1;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
write = start;
|
||||
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
|
||||
read[count] = start;
|
||||
}
|
||||
}
|
||||
|
||||
size_t writeTillWrap() {
|
||||
return (start + size) - write;
|
||||
}
|
||||
|
||||
size_t readTillWrap(uint8_t n = 0) {
|
||||
return (start + size) - read[n];
|
||||
}
|
||||
|
||||
size_t getStart() const {
|
||||
return start;
|
||||
}
|
||||
|
||||
protected:
|
||||
const size_t start;
|
||||
size_t write;
|
||||
size_t read[N_READ_PTRS];
|
||||
const size_t size;
|
||||
const bool overwriteOld;
|
||||
void incrementWrite(uint32_t amount) {
|
||||
write = ((write + amount - start) % size) + start;
|
||||
}
|
||||
void incrementRead(uint32_t amount, uint8_t n = 0) {
|
||||
read[n] = ((read[n] + amount - start) % size) + start;
|
||||
}
|
||||
|
||||
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
||||
if (getAvailableReadData(n) >= amount) {
|
||||
incrementRead(amount, n);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t writeData(uint32_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t getRead(uint8_t n = 0) const {
|
||||
return read[n];
|
||||
}
|
||||
|
||||
void setRead(uint32_t read, uint8_t n = 0) {
|
||||
if (read >= start && read < (start+size)) {
|
||||
this->read[n] = read;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getWrite() const {
|
||||
return write;
|
||||
}
|
||||
|
||||
void setWrite(uint32_t write) {
|
||||
this->write = write;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */
|
||||
|
@ -1,30 +1,30 @@
|
||||
#include <framework/container/SharedRingBuffer.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
#include <framework/ipc/MutexHelper.h>
|
||||
|
||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
||||
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
|
||||
return mutex->lockMutex(timeoutType, timeout);
|
||||
}
|
||||
|
||||
ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
|
||||
return mutex->unlockMutex();
|
||||
}
|
||||
|
||||
MutexIF* SharedRingBuffer::getMutexHandle() const {
|
||||
return mutex;
|
||||
}
|
||||
#include "../container/SharedRingBuffer.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
|
||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||
maxExcessBytes) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
||||
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
|
||||
return mutex->lockMutex(timeoutType, timeout);
|
||||
}
|
||||
|
||||
ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
|
||||
return mutex->unlockMutex();
|
||||
}
|
||||
|
||||
MutexIF* SharedRingBuffer::getMutexHandle() const {
|
||||
return mutex;
|
||||
}
|
||||
|
@ -1,68 +1,68 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
|
||||
#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
|
||||
|
||||
#include <framework/container/SimpleRingBuffer.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
|
||||
/**
|
||||
* @brief Ring buffer which can be shared among multiple objects
|
||||
* @details
|
||||
* This class offers a mutex to perform thread-safe operation on the ring
|
||||
* buffer. It is still up to the developer to actually perform the lock
|
||||
* and unlock operations.
|
||||
*/
|
||||
class SharedRingBuffer: public SystemObject,
|
||||
public SimpleRingBuffer {
|
||||
public:
|
||||
/**
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
|
||||
/**
|
||||
* Unless a read-only constant value is read, all operations on the
|
||||
* shared ring buffer should be protected by calling this function.
|
||||
* @param timeoutType
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t timeout);
|
||||
/**
|
||||
* Any locked mutex also has to be unlocked, otherwise, access to the
|
||||
* shared ring buffer will be blocked.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t unlockRingBufferMutex();
|
||||
|
||||
/**
|
||||
* The mutex handle can be accessed directly, for example to perform
|
||||
* the lock with the #MutexHelper for a RAII compliant lock operation.
|
||||
* @return
|
||||
*/
|
||||
MutexIF* getMutexHandle() const;
|
||||
private:
|
||||
MutexIF* mutex = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */
|
||||
#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
|
||||
#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
|
||||
|
||||
#include "../container/SimpleRingBuffer.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../timemanager/Clock.h"
|
||||
|
||||
/**
|
||||
* @brief Ring buffer which can be shared among multiple objects
|
||||
* @details
|
||||
* This class offers a mutex to perform thread-safe operation on the ring
|
||||
* buffer. It is still up to the developer to actually perform the lock
|
||||
* and unlock operations.
|
||||
*/
|
||||
class SharedRingBuffer: public SystemObject,
|
||||
public SimpleRingBuffer {
|
||||
public:
|
||||
/**
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
*/
|
||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes);
|
||||
|
||||
/**
|
||||
* Unless a read-only constant value is read, all operations on the
|
||||
* shared ring buffer should be protected by calling this function.
|
||||
* @param timeoutType
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t timeout);
|
||||
/**
|
||||
* Any locked mutex also has to be unlocked, otherwise, access to the
|
||||
* shared ring buffer will be blocked.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t unlockRingBufferMutex();
|
||||
|
||||
/**
|
||||
* The mutex handle can be accessed directly, for example to perform
|
||||
* the lock with the #MutexHelper for a RAII compliant lock operation.
|
||||
* @return
|
||||
*/
|
||||
MutexIF* getMutexHandle() const;
|
||||
private:
|
||||
MutexIF* mutex = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */
|
||||
|
@ -1,127 +1,135 @@
|
||||
#include <framework/container/SimpleRingBuffer.h>
|
||||
#include <cstring>
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes) :
|
||||
RingBufferBase<>(0, size, overwriteOld),
|
||||
maxExcessBytes(maxExcessBytes) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
buffer = new uint8_t[size + maxExcessBytes];
|
||||
}
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SimpleRingBuffer::~SimpleRingBuffer() {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
||||
size_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap < amount) {
|
||||
if((amount - amountTillWrap + excessBytes) > maxExcessBytes) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
excessBytes = amount - amountTillWrap;
|
||||
}
|
||||
*writePointer = &buffer[write];
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||
size_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap >= amount) {
|
||||
// remaining size in buffer is sufficient to fit full amount.
|
||||
memcpy(&buffer[write], data, amount);
|
||||
}
|
||||
else {
|
||||
memcpy(&buffer[write], data, amountTillWrap);
|
||||
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
||||
}
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
||||
size_t availableData = availableReadData(READ_PTR);
|
||||
size_t amountTillWrap = readTillWrap(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (readRemaining) {
|
||||
// more data available than amount specified.
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
if (amountTillWrap >= amount) {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||
} else {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
||||
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
||||
}
|
||||
|
||||
if(incrementReadPtr) {
|
||||
deleteData(amount, readRemaining);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
size_t SimpleRingBuffer::getExcessBytes() const {
|
||||
return excessBytes;
|
||||
}
|
||||
|
||||
void SimpleRingBuffer::moveExcessBytesToStart() {
|
||||
if(excessBytes > 0) {
|
||||
std::memcpy(buffer, &buffer[size], excessBytes);
|
||||
excessBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
||||
bool deleteRemaining, size_t* trueAmount) {
|
||||
size_t availableData = availableReadData(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (deleteRemaining) {
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
incrementRead(amount, READ_PTR);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
#include "../container/SimpleRingBuffer.h"
|
||||
#include <cstring>
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes) :
|
||||
RingBufferBase<>(0, size, overwriteOld),
|
||||
maxExcessBytes(maxExcessBytes) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
buffer = new uint8_t[size + maxExcessBytes];
|
||||
}
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
|
||||
bool overwriteOld, size_t maxExcessBytes):
|
||||
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
||||
if(maxExcessBytes > size) {
|
||||
this->maxExcessBytes = size;
|
||||
}
|
||||
else {
|
||||
this->maxExcessBytes = maxExcessBytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SimpleRingBuffer::~SimpleRingBuffer() {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
||||
size_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap < amount) {
|
||||
if((amount - amountTillWrap + excessBytes) > maxExcessBytes) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
excessBytes = amount - amountTillWrap;
|
||||
}
|
||||
*writePointer = &buffer[write];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
|
||||
if(getExcessBytes() > 0) {
|
||||
moveExcessBytesToStart();
|
||||
}
|
||||
incrementWrite(amount);
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||
size_t amount) {
|
||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap >= amount) {
|
||||
// remaining size in buffer is sufficient to fit full amount.
|
||||
memcpy(&buffer[write], data, amount);
|
||||
}
|
||||
else {
|
||||
memcpy(&buffer[write], data, amountTillWrap);
|
||||
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
||||
}
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
||||
size_t availableData = getAvailableReadData(READ_PTR);
|
||||
size_t amountTillWrap = readTillWrap(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (readRemaining) {
|
||||
// more data available than amount specified.
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
if (amountTillWrap >= amount) {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||
} else {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
||||
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
||||
}
|
||||
|
||||
if(incrementReadPtr) {
|
||||
deleteData(amount, readRemaining);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
size_t SimpleRingBuffer::getExcessBytes() const {
|
||||
return excessBytes;
|
||||
}
|
||||
|
||||
void SimpleRingBuffer::moveExcessBytesToStart() {
|
||||
if(excessBytes > 0) {
|
||||
std::memcpy(buffer, &buffer[size], excessBytes);
|
||||
excessBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
||||
bool deleteRemaining, size_t* trueAmount) {
|
||||
size_t availableData = getAvailableReadData(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (deleteRemaining) {
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != nullptr) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
incrementRead(amount, READ_PTR);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,119 +1,128 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||
|
||||
#include <framework/container/RingBufferBase.h>
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief Circular buffer implementation, useful for buffering
|
||||
* into data streams.
|
||||
* @details
|
||||
* Note that the deleteData() has to be called to increment the read pointer.
|
||||
* This class allocated dynamically, so
|
||||
* @ingroup containers
|
||||
*/
|
||||
class SimpleRingBuffer: public RingBufferBase<> {
|
||||
public:
|
||||
/**
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
*
|
||||
* @param size
|
||||
* @param overwriteOld If the ring buffer is overflowing at a write
|
||||
* operation, the oldest data will be overwritten.
|
||||
* @param maxExcessBytes These additional bytes will be allocated in addtion
|
||||
* to the specified size to accomodate contiguous write operations
|
||||
* with getFreeElement.
|
||||
*
|
||||
*/
|
||||
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
* @param maxExcessBytes
|
||||
* If the buffer can accomodate additional bytes for contigous write
|
||||
* operations with getFreeElement, this is the maximum allowed additional
|
||||
* size
|
||||
*/
|
||||
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
|
||||
virtual ~SimpleRingBuffer();
|
||||
|
||||
/**
|
||||
* Write to circular buffer and increment write pointer by amount.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @return -@c RETURN_OK if write operation was successfull
|
||||
* -@c RETURN_FAILED if
|
||||
*/
|
||||
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
||||
|
||||
/**
|
||||
* Returns a pointer to a free element. If the remaining buffer is
|
||||
* not large enough, the data will be written past the actual size
|
||||
* and the amount of excess bytes will be cached.
|
||||
* @param writePointer Pointer to a pointer which can be used to write
|
||||
* contiguous blocks into the ring buffer
|
||||
* @param amount
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
||||
|
||||
virtual size_t getExcessBytes() const;
|
||||
/**
|
||||
* Helper functions which moves any excess bytes to the start
|
||||
* of the ring buffer.
|
||||
* @return
|
||||
*/
|
||||
virtual void moveExcessBytesToStart();
|
||||
|
||||
/**
|
||||
* Read from circular buffer at read pointer.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @param incrementReadPtr
|
||||
* If this is set to true, the read pointer will be incremented.
|
||||
* If readRemaining is set to true, the read pointer will be incremented
|
||||
* accordingly.
|
||||
* @param readRemaining
|
||||
* If this is set to true, the data will be read even if the amount
|
||||
* specified exceeds the read data available.
|
||||
* @param trueAmount [out]
|
||||
* If readRemaining was set to true, the true amount read will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
* - @c RETURN_OK if data was read successfully
|
||||
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
||||
* was set to false.
|
||||
*/
|
||||
ReturnValue_t readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr = false, bool readRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
|
||||
/**
|
||||
* Delete data by incrementing read pointer.
|
||||
* @param amount
|
||||
* @param deleteRemaining
|
||||
* If the amount specified is larger than the remaing size to read and this
|
||||
* is set to true, the remaining amount will be deleted as well
|
||||
* @param trueAmount [out]
|
||||
* If deleteRemaining was set to true, the amount deleted will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
private:
|
||||
static const uint8_t READ_PTR = 0;
|
||||
uint8_t* buffer = nullptr;
|
||||
size_t maxExcessBytes;
|
||||
size_t excessBytes = 0;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */
|
||||
|
||||
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||
|
||||
#include "../container/RingBufferBase.h"
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief Circular buffer implementation, useful for buffering
|
||||
* into data streams.
|
||||
* @details
|
||||
* Note that the deleteData() has to be called to increment the read pointer.
|
||||
* This class allocated dynamically, so
|
||||
* @ingroup containers
|
||||
*/
|
||||
class SimpleRingBuffer: public RingBufferBase<> {
|
||||
public:
|
||||
/**
|
||||
* This constructor allocates a new internal buffer with the supplied size.
|
||||
*
|
||||
* @param size
|
||||
* @param overwriteOld If the ring buffer is overflowing at a write
|
||||
* operation, the oldest data will be overwritten.
|
||||
* @param maxExcessBytes These additional bytes will be allocated in addtion
|
||||
* to the specified size to accomodate contiguous write operations
|
||||
* with getFreeElement.
|
||||
*
|
||||
*/
|
||||
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
/**
|
||||
* This constructor takes an external buffer with the specified size.
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param overwriteOld
|
||||
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||
* will be overwritten.
|
||||
* @param maxExcessBytes
|
||||
* If the buffer can accomodate additional bytes for contigous write
|
||||
* operations with getFreeElement, this is the maximum allowed additional
|
||||
* size
|
||||
*/
|
||||
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
|
||||
size_t maxExcessBytes = 0);
|
||||
|
||||
virtual ~SimpleRingBuffer();
|
||||
|
||||
/**
|
||||
* Write to circular buffer and increment write pointer by amount.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @return -@c RETURN_OK if write operation was successfull
|
||||
* -@c RETURN_FAILED if
|
||||
*/
|
||||
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
||||
|
||||
/**
|
||||
* Returns a pointer to a free element. If the remaining buffer is
|
||||
* not large enough, the data will be written past the actual size
|
||||
* and the amount of excess bytes will be cached. This function
|
||||
* does not increment the write pointer!
|
||||
* @param writePointer Pointer to a pointer which can be used to write
|
||||
* contiguous blocks into the ring buffer
|
||||
* @param amount
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
||||
|
||||
/**
|
||||
* This increments the write pointer and also copies the excess bytes
|
||||
* to the beginning. It should be called if the write operation
|
||||
* conducted after calling getFreeElement() was performed.
|
||||
* @return
|
||||
*/
|
||||
void confirmBytesWritten(size_t amount);
|
||||
|
||||
virtual size_t getExcessBytes() const;
|
||||
/**
|
||||
* Helper functions which moves any excess bytes to the start
|
||||
* of the ring buffer.
|
||||
* @return
|
||||
*/
|
||||
virtual void moveExcessBytesToStart();
|
||||
|
||||
/**
|
||||
* Read from circular buffer at read pointer.
|
||||
* @param data
|
||||
* @param amount
|
||||
* @param incrementReadPtr
|
||||
* If this is set to true, the read pointer will be incremented.
|
||||
* If readRemaining is set to true, the read pointer will be incremented
|
||||
* accordingly.
|
||||
* @param readRemaining
|
||||
* If this is set to true, the data will be read even if the amount
|
||||
* specified exceeds the read data available.
|
||||
* @param trueAmount [out]
|
||||
* If readRemaining was set to true, the true amount read will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
* - @c RETURN_OK if data was read successfully
|
||||
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
||||
* was set to false.
|
||||
*/
|
||||
ReturnValue_t readData(uint8_t* data, size_t amount,
|
||||
bool incrementReadPtr = false, bool readRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
|
||||
/**
|
||||
* Delete data by incrementing read pointer.
|
||||
* @param amount
|
||||
* @param deleteRemaining
|
||||
* If the amount specified is larger than the remaing size to read and this
|
||||
* is set to true, the remaining amount will be deleted as well
|
||||
* @param trueAmount [out]
|
||||
* If deleteRemaining was set to true, the amount deleted will be assigned
|
||||
* to the passed value.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
||||
size_t* trueAmount = nullptr);
|
||||
private:
|
||||
static const uint8_t READ_PTR = 0;
|
||||
uint8_t* buffer = nullptr;
|
||||
size_t maxExcessBytes;
|
||||
size_t excessBytes = 0;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */
|
||||
|
||||
|
@ -1,137 +1,137 @@
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
#include <framework/controller/ControllerBase.h>
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
|
||||
ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
|
||||
SUBMODE_NONE), commandQueue(NULL), modeHelper(
|
||||
this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
if (parentId != 0) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
|
||||
parent->registerChild(getObjectId());
|
||||
}
|
||||
|
||||
result = healthHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = modeHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkSwitcher.initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void ControllerBase::handleQueue() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result;
|
||||
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
|
||||
result = modeHelper.handleModeCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = healthHelper.handleHealthCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
result = handleCommandMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
changeHK(this->mode, this->submode, true);
|
||||
}
|
||||
|
||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
*mode = this->mode;
|
||||
*submode = this->submode;
|
||||
}
|
||||
|
||||
void ControllerBase::setToExternalControl() {
|
||||
healthHelper.setHealth(EXTERNAL_CONTROL);
|
||||
}
|
||||
|
||||
void ControllerBase::announceMode(bool recursive) {
|
||||
triggerEvent(MODE_INFO, mode, submode);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
hkSwitcher.performOperation();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
switch (health) {
|
||||
case HEALTHY:
|
||||
case EXTERNAL_CONTROL:
|
||||
healthHelper.setHealth(health);
|
||||
return RETURN_OK;
|
||||
default:
|
||||
return INVALID_HEALTH_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||
return healthHelper.getHealth();
|
||||
}
|
||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
}
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "../controller/ControllerBase.h"
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../action/HasActionsIF.h"
|
||||
|
||||
ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
|
||||
SUBMODE_NONE), commandQueue(NULL), modeHelper(
|
||||
this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
if (parentId != 0) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
|
||||
parent->registerChild(getObjectId());
|
||||
}
|
||||
|
||||
result = healthHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = modeHelper.initialize(parentQueue);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkSwitcher.initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void ControllerBase::handleQueue() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result;
|
||||
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
|
||||
result = modeHelper.handleModeCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = healthHelper.handleHealthCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
result = handleCommandMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
changeHK(this->mode, this->submode, true);
|
||||
}
|
||||
|
||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
*mode = this->mode;
|
||||
*submode = this->submode;
|
||||
}
|
||||
|
||||
void ControllerBase::setToExternalControl() {
|
||||
healthHelper.setHealth(EXTERNAL_CONTROL);
|
||||
}
|
||||
|
||||
void ControllerBase::announceMode(bool recursive) {
|
||||
triggerEvent(MODE_INFO, mode, submode);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
hkSwitcher.performOperation();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
switch (health) {
|
||||
case HEALTHY:
|
||||
case EXTERNAL_CONTROL:
|
||||
healthHelper.setHealth(health);
|
||||
return RETURN_OK;
|
||||
default:
|
||||
return INVALID_HEALTH_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||
return healthHelper.getHealth();
|
||||
}
|
||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
}
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
@ -1,79 +1,79 @@
|
||||
#ifndef CONTROLLERBASE_H_
|
||||
#define CONTROLLERBASE_H_
|
||||
|
||||
#include <framework/health/HasHealthIF.h>
|
||||
#include <framework/health/HealthHelper.h>
|
||||
#include <framework/modes/HasModesIF.h>
|
||||
#include <framework/modes/ModeHelper.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/datapool/HkSwitchHelper.h>
|
||||
|
||||
|
||||
class ControllerBase: public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
|
||||
ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
virtual ReturnValue_t setHealth(HealthState health);
|
||||
|
||||
virtual HasHealthIF::HealthState getHealth();
|
||||
|
||||
/**
|
||||
* Implementation of ExecutableObjectIF function
|
||||
*
|
||||
* Used to setup the reference of the task, that executes this component
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_);
|
||||
|
||||
|
||||
protected:
|
||||
const uint32_t parentId;
|
||||
|
||||
Mode_t mode;
|
||||
|
||||
Submode_t submode;
|
||||
|
||||
MessageQueueIF* commandQueue;
|
||||
|
||||
ModeHelper modeHelper;
|
||||
|
||||
HealthHelper healthHelper;
|
||||
|
||||
HkSwitchHelper hkSwitcher;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask;
|
||||
|
||||
void handleQueue();
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
virtual void performControlOperation() = 0;
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) = 0;
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void announceMode(bool recursive);
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERBASE_H_ */
|
||||
#ifndef CONTROLLERBASE_H_
|
||||
#define CONTROLLERBASE_H_
|
||||
|
||||
#include "../health/HasHealthIF.h"
|
||||
#include "../health/HealthHelper.h"
|
||||
#include "../modes/HasModesIF.h"
|
||||
#include "../modes/ModeHelper.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../datapool/HkSwitchHelper.h"
|
||||
|
||||
|
||||
class ControllerBase: public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
|
||||
ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
virtual ReturnValue_t setHealth(HealthState health);
|
||||
|
||||
virtual HasHealthIF::HealthState getHealth();
|
||||
|
||||
/**
|
||||
* Implementation of ExecutableObjectIF function
|
||||
*
|
||||
* Used to setup the reference of the task, that executes this component
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_);
|
||||
|
||||
|
||||
protected:
|
||||
const uint32_t parentId;
|
||||
|
||||
Mode_t mode;
|
||||
|
||||
Submode_t submode;
|
||||
|
||||
MessageQueueIF* commandQueue;
|
||||
|
||||
ModeHelper modeHelper;
|
||||
|
||||
HealthHelper healthHelper;
|
||||
|
||||
HkSwitchHelper hkSwitcher;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask;
|
||||
|
||||
void handleQueue();
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
virtual void performControlOperation() = 0;
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) = 0;
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void announceMode(bool recursive);
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERBASE_H_ */
|
||||
|
@ -1,227 +1,227 @@
|
||||
#include <framework/coordinates/CoordinateTransformations.h>
|
||||
#include <framework/globalfunctions/constants.h>
|
||||
#include <framework/globalfunctions/math/MatrixOperations.h>
|
||||
#include <framework/globalfunctions/math/VectorOperations.h>
|
||||
#include <stddef.h>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition,
|
||||
double* eciPosition, timeval *timeUTC) {
|
||||
ecfToEci(ecfPosition, eciPosition, NULL, timeUTC);
|
||||
|
||||
}
|
||||
|
||||
void CoordinateTransformations::velocityEcfToEci(const double* ecfVelocity,
|
||||
const double* ecfPosition, double* eciVelocity, timeval *timeUTC) {
|
||||
ecfToEci(ecfVelocity, eciVelocity, ecfPosition, timeUTC);
|
||||
}
|
||||
|
||||
void CoordinateTransformations::positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC){
|
||||
eciToEcf(eciCoordinates,ecfCoordinates,NULL,timeUTC);
|
||||
};
|
||||
|
||||
void CoordinateTransformations::velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC){
|
||||
eciToEcf(eciVelocity,ecfVelocity,eciPosition,timeUTC);
|
||||
}
|
||||
|
||||
double CoordinateTransformations::getEarthRotationAngle(timeval timeUTC) {
|
||||
|
||||
double jD2000UTC;
|
||||
Clock::convertTimevalToJD2000(timeUTC, &jD2000UTC);
|
||||
|
||||
double TTt2000 = getJuleanCenturiesTT(timeUTC);
|
||||
|
||||
double theta = 2 * Math::PI
|
||||
* (0.779057273264 + 1.00273781191135448 * jD2000UTC);
|
||||
|
||||
//Correct theta according to IAU 2000 precession-nutation model
|
||||
theta = theta + 7.03270725817493E-008 + 0.0223603701 * TTt2000
|
||||
+ 6.77128219501896E-006 * TTt2000 * TTt2000
|
||||
+ 4.5300990362875E-010 * TTt2000 * TTt2000 * TTt2000
|
||||
+ 9.12419347848147E-011 * TTt2000 * TTt2000 * TTt2000 * TTt2000;
|
||||
return theta;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::getEarthRotationMatrix(timeval timeUTC,
|
||||
double matrix[][3]) {
|
||||
double theta = getEarthRotationAngle(timeUTC);
|
||||
|
||||
matrix[0][0] = cos(theta);
|
||||
matrix[0][1] = sin(theta);
|
||||
matrix[0][2] = 0;
|
||||
matrix[1][0] = -sin(theta);
|
||||
matrix[1][1] = cos(theta);
|
||||
matrix[1][2] = 0;
|
||||
matrix[2][0] = 0;
|
||||
matrix[2][1] = 0;
|
||||
matrix[2][2] = 1;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::ecfToEci(const double* ecfCoordinates,
|
||||
double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin) {
|
||||
|
||||
timeval timeUTC;
|
||||
if (timeUTCin != NULL) {
|
||||
timeUTC = *timeUTCin;
|
||||
} else {
|
||||
Clock::getClock_timeval(&timeUTC);
|
||||
}
|
||||
|
||||
double Tfi[3][3];
|
||||
double Tif[3][3];
|
||||
getTransMatrixECITOECF(timeUTC,Tfi);
|
||||
|
||||
MatrixOperations<double>::transpose(Tfi[0], Tif[0], 3);
|
||||
|
||||
MatrixOperations<double>::multiply(Tif[0], ecfCoordinates, eciCoordinates,
|
||||
3, 3, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
if (ecfPositionIfCoordinatesAreVelocity != NULL) {
|
||||
|
||||
double Tdotfi[3][3];
|
||||
double Tdotif[3][3];
|
||||
double Trot[3][3] = { { 0, Earth::OMEGA, 0 },
|
||||
{ 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } };
|
||||
|
||||
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
|
||||
3);
|
||||
|
||||
MatrixOperations<double>::transpose(Tdotfi[0], Tdotif[0], 3);
|
||||
|
||||
double velocityCorrection[3];
|
||||
|
||||
MatrixOperations<double>::multiply(Tdotif[0],
|
||||
ecfPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
|
||||
1);
|
||||
|
||||
VectorOperations<double>::add(velocityCorrection, eciCoordinates,
|
||||
eciCoordinates, 3);
|
||||
}
|
||||
}
|
||||
|
||||
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
|
||||
timeval timeTT;
|
||||
Clock::convertUTCToTT(timeUTC, &timeTT);
|
||||
double jD2000TT;
|
||||
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
|
||||
|
||||
return jD2000TT / 36525.;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::eciToEcf(const double* eciCoordinates,
|
||||
double* ecfCoordinates,
|
||||
const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin){
|
||||
timeval timeUTC;
|
||||
if (timeUTCin != NULL) {
|
||||
timeUTC = *timeUTCin;
|
||||
}else{
|
||||
Clock::getClock_timeval(&timeUTC);
|
||||
}
|
||||
|
||||
double Tfi[3][3];
|
||||
|
||||
getTransMatrixECITOECF(timeUTC,Tfi);
|
||||
|
||||
MatrixOperations<double>::multiply(Tfi[0],eciCoordinates,ecfCoordinates,3,3,1);
|
||||
|
||||
if (eciPositionIfCoordinatesAreVelocity != NULL) {
|
||||
|
||||
double Tdotfi[3][3];
|
||||
double Trot[3][3] = { { 0, Earth::OMEGA, 0 },
|
||||
{ 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } };
|
||||
|
||||
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
|
||||
3);
|
||||
|
||||
double velocityCorrection[3];
|
||||
|
||||
MatrixOperations<double>::multiply(Tdotfi[0],
|
||||
eciPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
|
||||
1);
|
||||
|
||||
VectorOperations<double>::add(ecfCoordinates, velocityCorrection,
|
||||
ecfCoordinates, 3);
|
||||
}
|
||||
};
|
||||
|
||||
void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC,double Tfi[3][3]){
|
||||
double TTt2000 = getJuleanCenturiesTT(timeUTC);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Precession Matrix
|
||||
|
||||
double zeta = 0.0111808609 * TTt2000
|
||||
+ 1.46355554053347E-006 * TTt2000 * TTt2000
|
||||
+ 8.72567663260943E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
double theta_p = 0.0097171735 * TTt2000
|
||||
- 2.06845757045384E-006 * TTt2000 * TTt2000
|
||||
- 2.02812107218552E-007 * TTt2000 * TTt2000 * TTt2000;
|
||||
double z = zeta + 3.8436028638364E-006 * TTt2000 * TTt2000
|
||||
+ 0.000000001 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double mPrecession[3][3];
|
||||
|
||||
mPrecession[0][0] = -sin(z) * sin(zeta) + cos(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[1][0] = cos(z) * sin(zeta) + sin(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[2][0] = sin(theta_p) * cos(zeta);
|
||||
|
||||
mPrecession[0][1] = -sin(z) * cos(zeta) - cos(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[1][1] = cos(z) * cos(zeta) - sin(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[2][1] = -sin(theta_p) * sin(zeta);
|
||||
|
||||
mPrecession[0][2] = -cos(z) * sin(theta_p);
|
||||
mPrecession[1][2] = -sin(z) * sin(theta_p);
|
||||
mPrecession[2][2] = cos(theta_p);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Nutation Matrix
|
||||
|
||||
double omega_moon = 2.1824386244 - 33.7570459338 * TTt2000
|
||||
+ 3.61428599267159E-005 * TTt2000 * TTt2000
|
||||
+ 3.87850944887629E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double deltaPsi = -0.000083388 * sin(omega_moon);
|
||||
double deltaEpsilon = 4.46174030725106E-005 * cos(omega_moon);
|
||||
|
||||
double epsilon = 0.4090928042 - 0.0002269655 * TTt2000
|
||||
- 2.86040071854626E-009 * TTt2000 * TTt2000
|
||||
+ 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
|
||||
double mNutation[3][3];
|
||||
|
||||
mNutation[0][0] = cos(deltaPsi);
|
||||
mNutation[1][0] = cos(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
mNutation[2][0] = sin(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
|
||||
mNutation[0][1] = -cos(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][1] = cos(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ sin(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][1] = cos(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- sin(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
mNutation[0][2] = -sin(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][2] = sin(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- cos(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][2] = sin(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ cos(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Earth rotation matrix
|
||||
//calculate theta
|
||||
|
||||
double mTheta[3][3];
|
||||
double Ttemp[3][3];
|
||||
getEarthRotationMatrix(timeUTC, mTheta);
|
||||
|
||||
//polar motion is neglected
|
||||
MatrixOperations<double>::multiply(mNutation[0], mPrecession[0], Ttemp[0],
|
||||
3, 3, 3);
|
||||
|
||||
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
|
||||
};
|
||||
#include "../coordinates/CoordinateTransformations.h"
|
||||
#include "../globalfunctions/constants.h"
|
||||
#include "../globalfunctions/math/MatrixOperations.h"
|
||||
#include "../globalfunctions/math/VectorOperations.h"
|
||||
#include <stddef.h>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition,
|
||||
double* eciPosition, timeval *timeUTC) {
|
||||
ecfToEci(ecfPosition, eciPosition, NULL, timeUTC);
|
||||
|
||||
}
|
||||
|
||||
void CoordinateTransformations::velocityEcfToEci(const double* ecfVelocity,
|
||||
const double* ecfPosition, double* eciVelocity, timeval *timeUTC) {
|
||||
ecfToEci(ecfVelocity, eciVelocity, ecfPosition, timeUTC);
|
||||
}
|
||||
|
||||
void CoordinateTransformations::positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC){
|
||||
eciToEcf(eciCoordinates,ecfCoordinates,NULL,timeUTC);
|
||||
};
|
||||
|
||||
void CoordinateTransformations::velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC){
|
||||
eciToEcf(eciVelocity,ecfVelocity,eciPosition,timeUTC);
|
||||
}
|
||||
|
||||
double CoordinateTransformations::getEarthRotationAngle(timeval timeUTC) {
|
||||
|
||||
double jD2000UTC;
|
||||
Clock::convertTimevalToJD2000(timeUTC, &jD2000UTC);
|
||||
|
||||
double TTt2000 = getJuleanCenturiesTT(timeUTC);
|
||||
|
||||
double theta = 2 * Math::PI
|
||||
* (0.779057273264 + 1.00273781191135448 * jD2000UTC);
|
||||
|
||||
//Correct theta according to IAU 2000 precession-nutation model
|
||||
theta = theta + 7.03270725817493E-008 + 0.0223603701 * TTt2000
|
||||
+ 6.77128219501896E-006 * TTt2000 * TTt2000
|
||||
+ 4.5300990362875E-010 * TTt2000 * TTt2000 * TTt2000
|
||||
+ 9.12419347848147E-011 * TTt2000 * TTt2000 * TTt2000 * TTt2000;
|
||||
return theta;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::getEarthRotationMatrix(timeval timeUTC,
|
||||
double matrix[][3]) {
|
||||
double theta = getEarthRotationAngle(timeUTC);
|
||||
|
||||
matrix[0][0] = cos(theta);
|
||||
matrix[0][1] = sin(theta);
|
||||
matrix[0][2] = 0;
|
||||
matrix[1][0] = -sin(theta);
|
||||
matrix[1][1] = cos(theta);
|
||||
matrix[1][2] = 0;
|
||||
matrix[2][0] = 0;
|
||||
matrix[2][1] = 0;
|
||||
matrix[2][2] = 1;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::ecfToEci(const double* ecfCoordinates,
|
||||
double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin) {
|
||||
|
||||
timeval timeUTC;
|
||||
if (timeUTCin != NULL) {
|
||||
timeUTC = *timeUTCin;
|
||||
} else {
|
||||
Clock::getClock_timeval(&timeUTC);
|
||||
}
|
||||
|
||||
double Tfi[3][3];
|
||||
double Tif[3][3];
|
||||
getTransMatrixECITOECF(timeUTC,Tfi);
|
||||
|
||||
MatrixOperations<double>::transpose(Tfi[0], Tif[0], 3);
|
||||
|
||||
MatrixOperations<double>::multiply(Tif[0], ecfCoordinates, eciCoordinates,
|
||||
3, 3, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
if (ecfPositionIfCoordinatesAreVelocity != NULL) {
|
||||
|
||||
double Tdotfi[3][3];
|
||||
double Tdotif[3][3];
|
||||
double Trot[3][3] = { { 0, Earth::OMEGA, 0 },
|
||||
{ 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } };
|
||||
|
||||
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
|
||||
3);
|
||||
|
||||
MatrixOperations<double>::transpose(Tdotfi[0], Tdotif[0], 3);
|
||||
|
||||
double velocityCorrection[3];
|
||||
|
||||
MatrixOperations<double>::multiply(Tdotif[0],
|
||||
ecfPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
|
||||
1);
|
||||
|
||||
VectorOperations<double>::add(velocityCorrection, eciCoordinates,
|
||||
eciCoordinates, 3);
|
||||
}
|
||||
}
|
||||
|
||||
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
|
||||
timeval timeTT;
|
||||
Clock::convertUTCToTT(timeUTC, &timeTT);
|
||||
double jD2000TT;
|
||||
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
|
||||
|
||||
return jD2000TT / 36525.;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::eciToEcf(const double* eciCoordinates,
|
||||
double* ecfCoordinates,
|
||||
const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin){
|
||||
timeval timeUTC;
|
||||
if (timeUTCin != NULL) {
|
||||
timeUTC = *timeUTCin;
|
||||
}else{
|
||||
Clock::getClock_timeval(&timeUTC);
|
||||
}
|
||||
|
||||
double Tfi[3][3];
|
||||
|
||||
getTransMatrixECITOECF(timeUTC,Tfi);
|
||||
|
||||
MatrixOperations<double>::multiply(Tfi[0],eciCoordinates,ecfCoordinates,3,3,1);
|
||||
|
||||
if (eciPositionIfCoordinatesAreVelocity != NULL) {
|
||||
|
||||
double Tdotfi[3][3];
|
||||
double Trot[3][3] = { { 0, Earth::OMEGA, 0 },
|
||||
{ 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } };
|
||||
|
||||
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
|
||||
3);
|
||||
|
||||
double velocityCorrection[3];
|
||||
|
||||
MatrixOperations<double>::multiply(Tdotfi[0],
|
||||
eciPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
|
||||
1);
|
||||
|
||||
VectorOperations<double>::add(ecfCoordinates, velocityCorrection,
|
||||
ecfCoordinates, 3);
|
||||
}
|
||||
};
|
||||
|
||||
void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC,double Tfi[3][3]){
|
||||
double TTt2000 = getJuleanCenturiesTT(timeUTC);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Precession Matrix
|
||||
|
||||
double zeta = 0.0111808609 * TTt2000
|
||||
+ 1.46355554053347E-006 * TTt2000 * TTt2000
|
||||
+ 8.72567663260943E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
double theta_p = 0.0097171735 * TTt2000
|
||||
- 2.06845757045384E-006 * TTt2000 * TTt2000
|
||||
- 2.02812107218552E-007 * TTt2000 * TTt2000 * TTt2000;
|
||||
double z = zeta + 3.8436028638364E-006 * TTt2000 * TTt2000
|
||||
+ 0.000000001 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double mPrecession[3][3];
|
||||
|
||||
mPrecession[0][0] = -sin(z) * sin(zeta) + cos(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[1][0] = cos(z) * sin(zeta) + sin(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[2][0] = sin(theta_p) * cos(zeta);
|
||||
|
||||
mPrecession[0][1] = -sin(z) * cos(zeta) - cos(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[1][1] = cos(z) * cos(zeta) - sin(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[2][1] = -sin(theta_p) * sin(zeta);
|
||||
|
||||
mPrecession[0][2] = -cos(z) * sin(theta_p);
|
||||
mPrecession[1][2] = -sin(z) * sin(theta_p);
|
||||
mPrecession[2][2] = cos(theta_p);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Nutation Matrix
|
||||
|
||||
double omega_moon = 2.1824386244 - 33.7570459338 * TTt2000
|
||||
+ 3.61428599267159E-005 * TTt2000 * TTt2000
|
||||
+ 3.87850944887629E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double deltaPsi = -0.000083388 * sin(omega_moon);
|
||||
double deltaEpsilon = 4.46174030725106E-005 * cos(omega_moon);
|
||||
|
||||
double epsilon = 0.4090928042 - 0.0002269655 * TTt2000
|
||||
- 2.86040071854626E-009 * TTt2000 * TTt2000
|
||||
+ 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
|
||||
double mNutation[3][3];
|
||||
|
||||
mNutation[0][0] = cos(deltaPsi);
|
||||
mNutation[1][0] = cos(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
mNutation[2][0] = sin(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
|
||||
mNutation[0][1] = -cos(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][1] = cos(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ sin(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][1] = cos(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- sin(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
mNutation[0][2] = -sin(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][2] = sin(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- cos(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][2] = sin(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ cos(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Earth rotation matrix
|
||||
//calculate theta
|
||||
|
||||
double mTheta[3][3];
|
||||
double Ttemp[3][3];
|
||||
getEarthRotationMatrix(timeUTC, mTheta);
|
||||
|
||||
//polar motion is neglected
|
||||
MatrixOperations<double>::multiply(mNutation[0], mPrecession[0], Ttemp[0],
|
||||
3, 3, 3);
|
||||
|
||||
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
|
||||
};
|
||||
|
@ -1,34 +1,34 @@
|
||||
#ifndef COORDINATETRANSFORMATIONS_H_
|
||||
#define COORDINATETRANSFORMATIONS_H_
|
||||
|
||||
#include <framework/timemanager/Clock.h>
|
||||
#include <cstring>
|
||||
|
||||
class CoordinateTransformations {
|
||||
public:
|
||||
static void positionEcfToEci(const double* ecfCoordinates, double* eciCoordinates, timeval *timeUTC = NULL);
|
||||
|
||||
static void velocityEcfToEci(const double* ecfVelocity,
|
||||
const double* ecfPosition,
|
||||
double* eciVelocity, timeval *timeUTC = NULL);
|
||||
|
||||
static void positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC = NULL);
|
||||
static void velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC = NULL);
|
||||
|
||||
static double getEarthRotationAngle(timeval timeUTC);
|
||||
|
||||
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
|
||||
private:
|
||||
CoordinateTransformations();
|
||||
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin);
|
||||
static void eciToEcf(const double* eciCoordinates,
|
||||
double* ecfCoordinates,
|
||||
const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin);
|
||||
|
||||
static double getJuleanCenturiesTT(timeval timeUTC);
|
||||
static void getTransMatrixECITOECF(timeval time,double Tfi[3][3]);
|
||||
|
||||
};
|
||||
|
||||
#endif /* COORDINATETRANSFORMATIONS_H_ */
|
||||
#ifndef COORDINATETRANSFORMATIONS_H_
|
||||
#define COORDINATETRANSFORMATIONS_H_
|
||||
|
||||
#include "../timemanager/Clock.h"
|
||||
#include <cstring>
|
||||
|
||||
class CoordinateTransformations {
|
||||
public:
|
||||
static void positionEcfToEci(const double* ecfCoordinates, double* eciCoordinates, timeval *timeUTC = NULL);
|
||||
|
||||
static void velocityEcfToEci(const double* ecfVelocity,
|
||||
const double* ecfPosition,
|
||||
double* eciVelocity, timeval *timeUTC = NULL);
|
||||
|
||||
static void positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC = NULL);
|
||||
static void velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC = NULL);
|
||||
|
||||
static double getEarthRotationAngle(timeval timeUTC);
|
||||
|
||||
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
|
||||
private:
|
||||
CoordinateTransformations();
|
||||
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin);
|
||||
static void eciToEcf(const double* eciCoordinates,
|
||||
double* ecfCoordinates,
|
||||
const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin);
|
||||
|
||||
static double getJuleanCenturiesTT(timeval timeUTC);
|
||||
static void getTransMatrixECITOECF(timeval time,double Tfi[3][3]);
|
||||
|
||||
};
|
||||
|
||||
#endif /* COORDINATETRANSFORMATIONS_H_ */
|
||||
|
@ -1,180 +1,180 @@
|
||||
#ifndef FRAMEWORK_COORDINATES_JGM3MODEL_H_
|
||||
#define FRAMEWORK_COORDINATES_JGM3MODEL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <framework/coordinates/CoordinateTransformations.h>
|
||||
#include <framework/globalfunctions/math/VectorOperations.h>
|
||||
#include <framework/globalfunctions/timevalOperations.h>
|
||||
#include <framework/globalfunctions/constants.h>
|
||||
#include <memory.h>
|
||||
|
||||
|
||||
template<uint8_t DEGREE,uint8_t ORDER>
|
||||
class Jgm3Model {
|
||||
public:
|
||||
static const uint32_t factorialLookupTable[DEGREE+3]; //This table is used instead of factorial calculation, must be increased if order or degree is higher
|
||||
|
||||
Jgm3Model() {
|
||||
y0[0] = 0;
|
||||
y0[1] = 0;
|
||||
y0[2] = 0;
|
||||
y0[3] = 0;
|
||||
y0[4] = 0;
|
||||
y0[5] = 0;
|
||||
|
||||
lastExecutionTime.tv_sec = 0;
|
||||
lastExecutionTime.tv_usec = 0;
|
||||
}
|
||||
virtual ~Jgm3Model(){};
|
||||
|
||||
//double acsNavOrbit(double posECF[3],double velECF[3],timeval gpsTime);
|
||||
|
||||
double y0[6]; //position and velocity at beginning of RK step in EC
|
||||
timeval lastExecutionTime; //Time of last execution
|
||||
|
||||
|
||||
void accelDegOrd(const double pos[3],const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1],double* accel){
|
||||
//Get radius of this position
|
||||
double r = VectorOperations<double>::norm(pos,3);
|
||||
|
||||
|
||||
|
||||
//Initialize the V and W matrix
|
||||
double V[DEGREE+2][ORDER+2] = {{0}};
|
||||
double W[DEGREE+2][ORDER+2] = {{0}};
|
||||
|
||||
for(uint8_t m=0;m<(ORDER+2);m++){
|
||||
for(uint8_t n=m;n<(DEGREE+2);n++){
|
||||
if((n==0) && (m==0)){
|
||||
//Montenbruck "Satellite Orbits Eq.3.31"
|
||||
V[0][0] = Earth::MEAN_RADIUS / r;
|
||||
W[0][0] = 0;
|
||||
}else{
|
||||
if(n==m){
|
||||
//Montenbruck "Satellite Orbits Eq.3.29"
|
||||
V[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1] - pos[1]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1]);
|
||||
W[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1] + pos[1]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1]);
|
||||
}else{
|
||||
//Montenbruck "Satellite Orbits Eq.3.30"
|
||||
V[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*V[n-1][m];
|
||||
W[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*W[n-1][m];
|
||||
if(n!=(m+1)){
|
||||
V[n][m] = V[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * V[n-2][m]);
|
||||
W[n][m] = W[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * W[n-2][m]);
|
||||
}//End of if(n!=(m+1))
|
||||
}//End of if(n==m){
|
||||
}//End of if(n==0 and m==0)
|
||||
}//End of for(uint8_t n=0;n<(DEGREE+1);n++)
|
||||
}//End of for(uint8_t m=0;m<(ORDER+1);m++)
|
||||
|
||||
|
||||
//overwrite accel if not properly initialized
|
||||
accel[0] = 0;
|
||||
accel[1] = 0;
|
||||
accel[2] = 0;
|
||||
|
||||
for(uint8_t m=0;m<(ORDER+1);m++){
|
||||
for(uint8_t n=m;n<(DEGREE+1);n++){
|
||||
//Use table lookup to get factorial
|
||||
double partAccel[3] = {0};
|
||||
double factor = Earth::STANDARD_GRAVITATIONAL_PARAMETER/pow(Earth::MEAN_RADIUS,2);
|
||||
if(m==0){
|
||||
//Montenbruck "Satellite Orbits Eq.3.33"
|
||||
partAccel[0] = factor * (-C[n][0]*V[n+1][1]);
|
||||
partAccel[1] = factor * (-C[n][0]*W[n+1][1]);
|
||||
}else{
|
||||
double factMN = static_cast<double>(factorialLookupTable[n-m+2]) / static_cast<double>(factorialLookupTable[n-m]);
|
||||
partAccel[0] = factor * 0.5 * ((-C[n][m]*V[n+1][m+1]-S[n][m]*W[n+1][m+1])+factMN*(C[n][m]*V[n+1][m-1]+S[n][m]*W[n+1][m-1]));
|
||||
partAccel[1] = factor * 0.5 * ((-C[n][m]*W[n+1][m+1]+S[n][m]*V[n+1][m+1])+factMN*(-C[n][m]*W[n+1][m-1]+S[n][m]*V[n+1][m-1]));
|
||||
}
|
||||
|
||||
partAccel[2] = factor * ((n-m+1)*(-C[n][m]*V[n+1][m]-S[n][m]*W[n+1][m]));
|
||||
|
||||
|
||||
accel[0] += partAccel[0];
|
||||
accel[1] += partAccel[1];
|
||||
accel[2] += partAccel[2];
|
||||
}//End of for(uint8_t n=0;n<DEGREE;n++)
|
||||
}//End of uint8_t m=0;m<ORDER;m++
|
||||
}
|
||||
|
||||
void initializeNavOrbit(const double position[3],const double velocity[3], timeval timeUTC){
|
||||
CoordinateTransformations::positionEcfToEci(position,&y0[0],&timeUTC);
|
||||
CoordinateTransformations::velocityEcfToEci(velocity,position,&y0[3],&timeUTC);
|
||||
lastExecutionTime = timeUTC;
|
||||
}
|
||||
|
||||
|
||||
void acsNavOrbit(timeval timeUTC, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1], double outputPos[3],double outputVel[3]){
|
||||
|
||||
//RK4 Integration for this timestamp
|
||||
double deltaT = timevalOperations::toDouble(timeUTC-lastExecutionTime);
|
||||
|
||||
double y0dot[6] = {0,0,0,0,0,0};
|
||||
double yA[6] = {0,0,0,0,0,0};
|
||||
double yAdot[6] = {0,0,0,0,0,0};
|
||||
double yB[6] = {0,0,0,0,0,0};
|
||||
double yBdot[6] = {0,0,0,0,0,0};
|
||||
double yC[6] = {0,0,0,0,0,0};
|
||||
double yCdot[6] = {0,0,0,0,0,0};
|
||||
|
||||
//Step One
|
||||
rungeKuttaStep(y0,y0dot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Two
|
||||
VectorOperations<double>::mulScalar(y0dot,deltaT/2,yA,6);
|
||||
VectorOperations<double>::add(y0,yA,yA,6);
|
||||
rungeKuttaStep(yA,yAdot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Three
|
||||
VectorOperations<double>::mulScalar(yAdot,deltaT/2,yB,6);
|
||||
VectorOperations<double>::add(y0,yB,yB,6);
|
||||
rungeKuttaStep(yB,yBdot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Four
|
||||
VectorOperations<double>::mulScalar(yBdot,deltaT,yC,6);
|
||||
VectorOperations<double>::add(y0,yC,yC,6);
|
||||
rungeKuttaStep(yC,yCdot,lastExecutionTime,S,C);
|
||||
|
||||
//Calc new State
|
||||
VectorOperations<double>::mulScalar(yAdot,2,yAdot,6);
|
||||
VectorOperations<double>::mulScalar(yBdot,2,yBdot,6);
|
||||
VectorOperations<double>::add(y0dot,yAdot,y0dot,6);
|
||||
VectorOperations<double>::add(y0dot,yBdot,y0dot,6);
|
||||
VectorOperations<double>::add(y0dot,yCdot,y0dot,6);
|
||||
VectorOperations<double>::mulScalar(y0dot,1./6.*deltaT,y0dot,6);
|
||||
VectorOperations<double>::add(y0,y0dot,y0,6);
|
||||
|
||||
CoordinateTransformations::positionEciToEcf(&y0[0],outputPos,&timeUTC);
|
||||
CoordinateTransformations::velocityEciToEcf(&y0[3],&y0[0],outputVel,&timeUTC);
|
||||
|
||||
lastExecutionTime = timeUTC;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void rungeKuttaStep(const double* yIn,double* yOut,timeval time, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1]){
|
||||
double rECF[3] = {0,0,0};
|
||||
double rDotECF[3] = {0,0,0};
|
||||
double accelECF[3] = {0,0,0};
|
||||
double accelECI[3] = {0,0,0};
|
||||
|
||||
|
||||
CoordinateTransformations::positionEciToEcf(&yIn[0],rECF,&time);
|
||||
CoordinateTransformations::velocityEciToEcf(&yIn[3],&yIn[0],rDotECF,&time);
|
||||
accelDegOrd(rECF,S,C,accelECF);
|
||||
//This is not correct, as the acceleration would have derived terms but we don't know the velocity and position at that time
|
||||
//Tests showed that a wrong velocity does make the equation worse than neglecting it
|
||||
CoordinateTransformations::positionEcfToEci(accelECF,accelECI,&time);
|
||||
memcpy(&yOut[0],&yIn[3],sizeof(yOut[0])*3);
|
||||
memcpy(&yOut[3],accelECI,sizeof(yOut[0])*3);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_COORDINATES_JGM3MODEL_H_ */
|
||||
#ifndef FRAMEWORK_COORDINATES_JGM3MODEL_H_
|
||||
#define FRAMEWORK_COORDINATES_JGM3MODEL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../coordinates/CoordinateTransformations.h"
|
||||
#include "../globalfunctions/math/VectorOperations.h"
|
||||
#include "../globalfunctions/timevalOperations.h"
|
||||
#include "../globalfunctions/constants.h"
|
||||
#include <memory.h>
|
||||
|
||||
|
||||
template<uint8_t DEGREE,uint8_t ORDER>
|
||||
class Jgm3Model {
|
||||
public:
|
||||
static const uint32_t factorialLookupTable[DEGREE+3]; //This table is used instead of factorial calculation, must be increased if order or degree is higher
|
||||
|
||||
Jgm3Model() {
|
||||
y0[0] = 0;
|
||||
y0[1] = 0;
|
||||
y0[2] = 0;
|
||||
y0[3] = 0;
|
||||
y0[4] = 0;
|
||||
y0[5] = 0;
|
||||
|
||||
lastExecutionTime.tv_sec = 0;
|
||||
lastExecutionTime.tv_usec = 0;
|
||||
}
|
||||
virtual ~Jgm3Model(){};
|
||||
|
||||
//double acsNavOrbit(double posECF[3],double velECF[3],timeval gpsTime);
|
||||
|
||||
double y0[6]; //position and velocity at beginning of RK step in EC
|
||||
timeval lastExecutionTime; //Time of last execution
|
||||
|
||||
|
||||
void accelDegOrd(const double pos[3],const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1],double* accel){
|
||||
//Get radius of this position
|
||||
double r = VectorOperations<double>::norm(pos,3);
|
||||
|
||||
|
||||
|
||||
//Initialize the V and W matrix
|
||||
double V[DEGREE+2][ORDER+2] = {{0}};
|
||||
double W[DEGREE+2][ORDER+2] = {{0}};
|
||||
|
||||
for(uint8_t m=0;m<(ORDER+2);m++){
|
||||
for(uint8_t n=m;n<(DEGREE+2);n++){
|
||||
if((n==0) && (m==0)){
|
||||
//Montenbruck "Satellite Orbits Eq.3.31"
|
||||
V[0][0] = Earth::MEAN_RADIUS / r;
|
||||
W[0][0] = 0;
|
||||
}else{
|
||||
if(n==m){
|
||||
//Montenbruck "Satellite Orbits Eq.3.29"
|
||||
V[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1] - pos[1]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1]);
|
||||
W[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1] + pos[1]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1]);
|
||||
}else{
|
||||
//Montenbruck "Satellite Orbits Eq.3.30"
|
||||
V[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*V[n-1][m];
|
||||
W[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*W[n-1][m];
|
||||
if(n!=(m+1)){
|
||||
V[n][m] = V[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * V[n-2][m]);
|
||||
W[n][m] = W[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * W[n-2][m]);
|
||||
}//End of if(n!=(m+1))
|
||||
}//End of if(n==m){
|
||||
}//End of if(n==0 and m==0)
|
||||
}//End of for(uint8_t n=0;n<(DEGREE+1);n++)
|
||||
}//End of for(uint8_t m=0;m<(ORDER+1);m++)
|
||||
|
||||
|
||||
//overwrite accel if not properly initialized
|
||||
accel[0] = 0;
|
||||
accel[1] = 0;
|
||||
accel[2] = 0;
|
||||
|
||||
for(uint8_t m=0;m<(ORDER+1);m++){
|
||||
for(uint8_t n=m;n<(DEGREE+1);n++){
|
||||
//Use table lookup to get factorial
|
||||
double partAccel[3] = {0};
|
||||
double factor = Earth::STANDARD_GRAVITATIONAL_PARAMETER/pow(Earth::MEAN_RADIUS,2);
|
||||
if(m==0){
|
||||
//Montenbruck "Satellite Orbits Eq.3.33"
|
||||
partAccel[0] = factor * (-C[n][0]*V[n+1][1]);
|
||||
partAccel[1] = factor * (-C[n][0]*W[n+1][1]);
|
||||
}else{
|
||||
double factMN = static_cast<double>(factorialLookupTable[n-m+2]) / static_cast<double>(factorialLookupTable[n-m]);
|
||||
partAccel[0] = factor * 0.5 * ((-C[n][m]*V[n+1][m+1]-S[n][m]*W[n+1][m+1])+factMN*(C[n][m]*V[n+1][m-1]+S[n][m]*W[n+1][m-1]));
|
||||
partAccel[1] = factor * 0.5 * ((-C[n][m]*W[n+1][m+1]+S[n][m]*V[n+1][m+1])+factMN*(-C[n][m]*W[n+1][m-1]+S[n][m]*V[n+1][m-1]));
|
||||
}
|
||||
|
||||
partAccel[2] = factor * ((n-m+1)*(-C[n][m]*V[n+1][m]-S[n][m]*W[n+1][m]));
|
||||
|
||||
|
||||
accel[0] += partAccel[0];
|
||||
accel[1] += partAccel[1];
|
||||
accel[2] += partAccel[2];
|
||||
}//End of for(uint8_t n=0;n<DEGREE;n++)
|
||||
}//End of uint8_t m=0;m<ORDER;m++
|
||||
}
|
||||
|
||||
void initializeNavOrbit(const double position[3],const double velocity[3], timeval timeUTC){
|
||||
CoordinateTransformations::positionEcfToEci(position,&y0[0],&timeUTC);
|
||||
CoordinateTransformations::velocityEcfToEci(velocity,position,&y0[3],&timeUTC);
|
||||
lastExecutionTime = timeUTC;
|
||||
}
|
||||
|
||||
|
||||
void acsNavOrbit(timeval timeUTC, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1], double outputPos[3],double outputVel[3]){
|
||||
|
||||
//RK4 Integration for this timestamp
|
||||
double deltaT = timevalOperations::toDouble(timeUTC-lastExecutionTime);
|
||||
|
||||
double y0dot[6] = {0,0,0,0,0,0};
|
||||
double yA[6] = {0,0,0,0,0,0};
|
||||
double yAdot[6] = {0,0,0,0,0,0};
|
||||
double yB[6] = {0,0,0,0,0,0};
|
||||
double yBdot[6] = {0,0,0,0,0,0};
|
||||
double yC[6] = {0,0,0,0,0,0};
|
||||
double yCdot[6] = {0,0,0,0,0,0};
|
||||
|
||||
//Step One
|
||||
rungeKuttaStep(y0,y0dot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Two
|
||||
VectorOperations<double>::mulScalar(y0dot,deltaT/2,yA,6);
|
||||
VectorOperations<double>::add(y0,yA,yA,6);
|
||||
rungeKuttaStep(yA,yAdot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Three
|
||||
VectorOperations<double>::mulScalar(yAdot,deltaT/2,yB,6);
|
||||
VectorOperations<double>::add(y0,yB,yB,6);
|
||||
rungeKuttaStep(yB,yBdot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Four
|
||||
VectorOperations<double>::mulScalar(yBdot,deltaT,yC,6);
|
||||
VectorOperations<double>::add(y0,yC,yC,6);
|
||||
rungeKuttaStep(yC,yCdot,lastExecutionTime,S,C);
|
||||
|
||||
//Calc new State
|
||||
VectorOperations<double>::mulScalar(yAdot,2,yAdot,6);
|
||||
VectorOperations<double>::mulScalar(yBdot,2,yBdot,6);
|
||||
VectorOperations<double>::add(y0dot,yAdot,y0dot,6);
|
||||
VectorOperations<double>::add(y0dot,yBdot,y0dot,6);
|
||||
VectorOperations<double>::add(y0dot,yCdot,y0dot,6);
|
||||
VectorOperations<double>::mulScalar(y0dot,1./6.*deltaT,y0dot,6);
|
||||
VectorOperations<double>::add(y0,y0dot,y0,6);
|
||||
|
||||
CoordinateTransformations::positionEciToEcf(&y0[0],outputPos,&timeUTC);
|
||||
CoordinateTransformations::velocityEciToEcf(&y0[3],&y0[0],outputVel,&timeUTC);
|
||||
|
||||
lastExecutionTime = timeUTC;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void rungeKuttaStep(const double* yIn,double* yOut,timeval time, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1]){
|
||||
double rECF[3] = {0,0,0};
|
||||
double rDotECF[3] = {0,0,0};
|
||||
double accelECF[3] = {0,0,0};
|
||||
double accelECI[3] = {0,0,0};
|
||||
|
||||
|
||||
CoordinateTransformations::positionEciToEcf(&yIn[0],rECF,&time);
|
||||
CoordinateTransformations::velocityEciToEcf(&yIn[3],&yIn[0],rDotECF,&time);
|
||||
accelDegOrd(rECF,S,C,accelECF);
|
||||
//This is not correct, as the acceleration would have derived terms but we don't know the velocity and position at that time
|
||||
//Tests showed that a wrong velocity does make the equation worse than neglecting it
|
||||
CoordinateTransformations::positionEcfToEci(accelECF,accelECI,&time);
|
||||
memcpy(&yOut[0],&yIn[3],sizeof(yOut[0])*3);
|
||||
memcpy(&yOut[3],accelECI,sizeof(yOut[0])*3);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_COORDINATES_JGM3MODEL_H_ */
|
||||
|
@ -1,228 +1,228 @@
|
||||
#include <framework/coordinates/CoordinateTransformations.h>
|
||||
#include <framework/coordinates/Sgp4Propagator.h>
|
||||
#include <framework/globalfunctions/constants.h>
|
||||
#include <framework/globalfunctions/math/MatrixOperations.h>
|
||||
#include <framework/globalfunctions/math/VectorOperations.h>
|
||||
#include <framework/globalfunctions/timevalOperations.h>
|
||||
#include <cstring>
|
||||
Sgp4Propagator::Sgp4Propagator() :
|
||||
initialized(false), epoch({0, 0}), whichconst(wgs84) {
|
||||
|
||||
}
|
||||
|
||||
Sgp4Propagator::~Sgp4Propagator() {
|
||||
|
||||
}
|
||||
|
||||
void jday(int year, int mon, int day, int hr, int minute, double sec,
|
||||
double& jd) {
|
||||
jd = 367.0 * year - floor((7 * (year + floor((mon + 9) / 12.0))) * 0.25)
|
||||
+ floor(275 * mon / 9.0) + day + 1721013.5
|
||||
+ ((sec / 60.0 + minute) / 60.0 + hr) / 24.0; // ut in days
|
||||
// - 0.5*sgn(100.0*year + mon - 190002.5) + 0.5;
|
||||
}
|
||||
|
||||
void days2mdhms(int year, double days, int& mon, int& day, int& hr, int& minute,
|
||||
double& sec) {
|
||||
int i, inttemp, dayofyr;
|
||||
double temp;
|
||||
int lmonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
dayofyr = (int) floor(days);
|
||||
/* ----------------- find month and day of month ---------------- */
|
||||
if ((year % 4) == 0)
|
||||
lmonth[1] = 29;
|
||||
|
||||
i = 1;
|
||||
inttemp = 0;
|
||||
while ((dayofyr > inttemp + lmonth[i - 1]) && (i < 12)) {
|
||||
inttemp = inttemp + lmonth[i - 1];
|
||||
i++;
|
||||
}
|
||||
mon = i;
|
||||
day = dayofyr - inttemp;
|
||||
|
||||
/* ----------------- find hours minutes and seconds ------------- */
|
||||
temp = (days - dayofyr) * 24.0;
|
||||
hr = (int) floor(temp);
|
||||
temp = (temp - hr) * 60.0;
|
||||
minute = (int) floor(temp);
|
||||
sec = (temp - minute) * 60.0;
|
||||
}
|
||||
|
||||
ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1,
|
||||
const uint8_t* line2) {
|
||||
|
||||
char longstr1[130];
|
||||
char longstr2[130];
|
||||
|
||||
//need some space for decimal points
|
||||
memcpy(longstr1, line1, 69);
|
||||
memcpy(longstr2, line2, 69);
|
||||
|
||||
const double deg2rad = Math::PI / 180.0; // 0.0174532925199433
|
||||
const double xpdotp = 1440.0 / (2.0 * Math::PI); // 229.1831180523293
|
||||
|
||||
double sec, mu, radiusearthkm, tumin, xke, j2, j3, j4, j3oj2;
|
||||
int cardnumb, numb, j;
|
||||
long revnum = 0, elnum = 0;
|
||||
char classification, intldesg[11];
|
||||
int year = 0;
|
||||
int mon, day, hr, minute, nexp, ibexp;
|
||||
|
||||
getgravconst(whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2);
|
||||
|
||||
satrec.error = 0;
|
||||
|
||||
// set the implied decimal points since doing a formated read
|
||||
// fixes for bad input data values (missing, ...)
|
||||
for (j = 10; j <= 15; j++)
|
||||
if (longstr1[j] == ' ')
|
||||
longstr1[j] = '_';
|
||||
|
||||
if (longstr1[44] != ' ')
|
||||
longstr1[43] = longstr1[44];
|
||||
longstr1[44] = '.';
|
||||
if (longstr1[7] == ' ')
|
||||
longstr1[7] = 'U';
|
||||
if (longstr1[9] == ' ')
|
||||
longstr1[9] = '.';
|
||||
for (j = 45; j <= 49; j++)
|
||||
if (longstr1[j] == ' ')
|
||||
longstr1[j] = '0';
|
||||
if (longstr1[51] == ' ')
|
||||
longstr1[51] = '0';
|
||||
if (longstr1[53] != ' ')
|
||||
longstr1[52] = longstr1[53];
|
||||
longstr1[53] = '.';
|
||||
longstr2[25] = '.';
|
||||
for (j = 26; j <= 32; j++)
|
||||
if (longstr2[j] == ' ')
|
||||
longstr2[j] = '0';
|
||||
if (longstr1[62] == ' ')
|
||||
longstr1[62] = '0';
|
||||
if (longstr1[68] == ' ')
|
||||
longstr1[68] = '0';
|
||||
|
||||
sscanf(longstr1,
|
||||
"%2d %5ld %1c %10s %2d %12lf %11lf %7lf %2d %7lf %2d %2d %6ld ",
|
||||
&cardnumb, &satrec.satnum, &classification, intldesg,
|
||||
&satrec.epochyr, &satrec.epochdays, &satrec.ndot, &satrec.nddot,
|
||||
&nexp, &satrec.bstar, &ibexp, &numb, &elnum);
|
||||
|
||||
if (longstr2[52] == ' ') {
|
||||
sscanf(longstr2, "%2d %5ld %9lf %9lf %8lf %9lf %9lf %10lf %6ld \n",
|
||||
&cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
|
||||
&satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum);
|
||||
} else {
|
||||
sscanf(longstr2, "%2d %5ld %9lf %9lf %8lf %9lf %9lf %11lf %6ld \n",
|
||||
&cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
|
||||
&satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum);
|
||||
}
|
||||
|
||||
// ---- find no, ndot, nddot ----
|
||||
satrec.no = satrec.no / xpdotp; //* rad/min
|
||||
satrec.nddot = satrec.nddot * pow(10.0, nexp);
|
||||
satrec.bstar = satrec.bstar * pow(10.0, ibexp);
|
||||
|
||||
// ---- convert to sgp4 units ----
|
||||
satrec.a = pow(satrec.no * tumin, (-2.0 / 3.0));
|
||||
satrec.ndot = satrec.ndot / (xpdotp * 1440.0); //* ? * minperday
|
||||
satrec.nddot = satrec.nddot / (xpdotp * 1440.0 * 1440);
|
||||
|
||||
// ---- find standard orbital elements ----
|
||||
satrec.inclo = satrec.inclo * deg2rad;
|
||||
satrec.nodeo = satrec.nodeo * deg2rad;
|
||||
satrec.argpo = satrec.argpo * deg2rad;
|
||||
satrec.mo = satrec.mo * deg2rad;
|
||||
|
||||
satrec.alta = satrec.a * (1.0 + satrec.ecco) - 1.0;
|
||||
satrec.altp = satrec.a * (1.0 - satrec.ecco) - 1.0;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// find sgp4epoch time of element set
|
||||
// remember that sgp4 uses units of days from 0 jan 1950 (sgp4epoch)
|
||||
// and minutes from the epoch (time)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// ---------------- temp fix for years from 1957-2056 -------------------
|
||||
// --------- correct fix will occur when year is 4-digit in tle ---------
|
||||
if (satrec.epochyr < 57) {
|
||||
year = satrec.epochyr + 2000;
|
||||
} else {
|
||||
year = satrec.epochyr + 1900;
|
||||
}
|
||||
|
||||
days2mdhms(year, satrec.epochdays, mon, day, hr, minute, sec);
|
||||
jday(year, mon, day, hr, minute, sec, satrec.jdsatepoch);
|
||||
|
||||
double unixSeconds = (satrec.jdsatepoch - 2451544.5) * 24 * 3600
|
||||
+ 946684800;
|
||||
|
||||
epoch.tv_sec = unixSeconds;
|
||||
double subseconds = unixSeconds - epoch.tv_sec;
|
||||
epoch.tv_usec = subseconds * 1000000;
|
||||
|
||||
// ---------------- initialize the orbit at sgp4epoch -------------------
|
||||
uint8_t result = sgp4init(whichconst, satrec.satnum,
|
||||
satrec.jdsatepoch - 2433281.5, satrec.bstar, satrec.ecco,
|
||||
satrec.argpo, satrec.inclo, satrec.mo, satrec.no, satrec.nodeo,
|
||||
satrec);
|
||||
|
||||
if (result != 00) {
|
||||
return MAKE_RETURN_CODE(result);
|
||||
} else {
|
||||
initialized = true;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity,
|
||||
timeval time, uint8_t gpsUtcOffset) {
|
||||
|
||||
if (!initialized) {
|
||||
return TLE_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
//Time since epoch in minutes
|
||||
timeval timeSinceEpoch = time - epoch;
|
||||
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60.
|
||||
+ timeSinceEpoch.tv_usec / 60000000.;
|
||||
|
||||
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
|
||||
|
||||
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
|
||||
return TLE_TOO_OLD;
|
||||
}
|
||||
|
||||
double positionTEME[3];
|
||||
double velocityTEME[3];
|
||||
|
||||
uint8_t result = sgp4(whichconst, satrec, minutesSinceEpoch, positionTEME,
|
||||
velocityTEME);
|
||||
|
||||
VectorOperations<double>::mulScalar(positionTEME, 1000, positionTEME, 3);
|
||||
VectorOperations<double>::mulScalar(velocityTEME, 1000, velocityTEME, 3);
|
||||
|
||||
//Transform to ECF
|
||||
double earthRotationMatrix[3][3];
|
||||
CoordinateTransformations::getEarthRotationMatrix(time,
|
||||
earthRotationMatrix);
|
||||
|
||||
MatrixOperations<double>::multiply(earthRotationMatrix[0], positionTEME,
|
||||
position, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(earthRotationMatrix[0], velocityTEME,
|
||||
velocity, 3, 3, 1);
|
||||
|
||||
double omegaEarth[3] = { 0, 0, Earth::OMEGA };
|
||||
double velocityCorrection[3];
|
||||
VectorOperations<double>::cross(omegaEarth, position, velocityCorrection);
|
||||
VectorOperations<double>::subtract(velocity, velocityCorrection, velocity);
|
||||
|
||||
if (result != 0) {
|
||||
return MAKE_RETURN_CODE(result || 0xB0);
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
}
|
||||
#include "../coordinates/CoordinateTransformations.h"
|
||||
#include "../coordinates/Sgp4Propagator.h"
|
||||
#include "../globalfunctions/constants.h"
|
||||
#include "../globalfunctions/math/MatrixOperations.h"
|
||||
#include "../globalfunctions/math/VectorOperations.h"
|
||||
#include "../globalfunctions/timevalOperations.h"
|
||||
#include <cstring>
|
||||
Sgp4Propagator::Sgp4Propagator() :
|
||||
initialized(false), epoch({0, 0}), whichconst(wgs84) {
|
||||
|
||||
}
|
||||
|
||||
Sgp4Propagator::~Sgp4Propagator() {
|
||||
|
||||
}
|
||||
|
||||
void jday(int year, int mon, int day, int hr, int minute, double sec,
|
||||
double& jd) {
|
||||
jd = 367.0 * year - floor((7 * (year + floor((mon + 9) / 12.0))) * 0.25)
|
||||
+ floor(275 * mon / 9.0) + day + 1721013.5
|
||||
+ ((sec / 60.0 + minute) / 60.0 + hr) / 24.0; // ut in days
|
||||
// - 0.5*sgn(100.0*year + mon - 190002.5) + 0.5;
|
||||
}
|
||||
|
||||
void days2mdhms(int year, double days, int& mon, int& day, int& hr, int& minute,
|
||||
double& sec) {
|
||||
int i, inttemp, dayofyr;
|
||||
double temp;
|
||||
int lmonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
dayofyr = (int) floor(days);
|
||||
/* ----------------- find month and day of month ---------------- */
|
||||
if ((year % 4) == 0)
|
||||
lmonth[1] = 29;
|
||||
|
||||
i = 1;
|
||||
inttemp = 0;
|
||||
while ((dayofyr > inttemp + lmonth[i - 1]) && (i < 12)) {
|
||||
inttemp = inttemp + lmonth[i - 1];
|
||||
i++;
|
||||
}
|
||||
mon = i;
|
||||
day = dayofyr - inttemp;
|
||||
|
||||
/* ----------------- find hours minutes and seconds ------------- */
|
||||
temp = (days - dayofyr) * 24.0;
|
||||
hr = (int) floor(temp);
|
||||
temp = (temp - hr) * 60.0;
|
||||
minute = (int) floor(temp);
|
||||
sec = (temp - minute) * 60.0;
|
||||
}
|
||||
|
||||
ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1,
|
||||
const uint8_t* line2) {
|
||||
|
||||
char longstr1[130];
|
||||
char longstr2[130];
|
||||
|
||||
//need some space for decimal points
|
||||
memcpy(longstr1, line1, 69);
|
||||
memcpy(longstr2, line2, 69);
|
||||
|
||||
const double deg2rad = Math::PI / 180.0; // 0.0174532925199433
|
||||
const double xpdotp = 1440.0 / (2.0 * Math::PI); // 229.1831180523293
|
||||
|
||||
double sec, mu, radiusearthkm, tumin, xke, j2, j3, j4, j3oj2;
|
||||
int cardnumb, numb, j;
|
||||
long revnum = 0, elnum = 0;
|
||||
char classification, intldesg[11];
|
||||
int year = 0;
|
||||
int mon, day, hr, minute, nexp, ibexp;
|
||||
|
||||
getgravconst(whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2);
|
||||
|
||||
satrec.error = 0;
|
||||
|
||||
// set the implied decimal points since doing a formated read
|
||||
// fixes for bad input data values (missing, ...)
|
||||
for (j = 10; j <= 15; j++)
|
||||
if (longstr1[j] == ' ')
|
||||
longstr1[j] = '_';
|
||||
|
||||
if (longstr1[44] != ' ')
|
||||
longstr1[43] = longstr1[44];
|
||||
longstr1[44] = '.';
|
||||
if (longstr1[7] == ' ')
|
||||
longstr1[7] = 'U';
|
||||
if (longstr1[9] == ' ')
|
||||
longstr1[9] = '.';
|
||||
for (j = 45; j <= 49; j++)
|
||||
if (longstr1[j] == ' ')
|
||||
longstr1[j] = '0';
|
||||
if (longstr1[51] == ' ')
|
||||
longstr1[51] = '0';
|
||||
if (longstr1[53] != ' ')
|
||||
longstr1[52] = longstr1[53];
|
||||
longstr1[53] = '.';
|
||||
longstr2[25] = '.';
|
||||
for (j = 26; j <= 32; j++)
|
||||
if (longstr2[j] == ' ')
|
||||
longstr2[j] = '0';
|
||||
if (longstr1[62] == ' ')
|
||||
longstr1[62] = '0';
|
||||
if (longstr1[68] == ' ')
|
||||
longstr1[68] = '0';
|
||||
|
||||
sscanf(longstr1,
|
||||
"%2d %5ld %1c %10s %2d %12lf %11lf %7lf %2d %7lf %2d %2d %6ld ",
|
||||
&cardnumb, &satrec.satnum, &classification, intldesg,
|
||||
&satrec.epochyr, &satrec.epochdays, &satrec.ndot, &satrec.nddot,
|
||||
&nexp, &satrec.bstar, &ibexp, &numb, &elnum);
|
||||
|
||||
if (longstr2[52] == ' ') {
|
||||
sscanf(longstr2, "%2d %5ld %9lf %9lf %8lf %9lf %9lf %10lf %6ld \n",
|
||||
&cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
|
||||
&satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum);
|
||||
} else {
|
||||
sscanf(longstr2, "%2d %5ld %9lf %9lf %8lf %9lf %9lf %11lf %6ld \n",
|
||||
&cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
|
||||
&satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum);
|
||||
}
|
||||
|
||||
// ---- find no, ndot, nddot ----
|
||||
satrec.no = satrec.no / xpdotp; //* rad/min
|
||||
satrec.nddot = satrec.nddot * pow(10.0, nexp);
|
||||
satrec.bstar = satrec.bstar * pow(10.0, ibexp);
|
||||
|
||||
// ---- convert to sgp4 units ----
|
||||
satrec.a = pow(satrec.no * tumin, (-2.0 / 3.0));
|
||||
satrec.ndot = satrec.ndot / (xpdotp * 1440.0); //* ? * minperday
|
||||
satrec.nddot = satrec.nddot / (xpdotp * 1440.0 * 1440);
|
||||
|
||||
// ---- find standard orbital elements ----
|
||||
satrec.inclo = satrec.inclo * deg2rad;
|
||||
satrec.nodeo = satrec.nodeo * deg2rad;
|
||||
satrec.argpo = satrec.argpo * deg2rad;
|
||||
satrec.mo = satrec.mo * deg2rad;
|
||||
|
||||
satrec.alta = satrec.a * (1.0 + satrec.ecco) - 1.0;
|
||||
satrec.altp = satrec.a * (1.0 - satrec.ecco) - 1.0;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// find sgp4epoch time of element set
|
||||
// remember that sgp4 uses units of days from 0 jan 1950 (sgp4epoch)
|
||||
// and minutes from the epoch (time)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// ---------------- temp fix for years from 1957-2056 -------------------
|
||||
// --------- correct fix will occur when year is 4-digit in tle ---------
|
||||
if (satrec.epochyr < 57) {
|
||||
year = satrec.epochyr + 2000;
|
||||
} else {
|
||||
year = satrec.epochyr + 1900;
|
||||
}
|
||||
|
||||
days2mdhms(year, satrec.epochdays, mon, day, hr, minute, sec);
|
||||
jday(year, mon, day, hr, minute, sec, satrec.jdsatepoch);
|
||||
|
||||
double unixSeconds = (satrec.jdsatepoch - 2451544.5) * 24 * 3600
|
||||
+ 946684800;
|
||||
|
||||
epoch.tv_sec = unixSeconds;
|
||||
double subseconds = unixSeconds - epoch.tv_sec;
|
||||
epoch.tv_usec = subseconds * 1000000;
|
||||
|
||||
// ---------------- initialize the orbit at sgp4epoch -------------------
|
||||
uint8_t result = sgp4init(whichconst, satrec.satnum,
|
||||
satrec.jdsatepoch - 2433281.5, satrec.bstar, satrec.ecco,
|
||||
satrec.argpo, satrec.inclo, satrec.mo, satrec.no, satrec.nodeo,
|
||||
satrec);
|
||||
|
||||
if (result != 00) {
|
||||
return MAKE_RETURN_CODE(result);
|
||||
} else {
|
||||
initialized = true;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity,
|
||||
timeval time, uint8_t gpsUtcOffset) {
|
||||
|
||||
if (!initialized) {
|
||||
return TLE_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
//Time since epoch in minutes
|
||||
timeval timeSinceEpoch = time - epoch;
|
||||
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60.
|
||||
+ timeSinceEpoch.tv_usec / 60000000.;
|
||||
|
||||
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
|
||||
|
||||
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
|
||||
return TLE_TOO_OLD;
|
||||
}
|
||||
|
||||
double positionTEME[3];
|
||||
double velocityTEME[3];
|
||||
|
||||
uint8_t result = sgp4(whichconst, satrec, minutesSinceEpoch, positionTEME,
|
||||
velocityTEME);
|
||||
|
||||
VectorOperations<double>::mulScalar(positionTEME, 1000, positionTEME, 3);
|
||||
VectorOperations<double>::mulScalar(velocityTEME, 1000, velocityTEME, 3);
|
||||
|
||||
//Transform to ECF
|
||||
double earthRotationMatrix[3][3];
|
||||
CoordinateTransformations::getEarthRotationMatrix(time,
|
||||
earthRotationMatrix);
|
||||
|
||||
MatrixOperations<double>::multiply(earthRotationMatrix[0], positionTEME,
|
||||
position, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(earthRotationMatrix[0], velocityTEME,
|
||||
velocity, 3, 3, 1);
|
||||
|
||||
double omegaEarth[3] = { 0, 0, Earth::OMEGA };
|
||||
double velocityCorrection[3];
|
||||
VectorOperations<double>::cross(omegaEarth, position, velocityCorrection);
|
||||
VectorOperations<double>::subtract(velocity, velocityCorrection, velocity);
|
||||
|
||||
if (result != 0) {
|
||||
return MAKE_RETURN_CODE(result || 0xB0);
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +1,44 @@
|
||||
#ifndef SGP4PROPAGATOR_H_
|
||||
#define SGP4PROPAGATOR_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "../contrib/sgp4/sgp4unit.h"
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
class Sgp4Propagator {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SGP4PROPAGATOR_CLASS;
|
||||
static const ReturnValue_t INVALID_ECCENTRICITY = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t INVALID_MEAN_MOTION = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t INVALID_PERTURBATION_ELEMENTS = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t INVALID_SEMI_LATUS_RECTUM = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t INVALID_EPOCH_ELEMENTS = MAKE_RETURN_CODE(0xA5);
|
||||
static const ReturnValue_t SATELLITE_HAS_DECAYED = MAKE_RETURN_CODE(0xA6);
|
||||
static const ReturnValue_t TLE_TOO_OLD = MAKE_RETURN_CODE(0xB1);
|
||||
static const ReturnValue_t TLE_NOT_INITIALIZED = MAKE_RETURN_CODE(0xB2);
|
||||
|
||||
|
||||
|
||||
Sgp4Propagator();
|
||||
virtual ~Sgp4Propagator();
|
||||
|
||||
ReturnValue_t initialize(const uint8_t *line1, const uint8_t *line2);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param[out] position in ECF
|
||||
* @param[out] velocity in ECF
|
||||
* @param time to which to propagate
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t propagate(double *position, double *velocity, timeval time, uint8_t gpsUtcOffset);
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
timeval epoch;
|
||||
elsetrec satrec;
|
||||
gravconsttype whichconst;
|
||||
|
||||
};
|
||||
|
||||
#endif /* SGP4PROPAGATOR_H_ */
|
||||
#ifndef SGP4PROPAGATOR_H_
|
||||
#define SGP4PROPAGATOR_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "../contrib/sgp4/sgp4unit.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
class Sgp4Propagator {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SGP4PROPAGATOR_CLASS;
|
||||
static const ReturnValue_t INVALID_ECCENTRICITY = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t INVALID_MEAN_MOTION = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t INVALID_PERTURBATION_ELEMENTS = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t INVALID_SEMI_LATUS_RECTUM = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t INVALID_EPOCH_ELEMENTS = MAKE_RETURN_CODE(0xA5);
|
||||
static const ReturnValue_t SATELLITE_HAS_DECAYED = MAKE_RETURN_CODE(0xA6);
|
||||
static const ReturnValue_t TLE_TOO_OLD = MAKE_RETURN_CODE(0xB1);
|
||||
static const ReturnValue_t TLE_NOT_INITIALIZED = MAKE_RETURN_CODE(0xB2);
|
||||
|
||||
|
||||
|
||||
Sgp4Propagator();
|
||||
virtual ~Sgp4Propagator();
|
||||
|
||||
ReturnValue_t initialize(const uint8_t *line1, const uint8_t *line2);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param[out] position in ECF
|
||||
* @param[out] velocity in ECF
|
||||
* @param time to which to propagate
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t propagate(double *position, double *velocity, timeval time, uint8_t gpsUtcOffset);
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
timeval epoch;
|
||||
elsetrec satrec;
|
||||
gravconsttype whichconst;
|
||||
|
||||
};
|
||||
|
||||
#endif /* SGP4PROPAGATOR_H_ */
|
||||
|
@ -1,62 +1,62 @@
|
||||
/**
|
||||
* @file BCFrame.h
|
||||
* @brief This file defines the BCFrame class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef BCFRAME_H_
|
||||
#define BCFRAME_H_
|
||||
|
||||
#include <framework/datalinklayer/CCSDSReturnValuesIF.h>
|
||||
|
||||
/**
|
||||
* Small helper class to identify a BcFrame.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class BcFrame: public CCSDSReturnValuesIF {
|
||||
private:
|
||||
static const uint8_t UNLOCK_COMMAND = 0b00000000;//! Identifier for a certain BC Command.
|
||||
static const uint8_t SET_V_R_1 = 0b10000010;//! Identifier for a certain BC Command.
|
||||
static const uint8_t SET_V_R_2 = 0b00000000;//! Identifier for a certain BC Command.
|
||||
|
||||
public:
|
||||
uint8_t byte1; //!< First content byte
|
||||
uint8_t byte2; //!< Second content byte
|
||||
uint8_t vR; //!< vR byte
|
||||
/**
|
||||
* Simple default constructor.
|
||||
*/
|
||||
BcFrame() :
|
||||
byte1(0), byte2(0), vR(0) {
|
||||
}
|
||||
/**
|
||||
* Main and only useful method of the class.
|
||||
* With the buffer and size information passed, the class passes the content
|
||||
* and checks if it is one of the two valid BC Command Frames.
|
||||
* @param inBuffer Content of the frame to check,
|
||||
* @param inSize Size of the data to check.
|
||||
* @return - #BC_ILLEGAL_COMMAND if it is no command.
|
||||
* - #BC_IS_UNLOCK_COMMAND if it is an unlock command.
|
||||
* - #BC_IS_SET_VR_COMMAND if it is such.
|
||||
*/
|
||||
ReturnValue_t initialize(const uint8_t* inBuffer, uint16_t inSize) {
|
||||
ReturnValue_t returnValue = BC_ILLEGAL_COMMAND;
|
||||
if (inSize == 1) {
|
||||
byte1 = inBuffer[0];
|
||||
if (byte1 == UNLOCK_COMMAND) {
|
||||
returnValue = BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
} else if (inSize == 3) {
|
||||
byte1 = inBuffer[0];
|
||||
byte2 = inBuffer[1];
|
||||
vR = inBuffer[2];
|
||||
if (byte1 == SET_V_R_1 && byte2 == SET_V_R_2) {
|
||||
returnValue = BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BCFRAME_H_ */
|
||||
/**
|
||||
* @file BCFrame.h
|
||||
* @brief This file defines the BCFrame class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef BCFRAME_H_
|
||||
#define BCFRAME_H_
|
||||
|
||||
#include "../datalinklayer/CCSDSReturnValuesIF.h"
|
||||
|
||||
/**
|
||||
* Small helper class to identify a BcFrame.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class BcFrame: public CCSDSReturnValuesIF {
|
||||
private:
|
||||
static const uint8_t UNLOCK_COMMAND = 0b00000000;//! Identifier for a certain BC Command.
|
||||
static const uint8_t SET_V_R_1 = 0b10000010;//! Identifier for a certain BC Command.
|
||||
static const uint8_t SET_V_R_2 = 0b00000000;//! Identifier for a certain BC Command.
|
||||
|
||||
public:
|
||||
uint8_t byte1; //!< First content byte
|
||||
uint8_t byte2; //!< Second content byte
|
||||
uint8_t vR; //!< vR byte
|
||||
/**
|
||||
* Simple default constructor.
|
||||
*/
|
||||
BcFrame() :
|
||||
byte1(0), byte2(0), vR(0) {
|
||||
}
|
||||
/**
|
||||
* Main and only useful method of the class.
|
||||
* With the buffer and size information passed, the class passes the content
|
||||
* and checks if it is one of the two valid BC Command Frames.
|
||||
* @param inBuffer Content of the frame to check,
|
||||
* @param inSize Size of the data to check.
|
||||
* @return - #BC_ILLEGAL_COMMAND if it is no command.
|
||||
* - #BC_IS_UNLOCK_COMMAND if it is an unlock command.
|
||||
* - #BC_IS_SET_VR_COMMAND if it is such.
|
||||
*/
|
||||
ReturnValue_t initialize(const uint8_t* inBuffer, uint16_t inSize) {
|
||||
ReturnValue_t returnValue = BC_ILLEGAL_COMMAND;
|
||||
if (inSize == 1) {
|
||||
byte1 = inBuffer[0];
|
||||
if (byte1 == UNLOCK_COMMAND) {
|
||||
returnValue = BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
} else if (inSize == 3) {
|
||||
byte1 = inBuffer[0];
|
||||
byte2 = inBuffer[1];
|
||||
vR = inBuffer[2];
|
||||
if (byte1 == SET_V_R_1 && byte2 == SET_V_R_2) {
|
||||
returnValue = BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* BCFRAME_H_ */
|
||||
|
@ -1,56 +1,56 @@
|
||||
/**
|
||||
* @file CCSDSReturnValuesIF.h
|
||||
* @brief This file defines the CCSDSReturnValuesIF class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef CCSDSRETURNVALUESIF_H_
|
||||
#define CCSDSRETURNVALUESIF_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
/**
|
||||
* This is a helper class to collect special return values that come up during CCSDS Handling.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class CCSDSReturnValuesIF: public HasReturnvaluesIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_HANDLER_IF; //!< Basic ID of the interface.
|
||||
|
||||
static const ReturnValue_t BC_IS_SET_VR_COMMAND = MAKE_RETURN_CODE( 0x01 ); //!< A value to describe a BC frame.
|
||||
static const ReturnValue_t BC_IS_UNLOCK_COMMAND = MAKE_RETURN_CODE( 0x02 ); //!< A value to describe a BC frame.
|
||||
static const ReturnValue_t BC_ILLEGAL_COMMAND = MAKE_RETURN_CODE( 0xB0 );//!< A value to describe an illegal BC frame.
|
||||
static const ReturnValue_t BOARD_READING_NOT_FINISHED = MAKE_RETURN_CODE( 0xB1 ); //! The CCSDS Board is not yet finished reading, it requires another cycle.
|
||||
|
||||
static const ReturnValue_t NS_POSITIVE_W = MAKE_RETURN_CODE( 0xF0 );//!< NS is in the positive window
|
||||
static const ReturnValue_t NS_NEGATIVE_W = MAKE_RETURN_CODE( 0xF1 );//!< NS is in the negative window
|
||||
static const ReturnValue_t NS_LOCKOUT = MAKE_RETURN_CODE( 0xF2 ); //!< NS is in lockout state
|
||||
static const ReturnValue_t FARM_IN_LOCKOUT = MAKE_RETURN_CODE( 0xF3 );//!< FARM-1 is currently in lockout state
|
||||
static const ReturnValue_t FARM_IN_WAIT = MAKE_RETURN_CODE( 0xF4 ); //!< FARM-1 is currently in wait state
|
||||
|
||||
static const ReturnValue_t WRONG_SYMBOL = MAKE_RETURN_CODE( 0xE0 ); //!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t DOUBLE_START = MAKE_RETURN_CODE( 0xE1 ); //!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t START_SYMBOL_MISSED = MAKE_RETURN_CODE( 0xE2 );//!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t END_WITHOUT_START = MAKE_RETURN_CODE( 0xE3 );//!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t TOO_LARGE = MAKE_RETURN_CODE( 0xE4 );//!< An error code for a frame.
|
||||
static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE( 0xE5 );//!< An error code for a frame.
|
||||
static const ReturnValue_t WRONG_TF_VERSION = MAKE_RETURN_CODE( 0xE6 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t WRONG_SPACECRAFT_ID = MAKE_RETURN_CODE( 0xE7 );//!< An error code for a frame.
|
||||
static const ReturnValue_t NO_VALID_FRAME_TYPE = MAKE_RETURN_CODE( 0xE8 );//!< An error code for a frame.
|
||||
static const ReturnValue_t CRC_FAILED = MAKE_RETURN_CODE( 0xE9 );//!< An error code for a frame.
|
||||
static const ReturnValue_t VC_NOT_FOUND = MAKE_RETURN_CODE( 0xEA ); //!< An error code for a frame.
|
||||
static const ReturnValue_t FORWARDING_FAILED = MAKE_RETURN_CODE( 0xEB );//!< An error code for a frame.
|
||||
static const ReturnValue_t CONTENT_TOO_LARGE = MAKE_RETURN_CODE( 0xEC );//!< An error code for a frame.
|
||||
static const ReturnValue_t RESIDUAL_DATA = MAKE_RETURN_CODE( 0xED );//!< An error code for a frame.
|
||||
static const ReturnValue_t DATA_CORRUPTED = MAKE_RETURN_CODE( 0xEE );//!< An error code for a frame.
|
||||
static const ReturnValue_t ILLEGAL_SEGMENTATION_FLAG = MAKE_RETURN_CODE( 0xEF );//!< An error code for a frame.
|
||||
static const ReturnValue_t ILLEGAL_FLAG_COMBINATION = MAKE_RETURN_CODE( 0xD0 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t SHORTER_THAN_HEADER = MAKE_RETURN_CODE( 0xD1 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t TOO_SHORT_BLOCKED_PACKET = MAKE_RETURN_CODE( 0xD2 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t TOO_SHORT_MAP_EXTRACTION = MAKE_RETURN_CODE( 0xD3 ); //!< An error code for a frame.
|
||||
|
||||
virtual ~CCSDSReturnValuesIF() {
|
||||
} //!< Empty virtual destructor
|
||||
};
|
||||
|
||||
#endif /* CCSDSRETURNVALUESIF_H_ */
|
||||
/**
|
||||
* @file CCSDSReturnValuesIF.h
|
||||
* @brief This file defines the CCSDSReturnValuesIF class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef CCSDSRETURNVALUESIF_H_
|
||||
#define CCSDSRETURNVALUESIF_H_
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
/**
|
||||
* This is a helper class to collect special return values that come up during CCSDS Handling.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class CCSDSReturnValuesIF: public HasReturnvaluesIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_HANDLER_IF; //!< Basic ID of the interface.
|
||||
|
||||
static const ReturnValue_t BC_IS_SET_VR_COMMAND = MAKE_RETURN_CODE( 0x01 ); //!< A value to describe a BC frame.
|
||||
static const ReturnValue_t BC_IS_UNLOCK_COMMAND = MAKE_RETURN_CODE( 0x02 ); //!< A value to describe a BC frame.
|
||||
static const ReturnValue_t BC_ILLEGAL_COMMAND = MAKE_RETURN_CODE( 0xB0 );//!< A value to describe an illegal BC frame.
|
||||
static const ReturnValue_t BOARD_READING_NOT_FINISHED = MAKE_RETURN_CODE( 0xB1 ); //! The CCSDS Board is not yet finished reading, it requires another cycle.
|
||||
|
||||
static const ReturnValue_t NS_POSITIVE_W = MAKE_RETURN_CODE( 0xF0 );//!< NS is in the positive window
|
||||
static const ReturnValue_t NS_NEGATIVE_W = MAKE_RETURN_CODE( 0xF1 );//!< NS is in the negative window
|
||||
static const ReturnValue_t NS_LOCKOUT = MAKE_RETURN_CODE( 0xF2 ); //!< NS is in lockout state
|
||||
static const ReturnValue_t FARM_IN_LOCKOUT = MAKE_RETURN_CODE( 0xF3 );//!< FARM-1 is currently in lockout state
|
||||
static const ReturnValue_t FARM_IN_WAIT = MAKE_RETURN_CODE( 0xF4 ); //!< FARM-1 is currently in wait state
|
||||
|
||||
static const ReturnValue_t WRONG_SYMBOL = MAKE_RETURN_CODE( 0xE0 ); //!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t DOUBLE_START = MAKE_RETURN_CODE( 0xE1 ); //!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t START_SYMBOL_MISSED = MAKE_RETURN_CODE( 0xE2 );//!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t END_WITHOUT_START = MAKE_RETURN_CODE( 0xE3 );//!< An error code in the FrameFinder.
|
||||
static const ReturnValue_t TOO_LARGE = MAKE_RETURN_CODE( 0xE4 );//!< An error code for a frame.
|
||||
static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE( 0xE5 );//!< An error code for a frame.
|
||||
static const ReturnValue_t WRONG_TF_VERSION = MAKE_RETURN_CODE( 0xE6 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t WRONG_SPACECRAFT_ID = MAKE_RETURN_CODE( 0xE7 );//!< An error code for a frame.
|
||||
static const ReturnValue_t NO_VALID_FRAME_TYPE = MAKE_RETURN_CODE( 0xE8 );//!< An error code for a frame.
|
||||
static const ReturnValue_t CRC_FAILED = MAKE_RETURN_CODE( 0xE9 );//!< An error code for a frame.
|
||||
static const ReturnValue_t VC_NOT_FOUND = MAKE_RETURN_CODE( 0xEA ); //!< An error code for a frame.
|
||||
static const ReturnValue_t FORWARDING_FAILED = MAKE_RETURN_CODE( 0xEB );//!< An error code for a frame.
|
||||
static const ReturnValue_t CONTENT_TOO_LARGE = MAKE_RETURN_CODE( 0xEC );//!< An error code for a frame.
|
||||
static const ReturnValue_t RESIDUAL_DATA = MAKE_RETURN_CODE( 0xED );//!< An error code for a frame.
|
||||
static const ReturnValue_t DATA_CORRUPTED = MAKE_RETURN_CODE( 0xEE );//!< An error code for a frame.
|
||||
static const ReturnValue_t ILLEGAL_SEGMENTATION_FLAG = MAKE_RETURN_CODE( 0xEF );//!< An error code for a frame.
|
||||
static const ReturnValue_t ILLEGAL_FLAG_COMBINATION = MAKE_RETURN_CODE( 0xD0 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t SHORTER_THAN_HEADER = MAKE_RETURN_CODE( 0xD1 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t TOO_SHORT_BLOCKED_PACKET = MAKE_RETURN_CODE( 0xD2 ); //!< An error code for a frame.
|
||||
static const ReturnValue_t TOO_SHORT_MAP_EXTRACTION = MAKE_RETURN_CODE( 0xD3 ); //!< An error code for a frame.
|
||||
|
||||
virtual ~CCSDSReturnValuesIF() {
|
||||
} //!< Empty virtual destructor
|
||||
};
|
||||
|
||||
#endif /* CCSDSRETURNVALUESIF_H_ */
|
||||
|
@ -1,63 +1,63 @@
|
||||
/**
|
||||
* @file Clcw.cpp
|
||||
* @brief This file defines the Clcw class.
|
||||
* @date 17.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <framework/datalinklayer/Clcw.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
Clcw::Clcw() {
|
||||
content.raw = 0;
|
||||
content.status = STATUS_FIELD_DEFAULT;
|
||||
}
|
||||
|
||||
Clcw::~Clcw() {
|
||||
}
|
||||
|
||||
void Clcw::setVirtualChannel(uint8_t setChannel) {
|
||||
content.virtualChannelIdSpare = ((setChannel & 0x3F) << 2);
|
||||
}
|
||||
|
||||
void Clcw::setLockoutFlag(bool lockout) {
|
||||
content.flags = (content.flags & LOCKOUT_FLAG_MASK) | (lockout << LOCKOUT_FLAG_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setWaitFlag(bool waitFlag) {
|
||||
content.flags = (content.flags & WAIT_FLAG_MASK) | (waitFlag << WAIT_FLAG_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setRetransmitFlag(bool retransmitFlag) {
|
||||
content.flags = (content.flags & RETRANSMIT_FLAG_MASK) | (retransmitFlag << RETRANSMIT_FLAG_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setFarmBCount(uint8_t count) {
|
||||
content.flags = (content.flags & FARM_B_COUNT_MASK) | ((count & 0x03) << 1);
|
||||
}
|
||||
|
||||
void Clcw::setReceiverFrameSequenceNumber(uint8_t vR) {
|
||||
content.vRValue = vR;
|
||||
}
|
||||
|
||||
uint32_t Clcw::getAsWhole() {
|
||||
return content.raw;
|
||||
}
|
||||
|
||||
void Clcw::setRFAvailable(bool rfAvailable) {
|
||||
content.flags = (content.flags & NO_RF_AVIALABLE_MASK) | (!rfAvailable << NO_RF_AVIALABLE_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setBitLock(bool bitLock) {
|
||||
content.flags = (content.flags & NO_BIT_LOCK_MASK) | (!bitLock << NO_BIT_LOCK_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::print() {
|
||||
sif::debug << "Clcw::print: Clcw is: " << std::hex << getAsWhole() << std::dec << std::endl;
|
||||
}
|
||||
|
||||
void Clcw::setWhole(uint32_t rawClcw) {
|
||||
content.raw = rawClcw;
|
||||
}
|
||||
/**
|
||||
* @file Clcw.cpp
|
||||
* @brief This file defines the Clcw class.
|
||||
* @date 17.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../datalinklayer/Clcw.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
Clcw::Clcw() {
|
||||
content.raw = 0;
|
||||
content.status = STATUS_FIELD_DEFAULT;
|
||||
}
|
||||
|
||||
Clcw::~Clcw() {
|
||||
}
|
||||
|
||||
void Clcw::setVirtualChannel(uint8_t setChannel) {
|
||||
content.virtualChannelIdSpare = ((setChannel & 0x3F) << 2);
|
||||
}
|
||||
|
||||
void Clcw::setLockoutFlag(bool lockout) {
|
||||
content.flags = (content.flags & LOCKOUT_FLAG_MASK) | (lockout << LOCKOUT_FLAG_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setWaitFlag(bool waitFlag) {
|
||||
content.flags = (content.flags & WAIT_FLAG_MASK) | (waitFlag << WAIT_FLAG_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setRetransmitFlag(bool retransmitFlag) {
|
||||
content.flags = (content.flags & RETRANSMIT_FLAG_MASK) | (retransmitFlag << RETRANSMIT_FLAG_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setFarmBCount(uint8_t count) {
|
||||
content.flags = (content.flags & FARM_B_COUNT_MASK) | ((count & 0x03) << 1);
|
||||
}
|
||||
|
||||
void Clcw::setReceiverFrameSequenceNumber(uint8_t vR) {
|
||||
content.vRValue = vR;
|
||||
}
|
||||
|
||||
uint32_t Clcw::getAsWhole() {
|
||||
return content.raw;
|
||||
}
|
||||
|
||||
void Clcw::setRFAvailable(bool rfAvailable) {
|
||||
content.flags = (content.flags & NO_RF_AVIALABLE_MASK) | (!rfAvailable << NO_RF_AVIALABLE_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::setBitLock(bool bitLock) {
|
||||
content.flags = (content.flags & NO_BIT_LOCK_MASK) | (!bitLock << NO_BIT_LOCK_POSITION);
|
||||
}
|
||||
|
||||
void Clcw::print() {
|
||||
sif::debug << "Clcw::print: Clcw is: " << std::hex << getAsWhole() << std::dec << std::endl;
|
||||
}
|
||||
|
||||
void Clcw::setWhole(uint32_t rawClcw) {
|
||||
content.raw = rawClcw;
|
||||
}
|
||||
|
@ -1,66 +1,66 @@
|
||||
/**
|
||||
* @file Clcw.h
|
||||
* @brief This file defines the Clcw class.
|
||||
* @date 17.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef CLCW_H_
|
||||
#define CLCW_H_
|
||||
|
||||
#include <framework/datalinklayer/ClcwIF.h>
|
||||
/**
|
||||
* Small helper method to handle the Clcw values.
|
||||
* It has a content struct that manages the register and can be set externally.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class Clcw : public ClcwIF {
|
||||
private:
|
||||
static const uint8_t STATUS_FIELD_DEFAULT = 0b00000001; //!< Default for the status field.
|
||||
static const uint8_t NO_RF_AVIALABLE_POSITION = 7; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t NO_BIT_LOCK_POSITION = 6; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t LOCKOUT_FLAG_POSITION = 5; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t WAIT_FLAG_POSITION = 4; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t RETRANSMIT_FLAG_POSITION = 3; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t NO_RF_AVIALABLE_MASK = 0xFF xor (1 << NO_RF_AVIALABLE_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t NO_BIT_LOCK_MASK = 0xFF xor (1 << NO_BIT_LOCK_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t LOCKOUT_FLAG_MASK = 0xFF xor (1 << LOCKOUT_FLAG_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t WAIT_FLAG_MASK = 0xFF xor (1 << WAIT_FLAG_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t RETRANSMIT_FLAG_MASK = 0xFF xor (1 << RETRANSMIT_FLAG_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t FARM_B_COUNT_MASK = 0b11111001; //!< Mask for a counter in the register.
|
||||
/**
|
||||
* This is the data structure of the CLCW register.
|
||||
*/
|
||||
union clcwContent {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t status;
|
||||
uint8_t virtualChannelIdSpare;
|
||||
uint8_t flags;
|
||||
uint8_t vRValue;
|
||||
};
|
||||
};
|
||||
clcwContent content; //!< Represents the content of the register.
|
||||
public:
|
||||
/**
|
||||
* The constructor sets everything to default values.
|
||||
*/
|
||||
Clcw();
|
||||
/**
|
||||
* Nothing happens in the destructor.
|
||||
*/
|
||||
~Clcw();
|
||||
void setVirtualChannel( uint8_t setChannel );
|
||||
void setLockoutFlag( bool lockout );
|
||||
void setWaitFlag( bool waitFlag );
|
||||
void setRetransmitFlag( bool retransmitFlag );
|
||||
void setFarmBCount( uint8_t count );
|
||||
void setReceiverFrameSequenceNumber( uint8_t vR );
|
||||
void setRFAvailable( bool rfAvailable );
|
||||
void setBitLock( bool bitLock );
|
||||
uint32_t getAsWhole();
|
||||
void setWhole( uint32_t rawClcw );
|
||||
void print();
|
||||
};
|
||||
|
||||
#endif /* CLCW_H_ */
|
||||
/**
|
||||
* @file Clcw.h
|
||||
* @brief This file defines the Clcw class.
|
||||
* @date 17.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef CLCW_H_
|
||||
#define CLCW_H_
|
||||
|
||||
#include "../datalinklayer/ClcwIF.h"
|
||||
/**
|
||||
* Small helper method to handle the Clcw values.
|
||||
* It has a content struct that manages the register and can be set externally.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class Clcw : public ClcwIF {
|
||||
private:
|
||||
static const uint8_t STATUS_FIELD_DEFAULT = 0b00000001; //!< Default for the status field.
|
||||
static const uint8_t NO_RF_AVIALABLE_POSITION = 7; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t NO_BIT_LOCK_POSITION = 6; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t LOCKOUT_FLAG_POSITION = 5; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t WAIT_FLAG_POSITION = 4; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t RETRANSMIT_FLAG_POSITION = 3; //!< Position of a flag in the register (starting with 0).
|
||||
static const uint8_t NO_RF_AVIALABLE_MASK = 0xFF xor (1 << NO_RF_AVIALABLE_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t NO_BIT_LOCK_MASK = 0xFF xor (1 << NO_BIT_LOCK_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t LOCKOUT_FLAG_MASK = 0xFF xor (1 << LOCKOUT_FLAG_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t WAIT_FLAG_MASK = 0xFF xor (1 << WAIT_FLAG_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t RETRANSMIT_FLAG_MASK = 0xFF xor (1 << RETRANSMIT_FLAG_POSITION); //!< Mask for a flag in the register.
|
||||
static const uint8_t FARM_B_COUNT_MASK = 0b11111001; //!< Mask for a counter in the register.
|
||||
/**
|
||||
* This is the data structure of the CLCW register.
|
||||
*/
|
||||
union clcwContent {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t status;
|
||||
uint8_t virtualChannelIdSpare;
|
||||
uint8_t flags;
|
||||
uint8_t vRValue;
|
||||
};
|
||||
};
|
||||
clcwContent content; //!< Represents the content of the register.
|
||||
public:
|
||||
/**
|
||||
* The constructor sets everything to default values.
|
||||
*/
|
||||
Clcw();
|
||||
/**
|
||||
* Nothing happens in the destructor.
|
||||
*/
|
||||
~Clcw();
|
||||
void setVirtualChannel( uint8_t setChannel );
|
||||
void setLockoutFlag( bool lockout );
|
||||
void setWaitFlag( bool waitFlag );
|
||||
void setRetransmitFlag( bool retransmitFlag );
|
||||
void setFarmBCount( uint8_t count );
|
||||
void setReceiverFrameSequenceNumber( uint8_t vR );
|
||||
void setRFAvailable( bool rfAvailable );
|
||||
void setBitLock( bool bitLock );
|
||||
uint32_t getAsWhole();
|
||||
void setWhole( uint32_t rawClcw );
|
||||
void print();
|
||||
};
|
||||
|
||||
#endif /* CLCW_H_ */
|
||||
|
@ -1,139 +1,139 @@
|
||||
#include <framework/datalinklayer/DataLinkLayer.h>
|
||||
#include <framework/globalfunctions/CRC.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
DataLinkLayer::DataLinkLayer(uint8_t* set_frame_buffer, ClcwIF* setClcw,
|
||||
uint8_t set_start_sequence_length, uint16_t set_scid) :
|
||||
spacecraftId(set_scid), frameBuffer(set_frame_buffer), clcw(setClcw), receivedDataLength(0), currentFrame(
|
||||
NULL), startSequenceLength(set_start_sequence_length) {
|
||||
//Nothing to do except from setting the values above.
|
||||
}
|
||||
|
||||
DataLinkLayer::~DataLinkLayer() {
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameDelimitingAndFillRemoval() {
|
||||
if ((receivedDataLength - startSequenceLength) < FRAME_PRIMARY_HEADER_LENGTH) {
|
||||
return SHORTER_THAN_HEADER;
|
||||
}
|
||||
//Removing start sequence.
|
||||
//SHOULDDO: Not implemented here.
|
||||
while ( *frameBuffer == START_SEQUENCE_PATTERN ) {
|
||||
frameBuffer++;
|
||||
}
|
||||
TcTransferFrame frame_candidate(frameBuffer);
|
||||
this->currentFrame = frame_candidate; //should work with shallow copy.
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameValidationCheck() {
|
||||
//Check TF_version number
|
||||
if (this->currentFrame.getVersionNumber() != FRAME_VERSION_NUMBER_DEFAULT) {
|
||||
return WRONG_TF_VERSION;
|
||||
}
|
||||
//Check SpaceCraft ID
|
||||
if (this->currentFrame.getSpacecraftId() != this->spacecraftId) {
|
||||
return WRONG_SPACECRAFT_ID;
|
||||
}
|
||||
//Check other header limitations:
|
||||
if (!this->currentFrame.bypassFlagSet() && this->currentFrame.controlCommandFlagSet()) {
|
||||
return NO_VALID_FRAME_TYPE;
|
||||
}
|
||||
//- Spares are zero
|
||||
if (!this->currentFrame.spareIsZero()) {
|
||||
return NO_VALID_FRAME_TYPE;
|
||||
}
|
||||
//Compare detected frame length with the one in the header
|
||||
uint16_t length = currentFrame.getFullSize();
|
||||
if (length > receivedDataLength) {
|
||||
//Frame is too long or just right
|
||||
// error << "frameValidationCheck: Too short.";
|
||||
// currentFrame.print();
|
||||
return TOO_SHORT;
|
||||
}
|
||||
if (USE_CRC) {
|
||||
return this->frameCheckCRC();
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameCheckCRC() {
|
||||
uint16_t checkValue = CRC::crc16ccitt(this->currentFrame.getFullFrame(),
|
||||
this->currentFrame.getFullSize());
|
||||
if (checkValue == 0) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return CRC_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::allFramesReception() {
|
||||
ReturnValue_t status = this->frameDelimitingAndFillRemoval();
|
||||
if (status != RETURN_OK) {
|
||||
return status;
|
||||
}
|
||||
return this->frameValidationCheck();
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::masterChannelDemultiplexing() {
|
||||
//Nothing to do at present. Ideally, there would be a map of MCID's identifying which MC to use.
|
||||
return virtualChannelDemultiplexing();
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() {
|
||||
uint8_t vcId = currentFrame.getVirtualChannelId();
|
||||
virtualChannelIterator iter = virtualChannels.find(vcId);
|
||||
if (iter == virtualChannels.end()) {
|
||||
//Do not report because passive board will get this error all the time.
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return (iter->second)->frameAcceptanceAndReportingMechanism(¤tFrame, clcw);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::processFrame(uint16_t length) {
|
||||
receivedDataLength = length;
|
||||
ReturnValue_t status = allFramesReception();
|
||||
if (status != RETURN_OK) {
|
||||
sif::error << "DataLinkLayer::processFrame: frame reception failed. "
|
||||
"Error code: " << std::hex << status << std::dec << std::endl;
|
||||
// currentFrame.print();
|
||||
return status;
|
||||
} else {
|
||||
return masterChannelDemultiplexing();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::addVirtualChannel(uint8_t virtualChannelId,
|
||||
VirtualChannelReceptionIF* object) {
|
||||
std::pair<virtualChannelIterator, bool> returnValue = virtualChannels.insert(
|
||||
std::pair<uint8_t, VirtualChannelReceptionIF*>(virtualChannelId, object));
|
||||
if (returnValue.second == true) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::initialize() {
|
||||
ReturnValue_t returnValue = RETURN_FAILED;
|
||||
//Set Virtual Channel ID to first virtual channel instance in this DataLinkLayer instance to avoid faulty information (e.g. 0) in the VCID.
|
||||
if ( virtualChannels.begin() != virtualChannels.end() ) {
|
||||
clcw->setVirtualChannel( virtualChannels.begin()->second->getChannelId() );
|
||||
} else {
|
||||
sif::error << "DataLinkLayer::initialize: No VC assigned to this DLL instance! " << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
for (virtualChannelIterator iterator = virtualChannels.begin();
|
||||
iterator != virtualChannels.end(); iterator++) {
|
||||
returnValue = iterator->second->initialize();
|
||||
if (returnValue != RETURN_OK)
|
||||
break;
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
#include "../datalinklayer/DataLinkLayer.h"
|
||||
#include "../globalfunctions/CRC.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
DataLinkLayer::DataLinkLayer(uint8_t* set_frame_buffer, ClcwIF* setClcw,
|
||||
uint8_t set_start_sequence_length, uint16_t set_scid) :
|
||||
spacecraftId(set_scid), frameBuffer(set_frame_buffer), clcw(setClcw), receivedDataLength(0), currentFrame(
|
||||
NULL), startSequenceLength(set_start_sequence_length) {
|
||||
//Nothing to do except from setting the values above.
|
||||
}
|
||||
|
||||
DataLinkLayer::~DataLinkLayer() {
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameDelimitingAndFillRemoval() {
|
||||
if ((receivedDataLength - startSequenceLength) < FRAME_PRIMARY_HEADER_LENGTH) {
|
||||
return SHORTER_THAN_HEADER;
|
||||
}
|
||||
//Removing start sequence.
|
||||
//SHOULDDO: Not implemented here.
|
||||
while ( *frameBuffer == START_SEQUENCE_PATTERN ) {
|
||||
frameBuffer++;
|
||||
}
|
||||
TcTransferFrame frame_candidate(frameBuffer);
|
||||
this->currentFrame = frame_candidate; //should work with shallow copy.
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameValidationCheck() {
|
||||
//Check TF_version number
|
||||
if (this->currentFrame.getVersionNumber() != FRAME_VERSION_NUMBER_DEFAULT) {
|
||||
return WRONG_TF_VERSION;
|
||||
}
|
||||
//Check SpaceCraft ID
|
||||
if (this->currentFrame.getSpacecraftId() != this->spacecraftId) {
|
||||
return WRONG_SPACECRAFT_ID;
|
||||
}
|
||||
//Check other header limitations:
|
||||
if (!this->currentFrame.bypassFlagSet() && this->currentFrame.controlCommandFlagSet()) {
|
||||
return NO_VALID_FRAME_TYPE;
|
||||
}
|
||||
//- Spares are zero
|
||||
if (!this->currentFrame.spareIsZero()) {
|
||||
return NO_VALID_FRAME_TYPE;
|
||||
}
|
||||
//Compare detected frame length with the one in the header
|
||||
uint16_t length = currentFrame.getFullSize();
|
||||
if (length > receivedDataLength) {
|
||||
//Frame is too long or just right
|
||||
// error << "frameValidationCheck: Too short.";
|
||||
// currentFrame.print();
|
||||
return TOO_SHORT;
|
||||
}
|
||||
if (USE_CRC) {
|
||||
return this->frameCheckCRC();
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameCheckCRC() {
|
||||
uint16_t checkValue = CRC::crc16ccitt(this->currentFrame.getFullFrame(),
|
||||
this->currentFrame.getFullSize());
|
||||
if (checkValue == 0) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return CRC_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::allFramesReception() {
|
||||
ReturnValue_t status = this->frameDelimitingAndFillRemoval();
|
||||
if (status != RETURN_OK) {
|
||||
return status;
|
||||
}
|
||||
return this->frameValidationCheck();
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::masterChannelDemultiplexing() {
|
||||
//Nothing to do at present. Ideally, there would be a map of MCID's identifying which MC to use.
|
||||
return virtualChannelDemultiplexing();
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() {
|
||||
uint8_t vcId = currentFrame.getVirtualChannelId();
|
||||
virtualChannelIterator iter = virtualChannels.find(vcId);
|
||||
if (iter == virtualChannels.end()) {
|
||||
//Do not report because passive board will get this error all the time.
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return (iter->second)->frameAcceptanceAndReportingMechanism(¤tFrame, clcw);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::processFrame(uint16_t length) {
|
||||
receivedDataLength = length;
|
||||
ReturnValue_t status = allFramesReception();
|
||||
if (status != RETURN_OK) {
|
||||
sif::error << "DataLinkLayer::processFrame: frame reception failed. "
|
||||
"Error code: " << std::hex << status << std::dec << std::endl;
|
||||
// currentFrame.print();
|
||||
return status;
|
||||
} else {
|
||||
return masterChannelDemultiplexing();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::addVirtualChannel(uint8_t virtualChannelId,
|
||||
VirtualChannelReceptionIF* object) {
|
||||
std::pair<virtualChannelIterator, bool> returnValue = virtualChannels.insert(
|
||||
std::pair<uint8_t, VirtualChannelReceptionIF*>(virtualChannelId, object));
|
||||
if (returnValue.second == true) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::initialize() {
|
||||
ReturnValue_t returnValue = RETURN_FAILED;
|
||||
//Set Virtual Channel ID to first virtual channel instance in this DataLinkLayer instance to avoid faulty information (e.g. 0) in the VCID.
|
||||
if ( virtualChannels.begin() != virtualChannels.end() ) {
|
||||
clcw->setVirtualChannel( virtualChannels.begin()->second->getChannelId() );
|
||||
} else {
|
||||
sif::error << "DataLinkLayer::initialize: No VC assigned to this DLL instance! " << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
for (virtualChannelIterator iterator = virtualChannels.begin();
|
||||
iterator != virtualChannels.end(); iterator++) {
|
||||
returnValue = iterator->second->initialize();
|
||||
if (returnValue != RETURN_OK)
|
||||
break;
|
||||
}
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
|
@ -1,112 +1,112 @@
|
||||
#ifndef DATALINKLAYER_H_
|
||||
#define DATALINKLAYER_H_
|
||||
|
||||
#include <framework/datalinklayer/CCSDSReturnValuesIF.h>
|
||||
#include <framework/datalinklayer/ClcwIF.h>
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
#include <framework/datalinklayer/VirtualChannelReceptionIF.h>
|
||||
#include <framework/events/Event.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
class VirtualChannelReception;
|
||||
/**
|
||||
* A complete representation of the CCSDS Data Link Layer.
|
||||
* The operations of this layer are defined in the CCSDS TC Space Data Link Protocol
|
||||
* document. It is configured to handle a VC Demultiplexing function. All reception
|
||||
* steps are performed.
|
||||
*/
|
||||
class DataLinkLayer : public CCSDSReturnValuesIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1;
|
||||
static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0
|
||||
static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
|
||||
static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
|
||||
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
|
||||
// static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. No parameters.
|
||||
static const Event FRAME_PROCESSING_FAILED = MAKE_EVENT(5, SEVERITY::LOW); //!< The CCSDS Board could not interpret a TC
|
||||
/**
|
||||
* The Constructor sets the passed parameters and nothing else.
|
||||
* @param set_frame_buffer The buffer in which incoming frame candidates are stored.
|
||||
* @param setClcw The CLCW class to work on when returning CLCW information.
|
||||
* @param set_start_sequence_length Length of the Start sequence in front of every TC Transfer Frame.
|
||||
* @param set_scid The SCID to operate on.
|
||||
*/
|
||||
DataLinkLayer( uint8_t* set_frame_buffer, ClcwIF* setClcw, uint8_t set_start_sequence_length, uint16_t set_scid );
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
~DataLinkLayer();
|
||||
/**
|
||||
* This method tries to process a frame that is placed in #frameBuffer.
|
||||
* The procedures described in the Standard are performed.
|
||||
* @param length Length of the incoming frame candidate.
|
||||
* @return @c RETURN_OK on successful handling, otherwise the return codes of the higher methods.
|
||||
*/
|
||||
ReturnValue_t processFrame( uint16_t length );
|
||||
/**
|
||||
* Configuration method to add a new TC Virtual Channel.
|
||||
* Shall only be called during initialization. As soon as the method was called, the layer can
|
||||
* handle Frames directed to this VC.
|
||||
* @param virtualChannelId Id of the VC. Shall be smaller than 64.
|
||||
* @param object Reference to the object that handles the Frame.
|
||||
* @return @c RETURN_OK on success, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t addVirtualChannel( uint8_t virtualChannelId, VirtualChannelReceptionIF* object );
|
||||
/**
|
||||
* The initialization method calls the @c initialize routine of all virtual channels.
|
||||
* @return The return code of the first failed VC initialization or @c RETURN_OK.
|
||||
*/
|
||||
ReturnValue_t initialize();
|
||||
private:
|
||||
typedef std::map<uint8_t, VirtualChannelReceptionIF*>::iterator virtualChannelIterator; //!< Typedef to simplify handling the #virtualChannels map.
|
||||
static const uint8_t FRAME_VERSION_NUMBER_DEFAULT = 0x00; //!< Constant for the default value of Frame Version Numbers.
|
||||
static const uint8_t FRAME_PRIMARY_HEADER_LENGTH = 5; //!< Length of the frame's primary header.
|
||||
static const uint8_t START_SEQUENCE_PATTERN = 0x00; //!< The start sequence pattern which might be with the frame.
|
||||
static const bool USE_CRC = true; //!< A global, so called "Managed Parameter" that identifies if incoming frames have CRC's or not.
|
||||
uint16_t spacecraftId; //!< The Space Craft Identifier (SCID) configured.
|
||||
uint8_t* frameBuffer; //!< A pointer to point to the current incoming frame.
|
||||
ClcwIF* clcw; //!< Pointer to store the CLCW to work on.
|
||||
uint16_t receivedDataLength; //!< Stores the length of the currently processed frame.
|
||||
TcTransferFrame currentFrame; //!< Stores a more convenient access to the current frame.
|
||||
uint8_t startSequenceLength; //!< Configured length of the start sequence. Maybe this must be done more variable.
|
||||
std::map<uint8_t, VirtualChannelReceptionIF*> virtualChannels; //!< Map of all virtual channels assigned.
|
||||
/**
|
||||
* Method that performs all possible frame validity checks (as specified).
|
||||
* @return Various error codes or @c RETURN_OK on success.
|
||||
*/
|
||||
ReturnValue_t frameValidationCheck();
|
||||
/**
|
||||
* First method to call.
|
||||
* Removes start sequence bytes and checks if the complete frame was received.
|
||||
* SHOULDDO: Maybe handling the start sequence must be done more variable.
|
||||
* @return @c RETURN_OK or @c TOO_SHORT.
|
||||
*/
|
||||
ReturnValue_t frameDelimitingAndFillRemoval();
|
||||
/**
|
||||
* Small helper method to check the CRC of the Frame.
|
||||
* @return @c RETURN_OK or @c CRC_FAILED.
|
||||
*/
|
||||
ReturnValue_t frameCheckCRC();
|
||||
/**
|
||||
* Method that groups the reception process of all Frames.
|
||||
* Calls #frameDelimitingAndFillRemoval and #frameValidationCheck.
|
||||
* @return The return codes of the sub calls.
|
||||
*/
|
||||
ReturnValue_t allFramesReception();
|
||||
/**
|
||||
* Dummy method for master channel demultiplexing.
|
||||
* As there's only one Master Channel here, the method calls #virtualChannelDemultiplexing.
|
||||
* @return The return codes of #virtualChannelDemultiplexing.
|
||||
*/
|
||||
ReturnValue_t masterChannelDemultiplexing();
|
||||
/**
|
||||
* Method to demultiplex the Frames to Virtual Channels (VC's).
|
||||
* Looks up the requested VC in #virtualChannels and forwards the Frame to its
|
||||
* #frameAcceptanceAndReportingMechanism method, if found.
|
||||
* @return The higher method codes or @c VC_NOT_FOUND.
|
||||
*/
|
||||
ReturnValue_t virtualChannelDemultiplexing();
|
||||
};
|
||||
|
||||
#endif /* DATALINKLAYER_H_ */
|
||||
#ifndef DATALINKLAYER_H_
|
||||
#define DATALINKLAYER_H_
|
||||
|
||||
#include "../datalinklayer/CCSDSReturnValuesIF.h"
|
||||
#include "../datalinklayer/ClcwIF.h"
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
#include "../datalinklayer/VirtualChannelReceptionIF.h"
|
||||
#include "../events/Event.h"
|
||||
#include <map>
|
||||
|
||||
|
||||
class VirtualChannelReception;
|
||||
/**
|
||||
* A complete representation of the CCSDS Data Link Layer.
|
||||
* The operations of this layer are defined in the CCSDS TC Space Data Link Protocol
|
||||
* document. It is configured to handle a VC Demultiplexing function. All reception
|
||||
* steps are performed.
|
||||
*/
|
||||
class DataLinkLayer : public CCSDSReturnValuesIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1;
|
||||
static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0
|
||||
static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
|
||||
static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
|
||||
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
|
||||
// static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. No parameters.
|
||||
static const Event FRAME_PROCESSING_FAILED = MAKE_EVENT(5, SEVERITY::LOW); //!< The CCSDS Board could not interpret a TC
|
||||
/**
|
||||
* The Constructor sets the passed parameters and nothing else.
|
||||
* @param set_frame_buffer The buffer in which incoming frame candidates are stored.
|
||||
* @param setClcw The CLCW class to work on when returning CLCW information.
|
||||
* @param set_start_sequence_length Length of the Start sequence in front of every TC Transfer Frame.
|
||||
* @param set_scid The SCID to operate on.
|
||||
*/
|
||||
DataLinkLayer( uint8_t* set_frame_buffer, ClcwIF* setClcw, uint8_t set_start_sequence_length, uint16_t set_scid );
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
~DataLinkLayer();
|
||||
/**
|
||||
* This method tries to process a frame that is placed in #frameBuffer.
|
||||
* The procedures described in the Standard are performed.
|
||||
* @param length Length of the incoming frame candidate.
|
||||
* @return @c RETURN_OK on successful handling, otherwise the return codes of the higher methods.
|
||||
*/
|
||||
ReturnValue_t processFrame( uint16_t length );
|
||||
/**
|
||||
* Configuration method to add a new TC Virtual Channel.
|
||||
* Shall only be called during initialization. As soon as the method was called, the layer can
|
||||
* handle Frames directed to this VC.
|
||||
* @param virtualChannelId Id of the VC. Shall be smaller than 64.
|
||||
* @param object Reference to the object that handles the Frame.
|
||||
* @return @c RETURN_OK on success, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t addVirtualChannel( uint8_t virtualChannelId, VirtualChannelReceptionIF* object );
|
||||
/**
|
||||
* The initialization method calls the @c initialize routine of all virtual channels.
|
||||
* @return The return code of the first failed VC initialization or @c RETURN_OK.
|
||||
*/
|
||||
ReturnValue_t initialize();
|
||||
private:
|
||||
typedef std::map<uint8_t, VirtualChannelReceptionIF*>::iterator virtualChannelIterator; //!< Typedef to simplify handling the #virtualChannels map.
|
||||
static const uint8_t FRAME_VERSION_NUMBER_DEFAULT = 0x00; //!< Constant for the default value of Frame Version Numbers.
|
||||
static const uint8_t FRAME_PRIMARY_HEADER_LENGTH = 5; //!< Length of the frame's primary header.
|
||||
static const uint8_t START_SEQUENCE_PATTERN = 0x00; //!< The start sequence pattern which might be with the frame.
|
||||
static const bool USE_CRC = true; //!< A global, so called "Managed Parameter" that identifies if incoming frames have CRC's or not.
|
||||
uint16_t spacecraftId; //!< The Space Craft Identifier (SCID) configured.
|
||||
uint8_t* frameBuffer; //!< A pointer to point to the current incoming frame.
|
||||
ClcwIF* clcw; //!< Pointer to store the CLCW to work on.
|
||||
uint16_t receivedDataLength; //!< Stores the length of the currently processed frame.
|
||||
TcTransferFrame currentFrame; //!< Stores a more convenient access to the current frame.
|
||||
uint8_t startSequenceLength; //!< Configured length of the start sequence. Maybe this must be done more variable.
|
||||
std::map<uint8_t, VirtualChannelReceptionIF*> virtualChannels; //!< Map of all virtual channels assigned.
|
||||
/**
|
||||
* Method that performs all possible frame validity checks (as specified).
|
||||
* @return Various error codes or @c RETURN_OK on success.
|
||||
*/
|
||||
ReturnValue_t frameValidationCheck();
|
||||
/**
|
||||
* First method to call.
|
||||
* Removes start sequence bytes and checks if the complete frame was received.
|
||||
* SHOULDDO: Maybe handling the start sequence must be done more variable.
|
||||
* @return @c RETURN_OK or @c TOO_SHORT.
|
||||
*/
|
||||
ReturnValue_t frameDelimitingAndFillRemoval();
|
||||
/**
|
||||
* Small helper method to check the CRC of the Frame.
|
||||
* @return @c RETURN_OK or @c CRC_FAILED.
|
||||
*/
|
||||
ReturnValue_t frameCheckCRC();
|
||||
/**
|
||||
* Method that groups the reception process of all Frames.
|
||||
* Calls #frameDelimitingAndFillRemoval and #frameValidationCheck.
|
||||
* @return The return codes of the sub calls.
|
||||
*/
|
||||
ReturnValue_t allFramesReception();
|
||||
/**
|
||||
* Dummy method for master channel demultiplexing.
|
||||
* As there's only one Master Channel here, the method calls #virtualChannelDemultiplexing.
|
||||
* @return The return codes of #virtualChannelDemultiplexing.
|
||||
*/
|
||||
ReturnValue_t masterChannelDemultiplexing();
|
||||
/**
|
||||
* Method to demultiplex the Frames to Virtual Channels (VC's).
|
||||
* Looks up the requested VC in #virtualChannels and forwards the Frame to its
|
||||
* #frameAcceptanceAndReportingMechanism method, if found.
|
||||
* @return The higher method codes or @c VC_NOT_FOUND.
|
||||
*/
|
||||
ReturnValue_t virtualChannelDemultiplexing();
|
||||
};
|
||||
|
||||
#endif /* DATALINKLAYER_H_ */
|
||||
|
@ -1,54 +1,54 @@
|
||||
/**
|
||||
* @file Farm1StateIF.h
|
||||
* @brief This file defines the Farm1StateIF class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATEIF_H_
|
||||
#define FARM1STATEIF_H_
|
||||
|
||||
#include <framework/datalinklayer/CCSDSReturnValuesIF.h>
|
||||
class VirtualChannelReception;
|
||||
class TcTransferFrame;
|
||||
class ClcwIF;
|
||||
|
||||
/**
|
||||
* This is the interface for states of the FARM-1 state machine.
|
||||
* Classes implementing this interface can be used as FARM-1 states. This is a simple implementation
|
||||
* of the state pattern.
|
||||
*/
|
||||
class Farm1StateIF : public CCSDSReturnValuesIF {
|
||||
public:
|
||||
/**
|
||||
* A method that shall handle an incoming frame as AD Frame.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If forwarding to a MAP Channel is required, the return value shall be #FRAME_OK.
|
||||
* Otherwise, an appropriate return value or error code shall be generated.
|
||||
*/
|
||||
virtual ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
* This method shall handle frames that have been successfully identified as BC Unlock frames.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If forwarding to a MAP Channel is required, the return value shall be #FRAME_OK.
|
||||
* Otherwise, an appropriate return value or error code shall be generated.
|
||||
*/
|
||||
virtual ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
* This method shall handle frames that have been successfully identified as BC Set VR frames.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return If forwarding to a MAP Channel is required, the return value shall be #FRAME_OK.
|
||||
* Otherwise, an appropriate return value or error code shall be generated.
|
||||
*/
|
||||
virtual ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr ) = 0;
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
virtual ~Farm1StateIF() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FARM1STATEIF_H_ */
|
||||
/**
|
||||
* @file Farm1StateIF.h
|
||||
* @brief This file defines the Farm1StateIF class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATEIF_H_
|
||||
#define FARM1STATEIF_H_
|
||||
|
||||
#include "../datalinklayer/CCSDSReturnValuesIF.h"
|
||||
class VirtualChannelReception;
|
||||
class TcTransferFrame;
|
||||
class ClcwIF;
|
||||
|
||||
/**
|
||||
* This is the interface for states of the FARM-1 state machine.
|
||||
* Classes implementing this interface can be used as FARM-1 states. This is a simple implementation
|
||||
* of the state pattern.
|
||||
*/
|
||||
class Farm1StateIF : public CCSDSReturnValuesIF {
|
||||
public:
|
||||
/**
|
||||
* A method that shall handle an incoming frame as AD Frame.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If forwarding to a MAP Channel is required, the return value shall be #FRAME_OK.
|
||||
* Otherwise, an appropriate return value or error code shall be generated.
|
||||
*/
|
||||
virtual ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
* This method shall handle frames that have been successfully identified as BC Unlock frames.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If forwarding to a MAP Channel is required, the return value shall be #FRAME_OK.
|
||||
* Otherwise, an appropriate return value or error code shall be generated.
|
||||
*/
|
||||
virtual ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
* This method shall handle frames that have been successfully identified as BC Set VR frames.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return If forwarding to a MAP Channel is required, the return value shall be #FRAME_OK.
|
||||
* Otherwise, an appropriate return value or error code shall be generated.
|
||||
*/
|
||||
virtual ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr ) = 0;
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
virtual ~Farm1StateIF() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FARM1STATEIF_H_ */
|
||||
|
@ -1,35 +1,35 @@
|
||||
/**
|
||||
* @file Farm1StateLockout.cpp
|
||||
* @brief This file defines the Farm1StateLockout class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <framework/datalinklayer/ClcwIF.h>
|
||||
#include <framework/datalinklayer/Farm1StateLockout.h>
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
#include <framework/datalinklayer/VirtualChannelReception.h>
|
||||
Farm1StateLockout::Farm1StateLockout(VirtualChannelReception* setMyVC) : myVC(setMyVC) {
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateLockout::handleADFrame(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
return FARM_IN_LOCKOUT;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateLockout::handleBCUnlockCommand(ClcwIF* clcw) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
clcw->setLockoutFlag( false );
|
||||
clcw->setWaitFlag( false );
|
||||
myVC->currentState = &(myVC->openState);
|
||||
return BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateLockout::handleBCSetVrCommand(ClcwIF* clcw,
|
||||
uint8_t vr) {
|
||||
myVC->farmBCounter++;
|
||||
return BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
/**
|
||||
* @file Farm1StateLockout.cpp
|
||||
* @brief This file defines the Farm1StateLockout class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../datalinklayer/ClcwIF.h"
|
||||
#include "../datalinklayer/Farm1StateLockout.h"
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
#include "../datalinklayer/VirtualChannelReception.h"
|
||||
Farm1StateLockout::Farm1StateLockout(VirtualChannelReception* setMyVC) : myVC(setMyVC) {
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateLockout::handleADFrame(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
return FARM_IN_LOCKOUT;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateLockout::handleBCUnlockCommand(ClcwIF* clcw) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
clcw->setLockoutFlag( false );
|
||||
clcw->setWaitFlag( false );
|
||||
myVC->currentState = &(myVC->openState);
|
||||
return BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateLockout::handleBCSetVrCommand(ClcwIF* clcw,
|
||||
uint8_t vr) {
|
||||
myVC->farmBCounter++;
|
||||
return BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
/**
|
||||
* @file Farm1StateLockout.h
|
||||
* @brief This file defines the Farm1StateLockout class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATELOCKOUT_H_
|
||||
#define FARM1STATELOCKOUT_H_
|
||||
|
||||
#include <framework/datalinklayer/Farm1StateIF.h>
|
||||
|
||||
/**
|
||||
* This class represents the FARM-1 "Lockout" State.
|
||||
* The Lockout state is reached if the received Transfer Frame Sequence Number is completely wrong
|
||||
* (i.e. within the Lockout Window). No AD Frames are forwarded. To leave the State, a BC Unlock
|
||||
* command is required.
|
||||
*/
|
||||
class Farm1StateLockout : public Farm1StateIF {
|
||||
private:
|
||||
/**
|
||||
* This is a reference to the "owner" class the State works on.
|
||||
*/
|
||||
VirtualChannelReception* myVC;
|
||||
public:
|
||||
/**
|
||||
* The default constructor if the State.
|
||||
* Sets the "owner" of the State.
|
||||
* @param setMyVC The "owner" class.
|
||||
*/
|
||||
Farm1StateLockout( VirtualChannelReception* setMyVC );
|
||||
/**
|
||||
* All AD Frames are rejected with FARM_IN_LOCKOUT
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return FARM_IN_LOCKOUT
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State changes to Farm1StateOpen.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_UNLOCK_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* The V(r) value is not set in Lockout State, even though the Command itself is accepted.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_SET_VR_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr );
|
||||
};
|
||||
|
||||
|
||||
#endif /* FARM1STATELOCKOUT_H_ */
|
||||
/**
|
||||
* @file Farm1StateLockout.h
|
||||
* @brief This file defines the Farm1StateLockout class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATELOCKOUT_H_
|
||||
#define FARM1STATELOCKOUT_H_
|
||||
|
||||
#include "../datalinklayer/Farm1StateIF.h"
|
||||
|
||||
/**
|
||||
* This class represents the FARM-1 "Lockout" State.
|
||||
* The Lockout state is reached if the received Transfer Frame Sequence Number is completely wrong
|
||||
* (i.e. within the Lockout Window). No AD Frames are forwarded. To leave the State, a BC Unlock
|
||||
* command is required.
|
||||
*/
|
||||
class Farm1StateLockout : public Farm1StateIF {
|
||||
private:
|
||||
/**
|
||||
* This is a reference to the "owner" class the State works on.
|
||||
*/
|
||||
VirtualChannelReception* myVC;
|
||||
public:
|
||||
/**
|
||||
* The default constructor if the State.
|
||||
* Sets the "owner" of the State.
|
||||
* @param setMyVC The "owner" class.
|
||||
*/
|
||||
Farm1StateLockout( VirtualChannelReception* setMyVC );
|
||||
/**
|
||||
* All AD Frames are rejected with FARM_IN_LOCKOUT
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return FARM_IN_LOCKOUT
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State changes to Farm1StateOpen.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_UNLOCK_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* The V(r) value is not set in Lockout State, even though the Command itself is accepted.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_SET_VR_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr );
|
||||
};
|
||||
|
||||
|
||||
#endif /* FARM1STATELOCKOUT_H_ */
|
||||
|
@ -1,49 +1,49 @@
|
||||
/**
|
||||
* @file Farm1StateOpen.cpp
|
||||
* @brief This file defines the Farm1StateOpen class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <framework/datalinklayer/ClcwIF.h>
|
||||
#include <framework/datalinklayer/Farm1StateOpen.h>
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
#include <framework/datalinklayer/VirtualChannelReception.h>
|
||||
|
||||
Farm1StateOpen::Farm1StateOpen(VirtualChannelReception* setMyVC) : myVC(setMyVC) {
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateOpen::handleADFrame(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
int8_t diff = frame->getSequenceNumber() - myVC->vR;
|
||||
if (diff == 0 ) {
|
||||
myVC->vR++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
return RETURN_OK;
|
||||
} else if (diff < myVC->positiveWindow && diff > 0 ) {
|
||||
clcw->setRetransmitFlag(true);
|
||||
return NS_POSITIVE_W;
|
||||
} else if (diff < 0 && diff >= -myVC->negativeWindow) {
|
||||
return NS_NEGATIVE_W;
|
||||
} else {
|
||||
clcw->setLockoutFlag(true);
|
||||
myVC->currentState = &(myVC->lockoutState);
|
||||
return NS_LOCKOUT;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateOpen::handleBCUnlockCommand( ClcwIF* clcw ) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
return BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateOpen::handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr ) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
myVC->vR = vr;
|
||||
return BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
/**
|
||||
* @file Farm1StateOpen.cpp
|
||||
* @brief This file defines the Farm1StateOpen class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include "../datalinklayer/ClcwIF.h"
|
||||
#include "../datalinklayer/Farm1StateOpen.h"
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
#include "../datalinklayer/VirtualChannelReception.h"
|
||||
|
||||
Farm1StateOpen::Farm1StateOpen(VirtualChannelReception* setMyVC) : myVC(setMyVC) {
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateOpen::handleADFrame(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
int8_t diff = frame->getSequenceNumber() - myVC->vR;
|
||||
if (diff == 0 ) {
|
||||
myVC->vR++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
return RETURN_OK;
|
||||
} else if (diff < myVC->positiveWindow && diff > 0 ) {
|
||||
clcw->setRetransmitFlag(true);
|
||||
return NS_POSITIVE_W;
|
||||
} else if (diff < 0 && diff >= -myVC->negativeWindow) {
|
||||
return NS_NEGATIVE_W;
|
||||
} else {
|
||||
clcw->setLockoutFlag(true);
|
||||
myVC->currentState = &(myVC->lockoutState);
|
||||
return NS_LOCKOUT;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateOpen::handleBCUnlockCommand( ClcwIF* clcw ) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
return BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateOpen::handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr ) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
myVC->vR = vr;
|
||||
return BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
|
@ -1,62 +1,62 @@
|
||||
/**
|
||||
* @file Farm1StateOpen.h
|
||||
* @brief This file defines the Farm1StateOpen class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATEOPEN_H_
|
||||
#define FARM1STATEOPEN_H_
|
||||
|
||||
#include <framework/datalinklayer/Farm1StateIF.h>
|
||||
|
||||
/**
|
||||
* This class represents the FARM-1 "Open" State.
|
||||
* The Open state is the state of normal operation. It handles all types of frames,
|
||||
* including AD Frames. If a wrong Frame Sequence Number is detected in an AD Frame, the
|
||||
* State reacts as specified.
|
||||
*/
|
||||
class Farm1StateOpen : public Farm1StateIF {
|
||||
private:
|
||||
/**
|
||||
* This is a reference to the "owner" class the State works on.
|
||||
*/
|
||||
VirtualChannelReception* myVC;
|
||||
public:
|
||||
/**
|
||||
* The default constructor if the State.
|
||||
* Sets the "owner" of the State.
|
||||
* @param setMyVC The "owner" class.
|
||||
*/
|
||||
Farm1StateOpen( VirtualChannelReception* setMyVC );
|
||||
/**
|
||||
* Method to check the validity of AD Frames.
|
||||
* It checks the Frame Sequence Number and reacts as specified in the standard. The state may
|
||||
* change to Farm1StateLockout.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If the Sequence Number is ok, it returns #RETURN_OK. Otherwise either #NS_POSITIVE_W,
|
||||
* #NS_NEGATIVE_W or NS_LOCKOUT is returned.
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State does not change.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_UNLOCK_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State does not change.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_SET_VR_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr );
|
||||
};
|
||||
|
||||
|
||||
#endif /* FARM1STATEOPEN_H_ */
|
||||
/**
|
||||
* @file Farm1StateOpen.h
|
||||
* @brief This file defines the Farm1StateOpen class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATEOPEN_H_
|
||||
#define FARM1STATEOPEN_H_
|
||||
|
||||
#include "../datalinklayer/Farm1StateIF.h"
|
||||
|
||||
/**
|
||||
* This class represents the FARM-1 "Open" State.
|
||||
* The Open state is the state of normal operation. It handles all types of frames,
|
||||
* including AD Frames. If a wrong Frame Sequence Number is detected in an AD Frame, the
|
||||
* State reacts as specified.
|
||||
*/
|
||||
class Farm1StateOpen : public Farm1StateIF {
|
||||
private:
|
||||
/**
|
||||
* This is a reference to the "owner" class the State works on.
|
||||
*/
|
||||
VirtualChannelReception* myVC;
|
||||
public:
|
||||
/**
|
||||
* The default constructor if the State.
|
||||
* Sets the "owner" of the State.
|
||||
* @param setMyVC The "owner" class.
|
||||
*/
|
||||
Farm1StateOpen( VirtualChannelReception* setMyVC );
|
||||
/**
|
||||
* Method to check the validity of AD Frames.
|
||||
* It checks the Frame Sequence Number and reacts as specified in the standard. The state may
|
||||
* change to Farm1StateLockout.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If the Sequence Number is ok, it returns #RETURN_OK. Otherwise either #NS_POSITIVE_W,
|
||||
* #NS_NEGATIVE_W or NS_LOCKOUT is returned.
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State does not change.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_UNLOCK_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State does not change.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_SET_VR_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr );
|
||||
};
|
||||
|
||||
|
||||
#endif /* FARM1STATEOPEN_H_ */
|
||||
|
@ -1,43 +1,43 @@
|
||||
/**
|
||||
* @file Farm1StateWait.cpp
|
||||
* @brief This file defines the Farm1StateWait class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
#include <framework/datalinklayer/ClcwIF.h>
|
||||
#include <framework/datalinklayer/Farm1StateWait.h>
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
#include <framework/datalinklayer/VirtualChannelReception.h>
|
||||
|
||||
Farm1StateWait::Farm1StateWait(VirtualChannelReception* setMyVC) : myVC(setMyVC) {
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateWait::handleADFrame(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
|
||||
int8_t diff = frame->getSequenceNumber() - myVC->vR;
|
||||
if ( diff < -myVC->negativeWindow || diff >= myVC->positiveWindow ) {
|
||||
clcw->setLockoutFlag(true);
|
||||
myVC->currentState = &(myVC->lockoutState);
|
||||
}
|
||||
return FARM_IN_WAIT;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateWait::handleBCUnlockCommand(ClcwIF* clcw) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
clcw->setWaitFlag( false );
|
||||
myVC->currentState = &(myVC->openState);
|
||||
return BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateWait::handleBCSetVrCommand(ClcwIF* clcw, uint8_t vr) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setWaitFlag( false );
|
||||
clcw->setRetransmitFlag(false);
|
||||
myVC->vR = vr;
|
||||
myVC->currentState = &(myVC->openState);
|
||||
return BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
/**
|
||||
* @file Farm1StateWait.cpp
|
||||
* @brief This file defines the Farm1StateWait class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
#include "../datalinklayer/ClcwIF.h"
|
||||
#include "../datalinklayer/Farm1StateWait.h"
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
#include "../datalinklayer/VirtualChannelReception.h"
|
||||
|
||||
Farm1StateWait::Farm1StateWait(VirtualChannelReception* setMyVC) : myVC(setMyVC) {
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateWait::handleADFrame(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
|
||||
int8_t diff = frame->getSequenceNumber() - myVC->vR;
|
||||
if ( diff < -myVC->negativeWindow || diff >= myVC->positiveWindow ) {
|
||||
clcw->setLockoutFlag(true);
|
||||
myVC->currentState = &(myVC->lockoutState);
|
||||
}
|
||||
return FARM_IN_WAIT;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateWait::handleBCUnlockCommand(ClcwIF* clcw) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
clcw->setWaitFlag( false );
|
||||
myVC->currentState = &(myVC->openState);
|
||||
return BC_IS_UNLOCK_COMMAND;
|
||||
}
|
||||
|
||||
ReturnValue_t Farm1StateWait::handleBCSetVrCommand(ClcwIF* clcw, uint8_t vr) {
|
||||
myVC->farmBCounter++;
|
||||
clcw->setWaitFlag( false );
|
||||
clcw->setRetransmitFlag(false);
|
||||
myVC->vR = vr;
|
||||
myVC->currentState = &(myVC->openState);
|
||||
return BC_IS_SET_VR_COMMAND;
|
||||
}
|
||||
|
@ -1,58 +1,58 @@
|
||||
/**
|
||||
* @file Farm1StateWait.h
|
||||
* @brief This file defines the Farm1StateWait class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATEWAIT_H_
|
||||
#define FARM1STATEWAIT_H_
|
||||
|
||||
#include <framework/datalinklayer/Farm1StateIF.h>
|
||||
|
||||
/**
|
||||
* This class represents the FARM-1 "Wait" State.
|
||||
* The Wait state is reached if higher level procedures inform the FARM-1 Machine to wait
|
||||
* for a certain period. Currently, it is not in use.
|
||||
*/
|
||||
class Farm1StateWait : public Farm1StateIF {
|
||||
private:
|
||||
/**
|
||||
* This is a reference to the "owner" class the State works on.
|
||||
*/
|
||||
VirtualChannelReception* myVC;
|
||||
public:
|
||||
/**
|
||||
* The default constructor if the State.
|
||||
* Sets the "owner" of the State.
|
||||
* @param setMyVC The "owner" class.
|
||||
*/
|
||||
Farm1StateWait( VirtualChannelReception* setMyVC );
|
||||
/**
|
||||
* AD Frames are always discarded.
|
||||
* If the frame number is in the lockout window, the state changes to Farm1StateLockout.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return Always returns FARM_IN_WAIT.
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State changes to Farm1StateOpen.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_UNLOCK_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_SET_VR_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr );
|
||||
};
|
||||
|
||||
|
||||
#endif /* FARM1STATEWAIT_H_ */
|
||||
/**
|
||||
* @file Farm1StateWait.h
|
||||
* @brief This file defines the Farm1StateWait class.
|
||||
* @date 24.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef FARM1STATEWAIT_H_
|
||||
#define FARM1STATEWAIT_H_
|
||||
|
||||
#include "../datalinklayer/Farm1StateIF.h"
|
||||
|
||||
/**
|
||||
* This class represents the FARM-1 "Wait" State.
|
||||
* The Wait state is reached if higher level procedures inform the FARM-1 Machine to wait
|
||||
* for a certain period. Currently, it is not in use.
|
||||
*/
|
||||
class Farm1StateWait : public Farm1StateIF {
|
||||
private:
|
||||
/**
|
||||
* This is a reference to the "owner" class the State works on.
|
||||
*/
|
||||
VirtualChannelReception* myVC;
|
||||
public:
|
||||
/**
|
||||
* The default constructor if the State.
|
||||
* Sets the "owner" of the State.
|
||||
* @param setMyVC The "owner" class.
|
||||
*/
|
||||
Farm1StateWait( VirtualChannelReception* setMyVC );
|
||||
/**
|
||||
* AD Frames are always discarded.
|
||||
* If the frame number is in the lockout window, the state changes to Farm1StateLockout.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return Always returns FARM_IN_WAIT.
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* State changes to Farm1StateOpen.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_UNLOCK_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCUnlockCommand( ClcwIF* clcw );
|
||||
/**
|
||||
* These commands are handled as specified.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @param vr The V(r) value found in the frame.
|
||||
* @return As the frame needs no forwarding to a MAP Channel, #BC_IS_SET_VR_COMMAND
|
||||
* is returned.
|
||||
*/
|
||||
ReturnValue_t handleBCSetVrCommand( ClcwIF* clcw, uint8_t vr );
|
||||
};
|
||||
|
||||
|
||||
#endif /* FARM1STATEWAIT_H_ */
|
||||
|
@ -1,154 +1,154 @@
|
||||
/**
|
||||
* @file MapPacketExtraction.cpp
|
||||
* @brief This file defines the MapPacketExtraction class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/datalinklayer/MapPacketExtraction.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <framework/tmtcpacket/SpacePacketBase.h>
|
||||
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
||||
#include <framework/tmtcservices/TmTcMessage.h>
|
||||
#include <string.h>
|
||||
|
||||
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
|
||||
object_id_t setPacketDestination) :
|
||||
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0),
|
||||
bufferPosition(packetBuffer), packetDestination(setPacketDestination),
|
||||
packetStore(nullptr), tcQueueId(MessageQueueMessageIF::NO_QUEUE) {
|
||||
memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {
|
||||
uint8_t segmentationFlag = frame->getSequenceFlags();
|
||||
ReturnValue_t status = TOO_SHORT_MAP_EXTRACTION;
|
||||
switch (segmentationFlag) {
|
||||
case NO_SEGMENTATION:
|
||||
status = unpackBlockingPackets(frame);
|
||||
break;
|
||||
case FIRST_PORTION:
|
||||
packetLength = frame->getDataLength();
|
||||
if (packetLength <= MAX_PACKET_SIZE) {
|
||||
memcpy(packetBuffer, frame->getDataField(), packetLength);
|
||||
bufferPosition = &packetBuffer[packetLength];
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Packet too large! Size: "
|
||||
<< packetLength << std::endl;
|
||||
clearBuffers();
|
||||
status = CONTENT_TOO_LARGE;
|
||||
}
|
||||
break;
|
||||
case CONTINUING_PORTION:
|
||||
case LAST_PORTION:
|
||||
if (lastSegmentationFlag == FIRST_PORTION
|
||||
|| lastSegmentationFlag == CONTINUING_PORTION) {
|
||||
packetLength += frame->getDataLength();
|
||||
if (packetLength <= MAX_PACKET_SIZE) {
|
||||
memcpy(bufferPosition, frame->getDataField(),
|
||||
frame->getDataLength());
|
||||
bufferPosition = &packetBuffer[packetLength];
|
||||
if (segmentationFlag == LAST_PORTION) {
|
||||
status = sendCompletePacket(packetBuffer, packetLength);
|
||||
clearBuffers();
|
||||
}
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Packet too large! Size: "
|
||||
<< packetLength << std::endl;
|
||||
clearBuffers();
|
||||
status = CONTENT_TOO_LARGE;
|
||||
}
|
||||
} else {
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Illegal segment! Last flag: "
|
||||
<< (int) lastSegmentationFlag << std::endl;
|
||||
clearBuffers();
|
||||
status = ILLEGAL_SEGMENTATION_FLAG;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Illegal segmentationFlag: "
|
||||
<< (int) segmentationFlag << std::endl;
|
||||
clearBuffers();
|
||||
status = DATA_CORRUPTED;
|
||||
break;
|
||||
}
|
||||
lastSegmentationFlag = segmentationFlag;
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::unpackBlockingPackets(
|
||||
TcTransferFrame* frame) {
|
||||
ReturnValue_t status = TOO_SHORT_BLOCKED_PACKET;
|
||||
uint32_t totalLength = frame->getDataLength();
|
||||
if (totalLength > MAX_PACKET_SIZE)
|
||||
return CONTENT_TOO_LARGE;
|
||||
uint8_t* position = frame->getDataField();
|
||||
while ((totalLength > SpacePacketBase::MINIMUM_SIZE)) {
|
||||
SpacePacketBase packet(position);
|
||||
uint32_t packetSize = packet.getFullSize();
|
||||
if (packetSize <= totalLength) {
|
||||
status = sendCompletePacket(packet.getWholeData(),
|
||||
packet.getFullSize());
|
||||
totalLength -= packet.getFullSize();
|
||||
position += packet.getFullSize();
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
status = DATA_CORRUPTED;
|
||||
totalLength = 0;
|
||||
}
|
||||
}
|
||||
if (totalLength > 0) {
|
||||
status = RESIDUAL_DATA;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data,
|
||||
uint32_t size) {
|
||||
store_address_t store_id;
|
||||
ReturnValue_t status = this->packetStore->addData(&store_id, data, size);
|
||||
if (status == RETURN_OK) {
|
||||
TmTcMessage message(store_id);
|
||||
status = MessageQueueSenderIF::sendMessage(tcQueueId,&message);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void MapPacketExtraction::clearBuffers() {
|
||||
memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
bufferPosition = packetBuffer;
|
||||
packetLength = 0;
|
||||
lastSegmentationFlag = NO_SEGMENTATION;
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::initialize() {
|
||||
packetStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
|
||||
AcceptsTelecommandsIF* distributor = objectManager->get<
|
||||
AcceptsTelecommandsIF>(packetDestination);
|
||||
if ((packetStore != NULL) && (distributor != NULL)) {
|
||||
tcQueueId = distributor->getRequestQueue();
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void MapPacketExtraction::printPacketBuffer(void) {
|
||||
sif::debug << "DLL: packet_buffer contains: " << std::endl;
|
||||
for (uint32_t i = 0; i < this->packetLength; ++i) {
|
||||
sif::debug << "packet_buffer[" << std::dec << i << "]: 0x" << std::hex
|
||||
<< (uint16_t) this->packetBuffer[i] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MapPacketExtraction::getMapId() const {
|
||||
return mapId;
|
||||
}
|
||||
/**
|
||||
* @file MapPacketExtraction.cpp
|
||||
* @brief This file defines the MapPacketExtraction class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include "../datalinklayer/MapPacketExtraction.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
#include "../tmtcpacket/SpacePacketBase.h"
|
||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "../tmtcservices/TmTcMessage.h"
|
||||
#include <string.h>
|
||||
|
||||
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
|
||||
object_id_t setPacketDestination) :
|
||||
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0),
|
||||
bufferPosition(packetBuffer), packetDestination(setPacketDestination),
|
||||
packetStore(nullptr), tcQueueId(MessageQueueMessageIF::NO_QUEUE) {
|
||||
memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {
|
||||
uint8_t segmentationFlag = frame->getSequenceFlags();
|
||||
ReturnValue_t status = TOO_SHORT_MAP_EXTRACTION;
|
||||
switch (segmentationFlag) {
|
||||
case NO_SEGMENTATION:
|
||||
status = unpackBlockingPackets(frame);
|
||||
break;
|
||||
case FIRST_PORTION:
|
||||
packetLength = frame->getDataLength();
|
||||
if (packetLength <= MAX_PACKET_SIZE) {
|
||||
memcpy(packetBuffer, frame->getDataField(), packetLength);
|
||||
bufferPosition = &packetBuffer[packetLength];
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Packet too large! Size: "
|
||||
<< packetLength << std::endl;
|
||||
clearBuffers();
|
||||
status = CONTENT_TOO_LARGE;
|
||||
}
|
||||
break;
|
||||
case CONTINUING_PORTION:
|
||||
case LAST_PORTION:
|
||||
if (lastSegmentationFlag == FIRST_PORTION
|
||||
|| lastSegmentationFlag == CONTINUING_PORTION) {
|
||||
packetLength += frame->getDataLength();
|
||||
if (packetLength <= MAX_PACKET_SIZE) {
|
||||
memcpy(bufferPosition, frame->getDataField(),
|
||||
frame->getDataLength());
|
||||
bufferPosition = &packetBuffer[packetLength];
|
||||
if (segmentationFlag == LAST_PORTION) {
|
||||
status = sendCompletePacket(packetBuffer, packetLength);
|
||||
clearBuffers();
|
||||
}
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Packet too large! Size: "
|
||||
<< packetLength << std::endl;
|
||||
clearBuffers();
|
||||
status = CONTENT_TOO_LARGE;
|
||||
}
|
||||
} else {
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Illegal segment! Last flag: "
|
||||
<< (int) lastSegmentationFlag << std::endl;
|
||||
clearBuffers();
|
||||
status = ILLEGAL_SEGMENTATION_FLAG;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sif::error
|
||||
<< "MapPacketExtraction::extractPackets. Illegal segmentationFlag: "
|
||||
<< (int) segmentationFlag << std::endl;
|
||||
clearBuffers();
|
||||
status = DATA_CORRUPTED;
|
||||
break;
|
||||
}
|
||||
lastSegmentationFlag = segmentationFlag;
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::unpackBlockingPackets(
|
||||
TcTransferFrame* frame) {
|
||||
ReturnValue_t status = TOO_SHORT_BLOCKED_PACKET;
|
||||
uint32_t totalLength = frame->getDataLength();
|
||||
if (totalLength > MAX_PACKET_SIZE)
|
||||
return CONTENT_TOO_LARGE;
|
||||
uint8_t* position = frame->getDataField();
|
||||
while ((totalLength > SpacePacketBase::MINIMUM_SIZE)) {
|
||||
SpacePacketBase packet(position);
|
||||
uint32_t packetSize = packet.getFullSize();
|
||||
if (packetSize <= totalLength) {
|
||||
status = sendCompletePacket(packet.getWholeData(),
|
||||
packet.getFullSize());
|
||||
totalLength -= packet.getFullSize();
|
||||
position += packet.getFullSize();
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
status = DATA_CORRUPTED;
|
||||
totalLength = 0;
|
||||
}
|
||||
}
|
||||
if (totalLength > 0) {
|
||||
status = RESIDUAL_DATA;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data,
|
||||
uint32_t size) {
|
||||
store_address_t store_id;
|
||||
ReturnValue_t status = this->packetStore->addData(&store_id, data, size);
|
||||
if (status == RETURN_OK) {
|
||||
TmTcMessage message(store_id);
|
||||
status = MessageQueueSenderIF::sendMessage(tcQueueId,&message);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void MapPacketExtraction::clearBuffers() {
|
||||
memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
bufferPosition = packetBuffer;
|
||||
packetLength = 0;
|
||||
lastSegmentationFlag = NO_SEGMENTATION;
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::initialize() {
|
||||
packetStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
|
||||
AcceptsTelecommandsIF* distributor = objectManager->get<
|
||||
AcceptsTelecommandsIF>(packetDestination);
|
||||
if ((packetStore != NULL) && (distributor != NULL)) {
|
||||
tcQueueId = distributor->getRequestQueue();
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void MapPacketExtraction::printPacketBuffer(void) {
|
||||
sif::debug << "DLL: packet_buffer contains: " << std::endl;
|
||||
for (uint32_t i = 0; i < this->packetLength; ++i) {
|
||||
sif::debug << "packet_buffer[" << std::dec << i << "]: 0x" << std::hex
|
||||
<< (uint16_t) this->packetBuffer[i] << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MapPacketExtraction::getMapId() const {
|
||||
return mapId;
|
||||
}
|
||||
|
@ -1,78 +1,78 @@
|
||||
/**
|
||||
* @file MapPacketExtraction.h
|
||||
* @brief This file defines the MapPacketExtraction class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef MAPPACKETEXTRACTION_H_
|
||||
#define MAPPACKETEXTRACTION_H_
|
||||
|
||||
#include <framework/datalinklayer/MapPacketExtractionIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
|
||||
class StorageManagerIF;
|
||||
|
||||
/**
|
||||
* Implementation of a MAP Packet Extraction class.
|
||||
* The class implements the full MAP Packet Extraction functionality as described in the CCSDS
|
||||
* TC Space Data Link Protocol. It internally stores incomplete segmented packets until they are
|
||||
* fully received. All found packets are forwarded to a single distribution entity.
|
||||
*/
|
||||
class MapPacketExtraction: public MapPacketExtractionIF {
|
||||
private:
|
||||
static const uint32_t MAX_PACKET_SIZE = 4096;
|
||||
uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame.
|
||||
uint8_t mapId; //!< MAP ID of this MAP Channel.
|
||||
uint32_t packetLength; //!< Complete length of the current Space Packet.
|
||||
uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer.
|
||||
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
|
||||
object_id_t packetDestination;
|
||||
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored.
|
||||
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
|
||||
/**
|
||||
* Debug method to print the packet Buffer's content.
|
||||
*/
|
||||
void printPacketBuffer();
|
||||
/**
|
||||
* Method that is called if the segmentation flag is @c NO_SEGMENTATION.
|
||||
* The method extracts one or more packets within the frame and forwards them to the OBSW.
|
||||
* @param frame The TC Transfer Frame to work on.
|
||||
* @return @c RETURN_OK if all Packets were extracted. If something is entirely wrong,
|
||||
* @c DATA_CORRUPTED is returned, if some bytes are left over @c RESIDUAL_DATA.
|
||||
*/
|
||||
ReturnValue_t unpackBlockingPackets(TcTransferFrame* frame);
|
||||
/**
|
||||
* Helper method to forward a complete packet to the OBSW.
|
||||
* @param data Pointer to the data, either directly from the frame or from the packetBuffer.
|
||||
* @param size Complete total size of the packet.
|
||||
* @return Return Code of the Packet Store or the Message Queue.
|
||||
*/
|
||||
ReturnValue_t sendCompletePacket( uint8_t* data, uint32_t size );
|
||||
/**
|
||||
* Helper method to reset the internal buffer.
|
||||
*/
|
||||
void clearBuffers();
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
* Members are set to default values.
|
||||
* @param setMapId The MAP ID of the instance.
|
||||
*/
|
||||
MapPacketExtraction( uint8_t setMapId, object_id_t setPacketDestination );
|
||||
ReturnValue_t extractPackets(TcTransferFrame* frame);
|
||||
/**
|
||||
* The #packetStore and the default destination of #tcQueue are initialized here.
|
||||
* @return @c RETURN_OK on success, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t initialize();
|
||||
/**
|
||||
* Getter.
|
||||
* @return The MAP ID of this instance.
|
||||
*/
|
||||
uint8_t getMapId() const;
|
||||
};
|
||||
|
||||
#endif /* MAPPACKETEXTRACTION_H_ */
|
||||
/**
|
||||
* @file MapPacketExtraction.h
|
||||
* @brief This file defines the MapPacketExtraction class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef MAPPACKETEXTRACTION_H_
|
||||
#define MAPPACKETEXTRACTION_H_
|
||||
|
||||
#include "../datalinklayer/MapPacketExtractionIF.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
|
||||
class StorageManagerIF;
|
||||
|
||||
/**
|
||||
* Implementation of a MAP Packet Extraction class.
|
||||
* The class implements the full MAP Packet Extraction functionality as described in the CCSDS
|
||||
* TC Space Data Link Protocol. It internally stores incomplete segmented packets until they are
|
||||
* fully received. All found packets are forwarded to a single distribution entity.
|
||||
*/
|
||||
class MapPacketExtraction: public MapPacketExtractionIF {
|
||||
private:
|
||||
static const uint32_t MAX_PACKET_SIZE = 4096;
|
||||
uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame.
|
||||
uint8_t mapId; //!< MAP ID of this MAP Channel.
|
||||
uint32_t packetLength; //!< Complete length of the current Space Packet.
|
||||
uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer.
|
||||
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
|
||||
object_id_t packetDestination;
|
||||
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored.
|
||||
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
|
||||
/**
|
||||
* Debug method to print the packet Buffer's content.
|
||||
*/
|
||||
void printPacketBuffer();
|
||||
/**
|
||||
* Method that is called if the segmentation flag is @c NO_SEGMENTATION.
|
||||
* The method extracts one or more packets within the frame and forwards them to the OBSW.
|
||||
* @param frame The TC Transfer Frame to work on.
|
||||
* @return @c RETURN_OK if all Packets were extracted. If something is entirely wrong,
|
||||
* @c DATA_CORRUPTED is returned, if some bytes are left over @c RESIDUAL_DATA.
|
||||
*/
|
||||
ReturnValue_t unpackBlockingPackets(TcTransferFrame* frame);
|
||||
/**
|
||||
* Helper method to forward a complete packet to the OBSW.
|
||||
* @param data Pointer to the data, either directly from the frame or from the packetBuffer.
|
||||
* @param size Complete total size of the packet.
|
||||
* @return Return Code of the Packet Store or the Message Queue.
|
||||
*/
|
||||
ReturnValue_t sendCompletePacket( uint8_t* data, uint32_t size );
|
||||
/**
|
||||
* Helper method to reset the internal buffer.
|
||||
*/
|
||||
void clearBuffers();
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
* Members are set to default values.
|
||||
* @param setMapId The MAP ID of the instance.
|
||||
*/
|
||||
MapPacketExtraction( uint8_t setMapId, object_id_t setPacketDestination );
|
||||
ReturnValue_t extractPackets(TcTransferFrame* frame);
|
||||
/**
|
||||
* The #packetStore and the default destination of #tcQueue are initialized here.
|
||||
* @return @c RETURN_OK on success, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t initialize();
|
||||
/**
|
||||
* Getter.
|
||||
* @return The MAP ID of this instance.
|
||||
*/
|
||||
uint8_t getMapId() const;
|
||||
};
|
||||
|
||||
#endif /* MAPPACKETEXTRACTION_H_ */
|
||||
|
@ -1,47 +1,47 @@
|
||||
/**
|
||||
* @file MapPacketExtractionIF.h
|
||||
* @brief This file defines the MapPacketExtractionIF class.
|
||||
* @date 25.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef MAPPACKETEXTRACTIONIF_H_
|
||||
#define MAPPACKETEXTRACTIONIF_H_
|
||||
|
||||
#include <framework/datalinklayer/CCSDSReturnValuesIF.h>
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
|
||||
/**
|
||||
* This is the interface for MAP Packet Extraction classes.
|
||||
* All classes implementing this interface shall be able to extract blocked or segmented Space
|
||||
* Packets on a certain MAP channel. This is done in accordance with the CCSDS TC Space Data Link
|
||||
* Protocol.
|
||||
*/
|
||||
class MapPacketExtractionIF : public CCSDSReturnValuesIF {
|
||||
protected:
|
||||
static const uint8_t FIRST_PORTION = 0b01; //!< Identification of the first part of a segmented Packet.
|
||||
static const uint8_t CONTINUING_PORTION = 0b00; //!< Identification of a continuing part of segmented Packets.
|
||||
static const uint8_t LAST_PORTION = 0b10; //!< The last portion of a segmented Packet.
|
||||
static const uint8_t NO_SEGMENTATION = 0b11; //!< A Frame without segmentation but maybe with blocking.
|
||||
public:
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
virtual ~MapPacketExtractionIF() {
|
||||
}
|
||||
/**
|
||||
* Method to call to handle a single Transfer Frame.
|
||||
* The method tries to extract Packets from the frame as stated in the Standard.
|
||||
* @param frame
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t extractPackets( TcTransferFrame* frame ) = 0;
|
||||
/**
|
||||
* Any post-instantiation initialization shall be done in this method.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initialize() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* MAPPACKETEXTRACTIONIF_H_ */
|
||||
/**
|
||||
* @file MapPacketExtractionIF.h
|
||||
* @brief This file defines the MapPacketExtractionIF class.
|
||||
* @date 25.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef MAPPACKETEXTRACTIONIF_H_
|
||||
#define MAPPACKETEXTRACTIONIF_H_
|
||||
|
||||
#include "../datalinklayer/CCSDSReturnValuesIF.h"
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
|
||||
/**
|
||||
* This is the interface for MAP Packet Extraction classes.
|
||||
* All classes implementing this interface shall be able to extract blocked or segmented Space
|
||||
* Packets on a certain MAP channel. This is done in accordance with the CCSDS TC Space Data Link
|
||||
* Protocol.
|
||||
*/
|
||||
class MapPacketExtractionIF : public CCSDSReturnValuesIF {
|
||||
protected:
|
||||
static const uint8_t FIRST_PORTION = 0b01; //!< Identification of the first part of a segmented Packet.
|
||||
static const uint8_t CONTINUING_PORTION = 0b00; //!< Identification of a continuing part of segmented Packets.
|
||||
static const uint8_t LAST_PORTION = 0b10; //!< The last portion of a segmented Packet.
|
||||
static const uint8_t NO_SEGMENTATION = 0b11; //!< A Frame without segmentation but maybe with blocking.
|
||||
public:
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
virtual ~MapPacketExtractionIF() {
|
||||
}
|
||||
/**
|
||||
* Method to call to handle a single Transfer Frame.
|
||||
* The method tries to extract Packets from the frame as stated in the Standard.
|
||||
* @param frame
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t extractPackets( TcTransferFrame* frame ) = 0;
|
||||
/**
|
||||
* Any post-instantiation initialization shall be done in this method.
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initialize() = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* MAPPACKETEXTRACTIONIF_H_ */
|
||||
|
@ -1,102 +1,102 @@
|
||||
/**
|
||||
* @file TcTransferFrame.cpp
|
||||
* @brief This file defines the TcTransferFrame class.
|
||||
* @date 27.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
TcTransferFrame::TcTransferFrame() {
|
||||
frame = NULL;
|
||||
}
|
||||
|
||||
TcTransferFrame::TcTransferFrame(uint8_t* setData) {
|
||||
this->frame = (tc_transfer_frame*)setData;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getVersionNumber() {
|
||||
return (this->frame->header.flagsAndScid & 0b11000000) >> 6;
|
||||
}
|
||||
|
||||
bool TcTransferFrame::bypassFlagSet() {
|
||||
return (this->frame->header.flagsAndScid & 0b00100000) != 0;
|
||||
}
|
||||
|
||||
bool TcTransferFrame::controlCommandFlagSet() {
|
||||
return (this->frame->header.flagsAndScid & 0b00010000) != 0;
|
||||
}
|
||||
|
||||
bool TcTransferFrame::spareIsZero() {
|
||||
return ( (this->frame->header.flagsAndScid & 0b00001100) == 0 );
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getSpacecraftId() {
|
||||
return ( (this->frame->header.flagsAndScid & 0b00000011) << 8 ) + this->frame->header.spacecraftId_l;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getVirtualChannelId() {
|
||||
return (this->frame->header.vcidAndLength_h & 0b11111100) >> 2;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getFrameLength() {
|
||||
return ( (this->frame->header.vcidAndLength_h & 0b00000011) << 8 ) + this->frame->header.length_l;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getDataLength() {
|
||||
return this->getFrameLength() - this->getHeaderSize() -1 - FRAME_CRC_SIZE + 1; // -1 for the segment header.
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getSequenceNumber() {
|
||||
return this->frame->header.sequenceNumber;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getSequenceFlags() {
|
||||
return (this->frame->dataField & 0b11000000)>>6;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getMAPId() {
|
||||
return this->frame->dataField & 0b00111111;
|
||||
}
|
||||
|
||||
uint8_t* TcTransferFrame::getDataField() {
|
||||
return &(this->frame->dataField) + 1;
|
||||
}
|
||||
|
||||
uint8_t* TcTransferFrame::getFullFrame() {
|
||||
return (uint8_t*)this->frame;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getFullSize() {
|
||||
return this->getFrameLength() + 1;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getHeaderSize() {
|
||||
return sizeof(frame->header);
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getFullDataLength() {
|
||||
return this->getFrameLength() - this->getHeaderSize() - FRAME_CRC_SIZE + 1;
|
||||
}
|
||||
|
||||
uint8_t* TcTransferFrame::getFullDataField() {
|
||||
return &frame->dataField;
|
||||
}
|
||||
|
||||
void TcTransferFrame::print() {
|
||||
sif::debug << "Raw Frame: " << std::hex << std::endl;
|
||||
for (uint16_t count = 0; count < this->getFullSize(); count++ ) {
|
||||
sif::debug << (uint16_t)this->getFullFrame()[count] << " ";
|
||||
}
|
||||
sif::debug << std::dec << std::endl;
|
||||
// debug << "Frame Header:" << std::endl;
|
||||
// debug << "Version Number: " << std::hex << (uint16_t)this->current_frame.getVersionNumber() << std::endl;
|
||||
// debug << "Bypass Flag set?| Ctrl Cmd Flag set?: " << (uint16_t)this->current_frame.bypassFlagSet() << " | " << (uint16_t)this->current_frame.controlCommandFlagSet() << std::endl;
|
||||
// debug << "SCID : " << this->current_frame.getSpacecraftId() << std::endl;
|
||||
// debug << "VCID : " << (uint16_t)this->current_frame.getVirtualChannelId() << std::endl;
|
||||
// debug << "Frame length: " << std::dec << this->current_frame.getFrameLength() << std::endl;
|
||||
// debug << "Sequence Number: " << (uint16_t)this->current_frame.getSequenceNumber() << std::endl;
|
||||
}
|
||||
/**
|
||||
* @file TcTransferFrame.cpp
|
||||
* @brief This file defines the TcTransferFrame class.
|
||||
* @date 27.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
TcTransferFrame::TcTransferFrame() {
|
||||
frame = NULL;
|
||||
}
|
||||
|
||||
TcTransferFrame::TcTransferFrame(uint8_t* setData) {
|
||||
this->frame = (tc_transfer_frame*)setData;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getVersionNumber() {
|
||||
return (this->frame->header.flagsAndScid & 0b11000000) >> 6;
|
||||
}
|
||||
|
||||
bool TcTransferFrame::bypassFlagSet() {
|
||||
return (this->frame->header.flagsAndScid & 0b00100000) != 0;
|
||||
}
|
||||
|
||||
bool TcTransferFrame::controlCommandFlagSet() {
|
||||
return (this->frame->header.flagsAndScid & 0b00010000) != 0;
|
||||
}
|
||||
|
||||
bool TcTransferFrame::spareIsZero() {
|
||||
return ( (this->frame->header.flagsAndScid & 0b00001100) == 0 );
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getSpacecraftId() {
|
||||
return ( (this->frame->header.flagsAndScid & 0b00000011) << 8 ) + this->frame->header.spacecraftId_l;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getVirtualChannelId() {
|
||||
return (this->frame->header.vcidAndLength_h & 0b11111100) >> 2;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getFrameLength() {
|
||||
return ( (this->frame->header.vcidAndLength_h & 0b00000011) << 8 ) + this->frame->header.length_l;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getDataLength() {
|
||||
return this->getFrameLength() - this->getHeaderSize() -1 - FRAME_CRC_SIZE + 1; // -1 for the segment header.
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getSequenceNumber() {
|
||||
return this->frame->header.sequenceNumber;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getSequenceFlags() {
|
||||
return (this->frame->dataField & 0b11000000)>>6;
|
||||
}
|
||||
|
||||
uint8_t TcTransferFrame::getMAPId() {
|
||||
return this->frame->dataField & 0b00111111;
|
||||
}
|
||||
|
||||
uint8_t* TcTransferFrame::getDataField() {
|
||||
return &(this->frame->dataField) + 1;
|
||||
}
|
||||
|
||||
uint8_t* TcTransferFrame::getFullFrame() {
|
||||
return (uint8_t*)this->frame;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getFullSize() {
|
||||
return this->getFrameLength() + 1;
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getHeaderSize() {
|
||||
return sizeof(frame->header);
|
||||
}
|
||||
|
||||
uint16_t TcTransferFrame::getFullDataLength() {
|
||||
return this->getFrameLength() - this->getHeaderSize() - FRAME_CRC_SIZE + 1;
|
||||
}
|
||||
|
||||
uint8_t* TcTransferFrame::getFullDataField() {
|
||||
return &frame->dataField;
|
||||
}
|
||||
|
||||
void TcTransferFrame::print() {
|
||||
sif::debug << "Raw Frame: " << std::hex << std::endl;
|
||||
for (uint16_t count = 0; count < this->getFullSize(); count++ ) {
|
||||
sif::debug << (uint16_t)this->getFullFrame()[count] << " ";
|
||||
}
|
||||
sif::debug << std::dec << std::endl;
|
||||
// debug << "Frame Header:" << std::endl;
|
||||
// debug << "Version Number: " << std::hex << (uint16_t)this->current_frame.getVersionNumber() << std::endl;
|
||||
// debug << "Bypass Flag set?| Ctrl Cmd Flag set?: " << (uint16_t)this->current_frame.bypassFlagSet() << " | " << (uint16_t)this->current_frame.controlCommandFlagSet() << std::endl;
|
||||
// debug << "SCID : " << this->current_frame.getSpacecraftId() << std::endl;
|
||||
// debug << "VCID : " << (uint16_t)this->current_frame.getVirtualChannelId() << std::endl;
|
||||
// debug << "Frame length: " << std::dec << this->current_frame.getFrameLength() << std::endl;
|
||||
// debug << "Sequence Number: " << (uint16_t)this->current_frame.getSequenceNumber() << std::endl;
|
||||
}
|
||||
|
@ -1,49 +1,49 @@
|
||||
/**
|
||||
* @file TcTransferFrameLocal.cpp
|
||||
* @brief This file defines the TcTransferFrameLocal class.
|
||||
* @date 27.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/datalinklayer/TcTransferFrameLocal.h>
|
||||
#include <framework/globalfunctions/CRC.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <string.h>
|
||||
|
||||
TcTransferFrameLocal::TcTransferFrameLocal(bool bypass, bool controlCommand, uint16_t scid,
|
||||
uint8_t vcId, uint8_t sequenceNumber, uint8_t setSegmentHeader, uint8_t* data, uint16_t dataSize, uint16_t forceCrc) {
|
||||
this->frame = (tc_transfer_frame*)&localData;
|
||||
frame->header.flagsAndScid = (bypass << 5) + (controlCommand << 4) + ((scid & 0x0300) >> 8);
|
||||
frame->header.spacecraftId_l = (scid & 0x00FF);
|
||||
frame->header.vcidAndLength_h = (vcId & 0b00111111) << 2;
|
||||
frame->header.length_l = sizeof(TcTransferFramePrimaryHeader) -1;
|
||||
frame->header.sequenceNumber = sequenceNumber;
|
||||
frame->dataField = setSegmentHeader;
|
||||
if (data != NULL) {
|
||||
if (bypass && controlCommand) {
|
||||
memcpy(&(frame->dataField), data, dataSize);
|
||||
uint16_t totalSize = sizeof(TcTransferFramePrimaryHeader) + dataSize + FRAME_CRC_SIZE -1;
|
||||
frame->header.vcidAndLength_h |= (totalSize & 0x0300) >> 8;
|
||||
frame->header.length_l = (totalSize & 0x00FF);
|
||||
uint16_t crc = CRC::crc16ccitt(getFullFrame(), getFullSize() -2);
|
||||
this->getFullFrame()[getFullSize()-2] = (crc & 0xFF00) >> 8;
|
||||
this->getFullFrame()[getFullSize()-1] = (crc & 0x00FF);
|
||||
} else if (dataSize <= 1016) {
|
||||
memcpy(&(frame->dataField) +1, data, dataSize);
|
||||
uint16_t dataCrcSize = sizeof(TcTransferFramePrimaryHeader) + 1 + dataSize + FRAME_CRC_SIZE -1;
|
||||
frame->header.vcidAndLength_h |= (dataCrcSize & 0x0300) >> 8;
|
||||
frame->header.length_l = (dataCrcSize & 0x00FF);
|
||||
uint16_t crc = CRC::crc16ccitt(getFullFrame(), getFullSize() -2);
|
||||
this->getFullFrame()[getFullSize()-2] = (crc & 0xFF00) >> 8;
|
||||
this->getFullFrame()[getFullSize()-1] = (crc & 0x00FF);
|
||||
} else {
|
||||
sif::debug << "TcTransferFrameLocal: dataSize too large: " << dataSize << std::endl;
|
||||
}
|
||||
} else {
|
||||
//No data in frame
|
||||
}
|
||||
if (forceCrc != 0 ) {
|
||||
localData.data[getFullSize()-2] = (forceCrc & 0xFF00) >> 8;
|
||||
localData.data[getFullSize()-1] = (forceCrc & 0x00FF);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @file TcTransferFrameLocal.cpp
|
||||
* @brief This file defines the TcTransferFrameLocal class.
|
||||
* @date 27.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include "../datalinklayer/TcTransferFrameLocal.h"
|
||||
#include "../globalfunctions/CRC.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include <string.h>
|
||||
|
||||
TcTransferFrameLocal::TcTransferFrameLocal(bool bypass, bool controlCommand, uint16_t scid,
|
||||
uint8_t vcId, uint8_t sequenceNumber, uint8_t setSegmentHeader, uint8_t* data, uint16_t dataSize, uint16_t forceCrc) {
|
||||
this->frame = (tc_transfer_frame*)&localData;
|
||||
frame->header.flagsAndScid = (bypass << 5) + (controlCommand << 4) + ((scid & 0x0300) >> 8);
|
||||
frame->header.spacecraftId_l = (scid & 0x00FF);
|
||||
frame->header.vcidAndLength_h = (vcId & 0b00111111) << 2;
|
||||
frame->header.length_l = sizeof(TcTransferFramePrimaryHeader) -1;
|
||||
frame->header.sequenceNumber = sequenceNumber;
|
||||
frame->dataField = setSegmentHeader;
|
||||
if (data != NULL) {
|
||||
if (bypass && controlCommand) {
|
||||
memcpy(&(frame->dataField), data, dataSize);
|
||||
uint16_t totalSize = sizeof(TcTransferFramePrimaryHeader) + dataSize + FRAME_CRC_SIZE -1;
|
||||
frame->header.vcidAndLength_h |= (totalSize & 0x0300) >> 8;
|
||||
frame->header.length_l = (totalSize & 0x00FF);
|
||||
uint16_t crc = CRC::crc16ccitt(getFullFrame(), getFullSize() -2);
|
||||
this->getFullFrame()[getFullSize()-2] = (crc & 0xFF00) >> 8;
|
||||
this->getFullFrame()[getFullSize()-1] = (crc & 0x00FF);
|
||||
} else if (dataSize <= 1016) {
|
||||
memcpy(&(frame->dataField) +1, data, dataSize);
|
||||
uint16_t dataCrcSize = sizeof(TcTransferFramePrimaryHeader) + 1 + dataSize + FRAME_CRC_SIZE -1;
|
||||
frame->header.vcidAndLength_h |= (dataCrcSize & 0x0300) >> 8;
|
||||
frame->header.length_l = (dataCrcSize & 0x00FF);
|
||||
uint16_t crc = CRC::crc16ccitt(getFullFrame(), getFullSize() -2);
|
||||
this->getFullFrame()[getFullSize()-2] = (crc & 0xFF00) >> 8;
|
||||
this->getFullFrame()[getFullSize()-1] = (crc & 0x00FF);
|
||||
} else {
|
||||
sif::debug << "TcTransferFrameLocal: dataSize too large: " << dataSize << std::endl;
|
||||
}
|
||||
} else {
|
||||
//No data in frame
|
||||
}
|
||||
if (forceCrc != 0 ) {
|
||||
localData.data[getFullSize()-2] = (forceCrc & 0xFF00) >> 8;
|
||||
localData.data[getFullSize()-1] = (forceCrc & 0x00FF);
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +1,49 @@
|
||||
/**
|
||||
* @file TcTransferFrameLocal.h
|
||||
* @brief This file defines the TcTransferFrameLocal class.
|
||||
* @date 27.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef TCTRANSFERFRAMELOCAL_H_
|
||||
#define TCTRANSFERFRAMELOCAL_H_
|
||||
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
|
||||
/**
|
||||
* This is a helper class to locally create TC Transfer Frames.
|
||||
* This is mainly required for testing purposes and therefore not very sophisticated.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class TcTransferFrameLocal : public TcTransferFrame {
|
||||
private:
|
||||
/**
|
||||
* A stuct to locally store the complete data.
|
||||
*/
|
||||
struct frameData {
|
||||
TcTransferFramePrimaryHeader header; //!< The primary header.
|
||||
uint8_t data[1019]; //!< The data field.
|
||||
};
|
||||
public:
|
||||
frameData localData; //!< The local data in the Frame.
|
||||
/**
|
||||
* The default Constructor.
|
||||
* All parameters in the Header are passed.
|
||||
* If a BC Frame is detected no segment header is created.
|
||||
* Otherwise (AD and BD), the Segment Header is set.
|
||||
* @param bypass The bypass flag.
|
||||
* @param controlCommand The Control Command flag.
|
||||
* @param scid The SCID.
|
||||
* @param vcId The VCID.
|
||||
* @param sequenceNumber The Frame Sequence Number N(s)
|
||||
* @param setSegmentHeader A value for the Segment Header.
|
||||
* @param data Data to put into the Frame Data Field.
|
||||
* @param dataSize Size of the Data.
|
||||
* @param forceCrc if != 0, the value is used as CRC.
|
||||
*/
|
||||
TcTransferFrameLocal(bool bypass, bool controlCommand, uint16_t scid, uint8_t vcId, uint8_t sequenceNumber,
|
||||
uint8_t setSegmentHeader = 0xC0, uint8_t* data = NULL, uint16_t dataSize = 0, uint16_t forceCrc = 0);
|
||||
};
|
||||
|
||||
|
||||
#endif /* TCTRANSFERFRAMELOCAL_H_ */
|
||||
/**
|
||||
* @file TcTransferFrameLocal.h
|
||||
* @brief This file defines the TcTransferFrameLocal class.
|
||||
* @date 27.04.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef TCTRANSFERFRAMELOCAL_H_
|
||||
#define TCTRANSFERFRAMELOCAL_H_
|
||||
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
|
||||
/**
|
||||
* This is a helper class to locally create TC Transfer Frames.
|
||||
* This is mainly required for testing purposes and therefore not very sophisticated.
|
||||
* @ingroup ccsds_handling
|
||||
*/
|
||||
class TcTransferFrameLocal : public TcTransferFrame {
|
||||
private:
|
||||
/**
|
||||
* A stuct to locally store the complete data.
|
||||
*/
|
||||
struct frameData {
|
||||
TcTransferFramePrimaryHeader header; //!< The primary header.
|
||||
uint8_t data[1019]; //!< The data field.
|
||||
};
|
||||
public:
|
||||
frameData localData; //!< The local data in the Frame.
|
||||
/**
|
||||
* The default Constructor.
|
||||
* All parameters in the Header are passed.
|
||||
* If a BC Frame is detected no segment header is created.
|
||||
* Otherwise (AD and BD), the Segment Header is set.
|
||||
* @param bypass The bypass flag.
|
||||
* @param controlCommand The Control Command flag.
|
||||
* @param scid The SCID.
|
||||
* @param vcId The VCID.
|
||||
* @param sequenceNumber The Frame Sequence Number N(s)
|
||||
* @param setSegmentHeader A value for the Segment Header.
|
||||
* @param data Data to put into the Frame Data Field.
|
||||
* @param dataSize Size of the Data.
|
||||
* @param forceCrc if != 0, the value is used as CRC.
|
||||
*/
|
||||
TcTransferFrameLocal(bool bypass, bool controlCommand, uint16_t scid, uint8_t vcId, uint8_t sequenceNumber,
|
||||
uint8_t setSegmentHeader = 0xC0, uint8_t* data = NULL, uint16_t dataSize = 0, uint16_t forceCrc = 0);
|
||||
};
|
||||
|
||||
|
||||
#endif /* TCTRANSFERFRAMELOCAL_H_ */
|
||||
|
@ -1,121 +1,121 @@
|
||||
/**
|
||||
* @file VirtualChannelReception.cpp
|
||||
* @brief This file defines the VirtualChannelReception class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/datalinklayer/BCFrame.h>
|
||||
#include <framework/datalinklayer/VirtualChannelReception.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
VirtualChannelReception::VirtualChannelReception(uint8_t setChannelId,
|
||||
uint8_t setSlidingWindowWidth) :
|
||||
channelId(setChannelId), slidingWindowWidth(setSlidingWindowWidth), positiveWindow(
|
||||
setSlidingWindowWidth / 2), negativeWindow(setSlidingWindowWidth / 2), currentState(
|
||||
&openState), openState(this), waitState(this), lockoutState(this), vR(0), farmBCounter(
|
||||
0) {
|
||||
internalClcw.setVirtualChannel(channelId);
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::mapDemultiplexing(TcTransferFrame* frame) {
|
||||
uint8_t mapId = frame->getMAPId();
|
||||
mapChannelIterator iter = mapChannels.find(mapId);
|
||||
if (iter == mapChannels.end()) {
|
||||
// error << "VirtualChannelReception::mapDemultiplexing on VC " << std::hex << (int) channelId
|
||||
// << ": MapChannel " << (int) mapId << std::dec << " not found." << std::endl;
|
||||
return VC_NOT_FOUND;
|
||||
} else {
|
||||
return (iter->second)->extractPackets(frame);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
uint8_t bypass = frame->bypassFlagSet();
|
||||
uint8_t controlCommand = frame->controlCommandFlagSet();
|
||||
uint8_t typeValue = (bypass << 1) + controlCommand;
|
||||
switch (typeValue) {
|
||||
case AD_FRAME:
|
||||
return currentState->handleADFrame(frame, clcw);
|
||||
case BD_FRAME:
|
||||
return handleBDFrame(frame, clcw);
|
||||
case BC_FRAME:
|
||||
return handleBCFrame(frame, clcw);
|
||||
default:
|
||||
return ILLEGAL_FLAG_COMBINATION;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = doFARM(frame, &internalClcw);
|
||||
internalClcw.setReceiverFrameSequenceNumber(vR);
|
||||
internalClcw.setFarmBCount(farmBCounter);
|
||||
clcw->setWhole(internalClcw.getAsWhole());
|
||||
switch (result) {
|
||||
case RETURN_OK:
|
||||
return mapDemultiplexing(frame);
|
||||
case BC_IS_SET_VR_COMMAND:
|
||||
case BC_IS_UNLOCK_COMMAND:
|
||||
//Need to catch these codes to avoid error reporting later.
|
||||
return RETURN_OK;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExtractionIF* object) {
|
||||
std::pair<mapChannelIterator, bool> returnValue = mapChannels.insert(
|
||||
std::pair<uint8_t, MapPacketExtractionIF*>(mapId, object));
|
||||
if (returnValue.second == true) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
farmBCounter++;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
BcFrame content;
|
||||
ReturnValue_t returnValue = content.initialize(frame->getFullDataField(),
|
||||
frame->getFullDataLength());
|
||||
if (returnValue == BC_IS_UNLOCK_COMMAND) {
|
||||
returnValue = currentState->handleBCUnlockCommand(clcw);
|
||||
} else if (returnValue == BC_IS_SET_VR_COMMAND) {
|
||||
returnValue = currentState->handleBCSetVrCommand(clcw, content.vR);
|
||||
} else {
|
||||
//Do nothing
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
uint8_t VirtualChannelReception::getChannelId() const {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::initialize() {
|
||||
ReturnValue_t returnValue = RETURN_FAILED;
|
||||
if ((slidingWindowWidth > 254) || (slidingWindowWidth % 2 != 0)) {
|
||||
sif::error << "VirtualChannelReception::initialize: Illegal sliding window width: "
|
||||
<< (int) slidingWindowWidth << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
for (mapChannelIterator iterator = mapChannels.begin(); iterator != mapChannels.end();
|
||||
iterator++) {
|
||||
returnValue = iterator->second->initialize();
|
||||
if (returnValue != RETURN_OK)
|
||||
break;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void VirtualChannelReception::setToWaitState() {
|
||||
internalClcw.setWaitFlag(true);
|
||||
this->currentState = &waitState;
|
||||
}
|
||||
/**
|
||||
* @file VirtualChannelReception.cpp
|
||||
* @brief This file defines the VirtualChannelReception class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include "../datalinklayer/BCFrame.h"
|
||||
#include "../datalinklayer/VirtualChannelReception.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
VirtualChannelReception::VirtualChannelReception(uint8_t setChannelId,
|
||||
uint8_t setSlidingWindowWidth) :
|
||||
channelId(setChannelId), slidingWindowWidth(setSlidingWindowWidth), positiveWindow(
|
||||
setSlidingWindowWidth / 2), negativeWindow(setSlidingWindowWidth / 2), currentState(
|
||||
&openState), openState(this), waitState(this), lockoutState(this), vR(0), farmBCounter(
|
||||
0) {
|
||||
internalClcw.setVirtualChannel(channelId);
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::mapDemultiplexing(TcTransferFrame* frame) {
|
||||
uint8_t mapId = frame->getMAPId();
|
||||
mapChannelIterator iter = mapChannels.find(mapId);
|
||||
if (iter == mapChannels.end()) {
|
||||
// error << "VirtualChannelReception::mapDemultiplexing on VC " << std::hex << (int) channelId
|
||||
// << ": MapChannel " << (int) mapId << std::dec << " not found." << std::endl;
|
||||
return VC_NOT_FOUND;
|
||||
} else {
|
||||
return (iter->second)->extractPackets(frame);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
uint8_t bypass = frame->bypassFlagSet();
|
||||
uint8_t controlCommand = frame->controlCommandFlagSet();
|
||||
uint8_t typeValue = (bypass << 1) + controlCommand;
|
||||
switch (typeValue) {
|
||||
case AD_FRAME:
|
||||
return currentState->handleADFrame(frame, clcw);
|
||||
case BD_FRAME:
|
||||
return handleBDFrame(frame, clcw);
|
||||
case BC_FRAME:
|
||||
return handleBCFrame(frame, clcw);
|
||||
default:
|
||||
return ILLEGAL_FLAG_COMBINATION;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = doFARM(frame, &internalClcw);
|
||||
internalClcw.setReceiverFrameSequenceNumber(vR);
|
||||
internalClcw.setFarmBCount(farmBCounter);
|
||||
clcw->setWhole(internalClcw.getAsWhole());
|
||||
switch (result) {
|
||||
case RETURN_OK:
|
||||
return mapDemultiplexing(frame);
|
||||
case BC_IS_SET_VR_COMMAND:
|
||||
case BC_IS_UNLOCK_COMMAND:
|
||||
//Need to catch these codes to avoid error reporting later.
|
||||
return RETURN_OK;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExtractionIF* object) {
|
||||
std::pair<mapChannelIterator, bool> returnValue = mapChannels.insert(
|
||||
std::pair<uint8_t, MapPacketExtractionIF*>(mapId, object));
|
||||
if (returnValue.second == true) {
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
farmBCounter++;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
BcFrame content;
|
||||
ReturnValue_t returnValue = content.initialize(frame->getFullDataField(),
|
||||
frame->getFullDataLength());
|
||||
if (returnValue == BC_IS_UNLOCK_COMMAND) {
|
||||
returnValue = currentState->handleBCUnlockCommand(clcw);
|
||||
} else if (returnValue == BC_IS_SET_VR_COMMAND) {
|
||||
returnValue = currentState->handleBCSetVrCommand(clcw, content.vR);
|
||||
} else {
|
||||
//Do nothing
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
uint8_t VirtualChannelReception::getChannelId() const {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::initialize() {
|
||||
ReturnValue_t returnValue = RETURN_FAILED;
|
||||
if ((slidingWindowWidth > 254) || (slidingWindowWidth % 2 != 0)) {
|
||||
sif::error << "VirtualChannelReception::initialize: Illegal sliding window width: "
|
||||
<< (int) slidingWindowWidth << std::endl;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
for (mapChannelIterator iterator = mapChannels.begin(); iterator != mapChannels.end();
|
||||
iterator++) {
|
||||
returnValue = iterator->second->initialize();
|
||||
if (returnValue != RETURN_OK)
|
||||
break;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void VirtualChannelReception::setToWaitState() {
|
||||
internalClcw.setWaitFlag(true);
|
||||
this->currentState = &waitState;
|
||||
}
|
||||
|
@ -1,114 +1,114 @@
|
||||
/**
|
||||
* @file VirtualChannelReception.h
|
||||
* @brief This file defines the VirtualChannelReception class.
|
||||
* @date 25.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef VIRTUALCHANNELRECEPTION_H_
|
||||
#define VIRTUALCHANNELRECEPTION_H_
|
||||
|
||||
#include <framework/datalinklayer/CCSDSReturnValuesIF.h>
|
||||
#include <framework/datalinklayer/Clcw.h>
|
||||
#include <framework/datalinklayer/Farm1StateIF.h>
|
||||
#include <framework/datalinklayer/Farm1StateLockout.h>
|
||||
#include <framework/datalinklayer/Farm1StateOpen.h>
|
||||
#include <framework/datalinklayer/Farm1StateWait.h>
|
||||
#include <framework/datalinklayer/MapPacketExtractionIF.h>
|
||||
#include <framework/datalinklayer/VirtualChannelReceptionIF.h>
|
||||
#include <map>
|
||||
/**
|
||||
* Implementation of a TC Virtual Channel.
|
||||
* This is a full implementation of a virtual channel as specified in the CCSDS TC Space Data Link
|
||||
* Protocol. It is designed to operate within an instance of the @c DataLinkLayer class.
|
||||
* Features:
|
||||
* - any (6bit) Virtual Channel ID is assignable.
|
||||
* - Supports an arbitrary number of MAP Channels (with a map).
|
||||
* - Has a complete FARM-1 Machine built-in.
|
||||
*
|
||||
* The FARM-1 state machine uses the State Pattern.
|
||||
*/
|
||||
class VirtualChannelReception : public VirtualChannelReceptionIF, public CCSDSReturnValuesIF {
|
||||
friend class Farm1StateOpen;
|
||||
friend class Farm1StateWait;
|
||||
friend class Farm1StateLockout;
|
||||
private:
|
||||
uint8_t channelId; //!< Stores the VCID that was assigned on construction.
|
||||
uint8_t slidingWindowWidth; //!< A constant to set the FARM-1 sliding window width.
|
||||
uint8_t positiveWindow; //!< The positive window for the FARM-1 machine.
|
||||
uint8_t negativeWindow; //!< The negative window for the FARM-1 machine.
|
||||
protected:
|
||||
Farm1StateIF* currentState; //!< The current state. To change, one of the other states must be assigned to this pointer.
|
||||
Farm1StateOpen openState; //!< Instance of the FARM-1 State "Open".
|
||||
Farm1StateWait waitState; //!< Instance of the FARM-1 State "Wait".
|
||||
Farm1StateLockout lockoutState; //!< Instance of the FARM-1 State "Lockout".
|
||||
Clcw internalClcw; //!< A CLCW class to internally set the values before writing them back to the TTC System.
|
||||
uint8_t vR; //!< The Receiver Frame Sequence Number V(R) as it shall be maintained for every Virtual Channel.
|
||||
uint8_t farmBCounter; //!< The FARM-B COunter as it shall be maintained for every Virtual Channel.
|
||||
typedef std::map<uint8_t, MapPacketExtractionIF*>::iterator mapChannelIterator; //!< Typedef to simplify handling of the mapChannels map.
|
||||
std::map<uint8_t, MapPacketExtractionIF*> mapChannels; //!< A map that maintains all map Channels. Channels must be configured on initialization. MAy be omitted in a simplified version.
|
||||
/**
|
||||
* This method handles demultiplexing to different map channels.
|
||||
* It parses the entries of #mapChannels and forwards the Frame to a found MAP Channel.
|
||||
* @param frame The frame to forward.
|
||||
* @return #VC_NOT_FOUND or the return value of the map channel extraction.
|
||||
*/
|
||||
ReturnValue_t mapDemultiplexing( TcTransferFrame* frame );
|
||||
/**
|
||||
* A sub-method that actually does the FARM-1 handling for different Frame types.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return The return code of higher methods or @c ILLEGAL_FLAG_COMBINATION.
|
||||
*/
|
||||
ReturnValue_t doFARM(TcTransferFrame* frame, ClcwIF* clcw);
|
||||
/**
|
||||
* Handles incoming BD Frames.
|
||||
* Handling these Frames is independent of the State, so no subcall to #currentState is
|
||||
* required.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return Always returns @c RETURN_OK.
|
||||
*/
|
||||
ReturnValue_t handleBDFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* Handles incoming BC Frames.
|
||||
* The type of the BC Frame is detected and checked first, then methods of #currentState are called.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return The failure code of BC Frame interpretation or the return code of higher methods.
|
||||
*/
|
||||
ReturnValue_t handleBCFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
* Only sets the channelId of the channel. Setting the Sliding Window width is possible as well.
|
||||
* @param setChannelId Virtual Channel Identifier (VCID) of the channel.
|
||||
*/
|
||||
VirtualChannelReception( uint8_t setChannelId, uint8_t setSlidingWindowWidth );
|
||||
ReturnValue_t frameAcceptanceAndReportingMechanism( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* Helper method to simplify adding a mapChannel during construction.
|
||||
* @param mapId The mapId of the object to add.
|
||||
* @param object Pointer to the MapPacketExtraction object itself.
|
||||
* @return @c RETURN_OK if the channel was successfully inserted, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t addMapChannel( uint8_t mapId, MapPacketExtractionIF* object );
|
||||
/**
|
||||
* The initialization routine checks the set #slidingWindowWidth and initializes all MAP
|
||||
* channels.
|
||||
* @return @c RETURN_OK on successful initialization, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t initialize();
|
||||
/**
|
||||
* Getter for the VCID.
|
||||
* @return The #channelId.
|
||||
*/
|
||||
uint8_t getChannelId() const;
|
||||
/**
|
||||
* Small method to set the state to Farm1StateWait.
|
||||
*/
|
||||
void setToWaitState();
|
||||
};
|
||||
|
||||
|
||||
#endif /* VIRTUALCHANNELRECEPTION_H_ */
|
||||
/**
|
||||
* @file VirtualChannelReception.h
|
||||
* @brief This file defines the VirtualChannelReception class.
|
||||
* @date 25.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef VIRTUALCHANNELRECEPTION_H_
|
||||
#define VIRTUALCHANNELRECEPTION_H_
|
||||
|
||||
#include "../datalinklayer/CCSDSReturnValuesIF.h"
|
||||
#include "../datalinklayer/Clcw.h"
|
||||
#include "../datalinklayer/Farm1StateIF.h"
|
||||
#include "../datalinklayer/Farm1StateLockout.h"
|
||||
#include "../datalinklayer/Farm1StateOpen.h"
|
||||
#include "../datalinklayer/Farm1StateWait.h"
|
||||
#include "../datalinklayer/MapPacketExtractionIF.h"
|
||||
#include "../datalinklayer/VirtualChannelReceptionIF.h"
|
||||
#include <map>
|
||||
/**
|
||||
* Implementation of a TC Virtual Channel.
|
||||
* This is a full implementation of a virtual channel as specified in the CCSDS TC Space Data Link
|
||||
* Protocol. It is designed to operate within an instance of the @c DataLinkLayer class.
|
||||
* Features:
|
||||
* - any (6bit) Virtual Channel ID is assignable.
|
||||
* - Supports an arbitrary number of MAP Channels (with a map).
|
||||
* - Has a complete FARM-1 Machine built-in.
|
||||
*
|
||||
* The FARM-1 state machine uses the State Pattern.
|
||||
*/
|
||||
class VirtualChannelReception : public VirtualChannelReceptionIF, public CCSDSReturnValuesIF {
|
||||
friend class Farm1StateOpen;
|
||||
friend class Farm1StateWait;
|
||||
friend class Farm1StateLockout;
|
||||
private:
|
||||
uint8_t channelId; //!< Stores the VCID that was assigned on construction.
|
||||
uint8_t slidingWindowWidth; //!< A constant to set the FARM-1 sliding window width.
|
||||
uint8_t positiveWindow; //!< The positive window for the FARM-1 machine.
|
||||
uint8_t negativeWindow; //!< The negative window for the FARM-1 machine.
|
||||
protected:
|
||||
Farm1StateIF* currentState; //!< The current state. To change, one of the other states must be assigned to this pointer.
|
||||
Farm1StateOpen openState; //!< Instance of the FARM-1 State "Open".
|
||||
Farm1StateWait waitState; //!< Instance of the FARM-1 State "Wait".
|
||||
Farm1StateLockout lockoutState; //!< Instance of the FARM-1 State "Lockout".
|
||||
Clcw internalClcw; //!< A CLCW class to internally set the values before writing them back to the TTC System.
|
||||
uint8_t vR; //!< The Receiver Frame Sequence Number V(R) as it shall be maintained for every Virtual Channel.
|
||||
uint8_t farmBCounter; //!< The FARM-B COunter as it shall be maintained for every Virtual Channel.
|
||||
typedef std::map<uint8_t, MapPacketExtractionIF*>::iterator mapChannelIterator; //!< Typedef to simplify handling of the mapChannels map.
|
||||
std::map<uint8_t, MapPacketExtractionIF*> mapChannels; //!< A map that maintains all map Channels. Channels must be configured on initialization. MAy be omitted in a simplified version.
|
||||
/**
|
||||
* This method handles demultiplexing to different map channels.
|
||||
* It parses the entries of #mapChannels and forwards the Frame to a found MAP Channel.
|
||||
* @param frame The frame to forward.
|
||||
* @return #VC_NOT_FOUND or the return value of the map channel extraction.
|
||||
*/
|
||||
ReturnValue_t mapDemultiplexing( TcTransferFrame* frame );
|
||||
/**
|
||||
* A sub-method that actually does the FARM-1 handling for different Frame types.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return The return code of higher methods or @c ILLEGAL_FLAG_COMBINATION.
|
||||
*/
|
||||
ReturnValue_t doFARM(TcTransferFrame* frame, ClcwIF* clcw);
|
||||
/**
|
||||
* Handles incoming BD Frames.
|
||||
* Handling these Frames is independent of the State, so no subcall to #currentState is
|
||||
* required.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return Always returns @c RETURN_OK.
|
||||
*/
|
||||
ReturnValue_t handleBDFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* Handles incoming BC Frames.
|
||||
* The type of the BC Frame is detected and checked first, then methods of #currentState are called.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return The failure code of BC Frame interpretation or the return code of higher methods.
|
||||
*/
|
||||
ReturnValue_t handleBCFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
* Only sets the channelId of the channel. Setting the Sliding Window width is possible as well.
|
||||
* @param setChannelId Virtual Channel Identifier (VCID) of the channel.
|
||||
*/
|
||||
VirtualChannelReception( uint8_t setChannelId, uint8_t setSlidingWindowWidth );
|
||||
ReturnValue_t frameAcceptanceAndReportingMechanism( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
* Helper method to simplify adding a mapChannel during construction.
|
||||
* @param mapId The mapId of the object to add.
|
||||
* @param object Pointer to the MapPacketExtraction object itself.
|
||||
* @return @c RETURN_OK if the channel was successfully inserted, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t addMapChannel( uint8_t mapId, MapPacketExtractionIF* object );
|
||||
/**
|
||||
* The initialization routine checks the set #slidingWindowWidth and initializes all MAP
|
||||
* channels.
|
||||
* @return @c RETURN_OK on successful initialization, @c RETURN_FAILED otherwise.
|
||||
*/
|
||||
ReturnValue_t initialize();
|
||||
/**
|
||||
* Getter for the VCID.
|
||||
* @return The #channelId.
|
||||
*/
|
||||
uint8_t getChannelId() const;
|
||||
/**
|
||||
* Small method to set the state to Farm1StateWait.
|
||||
*/
|
||||
void setToWaitState();
|
||||
};
|
||||
|
||||
|
||||
#endif /* VIRTUALCHANNELRECEPTION_H_ */
|
||||
|
@ -1,57 +1,57 @@
|
||||
/**
|
||||
* @file VirtualChannelReceptionIF.h
|
||||
* @brief This file defines the VirtualChannelReceptionIF class.
|
||||
* @date 25.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef VIRTUALCHANNELRECEPTIONIF_H_
|
||||
#define VIRTUALCHANNELRECEPTIONIF_H_
|
||||
|
||||
#include <framework/datalinklayer/ClcwIF.h>
|
||||
#include <framework/datalinklayer/TcTransferFrame.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
/**
|
||||
* This is the interface for Virtual Channel reception classes.
|
||||
* It represents a single TC Virtual Channel that operates on one IO
|
||||
*/
|
||||
class VirtualChannelReceptionIF {
|
||||
public:
|
||||
/**
|
||||
* Enum including all valid types of frames.
|
||||
* The type is made up by two flags, so 0b1111 is definitely illegal.
|
||||
*/
|
||||
enum frameType {
|
||||
AD_FRAME = 0b00,
|
||||
BC_FRAME = 0b11,
|
||||
BD_FRAME = 0b10,
|
||||
ILLEGAL_FRAME = 0b1111
|
||||
};
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
virtual ~VirtualChannelReceptionIF() {
|
||||
}
|
||||
/**
|
||||
* This method shall accept frames and do all FARM-1 stuff.
|
||||
* Handling the Frame includes forwarding to higher-level procedures.
|
||||
* @param frame The Tc Transfer Frame that was received and checked.
|
||||
* @param clcw Any changes to the CLCW value are forwarded by using this parameter.
|
||||
* @return The return Value shall indicate successful processing with @c RETURN_OK.
|
||||
*/
|
||||
virtual ReturnValue_t frameAcceptanceAndReportingMechanism( TcTransferFrame* frame, ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
* If any other System Objects are required for operation they shall be initialized here.
|
||||
* @return @c RETURN_OK for successful initialization.
|
||||
*/
|
||||
virtual ReturnValue_t initialize() = 0;
|
||||
/**
|
||||
* Getter for the VCID.
|
||||
* @return The #channelId.
|
||||
*/
|
||||
virtual uint8_t getChannelId() const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* VIRTUALCHANNELRECEPTIONIF_H_ */
|
||||
/**
|
||||
* @file VirtualChannelReceptionIF.h
|
||||
* @brief This file defines the VirtualChannelReceptionIF class.
|
||||
* @date 25.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef VIRTUALCHANNELRECEPTIONIF_H_
|
||||
#define VIRTUALCHANNELRECEPTIONIF_H_
|
||||
|
||||
#include "../datalinklayer/ClcwIF.h"
|
||||
#include "../datalinklayer/TcTransferFrame.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* This is the interface for Virtual Channel reception classes.
|
||||
* It represents a single TC Virtual Channel that operates on one IO
|
||||
*/
|
||||
class VirtualChannelReceptionIF {
|
||||
public:
|
||||
/**
|
||||
* Enum including all valid types of frames.
|
||||
* The type is made up by two flags, so 0b1111 is definitely illegal.
|
||||
*/
|
||||
enum frameType {
|
||||
AD_FRAME = 0b00,
|
||||
BC_FRAME = 0b11,
|
||||
BD_FRAME = 0b10,
|
||||
ILLEGAL_FRAME = 0b1111
|
||||
};
|
||||
/**
|
||||
* Empty virtual destructor.
|
||||
*/
|
||||
virtual ~VirtualChannelReceptionIF() {
|
||||
}
|
||||
/**
|
||||
* This method shall accept frames and do all FARM-1 stuff.
|
||||
* Handling the Frame includes forwarding to higher-level procedures.
|
||||
* @param frame The Tc Transfer Frame that was received and checked.
|
||||
* @param clcw Any changes to the CLCW value are forwarded by using this parameter.
|
||||
* @return The return Value shall indicate successful processing with @c RETURN_OK.
|
||||
*/
|
||||
virtual ReturnValue_t frameAcceptanceAndReportingMechanism( TcTransferFrame* frame, ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
* If any other System Objects are required for operation they shall be initialized here.
|
||||
* @return @c RETURN_OK for successful initialization.
|
||||
*/
|
||||
virtual ReturnValue_t initialize() = 0;
|
||||
/**
|
||||
* Getter for the VCID.
|
||||
* @return The #channelId.
|
||||
*/
|
||||
virtual uint8_t getChannelId() const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif /* VIRTUALCHANNELRECEPTIONIF_H_ */
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include <framework/datapool/ControllerSet.h>
|
||||
|
||||
ControllerSet::ControllerSet() {
|
||||
|
||||
}
|
||||
|
||||
ControllerSet::~ControllerSet() {
|
||||
}
|
||||
|
||||
void ControllerSet::setInvalid() {
|
||||
read();
|
||||
setToDefault();
|
||||
commit(PoolVariableIF::INVALID);
|
||||
}
|
||||
#include "../datapool/ControllerSet.h"
|
||||
|
||||
ControllerSet::ControllerSet() {
|
||||
|
||||
}
|
||||
|
||||
ControllerSet::~ControllerSet() {
|
||||
}
|
||||
|
||||
void ControllerSet::setInvalid() {
|
||||
read();
|
||||
setToDefault();
|
||||
commit(PoolVariableIF::INVALID);
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
#ifndef CONTROLLERSET_H_
|
||||
#define CONTROLLERSET_H_
|
||||
|
||||
#include <framework/datapoolglob/GlobalDataSet.h>
|
||||
|
||||
class ControllerSet :public GlobDataSet {
|
||||
public:
|
||||
ControllerSet();
|
||||
virtual ~ControllerSet();
|
||||
|
||||
virtual void setToDefault() = 0;
|
||||
void setInvalid();
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERSET_H_ */
|
||||
#ifndef CONTROLLERSET_H_
|
||||
#define CONTROLLERSET_H_
|
||||
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
|
||||
class ControllerSet :public GlobDataSet {
|
||||
public:
|
||||
ControllerSet();
|
||||
virtual ~ControllerSet();
|
||||
|
||||
virtual void setToDefault() = 0;
|
||||
void setInvalid();
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERSET_H_ */
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_DATASETIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_DATASETIF_H_
|
||||
#ifndef DATASETIF_H_
|
||||
#define DATASETIF_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../timemanager/Clock.h"
|
||||
class PoolVariableIF;
|
||||
|
||||
/**
|
||||
|
@ -1,75 +1,75 @@
|
||||
#include <framework/datapool/HkSwitchHelper.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
|
||||
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
|
||||
commandActionHelper(this), eventProxy(eventProxy) {
|
||||
actionQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
HkSwitchHelper::~HkSwitchHelper() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::initialize() {
|
||||
ReturnValue_t result = commandActionHelper.initialize();
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
|
||||
CommandMessage command;
|
||||
while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) {
|
||||
ReturnValue_t result = commandActionHelper.handleReply(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
actionQueue->reply(&command);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
|
||||
// ActionId_t action = HKService::DISABLE_HK;
|
||||
// if (enable) {
|
||||
// action = HKService::ENABLE_HK;
|
||||
// }
|
||||
//
|
||||
// ReturnValue_t result = commandActionHelper.commandAction(
|
||||
// objects::PUS_HK_SERVICE, action, sids);
|
||||
//
|
||||
// if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
|
||||
// }
|
||||
// return result;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() {
|
||||
return actionQueue;
|
||||
}
|
||||
#include "../datapool/HkSwitchHelper.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
|
||||
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
|
||||
commandActionHelper(this), eventProxy(eventProxy) {
|
||||
actionQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
HkSwitchHelper::~HkSwitchHelper() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::initialize() {
|
||||
ReturnValue_t result = commandActionHelper.initialize();
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
|
||||
CommandMessage command;
|
||||
while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) {
|
||||
ReturnValue_t result = commandActionHelper.handleReply(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
actionQueue->reply(&command);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
|
||||
// ActionId_t action = HKService::DISABLE_HK;
|
||||
// if (enable) {
|
||||
// action = HKService::ENABLE_HK;
|
||||
// }
|
||||
//
|
||||
// ReturnValue_t result = commandActionHelper.commandAction(
|
||||
// objects::PUS_HK_SERVICE, action, sids);
|
||||
//
|
||||
// if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
|
||||
// }
|
||||
// return result;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() {
|
||||
return actionQueue;
|
||||
}
|
||||
|
@ -1,46 +1,46 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/action/CommandsActionsIF.h>
|
||||
#include <framework/events/EventReportingProxyIF.h>
|
||||
|
||||
//TODO this class violations separation between mission and framework
|
||||
//but it is only a transitional solution until the Datapool is
|
||||
//implemented decentrally
|
||||
|
||||
class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF {
|
||||
public:
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
|
||||
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
|
||||
|
||||
HkSwitchHelper(EventReportingProxyIF *eventProxy);
|
||||
virtual ~HkSwitchHelper();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
ReturnValue_t switchHK(SerializeIF *sids, bool enable);
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_){};
|
||||
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode);
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size);
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId);
|
||||
virtual void completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode);
|
||||
virtual MessageQueueIF* getCommandQueuePtr();
|
||||
|
||||
private:
|
||||
CommandActionHelper commandActionHelper;
|
||||
MessageQueueIF* actionQueue;
|
||||
EventReportingProxyIF *eventProxy;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */
|
||||
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../action/CommandsActionsIF.h"
|
||||
#include "../events/EventReportingProxyIF.h"
|
||||
|
||||
//TODO this class violations separation between mission and framework
|
||||
//but it is only a transitional solution until the Datapool is
|
||||
//implemented decentrally
|
||||
|
||||
class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF {
|
||||
public:
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
|
||||
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
|
||||
|
||||
HkSwitchHelper(EventReportingProxyIF *eventProxy);
|
||||
virtual ~HkSwitchHelper();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
ReturnValue_t switchHK(SerializeIF *sids, bool enable);
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_){};
|
||||
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode);
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size);
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId);
|
||||
virtual void completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode);
|
||||
virtual MessageQueueIF* getCommandQueuePtr();
|
||||
|
||||
private:
|
||||
CommandActionHelper commandActionHelper;
|
||||
MessageQueueIF* actionQueue;
|
||||
EventReportingProxyIF *eventProxy;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <framework/datapool/PoolDataSetBase.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include "PoolDataSetBase.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount):
|
||||
|
@ -1,9 +1,8 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLPOOLDATASETBASE_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLPOOLDATASETBASE_H_
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapool/PoolDataSetIF.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#ifndef FRAMEWORK_DATAPOOL_DATASETBASE_H_
|
||||
#define FRAMEWORK_DATAPOOL_DATASETBASE_H_
|
||||
#include "../datapool/PoolDataSetIF.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
|
||||
/**
|
||||
* @brief The DataSetBase class manages a set of locally checked out variables.
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLDATASETIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLDATASETIF_H_
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include "DataSetIF.h"
|
||||
|
||||
class PoolDataSetIF: public DataSetIF {
|
||||
public:
|
||||
|
@ -1,87 +1,87 @@
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/globalfunctions/arrayprinter.h>
|
||||
#include <cstring>
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, uint8_t setLength,
|
||||
bool setValid ) : length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if(initValue.size() == 0) {
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
else if (initValue.size() != setLength){
|
||||
sif::warning << "PoolEntry: setLength is not equal to initializer list"
|
||||
"length! Performing zero initialization with given setLength"
|
||||
<< std::endl;
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
else {
|
||||
std::copy(initValue.begin(), initValue.end(), this->address);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry( T* initValue, uint8_t setLength, bool setValid ) :
|
||||
length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if (initValue != nullptr) {
|
||||
std::memcpy(this->address, initValue, this->getByteSize() );
|
||||
} else {
|
||||
std::memset(this->address, 0, this->getByteSize() );
|
||||
}
|
||||
}
|
||||
|
||||
//As the data pool is global, this dtor is only be called on program exit.
|
||||
//Warning! Never copy pool entries!
|
||||
template <typename T>
|
||||
PoolEntry<T>::~PoolEntry() {
|
||||
delete[] this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint16_t PoolEntry<T>::getByteSize() {
|
||||
return ( sizeof(T) * this->length );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint8_t PoolEntry<T>::getSize() {
|
||||
return this->length;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void* PoolEntry<T>::getRawData() {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::setValid(bool isValid) {
|
||||
this->valid = isValid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool PoolEntry<T>::getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::print() {
|
||||
sif::debug << "Pool Entry Validity: " <<
|
||||
(this->valid? " (valid) " : " (invalid) ") << std::endl;
|
||||
arrayprinter::print(reinterpret_cast<uint8_t*>(address), length);
|
||||
sif::debug << std::dec << std::endl;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Type PoolEntry<T>::getType() {
|
||||
return PodTypeConversion<T>::type;
|
||||
}
|
||||
|
||||
template class PoolEntry<uint8_t>;
|
||||
template class PoolEntry<uint16_t>;
|
||||
template class PoolEntry<uint32_t>;
|
||||
template class PoolEntry<int8_t>;
|
||||
template class PoolEntry<int16_t>;
|
||||
template class PoolEntry<int32_t>;
|
||||
template class PoolEntry<float>;
|
||||
template class PoolEntry<double>;
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../globalfunctions/arrayprinter.h"
|
||||
#include <cstring>
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, uint8_t setLength,
|
||||
bool setValid ) : length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if(initValue.size() == 0) {
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
else if (initValue.size() != setLength){
|
||||
sif::warning << "PoolEntry: setLength is not equal to initializer list"
|
||||
"length! Performing zero initialization with given setLength"
|
||||
<< std::endl;
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
else {
|
||||
std::copy(initValue.begin(), initValue.end(), this->address);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry( T* initValue, uint8_t setLength, bool setValid ) :
|
||||
length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if (initValue != nullptr) {
|
||||
std::memcpy(this->address, initValue, this->getByteSize() );
|
||||
} else {
|
||||
std::memset(this->address, 0, this->getByteSize() );
|
||||
}
|
||||
}
|
||||
|
||||
//As the data pool is global, this dtor is only be called on program exit.
|
||||
//Warning! Never copy pool entries!
|
||||
template <typename T>
|
||||
PoolEntry<T>::~PoolEntry() {
|
||||
delete[] this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint16_t PoolEntry<T>::getByteSize() {
|
||||
return ( sizeof(T) * this->length );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint8_t PoolEntry<T>::getSize() {
|
||||
return this->length;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void* PoolEntry<T>::getRawData() {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::setValid(bool isValid) {
|
||||
this->valid = isValid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool PoolEntry<T>::getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::print() {
|
||||
sif::debug << "Pool Entry Validity: " <<
|
||||
(this->valid? " (valid) " : " (invalid) ") << std::endl;
|
||||
arrayprinter::print(reinterpret_cast<uint8_t*>(address), length);
|
||||
sif::debug << std::dec << std::endl;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Type PoolEntry<T>::getType() {
|
||||
return PodTypeConversion<T>::type;
|
||||
}
|
||||
|
||||
template class PoolEntry<uint8_t>;
|
||||
template class PoolEntry<uint16_t>;
|
||||
template class PoolEntry<uint32_t>;
|
||||
template class PoolEntry<int8_t>;
|
||||
template class PoolEntry<int16_t>;
|
||||
template class PoolEntry<int32_t>;
|
||||
template class PoolEntry<float>;
|
||||
template class PoolEntry<double>;
|
||||
|
@ -1,130 +1,130 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLENTRY_H_
|
||||
|
||||
#include <framework/datapool/PoolEntryIF.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief This is a small helper class that defines a single data pool entry.
|
||||
* @details
|
||||
* The helper is used to store all information together with the data as a
|
||||
* single data pool entry. The content's type is defined by the template
|
||||
* argument.
|
||||
*
|
||||
* It is prepared for use with plain old data types, but may be
|
||||
* extended to complex types if necessary. It can be initialized with a
|
||||
* certain value, size and validity flag.
|
||||
*
|
||||
* It holds a pointer to the real data and offers methods to access this data
|
||||
* and to acquire additional information (such as validity and array/byte size).
|
||||
* It is NOT intended to be used outside DataPool implementations as it performs
|
||||
* dynamic memory allocation.
|
||||
*
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template <typename T>
|
||||
class PoolEntry : public PoolEntryIF {
|
||||
public:
|
||||
static_assert(not std::is_same<T, bool>::value,
|
||||
"Do not use boolean for the PoolEntry type, use uint8_t "
|
||||
"instead! The ECSS standard defines a boolean as a one bit "
|
||||
"field. Therefore it is preferred to store a boolean as an "
|
||||
"uint8_t");
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential init values are copied to that space.
|
||||
* @details
|
||||
* Not passing any arguments will initialize an non-array pool entry
|
||||
* (setLength = 1) with an initial invalid state.
|
||||
* Please note that if an initializer list is passed, the correct
|
||||
* corresponding length should be passed too, otherwise a zero
|
||||
* initialization will be performed with the given setLength.
|
||||
* @param initValue
|
||||
* Initializer list with values to initialize with, for example {0,0} to
|
||||
* initialize the two entries to zero.
|
||||
* @param setLength
|
||||
* Defines the array length of this entry. Should be equal to the
|
||||
* intializer list length.
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(std::initializer_list<T> initValue = {}, uint8_t setLength = 1,
|
||||
bool setValid = false);
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential init values are copied to that space.
|
||||
* @param initValue
|
||||
* A pointer to the single value or array that holds the init value.
|
||||
* With the default value (nullptr), the entry is initalized with all 0.
|
||||
* @param setLength
|
||||
* Defines the array length of this entry.
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
|
||||
//! Explicitely deleted copy ctor, copying is not allowed!
|
||||
PoolEntry(const PoolEntry&) = delete;
|
||||
//! Explicitely deleted copy assignment, copying is not allowed!
|
||||
PoolEntry& operator=(const PoolEntry&) = delete;
|
||||
|
||||
/**
|
||||
* @brief The allocated memory for the variable is freed
|
||||
* in the destructor.
|
||||
* @details
|
||||
* As the data pool is global, this dtor is only called on program exit.
|
||||
* PoolEntries shall never be copied, as a copy might delete the variable
|
||||
* on the heap.
|
||||
*/
|
||||
~PoolEntry();
|
||||
|
||||
/**
|
||||
* @brief This is the address pointing to the allocated memory.
|
||||
*/
|
||||
T* address;
|
||||
/**
|
||||
* @brief This attribute stores the length information.
|
||||
*/
|
||||
uint8_t length;
|
||||
/**
|
||||
* @brief Here, the validity information for a variable is stored.
|
||||
* Every entry (single variable or vector) has one valid flag.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief getSize returns the array size of the entry.
|
||||
* @details A single parameter has size 1.
|
||||
*/
|
||||
uint8_t getSize();
|
||||
/**
|
||||
* @brief This operation returns the size in bytes.
|
||||
* @details The size is calculated by sizeof(type) * array_size.
|
||||
*/
|
||||
uint16_t getByteSize();
|
||||
/**
|
||||
* @brief This operation returns a the address pointer casted to void*.
|
||||
*/
|
||||
void* getRawData();
|
||||
/**
|
||||
* @brief This method allows to set the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
void setValid( bool isValid );
|
||||
/**
|
||||
* @brief This method allows to get the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
bool getValid();
|
||||
/**
|
||||
* @brief This is a debug method that prints all values and the valid
|
||||
* information to the screen. It prints all array entries in a row.
|
||||
*/
|
||||
void print();
|
||||
|
||||
Type getType();
|
||||
};
|
||||
|
||||
#endif /* POOLENTRY_H_ */
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLENTRY_H_
|
||||
|
||||
#include "../datapool/PoolEntryIF.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @brief This is a small helper class that defines a single data pool entry.
|
||||
* @details
|
||||
* The helper is used to store all information together with the data as a
|
||||
* single data pool entry. The content's type is defined by the template
|
||||
* argument.
|
||||
*
|
||||
* It is prepared for use with plain old data types, but may be
|
||||
* extended to complex types if necessary. It can be initialized with a
|
||||
* certain value, size and validity flag.
|
||||
*
|
||||
* It holds a pointer to the real data and offers methods to access this data
|
||||
* and to acquire additional information (such as validity and array/byte size).
|
||||
* It is NOT intended to be used outside DataPool implementations as it performs
|
||||
* dynamic memory allocation.
|
||||
*
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template <typename T>
|
||||
class PoolEntry : public PoolEntryIF {
|
||||
public:
|
||||
static_assert(not std::is_same<T, bool>::value,
|
||||
"Do not use boolean for the PoolEntry type, use uint8_t "
|
||||
"instead! The ECSS standard defines a boolean as a one bit "
|
||||
"field. Therefore it is preferred to store a boolean as an "
|
||||
"uint8_t");
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential init values are copied to that space.
|
||||
* @details
|
||||
* Not passing any arguments will initialize an non-array pool entry
|
||||
* (setLength = 1) with an initial invalid state.
|
||||
* Please note that if an initializer list is passed, the correct
|
||||
* corresponding length should be passed too, otherwise a zero
|
||||
* initialization will be performed with the given setLength.
|
||||
* @param initValue
|
||||
* Initializer list with values to initialize with, for example {0,0} to
|
||||
* initialize the two entries to zero.
|
||||
* @param setLength
|
||||
* Defines the array length of this entry. Should be equal to the
|
||||
* intializer list length.
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(std::initializer_list<T> initValue = {}, uint8_t setLength = 1,
|
||||
bool setValid = false);
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential init values are copied to that space.
|
||||
* @param initValue
|
||||
* A pointer to the single value or array that holds the init value.
|
||||
* With the default value (nullptr), the entry is initalized with all 0.
|
||||
* @param setLength
|
||||
* Defines the array length of this entry.
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
|
||||
//! Explicitely deleted copy ctor, copying is not allowed!
|
||||
PoolEntry(const PoolEntry&) = delete;
|
||||
//! Explicitely deleted copy assignment, copying is not allowed!
|
||||
PoolEntry& operator=(const PoolEntry&) = delete;
|
||||
|
||||
/**
|
||||
* @brief The allocated memory for the variable is freed
|
||||
* in the destructor.
|
||||
* @details
|
||||
* As the data pool is global, this dtor is only called on program exit.
|
||||
* PoolEntries shall never be copied, as a copy might delete the variable
|
||||
* on the heap.
|
||||
*/
|
||||
~PoolEntry();
|
||||
|
||||
/**
|
||||
* @brief This is the address pointing to the allocated memory.
|
||||
*/
|
||||
T* address;
|
||||
/**
|
||||
* @brief This attribute stores the length information.
|
||||
*/
|
||||
uint8_t length;
|
||||
/**
|
||||
* @brief Here, the validity information for a variable is stored.
|
||||
* Every entry (single variable or vector) has one valid flag.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief getSize returns the array size of the entry.
|
||||
* @details A single parameter has size 1.
|
||||
*/
|
||||
uint8_t getSize();
|
||||
/**
|
||||
* @brief This operation returns the size in bytes.
|
||||
* @details The size is calculated by sizeof(type) * array_size.
|
||||
*/
|
||||
uint16_t getByteSize();
|
||||
/**
|
||||
* @brief This operation returns a the address pointer casted to void*.
|
||||
*/
|
||||
void* getRawData();
|
||||
/**
|
||||
* @brief This method allows to set the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
void setValid( bool isValid );
|
||||
/**
|
||||
* @brief This method allows to get the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
bool getValid();
|
||||
/**
|
||||
* @brief This is a debug method that prints all values and the valid
|
||||
* information to the screen. It prints all array entries in a row.
|
||||
*/
|
||||
void print();
|
||||
|
||||
Type getType();
|
||||
};
|
||||
|
||||
#endif /* POOLENTRY_H_ */
|
||||
|
@ -1,63 +1,63 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
|
||||
|
||||
#include <framework/globalfunctions/Type.h>
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* @brief This interface defines the access possibilities to a
|
||||
* single data pool entry.
|
||||
* @details
|
||||
* The interface provides methods to determine the size and the validity
|
||||
* information of a value. It also defines a method to receive a pointer to the
|
||||
* raw data content. It is mainly used by DataPool itself, but also as a
|
||||
* return pointer.
|
||||
*
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*
|
||||
*/
|
||||
class PoolEntryIF {
|
||||
public:
|
||||
/**
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is required for C++ interfaces.
|
||||
*/
|
||||
virtual ~PoolEntryIF() {
|
||||
}
|
||||
/**
|
||||
* @brief getSize returns the array size of the entry.
|
||||
* A single variable parameter has size 1.
|
||||
*/
|
||||
virtual uint8_t getSize() = 0;
|
||||
/**
|
||||
* @brief This operation returns the size in bytes, which is calculated by
|
||||
* sizeof(type) * array_size.
|
||||
*/
|
||||
virtual uint16_t getByteSize() = 0;
|
||||
/**
|
||||
* @brief This operation returns a the address pointer casted to void*.
|
||||
*/
|
||||
virtual void* getRawData() = 0;
|
||||
/**
|
||||
* @brief This method allows to set the valid information of the pool entry.
|
||||
*/
|
||||
virtual void setValid(bool isValid) = 0;
|
||||
/**
|
||||
* @brief This method allows to set the valid information of the pool entry.
|
||||
*/
|
||||
virtual bool getValid() = 0;
|
||||
/**
|
||||
* @brief This is a debug method that prints all values and the valid
|
||||
* information to the screen. It prints all array entries in a row.
|
||||
* @details
|
||||
* Also displays whether the pool entry is valid or invalid.
|
||||
*/
|
||||
virtual void print() = 0;
|
||||
/**
|
||||
* Returns the type of the entry.
|
||||
*/
|
||||
virtual Type getType() = 0;
|
||||
};
|
||||
|
||||
#endif /* POOLENTRYIF_H_ */
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
|
||||
|
||||
#include "../globalfunctions/Type.h"
|
||||
#include <cstdint>
|
||||
|
||||
/**
|
||||
* @brief This interface defines the access possibilities to a
|
||||
* single data pool entry.
|
||||
* @details
|
||||
* The interface provides methods to determine the size and the validity
|
||||
* information of a value. It also defines a method to receive a pointer to the
|
||||
* raw data content. It is mainly used by DataPool itself, but also as a
|
||||
* return pointer.
|
||||
*
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*
|
||||
*/
|
||||
class PoolEntryIF {
|
||||
public:
|
||||
/**
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is required for C++ interfaces.
|
||||
*/
|
||||
virtual ~PoolEntryIF() {
|
||||
}
|
||||
/**
|
||||
* @brief getSize returns the array size of the entry.
|
||||
* A single variable parameter has size 1.
|
||||
*/
|
||||
virtual uint8_t getSize() = 0;
|
||||
/**
|
||||
* @brief This operation returns the size in bytes, which is calculated by
|
||||
* sizeof(type) * array_size.
|
||||
*/
|
||||
virtual uint16_t getByteSize() = 0;
|
||||
/**
|
||||
* @brief This operation returns a the address pointer casted to void*.
|
||||
*/
|
||||
virtual void* getRawData() = 0;
|
||||
/**
|
||||
* @brief This method allows to set the valid information of the pool entry.
|
||||
*/
|
||||
virtual void setValid(bool isValid) = 0;
|
||||
/**
|
||||
* @brief This method allows to set the valid information of the pool entry.
|
||||
*/
|
||||
virtual bool getValid() = 0;
|
||||
/**
|
||||
* @brief This is a debug method that prints all values and the valid
|
||||
* information to the screen. It prints all array entries in a row.
|
||||
* @details
|
||||
* Also displays whether the pool entry is valid or invalid.
|
||||
*/
|
||||
virtual void print() = 0;
|
||||
/**
|
||||
* Returns the type of the entry.
|
||||
*/
|
||||
virtual Type getType() = 0;
|
||||
};
|
||||
|
||||
#endif /* POOLENTRYIF_H_ */
|
||||
|
@ -5,10 +5,10 @@
|
||||
* @author R. Mueller
|
||||
*/
|
||||
|
||||
#include <framework/datapool/PoolRawAccessHelper.h>
|
||||
#include <framework/datapoolglob/GlobalDataSet.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include "../datapool/PoolRawAccessHelper.h"
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
@ -7,9 +7,9 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/datapoolglob/GlobalDataSet.h>
|
||||
#include <framework/datapoolglob/PoolRawAccess.h>
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "../datapoolglob/PoolRawAccess.h"
|
||||
|
||||
/**
|
||||
* @brief This helper function simplifies accessing data pool entries
|
||||
|
@ -1,28 +1,28 @@
|
||||
#ifndef POOLVARLIST_H_
|
||||
#define POOLVARLIST_H_
|
||||
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/datapoolglob/GlobalPoolVariable.h>
|
||||
template <class T, uint8_t n_var>
|
||||
class PoolVarList {
|
||||
private:
|
||||
GlobPoolVar<T> variables[n_var];
|
||||
public:
|
||||
PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet, PoolVariableIF::ReadWriteMode_t setReadWriteMode ) {
|
||||
//I really should have a look at the new init list c++ syntax.
|
||||
if (dataSet == NULL) {
|
||||
return;
|
||||
}
|
||||
for (uint8_t count = 0; count < n_var; count++) {
|
||||
variables[count].dataPoolId = set_id[count];
|
||||
variables[count].readWriteMode = setReadWriteMode;
|
||||
dataSet->registerVariable(&variables[count]);
|
||||
}
|
||||
}
|
||||
|
||||
GlobPoolVar<T> &operator [](int i) { return variables[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* POOLVARLIST_H_ */
|
||||
#ifndef POOLVARLIST_H_
|
||||
#define POOLVARLIST_H_
|
||||
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapoolglob/GlobalPoolVariable.h"
|
||||
template <class T, uint8_t n_var>
|
||||
class PoolVarList {
|
||||
private:
|
||||
GlobPoolVar<T> variables[n_var];
|
||||
public:
|
||||
PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet, PoolVariableIF::ReadWriteMode_t setReadWriteMode ) {
|
||||
//I really should have a look at the new init list c++ syntax.
|
||||
if (dataSet == NULL) {
|
||||
return;
|
||||
}
|
||||
for (uint8_t count = 0; count < n_var; count++) {
|
||||
variables[count].dataPoolId = set_id[count];
|
||||
variables[count].readWriteMode = setReadWriteMode;
|
||||
dataSet->registerVariable(&variables[count]);
|
||||
}
|
||||
}
|
||||
|
||||
GlobPoolVar<T> &operator [](int i) { return variables[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* POOLVARLIST_H_ */
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_
|
||||
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
|
||||
/**
|
||||
* @brief This interface is used to control data pool
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapool/PoolDataSetIF.h>
|
||||
#include "PoolDataSetIF.h"
|
||||
|
||||
class SharedDataSetIF: public PoolDataSetIF {
|
||||
public:
|
||||
|
@ -1,300 +1,300 @@
|
||||
#include <framework/datapoolglob/DataPoolAdmin.h>
|
||||
#include <framework/datapoolglob/GlobalDataSet.h>
|
||||
#include <framework/datapoolglob/GlobalDataPool.h>
|
||||
#include <framework/datapoolglob/PoolRawAccess.h>
|
||||
#include <framework/ipc/CommandMessage.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/parameters/ParameterMessage.h>
|
||||
|
||||
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
|
||||
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
|
||||
this, NULL), actionHelper(this, NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
DataPoolAdmin::~DataPoolAdmin() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) {
|
||||
handleCommand();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
|
||||
if (actionId != SET_VALIDITY) {
|
||||
return INVALID_ACTION_ID;
|
||||
}
|
||||
|
||||
if (size != 5) {
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8)
|
||||
| data[3];
|
||||
|
||||
uint8_t valid = data[4];
|
||||
|
||||
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
|
||||
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE);
|
||||
ReturnValue_t status = mySet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
if (valid != 0) {
|
||||
variable.setValid(PoolVariableIF::VALID);
|
||||
} else {
|
||||
variable.setValid(PoolVariableIF::INVALID);
|
||||
}
|
||||
|
||||
mySet.commit();
|
||||
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
void DataPoolAdmin::handleCommand() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = actionHelper.handleActionMessage(&command);
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = handleParameterCommand(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = memoryHelper.handleMemoryCommand(&command);
|
||||
if (result != RETURN_OK) {
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
|
||||
const uint8_t* data, size_t size, uint8_t** dataPointer) {
|
||||
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
|
||||
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
|
||||
GlobDataSet testSet;
|
||||
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = testSet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
uint8_t typeSize = varToGetSize.getSizeOfType();
|
||||
|
||||
if (size % typeSize != 0) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (size > varToGetSize.getSizeTillEnd()) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
const uint8_t* readPosition = data;
|
||||
|
||||
for (; size > 0; size -= typeSize) {
|
||||
GlobDataSet rawSet;
|
||||
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
status = rawSet.read();
|
||||
if (status == RETURN_OK) {
|
||||
status = variable.setEntryFromBigEndian(readPosition, typeSize);
|
||||
if (status == RETURN_OK) {
|
||||
status = rawSet.commit();
|
||||
}
|
||||
}
|
||||
arrayIndex += 1;
|
||||
readPosition += typeSize;
|
||||
}
|
||||
return ACTIVITY_COMPLETED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size,
|
||||
uint8_t** dataPointer, uint8_t* copyHere) {
|
||||
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
|
||||
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
|
||||
GlobDataSet testSet;
|
||||
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = testSet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
uint8_t typeSize = varToGetSize.getSizeOfType();
|
||||
if (size > varToGetSize.getSizeTillEnd()) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
uint8_t* ptrToCopy = copyHere;
|
||||
for (; size > 0; size -= typeSize) {
|
||||
GlobDataSet rawSet;
|
||||
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
status = rawSet.read();
|
||||
if (status == RETURN_OK) {
|
||||
size_t temp = 0;
|
||||
status = variable.getEntryEndianSafe(ptrToCopy, &temp, size);
|
||||
if (status != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
} else {
|
||||
//Error reading parameter.
|
||||
}
|
||||
arrayIndex += 1;
|
||||
ptrToCopy += typeSize;
|
||||
}
|
||||
return ACTIVITY_COMPLETED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = memoryHelper.initialize(commandQueue);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (storage == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//mostly identical to ParameterHelper::handleParameterMessage()
|
||||
ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
switch (command->getCommand()) {
|
||||
case ParameterMessage::CMD_PARAMETER_DUMP: {
|
||||
uint8_t domain = HasParametersIF::getDomain(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint16_t parameterId = HasParametersIF::getMatrixId(
|
||||
ParameterMessage::getParameterId(command));
|
||||
|
||||
DataPoolParameterWrapper wrapper;
|
||||
result = wrapper.set(domain, parameterId);
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
result = sendParameter(command->getSender(),
|
||||
ParameterMessage::getParameterId(command), &wrapper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParameterMessage::CMD_PARAMETER_LOAD: {
|
||||
|
||||
uint8_t domain = HasParametersIF::getDomain(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint16_t parameterId = HasParametersIF::getMatrixId(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint8_t index = HasParametersIF::getIndex(
|
||||
ParameterMessage::getParameterId(command));
|
||||
|
||||
const uint8_t *storedStream;
|
||||
size_t storedStreamSize;
|
||||
result = storage->getData(ParameterMessage::getStoreId(command),
|
||||
&storedStream, &storedStreamSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
ParameterWrapper streamWrapper;
|
||||
result = streamWrapper.set(storedStream, storedStreamSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
break;
|
||||
}
|
||||
|
||||
DataPoolParameterWrapper poolWrapper;
|
||||
result = poolWrapper.set(domain, parameterId);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
break;
|
||||
}
|
||||
|
||||
result = poolWrapper.copyFrom(&streamWrapper, index);
|
||||
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
result = sendParameter(command->getSender(),
|
||||
ParameterMessage::getParameterId(command), &poolWrapper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
rejectCommand(command->getSender(), result, command->getCommand());
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
//identical to ParameterHelper::sendParameter()
|
||||
ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const DataPoolParameterWrapper* wrapper) {
|
||||
size_t serializedSize = wrapper->getSerializedSize();
|
||||
|
||||
uint8_t *storeElement;
|
||||
store_address_t address;
|
||||
|
||||
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
||||
&storeElement);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t storeElementSize = 0;
|
||||
|
||||
result = wrapper->serialize(&storeElement, &storeElementSize,
|
||||
serializedSize, SerializeIF::Endianness::BIG);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
CommandMessage reply;
|
||||
|
||||
ParameterMessage::setParameterDumpReply(&reply, id, address);
|
||||
|
||||
commandQueue->sendMessage(to, &reply);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
//identical to ParameterHelper::rejectCommand()
|
||||
void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
|
||||
Command_t initialCommand) {
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(reason, initialCommand);
|
||||
commandQueue->sendMessage(to, &reply);
|
||||
}
|
||||
#include "../datapoolglob/DataPoolAdmin.h"
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "../datapoolglob/GlobalDataPool.h"
|
||||
#include "../datapoolglob/PoolRawAccess.h"
|
||||
#include "../ipc/CommandMessage.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../parameters/ParameterMessage.h"
|
||||
|
||||
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
|
||||
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
|
||||
this, NULL), actionHelper(this, NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
DataPoolAdmin::~DataPoolAdmin() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) {
|
||||
handleCommand();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
|
||||
if (actionId != SET_VALIDITY) {
|
||||
return INVALID_ACTION_ID;
|
||||
}
|
||||
|
||||
if (size != 5) {
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8)
|
||||
| data[3];
|
||||
|
||||
uint8_t valid = data[4];
|
||||
|
||||
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
|
||||
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE);
|
||||
ReturnValue_t status = mySet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
if (valid != 0) {
|
||||
variable.setValid(PoolVariableIF::VALID);
|
||||
} else {
|
||||
variable.setValid(PoolVariableIF::INVALID);
|
||||
}
|
||||
|
||||
mySet.commit();
|
||||
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
void DataPoolAdmin::handleCommand() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = actionHelper.handleActionMessage(&command);
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = handleParameterCommand(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = memoryHelper.handleMemoryCommand(&command);
|
||||
if (result != RETURN_OK) {
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
|
||||
const uint8_t* data, size_t size, uint8_t** dataPointer) {
|
||||
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
|
||||
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
|
||||
GlobDataSet testSet;
|
||||
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = testSet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
uint8_t typeSize = varToGetSize.getSizeOfType();
|
||||
|
||||
if (size % typeSize != 0) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (size > varToGetSize.getSizeTillEnd()) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
const uint8_t* readPosition = data;
|
||||
|
||||
for (; size > 0; size -= typeSize) {
|
||||
GlobDataSet rawSet;
|
||||
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
status = rawSet.read();
|
||||
if (status == RETURN_OK) {
|
||||
status = variable.setEntryFromBigEndian(readPosition, typeSize);
|
||||
if (status == RETURN_OK) {
|
||||
status = rawSet.commit();
|
||||
}
|
||||
}
|
||||
arrayIndex += 1;
|
||||
readPosition += typeSize;
|
||||
}
|
||||
return ACTIVITY_COMPLETED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size,
|
||||
uint8_t** dataPointer, uint8_t* copyHere) {
|
||||
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
|
||||
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
|
||||
GlobDataSet testSet;
|
||||
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = testSet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
uint8_t typeSize = varToGetSize.getSizeOfType();
|
||||
if (size > varToGetSize.getSizeTillEnd()) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
uint8_t* ptrToCopy = copyHere;
|
||||
for (; size > 0; size -= typeSize) {
|
||||
GlobDataSet rawSet;
|
||||
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
status = rawSet.read();
|
||||
if (status == RETURN_OK) {
|
||||
size_t temp = 0;
|
||||
status = variable.getEntryEndianSafe(ptrToCopy, &temp, size);
|
||||
if (status != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
} else {
|
||||
//Error reading parameter.
|
||||
}
|
||||
arrayIndex += 1;
|
||||
ptrToCopy += typeSize;
|
||||
}
|
||||
return ACTIVITY_COMPLETED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = memoryHelper.initialize(commandQueue);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (storage == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//mostly identical to ParameterHelper::handleParameterMessage()
|
||||
ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
switch (command->getCommand()) {
|
||||
case ParameterMessage::CMD_PARAMETER_DUMP: {
|
||||
uint8_t domain = HasParametersIF::getDomain(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint16_t parameterId = HasParametersIF::getMatrixId(
|
||||
ParameterMessage::getParameterId(command));
|
||||
|
||||
DataPoolParameterWrapper wrapper;
|
||||
result = wrapper.set(domain, parameterId);
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
result = sendParameter(command->getSender(),
|
||||
ParameterMessage::getParameterId(command), &wrapper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParameterMessage::CMD_PARAMETER_LOAD: {
|
||||
|
||||
uint8_t domain = HasParametersIF::getDomain(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint16_t parameterId = HasParametersIF::getMatrixId(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint8_t index = HasParametersIF::getIndex(
|
||||
ParameterMessage::getParameterId(command));
|
||||
|
||||
const uint8_t *storedStream;
|
||||
size_t storedStreamSize;
|
||||
result = storage->getData(ParameterMessage::getStoreId(command),
|
||||
&storedStream, &storedStreamSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
ParameterWrapper streamWrapper;
|
||||
result = streamWrapper.set(storedStream, storedStreamSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
break;
|
||||
}
|
||||
|
||||
DataPoolParameterWrapper poolWrapper;
|
||||
result = poolWrapper.set(domain, parameterId);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
break;
|
||||
}
|
||||
|
||||
result = poolWrapper.copyFrom(&streamWrapper, index);
|
||||
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
result = sendParameter(command->getSender(),
|
||||
ParameterMessage::getParameterId(command), &poolWrapper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
rejectCommand(command->getSender(), result, command->getCommand());
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
//identical to ParameterHelper::sendParameter()
|
||||
ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const DataPoolParameterWrapper* wrapper) {
|
||||
size_t serializedSize = wrapper->getSerializedSize();
|
||||
|
||||
uint8_t *storeElement;
|
||||
store_address_t address;
|
||||
|
||||
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
||||
&storeElement);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t storeElementSize = 0;
|
||||
|
||||
result = wrapper->serialize(&storeElement, &storeElementSize,
|
||||
serializedSize, SerializeIF::Endianness::BIG);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
CommandMessage reply;
|
||||
|
||||
ParameterMessage::setParameterDumpReply(&reply, id, address);
|
||||
|
||||
commandQueue->sendMessage(to, &reply);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
//identical to ParameterHelper::rejectCommand()
|
||||
void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
|
||||
Command_t initialCommand) {
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(reason, initialCommand);
|
||||
commandQueue->sendMessage(to, &reply);
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
#ifndef DATAPOOLADMIN_H_
|
||||
#define DATAPOOLADMIN_H_
|
||||
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
#include <framework/parameters/ReceivesParameterMessagesIF.h>
|
||||
|
||||
#include <framework/memory/MemoryHelper.h>
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
#include <framework/datapoolglob/DataPoolParameterWrapper.h>
|
||||
|
||||
class DataPoolAdmin: public HasActionsIF,
|
||||
public ExecutableObjectIF,
|
||||
public AcceptsMemoryMessagesIF,
|
||||
public HasReturnvaluesIF,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public SystemObject {
|
||||
public:
|
||||
static const ActionId_t SET_VALIDITY = 1;
|
||||
|
||||
DataPoolAdmin(object_id_t objectId);
|
||||
|
||||
~DataPoolAdmin();
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data,
|
||||
size_t size, uint8_t** dataPointer);
|
||||
ReturnValue_t handleMemoryDump(uint32_t address, size_t size,
|
||||
uint8_t** dataPointer, uint8_t* copyHere);
|
||||
|
||||
ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size);
|
||||
|
||||
//not implemented as ParameterHelper is no used
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
ReturnValue_t initialize();
|
||||
private:
|
||||
StorageManagerIF *storage;
|
||||
MessageQueueIF* commandQueue;
|
||||
MemoryHelper memoryHelper;
|
||||
SimpleActionHelper actionHelper;
|
||||
void handleCommand();
|
||||
ReturnValue_t handleParameterCommand(CommandMessage *command);
|
||||
ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const DataPoolParameterWrapper* wrapper);
|
||||
void rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
|
||||
Command_t initialCommand);
|
||||
};
|
||||
|
||||
#endif /* DATAPOOLADMIN_H_ */
|
||||
#ifndef DATAPOOLADMIN_H_
|
||||
#define DATAPOOLADMIN_H_
|
||||
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../action/HasActionsIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../parameters/ReceivesParameterMessagesIF.h"
|
||||
|
||||
#include "../memory/MemoryHelper.h"
|
||||
#include "../action/SimpleActionHelper.h"
|
||||
#include "../datapoolglob/DataPoolParameterWrapper.h"
|
||||
|
||||
class DataPoolAdmin: public HasActionsIF,
|
||||
public ExecutableObjectIF,
|
||||
public AcceptsMemoryMessagesIF,
|
||||
public HasReturnvaluesIF,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public SystemObject {
|
||||
public:
|
||||
static const ActionId_t SET_VALIDITY = 1;
|
||||
|
||||
DataPoolAdmin(object_id_t objectId);
|
||||
|
||||
~DataPoolAdmin();
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data,
|
||||
size_t size, uint8_t** dataPointer);
|
||||
ReturnValue_t handleMemoryDump(uint32_t address, size_t size,
|
||||
uint8_t** dataPointer, uint8_t* copyHere);
|
||||
|
||||
ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size);
|
||||
|
||||
//not implemented as ParameterHelper is no used
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
ReturnValue_t initialize();
|
||||
private:
|
||||
StorageManagerIF *storage;
|
||||
MessageQueueIF* commandQueue;
|
||||
MemoryHelper memoryHelper;
|
||||
SimpleActionHelper actionHelper;
|
||||
void handleCommand();
|
||||
ReturnValue_t handleParameterCommand(CommandMessage *command);
|
||||
ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const DataPoolParameterWrapper* wrapper);
|
||||
void rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
|
||||
Command_t initialCommand);
|
||||
};
|
||||
|
||||
#endif /* DATAPOOLADMIN_H_ */
|
||||
|
@ -1,179 +1,179 @@
|
||||
#include <framework/datapoolglob/GlobalDataSet.h>
|
||||
#include <framework/datapoolglob/DataPoolParameterWrapper.h>
|
||||
#include <framework/datapoolglob/PoolRawAccess.h>
|
||||
#include <framework/parameters/HasParametersIF.h>
|
||||
|
||||
|
||||
DataPoolParameterWrapper::DataPoolParameterWrapper() :
|
||||
type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId(
|
||||
PoolVariableIF::NO_PARAMETER) {
|
||||
|
||||
}
|
||||
|
||||
DataPoolParameterWrapper::~DataPoolParameterWrapper() {
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
|
||||
uint16_t parameterId) {
|
||||
poolId = (domainId << 16) + parameterId;
|
||||
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = mySet.read();
|
||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||
//should only fail for invalid pool id
|
||||
return HasParametersIF::INVALID_MATRIX_ID;
|
||||
}
|
||||
|
||||
type = raw.getType();
|
||||
rows = raw.getArraySize();
|
||||
columns = 1;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize, Endianness streamEndianness) const {
|
||||
ReturnValue_t result;
|
||||
|
||||
result = SerializeAdapter::serialize(&type, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::serialize(&columns, buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&rows, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < rows; index++){
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ);
|
||||
mySet.read();
|
||||
result = raw.serialize(buffer,size,maxSize,streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
//same as ParameterWrapper
|
||||
size_t DataPoolParameterWrapper::getSerializedSize() const {
|
||||
size_t serializedSize = 0;
|
||||
serializedSize += type.getSerializedSize();
|
||||
serializedSize += sizeof(rows);
|
||||
serializedSize += sizeof(columns);
|
||||
serializedSize += rows * columns * type.getSize();
|
||||
|
||||
return serializedSize;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
|
||||
size_t* size, Endianness streamEndianness) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow,
|
||||
uint8_t startingColumn, const void* from, uint8_t fromRows) {
|
||||
//treat from as a continuous Stream as we copy all of it
|
||||
const uint8_t *fromAsStream = (const uint8_t *) from;
|
||||
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
|
||||
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess raw(poolId, startingRow + fromRow, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
mySet.read();
|
||||
|
||||
result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T));
|
||||
|
||||
fromAsStream += sizeof(T);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mySet.commit();
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from,
|
||||
uint16_t startWritingAtIndex) {
|
||||
if (poolId == PoolVariableIF::NO_PARAMETER) {
|
||||
return ParameterWrapper::NOT_SET;
|
||||
}
|
||||
|
||||
if (type != from->type) {
|
||||
return ParameterWrapper::DATATYPE_MISSMATCH;
|
||||
}
|
||||
|
||||
//check if from fits into this
|
||||
uint8_t startingRow = startWritingAtIndex / columns;
|
||||
uint8_t startingColumn = startWritingAtIndex % columns;
|
||||
|
||||
if ((from->rows > (rows - startingRow))
|
||||
|| (from->columns > (columns - startingColumn))) {
|
||||
return ParameterWrapper::TOO_BIG;
|
||||
}
|
||||
|
||||
ReturnValue_t result;
|
||||
//copy data
|
||||
if (from->pointsToStream) {
|
||||
switch (type) {
|
||||
case Type::UINT8_T:
|
||||
result = deSerializeData<uint8_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT8_T:
|
||||
result = deSerializeData<int8_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::UINT16_T:
|
||||
result = deSerializeData<uint16_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT16_T:
|
||||
result = deSerializeData<int16_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::UINT32_T:
|
||||
result = deSerializeData<uint32_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT32_T:
|
||||
result = deSerializeData<int32_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::FLOAT:
|
||||
result = deSerializeData<float>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::DOUBLE:
|
||||
result = deSerializeData<double>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
default:
|
||||
result = ParameterWrapper::UNKNOW_DATATYPE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//not supported
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "../datapoolglob/DataPoolParameterWrapper.h"
|
||||
#include "../datapoolglob/PoolRawAccess.h"
|
||||
#include "../parameters/HasParametersIF.h"
|
||||
|
||||
|
||||
DataPoolParameterWrapper::DataPoolParameterWrapper() :
|
||||
type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId(
|
||||
PoolVariableIF::NO_PARAMETER) {
|
||||
|
||||
}
|
||||
|
||||
DataPoolParameterWrapper::~DataPoolParameterWrapper() {
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
|
||||
uint16_t parameterId) {
|
||||
poolId = (domainId << 16) + parameterId;
|
||||
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = mySet.read();
|
||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||
//should only fail for invalid pool id
|
||||
return HasParametersIF::INVALID_MATRIX_ID;
|
||||
}
|
||||
|
||||
type = raw.getType();
|
||||
rows = raw.getArraySize();
|
||||
columns = 1;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
|
||||
size_t* size, size_t maxSize, Endianness streamEndianness) const {
|
||||
ReturnValue_t result;
|
||||
|
||||
result = SerializeAdapter::serialize(&type, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter::serialize(&columns, buffer, size,
|
||||
maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter::serialize(&rows, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < rows; index++){
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ);
|
||||
mySet.read();
|
||||
result = raw.serialize(buffer,size,maxSize,streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
//same as ParameterWrapper
|
||||
size_t DataPoolParameterWrapper::getSerializedSize() const {
|
||||
size_t serializedSize = 0;
|
||||
serializedSize += type.getSerializedSize();
|
||||
serializedSize += sizeof(rows);
|
||||
serializedSize += sizeof(columns);
|
||||
serializedSize += rows * columns * type.getSize();
|
||||
|
||||
return serializedSize;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
|
||||
size_t* size, Endianness streamEndianness) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow,
|
||||
uint8_t startingColumn, const void* from, uint8_t fromRows) {
|
||||
//treat from as a continuous Stream as we copy all of it
|
||||
const uint8_t *fromAsStream = (const uint8_t *) from;
|
||||
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
|
||||
|
||||
GlobDataSet mySet;
|
||||
PoolRawAccess raw(poolId, startingRow + fromRow, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
mySet.read();
|
||||
|
||||
result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T));
|
||||
|
||||
fromAsStream += sizeof(T);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mySet.commit();
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from,
|
||||
uint16_t startWritingAtIndex) {
|
||||
if (poolId == PoolVariableIF::NO_PARAMETER) {
|
||||
return ParameterWrapper::NOT_SET;
|
||||
}
|
||||
|
||||
if (type != from->type) {
|
||||
return ParameterWrapper::DATATYPE_MISSMATCH;
|
||||
}
|
||||
|
||||
//check if from fits into this
|
||||
uint8_t startingRow = startWritingAtIndex / columns;
|
||||
uint8_t startingColumn = startWritingAtIndex % columns;
|
||||
|
||||
if ((from->rows > (rows - startingRow))
|
||||
|| (from->columns > (columns - startingColumn))) {
|
||||
return ParameterWrapper::TOO_BIG;
|
||||
}
|
||||
|
||||
ReturnValue_t result;
|
||||
//copy data
|
||||
if (from->pointsToStream) {
|
||||
switch (type) {
|
||||
case Type::UINT8_T:
|
||||
result = deSerializeData<uint8_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT8_T:
|
||||
result = deSerializeData<int8_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::UINT16_T:
|
||||
result = deSerializeData<uint16_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT16_T:
|
||||
result = deSerializeData<int16_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::UINT32_T:
|
||||
result = deSerializeData<uint32_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT32_T:
|
||||
result = deSerializeData<int32_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::FLOAT:
|
||||
result = deSerializeData<float>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::DOUBLE:
|
||||
result = deSerializeData<double>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
default:
|
||||
result = ParameterWrapper::UNKNOW_DATATYPE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//not supported
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1,38 +1,38 @@
|
||||
#ifndef DATAPOOLPARAMETERWRAPPER_H_
|
||||
#define DATAPOOLPARAMETERWRAPPER_H_
|
||||
|
||||
#include <framework/globalfunctions/Type.h>
|
||||
#include <framework/parameters/ParameterWrapper.h>
|
||||
|
||||
class DataPoolParameterWrapper: public SerializeIF {
|
||||
public:
|
||||
DataPoolParameterWrapper();
|
||||
virtual ~DataPoolParameterWrapper();
|
||||
|
||||
ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const override;
|
||||
|
||||
virtual size_t getSerializedSize() const override;
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
ReturnValue_t copyFrom(const ParameterWrapper *from,
|
||||
uint16_t startWritingAtIndex);
|
||||
|
||||
private:
|
||||
Type type;
|
||||
uint8_t rows;
|
||||
uint8_t columns;
|
||||
|
||||
uint32_t poolId;
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
|
||||
const void *from, uint8_t fromRows);
|
||||
|
||||
};
|
||||
|
||||
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */
|
||||
#ifndef DATAPOOLPARAMETERWRAPPER_H_
|
||||
#define DATAPOOLPARAMETERWRAPPER_H_
|
||||
|
||||
#include "../globalfunctions/Type.h"
|
||||
#include "../parameters/ParameterWrapper.h"
|
||||
|
||||
class DataPoolParameterWrapper: public SerializeIF {
|
||||
public:
|
||||
DataPoolParameterWrapper();
|
||||
virtual ~DataPoolParameterWrapper();
|
||||
|
||||
ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const override;
|
||||
|
||||
virtual size_t getSerializedSize() const override;
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
ReturnValue_t copyFrom(const ParameterWrapper *from,
|
||||
uint16_t startWritingAtIndex);
|
||||
|
||||
private:
|
||||
Type type;
|
||||
uint8_t rows;
|
||||
uint8_t columns;
|
||||
|
||||
uint32_t poolId;
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
|
||||
const void *from, uint8_t fromRows);
|
||||
|
||||
};
|
||||
|
||||
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */
|
||||
|
@ -1,133 +1,133 @@
|
||||
#include <framework/datapoolglob/GlobalDataPool.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
|
||||
GlobalDataPool::GlobalDataPool(
|
||||
void(*initFunction)(GlobPoolMap* pool_map)) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
if (initFunction != NULL ) {
|
||||
initFunction( &this->globDataPool );
|
||||
}
|
||||
}
|
||||
|
||||
GlobalDataPool::~GlobalDataPool() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
for(GlobPoolMapIter it = this->globDataPool.begin();
|
||||
it != this->globDataPool.end(); ++it )
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// The function checks PID, type and array length before returning a copy of
|
||||
// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr.
|
||||
template <typename T> PoolEntry<T>* GlobalDataPool::getData( uint32_t data_pool_id,
|
||||
uint8_t sizeOrPosition ) {
|
||||
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
|
||||
if ( it != this->globDataPool.end() ) {
|
||||
PoolEntry<T>* entry = dynamic_cast< PoolEntry<T>* >( it->second );
|
||||
if (entry != nullptr ) {
|
||||
if ( sizeOrPosition <= entry->length ) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) {
|
||||
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
|
||||
if ( it != this->globDataPool.end() ) {
|
||||
return it->second;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t GlobalDataPool::unlockDataPool() {
|
||||
ReturnValue_t status = mutex->unlockMutex();
|
||||
if(status != RETURN_OK) {
|
||||
sif::error << "DataPool::DataPool: unlock of mutex failed with"
|
||||
" error code: " << status << std::endl;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) {
|
||||
ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
|
||||
timeoutMs);
|
||||
if(status != RETURN_OK) {
|
||||
sif::error << "DataPool::DataPool: lock of mutex failed "
|
||||
"with error code: " << status << std::endl;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void GlobalDataPool::print() {
|
||||
sif::debug << "DataPool contains: " << std::endl;
|
||||
std::map<uint32_t, PoolEntryIF*>::iterator dataPoolIt;
|
||||
dataPoolIt = this->globDataPool.begin();
|
||||
while( dataPoolIt != this->globDataPool.end() ) {
|
||||
sif::debug << std::hex << dataPoolIt->first << std::dec << " |";
|
||||
dataPoolIt->second->print();
|
||||
dataPoolIt++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) {
|
||||
return (parameter_id >> 8) & 0x00FFFFFF;
|
||||
}
|
||||
|
||||
uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) {
|
||||
return (parameter_id & 0x000000FF);
|
||||
}
|
||||
|
||||
uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) {
|
||||
return (poolId << 8) + index;
|
||||
}
|
||||
|
||||
|
||||
//SHOULDDO: Do we need a mutex lock here... I don't think so,
|
||||
//as we only check static const values of elements in a list that do not change.
|
||||
//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM
|
||||
ReturnValue_t GlobalDataPool::getType(uint32_t parameter_id, Type* type) {
|
||||
GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id));
|
||||
if ( it != this->globDataPool.end() ) {
|
||||
*type = it->second->getType();
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
*type = Type::UNKNOWN_TYPE;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalDataPool::exists(uint32_t parameterId) {
|
||||
uint32_t poolId = PIDToDataPoolId(parameterId);
|
||||
uint32_t index = PIDToArrayIndex(parameterId);
|
||||
GlobPoolMapIter it = this->globDataPool.find( poolId );
|
||||
if (it != globDataPool.end()) {
|
||||
if (it->second->getSize() >= index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template PoolEntry<uint8_t>* GlobalDataPool::getData<uint8_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<uint16_t>* GlobalDataPool::getData<uint16_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<uint32_t>* GlobalDataPool::getData<uint32_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<uint64_t>* GlobalDataPool::getData<uint64_t>(
|
||||
uint32_t data_pool_id, uint8_t size);
|
||||
template PoolEntry<int8_t>* GlobalDataPool::getData<int8_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<int16_t>* GlobalDataPool::getData<int16_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<int32_t>* GlobalDataPool::getData<int32_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<float>* GlobalDataPool::getData<float>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<double>* GlobalDataPool::getData<double>(
|
||||
uint32_t data_pool_id, uint8_t size);
|
||||
#include "../datapoolglob/GlobalDataPool.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
|
||||
GlobalDataPool::GlobalDataPool(
|
||||
void(*initFunction)(GlobPoolMap* pool_map)) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
if (initFunction != NULL ) {
|
||||
initFunction( &this->globDataPool );
|
||||
}
|
||||
}
|
||||
|
||||
GlobalDataPool::~GlobalDataPool() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
for(GlobPoolMapIter it = this->globDataPool.begin();
|
||||
it != this->globDataPool.end(); ++it )
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// The function checks PID, type and array length before returning a copy of
|
||||
// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr.
|
||||
template <typename T> PoolEntry<T>* GlobalDataPool::getData( uint32_t data_pool_id,
|
||||
uint8_t sizeOrPosition ) {
|
||||
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
|
||||
if ( it != this->globDataPool.end() ) {
|
||||
PoolEntry<T>* entry = dynamic_cast< PoolEntry<T>* >( it->second );
|
||||
if (entry != nullptr ) {
|
||||
if ( sizeOrPosition <= entry->length ) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) {
|
||||
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
|
||||
if ( it != this->globDataPool.end() ) {
|
||||
return it->second;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t GlobalDataPool::unlockDataPool() {
|
||||
ReturnValue_t status = mutex->unlockMutex();
|
||||
if(status != RETURN_OK) {
|
||||
sif::error << "DataPool::DataPool: unlock of mutex failed with"
|
||||
" error code: " << status << std::endl;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) {
|
||||
ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
|
||||
timeoutMs);
|
||||
if(status != RETURN_OK) {
|
||||
sif::error << "DataPool::DataPool: lock of mutex failed "
|
||||
"with error code: " << status << std::endl;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void GlobalDataPool::print() {
|
||||
sif::debug << "DataPool contains: " << std::endl;
|
||||
std::map<uint32_t, PoolEntryIF*>::iterator dataPoolIt;
|
||||
dataPoolIt = this->globDataPool.begin();
|
||||
while( dataPoolIt != this->globDataPool.end() ) {
|
||||
sif::debug << std::hex << dataPoolIt->first << std::dec << " |";
|
||||
dataPoolIt->second->print();
|
||||
dataPoolIt++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) {
|
||||
return (parameter_id >> 8) & 0x00FFFFFF;
|
||||
}
|
||||
|
||||
uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) {
|
||||
return (parameter_id & 0x000000FF);
|
||||
}
|
||||
|
||||
uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) {
|
||||
return (poolId << 8) + index;
|
||||
}
|
||||
|
||||
|
||||
//SHOULDDO: Do we need a mutex lock here... I don't think so,
|
||||
//as we only check static const values of elements in a list that do not change.
|
||||
//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM
|
||||
ReturnValue_t GlobalDataPool::getType(uint32_t parameter_id, Type* type) {
|
||||
GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id));
|
||||
if ( it != this->globDataPool.end() ) {
|
||||
*type = it->second->getType();
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
*type = Type::UNKNOWN_TYPE;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalDataPool::exists(uint32_t parameterId) {
|
||||
uint32_t poolId = PIDToDataPoolId(parameterId);
|
||||
uint32_t index = PIDToArrayIndex(parameterId);
|
||||
GlobPoolMapIter it = this->globDataPool.find( poolId );
|
||||
if (it != globDataPool.end()) {
|
||||
if (it->second->getSize() >= index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template PoolEntry<uint8_t>* GlobalDataPool::getData<uint8_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<uint16_t>* GlobalDataPool::getData<uint16_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<uint32_t>* GlobalDataPool::getData<uint32_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<uint64_t>* GlobalDataPool::getData<uint64_t>(
|
||||
uint32_t data_pool_id, uint8_t size);
|
||||
template PoolEntry<int8_t>* GlobalDataPool::getData<int8_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<int16_t>* GlobalDataPool::getData<int16_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<int32_t>* GlobalDataPool::getData<int32_t>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<float>* GlobalDataPool::getData<float>(
|
||||
uint32_t data_pool_id, uint8_t size );
|
||||
template PoolEntry<double>* GlobalDataPool::getData<double>(
|
||||
uint32_t data_pool_id, uint8_t size);
|
||||
|
@ -1,149 +1,149 @@
|
||||
#ifndef GLOBALDATAPOOL_H_
|
||||
#define GLOBALDATAPOOL_H_
|
||||
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/globalfunctions/Type.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @defgroup data_pool Global data pool
|
||||
* This is the group, where all classes associated with global
|
||||
* data pool handling belong to.
|
||||
* This includes classes to access Data Pool variables.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Typedefs for the global pool representations
|
||||
*/
|
||||
using GlobPoolMap = std::map<uint32_t, PoolEntryIF*>;
|
||||
using GlobPoolMapIter = GlobPoolMap::iterator;
|
||||
|
||||
/**
|
||||
* @brief This class represents the OBSW global data-pool.
|
||||
*
|
||||
* @details
|
||||
* All variables are registered and space is allocated in an initialization
|
||||
* function, which is passed do the constructor. Space for the variables is
|
||||
* allocated on the heap (with a new call).
|
||||
*
|
||||
* The data is found by a data pool id, which uniquely represents a variable.
|
||||
* Data pool variables should be used with a blackboard logic in mind,
|
||||
* which means read data is valid (if flagged so),
|
||||
* but not necessarily up-to-date.
|
||||
*
|
||||
* Variables are either single values or arrays.
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class GlobalDataPool : public HasReturnvaluesIF {
|
||||
private:
|
||||
/**
|
||||
* @brief This is the actual data pool itself.
|
||||
* @details It is represented by a map with the data pool id as index
|
||||
* and a pointer to a single PoolEntry as value.
|
||||
*/
|
||||
GlobPoolMap globDataPool;
|
||||
|
||||
/**
|
||||
* @brief The mutex is created in the constructor and makes
|
||||
* access mutual exclusive.
|
||||
* @details Locking and unlocking the pool is only done by the DataSet class.
|
||||
*/
|
||||
MutexIF* mutex;
|
||||
public:
|
||||
/**
|
||||
* @brief In the classes constructor,
|
||||
* the passed initialization function is called.
|
||||
* @details
|
||||
* To enable filling the pool, a pointer to the map is passed,
|
||||
* allowing direct access to the pool's content.
|
||||
* On runtime, adding or removing variables is forbidden.
|
||||
*/
|
||||
GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) );
|
||||
|
||||
/**
|
||||
* @brief The destructor iterates through the data_pool map and
|
||||
* calls all entries destructors to clean up the heap.
|
||||
*/
|
||||
~GlobalDataPool();
|
||||
|
||||
/**
|
||||
* @brief This is the default call to access the pool.
|
||||
* @details
|
||||
* A pointer to the PoolEntry object is returned.
|
||||
* The call checks data pool id, type and array size.
|
||||
* Returns NULL in case of failure.
|
||||
* @param data_pool_id The data pool id to search.
|
||||
* @param sizeOrPosition The array size (not byte size!) of the pool entry,
|
||||
* or the position the user wants to read.
|
||||
* If smaller than the entry size, everything's ok.
|
||||
*/
|
||||
template <typename T> PoolEntry<T>* getData( uint32_t data_pool_id,
|
||||
uint8_t sizeOrPosition );
|
||||
|
||||
/**
|
||||
* @brief An alternative call to get a data pool entry in case the type is not implicitly known
|
||||
* (i.e. in Housekeeping Telemetry).
|
||||
* @details It returns a basic interface and does NOT perform
|
||||
* a size check. The caller has to assure he does not copy too much data.
|
||||
* Returns NULL in case the entry is not found.
|
||||
* @param data_pool_id The data pool id to search.
|
||||
*/
|
||||
PoolEntryIF* getRawData( uint32_t data_pool_id );
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate locking the global data pool.
|
||||
* @details It fetches the pool's mutex id and tries to acquire the mutex.
|
||||
*/
|
||||
ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING);
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate unlocking the global data pool.
|
||||
* @details It fetches the pool's mutex id and tries to free the mutex.
|
||||
*/
|
||||
ReturnValue_t unlockDataPool();
|
||||
/**
|
||||
* @brief The print call is a simple debug method.
|
||||
* @details It prints the current content of the data pool.
|
||||
* It iterates through the data_pool map and calls each entry's print() method.
|
||||
*/
|
||||
void print();
|
||||
/**
|
||||
* Extracts the data pool id from a SCOS 2000 PID.
|
||||
* @param parameter_id The passed Parameter ID.
|
||||
* @return The data pool id as used within the OBSW.
|
||||
*/
|
||||
static uint32_t PIDToDataPoolId( uint32_t parameter_id );
|
||||
/**
|
||||
* Extracts an array index out of a SCOS 2000 PID.
|
||||
* @param parameter_id The passed Parameter ID.
|
||||
* @return The index of the corresponding data pool entry.
|
||||
*/
|
||||
static uint8_t PIDToArrayIndex( uint32_t parameter_id );
|
||||
/**
|
||||
* Retransforms a data pool id and an array index to a SCOS 2000 PID.
|
||||
*/
|
||||
static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index );
|
||||
|
||||
/**
|
||||
* Method to return the type of a pool variable.
|
||||
* @param parameter_id A parameterID (not pool id) of a DP member.
|
||||
* @param type Returns the type or TYPE::UNKNOWN_TYPE
|
||||
* @return RETURN_OK if parameter exists, RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t getType( uint32_t parameter_id, Type* type );
|
||||
|
||||
/**
|
||||
* Method to check if a PID exists. Does not lock, as there's no
|
||||
* possibility to alter the list that is checked during run-time.
|
||||
* @param parameterId The PID (not pool id!) of a parameter.
|
||||
* @return true if exists, false else.
|
||||
*/
|
||||
bool exists(uint32_t parameterId);
|
||||
};
|
||||
|
||||
//We assume someone globally instantiates a DataPool.
|
||||
namespace glob {
|
||||
extern GlobalDataPool dataPool;
|
||||
}
|
||||
|
||||
#endif /* DATAPOOL_H_ */
|
||||
#ifndef GLOBALDATAPOOL_H_
|
||||
#define GLOBALDATAPOOL_H_
|
||||
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../globalfunctions/Type.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @defgroup data_pool Global data pool
|
||||
* This is the group, where all classes associated with global
|
||||
* data pool handling belong to.
|
||||
* This includes classes to access Data Pool variables.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Typedefs for the global pool representations
|
||||
*/
|
||||
using GlobPoolMap = std::map<uint32_t, PoolEntryIF*>;
|
||||
using GlobPoolMapIter = GlobPoolMap::iterator;
|
||||
|
||||
/**
|
||||
* @brief This class represents the OBSW global data-pool.
|
||||
*
|
||||
* @details
|
||||
* All variables are registered and space is allocated in an initialization
|
||||
* function, which is passed do the constructor. Space for the variables is
|
||||
* allocated on the heap (with a new call).
|
||||
*
|
||||
* The data is found by a data pool id, which uniquely represents a variable.
|
||||
* Data pool variables should be used with a blackboard logic in mind,
|
||||
* which means read data is valid (if flagged so),
|
||||
* but not necessarily up-to-date.
|
||||
*
|
||||
* Variables are either single values or arrays.
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class GlobalDataPool : public HasReturnvaluesIF {
|
||||
private:
|
||||
/**
|
||||
* @brief This is the actual data pool itself.
|
||||
* @details It is represented by a map with the data pool id as index
|
||||
* and a pointer to a single PoolEntry as value.
|
||||
*/
|
||||
GlobPoolMap globDataPool;
|
||||
|
||||
/**
|
||||
* @brief The mutex is created in the constructor and makes
|
||||
* access mutual exclusive.
|
||||
* @details Locking and unlocking the pool is only done by the DataSet class.
|
||||
*/
|
||||
MutexIF* mutex;
|
||||
public:
|
||||
/**
|
||||
* @brief In the classes constructor,
|
||||
* the passed initialization function is called.
|
||||
* @details
|
||||
* To enable filling the pool, a pointer to the map is passed,
|
||||
* allowing direct access to the pool's content.
|
||||
* On runtime, adding or removing variables is forbidden.
|
||||
*/
|
||||
GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) );
|
||||
|
||||
/**
|
||||
* @brief The destructor iterates through the data_pool map and
|
||||
* calls all entries destructors to clean up the heap.
|
||||
*/
|
||||
~GlobalDataPool();
|
||||
|
||||
/**
|
||||
* @brief This is the default call to access the pool.
|
||||
* @details
|
||||
* A pointer to the PoolEntry object is returned.
|
||||
* The call checks data pool id, type and array size.
|
||||
* Returns NULL in case of failure.
|
||||
* @param data_pool_id The data pool id to search.
|
||||
* @param sizeOrPosition The array size (not byte size!) of the pool entry,
|
||||
* or the position the user wants to read.
|
||||
* If smaller than the entry size, everything's ok.
|
||||
*/
|
||||
template <typename T> PoolEntry<T>* getData( uint32_t data_pool_id,
|
||||
uint8_t sizeOrPosition );
|
||||
|
||||
/**
|
||||
* @brief An alternative call to get a data pool entry in case the type is not implicitly known
|
||||
* (i.e. in Housekeeping Telemetry).
|
||||
* @details It returns a basic interface and does NOT perform
|
||||
* a size check. The caller has to assure he does not copy too much data.
|
||||
* Returns NULL in case the entry is not found.
|
||||
* @param data_pool_id The data pool id to search.
|
||||
*/
|
||||
PoolEntryIF* getRawData( uint32_t data_pool_id );
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate locking the global data pool.
|
||||
* @details It fetches the pool's mutex id and tries to acquire the mutex.
|
||||
*/
|
||||
ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING);
|
||||
/**
|
||||
* @brief This is a small helper function to facilitate unlocking the global data pool.
|
||||
* @details It fetches the pool's mutex id and tries to free the mutex.
|
||||
*/
|
||||
ReturnValue_t unlockDataPool();
|
||||
/**
|
||||
* @brief The print call is a simple debug method.
|
||||
* @details It prints the current content of the data pool.
|
||||
* It iterates through the data_pool map and calls each entry's print() method.
|
||||
*/
|
||||
void print();
|
||||
/**
|
||||
* Extracts the data pool id from a SCOS 2000 PID.
|
||||
* @param parameter_id The passed Parameter ID.
|
||||
* @return The data pool id as used within the OBSW.
|
||||
*/
|
||||
static uint32_t PIDToDataPoolId( uint32_t parameter_id );
|
||||
/**
|
||||
* Extracts an array index out of a SCOS 2000 PID.
|
||||
* @param parameter_id The passed Parameter ID.
|
||||
* @return The index of the corresponding data pool entry.
|
||||
*/
|
||||
static uint8_t PIDToArrayIndex( uint32_t parameter_id );
|
||||
/**
|
||||
* Retransforms a data pool id and an array index to a SCOS 2000 PID.
|
||||
*/
|
||||
static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index );
|
||||
|
||||
/**
|
||||
* Method to return the type of a pool variable.
|
||||
* @param parameter_id A parameterID (not pool id) of a DP member.
|
||||
* @param type Returns the type or TYPE::UNKNOWN_TYPE
|
||||
* @return RETURN_OK if parameter exists, RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t getType( uint32_t parameter_id, Type* type );
|
||||
|
||||
/**
|
||||
* Method to check if a PID exists. Does not lock, as there's no
|
||||
* possibility to alter the list that is checked during run-time.
|
||||
* @param parameterId The PID (not pool id!) of a parameter.
|
||||
* @return true if exists, false else.
|
||||
*/
|
||||
bool exists(uint32_t parameterId);
|
||||
};
|
||||
|
||||
//We assume someone globally instantiates a DataPool.
|
||||
namespace glob {
|
||||
extern GlobalDataPool dataPool;
|
||||
}
|
||||
|
||||
#endif /* DATAPOOL_H_ */
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <framework/datapoolglob/GlobalDataPool.h>
|
||||
#include <framework/datapoolglob/GlobalDataSet.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include "../datapoolglob/GlobalDataPool.h"
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
GlobDataSet::GlobDataSet(): PoolDataSetBase(
|
||||
reinterpret_cast<PoolVariableIF**>(®isteredVariables),
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLGLOB_DATASET_H_
|
||||
#define FRAMEWORK_DATAPOOLGLOB_DATASET_H_
|
||||
|
||||
#include <framework/datapool/PoolDataSetBase.h>
|
||||
#include "../datapool/PoolDataSetBase.h"
|
||||
|
||||
/**
|
||||
* @brief The DataSet class manages a set of locally checked out variables
|
||||
|
@ -1,213 +1,213 @@
|
||||
#ifndef GLOBALPOOLVARIABLE_H_
|
||||
#define GLOBALPOOLVARIABLE_H_
|
||||
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapoolglob/GlobalDataPool.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
template<typename T, uint8_t n_var> class PoolVarList;
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is the access class for non-array data pool entries.
|
||||
*
|
||||
* @details
|
||||
* To ensure safe usage of the data pool, operation is not done directly
|
||||
* on the data pool entries, but on local copies. This class provides simple
|
||||
* type-safe access to single data pool entries (i.e. entries with length = 1).
|
||||
* The class can be instantiated as read-write and read only.
|
||||
* It provides a commit-and-roll-back semantic, which means that the
|
||||
* variable's value in the data pool is not changed until the
|
||||
* commit call is executed.
|
||||
* @tparam T The template parameter sets the type of the variable.
|
||||
* Currently, all plain data types are supported, but in principle
|
||||
* any type is possible.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template<typename T>
|
||||
class GlobPoolVar: public PoolVariableIF {
|
||||
template<typename U, uint8_t n_var> friend class PoolVarList;
|
||||
static_assert(not std::is_same<T, bool>::value,
|
||||
"Do not use boolean for the PoolEntry type, use uint8_t instead!"
|
||||
"There is no boolean type in CCSDS.");
|
||||
public:
|
||||
/**
|
||||
* @brief In the constructor, the variable can register itself in a
|
||||
* DataSet (if nullptr is not passed).
|
||||
* @details
|
||||
* It DOES NOT fetch the current value from the data pool, but
|
||||
* sets the value attribute to default (0).
|
||||
* The value is fetched within the read() operation.
|
||||
* @param set_id This is the id in the global data pool
|
||||
* this instance of the access class corresponds to.
|
||||
* @param dataSet The data set in which the variable shall register
|
||||
* itself. If NULL, the variable is not registered.
|
||||
* @param setWritable If this flag is set to true, changes in the value
|
||||
* attribute can be written back to the data pool, otherwise not.
|
||||
*/
|
||||
GlobPoolVar(uint32_t set_id, DataSetIF* dataSet,
|
||||
ReadWriteMode_t setReadWriteMode);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details The user can work on this attribute
|
||||
* just like he would on a simple local variable.
|
||||
*/
|
||||
T value = 0;
|
||||
|
||||
/**
|
||||
* @brief Copy ctor to copy classes containing Pool Variables.
|
||||
* (Robin): This only copies member variables, which is done
|
||||
* by the default copy ctor. maybe we can ommit this ctor?
|
||||
*/
|
||||
GlobPoolVar(const GlobPoolVar& rhs);
|
||||
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~GlobPoolVar() {}
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the value from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the global data pool and copies the value and the valid
|
||||
* information to its local attributes. In case of a failure (wrong type or
|
||||
* pool id not found), the variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout) override;
|
||||
/**
|
||||
* @brief The commit call writes back the variable's value to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the valid flag is automatically set to "valid".
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* The commit call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls,
|
||||
* the data pool is stored.
|
||||
*/
|
||||
uint32_t dataPoolId;
|
||||
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool is
|
||||
* copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
|
||||
/**
|
||||
* @brief The information whether the class is read-write or read-only
|
||||
* is stored here.
|
||||
*/
|
||||
pool_rwm_t readWriteMode;
|
||||
|
||||
/**
|
||||
* Empty ctor for List initialization
|
||||
*/
|
||||
GlobPoolVar();
|
||||
public:
|
||||
/**
|
||||
* \brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const override;
|
||||
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const override;
|
||||
/**
|
||||
* This operation sets the data pool id of the variable.
|
||||
* The method is necessary to set id's of data pool member variables with bad initialization.
|
||||
*/
|
||||
void setDataPoolId(uint32_t poolId);
|
||||
|
||||
/**
|
||||
* \brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const override;
|
||||
|
||||
uint8_t getValid();
|
||||
|
||||
void setValid(bool valid) override;
|
||||
|
||||
operator T() {
|
||||
return value;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
GlobPoolVar<T> &operator=(T newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GlobPoolVar<T> &operator=(GlobPoolVar<T> newPoolVariable) {
|
||||
value = newPoolVariable.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t max_size,
|
||||
SerializeIF::Endianness streamEndianness) const override {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, max_size,
|
||||
streamEndianness);
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size,
|
||||
streamEndianness);
|
||||
}
|
||||
};
|
||||
|
||||
#include <framework/datapoolglob/GlobalPoolVariable.tpp>
|
||||
|
||||
typedef GlobPoolVar<uint8_t> gp_bool_t;
|
||||
typedef GlobPoolVar<uint8_t> gp_uint8_t;
|
||||
typedef GlobPoolVar<uint16_t> gp_uint16_t;
|
||||
typedef GlobPoolVar<uint32_t> gp_uint32_t;
|
||||
typedef GlobPoolVar<int8_t> gp_int8_t;
|
||||
typedef GlobPoolVar<int16_t> gp_int16_t;
|
||||
typedef GlobPoolVar<int32_t> gp_int32_t;
|
||||
typedef GlobPoolVar<float> gp_float_t;
|
||||
typedef GlobPoolVar<double> gp_double_t;
|
||||
|
||||
#endif /* POOLVARIABLE_H_ */
|
||||
#ifndef GLOBALPOOLVARIABLE_H_
|
||||
#define GLOBALPOOLVARIABLE_H_
|
||||
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapoolglob/GlobalDataPool.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
template<typename T, uint8_t n_var> class PoolVarList;
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is the access class for non-array data pool entries.
|
||||
*
|
||||
* @details
|
||||
* To ensure safe usage of the data pool, operation is not done directly
|
||||
* on the data pool entries, but on local copies. This class provides simple
|
||||
* type-safe access to single data pool entries (i.e. entries with length = 1).
|
||||
* The class can be instantiated as read-write and read only.
|
||||
* It provides a commit-and-roll-back semantic, which means that the
|
||||
* variable's value in the data pool is not changed until the
|
||||
* commit call is executed.
|
||||
* @tparam T The template parameter sets the type of the variable.
|
||||
* Currently, all plain data types are supported, but in principle
|
||||
* any type is possible.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template<typename T>
|
||||
class GlobPoolVar: public PoolVariableIF {
|
||||
template<typename U, uint8_t n_var> friend class PoolVarList;
|
||||
static_assert(not std::is_same<T, bool>::value,
|
||||
"Do not use boolean for the PoolEntry type, use uint8_t instead!"
|
||||
"There is no boolean type in CCSDS.");
|
||||
public:
|
||||
/**
|
||||
* @brief In the constructor, the variable can register itself in a
|
||||
* DataSet (if nullptr is not passed).
|
||||
* @details
|
||||
* It DOES NOT fetch the current value from the data pool, but
|
||||
* sets the value attribute to default (0).
|
||||
* The value is fetched within the read() operation.
|
||||
* @param set_id This is the id in the global data pool
|
||||
* this instance of the access class corresponds to.
|
||||
* @param dataSet The data set in which the variable shall register
|
||||
* itself. If NULL, the variable is not registered.
|
||||
* @param setWritable If this flag is set to true, changes in the value
|
||||
* attribute can be written back to the data pool, otherwise not.
|
||||
*/
|
||||
GlobPoolVar(uint32_t set_id, DataSetIF* dataSet,
|
||||
ReadWriteMode_t setReadWriteMode);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details The user can work on this attribute
|
||||
* just like he would on a simple local variable.
|
||||
*/
|
||||
T value = 0;
|
||||
|
||||
/**
|
||||
* @brief Copy ctor to copy classes containing Pool Variables.
|
||||
* (Robin): This only copies member variables, which is done
|
||||
* by the default copy ctor. maybe we can ommit this ctor?
|
||||
*/
|
||||
GlobPoolVar(const GlobPoolVar& rhs);
|
||||
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~GlobPoolVar() {}
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the value from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the global data pool and copies the value and the valid
|
||||
* information to its local attributes. In case of a failure (wrong type or
|
||||
* pool id not found), the variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout) override;
|
||||
/**
|
||||
* @brief The commit call writes back the variable's value to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the valid flag is automatically set to "valid".
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* The commit call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls,
|
||||
* the data pool is stored.
|
||||
*/
|
||||
uint32_t dataPoolId;
|
||||
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool is
|
||||
* copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
|
||||
/**
|
||||
* @brief The information whether the class is read-write or read-only
|
||||
* is stored here.
|
||||
*/
|
||||
pool_rwm_t readWriteMode;
|
||||
|
||||
/**
|
||||
* Empty ctor for List initialization
|
||||
*/
|
||||
GlobPoolVar();
|
||||
public:
|
||||
/**
|
||||
* \brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const override;
|
||||
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const override;
|
||||
/**
|
||||
* This operation sets the data pool id of the variable.
|
||||
* The method is necessary to set id's of data pool member variables with bad initialization.
|
||||
*/
|
||||
void setDataPoolId(uint32_t poolId);
|
||||
|
||||
/**
|
||||
* \brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const override;
|
||||
|
||||
uint8_t getValid();
|
||||
|
||||
void setValid(bool valid) override;
|
||||
|
||||
operator T() {
|
||||
return value;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
GlobPoolVar<T> &operator=(T newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GlobPoolVar<T> &operator=(GlobPoolVar<T> newPoolVariable) {
|
||||
value = newPoolVariable.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t max_size,
|
||||
SerializeIF::Endianness streamEndianness) const override {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, max_size,
|
||||
streamEndianness);
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size,
|
||||
streamEndianness);
|
||||
}
|
||||
};
|
||||
|
||||
#include "../datapoolglob/GlobalPoolVariable.tpp"
|
||||
|
||||
typedef GlobPoolVar<uint8_t> gp_bool_t;
|
||||
typedef GlobPoolVar<uint8_t> gp_uint8_t;
|
||||
typedef GlobPoolVar<uint16_t> gp_uint16_t;
|
||||
typedef GlobPoolVar<uint32_t> gp_uint32_t;
|
||||
typedef GlobPoolVar<int8_t> gp_int8_t;
|
||||
typedef GlobPoolVar<int16_t> gp_int16_t;
|
||||
typedef GlobPoolVar<int32_t> gp_int32_t;
|
||||
typedef GlobPoolVar<float> gp_float_t;
|
||||
typedef GlobPoolVar<double> gp_double_t;
|
||||
|
||||
#endif /* POOLVARIABLE_H_ */
|
||||
|
@ -1,185 +1,185 @@
|
||||
#ifndef GLOBALPOOLVECTOR_H_
|
||||
#define GLOBALPOOLVECTOR_H_
|
||||
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
/**
|
||||
* @brief This is the access class for array-type data pool entries.
|
||||
*
|
||||
* @details
|
||||
* To ensure safe usage of the data pool, operation is not done directly on the
|
||||
* data pool entries, but on local copies. This class provides simple type-
|
||||
* and length-safe access to vector-style data pool entries (i.e. entries with
|
||||
* length > 1). The class can be instantiated as read-write and read only.
|
||||
*
|
||||
* It provides a commit-and-roll-back semantic, which means that no array
|
||||
* entry in the data pool is changed until the commit call is executed.
|
||||
* There are two template parameters:
|
||||
* @tparam T
|
||||
* This template parameter specifies the data type of an array entry. Currently,
|
||||
* all plain data types are supported, but in principle any type is possible.
|
||||
* @tparam vector_size
|
||||
* This template parameter specifies the vector size of this entry. Using a
|
||||
* template parameter for this is not perfect, but avoids
|
||||
* dynamic memory allocation.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template<typename T, uint16_t vectorSize>
|
||||
class GlobPoolVector: public PoolVariableIF {
|
||||
public:
|
||||
/**
|
||||
* @brief In the constructor, the variable can register itself in a
|
||||
* DataSet (if no nullptr is passed).
|
||||
* @details
|
||||
* It DOES NOT fetch the current value from the data pool, but sets the
|
||||
* value attribute to default (0). The value is fetched within the
|
||||
* read() operation.
|
||||
* @param set_id
|
||||
* This is the id in the global data pool this instance of the access
|
||||
* class corresponds to.
|
||||
* @param dataSet
|
||||
* The data set in which the variable shall register itself. If nullptr,
|
||||
* the variable is not registered.
|
||||
* @param setWritable
|
||||
* If this flag is set to true, changes in the value attribute can be
|
||||
* written back to the data pool, otherwise not.
|
||||
*/
|
||||
GlobPoolVector(uint32_t set_id, DataSetIF* set,
|
||||
ReadWriteMode_t setReadWriteMode);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details The user can work on this attribute
|
||||
* just like he would on a local array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~GlobPoolVector() {};
|
||||
/**
|
||||
* @brief The operation returns the number of array entries
|
||||
* in this variable.
|
||||
*/
|
||||
uint8_t getSize() {
|
||||
return vectorSize;
|
||||
}
|
||||
/**
|
||||
* @brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const {
|
||||
return dataPoolId;
|
||||
}
|
||||
/**
|
||||
* @brief This operation sets the data pool id of the variable.
|
||||
* @details
|
||||
* The method is necessary to set id's of data pool member variables
|
||||
* with bad initialization.
|
||||
*/
|
||||
void setDataPoolId(uint32_t poolId) {
|
||||
dataPoolId = poolId;
|
||||
}
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const {
|
||||
return readWriteMode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const {
|
||||
if (valid != INVALID)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void setValid(bool valid) {this->valid = valid;}
|
||||
uint8_t getValid() {return valid;}
|
||||
|
||||
T &operator [](int i) {return value[i];}
|
||||
const T &operator [](int i) const {return value[i];}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t max_size, Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the global data pool and copies all array values
|
||||
* and the valid information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected by a lock of the global data pool.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the valid flag is automatically set to "valid".
|
||||
* The commit call is protected by a lock of the global data pool.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls,
|
||||
* the data pool id is stored.
|
||||
*/
|
||||
uint32_t dataPoolId;
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool
|
||||
* is copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief The information whether the class is read-write or
|
||||
* read-only is stored here.
|
||||
*/
|
||||
ReadWriteMode_t readWriteMode;
|
||||
};
|
||||
|
||||
#include <framework/datapoolglob/GlobalPoolVector.tpp>
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
using gp_vec_t = GlobPoolVector<T, vectorSize>;
|
||||
|
||||
#endif /* POOLVECTOR_H_ */
|
||||
#ifndef GLOBALPOOLVECTOR_H_
|
||||
#define GLOBALPOOLVECTOR_H_
|
||||
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
/**
|
||||
* @brief This is the access class for array-type data pool entries.
|
||||
*
|
||||
* @details
|
||||
* To ensure safe usage of the data pool, operation is not done directly on the
|
||||
* data pool entries, but on local copies. This class provides simple type-
|
||||
* and length-safe access to vector-style data pool entries (i.e. entries with
|
||||
* length > 1). The class can be instantiated as read-write and read only.
|
||||
*
|
||||
* It provides a commit-and-roll-back semantic, which means that no array
|
||||
* entry in the data pool is changed until the commit call is executed.
|
||||
* There are two template parameters:
|
||||
* @tparam T
|
||||
* This template parameter specifies the data type of an array entry. Currently,
|
||||
* all plain data types are supported, but in principle any type is possible.
|
||||
* @tparam vector_size
|
||||
* This template parameter specifies the vector size of this entry. Using a
|
||||
* template parameter for this is not perfect, but avoids
|
||||
* dynamic memory allocation.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template<typename T, uint16_t vectorSize>
|
||||
class GlobPoolVector: public PoolVariableIF {
|
||||
public:
|
||||
/**
|
||||
* @brief In the constructor, the variable can register itself in a
|
||||
* DataSet (if no nullptr is passed).
|
||||
* @details
|
||||
* It DOES NOT fetch the current value from the data pool, but sets the
|
||||
* value attribute to default (0). The value is fetched within the
|
||||
* read() operation.
|
||||
* @param set_id
|
||||
* This is the id in the global data pool this instance of the access
|
||||
* class corresponds to.
|
||||
* @param dataSet
|
||||
* The data set in which the variable shall register itself. If nullptr,
|
||||
* the variable is not registered.
|
||||
* @param setWritable
|
||||
* If this flag is set to true, changes in the value attribute can be
|
||||
* written back to the data pool, otherwise not.
|
||||
*/
|
||||
GlobPoolVector(uint32_t set_id, DataSetIF* set,
|
||||
ReadWriteMode_t setReadWriteMode);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details The user can work on this attribute
|
||||
* just like he would on a local array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~GlobPoolVector() {};
|
||||
/**
|
||||
* @brief The operation returns the number of array entries
|
||||
* in this variable.
|
||||
*/
|
||||
uint8_t getSize() {
|
||||
return vectorSize;
|
||||
}
|
||||
/**
|
||||
* @brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const {
|
||||
return dataPoolId;
|
||||
}
|
||||
/**
|
||||
* @brief This operation sets the data pool id of the variable.
|
||||
* @details
|
||||
* The method is necessary to set id's of data pool member variables
|
||||
* with bad initialization.
|
||||
*/
|
||||
void setDataPoolId(uint32_t poolId) {
|
||||
dataPoolId = poolId;
|
||||
}
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const {
|
||||
return readWriteMode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const {
|
||||
if (valid != INVALID)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void setValid(bool valid) {this->valid = valid;}
|
||||
uint8_t getValid() {return valid;}
|
||||
|
||||
T &operator [](int i) {return value[i];}
|
||||
const T &operator [](int i) const {return value[i];}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
size_t max_size, Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the global data pool and copies all array values
|
||||
* and the valid information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected by a lock of the global data pool.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the valid flag is automatically set to "valid".
|
||||
* The commit call is protected by a lock of the global data pool.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls,
|
||||
* the data pool id is stored.
|
||||
*/
|
||||
uint32_t dataPoolId;
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool
|
||||
* is copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief The information whether the class is read-write or
|
||||
* read-only is stored here.
|
||||
*/
|
||||
ReadWriteMode_t readWriteMode;
|
||||
};
|
||||
|
||||
#include "../datapoolglob/GlobalPoolVector.tpp"
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
using gp_vec_t = GlobPoolVector<T, vectorSize>;
|
||||
|
||||
#endif /* POOLVECTOR_H_ */
|
||||
|
@ -1,164 +1,164 @@
|
||||
#ifndef PIDREADER_H_
|
||||
#define PIDREADER_H_
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapoolglob/GlobalDataPool.h>
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
template<typename U, uint8_t n_var> class PIDReaderList;
|
||||
|
||||
template<typename T>
|
||||
class PIDReader: public PoolVariableIF {
|
||||
template<typename U, uint8_t n_var> friend class PIDReaderList;
|
||||
protected:
|
||||
uint32_t parameterId;
|
||||
uint8_t valid;
|
||||
ReturnValue_t readWithoutLock() {
|
||||
uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId);
|
||||
PoolEntry<T> *read_out = glob::dataPool.getData<T>(
|
||||
GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex);
|
||||
if (read_out != NULL) {
|
||||
valid = read_out->valid;
|
||||
value = read_out->address[arrayIndex];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
value = 0;
|
||||
valid = false;
|
||||
sif::error << "PIDReader: read of PID 0x" << std::hex << parameterId
|
||||
<< std::dec << " failed." << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Never commit, is read-only.
|
||||
* Reason is the possibility to access a single DP vector element, but if we commit,
|
||||
* we set validity of the whole vector.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout) override {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t commitWithoutLock() override {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty ctor for List initialization
|
||||
*/
|
||||
PIDReader() :
|
||||
parameterId(PoolVariableIF::NO_PARAMETER), valid(
|
||||
PoolVariableIF::INVALID), value(0) {
|
||||
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* \brief This is the local copy of the data pool entry.
|
||||
*/
|
||||
T value;
|
||||
/**
|
||||
* \brief In the constructor, the variable can register itself in a DataSet (if not NULL is
|
||||
* passed).
|
||||
* \details It DOES NOT fetch the current value from the data pool, but sets the value
|
||||
* attribute to default (0). The value is fetched within the read() operation.
|
||||
* \param set_id This is the id in the global data pool this instance of the access class
|
||||
* corresponds to.
|
||||
* \param dataSet The data set in which the variable shall register itself. If NULL,
|
||||
* the variable is not registered.
|
||||
* \param setWritable If this flag is set to true, changes in the value attribute can be
|
||||
* written back to the data pool, otherwise not.
|
||||
*/
|
||||
PIDReader(uint32_t setParameterId, DataSetIF *dataSet) :
|
||||
parameterId(setParameterId), valid(PoolVariableIF::INVALID), value(
|
||||
0) {
|
||||
if (dataSet != NULL) {
|
||||
dataSet->registerVariable(this);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t read(uint32_t lockTimeout) override {
|
||||
ReturnValue_t result = glob::dataPool.lockDataPool();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = readWithoutLock();
|
||||
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
|
||||
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "PIDReader::read: Could not unlock data pool!"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Copy ctor to copy classes containing Pool Variables.
|
||||
*/
|
||||
PIDReader(const PIDReader &rhs) :
|
||||
parameterId(rhs.parameterId), valid(rhs.valid), value(rhs.value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief The classes destructor is empty.
|
||||
*/
|
||||
~PIDReader() {
|
||||
|
||||
}
|
||||
/**
|
||||
* \brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const {
|
||||
return GlobalDataPool::PIDToDataPoolId(parameterId);
|
||||
}
|
||||
uint32_t getParameterId() const {
|
||||
return parameterId;
|
||||
}
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const {
|
||||
return VAR_READ;
|
||||
}
|
||||
/**
|
||||
* \brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const {
|
||||
if (valid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
void setValid(bool valid) {
|
||||
this->valid = valid;
|
||||
}
|
||||
|
||||
operator T() {
|
||||
return value;
|
||||
}
|
||||
|
||||
PIDReader<T>& operator=(T newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
|
||||
size_t maxSize, Endianness streamEndianness) const override {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const override {
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size,
|
||||
streamEndianness);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* PIDREADER_H_ */
|
||||
#ifndef PIDREADER_H_
|
||||
#define PIDREADER_H_
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapoolglob/GlobalDataPool.h"
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
template<typename U, uint8_t n_var> class PIDReaderList;
|
||||
|
||||
template<typename T>
|
||||
class PIDReader: public PoolVariableIF {
|
||||
template<typename U, uint8_t n_var> friend class PIDReaderList;
|
||||
protected:
|
||||
uint32_t parameterId;
|
||||
uint8_t valid;
|
||||
ReturnValue_t readWithoutLock() {
|
||||
uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId);
|
||||
PoolEntry<T> *read_out = glob::dataPool.getData<T>(
|
||||
GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex);
|
||||
if (read_out != NULL) {
|
||||
valid = read_out->valid;
|
||||
value = read_out->address[arrayIndex];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
value = 0;
|
||||
valid = false;
|
||||
sif::error << "PIDReader: read of PID 0x" << std::hex << parameterId
|
||||
<< std::dec << " failed." << std::endl;
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Never commit, is read-only.
|
||||
* Reason is the possibility to access a single DP vector element, but if we commit,
|
||||
* we set validity of the whole vector.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout) override {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
ReturnValue_t commitWithoutLock() override {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty ctor for List initialization
|
||||
*/
|
||||
PIDReader() :
|
||||
parameterId(PoolVariableIF::NO_PARAMETER), valid(
|
||||
PoolVariableIF::INVALID), value(0) {
|
||||
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* \brief This is the local copy of the data pool entry.
|
||||
*/
|
||||
T value;
|
||||
/**
|
||||
* \brief In the constructor, the variable can register itself in a DataSet (if not NULL is
|
||||
* passed).
|
||||
* \details It DOES NOT fetch the current value from the data pool, but sets the value
|
||||
* attribute to default (0). The value is fetched within the read() operation.
|
||||
* \param set_id This is the id in the global data pool this instance of the access class
|
||||
* corresponds to.
|
||||
* \param dataSet The data set in which the variable shall register itself. If NULL,
|
||||
* the variable is not registered.
|
||||
* \param setWritable If this flag is set to true, changes in the value attribute can be
|
||||
* written back to the data pool, otherwise not.
|
||||
*/
|
||||
PIDReader(uint32_t setParameterId, DataSetIF *dataSet) :
|
||||
parameterId(setParameterId), valid(PoolVariableIF::INVALID), value(
|
||||
0) {
|
||||
if (dataSet != NULL) {
|
||||
dataSet->registerVariable(this);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t read(uint32_t lockTimeout) override {
|
||||
ReturnValue_t result = glob::dataPool.lockDataPool();
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = readWithoutLock();
|
||||
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
|
||||
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "PIDReader::read: Could not unlock data pool!"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Copy ctor to copy classes containing Pool Variables.
|
||||
*/
|
||||
PIDReader(const PIDReader &rhs) :
|
||||
parameterId(rhs.parameterId), valid(rhs.valid), value(rhs.value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief The classes destructor is empty.
|
||||
*/
|
||||
~PIDReader() {
|
||||
|
||||
}
|
||||
/**
|
||||
* \brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const {
|
||||
return GlobalDataPool::PIDToDataPoolId(parameterId);
|
||||
}
|
||||
uint32_t getParameterId() const {
|
||||
return parameterId;
|
||||
}
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const {
|
||||
return VAR_READ;
|
||||
}
|
||||
/**
|
||||
* \brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const {
|
||||
if (valid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
void setValid(bool valid) {
|
||||
this->valid = valid;
|
||||
}
|
||||
|
||||
operator T() {
|
||||
return value;
|
||||
}
|
||||
|
||||
PIDReader<T>& operator=(T newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
|
||||
size_t maxSize, Endianness streamEndianness) const override {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, maxSize,
|
||||
streamEndianness);
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const override {
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size,
|
||||
streamEndianness);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* PIDREADER_H_ */
|
||||
|
@ -1,27 +1,27 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
|
||||
#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
|
||||
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/datapoolglob/PIDReader.h>
|
||||
template <class T, uint8_t n_var>
|
||||
class PIDReaderList {
|
||||
private:
|
||||
PIDReader<T> variables[n_var];
|
||||
public:
|
||||
PIDReaderList( const uint32_t setPid[n_var], DataSetIF* dataSet) {
|
||||
//I really should have a look at the new init list c++ syntax.
|
||||
if (dataSet == NULL) {
|
||||
return;
|
||||
}
|
||||
for (uint8_t count = 0; count < n_var; count++) {
|
||||
variables[count].parameterId = setPid[count];
|
||||
dataSet->registerVariable(&variables[count]);
|
||||
}
|
||||
}
|
||||
|
||||
PIDReader<T> &operator [](int i) { return variables[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */
|
||||
#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
|
||||
#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
|
||||
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapoolglob/PIDReader.h"
|
||||
template <class T, uint8_t n_var>
|
||||
class PIDReaderList {
|
||||
private:
|
||||
PIDReader<T> variables[n_var];
|
||||
public:
|
||||
PIDReaderList( const uint32_t setPid[n_var], DataSetIF* dataSet) {
|
||||
//I really should have a look at the new init list c++ syntax.
|
||||
if (dataSet == NULL) {
|
||||
return;
|
||||
}
|
||||
for (uint8_t count = 0; count < n_var; count++) {
|
||||
variables[count].parameterId = setPid[count];
|
||||
dataSet->registerVariable(&variables[count]);
|
||||
}
|
||||
}
|
||||
|
||||
PIDReader<T> &operator [](int i) { return variables[i]; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */
|
||||
|
@ -1,239 +1,239 @@
|
||||
#include <framework/datapoolglob/GlobalDataPool.h>
|
||||
#include <framework/datapoolglob/PoolRawAccess.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/serialize/EndianConverter.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
|
||||
DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) :
|
||||
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false),
|
||||
type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0),
|
||||
readWriteMode(setReadWriteMode) {
|
||||
memset(value, 0, sizeof(value));
|
||||
if (dataSet != nullptr) {
|
||||
dataSet->registerVariable(this);
|
||||
}
|
||||
}
|
||||
|
||||
PoolRawAccess::~PoolRawAccess() {}
|
||||
|
||||
ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) {
|
||||
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = readWithoutLock();
|
||||
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
|
||||
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::readWithoutLock() {
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId);
|
||||
if (readOut != nullptr) {
|
||||
result = handleReadOut(readOut);
|
||||
if(result == RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result = READ_ENTRY_NON_EXISTENT;
|
||||
}
|
||||
handleReadError(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) {
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
valid = readOut->getValid();
|
||||
if (readOut->getSize() > arrayEntry) {
|
||||
arraySize = readOut->getSize();
|
||||
typeSize = readOut->getByteSize() / readOut->getSize();
|
||||
type = readOut->getType();
|
||||
if (typeSize <= sizeof(value)) {
|
||||
uint16_t arrayPosition = arrayEntry * typeSize;
|
||||
sizeTillEnd = readOut->getByteSize() - arrayPosition;
|
||||
uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition];
|
||||
memcpy(value, ptr, typeSize);
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
result = READ_TYPE_TOO_LARGE;
|
||||
}
|
||||
} else {
|
||||
//debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
|
||||
result = READ_INDEX_TOO_LARGE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PoolRawAccess::handleReadError(ReturnValue_t result) {
|
||||
sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
|
||||
<< std::dec << " failed, ";
|
||||
if(result == READ_TYPE_TOO_LARGE) {
|
||||
sif::error << "type too large." << std::endl;
|
||||
}
|
||||
else if(result == READ_INDEX_TOO_LARGE) {
|
||||
sif::error << "index too large." << std::endl;
|
||||
}
|
||||
else if(result == READ_ENTRY_NON_EXISTENT) {
|
||||
sif::error << "entry does not exist." << std::endl;
|
||||
}
|
||||
|
||||
valid = INVALID;
|
||||
typeSize = 0;
|
||||
sizeTillEnd = 0;
|
||||
memset(value, 0, sizeof(value));
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) {
|
||||
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = commitWithoutLock();
|
||||
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
|
||||
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::commitWithoutLock() {
|
||||
PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId);
|
||||
if ((write_back != NULL) && (readWriteMode != VAR_READ)) {
|
||||
write_back->setValid(valid);
|
||||
uint8_t array_position = arrayEntry * typeSize;
|
||||
uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position];
|
||||
memcpy(ptr, value, typeSize);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* PoolRawAccess::getEntry() {
|
||||
return value;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
|
||||
size_t* writtenBytes, size_t max_size) {
|
||||
uint8_t* data_ptr = getEntry();
|
||||
// debug << "PoolRawAccess::getEntry: Array position: " <<
|
||||
// index * size_of_type << " Size of T: " << (int)size_of_type <<
|
||||
// " ByteSize: " << byte_size << " Position: " << *size << std::endl;
|
||||
if (typeSize == 0)
|
||||
return DATA_POOL_ACCESS_FAILED;
|
||||
if (typeSize > max_size)
|
||||
return INCORRECT_SIZE;
|
||||
EndianConverter::convertBigEndian(buffer, data_ptr, typeSize);
|
||||
*writtenBytes = typeSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
if (typeSize + *size <= maxSize) {
|
||||
switch(streamEndianness) {
|
||||
case(Endianness::BIG):
|
||||
EndianConverter::convertBigEndian(*buffer, value, typeSize);
|
||||
break;
|
||||
case(Endianness::LITTLE):
|
||||
EndianConverter::convertLittleEndian(*buffer, value, typeSize);
|
||||
break;
|
||||
case(Endianness::MACHINE):
|
||||
default:
|
||||
memcpy(*buffer, value, typeSize);
|
||||
break;
|
||||
}
|
||||
*size += typeSize;
|
||||
(*buffer) += typeSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Type PoolRawAccess::getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
size_t PoolRawAccess::getSizeOfType() {
|
||||
return typeSize;
|
||||
}
|
||||
|
||||
size_t PoolRawAccess::getArraySize(){
|
||||
return arraySize;
|
||||
}
|
||||
|
||||
uint32_t PoolRawAccess::getDataPoolId() const {
|
||||
return dataPoolId;
|
||||
}
|
||||
|
||||
PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
|
||||
return readWriteMode;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer,
|
||||
size_t setSize) {
|
||||
if (typeSize == setSize) {
|
||||
EndianConverter::convertBigEndian(value, buffer, typeSize);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: "
|
||||
"Internal" << (uint32_t) typeSize << ", Requested: " << setSize
|
||||
<< std::endl;
|
||||
return INCORRECT_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
bool PoolRawAccess::isValid() const {
|
||||
if (valid != INVALID)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void PoolRawAccess::setValid(bool valid) {
|
||||
this->valid = valid;
|
||||
}
|
||||
|
||||
size_t PoolRawAccess::getSizeTillEnd() const {
|
||||
return sizeTillEnd;
|
||||
}
|
||||
|
||||
|
||||
size_t PoolRawAccess::getSerializedSize() const {
|
||||
return typeSize;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) {
|
||||
|
||||
if (*size >= typeSize) {
|
||||
switch(streamEndianness) {
|
||||
case(Endianness::BIG):
|
||||
EndianConverter::convertBigEndian(value, *buffer, typeSize);
|
||||
break;
|
||||
case(Endianness::LITTLE):
|
||||
EndianConverter::convertLittleEndian(value, *buffer, typeSize);
|
||||
break;
|
||||
case(Endianness::MACHINE):
|
||||
default:
|
||||
memcpy(value, *buffer, typeSize);
|
||||
break;
|
||||
}
|
||||
*size -= typeSize;
|
||||
*buffer += typeSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
}
|
||||
#include "../datapoolglob/GlobalDataPool.h"
|
||||
#include "../datapoolglob/PoolRawAccess.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../serialize/EndianConverter.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
|
||||
DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) :
|
||||
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false),
|
||||
type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0),
|
||||
readWriteMode(setReadWriteMode) {
|
||||
memset(value, 0, sizeof(value));
|
||||
if (dataSet != nullptr) {
|
||||
dataSet->registerVariable(this);
|
||||
}
|
||||
}
|
||||
|
||||
PoolRawAccess::~PoolRawAccess() {}
|
||||
|
||||
ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) {
|
||||
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = readWithoutLock();
|
||||
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
|
||||
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::readWithoutLock() {
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId);
|
||||
if (readOut != nullptr) {
|
||||
result = handleReadOut(readOut);
|
||||
if(result == RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result = READ_ENTRY_NON_EXISTENT;
|
||||
}
|
||||
handleReadError(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) {
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
valid = readOut->getValid();
|
||||
if (readOut->getSize() > arrayEntry) {
|
||||
arraySize = readOut->getSize();
|
||||
typeSize = readOut->getByteSize() / readOut->getSize();
|
||||
type = readOut->getType();
|
||||
if (typeSize <= sizeof(value)) {
|
||||
uint16_t arrayPosition = arrayEntry * typeSize;
|
||||
sizeTillEnd = readOut->getByteSize() - arrayPosition;
|
||||
uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition];
|
||||
memcpy(value, ptr, typeSize);
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
result = READ_TYPE_TOO_LARGE;
|
||||
}
|
||||
} else {
|
||||
//debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
|
||||
result = READ_INDEX_TOO_LARGE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PoolRawAccess::handleReadError(ReturnValue_t result) {
|
||||
sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
|
||||
<< std::dec << " failed, ";
|
||||
if(result == READ_TYPE_TOO_LARGE) {
|
||||
sif::error << "type too large." << std::endl;
|
||||
}
|
||||
else if(result == READ_INDEX_TOO_LARGE) {
|
||||
sif::error << "index too large." << std::endl;
|
||||
}
|
||||
else if(result == READ_ENTRY_NON_EXISTENT) {
|
||||
sif::error << "entry does not exist." << std::endl;
|
||||
}
|
||||
|
||||
valid = INVALID;
|
||||
typeSize = 0;
|
||||
sizeTillEnd = 0;
|
||||
memset(value, 0, sizeof(value));
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) {
|
||||
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = commitWithoutLock();
|
||||
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
|
||||
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
|
||||
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::commitWithoutLock() {
|
||||
PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId);
|
||||
if ((write_back != NULL) && (readWriteMode != VAR_READ)) {
|
||||
write_back->setValid(valid);
|
||||
uint8_t array_position = arrayEntry * typeSize;
|
||||
uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position];
|
||||
memcpy(ptr, value, typeSize);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* PoolRawAccess::getEntry() {
|
||||
return value;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
|
||||
size_t* writtenBytes, size_t max_size) {
|
||||
uint8_t* data_ptr = getEntry();
|
||||
// debug << "PoolRawAccess::getEntry: Array position: " <<
|
||||
// index * size_of_type << " Size of T: " << (int)size_of_type <<
|
||||
// " ByteSize: " << byte_size << " Position: " << *size << std::endl;
|
||||
if (typeSize == 0)
|
||||
return DATA_POOL_ACCESS_FAILED;
|
||||
if (typeSize > max_size)
|
||||
return INCORRECT_SIZE;
|
||||
EndianConverter::convertBigEndian(buffer, data_ptr, typeSize);
|
||||
*writtenBytes = typeSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
|
||||
size_t maxSize, Endianness streamEndianness) const {
|
||||
if (typeSize + *size <= maxSize) {
|
||||
switch(streamEndianness) {
|
||||
case(Endianness::BIG):
|
||||
EndianConverter::convertBigEndian(*buffer, value, typeSize);
|
||||
break;
|
||||
case(Endianness::LITTLE):
|
||||
EndianConverter::convertLittleEndian(*buffer, value, typeSize);
|
||||
break;
|
||||
case(Endianness::MACHINE):
|
||||
default:
|
||||
memcpy(*buffer, value, typeSize);
|
||||
break;
|
||||
}
|
||||
*size += typeSize;
|
||||
(*buffer) += typeSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Type PoolRawAccess::getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
size_t PoolRawAccess::getSizeOfType() {
|
||||
return typeSize;
|
||||
}
|
||||
|
||||
size_t PoolRawAccess::getArraySize(){
|
||||
return arraySize;
|
||||
}
|
||||
|
||||
uint32_t PoolRawAccess::getDataPoolId() const {
|
||||
return dataPoolId;
|
||||
}
|
||||
|
||||
PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
|
||||
return readWriteMode;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer,
|
||||
size_t setSize) {
|
||||
if (typeSize == setSize) {
|
||||
EndianConverter::convertBigEndian(value, buffer, typeSize);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: "
|
||||
"Internal" << (uint32_t) typeSize << ", Requested: " << setSize
|
||||
<< std::endl;
|
||||
return INCORRECT_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
bool PoolRawAccess::isValid() const {
|
||||
if (valid != INVALID)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void PoolRawAccess::setValid(bool valid) {
|
||||
this->valid = valid;
|
||||
}
|
||||
|
||||
size_t PoolRawAccess::getSizeTillEnd() const {
|
||||
return sizeTillEnd;
|
||||
}
|
||||
|
||||
|
||||
size_t PoolRawAccess::getSerializedSize() const {
|
||||
return typeSize;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) {
|
||||
|
||||
if (*size >= typeSize) {
|
||||
switch(streamEndianness) {
|
||||
case(Endianness::BIG):
|
||||
EndianConverter::convertBigEndian(value, *buffer, typeSize);
|
||||
break;
|
||||
case(Endianness::LITTLE):
|
||||
EndianConverter::convertLittleEndian(value, *buffer, typeSize);
|
||||
break;
|
||||
case(Endianness::MACHINE):
|
||||
default:
|
||||
memcpy(value, *buffer, typeSize);
|
||||
break;
|
||||
}
|
||||
*size -= typeSize;
|
||||
*buffer += typeSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
else {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
}
|
||||
|
@ -1,220 +1,220 @@
|
||||
#ifndef POOLRAWACCESS_H_
|
||||
#define POOLRAWACCESS_H_
|
||||
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapool/PoolEntryIF.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/globalfunctions/Type.h>
|
||||
|
||||
/**
|
||||
* @brief This class allows accessing Data Pool variables as raw bytes.
|
||||
* @details
|
||||
* This is necessary to have an access method for HK data, as the PID's alone
|
||||
* do not provide type information. Please note that the the raw pool access
|
||||
* read() and commit() calls are not thread-safe.
|
||||
*
|
||||
* Please supply a data set and use the data set read(), commit() calls for
|
||||
* thread-safe data pool access.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
|
||||
public:
|
||||
/**
|
||||
* This constructor is used to access a data pool entry with a
|
||||
* given ID if the target type is not known. A DataSet object is supplied
|
||||
* and the data pool entry with the given ID is registered to that data set.
|
||||
* Please note that a pool raw access buffer only has a buffer
|
||||
* with a size of double. As such, for vector entries which have
|
||||
* @param data_pool_id Target data pool entry ID
|
||||
* @param arrayEntry
|
||||
* @param data_set Dataset to register data pool entry to
|
||||
* @param setReadWriteMode
|
||||
* @param registerVectors If set to true, the constructor checks if
|
||||
* there are multiple vector entries to registers
|
||||
* and registers all of them recursively into the data_set
|
||||
*
|
||||
*/
|
||||
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
|
||||
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
|
||||
PoolVariableIF::VAR_READ);
|
||||
|
||||
/**
|
||||
* @brief This operation returns a pointer to the entry fetched.
|
||||
* @details Return pointer to the buffer containing the raw data
|
||||
* Size and number of data can be retrieved by other means.
|
||||
*/
|
||||
uint8_t* getEntry();
|
||||
/**
|
||||
* @brief This operation returns the fetched entry from the data pool and
|
||||
* flips the bytes, if necessary.
|
||||
* @details It makes use of the getEntry call of this function, but additionally flips the
|
||||
* bytes to big endian, which is the default for external communication (as House-
|
||||
* keeping telemetry). To achieve this, the data is copied directly to the passed
|
||||
* buffer, if it fits in the given max_size.
|
||||
* @param buffer A pointer to a buffer to write to
|
||||
* @param writtenBytes The number of bytes written is returned with this value.
|
||||
* @param max_size The maximum size that the function may write to buffer.
|
||||
* @return - @c RETURN_OK if entry could be acquired
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size,
|
||||
size_t maxSize);
|
||||
|
||||
/**
|
||||
* @brief Serialize raw pool entry into provided buffer directly
|
||||
* @param buffer Provided buffer. Raw pool data will be copied here
|
||||
* @param size [out] Increment provided size value by serialized size
|
||||
* @param max_size Maximum allowed serialization size
|
||||
* @param bigEndian Specify endianess
|
||||
* @return - @c RETURN_OK if serialization was successfull
|
||||
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
|
||||
*/
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
|
||||
size_t maxSize, Endianness streamEndianness) const override;
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* With this method, the content can be set from a big endian buffer safely.
|
||||
* @param buffer Pointer to the data to set
|
||||
* @param size Size of the data to write. Must fit this->size.
|
||||
* @return - @c RETURN_OK on success
|
||||
* - @c RETURN_FAILED on failure
|
||||
*/
|
||||
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
|
||||
size_t setSize);
|
||||
/**
|
||||
* @brief This operation returns the type of the entry currently stored.
|
||||
*/
|
||||
Type getType();
|
||||
/**
|
||||
* @brief This operation returns the size of the entry currently stored.
|
||||
*/
|
||||
size_t getSizeOfType();
|
||||
/**
|
||||
*
|
||||
* @return the size of the datapool array
|
||||
*/
|
||||
size_t getArraySize();
|
||||
/**
|
||||
* @brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
|
||||
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
|
||||
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
|
||||
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
|
||||
static const uint8_t RAW_MAX_SIZE = sizeof(double);
|
||||
uint8_t value[RAW_MAX_SIZE];
|
||||
|
||||
|
||||
/**
|
||||
* @brief The classes destructor is empty. If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~PoolRawAccess();
|
||||
|
||||
/**
|
||||
* This method returns if the variable is read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const;
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
void setValid(bool valid);
|
||||
/**
|
||||
* Getter for the remaining size.
|
||||
*/
|
||||
size_t getSizeTillEnd() const;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the value from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the global data pool and copies the value and the valid
|
||||
* information to its local attributes. In case of a failure (wrong type or
|
||||
* pool id not found), the variable is set to zero and invalid.
|
||||
* The call is protected by a lock of the global data pool.
|
||||
* @return -@c RETURN_OK Read successfull
|
||||
* -@c READ_TYPE_TOO_LARGE
|
||||
* -@c READ_INDEX_TOO_LARGE
|
||||
* -@c READ_ENTRY_NON_EXISTENT
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call writes back the variable's value to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the valid flag is automatically set to "valid".
|
||||
* The call is protected by a lock of the global data pool.
|
||||
*
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
|
||||
void handleReadError(ReturnValue_t result);
|
||||
private:
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls, the data pool id
|
||||
* is stored.
|
||||
*/
|
||||
uint32_t dataPoolId;
|
||||
/**
|
||||
* @brief The array entry that is fetched from the data pool.
|
||||
*/
|
||||
uint8_t arrayEntry;
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool is copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief This value contains the type of the data pool entry.
|
||||
*/
|
||||
Type type;
|
||||
/**
|
||||
* @brief This value contains the size of the data pool entry type in bytes.
|
||||
*/
|
||||
size_t typeSize;
|
||||
/**
|
||||
* The size of the DP array (single values return 1)
|
||||
*/
|
||||
size_t arraySize;
|
||||
/**
|
||||
* The size (in bytes) from the selected entry till the end of this DataPool variable.
|
||||
*/
|
||||
size_t sizeTillEnd;
|
||||
/**
|
||||
* @brief The information whether the class is read-write or read-only is stored here.
|
||||
*/
|
||||
ReadWriteMode_t readWriteMode;
|
||||
};
|
||||
|
||||
#endif /* POOLRAWACCESS_H_ */
|
||||
#ifndef POOLRAWACCESS_H_
|
||||
#define POOLRAWACCESS_H_
|
||||
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapool/PoolEntryIF.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../globalfunctions/Type.h"
|
||||
|
||||
/**
|
||||
* @brief This class allows accessing Data Pool variables as raw bytes.
|
||||
* @details
|
||||
* This is necessary to have an access method for HK data, as the PID's alone
|
||||
* do not provide type information. Please note that the the raw pool access
|
||||
* read() and commit() calls are not thread-safe.
|
||||
*
|
||||
* Please supply a data set and use the data set read(), commit() calls for
|
||||
* thread-safe data pool access.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
|
||||
public:
|
||||
/**
|
||||
* This constructor is used to access a data pool entry with a
|
||||
* given ID if the target type is not known. A DataSet object is supplied
|
||||
* and the data pool entry with the given ID is registered to that data set.
|
||||
* Please note that a pool raw access buffer only has a buffer
|
||||
* with a size of double. As such, for vector entries which have
|
||||
* @param data_pool_id Target data pool entry ID
|
||||
* @param arrayEntry
|
||||
* @param data_set Dataset to register data pool entry to
|
||||
* @param setReadWriteMode
|
||||
* @param registerVectors If set to true, the constructor checks if
|
||||
* there are multiple vector entries to registers
|
||||
* and registers all of them recursively into the data_set
|
||||
*
|
||||
*/
|
||||
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
|
||||
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
|
||||
PoolVariableIF::VAR_READ);
|
||||
|
||||
/**
|
||||
* @brief This operation returns a pointer to the entry fetched.
|
||||
* @details Return pointer to the buffer containing the raw data
|
||||
* Size and number of data can be retrieved by other means.
|
||||
*/
|
||||
uint8_t* getEntry();
|
||||
/**
|
||||
* @brief This operation returns the fetched entry from the data pool and
|
||||
* flips the bytes, if necessary.
|
||||
* @details It makes use of the getEntry call of this function, but additionally flips the
|
||||
* bytes to big endian, which is the default for external communication (as House-
|
||||
* keeping telemetry). To achieve this, the data is copied directly to the passed
|
||||
* buffer, if it fits in the given max_size.
|
||||
* @param buffer A pointer to a buffer to write to
|
||||
* @param writtenBytes The number of bytes written is returned with this value.
|
||||
* @param max_size The maximum size that the function may write to buffer.
|
||||
* @return - @c RETURN_OK if entry could be acquired
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size,
|
||||
size_t maxSize);
|
||||
|
||||
/**
|
||||
* @brief Serialize raw pool entry into provided buffer directly
|
||||
* @param buffer Provided buffer. Raw pool data will be copied here
|
||||
* @param size [out] Increment provided size value by serialized size
|
||||
* @param max_size Maximum allowed serialization size
|
||||
* @param bigEndian Specify endianess
|
||||
* @return - @c RETURN_OK if serialization was successfull
|
||||
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
|
||||
*/
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
|
||||
size_t maxSize, Endianness streamEndianness) const override;
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* With this method, the content can be set from a big endian buffer safely.
|
||||
* @param buffer Pointer to the data to set
|
||||
* @param size Size of the data to write. Must fit this->size.
|
||||
* @return - @c RETURN_OK on success
|
||||
* - @c RETURN_FAILED on failure
|
||||
*/
|
||||
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
|
||||
size_t setSize);
|
||||
/**
|
||||
* @brief This operation returns the type of the entry currently stored.
|
||||
*/
|
||||
Type getType();
|
||||
/**
|
||||
* @brief This operation returns the size of the entry currently stored.
|
||||
*/
|
||||
size_t getSizeOfType();
|
||||
/**
|
||||
*
|
||||
* @return the size of the datapool array
|
||||
*/
|
||||
size_t getArraySize();
|
||||
/**
|
||||
* @brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
uint32_t getDataPoolId() const;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
|
||||
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
|
||||
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
|
||||
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
|
||||
static const uint8_t RAW_MAX_SIZE = sizeof(double);
|
||||
uint8_t value[RAW_MAX_SIZE];
|
||||
|
||||
|
||||
/**
|
||||
* @brief The classes destructor is empty. If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~PoolRawAccess();
|
||||
|
||||
/**
|
||||
* This method returns if the variable is read-write or read-only.
|
||||
*/
|
||||
ReadWriteMode_t getReadWriteMode() const;
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
void setValid(bool valid);
|
||||
/**
|
||||
* Getter for the remaining size.
|
||||
*/
|
||||
size_t getSizeTillEnd() const;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the value from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the global data pool and copies the value and the valid
|
||||
* information to its local attributes. In case of a failure (wrong type or
|
||||
* pool id not found), the variable is set to zero and invalid.
|
||||
* The call is protected by a lock of the global data pool.
|
||||
* @return -@c RETURN_OK Read successfull
|
||||
* -@c READ_TYPE_TOO_LARGE
|
||||
* -@c READ_INDEX_TOO_LARGE
|
||||
* -@c READ_ENTRY_NON_EXISTENT
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call writes back the variable's value to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the valid flag is automatically set to "valid".
|
||||
* The call is protected by a lock of the global data pool.
|
||||
*
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
|
||||
void handleReadError(ReturnValue_t result);
|
||||
private:
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls, the data pool id
|
||||
* is stored.
|
||||
*/
|
||||
uint32_t dataPoolId;
|
||||
/**
|
||||
* @brief The array entry that is fetched from the data pool.
|
||||
*/
|
||||
uint8_t arrayEntry;
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool is copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief This value contains the type of the data pool entry.
|
||||
*/
|
||||
Type type;
|
||||
/**
|
||||
* @brief This value contains the size of the data pool entry type in bytes.
|
||||
*/
|
||||
size_t typeSize;
|
||||
/**
|
||||
* The size of the DP array (single values return 1)
|
||||
*/
|
||||
size_t arraySize;
|
||||
/**
|
||||
* The size (in bytes) from the selected entry till the end of this DataPool variable.
|
||||
*/
|
||||
size_t sizeTillEnd;
|
||||
/**
|
||||
* @brief The information whether the class is read-write or read-only is stored here.
|
||||
*/
|
||||
ReadWriteMode_t readWriteMode;
|
||||
};
|
||||
|
||||
#endif /* POOLRAWACCESS_H_ */
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_
|
||||
#include <framework/datapool/PoolEntryIF.h>
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
#include <framework/housekeeping/HousekeepingMessage.h>
|
||||
#include "../datapool/PoolEntryIF.h"
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
#include "../housekeeping/HousekeepingMessage.h"
|
||||
#include <map>
|
||||
|
||||
class LocalDataPoolManager;
|
||||
|
@ -1,10 +1,9 @@
|
||||
#include <framework/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <framework/datapoollocal/LocalPoolDataSetBase.h>
|
||||
#include <framework/housekeeping/AcceptsHkPacketsIF.h>
|
||||
#include <framework/housekeeping/HousekeepingPacketDownlink.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
#include <framework/ipc/MutexHelper.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../datapoollocal/LocalDataSet.h"
|
||||
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
@ -264,7 +263,7 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) {
|
||||
uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics,
|
||||
float collectionIntervalSeconds) {
|
||||
if(isDiagnostics) {
|
||||
return std::ceil(collectionIntervalSeconds/diagnosticMinimumInterval);
|
||||
return std::ceil(collectionIntervalSeconds/diagnosticMinimumInterval);
|
||||
}
|
||||
else {
|
||||
return std::ceil(collectionIntervalSeconds/regularMinimumInterval);
|
||||
|
@ -1,21 +1,21 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
|
||||
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include "../housekeeping/HousekeepingPacketDownlink.h"
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
|
||||
#include <framework/housekeeping/HousekeepingMessage.h>
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/datapoollocal/HasLocalDataPoolIF.h>
|
||||
#include <framework/housekeeping/HousekeepingPacketDownlink.h>
|
||||
#include <framework/ipc/CommandMessage.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
#include <framework/ipc/MutexHelper.h>
|
||||
#include "../housekeeping/HousekeepingMessage.h"
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
||||
#include "../ipc/CommandMessage.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../ipc/MutexHelper.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class LocalPoolDataSetBase;
|
||||
class LocalDataSetBase;
|
||||
|
||||
/**
|
||||
* @brief This class is the managing instance for local data pool.
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <framework/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <framework/datapoollocal/LocalDataSet.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include "LocalDataSet.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_
|
||||
#include <framework/datapoollocal/LocalPoolDataSetBase.h>
|
||||
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
||||
#include <vector>
|
||||
|
||||
class LocalDataSet: public LocalPoolDataSetBase {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <framework/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <framework/datapoollocal/LocalPoolDataSetBase.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapool/PoolDataSetBase.h>
|
||||
#include <framework/datapoollocal/HasLocalDataPoolIF.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapool/PoolDataSetBase.h"
|
||||
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
|
||||
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapoollocal/HasLocalDataPoolIF.h>
|
||||
#include <framework/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapoollocal/HasLocalDataPoolIF.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
|
||||
/**
|
||||
* @brief Local Pool Variable class which is used to access the local pools.
|
||||
@ -155,7 +155,7 @@ private:
|
||||
LocalDataPoolManager* hkManager;
|
||||
};
|
||||
|
||||
#include <framework/datapoollocal/LocalPoolVariable.tpp>
|
||||
#include "LocalPoolVariable.tpp"
|
||||
|
||||
template<class T>
|
||||
using lp_var_t = LocalPoolVar<T>;
|
||||
|
@ -1,200 +1,200 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
|
||||
|
||||
#include <framework/datapool/DataSetIF.h>
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/datapoollocal/LocalDataPoolManager.h>
|
||||
#include <framework/serialize/SerializeAdapter.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is the access class for array-type data pool entries.
|
||||
* @details
|
||||
* To ensure safe usage of the data pool, operation is not done directly on the
|
||||
* data pool entries, but on local copies. This class provides simple type-
|
||||
* and length-safe access to vector-style data pool entries (i.e. entries with
|
||||
* length > 1). The class can be instantiated as read-write and read only.
|
||||
*
|
||||
* It provides a commit-and-roll-back semantic, which means that no array
|
||||
* entry in the data pool is changed until the commit call is executed.
|
||||
* There are two template parameters:
|
||||
* @tparam T
|
||||
* This template parameter specifies the data type of an array entry. Currently,
|
||||
* all plain data types are supported, but in principle any type is possible.
|
||||
* @tparam vector_size
|
||||
* This template parameter specifies the vector size of this entry. Using a
|
||||
* template parameter for this is not perfect, but avoids
|
||||
* dynamic memory allocation.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template<typename T, uint16_t vectorSize>
|
||||
class LocalPoolVector: public PoolVariableIF, public HasReturnvaluesIF {
|
||||
public:
|
||||
LocalPoolVector() = delete;
|
||||
/**
|
||||
* This constructor is used by the data creators to have pool variable
|
||||
* instances which can also be stored in datasets.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
|
||||
DataSetIF* dataSet = nullptr);
|
||||
|
||||
/**
|
||||
* This constructor is used by data users like controllers to have
|
||||
* access to the local pool variables of data creators by supplying
|
||||
* the respective creator object ID.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(lp_id_t poolId, object_id_t poolOwner,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
|
||||
DataSetIF* dataSet = nullptr);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details
|
||||
* The user can work on this attribute just like he would on a local
|
||||
* array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~LocalPoolVector() {};
|
||||
/**
|
||||
* @brief The operation returns the number of array entries
|
||||
* in this variable.
|
||||
*/
|
||||
uint8_t getSize() {
|
||||
return vectorSize;
|
||||
}
|
||||
|
||||
uint32_t getDataPoolId() const override;
|
||||
/**
|
||||
* @brief This operation sets the data pool ID of the variable.
|
||||
* @details
|
||||
* The method is necessary to set id's of data pool member variables
|
||||
* with bad initialization.
|
||||
*/
|
||||
void setDataPoolId(uint32_t poolId);
|
||||
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
pool_rwm_t getReadWriteMode() const;
|
||||
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const override;
|
||||
void setValid(bool valid) override;
|
||||
uint8_t getValid() const;
|
||||
|
||||
T& operator [](int i);
|
||||
const T &operator [](int i) const;
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndiannes) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the data pool and copies all array values and the valid
|
||||
* information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the local valid flag is written back as well.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls,
|
||||
* the data pool id is stored.
|
||||
*/
|
||||
uint32_t localPoolId;
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool
|
||||
* is copied to this attribute.
|
||||
*/
|
||||
bool valid;
|
||||
/**
|
||||
* @brief The information whether the class is read-write or
|
||||
* read-only is stored here.
|
||||
*/
|
||||
ReadWriteMode_t readWriteMode;
|
||||
//! @brief Pointer to the class which manages the HK pool.
|
||||
LocalDataPoolManager* hkManager;
|
||||
|
||||
// std::ostream is the type for object std::cout
|
||||
template <typename U, uint16_t otherSize>
|
||||
friend std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVector<U, otherSize> &var);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#include <framework/datapoollocal/LocalPoolVector.tpp>
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
using lp_vec_t = LocalPoolVector<T, vectorSize>;
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
|
||||
|
||||
#include "../datapool/DataSetIF.h"
|
||||
#include "../datapool/PoolEntry.h"
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../serialize/SerializeAdapter.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is the access class for array-type data pool entries.
|
||||
* @details
|
||||
* To ensure safe usage of the data pool, operation is not done directly on the
|
||||
* data pool entries, but on local copies. This class provides simple type-
|
||||
* and length-safe access to vector-style data pool entries (i.e. entries with
|
||||
* length > 1). The class can be instantiated as read-write and read only.
|
||||
*
|
||||
* It provides a commit-and-roll-back semantic, which means that no array
|
||||
* entry in the data pool is changed until the commit call is executed.
|
||||
* There are two template parameters:
|
||||
* @tparam T
|
||||
* This template parameter specifies the data type of an array entry. Currently,
|
||||
* all plain data types are supported, but in principle any type is possible.
|
||||
* @tparam vector_size
|
||||
* This template parameter specifies the vector size of this entry. Using a
|
||||
* template parameter for this is not perfect, but avoids
|
||||
* dynamic memory allocation.
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template<typename T, uint16_t vectorSize>
|
||||
class LocalPoolVector: public PoolVariableIF, public HasReturnvaluesIF {
|
||||
public:
|
||||
LocalPoolVector() = delete;
|
||||
/**
|
||||
* This constructor is used by the data creators to have pool variable
|
||||
* instances which can also be stored in datasets.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
|
||||
DataSetIF* dataSet = nullptr);
|
||||
|
||||
/**
|
||||
* This constructor is used by data users like controllers to have
|
||||
* access to the local pool variables of data creators by supplying
|
||||
* the respective creator object ID.
|
||||
* It does not fetch the current value from the data pool. This is performed
|
||||
* by the read() operation (which is not thread-safe).
|
||||
* Datasets can be used to access local pool entires in a thread-safe way.
|
||||
* @param poolId ID of the local pool entry.
|
||||
* @param hkOwner Pointer of the owner. This will generally be the calling
|
||||
* class itself which passes "this".
|
||||
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
||||
* @param dataSet The data set in which the variable shall register itself.
|
||||
* If nullptr, the variable is not registered.
|
||||
*/
|
||||
LocalPoolVector(lp_id_t poolId, object_id_t poolOwner,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
|
||||
DataSetIF* dataSet = nullptr);
|
||||
|
||||
/**
|
||||
* @brief This is the local copy of the data pool entry.
|
||||
* @details
|
||||
* The user can work on this attribute just like he would on a local
|
||||
* array of this type.
|
||||
*/
|
||||
T value[vectorSize];
|
||||
/**
|
||||
* @brief The classes destructor is empty.
|
||||
* @details If commit() was not called, the local value is
|
||||
* discarded and not written back to the data pool.
|
||||
*/
|
||||
~LocalPoolVector() {};
|
||||
/**
|
||||
* @brief The operation returns the number of array entries
|
||||
* in this variable.
|
||||
*/
|
||||
uint8_t getSize() {
|
||||
return vectorSize;
|
||||
}
|
||||
|
||||
uint32_t getDataPoolId() const override;
|
||||
/**
|
||||
* @brief This operation sets the data pool ID of the variable.
|
||||
* @details
|
||||
* The method is necessary to set id's of data pool member variables
|
||||
* with bad initialization.
|
||||
*/
|
||||
void setDataPoolId(uint32_t poolId);
|
||||
|
||||
/**
|
||||
* This method returns if the variable is write-only, read-write or read-only.
|
||||
*/
|
||||
pool_rwm_t getReadWriteMode() const;
|
||||
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is returned.
|
||||
*/
|
||||
bool isValid() const override;
|
||||
void setValid(bool valid) override;
|
||||
uint8_t getValid() const;
|
||||
|
||||
T& operator [](int i);
|
||||
const T &operator [](int i) const;
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||
const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndiannes) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* @brief This is a call to read the array's values
|
||||
* from the global data pool.
|
||||
* @details
|
||||
* When executed, this operation tries to fetch the pool entry with matching
|
||||
* data pool id from the data pool and copies all array values and the valid
|
||||
* information to its local attributes.
|
||||
* In case of a failure (wrong type, size or pool id not found), the
|
||||
* variable is set to zero and invalid.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
/**
|
||||
* @brief The commit call copies the array values back to the data pool.
|
||||
* @details
|
||||
* It checks type and size, as well as if the variable is writable. If so,
|
||||
* the value is copied and the local valid flag is written back as well.
|
||||
* The read call is protected with a lock.
|
||||
* It is recommended to use DataSets to read and commit multiple variables
|
||||
* at once to avoid the overhead of unnecessary lock und unlock operations.
|
||||
*/
|
||||
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Like #read, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t readWithoutLock() override;
|
||||
/**
|
||||
* @brief Like #commit, but without a lock protection of the global pool.
|
||||
* @details
|
||||
* The operation does NOT provide any mutual exclusive protection by itself.
|
||||
* This can be used if the lock is handled externally to avoid the overhead
|
||||
* of consecutive lock und unlock operations.
|
||||
* Declared protected to discourage free public usage.
|
||||
*/
|
||||
ReturnValue_t commitWithoutLock() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief To access the correct data pool entry on read and commit calls,
|
||||
* the data pool id is stored.
|
||||
*/
|
||||
uint32_t localPoolId;
|
||||
/**
|
||||
* @brief The valid information as it was stored in the data pool
|
||||
* is copied to this attribute.
|
||||
*/
|
||||
bool valid;
|
||||
/**
|
||||
* @brief The information whether the class is read-write or
|
||||
* read-only is stored here.
|
||||
*/
|
||||
ReadWriteMode_t readWriteMode;
|
||||
//! @brief Pointer to the class which manages the HK pool.
|
||||
LocalDataPoolManager* hkManager;
|
||||
|
||||
// std::ostream is the type for object std::cout
|
||||
template <typename U, uint16_t otherSize>
|
||||
friend std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVector<U, otherSize> &var);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#include "../datapoollocal/LocalPoolVector.tpp"
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
using lp_vec_t = LocalPoolVector<T, vectorSize>;
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <framework/datapoollocal/SharedLocalDataSet.h>
|
||||
#include "SharedLocalDataSet.h"
|
||||
|
||||
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, object_id_t owner,
|
||||
const size_t maxSize): SystemObject(objectId),
|
||||
|
@ -1,8 +1,8 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
|
||||
#include <framework/datapool/SharedDataSetIF.h>
|
||||
#include <framework/datapoollocal/LocalPoolDataSetBase.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include "../datapool/SharedDataSetIF.h"
|
||||
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||
#define FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||
#include <framework/datapoollocal/LocalPoolDataSetBase.h>
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include "LocalPoolDataSetBase.h"
|
||||
#include "../objectmanager/SystemObjectIF.h"
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
|
@ -1,19 +1,19 @@
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
|
||||
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
|
||||
/**
|
||||
* This interface is used by the device handler to send a device response
|
||||
* to the queue ID, which is returned in the implemented abstract method.
|
||||
*/
|
||||
class AcceptsDeviceResponsesIF {
|
||||
public:
|
||||
/**
|
||||
* Default empty virtual destructor.
|
||||
*/
|
||||
virtual ~AcceptsDeviceResponsesIF() {}
|
||||
virtual MessageQueueId_t getDeviceQueue() = 0;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ */
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
|
||||
|
||||
#include "../ipc/MessageQueueSenderIF.h"
|
||||
|
||||
/**
|
||||
* This interface is used by the device handler to send a device response
|
||||
* to the queue ID, which is returned in the implemented abstract method.
|
||||
*/
|
||||
class AcceptsDeviceResponsesIF {
|
||||
public:
|
||||
/**
|
||||
* Default empty virtual destructor.
|
||||
*/
|
||||
virtual ~AcceptsDeviceResponsesIF() {}
|
||||
virtual MessageQueueId_t getDeviceQueue() = 0;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ */
|
||||
|
@ -1,273 +1,273 @@
|
||||
#include <framework/devicehandlers/AssemblyBase.h>
|
||||
|
||||
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId,
|
||||
uint16_t commandQueueDepth) :
|
||||
SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
|
||||
internalState(STATE_NONE), recoveryState(RECOVERY_IDLE),
|
||||
recoveringDevice(childrenMap.end()), targetMode(MODE_OFF),
|
||||
targetSubmode(SUBMODE_NONE) {
|
||||
recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS);
|
||||
}
|
||||
|
||||
AssemblyBase::~AssemblyBase() {
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::handleCommandMessage(CommandMessage* message) {
|
||||
return handleHealthReply(message);
|
||||
}
|
||||
|
||||
void AssemblyBase::performChildOperation() {
|
||||
if (isInTransition()) {
|
||||
handleChildrenTransition();
|
||||
} else {
|
||||
handleChildrenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
doStartTransition(mode, submode);
|
||||
if (modeHelper.isForced()) {
|
||||
triggerEvent(FORCING_MODE, mode, submode);
|
||||
} else {
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||
targetMode = mode;
|
||||
targetSubmode = submode;
|
||||
internalState = STATE_SINGLE_STEP;
|
||||
ReturnValue_t result = commandChildren(mode, submode);
|
||||
if (result == NEED_SECOND_STEP) {
|
||||
internalState = STATE_NEED_SECOND_STEP;
|
||||
}
|
||||
}
|
||||
|
||||
bool AssemblyBase::isInTransition() {
|
||||
return (internalState != STATE_NONE) || (recoveryState != RECOVERY_IDLE);
|
||||
}
|
||||
|
||||
bool AssemblyBase::handleChildrenChanged() {
|
||||
if (childrenChangedMode) {
|
||||
ReturnValue_t result = checkChildrenState();
|
||||
if (result != RETURN_OK) {
|
||||
handleChildrenLostMode(result);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return handleChildrenChangedHealth();
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::handleChildrenLostMode(ReturnValue_t result) {
|
||||
triggerEvent(CANT_KEEP_MODE, mode, submode);
|
||||
startTransition(MODE_OFF, SUBMODE_NONE);
|
||||
}
|
||||
|
||||
bool AssemblyBase::handleChildrenChangedHealth() {
|
||||
auto iter = childrenMap.begin();
|
||||
for (; iter != childrenMap.end(); iter++) {
|
||||
if (iter->second.healthChanged) {
|
||||
iter->second.healthChanged = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter == childrenMap.end()) {
|
||||
return false;
|
||||
}
|
||||
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
||||
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
||||
triggerEvent(TRYING_RECOVERY);
|
||||
recoveryState = RECOVERY_STARTED;
|
||||
recoveringDevice = iter;
|
||||
doStartTransition(targetMode, targetSubmode);
|
||||
} else {
|
||||
triggerEvent(CHILD_CHANGED_HEALTH);
|
||||
doStartTransition(mode, submode);
|
||||
}
|
||||
if (modeHelper.isForced()) {
|
||||
triggerEvent(FORCING_MODE, targetMode, targetSubmode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssemblyBase::handleChildrenTransition() {
|
||||
if (commandsOutstanding <= 0) {
|
||||
switch (internalState) {
|
||||
case STATE_NEED_SECOND_STEP:
|
||||
internalState = STATE_SECOND_STEP;
|
||||
commandChildren(targetMode, targetSubmode);
|
||||
return;
|
||||
case STATE_OVERWRITE_HEALTH: {
|
||||
internalState = STATE_SINGLE_STEP;
|
||||
ReturnValue_t result = commandChildren(mode, submode);
|
||||
if (result == NEED_SECOND_STEP) {
|
||||
internalState = STATE_NEED_SECOND_STEP;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case STATE_NONE:
|
||||
//Valid state, used in recovery.
|
||||
case STATE_SINGLE_STEP:
|
||||
case STATE_SECOND_STEP:
|
||||
if (checkAndHandleRecovery()) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ReturnValue_t result = checkChildrenState();
|
||||
if (result == RETURN_OK) {
|
||||
handleModeReached();
|
||||
} else {
|
||||
handleModeTransitionFailed(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::handleModeReached() {
|
||||
internalState = STATE_NONE;
|
||||
setMode(targetMode, targetSubmode);
|
||||
}
|
||||
|
||||
void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
|
||||
//always accept transition to OFF, there is nothing we can do except sending an info event
|
||||
//In theory this should never happen, but we would risk an infinite loop otherwise
|
||||
if (targetMode == MODE_OFF) {
|
||||
triggerEvent(CHILD_PROBLEMS, result);
|
||||
internalState = STATE_NONE;
|
||||
setMode(targetMode, targetSubmode);
|
||||
} else {
|
||||
if (handleChildrenChangedHealth()) {
|
||||
//If any health change is pending, handle that first.
|
||||
return;
|
||||
}
|
||||
triggerEvent(MODE_TRANSITION_FAILED, result);
|
||||
startTransition(MODE_OFF, SUBMODE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo,
|
||||
HealthState health) {
|
||||
CommandMessage command;
|
||||
HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET,
|
||||
health);
|
||||
if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) {
|
||||
commandsOutstanding++;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkChildrenState() {
|
||||
if (targetMode == MODE_OFF) {
|
||||
return checkChildrenStateOff();
|
||||
} else {
|
||||
return checkChildrenStateOn(targetMode, targetSubmode);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkChildrenStateOff() {
|
||||
for (const auto& childIter: childrenMap) {
|
||||
if (checkChildOff(childIter.first) != RETURN_OK) {
|
||||
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) {
|
||||
ChildInfo childInfo = childrenMap.find(objectId)->second;
|
||||
if (healthHelper.healthTable->isCommandable(objectId)) {
|
||||
if (childInfo.submode != SUBMODE_NONE) {
|
||||
return RETURN_FAILED;
|
||||
} else {
|
||||
if ((childInfo.mode != MODE_OFF)
|
||||
&& (childInfo.mode != DeviceHandlerIF::MODE_ERROR_ON)) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) {
|
||||
|
||||
//always accept transition to OFF
|
||||
if (mode == MODE_OFF) {
|
||||
if (submode != SUBMODE_NONE) {
|
||||
return INVALID_SUBMODE;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
if ((mode != MODE_ON) && (mode != DeviceHandlerIF::MODE_NORMAL)) {
|
||||
return INVALID_MODE;
|
||||
}
|
||||
|
||||
if (internalState != STATE_NONE) {
|
||||
return IN_TRANSITION;
|
||||
}
|
||||
|
||||
return isModeCombinationValid(mode, submode);
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
|
||||
if (message->getCommand() == HealthMessage::HEALTH_INFO) {
|
||||
HealthState health = HealthMessage::getHealth(message);
|
||||
if (health != EXTERNAL_CONTROL) {
|
||||
updateChildChangedHealth(message->getSender(), true);
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
if (message->getCommand() == HealthMessage::REPLY_HEALTH_SET
|
||||
|| (message->getCommand() == CommandMessage::REPLY_REJECTED
|
||||
&& message->getParameter2() == HealthMessage::HEALTH_SET)) {
|
||||
if (isInTransition()) {
|
||||
commandsOutstanding--;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
bool AssemblyBase::checkAndHandleRecovery() {
|
||||
switch (recoveryState) {
|
||||
case RECOVERY_STARTED:
|
||||
recoveryState = RECOVERY_WAIT;
|
||||
recoveryOffTimer.resetTimer();
|
||||
return true;
|
||||
case RECOVERY_WAIT:
|
||||
if (recoveryOffTimer.isBusy()) {
|
||||
return true;
|
||||
}
|
||||
triggerEvent(RECOVERY_STEP, 0);
|
||||
sendHealthCommand(recoveringDevice->second.commandQueue, HEALTHY);
|
||||
internalState = STATE_NONE;
|
||||
recoveryState = RECOVERY_ONGOING;
|
||||
//Don't check state!
|
||||
return true;
|
||||
case RECOVERY_ONGOING:
|
||||
triggerEvent(RECOVERY_STEP, 1);
|
||||
recoveryState = RECOVERY_ONGOING_2;
|
||||
recoveringDevice->second.healthChanged = false;
|
||||
//Device should be healthy again, so restart a transition.
|
||||
//Might be including second step, but that's already handled.
|
||||
doStartTransition(targetMode, targetSubmode);
|
||||
return true;
|
||||
case RECOVERY_ONGOING_2:
|
||||
triggerEvent(RECOVERY_DONE);
|
||||
//Now we're through, but not sure if it was successful.
|
||||
recoveryState = RECOVERY_IDLE;
|
||||
return false;
|
||||
case RECOVERY_IDLE:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::overwriteDeviceHealth(object_id_t objectId,
|
||||
HasHealthIF::HealthState oldHealth) {
|
||||
triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth);
|
||||
internalState = STATE_OVERWRITE_HEALTH;
|
||||
modeHelper.setForced(true);
|
||||
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
||||
}
|
||||
#include "../devicehandlers/AssemblyBase.h"
|
||||
|
||||
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId,
|
||||
uint16_t commandQueueDepth) :
|
||||
SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
|
||||
internalState(STATE_NONE), recoveryState(RECOVERY_IDLE),
|
||||
recoveringDevice(childrenMap.end()), targetMode(MODE_OFF),
|
||||
targetSubmode(SUBMODE_NONE) {
|
||||
recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS);
|
||||
}
|
||||
|
||||
AssemblyBase::~AssemblyBase() {
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::handleCommandMessage(CommandMessage* message) {
|
||||
return handleHealthReply(message);
|
||||
}
|
||||
|
||||
void AssemblyBase::performChildOperation() {
|
||||
if (isInTransition()) {
|
||||
handleChildrenTransition();
|
||||
} else {
|
||||
handleChildrenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
doStartTransition(mode, submode);
|
||||
if (modeHelper.isForced()) {
|
||||
triggerEvent(FORCING_MODE, mode, submode);
|
||||
} else {
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||
targetMode = mode;
|
||||
targetSubmode = submode;
|
||||
internalState = STATE_SINGLE_STEP;
|
||||
ReturnValue_t result = commandChildren(mode, submode);
|
||||
if (result == NEED_SECOND_STEP) {
|
||||
internalState = STATE_NEED_SECOND_STEP;
|
||||
}
|
||||
}
|
||||
|
||||
bool AssemblyBase::isInTransition() {
|
||||
return (internalState != STATE_NONE) || (recoveryState != RECOVERY_IDLE);
|
||||
}
|
||||
|
||||
bool AssemblyBase::handleChildrenChanged() {
|
||||
if (childrenChangedMode) {
|
||||
ReturnValue_t result = checkChildrenState();
|
||||
if (result != RETURN_OK) {
|
||||
handleChildrenLostMode(result);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return handleChildrenChangedHealth();
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::handleChildrenLostMode(ReturnValue_t result) {
|
||||
triggerEvent(CANT_KEEP_MODE, mode, submode);
|
||||
startTransition(MODE_OFF, SUBMODE_NONE);
|
||||
}
|
||||
|
||||
bool AssemblyBase::handleChildrenChangedHealth() {
|
||||
auto iter = childrenMap.begin();
|
||||
for (; iter != childrenMap.end(); iter++) {
|
||||
if (iter->second.healthChanged) {
|
||||
iter->second.healthChanged = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iter == childrenMap.end()) {
|
||||
return false;
|
||||
}
|
||||
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
||||
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
||||
triggerEvent(TRYING_RECOVERY);
|
||||
recoveryState = RECOVERY_STARTED;
|
||||
recoveringDevice = iter;
|
||||
doStartTransition(targetMode, targetSubmode);
|
||||
} else {
|
||||
triggerEvent(CHILD_CHANGED_HEALTH);
|
||||
doStartTransition(mode, submode);
|
||||
}
|
||||
if (modeHelper.isForced()) {
|
||||
triggerEvent(FORCING_MODE, targetMode, targetSubmode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssemblyBase::handleChildrenTransition() {
|
||||
if (commandsOutstanding <= 0) {
|
||||
switch (internalState) {
|
||||
case STATE_NEED_SECOND_STEP:
|
||||
internalState = STATE_SECOND_STEP;
|
||||
commandChildren(targetMode, targetSubmode);
|
||||
return;
|
||||
case STATE_OVERWRITE_HEALTH: {
|
||||
internalState = STATE_SINGLE_STEP;
|
||||
ReturnValue_t result = commandChildren(mode, submode);
|
||||
if (result == NEED_SECOND_STEP) {
|
||||
internalState = STATE_NEED_SECOND_STEP;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case STATE_NONE:
|
||||
//Valid state, used in recovery.
|
||||
case STATE_SINGLE_STEP:
|
||||
case STATE_SECOND_STEP:
|
||||
if (checkAndHandleRecovery()) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ReturnValue_t result = checkChildrenState();
|
||||
if (result == RETURN_OK) {
|
||||
handleModeReached();
|
||||
} else {
|
||||
handleModeTransitionFailed(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::handleModeReached() {
|
||||
internalState = STATE_NONE;
|
||||
setMode(targetMode, targetSubmode);
|
||||
}
|
||||
|
||||
void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
|
||||
//always accept transition to OFF, there is nothing we can do except sending an info event
|
||||
//In theory this should never happen, but we would risk an infinite loop otherwise
|
||||
if (targetMode == MODE_OFF) {
|
||||
triggerEvent(CHILD_PROBLEMS, result);
|
||||
internalState = STATE_NONE;
|
||||
setMode(targetMode, targetSubmode);
|
||||
} else {
|
||||
if (handleChildrenChangedHealth()) {
|
||||
//If any health change is pending, handle that first.
|
||||
return;
|
||||
}
|
||||
triggerEvent(MODE_TRANSITION_FAILED, result);
|
||||
startTransition(MODE_OFF, SUBMODE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo,
|
||||
HealthState health) {
|
||||
CommandMessage command;
|
||||
HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET,
|
||||
health);
|
||||
if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) {
|
||||
commandsOutstanding++;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkChildrenState() {
|
||||
if (targetMode == MODE_OFF) {
|
||||
return checkChildrenStateOff();
|
||||
} else {
|
||||
return checkChildrenStateOn(targetMode, targetSubmode);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkChildrenStateOff() {
|
||||
for (const auto& childIter: childrenMap) {
|
||||
if (checkChildOff(childIter.first) != RETURN_OK) {
|
||||
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) {
|
||||
ChildInfo childInfo = childrenMap.find(objectId)->second;
|
||||
if (healthHelper.healthTable->isCommandable(objectId)) {
|
||||
if (childInfo.submode != SUBMODE_NONE) {
|
||||
return RETURN_FAILED;
|
||||
} else {
|
||||
if ((childInfo.mode != MODE_OFF)
|
||||
&& (childInfo.mode != DeviceHandlerIF::MODE_ERROR_ON)) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) {
|
||||
|
||||
//always accept transition to OFF
|
||||
if (mode == MODE_OFF) {
|
||||
if (submode != SUBMODE_NONE) {
|
||||
return INVALID_SUBMODE;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
if ((mode != MODE_ON) && (mode != DeviceHandlerIF::MODE_NORMAL)) {
|
||||
return INVALID_MODE;
|
||||
}
|
||||
|
||||
if (internalState != STATE_NONE) {
|
||||
return IN_TRANSITION;
|
||||
}
|
||||
|
||||
return isModeCombinationValid(mode, submode);
|
||||
}
|
||||
|
||||
ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
|
||||
if (message->getCommand() == HealthMessage::HEALTH_INFO) {
|
||||
HealthState health = HealthMessage::getHealth(message);
|
||||
if (health != EXTERNAL_CONTROL) {
|
||||
updateChildChangedHealth(message->getSender(), true);
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
if (message->getCommand() == HealthMessage::REPLY_HEALTH_SET
|
||||
|| (message->getCommand() == CommandMessage::REPLY_REJECTED
|
||||
&& message->getParameter2() == HealthMessage::HEALTH_SET)) {
|
||||
if (isInTransition()) {
|
||||
commandsOutstanding--;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
bool AssemblyBase::checkAndHandleRecovery() {
|
||||
switch (recoveryState) {
|
||||
case RECOVERY_STARTED:
|
||||
recoveryState = RECOVERY_WAIT;
|
||||
recoveryOffTimer.resetTimer();
|
||||
return true;
|
||||
case RECOVERY_WAIT:
|
||||
if (recoveryOffTimer.isBusy()) {
|
||||
return true;
|
||||
}
|
||||
triggerEvent(RECOVERY_STEP, 0);
|
||||
sendHealthCommand(recoveringDevice->second.commandQueue, HEALTHY);
|
||||
internalState = STATE_NONE;
|
||||
recoveryState = RECOVERY_ONGOING;
|
||||
//Don't check state!
|
||||
return true;
|
||||
case RECOVERY_ONGOING:
|
||||
triggerEvent(RECOVERY_STEP, 1);
|
||||
recoveryState = RECOVERY_ONGOING_2;
|
||||
recoveringDevice->second.healthChanged = false;
|
||||
//Device should be healthy again, so restart a transition.
|
||||
//Might be including second step, but that's already handled.
|
||||
doStartTransition(targetMode, targetSubmode);
|
||||
return true;
|
||||
case RECOVERY_ONGOING_2:
|
||||
triggerEvent(RECOVERY_DONE);
|
||||
//Now we're through, but not sure if it was successful.
|
||||
recoveryState = RECOVERY_IDLE;
|
||||
return false;
|
||||
case RECOVERY_IDLE:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyBase::overwriteDeviceHealth(object_id_t objectId,
|
||||
HasHealthIF::HealthState oldHealth) {
|
||||
triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth);
|
||||
internalState = STATE_OVERWRITE_HEALTH;
|
||||
modeHelper.setForced(true);
|
||||
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
||||
}
|
||||
|
@ -1,163 +1,163 @@
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
|
||||
|
||||
#include <framework/container/FixedArrayList.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
|
||||
/**
|
||||
* @brief Base class to implement reconfiguration and failure handling for
|
||||
* redundant devices by monitoring their modes health states.
|
||||
* @details
|
||||
* Documentation: Dissertation Baetz p.156, 157.
|
||||
*
|
||||
* This class reduces the complexity of controller components which would
|
||||
* otherwise be needed for the handling of redundant devices.
|
||||
*
|
||||
* The template class monitors mode and health state of its children
|
||||
* and checks availability of devices on every detected change.
|
||||
* AssemblyBase does not implement any redundancy logic by itself, but provides
|
||||
* adaptation points for implementations to do so. Since most monitoring
|
||||
* activities rely on mode and health state only and are therefore
|
||||
* generic, it is sufficient for subclasses to provide:
|
||||
*
|
||||
* 1. check logic when active-> checkChildrenStateOn
|
||||
* 2. transition logic to change the mode -> commandChildren
|
||||
*
|
||||
*/
|
||||
class AssemblyBase: public SubsystemBase {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE;
|
||||
static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03);
|
||||
static const ReturnValue_t CHILD_NOT_COMMANDABLE = MAKE_RETURN_CODE(0x04);
|
||||
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
|
||||
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE =
|
||||
MAKE_RETURN_CODE(0xa1);
|
||||
|
||||
AssemblyBase(object_id_t objectId, object_id_t parentId,
|
||||
uint16_t commandQueueDepth = 8);
|
||||
virtual ~AssemblyBase();
|
||||
|
||||
protected:
|
||||
|
||||
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
|
||||
// (or return internalState directly?)
|
||||
/**
|
||||
* Command children to reach [mode,submode] combination
|
||||
* Can be done by setting #commandsOutstanding correctly,
|
||||
* or using executeTable()
|
||||
* @param mode
|
||||
* @param submode
|
||||
* @return
|
||||
* - @c RETURN_OK if ok
|
||||
* - @c NEED_SECOND_STEP if children need to be commanded again
|
||||
*/
|
||||
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
||||
|
||||
/**
|
||||
* Check whether desired assembly mode was achieved by checking the modes
|
||||
* or/and health states of child device handlers.
|
||||
* The assembly template class will also call this function if a health
|
||||
* or mode change of a child device handler was detected.
|
||||
* @param wantedMode
|
||||
* @param wantedSubmode
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
|
||||
Submode_t wantedSubmode) = 0;
|
||||
|
||||
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
||||
Submode_t submode) = 0;
|
||||
|
||||
enum InternalState {
|
||||
STATE_NONE,
|
||||
STATE_OVERWRITE_HEALTH,
|
||||
STATE_NEED_SECOND_STEP,
|
||||
STATE_SINGLE_STEP,
|
||||
STATE_SECOND_STEP,
|
||||
} internalState;
|
||||
|
||||
enum RecoveryState {
|
||||
RECOVERY_IDLE,
|
||||
RECOVERY_STARTED,
|
||||
RECOVERY_ONGOING,
|
||||
RECOVERY_ONGOING_2,
|
||||
RECOVERY_WAIT
|
||||
} recoveryState; //!< Indicates if one of the children requested a recovery.
|
||||
ChildrenMap::iterator recoveringDevice;
|
||||
|
||||
/**
|
||||
* the mode the current transition is trying to achieve.
|
||||
* Can be different from the modehelper.commandedMode!
|
||||
*/
|
||||
Mode_t targetMode;
|
||||
|
||||
/**
|
||||
* the submode the current transition is trying to achieve.
|
||||
* Can be different from the modehelper.commandedSubmode!
|
||||
*/
|
||||
Submode_t targetSubmode;
|
||||
|
||||
Countdown recoveryOffTimer;
|
||||
|
||||
static const uint32_t POWER_OFF_TIME_MS = 1000;
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
|
||||
|
||||
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
||||
|
||||
virtual void performChildOperation();
|
||||
|
||||
bool handleChildrenChanged();
|
||||
|
||||
/**
|
||||
* This method is called if the children changed its mode in a way that
|
||||
* the current mode can't be kept.
|
||||
* Default behavior is to go to MODE_OFF.
|
||||
* @param result The failure code which was returned by checkChildrenState.
|
||||
*/
|
||||
virtual void handleChildrenLostMode(ReturnValue_t result);
|
||||
|
||||
bool handleChildrenChangedHealth();
|
||||
|
||||
virtual void handleChildrenTransition();
|
||||
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode);
|
||||
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
|
||||
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
||||
|
||||
virtual bool isInTransition();
|
||||
|
||||
virtual void handleModeReached();
|
||||
|
||||
virtual void handleModeTransitionFailed(ReturnValue_t result);
|
||||
|
||||
void sendHealthCommand(MessageQueueId_t sendTo, HealthState health);
|
||||
|
||||
virtual ReturnValue_t checkChildrenStateOff();
|
||||
|
||||
ReturnValue_t checkChildrenState();
|
||||
|
||||
virtual ReturnValue_t checkChildOff(uint32_t objectId);
|
||||
|
||||
/**
|
||||
* Manages recovery of a device
|
||||
* @return true if recovery is still ongoing, false else.
|
||||
*/
|
||||
bool checkAndHandleRecovery();
|
||||
|
||||
/**
|
||||
* Helper method to overwrite health state of one of the children.
|
||||
* Also sets state to STATE_OVERWRITE_HEATH.
|
||||
* @param objectId Must be a registered child.
|
||||
*/
|
||||
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
||||
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
|
||||
|
||||
#include "../container/FixedArrayList.h"
|
||||
#include "../devicehandlers/DeviceHandlerBase.h"
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
|
||||
/**
|
||||
* @brief Base class to implement reconfiguration and failure handling for
|
||||
* redundant devices by monitoring their modes health states.
|
||||
* @details
|
||||
* Documentation: Dissertation Baetz p.156, 157.
|
||||
*
|
||||
* This class reduces the complexity of controller components which would
|
||||
* otherwise be needed for the handling of redundant devices.
|
||||
*
|
||||
* The template class monitors mode and health state of its children
|
||||
* and checks availability of devices on every detected change.
|
||||
* AssemblyBase does not implement any redundancy logic by itself, but provides
|
||||
* adaptation points for implementations to do so. Since most monitoring
|
||||
* activities rely on mode and health state only and are therefore
|
||||
* generic, it is sufficient for subclasses to provide:
|
||||
*
|
||||
* 1. check logic when active-> checkChildrenStateOn
|
||||
* 2. transition logic to change the mode -> commandChildren
|
||||
*
|
||||
*/
|
||||
class AssemblyBase: public SubsystemBase {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE;
|
||||
static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03);
|
||||
static const ReturnValue_t CHILD_NOT_COMMANDABLE = MAKE_RETURN_CODE(0x04);
|
||||
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
|
||||
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE =
|
||||
MAKE_RETURN_CODE(0xa1);
|
||||
|
||||
AssemblyBase(object_id_t objectId, object_id_t parentId,
|
||||
uint16_t commandQueueDepth = 8);
|
||||
virtual ~AssemblyBase();
|
||||
|
||||
protected:
|
||||
|
||||
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
|
||||
// (or return internalState directly?)
|
||||
/**
|
||||
* Command children to reach [mode,submode] combination
|
||||
* Can be done by setting #commandsOutstanding correctly,
|
||||
* or using executeTable()
|
||||
* @param mode
|
||||
* @param submode
|
||||
* @return
|
||||
* - @c RETURN_OK if ok
|
||||
* - @c NEED_SECOND_STEP if children need to be commanded again
|
||||
*/
|
||||
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
||||
|
||||
/**
|
||||
* Check whether desired assembly mode was achieved by checking the modes
|
||||
* or/and health states of child device handlers.
|
||||
* The assembly template class will also call this function if a health
|
||||
* or mode change of a child device handler was detected.
|
||||
* @param wantedMode
|
||||
* @param wantedSubmode
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
|
||||
Submode_t wantedSubmode) = 0;
|
||||
|
||||
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
|
||||
Submode_t submode) = 0;
|
||||
|
||||
enum InternalState {
|
||||
STATE_NONE,
|
||||
STATE_OVERWRITE_HEALTH,
|
||||
STATE_NEED_SECOND_STEP,
|
||||
STATE_SINGLE_STEP,
|
||||
STATE_SECOND_STEP,
|
||||
} internalState;
|
||||
|
||||
enum RecoveryState {
|
||||
RECOVERY_IDLE,
|
||||
RECOVERY_STARTED,
|
||||
RECOVERY_ONGOING,
|
||||
RECOVERY_ONGOING_2,
|
||||
RECOVERY_WAIT
|
||||
} recoveryState; //!< Indicates if one of the children requested a recovery.
|
||||
ChildrenMap::iterator recoveringDevice;
|
||||
|
||||
/**
|
||||
* the mode the current transition is trying to achieve.
|
||||
* Can be different from the modehelper.commandedMode!
|
||||
*/
|
||||
Mode_t targetMode;
|
||||
|
||||
/**
|
||||
* the submode the current transition is trying to achieve.
|
||||
* Can be different from the modehelper.commandedSubmode!
|
||||
*/
|
||||
Submode_t targetSubmode;
|
||||
|
||||
Countdown recoveryOffTimer;
|
||||
|
||||
static const uint32_t POWER_OFF_TIME_MS = 1000;
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
|
||||
|
||||
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
||||
|
||||
virtual void performChildOperation();
|
||||
|
||||
bool handleChildrenChanged();
|
||||
|
||||
/**
|
||||
* This method is called if the children changed its mode in a way that
|
||||
* the current mode can't be kept.
|
||||
* Default behavior is to go to MODE_OFF.
|
||||
* @param result The failure code which was returned by checkChildrenState.
|
||||
*/
|
||||
virtual void handleChildrenLostMode(ReturnValue_t result);
|
||||
|
||||
bool handleChildrenChangedHealth();
|
||||
|
||||
virtual void handleChildrenTransition();
|
||||
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode);
|
||||
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
|
||||
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
||||
|
||||
virtual bool isInTransition();
|
||||
|
||||
virtual void handleModeReached();
|
||||
|
||||
virtual void handleModeTransitionFailed(ReturnValue_t result);
|
||||
|
||||
void sendHealthCommand(MessageQueueId_t sendTo, HealthState health);
|
||||
|
||||
virtual ReturnValue_t checkChildrenStateOff();
|
||||
|
||||
ReturnValue_t checkChildrenState();
|
||||
|
||||
virtual ReturnValue_t checkChildOff(uint32_t objectId);
|
||||
|
||||
/**
|
||||
* Manages recovery of a device
|
||||
* @return true if recovery is still ongoing, false else.
|
||||
*/
|
||||
bool checkAndHandleRecovery();
|
||||
|
||||
/**
|
||||
* Helper method to overwrite health state of one of the children.
|
||||
* Also sets state to STATE_OVERWRITE_HEATH.
|
||||
* @param objectId Must be a registered child.
|
||||
*/
|
||||
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
||||
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
||||
|
@ -1,47 +1,47 @@
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
#include <framework/devicehandlers/ChildHandlerBase.h>
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
|
||||
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
|
||||
object_id_t deviceCommunication, CookieIF * cookie,
|
||||
object_id_t hkDestination, uint32_t thermalStatePoolId,
|
||||
uint32_t thermalRequestPoolId,
|
||||
object_id_t parent,
|
||||
FailureIsolationBase* customFdir, size_t cmdQueueSize) :
|
||||
DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
|
||||
(customFdir == nullptr? &childHandlerFdir : customFdir),
|
||||
cmdQueueSize),
|
||||
parentId(parent), childHandlerFdir(setObjectId) {
|
||||
this->setHkDestination(hkDestination);
|
||||
this->setThermalStateRequestPoolIds(thermalStatePoolId,
|
||||
thermalRequestPoolId);
|
||||
|
||||
}
|
||||
|
||||
ChildHandlerBase::~ChildHandlerBase() {
|
||||
}
|
||||
|
||||
ReturnValue_t ChildHandlerBase::initialize() {
|
||||
ReturnValue_t result = DeviceHandlerBase::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
|
||||
if (parentId != objects::NO_OBJECT) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
|
||||
parent->registerChild(getObjectId());
|
||||
}
|
||||
|
||||
healthHelper.setParentQueue(parentQueue);
|
||||
|
||||
modeHelper.setParentQueue(parentQueue);
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "../devicehandlers/ChildHandlerBase.h"
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
|
||||
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
|
||||
object_id_t deviceCommunication, CookieIF * cookie,
|
||||
object_id_t hkDestination, uint32_t thermalStatePoolId,
|
||||
uint32_t thermalRequestPoolId,
|
||||
object_id_t parent,
|
||||
FailureIsolationBase* customFdir, size_t cmdQueueSize) :
|
||||
DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
|
||||
(customFdir == nullptr? &childHandlerFdir : customFdir),
|
||||
cmdQueueSize),
|
||||
parentId(parent), childHandlerFdir(setObjectId) {
|
||||
this->setHkDestination(hkDestination);
|
||||
this->setThermalStateRequestPoolIds(thermalStatePoolId,
|
||||
thermalRequestPoolId);
|
||||
|
||||
}
|
||||
|
||||
ChildHandlerBase::~ChildHandlerBase() {
|
||||
}
|
||||
|
||||
ReturnValue_t ChildHandlerBase::initialize() {
|
||||
ReturnValue_t result = DeviceHandlerBase::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
|
||||
if (parentId != objects::NO_OBJECT) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
|
||||
parent->registerChild(getObjectId());
|
||||
}
|
||||
|
||||
healthHelper.setParentQueue(parentQueue);
|
||||
|
||||
modeHelper.setParentQueue(parentQueue);
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user