Compare commits

..

72 Commits

Author SHA1 Message Date
6fa453940f move semantics 2023-03-13 13:29:16 +01:00
9a8d775eb1 optimization for cmd executor 2023-03-12 20:49:34 +01:00
4d6f6e6b23 event manager queue depth configurable 2023-03-10 14:58:20 +01:00
55f6825a03 Revert "Modes: reusing submode for mode mask, more unittests"
This reverts commit f0bddfcb21.
2023-03-10 14:50:16 +01:00
c162acb7df Merge branch 'develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into develop 2023-03-10 14:23:51 +01:00
87462afe6d better error printout for i2c write error 2023-03-10 14:23:40 +01:00
a8de395ea0 Merge pull request 'Modes: reusing submode for mode mask, more unittests' (#133) from mohr/submode_mask into develop
Reviewed-on: #133
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-03-10 11:22:11 +01:00
f0bddfcb21 Modes: reusing submode for mode mask, more unittests 2023-03-09 16:43:45 +01:00
23d9b44b3e Merge pull request 'exceptionless host filesystem' (#132) from avoid_exceptions into develop
Reviewed-on: #132
2023-03-08 14:55:18 +01:00
26e4445189 exceptionless host filesystem 2023-03-08 14:47:03 +01:00
9ee3cdf729 Merge pull request 'OFF -> NORMAL: Set transition source modes' (#131) from off_to_normal_transition_sources into develop
Reviewed-on: #131
2023-03-08 01:24:54 +01:00
1b7493f945 OFF -> NORMAL: Set transition source modes 2023-03-08 01:18:11 +01:00
7f6ba5f40b Merge pull request 'Feature: Allowed Submodes Mask for Mode List Entry' (#130) from feature_allow_submodes_mode_list_entry into develop
Reviewed-on: #130
Reviewed-by: Steffen Gaisser <gaisser@irs.uni-stuttgart.de>
2023-03-07 17:20:47 +01:00
070b48ada2 review improvements 2023-03-07 17:15:34 +01:00
d9a139e1ef Merge remote-tracking branch 'origin/develop' into feature_allow_submodes_mode_list_entry 2023-03-07 16:31:28 +01:00
c80a3752d9 afmt 2023-03-07 16:31:08 +01:00
af58c414fc bugfix in submode check logic 2023-03-07 16:29:10 +01:00
4c48668125 add copy and assignment ctor for mode definition 2023-03-07 16:03:28 +01:00
2745b2080d allow submode mask now 2023-03-07 13:55:40 +01:00
e9d9f44605 added length check 2023-03-06 14:01:45 +01:00
2c5af91db1 Merge pull request 'new monotonic clock API' (#128) from feature_monotonic_clock_api into develop
Reviewed-on: #128
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-03-04 11:47:37 +01:00
5cd7b98ba7 more todo docs 2023-03-04 11:38:16 +01:00
a39f1271ec return FAILED for win 2023-03-04 11:32:32 +01:00
bbf0d7a0d2 add basic impl (no windows) for host 2023-03-04 11:31:54 +01:00
04ee3c7362 renaming 2023-03-04 11:04:55 +01:00
95dab69b35 new monotonic clock API 2023-03-04 11:03:22 +01:00
33de15205b Merge pull request 'configurable queue depth' (#127) from feature_configurable_queue_depth_tcpip_servers into develop
Reviewed-on: #127
2023-03-03 16:33:29 +01:00
4d353a1ad2 remove obsolete constant 2023-03-03 16:36:30 +01:00
6006c97e48 configurable queue depth 2023-03-03 15:45:44 +01:00
6e17e45506 Merge pull request 'timeval: Use system clock' (#126) from feature_timeval_use_sysclock into develop
Reviewed-on: #126
2023-03-03 15:25:38 +01:00
64537d442a extneded and fixed countdown unittests 2023-03-03 14:54:52 +01:00
78cf00315d use sys clock for Countdown 2023-03-03 14:30:35 +01:00
245886c555 add lock context for pool manager 2023-03-02 15:33:49 +01:00
f84097543e allow passing context to mutex guard 2023-03-02 15:20:59 +01:00
511d07c0c7 refactored MGM device code 2023-02-26 21:26:24 +01:00
cf735143fe update for SPI/gyro dev handler code 2023-02-26 14:54:35 +01:00
bdfe31dba4 Merge branch 'mueller/pus-15-tm-storage' into develop 2023-02-24 19:03:21 +01:00
216f603d62 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-24 16:56:32 +01:00
174a6aa862 Merge pull request 'use timeval instead of uptime for stopwatch' (#125) from stopwatch-fix into develop
Reviewed-on: #125
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-02-24 16:51:28 +01:00
c2d9370aa1 Merge branch 'develop' into stopwatch-fix 2023-02-24 16:51:08 +01:00
893b434728 allow dest handler to handle folder destinations 2023-02-24 16:49:23 +01:00
6eba84566d use timeval instead of uptime 2023-02-24 16:39:49 +01:00
f0415a97b1 some fixes and improvements 2023-02-24 15:49:05 +01:00
abcf1b29b2 execution complete 2023-02-24 14:50:36 +01:00
d373c45d36 Merge branch 'develop' into mueller/pus-15-tm-storage 2023-02-22 15:45:54 +01:00
bd208038dd printout fixes 2023-02-22 15:45:39 +01:00
206af00c8b Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-21 11:14:19 +01:00
2a0c244468 add pus 15 store ID 2023-02-20 16:10:21 +01:00
e1711f0345 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-20 15:04:13 +01:00
b45206ccd6 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-20 13:33:10 +01:00
c745c0c8b4 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-17 13:18:09 +01:00
dae5e988fd Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-17 11:52:23 +01:00
70b785984c Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-14 17:33:59 +01:00
7f907fb9d3 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-08 17:17:33 +01:00
a1567de9e8 Merge branch 'develop' into mueller/pus-15-tm-storage 2023-02-07 12:21:35 +01:00
06dca7608a time stamper empty ctor 2023-02-07 12:06:34 +01:00
6af5274b68 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-07 10:51:17 +01:00
0cc3231ceb Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-01-23 14:20:38 +01:00
041d1b8795 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-01-11 09:17:57 +01:00
2aa4af6974 make function public 2022-12-14 13:50:57 +01:00
75fc7a056d Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-12-12 09:02:04 +01:00
1b005d706a Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-12-01 16:40:39 +01:00
e68f54b9bd Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-11-28 11:37:15 +01:00
296bc56e2a Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-11-24 15:16:34 +01:00
2b6a33e718 afmt 2022-11-11 14:13:46 +01:00
61fd5d1b62 impl function to generate ASCII timestamp sec accuracy 2022-11-11 14:12:42 +01:00
046dbe1deb Merge branch 'develop' into mueller/pus-15-tm-storage 2022-11-11 11:38:32 +01:00
0303c1a885 remove file 2022-11-11 11:31:22 +01:00
4d2802a470 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-11-11 11:29:29 +01:00
819a2bfac4 add prototype for new ToAscii CCSDSTime function 2022-10-25 18:20:48 +02:00
096af44e39 needs some fixing 2022-10-24 10:56:01 +02:00
56e8e5a8b3 dont know if I am going to need this 2022-10-24 10:39:43 +02:00
62 changed files with 910 additions and 545 deletions

View File

@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes ## Fixes
- Add monotonic watchdog Clock API and use it in `Countdown` and `Stopwatch` class.
- Bugfix in `Service11TelecommandScheduling` which allowed commands - Bugfix in `Service11TelecommandScheduling` which allowed commands
time tagged in the past to be inserted. time tagged in the past to be inserted.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738

View File

@@ -178,16 +178,25 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info)
dp.user.fileSegmentRecvdIndication(segParams); dp.user.fileSegmentRecvdIndication(segParams);
} }
result = dp.user.vfs.writeToFile(fileOpParams, fileData); result = dp.user.vfs.writeToFile(fileOpParams, fileData);
if (offset.value() + fileSegmentLen > tp.progress) {
tp.progress = offset.value() + fileSegmentLen;
}
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
// TODO: Proper Error handling // TODO: Proper Error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "File write error" << std::endl; sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
<< result << std::endl;
#endif #endif
tp.vfsErrorCount++;
if (tp.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step),
result);
}
return result;
} else { } else {
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE; tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
tp.vfsErrorCount = 0;
}
if (offset.value() + fileSegmentLen > tp.progress) {
tp.progress = offset.value() + fileSegmentLen;
} }
return result; return result;
} }
@@ -271,35 +280,55 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
return OK; return OK;
} }
ReturnValue_t result = OK; ReturnValue_t result = OK;
fsmRes.step = TransactionStep::TRANSACTION_START;
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
}
tp.checksumType = info.getChecksumType();
tp.closureRequested = info.isClosureRequested();
size_t sourceNameSize = 0; size_t sourceNameSize = 0;
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize); const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize > tp.sourceName.size()) { if (sourceNameSize + 1 > tp.sourceName.size()) {
// TODO: Warning, event etc. fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
return FAILED; return FAILED;
} }
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize); std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
tp.sourceName[sourceNameSize] = '\0'; tp.sourceName[sourceNameSize] = '\0';
size_t destNameSize = 0; size_t destNameSize = 0;
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize); const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
if (destNameSize > tp.destName.size()) { if (destNameSize + 1 > tp.destName.size()) {
// TODO: Warning, event etc. fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
return FAILED; return FAILED;
} }
std::memcpy(tp.destName.data(), destNamePtr, destNameSize); std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
tp.destName[destNameSize] = '\0'; tp.destName[destNameSize] = '\0';
reader.fillConfig(tp.pduConf);
tp.pduConf.direction = Direction::TOWARDS_SENDER; // If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
tp.transactionId.entityId = tp.pduConf.sourceId; // so there is no need to create a file or truncate an existing file
tp.transactionId.seqNum = tp.pduConf.seqNum; if (destNameSize > 0 and sourceNameSize > 0) {
if (not dp.remoteCfgTable.getRemoteCfg(tp.pduConf.sourceId, &tp.remoteCfg)) { FilesystemParams fparams(tp.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
if (dp.user.vfs.isDirectory(tp.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
if (dp.user.vfs.fileExists(fparams)) {
result = dp.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
} else {
result = dp.user.vfs.createFile(fparams);
if (result != OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
}
}
EntityId sourceId;
reader.getSourceId(sourceId);
if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) {
// TODO: Warning, event etc. // TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__ sif::warning << "cfdp::DestHandler" << __func__
@@ -308,22 +337,18 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
#endif #endif
return FAILED; return FAILED;
} }
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU, fsmRes.step = TransactionStep::TRANSACTION_START;
// so there is no need to create a file or truncate an existing file if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
if (destNameSize > 0 and sourceNameSize > 0) { fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
FilesystemParams fparams(tp.destName.data()); } else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
// TODO: Filesystem errors? fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
if (dp.user.vfs.fileExists(fparams)) {
dp.user.vfs.truncateFile(fparams);
} else {
result = dp.user.vfs.createFile(fparams);
if (result != OK) {
// TODO: Handle FS error. This is probably a case for the filestore rejection mechanism of
// CFDP.
// In any case, it does not really make sense to continue here
}
}
} }
tp.checksumType = info.getChecksumType();
tp.closureRequested = info.isClosureRequested();
reader.fillConfig(tp.pduConf);
tp.pduConf.direction = Direction::TOWARDS_SENDER;
tp.transactionId.entityId = tp.pduConf.sourceId;
tp.transactionId.seqNum = tp.pduConf.seqNum;
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS; fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId); MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
params.fileSize = tp.fileSize.getSize(); params.fileSize = tp.fileSize.getSize();
@@ -362,6 +387,37 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
return OK; return OK;
} }
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
char baseNameBuf[tp.destName.size()]{};
FilesystemParams fparamsSrc(tp.sourceName.data());
size_t baseNameLen = 0;
ReturnValue_t result =
dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED;
}
// Destination name + slash + base name + null termination
if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
tp.destName[destNameSize++] = '/';
std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
tp.destName[destNameSize++] = '\0';
return OK;
}
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
static_cast<uint8_t>(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif
}
void cfdp::DestHandler::finish() { void cfdp::DestHandler::finish() {
tp.reset(); tp.reset();
dp.packetListRef.clear(); dp.packetListRef.clear();

View File

@@ -84,7 +84,7 @@ enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
class DestHandler { class DestHandler {
public: public:
enum class TransactionStep { enum class TransactionStep : uint8_t {
IDLE = 0, IDLE = 0,
TRANSACTION_START = 1, TRANSACTION_START = 1,
RECEIVING_FILE_DATA_PDUS = 2, RECEIVING_FILE_DATA_PDUS = 2,
@@ -157,11 +157,13 @@ class DestHandler {
progress = 0; progress = 0;
remoteCfg = nullptr; remoteCfg = nullptr;
closureRequested = false; closureRequested = false;
vfsErrorCount = 0;
checksumType = ChecksumType::NULL_CHECKSUM; checksumType = ChecksumType::NULL_CHECKSUM;
} }
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM; ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
bool closureRequested = false; bool closureRequested = false;
uint16_t vfsErrorCount = 0;
std::vector<char> sourceName; std::vector<char> sourceName;
std::vector<char> destName; std::vector<char> destName;
cfdp::FileSize fileSize; cfdp::FileSize fileSize;
@@ -189,9 +191,11 @@ class DestHandler {
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData, ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
size_t maxSize); size_t maxSize);
ReturnValue_t handleTransferCompletion(); ReturnValue_t handleTransferCompletion();
ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize);
ReturnValue_t sendFinishedPdu(); ReturnValue_t sendFinishedPdu();
ReturnValue_t noticeOfCompletion(); ReturnValue_t noticeOfCompletion();
ReturnValue_t checksumVerification(); ReturnValue_t checksumVerification();
void fileErrorHandler(Event event, ReturnValue_t result, const char* info);
const FsmResult& updateFsmRes(uint8_t errors); const FsmResult& updateFsmRes(uint8_t errors);
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx); void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
void finish(); void finish();

View File

@@ -12,6 +12,9 @@ namespace events {
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW); static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW); static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW); static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
} // namespace events } // namespace events

View File

@@ -565,6 +565,9 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
*/ */
if (newMode == MODE_ON and continueToNormal) { if (newMode == MODE_ON and continueToNormal) {
continueToNormal = false; continueToNormal = false;
// TODO: Check whether the following two lines are okay to do so.
transitionSourceMode = MODE_ON;
transitionSourceSubMode = submode;
mode = _MODE_TO_NORMAL; mode = _MODE_TO_NORMAL;
return; return;
} }

View File

@@ -15,12 +15,12 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)}, {fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}}; {fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
EventManager::EventManager(object_id_t setObjectId) EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) { : SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this)); auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue( eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
} }
EventManager::~EventManager() { EventManager::~EventManager() {

View File

@@ -21,9 +21,9 @@ extern const char* translateEvents(Event event);
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject { class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
public: public:
static const uint16_t MAX_EVENTS_PER_CYCLE = 80; static const uint16_t DEFAULT_MAX_EVENTS_PER_CYCLE = 80;
EventManager(object_id_t setObjectId); EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
virtual ~EventManager(); virtual ~EventManager();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);

View File

@@ -68,7 +68,7 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
parameterWrapper->set(faultCount); parameterWrapper->set(faultCount);
break; break;
case ParameterIds::TIMEOUT: case ParameterIds::TIMEOUT:
parameterWrapper->set(timer.timeout); parameterWrapper->set(timer.getTimeoutMs());
break; break;
default: default:
return INVALID_IDENTIFIER_ID; return INVALID_IDENTIFIER_ID;

View File

@@ -74,6 +74,12 @@ class HasFileSystemIF {
return MessageQueueIF::NO_QUEUE; return MessageQueueIF::NO_QUEUE;
} }
// Get the base filename without the full directory path
virtual ReturnValue_t getBaseFilename(FilesystemParams params, char* nameBuf, size_t maxLen,
size_t& baseNameLen) = 0;
virtual bool isDirectory(const char* path) = 0;
virtual bool fileExists(FilesystemParams params) = 0; virtual bool fileExists(FilesystemParams params) = 0;
/** /**

View File

@@ -7,14 +7,17 @@
class MutexGuard { class MutexGuard {
public: public:
MutexGuard(MutexIF* mutex, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING, MutexGuard(MutexIF* mutex, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING,
uint32_t timeoutMs = 0) uint32_t timeoutMs = 0, const char* context = nullptr)
: internalMutex(mutex) { : internalMutex(mutex) {
if (context == nullptr) {
context = "unknown";
}
if (mutex == nullptr) { if (mutex == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexGuard: Passed mutex is invalid!" << std::endl; sif::error << "MutexGuard::" << context << ": Passed mutex is invalid!" << std::endl;
#else #else
sif::printError("MutexGuard: Passed mutex is invalid!\n"); sif::printError("MutexGuard::%s: Passed mutex is invalid!\n", context);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */
return; return;
@@ -23,11 +26,11 @@ class MutexGuard {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
if (result == MutexIF::MUTEX_TIMEOUT) { if (result == MutexIF::MUTEX_TIMEOUT) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexGuard: Lock of mutex failed with timeout of " << timeoutMs sif::error << "MutexGuard::" << context << ": Lock of mutex failed with timeout of "
<< " milliseconds!" << std::endl; << timeoutMs << " milliseconds!" << std::endl;
#else #else
sif::printError("MutexGuard: Lock of mutex failed with timeout of %lu milliseconds\n", sif::printError("MutexGuard::%s: Lock of mutex failed with timeout of %lu milliseconds\n",
timeoutMs); context, timeoutMs);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} else if (result != returnvalue::OK) { } else if (result != returnvalue::OK) {

View File

@@ -15,6 +15,7 @@ enum framework_objects : object_id_t {
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008, PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
PUS_SERVICE_9_TIME_MGMT = 0x53000009, PUS_SERVICE_9_TIME_MGMT = 0x53000009,
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011, PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
PUS_SERVICE_15_TM_STORAGE = 0x53000015,
PUS_SERVICE_17_TEST = 0x53000017, PUS_SERVICE_17_TEST = 0x53000017,
PUS_SERVICE_20_PARAMETERS = 0x53000020, PUS_SERVICE_20_PARAMETERS = 0x53000020,
PUS_SERVICE_200_MODE_MGMT = 0x53000200, PUS_SERVICE_200_MODE_MGMT = 0x53000200,

View File

@@ -16,9 +16,9 @@
#endif #endif
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tcStoreId) uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
: TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) { : TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
// Connection is always up, TM is requested by connecting to server and receiving packets // Connection is always up, TM is requested by connecting to server and receiving packets
registerCommConnect(); registerCommConnect();

View File

@@ -38,7 +38,7 @@ class TcpTmTcBridge : public TmTcBridge {
* @param tmStoreId TM store object ID. It is recommended to the default object ID * @param tmStoreId TM store object ID. It is recommended to the default object ID
* @param tcStoreId TC store object ID. It is recommended to the default object ID * @param tcStoreId TC store object ID. It is recommended to the default object ID
*/ */
TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
object_id_t tmStoreId = objects::TM_STORE, object_id_t tmStoreId = objects::TM_STORE,
object_id_t tcStoreId = objects::TC_STORE); object_id_t tcStoreId = objects::TC_STORE);
virtual ~TcpTmTcBridge(); virtual ~TcpTmTcBridge();

View File

@@ -20,9 +20,9 @@
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
const std::string &udpServerPort_, object_id_t tmStoreId, uint32_t msgQueueDepth, const std::string &udpServerPort_,
object_id_t tcStoreId) object_id_t tmStoreId, object_id_t tcStoreId)
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) { : TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
if (udpServerPort_.empty()) { if (udpServerPort_.empty()) {
udpServerPort = DEFAULT_SERVER_PORT; udpServerPort = DEFAULT_SERVER_PORT;
} else { } else {

View File

@@ -29,7 +29,7 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
/* The ports chosen here should not be used by any other process. */ /* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_SERVER_PORT; static const std::string DEFAULT_SERVER_PORT;
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE, const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
object_id_t tcStoreId = objects::TC_STORE); object_id_t tcStoreId = objects::TC_STORE);
~UdpTmTcBridge() override; ~UdpTmTcBridge() override;

View File

@@ -47,7 +47,32 @@ ReturnValue_t Clock::setClock(const timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClockMonotonic(timeval* time) {
#if defined(PLATFORM_WIN)
// TODO: Implement with std::chrono::steady_clock.. or in some other way. I am not even sure
// whether this is possible with steady_clock. The conversion we have to do here just to be
// generic is kind of awkward..
return returnvalue::FAILED;
#elif defined(PLATFORM_UNIX)
timespec timeMonotonic;
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
if (status != 0) {
return returnvalue::FAILED;
}
time->tv_sec = timeMonotonic.tv_sec;
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
return returnvalue::OK;
#else
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
#else
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
#endif
return returnvalue::FAILED;
#endif
}
ReturnValue_t Clock::getClock(timeval* time) {
#if defined(PLATFORM_WIN) #if defined(PLATFORM_WIN)
auto now = std::chrono::system_clock::now(); auto now = std::chrono::system_clock::now();
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now); auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
@@ -75,6 +100,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
#endif #endif
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
if (time == nullptr) { if (time == nullptr) {
return returnvalue::FAILED; return returnvalue::FAILED;

View File

@@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClock(timeval* time) {
timespec timeUnix{}; timespec timeUnix{};
int status = clock_gettime(CLOCK_REALTIME, &timeUnix); int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) { if (status != 0) {
@@ -53,6 +53,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) { ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{}; timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal); ReturnValue_t result = getClock_timeval(&timeVal);
@@ -64,6 +66,17 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
timespec timeMonotonic{};
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
if (status != 0) {
return returnvalue::FAILED;
}
time->tv_sec = timeMonotonic.tv_sec;
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
return returnvalue::OK;
}
timeval Clock::getUptime() { timeval Clock::getUptime() {
timeval uptime{}; timeval uptime{};
auto result = getUptime(&uptime); auto result = getUptime(&uptime);
@@ -79,11 +92,16 @@ ReturnValue_t Clock::getUptime(timeval* uptime) {
// TODO This is not posix compatible and delivers only seconds precision // TODO This is not posix compatible and delivers only seconds precision
// Linux specific file read but more precise. // Linux specific file read but more precise.
double uptimeSeconds; double uptimeSeconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) { std::ifstream ifile("/proc/uptime");
if (ifile.bad()) {
return returnvalue::FAILED;
}
if (ifile >> uptimeSeconds) {
uptime->tv_sec = uptimeSeconds; uptime->tv_sec = uptimeSeconds;
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6); uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
return returnvalue::OK;
} }
return returnvalue::OK; return returnvalue::FAILED;
} }
// Wait for new FSFW Clock function delivering seconds uptime. // Wait for new FSFW Clock function delivering seconds uptime.

View File

@@ -1,5 +1,7 @@
#include "DummyPowerSwitcher.h" #include "DummyPowerSwitcher.h"
#include <utility>
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
size_t numberOfFuses, bool registerGlobally, size_t numberOfFuses, bool registerGlobally,
uint32_t switchDelayMs) uint32_t switchDelayMs)
@@ -9,11 +11,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
switchDelayMs(switchDelayMs) {} switchDelayMs(switchDelayMs) {}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) { void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList; this->switcherList = std::move(switcherList);
} }
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) { void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
this->fuseList = fuseList; this->fuseList = std::move(fuseList);
} }
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) { ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {

View File

@@ -68,6 +68,9 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (subservice) { switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): { case (Subservice::COMMAND_SET_HEALTH): {
if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
return CommandingServiceBase::INVALID_TC;
}
HealthSetCommand healthCommand; HealthSetCommand healthCommand;
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
@@ -79,7 +82,7 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
} }
case (Subservice::COMMAND_ANNOUNCE_HEALTH): { case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE); HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
break; return CommandingServiceBase::EXECUTION_COMPLETE;
} }
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): { case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
ReturnValue_t result = iterateHealthTable(true); ReturnValue_t result = iterateHealthTable(true);

View File

@@ -10,7 +10,7 @@ PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPo
PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); } PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); }
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) { ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) {
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs); MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
ReturnValue_t status = LocalPool::reserveSpace(size, address); ReturnValue_t status = LocalPool::reserveSpace(size, address);
return status; return status;
} }
@@ -22,12 +22,12 @@ ReturnValue_t PoolManager::deleteData(store_address_t storeId) {
<< storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl; << storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl;
#endif #endif
#endif #endif
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs); MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
return LocalPool::deleteData(storeId); return LocalPool::deleteData(storeId);
} }
ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) { ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) {
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId);
return status; return status;
} }

View File

@@ -56,6 +56,7 @@ class PoolManager : public LocalPool {
protected: protected:
//! Default mutex timeout value to prevent permanent blocking. //! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20; uint32_t mutexTimeoutMs = 20;
static constexpr char LOCK_CTX[] = "PoolManager";
ReturnValue_t reserveSpace(size_t size, store_address_t* address) override; ReturnValue_t reserveSpace(size_t size, store_address_t* address) override;

View File

@@ -21,6 +21,7 @@ SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(c
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter, ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
Submode_t targetSubmode) { Submode_t targetSubmode) {
using namespace mode;
std::map<object_id_t, ChildInfo>::iterator childIter; std::map<object_id_t, ChildInfo>::iterator childIter;
for (; tableIter.value != NULL; ++tableIter) { for (; tableIter.value != NULL; ++tableIter) {
@@ -34,13 +35,21 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry
return returnvalue::FAILED; return returnvalue::FAILED;
} }
Submode_t submodeToCheckAgainst = tableIter.value->getSubmode(); // Check submodes here.
uint8_t mask;
bool submodesAllowedMask = tableIter.value->submodesAllowed(&mask);
uint8_t submodeToCheckAgainst = tableIter.value->getSubmode();
if (tableIter.value->inheritSubmode()) { if (tableIter.value->inheritSubmode()) {
submodeToCheckAgainst = targetSubmode; submodeToCheckAgainst = targetSubmode;
} }
if (submodesAllowedMask) {
if (childIter->second.submode != submodeToCheckAgainst) { if ((childIter->second.submode | mask) != mask) {
return returnvalue::FAILED; return returnvalue::FAILED;
}
} else {
if (childIter->second.submode != submodeToCheckAgainst) {
return returnvalue::FAILED;
}
} }
} }
return returnvalue::OK; return returnvalue::OK;

View File

@@ -1,111 +1,126 @@
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ #ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_ #define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#include "../../modes/HasModesIF.h" #include "fsfw/modes/HasModesIF.h"
#include "../../objectmanager/SystemObjectIF.h" #include "fsfw/objectmanager/SystemObjectIF.h"
#include "../../serialize/SerialLinkedListAdapter.h" #include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "../../serialize/SerializeIF.h" #include "fsfw/serialize/SerializeIF.h"
class ModeListEntry : public SerializeIF, public LinkedElement<ModeListEntry> { namespace mode {
enum SpecialSubmodeFlags : uint8_t { INHERIT = 1 << 0, ALLOWED_MASK = 1 << 1 };
}
class ModeListEntry : public SerialLinkedListAdapter<SerializeIF>,
public LinkedElement<ModeListEntry> {
public: public:
ModeListEntry() : LinkedElement<ModeListEntry>(this) {} static constexpr uint8_t ALL_SUBMODES_ALLOWED_MASK = 0xff;
uint32_t value1 = 0; ModeListEntry() : SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) { setLinks(); }
uint32_t value2 = 0;
uint8_t value3 = 0;
uint8_t value4 = 0;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, SerializeElement<uint32_t> value1 = 0;
Endianness streamEndianness) const { SerializeElement<uint32_t> value2 = 0;
ReturnValue_t result; SerializeElement<uint8_t> value3 = 0;
SerializeElement<uint8_t> value4 = 0;
SerializeElement<uint8_t> value5 = 0;
result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness); ModeListEntry(const ModeListEntry& other)
: SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) {
if (result != returnvalue::OK) { value1.entry = other.value1.entry;
return result; value2.entry = other.value2.entry;
} value3.entry = other.value3.entry;
result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness); value4.entry = other.value4.entry;
value5.entry = other.value5.entry;
if (result != returnvalue::OK) { setLinks();
return result;
}
result = SerializeAdapter::serialize(&value3, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&value4, buffer, size, maxSize, streamEndianness);
return result;
} }
virtual size_t getSerializedSize() const { ModeListEntry& operator=(const ModeListEntry& other) {
return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); this->value1.entry = other.value1.entry;
this->value2.entry = other.value2.entry;
this->value3.entry = other.value3.entry;
this->value4.entry = other.value4.entry;
this->value5.entry = other.value5.entry;
return *this;
} }
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, void setLinks() {
Endianness streamEndianness) { setStart(&value1);
ReturnValue_t result; value1.setNext(&value2);
value2.setNext(&value3);
result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness); value3.setNext(&value4);
value4.setNext(&value5);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value2, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value3, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value4, buffer, size, streamEndianness);
return result;
} }
// for Sequences // for Sequences
Mode_t getTableId() const { return value1; } Mode_t getTableId() const { return value1.entry; }
void setTableId(Mode_t tableId) { this->value1 = tableId; } void setTableId(Mode_t tableId) { this->value1.entry = tableId; }
uint8_t getWaitSeconds() const { return value2; } uint8_t getWaitSeconds() const { return value2.entry; }
void setWaitSeconds(uint8_t waitSeconds) { this->value2 = waitSeconds; } void setWaitSeconds(uint8_t waitSeconds) { this->value2.entry = waitSeconds; }
bool checkSuccess() const { return value3 == 1; } bool checkSuccess() const { return value3.entry == 1; }
void setCheckSuccess(bool checkSuccess) { this->value3 = checkSuccess; } void setCheckSuccess(bool checkSuccess) { this->value3.entry = checkSuccess; }
// for Tables // for Tables
object_id_t getObject() const { return value1; } object_id_t getObject() const { return value1.entry; }
void setObject(object_id_t object) { this->value1 = object; } void setObject(object_id_t object) { this->value1.entry = object; }
Mode_t getMode() const { return value2; } Mode_t getMode() const { return value2.entry; }
void setMode(Mode_t mode) { this->value2 = mode; } void setMode(Mode_t mode) { this->value2.entry = mode; }
Submode_t getSubmode() const { return value3; } Submode_t getSubmode() const { return value3.entry; }
void setSubmode(Submode_t submode) { this->value3 = submode; } void setSubmode(Submode_t submode) { this->value3.entry = submode; }
bool inheritSubmode() const { return value4 == 1; } bool inheritSubmode() const {
return (value4.entry & mode::SpecialSubmodeFlags::INHERIT) ==
void setInheritSubmode(bool inherit) { mode::SpecialSubmodeFlags::INHERIT;
if (inherit) { }
value4 = 1; bool submodesAllowed(uint8_t* mask) const {
} else { bool submodesAllowed = (value4.entry & mode::SpecialSubmodeFlags::ALLOWED_MASK) ==
value4 = 0; mode::SpecialSubmodeFlags::ALLOWED_MASK;
if (submodesAllowed and mask != nullptr) {
*mask = value5.entry;
} }
return submodesAllowed;
} }
bool operator==(ModeListEntry other) { /**
return ((value1 == other.value1) && (value2 == other.value2) && (value3 == other.value3)); * Enable the inheritance of submodes. This is relevant for both the execution
* of mode tables and for mode checking.
*/
void enableInheritSubmode() { value4.entry |= mode::SpecialSubmodeFlags::INHERIT; }
/**
* Disable the inheritance of submodes. This is relevant for both the execution
* of mode tables and for mode checking.
*/
void disableInheritSubmode() { value4.entry &= ~mode::SpecialSubmodeFlags::INHERIT; }
/**
* Specialization of @enableSubmodeAllowed which allows all submodes.
*/
void allowAllSubmodes() { enableSubmodeAllowed(ALL_SUBMODES_ALLOWED_MASK); }
/**
* Enable an allowed submode mask for mode checks. Any submode which contains bits
* outside of the mask will be declined.
*
* For example, for a mask of 0b11, only the modes 0b00, 0b01 and 0b11 will be accepted.
*/
void enableSubmodeAllowed(uint8_t mask) {
value4.entry |= mode::SpecialSubmodeFlags::ALLOWED_MASK;
value5.entry = mask;
}
/**
* Enforce the equality of submodes for mode checks. This is the default.
*/
void disableSubmodeAllowed() {
value4.entry &= ~mode::SpecialSubmodeFlags::ALLOWED_MASK;
value5.entry = 0;
} }
}; };

View File

@@ -15,10 +15,10 @@ ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjec
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (execObj == nullptr) { if (execObj == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execObj sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execId
<< std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl; << std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl;
#else #else
sif::printError("Component 0x%08x not found, not adding it to PST\n"); sif::printError("Component 0x%08x not found, not adding it to PST\n", execId);
#endif #endif
return returnvalue::FAILED; return returnvalue::FAILED;
} }

View File

@@ -283,7 +283,7 @@ ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
} }
switch (uniqueId) { switch (uniqueId) {
case 0: case 0:
parameterWrapper->set(heaterOnCountdown.timeout); parameterWrapper->set(heaterOnCountdown.getTimeoutMs());
break; break;
default: default:
return INVALID_IDENTIFIER_ID; return INVALID_IDENTIFIER_ID;

View File

@@ -246,6 +246,20 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t*
return UNSUPPORTED_TIME_FORMAT; return UNSUPPORTED_TIME_FORMAT;
} }
ReturnValue_t CCSDSTime::convertToAsciiWithSecs(int8_t* to, const Clock::TimeOfDay_t* from,
uint8_t length) {
if (from == nullptr or to == nullptr) {
return returnvalue::FAILED;
}
int count = snprintf(reinterpret_cast<char*>(to), length,
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32,
from->year, from->month, from->day, from->hour, from->minute, from->second);
if (count >= length) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) { ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) {
const Ccs_mseconds* time_struct = reinterpret_cast<const Ccs_mseconds*>(time); const Ccs_mseconds* time_struct = reinterpret_cast<const Ccs_mseconds*>(time);

View File

@@ -207,7 +207,8 @@ class CCSDSTime {
static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from, static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from,
uint8_t length); uint8_t length);
static ReturnValue_t convertToAsciiWithSecs(int8_t *to, const Clock::TimeOfDay_t *from,
uint8_t length);
static uint32_t subsecondsToMicroseconds(uint16_t subseconds); static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
private: private:

View File

@@ -49,6 +49,13 @@ class Clock {
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned. * @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t setClock(const timeval *time); static ReturnValue_t setClock(const timeval *time);
/**
* @deprecated Use getClock instead, which does the same.
* @param time
* @return
*/
static ReturnValue_t getClock_timeval(timeval *time);
/** /**
* This system call returns the current system clock in timeval format. * This system call returns the current system clock in timeval format.
* The timval format has the fields @c tv_sec with seconds and @c tv_usec with * The timval format has the fields @c tv_sec with seconds and @c tv_usec with
@@ -56,7 +63,18 @@ class Clock {
* @param time A pointer to a timeval struct where the current time is stored. * @param time A pointer to a timeval struct where the current time is stored.
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned. * @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t getClock_timeval(timeval *time); static ReturnValue_t getClock(timeval *time);
/**
* Retrieve a monotonic clock. This clock this is also more suited for measuring elapsed times
* between two time points, but less suited when the absolute time is required.
*
* Implementation example: A generic UNIX implementation can use CLOCK_MONOTONIC_RAW with
* `clock_gettime`.
* @param time
* @return
*/
static ReturnValue_t getClockMonotonic(timeval *time);
/** /**
* Get the time since boot in a timeval struct * Get the time since boot in a timeval struct

View File

@@ -1,49 +1,62 @@
#include "fsfw/timemanager/Countdown.h" #include "fsfw/timemanager/Countdown.h"
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) { #include "fsfw/globalfunctions/timevalOperations.h"
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) {
if (startImmediately) { if (startImmediately) {
setTimeout(initialTimeout); setTimeout(initialTimeout);
} else { } else {
timeout = initialTimeout; timeout.tv_sec = initialTimeout / 1000;
timeout.tv_usec = (initialTimeout % 1000) * 1000;
} }
} }
Countdown::~Countdown() {} Countdown::~Countdown() = default;
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) { ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
ReturnValue_t returnValue = Clock::getUptime(&startTime); timeout.tv_sec = milliseconds / 1000;
timeout = milliseconds; timeout.tv_usec = (milliseconds % 1000) * 1000;
return returnValue; return Clock::getClockMonotonic(&startTime);
} }
bool Countdown::hasTimedOut() const { bool Countdown::hasTimedOut() const {
if (uint32_t(this->getCurrentTime() - startTime) >= timeout) { // Account for system clock going back in time.
if (getCurrentTime() < startTime) {
return true; return true;
} else {
return false;
} }
if (getCurrentTime() - startTime >= timeout) {
return true;
}
return false;
} }
bool Countdown::isBusy() const { return !hasTimedOut(); } bool Countdown::isBusy() const { return !hasTimedOut(); }
ReturnValue_t Countdown::resetTimer() { return setTimeout(timeout); } ReturnValue_t Countdown::resetTimer() { return setTimeoutTv(timeout); }
void Countdown::timeOut() { startTime = this->getCurrentTime() - timeout; } void Countdown::timeOut() { startTime = this->getCurrentTime() - timeout; }
uint32_t Countdown::getRemainingMillis() const { uint32_t Countdown::getRemainingMillis() const {
// We fetch the time before the if-statement
// to be sure that the return is in
// range 0 <= number <= timeout
uint32_t currentTime = this->getCurrentTime();
if (this->hasTimedOut()) { if (this->hasTimedOut()) {
return 0; return 0;
} else {
return (startTime + timeout) - currentTime;
} }
timeval remainingMillisTv = (startTime + timeout) - this->getCurrentTime();
return remainingMillisTv.tv_sec * 1000 + remainingMillisTv.tv_usec / 1000;
} }
uint32_t Countdown::getCurrentTime() const { uint32_t Countdown::timevalToMs(timeval &tv) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; }
uint32_t currentTime;
Clock::getUptime(&currentTime); ReturnValue_t Countdown::setTimeoutTv(timeval tv) {
timeout = tv;
return Clock::getClockMonotonic(&startTime);
}
uint32_t Countdown::getTimeoutMs() const { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; }
timeval Countdown::getTimeout() const { return timeout; }
timeval Countdown::getCurrentTime() const {
timeval currentTime{};
Clock::getClockMonotonic(&currentTime);
return currentTime; return currentTime;
} }

View File

@@ -6,6 +6,10 @@
/** /**
* *
* Countdown keeps track of a timespan. * Countdown keeps track of a timespan.
* This class uses the system clock internally to achieve
* a high resolution. This means that the API is only partially
* resistant against time jumps. The user must take care to account
* for time jumps in some from if this relevant.
* *
* Countdown::resetTimer restarts the timer. * Countdown::resetTimer restarts the timer.
* Countdown::setTimeout sets a new countdown duration and resets. * Countdown::setTimeout sets a new countdown duration and resets.
@@ -39,6 +43,8 @@ class Countdown {
* @return Returnvalue from Clock::getUptime * @return Returnvalue from Clock::getUptime
*/ */
ReturnValue_t setTimeout(uint32_t milliseconds); ReturnValue_t setTimeout(uint32_t milliseconds);
ReturnValue_t setTimeoutTv(timeval tv);
/** /**
* Returns true if the countdown duration has passed. * Returns true if the countdown duration has passed.
* *
@@ -61,22 +67,31 @@ class Countdown {
* Returns the remaining milliseconds (0 if timeout) * Returns the remaining milliseconds (0 if timeout)
*/ */
uint32_t getRemainingMillis() const; uint32_t getRemainingMillis() const;
uint32_t getTimeoutMs() const;
timeval getTimeout() const;
/** /**
* Makes hasTimedOut() return true * Makes hasTimedOut() return true
*/ */
void timeOut(); void timeOut();
/**
* Internal countdown duration in milliseconds static inline uint32_t timevalToMs(timeval& tv);
*/
uint32_t timeout;
private: private:
/** /**
* Last time the timer was started (uptime) * Start time of the countdown.
*/ */
uint32_t startTime = 0; timeval startTime{};
uint32_t getCurrentTime() const; /**
* Timeout as timeval type. The countdown has timed out when the
* current time exceeds the start time plus the timeout.
*/
timeval timeout{};
timeval getCurrentTime() const;
}; };
#endif /* FSFW_TIMEMANAGER_COUNTDOWN_H_ */ #endif /* FSFW_TIMEMANAGER_COUNTDOWN_H_ */

View File

@@ -9,10 +9,10 @@
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode) Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) { : displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
// Measures start time on initialization. // Measures start time on initialization.
Clock::getUptime(&startTime); Clock::getClockMonotonic(&startTime);
} }
void Stopwatch::start() { Clock::getUptime(&startTime); } void Stopwatch::start() { Clock::getClockMonotonic(&startTime); }
dur_millis_t Stopwatch::stop(bool display) { dur_millis_t Stopwatch::stop(bool display) {
stopInternal(); stopInternal();
@@ -63,6 +63,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; }
void Stopwatch::stopInternal() { void Stopwatch::stopInternal() {
timeval endTime; timeval endTime;
Clock::getUptime(&endTime); Clock::getClockMonotonic(&endTime);
elapsedTime = endTime - startTime; elapsedTime = endTime - startTime;
} }

View File

@@ -6,47 +6,12 @@
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "tmStorageConf.h" #include "tmStorageConf.h"
class TmPacketMinimal; class PusTmReader;
class SpacePacketBase; class SpacePacketReader;
class TmStoreBackendIF; class TmStoreBackendIF;
class TmStoreFrontendIF { class TmStoreFrontendIF {
public: public:
virtual TmStoreBackendIF* getBackend() const = 0;
/**
* What do I need to implement here?
* This is propably used by PUS Service 15 so we should propably check for messages..
* Provide base implementation?
* @param opCode
* @return
*/
virtual ReturnValue_t performOperation(uint8_t opCode) = 0;
/**
* Callback from the back-end to indicate a certain packet was received.
* front-end takes care of discarding/downloading the packet.
* @param packet Pointer to the newly received Space Packet.
* @param address Start address of the packet found
* @param isLastPacket Indicates if no more packets can be fetched.
* @return If more packets shall be fetched, returnvalue::OK must be returned.
* Any other code stops fetching packets.
*/
virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address) = 0;
virtual void noMorePacketsInStore() = 0;
virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) = 0;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0;
virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0;
virtual ReturnValue_t checkPacket(SpacePacketBase* tmPacket) = 0;
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void resetDownlinkedPacketCount() = 0;
virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0;
static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_FRONTEND_IF; static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_FRONTEND_IF;
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1); static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1);
static const ReturnValue_t LAST_PACKET_FOUND = MAKE_RETURN_CODE(2); static const ReturnValue_t LAST_PACKET_FOUND = MAKE_RETURN_CODE(2);
@@ -57,7 +22,38 @@ class TmStoreFrontendIF {
static const ReturnValue_t ALL_DELETED = MAKE_RETURN_CODE(7); static const ReturnValue_t ALL_DELETED = MAKE_RETURN_CODE(7);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(8); static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(8);
static const ReturnValue_t NOT_READY = MAKE_RETURN_CODE(9); static const ReturnValue_t NOT_READY = MAKE_RETURN_CODE(9);
virtual ~TmStoreFrontendIF() {}
virtual ~TmStoreFrontendIF() = default;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual TmStoreBackendIF* getBackend() const = 0;
/**
* Callback from the back-end to indicate a certain packet was received.
* front-end takes care of discarding/downloading the packet.
* @param packet Pointer to the newly received Space Packet.
* @param address Start address of the packet found
* @param isLastPacket Indicates if no more packets can be fetched.
* @return If more packets shall be fetched, returnvalue::OK must be returned.
* Any other code stops fetching packets.
*/
virtual ReturnValue_t packetRetrieved(PusTmReader* packet, uint32_t address) = 0;
virtual void noMorePacketsInStore() = 0;
virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) = 0;
virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0;
virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0;
virtual ReturnValue_t checkPacket(SpacePacketReader* tmPacket) = 0;
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void resetDownlinkedPacketCount() = 0;
virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0;
}; };
#endif /* FSFW_TMTCSERVICES_TMSTOREFRONTENDIF_H_ */ #endif /* FSFW_TMTCSERVICES_TMSTOREFRONTENDIF_H_ */

View File

@@ -0,0 +1,15 @@
#ifndef FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_
#define FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
class TmStoreFrontendSimpleIF {
public:
virtual ~TmStoreFrontendSimpleIF() = default;
virtual MessageQueueId_t getCommandQueue() const = 0;
private:
};
#endif /* FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_ */

View File

@@ -1,6 +1,10 @@
#ifndef FSFW_TMSTORAGE_TMSTOREPACKETS_H_ #ifndef FSFW_TMSTORAGE_TMSTOREPACKETS_H_
#define FSFW_TMSTORAGE_TMSTOREPACKETS_H_ #define FSFW_TMSTORAGE_TMSTOREPACKETS_H_
#include <fsfw/tmtcpacket/pus/tm/PusTmReader.h>
#include <vector>
#include "fsfw/globalfunctions/timevalOperations.h" #include "fsfw/globalfunctions/timevalOperations.h"
#include "fsfw/serialize/SerialBufferAdapter.h" #include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/serialize/SerialFixedArrayListAdapter.h" #include "fsfw/serialize/SerialFixedArrayListAdapter.h"
@@ -24,7 +28,7 @@ class ServiceSubservice : public SerialLinkedListAdapter<SerializeIF> {
class ApidSsc : public SerializeIF { class ApidSsc : public SerializeIF {
public: public:
ApidSsc() : apid(SpacePacketBase::LIMIT_APID), ssc(0) {} ApidSsc() : apid(ccsds::LIMIT_APID), ssc(0) {}
ApidSsc(uint16_t apid, uint16_t ssc) : apid(apid), ssc(ssc) {} ApidSsc(uint16_t apid, uint16_t ssc) : apid(apid), ssc(ssc) {}
uint16_t apid; uint16_t apid;
uint16_t ssc; uint16_t ssc;
@@ -62,51 +66,59 @@ class ChangeSelectionDefinition : public SerialLinkedListAdapter<SerializeIF> {
class TmPacketInformation : public SerializeIF { class TmPacketInformation : public SerializeIF {
public: public:
TmPacketInformation(TmPacketMinimal* packet) { setContent(packet); } TmPacketInformation(PusTmReader* packet, size_t timestampLen) : rawTimestamp(timestampLen) {
TmPacketInformation() setContent(packet);
: apid(SpacePacketBase::LIMIT_APID), }
TmPacketInformation(size_t timestampLen)
: apid(ccsds::LIMIT_APID),
sourceSequenceCount(0), sourceSequenceCount(0),
serviceType(0), serviceType(0),
serviceSubtype(0), serviceSubtype(0),
subCounter(0) {} subCounter(0),
rawTimestamp(timestampLen) {}
void reset() { void reset() {
apid = SpacePacketBase::LIMIT_APID; apid = ccsds::LIMIT_APID;
sourceSequenceCount = 0; sourceSequenceCount = 0;
serviceType = 0; serviceType = 0;
serviceSubtype = 0; serviceSubtype = 0;
subCounter = 0; subCounter = 0;
memset(rawTimestamp, 0, sizeof(rawTimestamp)); memset(rawTimestamp.data(), 0, rawTimestamp.size());
} }
void setContent(TmPacketMinimal* packet) { void setContent(PusTmReader* packet) {
apid = packet->getAPID(); apid = packet->getApid();
sourceSequenceCount = packet->getPacketSequenceCount(); sourceSequenceCount = packet->getSequenceCount();
serviceType = packet->getService(); serviceType = packet->getService();
serviceSubtype = packet->getSubService(); serviceSubtype = packet->getSubService();
subCounter = packet->getPacketSubcounter(); subCounter = packet->getMessageTypeCounter();
memset(rawTimestamp, 0, sizeof(rawTimestamp)); memset(rawTimestamp.data(), 0, rawTimestamp.size());
const uint8_t* pField = NULL; // TODO: Fix all of this
uint32_t size = 0; // const uint8_t* pField = NULL;
ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size); // uint32_t size = 0;
if (result != returnvalue::OK) { // auto* timeReader = packet->getTimeReader();
return; // ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size);
} // if (result != returnvalue::OK) {
if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) { // return;
// Shortcut to avoid converting CDS back and forth. //}
memcpy(rawTimestamp, pField, size); // if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE)
return; // {
} // Shortcut to avoid converting CDS back and forth.
timeval time = {0, 0}; // TODO: Fix
result = packet->getPacketTime(&time); // memcpy(rawTimestamp, pField, size);
if (result != returnvalue::OK) { // return;
return; // }
} // timeval time = {0, 0};
// result = packet->getPacketTime(&time);
CCSDSTime::CDS_short cdsFormat; // if (result != returnvalue::OK) {
result = CCSDSTime::convertToCcsds(&cdsFormat, &time); // return;
if (result != returnvalue::OK) { // }
return; //
} // CCSDSTime::CDS_short cdsFormat;
memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat)); // result = CCSDSTime::convertToCcsds(&cdsFormat, &time);
// if (result != returnvalue::OK) {
// return;
// }
// TODO: Fix
// memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat));
} }
void setContent(TmPacketInformation* content) { void setContent(TmPacketInformation* content) {
apid = content->apid; apid = content->apid;
@@ -114,9 +126,10 @@ class TmPacketInformation : public SerializeIF {
serviceType = content->serviceType; serviceType = content->serviceType;
serviceSubtype = content->serviceSubtype; serviceSubtype = content->serviceSubtype;
subCounter = content->subCounter; subCounter = content->subCounter;
memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp)); // TODO: Fix
// memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp));
} }
bool isValid() const { return (apid < SpacePacketBase::LIMIT_APID) ? true : false; } bool isValid() const { return (apid < ccsds::LIMIT_APID) ? true : false; }
static void reset(TmPacketInformation* packet) { packet->reset(); } static void reset(TmPacketInformation* packet) { packet->reset(); }
static bool isOlderThan(const TmPacketInformation* packet, const timeval* cmpTime) { static bool isOlderThan(const TmPacketInformation* packet, const timeval* cmpTime) {
@@ -216,7 +229,7 @@ class TmPacketInformation : public SerializeIF {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp)); SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
return adapter.serialize(buffer, size, maxSize, streamEndianness); return adapter.serialize(buffer, size, maxSize, streamEndianness);
} }
@@ -227,7 +240,7 @@ class TmPacketInformation : public SerializeIF {
size += SerializeAdapter::getSerializedSize(&serviceType); size += SerializeAdapter::getSerializedSize(&serviceType);
size += SerializeAdapter::getSerializedSize(&serviceSubtype); size += SerializeAdapter::getSerializedSize(&serviceSubtype);
size += SerializeAdapter::getSerializedSize(&subCounter); size += SerializeAdapter::getSerializedSize(&subCounter);
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp)); SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
size += adapter.getSerializedSize(); size += adapter.getSerializedSize();
return size; return size;
}; };
@@ -253,7 +266,7 @@ class TmPacketInformation : public SerializeIF {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp)); SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
return adapter.deSerialize(buffer, size, streamEndianness); return adapter.deSerialize(buffer, size, streamEndianness);
} }
@@ -263,6 +276,6 @@ class TmPacketInformation : public SerializeIF {
uint8_t serviceType; uint8_t serviceType;
uint8_t serviceSubtype; uint8_t serviceSubtype;
uint8_t subCounter; uint8_t subCounter;
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; std::vector<uint8_t> rawTimestamp;
}; };
#endif /* FSFW_TMSTORAGE_TMSTOREPACKETS_H_ */ #endif /* FSFW_TMSTORAGE_TMSTOREPACKETS_H_ */

View File

@@ -8,7 +8,7 @@
#define TMTCBRIDGE_WIRETAPPING 0 #define TMTCBRIDGE_WIRETAPPING 0
TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination, TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId) uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
: SystemObject(objectId), : SystemObject(objectId),
name(name), name(name),
tmStoreId(tmStoreId), tmStoreId(tmStoreId),
@@ -18,7 +18,7 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
{ {
auto mqArgs = MqArgs(objectId, static_cast<void*>(this)); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue( tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); } TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }

View File

@@ -15,7 +15,6 @@ class TmTcBridge : public AcceptsTelemetryIF,
public ExecutableObjectIF, public ExecutableObjectIF,
public SystemObject { public SystemObject {
public: public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500; static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
@@ -23,7 +22,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination, TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId); uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId);
~TmTcBridge() override; ~TmTcBridge() override;
/** /**

View File

@@ -1,3 +1,5 @@
target_sources( target_sources(
${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp ${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp
MgmLIS3MDLHandler.cpp) MgmLIS3MDLHandler.cpp)
add_subdirectory(devicedefinitions)

View File

@@ -46,17 +46,17 @@ ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t
return NOTHING_TO_SEND; return NOTHING_TO_SEND;
} }
case (InternalState::CONFIGURE): { case (InternalState::CONFIGURE): {
*id = L3GD20H::CONFIGURE_CTRL_REGS; *id = l3gd20h::CONFIGURE_CTRL_REGS;
uint8_t command[5]; uint8_t command[5];
command[0] = L3GD20H::CTRL_REG_1_VAL; command[0] = l3gd20h::CTRL_REG_1_VAL;
command[1] = L3GD20H::CTRL_REG_2_VAL; command[1] = l3gd20h::CTRL_REG_2_VAL;
command[2] = L3GD20H::CTRL_REG_3_VAL; command[2] = l3gd20h::CTRL_REG_3_VAL;
command[3] = L3GD20H::CTRL_REG_4_VAL; command[3] = l3gd20h::CTRL_REG_4_VAL;
command[4] = L3GD20H::CTRL_REG_5_VAL; command[4] = l3gd20h::CTRL_REG_5_VAL;
return buildCommandFromCommand(*id, command, 5); return buildCommandFromCommand(*id, command, 5);
} }
case (InternalState::CHECK_REGS): { case (InternalState::CHECK_REGS): {
*id = L3GD20H::READ_REGS; *id = l3gd20h::READ_REGS;
return buildCommandFromCommand(*id, nullptr, 0); return buildCommandFromCommand(*id, nullptr, 0);
} }
default: default:
@@ -76,7 +76,7 @@ ReturnValue_t GyroHandlerL3GD20H::buildTransitionDeviceCommand(DeviceCommandId_t
} }
ReturnValue_t GyroHandlerL3GD20H::buildNormalDeviceCommand(DeviceCommandId_t *id) { ReturnValue_t GyroHandlerL3GD20H::buildNormalDeviceCommand(DeviceCommandId_t *id) {
*id = L3GD20H::READ_REGS; *id = l3gd20h::READ_REGS;
return buildCommandFromCommand(*id, nullptr, 0); return buildCommandFromCommand(*id, nullptr, 0);
} }
@@ -84,15 +84,15 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi
const uint8_t *commandData, const uint8_t *commandData,
size_t commandDataLen) { size_t commandDataLen) {
switch (deviceCommand) { switch (deviceCommand) {
case (L3GD20H::READ_REGS): { case (l3gd20h::READ_REGS): {
commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK; commandBuffer[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
std::memset(commandBuffer + 1, 0, L3GD20H::READ_LEN); std::memset(commandBuffer + 1, 0, l3gd20h::READ_LEN);
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = L3GD20H::READ_LEN + 1; rawPacketLen = l3gd20h::READ_LEN + 1;
break; break;
} }
case (L3GD20H::CONFIGURE_CTRL_REGS): { case (l3gd20h::CONFIGURE_CTRL_REGS): {
commandBuffer[0] = L3GD20H::CTRL_REG_1 | L3GD20H::AUTO_INCREMENT_MASK; commandBuffer[0] = l3gd20h::CTRL_REG_1 | l3gd20h::AUTO_INCREMENT_MASK;
if (commandData == nullptr or commandDataLen != 5) { if (commandData == nullptr or commandDataLen != 5) {
return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; return DeviceHandlerIF::INVALID_COMMAND_PARAMETER;
} }
@@ -103,15 +103,15 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi
ctrlReg4Value = commandData[3]; ctrlReg4Value = commandData[3];
ctrlReg5Value = commandData[4]; ctrlReg5Value = commandData[4];
bool fsH = ctrlReg4Value & L3GD20H::SET_FS_1; bool fsH = ctrlReg4Value & l3gd20h::SET_FS_1;
bool fsL = ctrlReg4Value & L3GD20H::SET_FS_0; bool fsL = ctrlReg4Value & l3gd20h::SET_FS_0;
if (not fsH and not fsL) { if (not fsH and not fsL) {
sensitivity = L3GD20H::SENSITIVITY_00; sensitivity = l3gd20h::SENSITIVITY_00;
} else if (not fsH and fsL) { } else if (not fsH and fsL) {
sensitivity = L3GD20H::SENSITIVITY_01; sensitivity = l3gd20h::SENSITIVITY_01;
} else { } else {
sensitivity = L3GD20H::SENSITIVITY_11; sensitivity = l3gd20h::SENSITIVITY_11;
} }
commandBuffer[1] = ctrlReg1Value; commandBuffer[1] = ctrlReg1Value;
@@ -124,8 +124,8 @@ ReturnValue_t GyroHandlerL3GD20H::buildCommandFromCommand(DeviceCommandId_t devi
rawPacketLen = 6; rawPacketLen = 6;
break; break;
} }
case (L3GD20H::READ_CTRL_REGS): { case (l3gd20h::READ_CTRL_REGS): {
commandBuffer[0] = L3GD20H::READ_START | L3GD20H::AUTO_INCREMENT_MASK | L3GD20H::READ_MASK; commandBuffer[0] = l3gd20h::READ_START | l3gd20h::AUTO_INCREMENT_MASK | l3gd20h::READ_MASK;
std::memset(commandBuffer + 1, 0, 5); std::memset(commandBuffer + 1, 0, 5);
rawPacket = commandBuffer; rawPacket = commandBuffer;
@@ -151,11 +151,11 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) { const uint8_t *packet) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (id) { switch (id) {
case (L3GD20H::CONFIGURE_CTRL_REGS): { case (l3gd20h::CONFIGURE_CTRL_REGS): {
commandExecuted = true; commandExecuted = true;
break; break;
} }
case (L3GD20H::READ_CTRL_REGS): { case (l3gd20h::READ_CTRL_REGS): {
if (packet[1] == ctrlReg1Value and packet[2] == ctrlReg2Value and if (packet[1] == ctrlReg1Value and packet[2] == ctrlReg2Value and
packet[3] == ctrlReg3Value and packet[4] == ctrlReg4Value and packet[3] == ctrlReg3Value and packet[4] == ctrlReg4Value and
packet[5] == ctrlReg5Value) { packet[5] == ctrlReg5Value) {
@@ -167,7 +167,7 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
} }
break; break;
} }
case (L3GD20H::READ_REGS): { case (l3gd20h::READ_REGS): {
if (packet[1] != ctrlReg1Value and packet[2] != ctrlReg2Value and if (packet[1] != ctrlReg1Value and packet[2] != ctrlReg2Value and
packet[3] != ctrlReg3Value and packet[4] != ctrlReg4Value and packet[3] != ctrlReg3Value and packet[4] != ctrlReg4Value and
packet[5] != ctrlReg5Value) { packet[5] != ctrlReg5Value) {
@@ -178,16 +178,16 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
} }
} }
statusReg = packet[L3GD20H::STATUS_IDX]; statusReg = packet[l3gd20h::STATUS_IDX];
int16_t angVelocXRaw = packet[L3GD20H::OUT_X_H] << 8 | packet[L3GD20H::OUT_X_L]; int16_t angVelocXRaw = packet[l3gd20h::OUT_X_H] << 8 | packet[l3gd20h::OUT_X_L];
int16_t angVelocYRaw = packet[L3GD20H::OUT_Y_H] << 8 | packet[L3GD20H::OUT_Y_L]; int16_t angVelocYRaw = packet[l3gd20h::OUT_Y_H] << 8 | packet[l3gd20h::OUT_Y_L];
int16_t angVelocZRaw = packet[L3GD20H::OUT_Z_H] << 8 | packet[L3GD20H::OUT_Z_L]; int16_t angVelocZRaw = packet[l3gd20h::OUT_Z_H] << 8 | packet[l3gd20h::OUT_Z_L];
float angVelocX = angVelocXRaw * sensitivity; float angVelocX = angVelocXRaw * sensitivity;
float angVelocY = angVelocYRaw * sensitivity; float angVelocY = angVelocYRaw * sensitivity;
float angVelocZ = angVelocZRaw * sensitivity; float angVelocZ = angVelocZRaw * sensitivity;
int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; int8_t temperaturOffset = (-1) * packet[l3gd20h::TEMPERATURE_IDX];
float temperature = 25.0 + temperaturOffset; float temperature = 25.0 + temperaturOffset;
if (periodicPrintout) { if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) { if (debugDivider.checkAndIncrement()) {
@@ -248,19 +248,19 @@ void GyroHandlerL3GD20H::setToGoToNormalMode(bool enable) { this->goNormalModeIm
ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) { LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, new PoolEntry<float>({0.0})); localDataPoolMap.emplace(l3gd20h::ANG_VELOC_X, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry<float>({0.0})); localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Y, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry<float>({0.0})); localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Z, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry<float>({0.0})); localDataPoolMap.emplace(l3gd20h::TEMPERATURE, new PoolEntry<float>({0.0}));
poolManager.subscribeForRegularPeriodicPacket( poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 10.0)); subdp::RegularHkPeriodicParams(dataset.getSid(), false, 10.0));
return returnvalue::OK; return returnvalue::OK;
} }
void GyroHandlerL3GD20H::fillCommandAndReplyMap() { void GyroHandlerL3GD20H::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(L3GD20H::READ_REGS, 1, &dataset); insertInCommandAndReplyMap(l3gd20h::READ_REGS, 1, &dataset);
insertInCommandAndReplyMap(L3GD20H::CONFIGURE_CTRL_REGS, 1); insertInCommandAndReplyMap(l3gd20h::CONFIGURE_CTRL_REGS, 1);
insertInCommandAndReplyMap(L3GD20H::READ_CTRL_REGS, 1); insertInCommandAndReplyMap(l3gd20h::READ_CTRL_REGS, 1);
} }
void GyroHandlerL3GD20H::modeChanged() { internalState = InternalState::NONE; } void GyroHandlerL3GD20H::modeChanged() { internalState = InternalState::NONE; }

View File

@@ -3,8 +3,7 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h> #include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h> #include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
#include "devicedefinitions/GyroL3GD20Definitions.h"
/** /**
* @brief Device Handler for the L3GD20H gyroscope sensor * @brief Device Handler for the L3GD20H gyroscope sensor
@@ -59,9 +58,9 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
uint32_t transitionDelayMs = 0; uint32_t transitionDelayMs = 0;
GyroPrimaryDataset dataset; GyroPrimaryDataset dataset;
float absLimitX = L3GD20H::RANGE_DPS_00; float absLimitX = l3gd20h::RANGE_DPS_00;
float absLimitY = L3GD20H::RANGE_DPS_00; float absLimitY = l3gd20h::RANGE_DPS_00;
float absLimitZ = L3GD20H::RANGE_DPS_00; float absLimitZ = l3gd20h::RANGE_DPS_00;
enum class InternalState { NONE, CONFIGURE, CHECK_REGS, NORMAL }; enum class InternalState { NONE, CONFIGURE, CHECK_REGS, NORMAL };
InternalState internalState = InternalState::NONE; InternalState internalState = InternalState::NONE;
@@ -70,16 +69,16 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
uint8_t statusReg = 0; uint8_t statusReg = 0;
bool goNormalModeImmediately = false; bool goNormalModeImmediately = false;
uint8_t ctrlReg1Value = L3GD20H::CTRL_REG_1_VAL; uint8_t ctrlReg1Value = l3gd20h::CTRL_REG_1_VAL;
uint8_t ctrlReg2Value = L3GD20H::CTRL_REG_2_VAL; uint8_t ctrlReg2Value = l3gd20h::CTRL_REG_2_VAL;
uint8_t ctrlReg3Value = L3GD20H::CTRL_REG_3_VAL; uint8_t ctrlReg3Value = l3gd20h::CTRL_REG_3_VAL;
uint8_t ctrlReg4Value = L3GD20H::CTRL_REG_4_VAL; uint8_t ctrlReg4Value = l3gd20h::CTRL_REG_4_VAL;
uint8_t ctrlReg5Value = L3GD20H::CTRL_REG_5_VAL; uint8_t ctrlReg5Value = l3gd20h::CTRL_REG_5_VAL;
uint8_t commandBuffer[L3GD20H::READ_LEN + 1]; uint8_t commandBuffer[l3gd20h::READ_LEN + 1];
// Set default value // Set default value
float sensitivity = L3GD20H::SENSITIVITY_00; float sensitivity = l3gd20h::SENSITIVITY_00;
bool periodicPrintout = false; bool periodicPrintout = false;
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3); PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);

View File

@@ -10,11 +10,11 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom
dataset(this), dataset(this),
transitionDelay(transitionDelay) { transitionDelay(transitionDelay) {
// Set to default values right away // Set to default values right away
registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT; registers[0] = mgmLis3::CTRL_REG1_DEFAULT;
registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT; registers[1] = mgmLis3::CTRL_REG2_DEFAULT;
registers[2] = MGMLIS3MDL::CTRL_REG3_DEFAULT; registers[2] = mgmLis3::CTRL_REG3_DEFAULT;
registers[3] = MGMLIS3MDL::CTRL_REG4_DEFAULT; registers[3] = mgmLis3::CTRL_REG4_DEFAULT;
registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT; registers[4] = mgmLis3::CTRL_REG5_DEFAULT;
} }
MgmLIS3MDLHandler::~MgmLIS3MDLHandler() {} MgmLIS3MDLHandler::~MgmLIS3MDLHandler() {}
@@ -63,15 +63,15 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t
return DeviceHandlerBase::NOTHING_TO_SEND; return DeviceHandlerBase::NOTHING_TO_SEND;
} }
case (InternalState::STATE_FIRST_CONTACT): { case (InternalState::STATE_FIRST_CONTACT): {
*id = MGMLIS3MDL::IDENTIFY_DEVICE; *id = mgmLis3::IDENTIFY_DEVICE;
break; break;
} }
case (InternalState::STATE_SETUP): { case (InternalState::STATE_SETUP): {
*id = MGMLIS3MDL::SETUP_MGM; *id = mgmLis3::SETUP_MGM;
break; break;
} }
case (InternalState::STATE_CHECK_REGISTERS): { case (InternalState::STATE_CHECK_REGISTERS): {
*id = MGMLIS3MDL::READ_CONFIG_AND_DATA; *id = mgmLis3::READ_CONFIG_AND_DATA;
break; break;
} }
default: { default: {
@@ -88,28 +88,12 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t
return buildCommandFromCommand(*id, NULL, 0); return buildCommandFromCommand(*id, NULL, 0);
} }
uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) {
command |= (1 << MGMLIS3MDL::RW_BIT);
if (continuousCom == true) {
command |= (1 << MGMLIS3MDL::MS_BIT);
}
return command;
}
uint8_t MgmLIS3MDLHandler::writeCommand(uint8_t command, bool continuousCom) {
command &= ~(1 << MGMLIS3MDL::RW_BIT);
if (continuousCom == true) {
command |= (1 << MGMLIS3MDL::MS_BIT);
}
return command;
}
void MgmLIS3MDLHandler::setupMgm() { void MgmLIS3MDLHandler::setupMgm() {
registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT; registers[0] = mgmLis3::CTRL_REG1_DEFAULT;
registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT; registers[1] = mgmLis3::CTRL_REG2_DEFAULT;
registers[2] = MGMLIS3MDL::CTRL_REG3_DEFAULT; registers[2] = mgmLis3::CTRL_REG3_DEFAULT;
registers[3] = MGMLIS3MDL::CTRL_REG4_DEFAULT; registers[3] = mgmLis3::CTRL_REG4_DEFAULT;
registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT; registers[4] = mgmLis3::CTRL_REG5_DEFAULT;
prepareCtrlRegisterWrite(); prepareCtrlRegisterWrite();
} }
@@ -117,11 +101,11 @@ void MgmLIS3MDLHandler::setupMgm() {
ReturnValue_t MgmLIS3MDLHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) { ReturnValue_t MgmLIS3MDLHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
// Data/config register will be read in an alternating manner. // Data/config register will be read in an alternating manner.
if (communicationStep == CommunicationStep::DATA) { if (communicationStep == CommunicationStep::DATA) {
*id = MGMLIS3MDL::READ_CONFIG_AND_DATA; *id = mgmLis3::READ_CONFIG_AND_DATA;
communicationStep = CommunicationStep::TEMPERATURE; communicationStep = CommunicationStep::TEMPERATURE;
return buildCommandFromCommand(*id, NULL, 0); return buildCommandFromCommand(*id, NULL, 0);
} else { } else {
*id = MGMLIS3MDL::READ_TEMPERATURE; *id = mgmLis3::READ_TEMPERATURE;
communicationStep = CommunicationStep::DATA; communicationStep = CommunicationStep::DATA;
return buildCommandFromCommand(*id, NULL, 0); return buildCommandFromCommand(*id, NULL, 0);
} }
@@ -131,33 +115,33 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic
const uint8_t *commandData, const uint8_t *commandData,
size_t commandDataLen) { size_t commandDataLen) {
switch (deviceCommand) { switch (deviceCommand) {
case (MGMLIS3MDL::READ_CONFIG_AND_DATA): { case (mgmLis3::READ_CONFIG_AND_DATA): {
std::memset(commandBuffer, 0, sizeof(commandBuffer)); std::memset(commandBuffer, 0, sizeof(commandBuffer));
commandBuffer[0] = readCommand(MGMLIS3MDL::CTRL_REG1, true); commandBuffer[0] = mgmLis3::readCommand(mgmLis3::CTRL_REG1, true);
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1; rawPacketLen = mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1;
return returnvalue::OK; return returnvalue::OK;
} }
case (MGMLIS3MDL::READ_TEMPERATURE): { case (mgmLis3::READ_TEMPERATURE): {
std::memset(commandBuffer, 0, 3); std::memset(commandBuffer, 0, 3);
commandBuffer[0] = readCommand(MGMLIS3MDL::TEMP_LOWBYTE, true); commandBuffer[0] = mgmLis3::readCommand(mgmLis3::TEMP_LOWBYTE, true);
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 3; rawPacketLen = 3;
return returnvalue::OK; return returnvalue::OK;
} }
case (MGMLIS3MDL::IDENTIFY_DEVICE): { case (mgmLis3::IDENTIFY_DEVICE): {
return identifyDevice(); return identifyDevice();
} }
case (MGMLIS3MDL::TEMP_SENSOR_ENABLE): { case (mgmLis3::TEMP_SENSOR_ENABLE): {
return enableTemperatureSensor(commandData, commandDataLen); return enableTemperatureSensor(commandData, commandDataLen);
} }
case (MGMLIS3MDL::SETUP_MGM): { case (mgmLis3::SETUP_MGM): {
setupMgm(); setupMgm();
return returnvalue::OK; return returnvalue::OK;
} }
case (MGMLIS3MDL::ACCURACY_OP_MODE_SET): { case (mgmLis3::ACCURACY_OP_MODE_SET): {
return setOperatingMode(commandData, commandDataLen); return setOperatingMode(commandData, commandDataLen);
} }
default: default:
@@ -168,7 +152,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildCommandFromCommand(DeviceCommandId_t devic
ReturnValue_t MgmLIS3MDLHandler::identifyDevice() { ReturnValue_t MgmLIS3MDLHandler::identifyDevice() {
uint32_t size = 2; uint32_t size = 2;
commandBuffer[0] = readCommand(MGMLIS3MDL::IDENTIFY_DEVICE_REG_ADDR); commandBuffer[0] = mgmLis3::readCommand(mgmLis3::IDENTIFY_DEVICE_REG_ADDR);
commandBuffer[1] = 0x00; commandBuffer[1] = 0x00;
rawPacket = commandBuffer; rawPacket = commandBuffer;
@@ -180,9 +164,9 @@ ReturnValue_t MgmLIS3MDLHandler::identifyDevice() {
ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) { DeviceCommandId_t *foundId, size_t *foundLen) {
*foundLen = len; *foundLen = len;
if (len == MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1) { if (len == mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1) {
*foundLen = len; *foundLen = len;
*foundId = MGMLIS3MDL::READ_CONFIG_AND_DATA; *foundId = mgmLis3::READ_CONFIG_AND_DATA;
// Check validity by checking config registers // Check validity by checking config registers
if (start[1] != registers[0] or start[2] != registers[1] or start[3] != registers[2] or if (start[1] != registers[0] or start[2] != registers[1] or start[3] != registers[2] or
start[4] != registers[3] or start[5] != registers[4]) { start[4] != registers[3] or start[5] != registers[4]) {
@@ -199,17 +183,17 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len,
commandExecuted = true; commandExecuted = true;
} }
} else if (len == MGMLIS3MDL::TEMPERATURE_REPLY_LEN) { } else if (len == mgmLis3::TEMPERATURE_REPLY_LEN) {
*foundLen = len; *foundLen = len;
*foundId = MGMLIS3MDL::READ_TEMPERATURE; *foundId = mgmLis3::READ_TEMPERATURE;
} else if (len == MGMLIS3MDL::SETUP_REPLY_LEN) { } else if (len == mgmLis3::SETUP_REPLY_LEN) {
*foundLen = len; *foundLen = len;
*foundId = MGMLIS3MDL::SETUP_MGM; *foundId = mgmLis3::SETUP_MGM;
} else if (len == SINGLE_COMMAND_ANSWER_LEN) { } else if (len == SINGLE_COMMAND_ANSWER_LEN) {
*foundLen = len; *foundLen = len;
*foundId = getPendingCommand(); *foundId = getPendingCommand();
if (*foundId == MGMLIS3MDL::IDENTIFY_DEVICE) { if (*foundId == mgmLis3::IDENTIFY_DEVICE) {
if (start[1] != MGMLIS3MDL::DEVICE_ID) { if (start[1] != mgmLis3::DEVICE_ID) {
#if FSFW_VERBOSE_LEVEL >= 1 #if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "MGMHandlerLIS3MDL::scanForReply: " sif::warning << "MGMHandlerLIS3MDL::scanForReply: "
@@ -241,30 +225,31 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len,
} }
ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
switch (id) { switch (id) {
case MGMLIS3MDL::IDENTIFY_DEVICE: { case mgmLis3::IDENTIFY_DEVICE: {
break; break;
} }
case MGMLIS3MDL::SETUP_MGM: { case mgmLis3::SETUP_MGM: {
break; break;
} }
case MGMLIS3MDL::READ_CONFIG_AND_DATA: { case mgmLis3::READ_CONFIG_AND_DATA: {
using namespace mgmLis3;
// TODO: Store configuration in new local datasets. // TODO: Store configuration in new local datasets.
float sensitivityFactor = getSensitivityFactor(getSensitivity(registers[2])); float sensitivityFactor = getSensitivityFactor(getSensitivity(registers[2]));
int16_t mgmMeasurementRawX = int16_t mgmMeasurementRawX =
packet[MGMLIS3MDL::X_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::X_LOWBYTE_IDX]; packet[mgmLis3::X_HIGHBYTE_IDX] << 8 | packet[mgmLis3::X_LOWBYTE_IDX];
int16_t mgmMeasurementRawY = int16_t mgmMeasurementRawY =
packet[MGMLIS3MDL::Y_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::Y_LOWBYTE_IDX]; packet[mgmLis3::Y_HIGHBYTE_IDX] << 8 | packet[mgmLis3::Y_LOWBYTE_IDX];
int16_t mgmMeasurementRawZ = int16_t mgmMeasurementRawZ =
packet[MGMLIS3MDL::Z_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::Z_LOWBYTE_IDX]; packet[mgmLis3::Z_HIGHBYTE_IDX] << 8 | packet[mgmLis3::Z_LOWBYTE_IDX];
// Target value in microtesla // Target value in microtesla
float mgmX = static_cast<float>(mgmMeasurementRawX) * sensitivityFactor * float mgmX = static_cast<float>(mgmMeasurementRawX) * sensitivityFactor *
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR; mgmLis3::GAUSS_TO_MICROTESLA_FACTOR;
float mgmY = static_cast<float>(mgmMeasurementRawY) * sensitivityFactor * float mgmY = static_cast<float>(mgmMeasurementRawY) * sensitivityFactor *
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR; mgmLis3::GAUSS_TO_MICROTESLA_FACTOR;
float mgmZ = static_cast<float>(mgmMeasurementRawZ) * sensitivityFactor * float mgmZ = static_cast<float>(mgmMeasurementRawZ) * sensitivityFactor *
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR; mgmLis3::GAUSS_TO_MICROTESLA_FACTOR;
if (periodicPrintout) { if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) { if (debugDivider.checkAndIncrement()) {
@@ -306,7 +291,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
break; break;
} }
case MGMLIS3MDL::READ_TEMPERATURE: { case mgmLis3::READ_TEMPERATURE: {
int16_t tempValueRaw = packet[2] << 8 | packet[1]; int16_t tempValueRaw = packet[2] << 8 | packet[1];
float tempValue = 25.0 + ((static_cast<float>(tempValueRaw)) / 8.0); float tempValue = 25.0 + ((static_cast<float>(tempValueRaw)) / 8.0);
if (periodicPrintout) { if (periodicPrintout) {
@@ -334,41 +319,6 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
return returnvalue::OK; return returnvalue::OK;
} }
MGMLIS3MDL::Sensitivies MgmLIS3MDLHandler::getSensitivity(uint8_t ctrlRegister2) {
bool fs0Set = ctrlRegister2 & (1 << MGMLIS3MDL::FSO); // Checks if FS0 bit is set
bool fs1Set = ctrlRegister2 & (1 << MGMLIS3MDL::FS1); // Checks if FS1 bit is set
if (fs0Set && fs1Set)
return MGMLIS3MDL::Sensitivies::GAUSS_16;
else if (!fs0Set && fs1Set)
return MGMLIS3MDL::Sensitivies::GAUSS_12;
else if (fs0Set && !fs1Set)
return MGMLIS3MDL::Sensitivies::GAUSS_8;
else
return MGMLIS3MDL::Sensitivies::GAUSS_4;
}
float MgmLIS3MDLHandler::getSensitivityFactor(MGMLIS3MDL::Sensitivies sens) {
switch (sens) {
case (MGMLIS3MDL::GAUSS_4): {
return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_4_SENS;
}
case (MGMLIS3MDL::GAUSS_8): {
return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_8_SENS;
}
case (MGMLIS3MDL::GAUSS_12): {
return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_12_SENS;
}
case (MGMLIS3MDL::GAUSS_16): {
return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_16_SENS;
}
default: {
// Should never happen
return MGMLIS3MDL::FIELD_LSB_PER_GAUSS_4_SENS;
}
}
}
ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandData, ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandData,
size_t commandDataLen) { size_t commandDataLen) {
if (commandData == nullptr) { if (commandData == nullptr) {
@@ -376,16 +326,16 @@ ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandD
} }
triggerEvent(CHANGE_OF_SETUP_PARAMETER); triggerEvent(CHANGE_OF_SETUP_PARAMETER);
uint32_t size = 2; uint32_t size = 2;
commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1); commandBuffer[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1);
if (commandDataLen > 1) { if (commandDataLen > 1) {
return INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS; return INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
} }
switch (commandData[0]) { switch (commandData[0]) {
case (MGMLIS3MDL::ON): { case (mgmLis3::ON): {
commandBuffer[1] = registers[0] | (1 << 7); commandBuffer[1] = registers[0] | (1 << 7);
break; break;
} }
case (MGMLIS3MDL::OFF): { case (mgmLis3::OFF): {
commandBuffer[1] = registers[0] & ~(1 << 7); commandBuffer[1] = registers[0] & ~(1 << 7);
break; break;
} }
@@ -408,23 +358,23 @@ ReturnValue_t MgmLIS3MDLHandler::setOperatingMode(const uint8_t *commandData,
} }
switch (commandData[0]) { switch (commandData[0]) {
case MGMLIS3MDL::LOW: case mgmLis3::LOW:
registers[0] = (registers[0] & (~(1 << MGMLIS3MDL::OM1))) & (~(1 << MGMLIS3MDL::OM0)); registers[0] = (registers[0] & (~(1 << mgmLis3::OM1))) & (~(1 << mgmLis3::OM0));
registers[3] = (registers[3] & (~(1 << MGMLIS3MDL::OMZ1))) & (~(1 << MGMLIS3MDL::OMZ0)); registers[3] = (registers[3] & (~(1 << mgmLis3::OMZ1))) & (~(1 << mgmLis3::OMZ0));
break; break;
case MGMLIS3MDL::MEDIUM: case mgmLis3::MEDIUM:
registers[0] = (registers[0] & (~(1 << MGMLIS3MDL::OM1))) | (1 << MGMLIS3MDL::OM0); registers[0] = (registers[0] & (~(1 << mgmLis3::OM1))) | (1 << mgmLis3::OM0);
registers[3] = (registers[3] & (~(1 << MGMLIS3MDL::OMZ1))) | (1 << MGMLIS3MDL::OMZ0); registers[3] = (registers[3] & (~(1 << mgmLis3::OMZ1))) | (1 << mgmLis3::OMZ0);
break; break;
case MGMLIS3MDL::HIGH: case mgmLis3::HIGH:
registers[0] = (registers[0] | (1 << MGMLIS3MDL::OM1)) & (~(1 << MGMLIS3MDL::OM0)); registers[0] = (registers[0] | (1 << mgmLis3::OM1)) & (~(1 << mgmLis3::OM0));
registers[3] = (registers[3] | (1 << MGMLIS3MDL::OMZ1)) & (~(1 << MGMLIS3MDL::OMZ0)); registers[3] = (registers[3] | (1 << mgmLis3::OMZ1)) & (~(1 << mgmLis3::OMZ0));
break; break;
case MGMLIS3MDL::ULTRA: case mgmLis3::ULTRA:
registers[0] = (registers[0] | (1 << MGMLIS3MDL::OM1)) | (1 << MGMLIS3MDL::OM0); registers[0] = (registers[0] | (1 << mgmLis3::OM1)) | (1 << mgmLis3::OM0);
registers[3] = (registers[3] | (1 << MGMLIS3MDL::OMZ1)) | (1 << MGMLIS3MDL::OMZ0); registers[3] = (registers[3] | (1 << mgmLis3::OMZ1)) | (1 << mgmLis3::OMZ0);
break; break;
default: default:
break; break;
@@ -434,24 +384,24 @@ ReturnValue_t MgmLIS3MDLHandler::setOperatingMode(const uint8_t *commandData,
} }
void MgmLIS3MDLHandler::fillCommandAndReplyMap() { void MgmLIS3MDLHandler::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(MGMLIS3MDL::READ_CONFIG_AND_DATA, 1, &dataset); insertInCommandAndReplyMap(mgmLis3::READ_CONFIG_AND_DATA, 1, &dataset);
insertInCommandAndReplyMap(MGMLIS3MDL::READ_TEMPERATURE, 1); insertInCommandAndReplyMap(mgmLis3::READ_TEMPERATURE, 1);
insertInCommandAndReplyMap(MGMLIS3MDL::SETUP_MGM, 1); insertInCommandAndReplyMap(mgmLis3::SETUP_MGM, 1);
insertInCommandAndReplyMap(MGMLIS3MDL::IDENTIFY_DEVICE, 1); insertInCommandAndReplyMap(mgmLis3::IDENTIFY_DEVICE, 1);
insertInCommandAndReplyMap(MGMLIS3MDL::TEMP_SENSOR_ENABLE, 1); insertInCommandAndReplyMap(mgmLis3::TEMP_SENSOR_ENABLE, 1);
insertInCommandAndReplyMap(MGMLIS3MDL::ACCURACY_OP_MODE_SET, 1); insertInCommandAndReplyMap(mgmLis3::ACCURACY_OP_MODE_SET, 1);
} }
void MgmLIS3MDLHandler::setToGoToNormalMode(bool enable) { this->goToNormalMode = enable; } void MgmLIS3MDLHandler::setToGoToNormalMode(bool enable) { this->goToNormalMode = enable; }
ReturnValue_t MgmLIS3MDLHandler::prepareCtrlRegisterWrite() { ReturnValue_t MgmLIS3MDLHandler::prepareCtrlRegisterWrite() {
commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1, true); commandBuffer[0] = mgmLis3::writeCommand(mgmLis3::CTRL_REG1, true);
for (size_t i = 0; i < MGMLIS3MDL::NR_OF_CTRL_REGISTERS; i++) { for (size_t i = 0; i < mgmLis3::NR_OF_CTRL_REGISTERS; i++) {
commandBuffer[i + 1] = registers[i]; commandBuffer[i + 1] = registers[i];
} }
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = MGMLIS3MDL::NR_OF_CTRL_REGISTERS + 1; rawPacketLen = mgmLis3::NR_OF_CTRL_REGISTERS + 1;
// We dont have to check if this is working because we just did i // We dont have to check if this is working because we just did i
return returnvalue::OK; return returnvalue::OK;
@@ -467,8 +417,8 @@ void MgmLIS3MDLHandler::modeChanged(void) { internalState = InternalState::STATE
ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) { LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTHS, &mgmXYZ); localDataPoolMap.emplace(mgmLis3::FIELD_STRENGTHS, &mgmXYZ);
localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, &temperature); localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, &temperature);
poolManager.subscribeForRegularPeriodicPacket({dataset.getSid(), false, 10.0}); poolManager.subscribeForRegularPeriodicPacket({dataset.getSid(), false, 10.0});
return returnvalue::OK; return returnvalue::OK;
} }

View File

@@ -1,7 +1,8 @@
#ifndef MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ #ifndef MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ #define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#include "devicedefinitions/MgmLIS3HandlerDefs.h" #include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
#include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h" #include "fsfw/globalfunctions/PeriodicOperationDivider.h"
@@ -66,7 +67,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
LocalDataPoolManager &poolManager) override; LocalDataPoolManager &poolManager) override;
private: private:
MGMLIS3MDL::MgmPrimaryDataset dataset; mgmLis3::MgmPrimaryDataset dataset;
// Length a single command SPI answer // Length a single command SPI answer
static const uint8_t SINGLE_COMMAND_ANSWER_LEN = 2; static const uint8_t SINGLE_COMMAND_ANSWER_LEN = 2;
@@ -74,7 +75,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
// Single SPI command has 2 bytes, first for adress, second for content // Single SPI command has 2 bytes, first for adress, second for content
size_t singleComandSize = 2; size_t singleComandSize = 2;
// Has the size for all adresses of the lis3mdl + the continous write bit // Has the size for all adresses of the lis3mdl + the continous write bit
uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1]; uint8_t commandBuffer[mgmLis3::NR_OF_DATA_AND_CFG_REGISTERS + 1];
float absLimitX = 100; float absLimitX = 100;
float absLimitY = 100; float absLimitY = 100;
@@ -85,7 +86,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
* registers when we want to change something. * registers when we want to change something.
* --> everytime we change set a register we have to save it * --> everytime we change set a register we have to save it
*/ */
uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS]; uint8_t registers[mgmLis3::NR_OF_CTRL_REGISTERS];
uint8_t statusRegister = 0; uint8_t statusRegister = 0;
bool goToNormalMode = false; bool goToNormalMode = false;
@@ -107,35 +108,6 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Device specific commands and variables */ /* Device specific commands and variables */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/**
* Sets the read bit for the command
* @param single command to set the read-bit at
* @param boolean to select a continuous read bit, default = false
*/
uint8_t readCommand(uint8_t command, bool continuousCom = false);
/**
* Sets the write bit for the command
* @param single command to set the write-bit at
* @param boolean to select a continuous write bit, default = false
*/
uint8_t writeCommand(uint8_t command, bool continuousCom = false);
/**
* This Method gets the full scale for the measurement range
* e.g.: +- 4 gauss. See p.25 datasheet.
* @return The ReturnValue does not contain the sign of the value
*/
MGMLIS3MDL::Sensitivies getSensitivity(uint8_t ctrlReg2);
/**
* The 16 bit value needs to be multiplied with a sensitivity factor
* which depends on the sensitivity configuration
*
* @param sens Configured sensitivity of the LIS3 device
* @return Multiplication factor to get the sensor value from raw data.
*/
float getSensitivityFactor(MGMLIS3MDL::Sensitivies sens);
/** /**
* This Command detects the device ID * This Command detects the device ID

View File

@@ -63,21 +63,21 @@ ReturnValue_t MgmRM3100Handler::buildTransitionDeviceCommand(DeviceCommandId_t *
return NOTHING_TO_SEND; return NOTHING_TO_SEND;
} }
case (InternalState::CONFIGURE_CMM): { case (InternalState::CONFIGURE_CMM): {
*id = RM3100::CONFIGURE_CMM; *id = mgmRm3100::CONFIGURE_CMM;
break; break;
} }
case (InternalState::READ_CMM): { case (InternalState::READ_CMM): {
*id = RM3100::READ_CMM; *id = mgmRm3100::READ_CMM;
break; break;
} }
case (InternalState::STATE_CONFIGURE_TMRC): { case (InternalState::STATE_CONFIGURE_TMRC): {
commandBuffer[0] = RM3100::TMRC_DEFAULT_VALUE; commandBuffer[0] = mgmRm3100::TMRC_DEFAULT_VALUE;
commandLen = 1; commandLen = 1;
*id = RM3100::CONFIGURE_TMRC; *id = mgmRm3100::CONFIGURE_TMRC;
break; break;
} }
case (InternalState::STATE_READ_TMRC): { case (InternalState::STATE_READ_TMRC): {
*id = RM3100::READ_TMRC; *id = mgmRm3100::READ_TMRC;
break; break;
} }
default: default:
@@ -103,42 +103,42 @@ ReturnValue_t MgmRM3100Handler::buildCommandFromCommand(DeviceCommandId_t device
const uint8_t *commandData, const uint8_t *commandData,
size_t commandDataLen) { size_t commandDataLen) {
switch (deviceCommand) { switch (deviceCommand) {
case (RM3100::CONFIGURE_CMM): { case (mgmRm3100::CONFIGURE_CMM): {
commandBuffer[0] = RM3100::CMM_REGISTER; commandBuffer[0] = mgmRm3100::CMM_REGISTER;
commandBuffer[1] = RM3100::CMM_VALUE; commandBuffer[1] = mgmRm3100::CMM_VALUE;
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 2; rawPacketLen = 2;
break; break;
} }
case (RM3100::READ_CMM): { case (mgmRm3100::READ_CMM): {
commandBuffer[0] = RM3100::CMM_REGISTER | RM3100::READ_MASK; commandBuffer[0] = mgmRm3100::CMM_REGISTER | mgmRm3100::READ_MASK;
commandBuffer[1] = 0; commandBuffer[1] = 0;
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 2; rawPacketLen = 2;
break; break;
} }
case (RM3100::CONFIGURE_TMRC): { case (mgmRm3100::CONFIGURE_TMRC): {
return handleTmrcConfigCommand(deviceCommand, commandData, commandDataLen); return handleTmrcConfigCommand(deviceCommand, commandData, commandDataLen);
} }
case (RM3100::READ_TMRC): { case (mgmRm3100::READ_TMRC): {
commandBuffer[0] = RM3100::TMRC_REGISTER | RM3100::READ_MASK; commandBuffer[0] = mgmRm3100::TMRC_REGISTER | mgmRm3100::READ_MASK;
commandBuffer[1] = 0; commandBuffer[1] = 0;
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 2; rawPacketLen = 2;
break; break;
} }
case (RM3100::CONFIGURE_CYCLE_COUNT): { case (mgmRm3100::CONFIGURE_CYCLE_COUNT): {
return handleCycleCountConfigCommand(deviceCommand, commandData, commandDataLen); return handleCycleCountConfigCommand(deviceCommand, commandData, commandDataLen);
} }
case (RM3100::READ_CYCLE_COUNT): { case (mgmRm3100::READ_CYCLE_COUNT): {
commandBuffer[0] = RM3100::CYCLE_COUNT_START_REGISTER | RM3100::READ_MASK; commandBuffer[0] = mgmRm3100::CYCLE_COUNT_START_REGISTER | mgmRm3100::READ_MASK;
std::memset(commandBuffer + 1, 0, 6); std::memset(commandBuffer + 1, 0, 6);
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 7; rawPacketLen = 7;
break; break;
} }
case (RM3100::READ_DATA): { case (mgmRm3100::READ_DATA): {
commandBuffer[0] = RM3100::MEASUREMENT_REG_START | RM3100::READ_MASK; commandBuffer[0] = mgmRm3100::MEASUREMENT_REG_START | mgmRm3100::READ_MASK;
std::memset(commandBuffer + 1, 0, 9); std::memset(commandBuffer + 1, 0, 9);
rawPacketLen = 10; rawPacketLen = 10;
break; break;
@@ -150,7 +150,7 @@ ReturnValue_t MgmRM3100Handler::buildCommandFromCommand(DeviceCommandId_t device
} }
ReturnValue_t MgmRM3100Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) { ReturnValue_t MgmRM3100Handler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
*id = RM3100::READ_DATA; *id = mgmRm3100::READ_DATA;
return buildCommandFromCommand(*id, nullptr, 0); return buildCommandFromCommand(*id, nullptr, 0);
} }
@@ -165,16 +165,16 @@ ReturnValue_t MgmRM3100Handler::scanForReply(const uint8_t *start, size_t len,
ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (id) { switch (id) {
case (RM3100::CONFIGURE_CMM): case (mgmRm3100::CONFIGURE_CMM):
case (RM3100::CONFIGURE_CYCLE_COUNT): case (mgmRm3100::CONFIGURE_CYCLE_COUNT):
case (RM3100::CONFIGURE_TMRC): { case (mgmRm3100::CONFIGURE_TMRC): {
// We can only check whether write was successful with read operation // We can only check whether write was successful with read operation
if (getMode() == _MODE_START_UP) { if (getMode() == _MODE_START_UP) {
commandExecuted = true; commandExecuted = true;
} }
break; break;
} }
case (RM3100::READ_CMM): { case (mgmRm3100::READ_CMM): {
uint8_t cmmValue = packet[1]; uint8_t cmmValue = packet[1];
// We clear the seventh bit in any case // We clear the seventh bit in any case
// because this one is zero sometimes for some reason // because this one is zero sometimes for some reason
@@ -188,7 +188,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const
} }
break; break;
} }
case (RM3100::READ_TMRC): { case (mgmRm3100::READ_TMRC): {
if (packet[1] == tmrcRegValue) { if (packet[1] == tmrcRegValue) {
commandExecuted = true; commandExecuted = true;
// Reading TMRC was commanded. Trigger event to inform ground // Reading TMRC was commanded. Trigger event to inform ground
@@ -202,7 +202,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const
} }
break; break;
} }
case (RM3100::READ_CYCLE_COUNT): { case (mgmRm3100::READ_CYCLE_COUNT): {
uint16_t cycleCountX = packet[1] << 8 | packet[2]; uint16_t cycleCountX = packet[1] << 8 | packet[2];
uint16_t cycleCountY = packet[3] << 8 | packet[4]; uint16_t cycleCountY = packet[3] << 8 | packet[4];
uint16_t cycleCountZ = packet[5] << 8 | packet[6]; uint16_t cycleCountZ = packet[5] << 8 | packet[6];
@@ -217,7 +217,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const
} }
break; break;
} }
case (RM3100::READ_DATA): { case (mgmRm3100::READ_DATA): {
result = handleDataReadout(packet); result = handleDataReadout(packet);
break; break;
} }
@@ -244,7 +244,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCountConfigCommand(DeviceCommandId_t
return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; return DeviceHandlerIF::INVALID_COMMAND_PARAMETER;
} }
commandBuffer[0] = RM3100::CYCLE_COUNT_VALUE; commandBuffer[0] = mgmRm3100::CYCLE_COUNT_VALUE;
std::memcpy(commandBuffer + 1, &cycleCountRegValueX, 2); std::memcpy(commandBuffer + 1, &cycleCountRegValueX, 2);
std::memcpy(commandBuffer + 3, &cycleCountRegValueY, 2); std::memcpy(commandBuffer + 3, &cycleCountRegValueY, 2);
std::memcpy(commandBuffer + 5, &cycleCountRegValueZ, 2); std::memcpy(commandBuffer + 5, &cycleCountRegValueZ, 2);
@@ -255,7 +255,7 @@ ReturnValue_t MgmRM3100Handler::handleCycleCountConfigCommand(DeviceCommandId_t
ReturnValue_t MgmRM3100Handler::handleCycleCommand(bool oneCycleValue, const uint8_t *commandData, ReturnValue_t MgmRM3100Handler::handleCycleCommand(bool oneCycleValue, const uint8_t *commandData,
size_t commandDataLen) { size_t commandDataLen) {
RM3100::CycleCountCommand command(oneCycleValue); mgmRm3100::CycleCountCommand command(oneCycleValue);
ReturnValue_t result = ReturnValue_t result =
command.deSerialize(&commandData, &commandDataLen, SerializeIF::Endianness::BIG); command.deSerialize(&commandData, &commandDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
@@ -284,7 +284,7 @@ ReturnValue_t MgmRM3100Handler::handleTmrcConfigCommand(DeviceCommandId_t device
return DeviceHandlerIF::INVALID_COMMAND_PARAMETER; return DeviceHandlerIF::INVALID_COMMAND_PARAMETER;
} }
commandBuffer[0] = RM3100::TMRC_REGISTER; commandBuffer[0] = mgmRm3100::TMRC_REGISTER;
commandBuffer[1] = commandData[0]; commandBuffer[1] = commandData[0];
tmrcRegValue = commandData[0]; tmrcRegValue = commandData[0];
rawPacketLen = 2; rawPacketLen = 2;
@@ -293,23 +293,23 @@ ReturnValue_t MgmRM3100Handler::handleTmrcConfigCommand(DeviceCommandId_t device
} }
void MgmRM3100Handler::fillCommandAndReplyMap() { void MgmRM3100Handler::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(RM3100::CONFIGURE_CMM, 3); insertInCommandAndReplyMap(mgmRm3100::CONFIGURE_CMM, 3);
insertInCommandAndReplyMap(RM3100::READ_CMM, 3); insertInCommandAndReplyMap(mgmRm3100::READ_CMM, 3);
insertInCommandAndReplyMap(RM3100::CONFIGURE_TMRC, 3); insertInCommandAndReplyMap(mgmRm3100::CONFIGURE_TMRC, 3);
insertInCommandAndReplyMap(RM3100::READ_TMRC, 3); insertInCommandAndReplyMap(mgmRm3100::READ_TMRC, 3);
insertInCommandAndReplyMap(RM3100::CONFIGURE_CYCLE_COUNT, 3); insertInCommandAndReplyMap(mgmRm3100::CONFIGURE_CYCLE_COUNT, 3);
insertInCommandAndReplyMap(RM3100::READ_CYCLE_COUNT, 3); insertInCommandAndReplyMap(mgmRm3100::READ_CYCLE_COUNT, 3);
insertInCommandAndReplyMap(RM3100::READ_DATA, 3, &primaryDataset); insertInCommandAndReplyMap(mgmRm3100::READ_DATA, 3, &primaryDataset);
} }
void MgmRM3100Handler::modeChanged() { internalState = InternalState::NONE; } void MgmRM3100Handler::modeChanged() { internalState = InternalState::NONE; }
ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) { LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(RM3100::FIELD_STRENGTHS, &mgmXYZ); localDataPoolMap.emplace(mgmRm3100::FIELD_STRENGTHS, &mgmXYZ);
poolManager.subscribeForRegularPeriodicPacket({primaryDataset.getSid(), false, 10.0}); poolManager.subscribeForRegularPeriodicPacket({primaryDataset.getSid(), false, 10.0});
return returnvalue::OK; return returnvalue::OK;
} }

View File

@@ -1,7 +1,8 @@
#ifndef MISSION_DEVICES_MGMRM3100HANDLER_H_ #ifndef MISSION_DEVICES_MGMRM3100HANDLER_H_
#define MISSION_DEVICES_MGMRM3100HANDLER_H_ #define MISSION_DEVICES_MGMRM3100HANDLER_H_
#include "devicedefinitions/MgmRM3100HandlerDefs.h" #include <fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h>
#include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h" #include "fsfw/globalfunctions/PeriodicOperationDivider.h"
@@ -69,19 +70,19 @@ class MgmRM3100Handler : public DeviceHandlerBase {
}; };
InternalState internalState = InternalState::NONE; InternalState internalState = InternalState::NONE;
bool commandExecuted = false; bool commandExecuted = false;
RM3100::Rm3100PrimaryDataset primaryDataset; mgmRm3100::Rm3100PrimaryDataset primaryDataset;
uint8_t commandBuffer[10]; uint8_t commandBuffer[10];
uint8_t commandBufferLen = 0; uint8_t commandBufferLen = 0;
uint8_t cmmRegValue = RM3100::CMM_VALUE; uint8_t cmmRegValue = mgmRm3100::CMM_VALUE;
uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE; uint8_t tmrcRegValue = mgmRm3100::TMRC_DEFAULT_VALUE;
uint16_t cycleCountRegValueX = RM3100::CYCLE_COUNT_VALUE; uint16_t cycleCountRegValueX = mgmRm3100::CYCLE_COUNT_VALUE;
uint16_t cycleCountRegValueY = RM3100::CYCLE_COUNT_VALUE; uint16_t cycleCountRegValueY = mgmRm3100::CYCLE_COUNT_VALUE;
uint16_t cycleCountRegValueZ = RM3100::CYCLE_COUNT_VALUE; uint16_t cycleCountRegValueZ = mgmRm3100::CYCLE_COUNT_VALUE;
float scaleFactorX = 1.0 / RM3100::DEFAULT_GAIN; float scaleFactorX = 1.0 / mgmRm3100::DEFAULT_GAIN;
float scaleFactorY = 1.0 / RM3100::DEFAULT_GAIN; float scaleFactorY = 1.0 / mgmRm3100::DEFAULT_GAIN;
float scaleFactorZ = 1.0 / RM3100::DEFAULT_GAIN; float scaleFactorZ = 1.0 / mgmRm3100::DEFAULT_GAIN;
bool goToNormalModeAtStartup = false; bool goToNormalModeAtStartup = false;
uint32_t transitionDelay; uint32_t transitionDelay;

View File

@@ -0,0 +1 @@
target_sources(${LIB_FSFW_NAME} PRIVATE gyroL3gHelpers.cpp mgmLis3Helpers.cpp)

View File

@@ -0,0 +1,14 @@
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
float l3gd20h::ctrlReg4ToSensitivity(uint8_t reg) {
bool fsH = reg & l3gd20h::SET_FS_1;
bool fsL = reg & l3gd20h::SET_FS_0;
if (not fsH and not fsL) {
return l3gd20h::SENSITIVITY_00;
} else if (not fsH and fsL) {
return l3gd20h::SENSITIVITY_01;
} else {
return l3gd20h::SENSITIVITY_11;
}
}

View File

@@ -6,7 +6,9 @@
#include <cstdint> #include <cstdint>
namespace L3GD20H { namespace l3gd20h {
float ctrlReg4ToSensitivity(uint8_t reg);
/* Actual size is 15 but we round up a bit */ /* Actual size is 15 but we round up a bit */
static constexpr size_t MAX_BUFFER_SIZE = 16; static constexpr size_t MAX_BUFFER_SIZE = 16;
@@ -103,31 +105,33 @@ static constexpr DeviceCommandId_t READ_REGS = 0;
static constexpr DeviceCommandId_t CONFIGURE_CTRL_REGS = 1; static constexpr DeviceCommandId_t CONFIGURE_CTRL_REGS = 1;
static constexpr DeviceCommandId_t READ_CTRL_REGS = 2; static constexpr DeviceCommandId_t READ_CTRL_REGS = 2;
static constexpr DeviceCommandId_t REQUEST = 0x70;
static constexpr DeviceCommandId_t REPLY = 0x77;
static constexpr uint32_t GYRO_DATASET_ID = READ_REGS; static constexpr uint32_t GYRO_DATASET_ID = READ_REGS;
enum GyroPoolIds : lp_id_t { ANG_VELOC_X, ANG_VELOC_Y, ANG_VELOC_Z, TEMPERATURE }; enum GyroPoolIds : lp_id_t { ANG_VELOC_X, ANG_VELOC_Y, ANG_VELOC_Z, TEMPERATURE };
} // namespace L3GD20H } // namespace l3gd20h
class GyroPrimaryDataset : public StaticLocalDataSet<5> { class GyroPrimaryDataset : public StaticLocalDataSet<5> {
public: public:
/** Constructor for data users like controllers */ /** Constructor for data users like controllers */
GyroPrimaryDataset(object_id_t mgmId) GyroPrimaryDataset(object_id_t mgmId)
: StaticLocalDataSet(sid_t(mgmId, L3GD20H::GYRO_DATASET_ID)) { : StaticLocalDataSet(sid_t(mgmId, l3gd20h::GYRO_DATASET_ID)) {
setAllVariablesReadOnly(); setAllVariablesReadOnly();
} }
/* Angular velocities in degrees per second (DPS) */
lp_var_t<float> angVelocX = lp_var_t<float>(sid.objectId, L3GD20H::ANG_VELOC_X, this);
lp_var_t<float> angVelocY = lp_var_t<float>(sid.objectId, L3GD20H::ANG_VELOC_Y, this);
lp_var_t<float> angVelocZ = lp_var_t<float>(sid.objectId, L3GD20H::ANG_VELOC_Z, this);
lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, L3GD20H::TEMPERATURE, this);
private:
friend class GyroHandlerL3GD20H;
/** Constructor for the data creator */ /** Constructor for the data creator */
GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner) GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner)
: StaticLocalDataSet(hkOwner, L3GD20H::GYRO_DATASET_ID) {} : StaticLocalDataSet(hkOwner, l3gd20h::GYRO_DATASET_ID) {}
/* Angular velocities in degrees per second (DPS) */
lp_var_t<float> angVelocX = lp_var_t<float>(sid.objectId, l3gd20h::ANG_VELOC_X, this);
lp_var_t<float> angVelocY = lp_var_t<float>(sid.objectId, l3gd20h::ANG_VELOC_Y, this);
lp_var_t<float> angVelocZ = lp_var_t<float>(sid.objectId, l3gd20h::ANG_VELOC_Z, this);
lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, l3gd20h::TEMPERATURE, this);
private:
}; };
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_ */ #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_ */

View File

@@ -0,0 +1,52 @@
#include "mgmLis3Helpers.h"
uint8_t mgmLis3::readCommand(uint8_t command, bool continuousCom) {
command |= (1 << mgmLis3::RW_BIT);
if (continuousCom == true) {
command |= (1 << mgmLis3::MS_BIT);
}
return command;
}
uint8_t mgmLis3::writeCommand(uint8_t command, bool continuousCom) {
command &= ~(1 << mgmLis3::RW_BIT);
if (continuousCom == true) {
command |= (1 << mgmLis3::MS_BIT);
}
return command;
}
mgmLis3::Sensitivies mgmLis3::getSensitivity(uint8_t ctrlRegister2) {
bool fs0Set = ctrlRegister2 & (1 << mgmLis3::FSO); // Checks if FS0 bit is set
bool fs1Set = ctrlRegister2 & (1 << mgmLis3::FS1); // Checks if FS1 bit is set
if (fs0Set && fs1Set)
return mgmLis3::Sensitivies::GAUSS_16;
else if (!fs0Set && fs1Set)
return mgmLis3::Sensitivies::GAUSS_12;
else if (fs0Set && !fs1Set)
return mgmLis3::Sensitivies::GAUSS_8;
else
return mgmLis3::Sensitivies::GAUSS_4;
}
float mgmLis3::getSensitivityFactor(mgmLis3::Sensitivies sens) {
switch (sens) {
case (mgmLis3::GAUSS_4): {
return mgmLis3::FIELD_LSB_PER_GAUSS_4_SENS;
}
case (mgmLis3::GAUSS_8): {
return mgmLis3::FIELD_LSB_PER_GAUSS_8_SENS;
}
case (mgmLis3::GAUSS_12): {
return mgmLis3::FIELD_LSB_PER_GAUSS_12_SENS;
}
case (mgmLis3::GAUSS_16): {
return mgmLis3::FIELD_LSB_PER_GAUSS_16_SENS;
}
default: {
// Should never happen
return mgmLis3::FIELD_LSB_PER_GAUSS_4_SENS;
}
}
}

View File

@@ -7,13 +7,43 @@
#include <cstdint> #include <cstdint>
namespace MGMLIS3MDL { namespace mgmLis3 {
enum Set { ON, OFF }; enum Set { ON, OFF };
enum OpMode { LOW, MEDIUM, HIGH, ULTRA }; enum OpMode { LOW, MEDIUM, HIGH, ULTRA };
enum Sensitivies : uint8_t { GAUSS_4 = 4, GAUSS_8 = 8, GAUSS_12 = 12, GAUSS_16 = 16 }; enum Sensitivies : uint8_t { GAUSS_4 = 4, GAUSS_8 = 8, GAUSS_12 = 12, GAUSS_16 = 16 };
/**
* Sets the read bit for the command
* @param single command to set the read-bit at
* @param boolean to select a continuous read bit, default = false
*/
uint8_t readCommand(uint8_t command, bool continuousCom = false);
/**
* Sets the write bit for the command
* @param single command to set the write-bit at
* @param boolean to select a continuous write bit, default = false
*/
uint8_t writeCommand(uint8_t command, bool continuousCom = false);
/**
* This Method gets the full scale for the measurement range
* e.g.: +- 4 gauss. See p.25 datasheet.
* @return The ReturnValue does not contain the sign of the value
*/
mgmLis3::Sensitivies getSensitivity(uint8_t ctrlReg2);
/**
* The 16 bit value needs to be multiplied with a sensitivity factor
* which depends on the sensitivity configuration
*
* @param sens Configured sensitivity of the LIS3 device
* @return Multiplication factor to get the sensor value from raw data.
*/
float getSensitivityFactor(mgmLis3::Sensitivies sens);
/* Actually 15, we just round up a bit */ /* Actually 15, we just round up a bit */
static constexpr size_t MAX_BUFFER_SIZE = 16; static constexpr size_t MAX_BUFFER_SIZE = 16;
@@ -154,6 +184,6 @@ class MgmPrimaryDataset : public StaticLocalDataSet<4> {
lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, TEMPERATURE_CELCIUS, this); lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, TEMPERATURE_CELCIUS, this);
}; };
} // namespace MGMLIS3MDL } // namespace mgmLis3
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMLIS3HANDLERDEFS_H_ */ #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMLIS3HANDLERDEFS_H_ */

View File

@@ -8,7 +8,7 @@
#include <cstdint> #include <cstdint>
namespace RM3100 { namespace mgmRm3100 {
/* Actually 10, we round up a little bit */ /* Actually 10, we round up a little bit */
static constexpr size_t MAX_BUFFER_SIZE = 12; static constexpr size_t MAX_BUFFER_SIZE = 12;
@@ -115,6 +115,6 @@ class Rm3100PrimaryDataset : public StaticLocalDataSet<3> {
lp_vec_t<float, 3> fieldStrengths = lp_vec_t<float, 3>(sid.objectId, FIELD_STRENGTHS, this); lp_vec_t<float, 3> fieldStrengths = lp_vec_t<float, 3>(sid.objectId, FIELD_STRENGTHS, this);
}; };
} // namespace RM3100 } // namespace mgmRm3100
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMHANDLERRM3100DEFINITIONS_H_ */ #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMHANDLERRM3100DEFINITIONS_H_ */

View File

@@ -15,7 +15,8 @@ ReturnValue_t HostFilesystem::writeToFile(FileOpParams params, const uint8_t *da
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(params.path()); path path(params.path());
if (not exists(path)) { std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
} }
// This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate // This is equivalent to "r+" mode, which is what we need here. Only using ::out would truncate
@@ -35,7 +36,8 @@ ReturnValue_t HostFilesystem::readFromFile(FileOpParams params, uint8_t **buffer
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(params.path()); path path(params.path());
if (not exists(path)) { std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
} }
ifstream file(path); ifstream file(path);
@@ -59,7 +61,8 @@ ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(params.path); path path(params.path);
if (exists(path)) { std::error_code e;
if (exists(path, e)) {
return HasFileSystemIF::FILE_ALREADY_EXISTS; return HasFileSystemIF::FILE_ALREADY_EXISTS;
} }
ofstream file(path); ofstream file(path);
@@ -74,7 +77,8 @@ ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *ar
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path path(path_); path path(path_);
if (not exists(path)) { std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
} }
if (remove(path, errorCode)) { if (remove(path, errorCode)) {
@@ -89,7 +93,8 @@ ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool crea
} }
path dirPath(params.path); path dirPath(params.path);
if (exists(dirPath)) { std::error_code e;
if (exists(dirPath, e)) {
return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS; return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS;
} }
@@ -110,7 +115,8 @@ ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool dele
return returnvalue::FAILED; return returnvalue::FAILED;
} }
path dirPath(params.path); path dirPath(params.path);
if (not exists(dirPath)) { std::error_code e;
if (not exists(dirPath, e)) {
return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST; return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST;
} }
if (is_regular_file(dirPath)) { if (is_regular_file(dirPath)) {
@@ -149,14 +155,31 @@ ReturnValue_t HostFilesystem::rename(const char *oldPath_, const char *newPath_,
bool HostFilesystem::fileExists(FilesystemParams params) { bool HostFilesystem::fileExists(FilesystemParams params) {
path path(params.path); path path(params.path);
return filesystem::exists(path); std::error_code e;
return filesystem::exists(path, e);
} }
ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) { ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
path path(params.path); path path(params.path);
if (not filesystem::exists(path)) { std::error_code e;
if (not filesystem::exists(path, e)) {
return FILE_DOES_NOT_EXIST; return FILE_DOES_NOT_EXIST;
} }
ofstream of(path); ofstream of(path);
return returnvalue::OK; return returnvalue::OK;
} }
bool HostFilesystem::isDirectory(const char *path) { return filesystem::is_directory(path); }
ReturnValue_t HostFilesystem::getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) {
std::string path(params.path);
std::string baseName = path.substr(path.find_last_of("/\\") + 1);
if (baseName.size() + 1 > maxLen) {
return returnvalue::FAILED;
}
std::memcpy(nameBuf, baseName.c_str(), baseName.size());
nameBuf[baseName.size()] = '\0';
baseNameLen = baseName.size();
return returnvalue::OK;
}

View File

@@ -9,6 +9,9 @@ class HostFilesystem : public HasFileSystemIF {
public: public:
HostFilesystem(); HostFilesystem();
ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) override;
bool isDirectory(const char *path) override;
bool fileExists(FilesystemParams params) override; bool fileExists(FilesystemParams params) override;
ReturnValue_t truncateFile(FilesystemParams params) override; ReturnValue_t truncateFile(FilesystemParams params) override;
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override; ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;

View File

@@ -17,7 +17,7 @@ ReturnValue_t CommandExecutor::load(std::string command, bool blocking, bool pri
return COMMAND_PENDING; return COMMAND_PENDING;
} }
currentCmd = command; currentCmd = std::move(command);
this->blocking = blocking; this->blocking = blocking;
this->printOutput = printOutput; this->printOutput = printOutput;
if (state == States::IDLE) { if (state == States::IDLE) {

View File

@@ -112,7 +112,7 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
if (i2cCookie->errorCounter < 3) { if (i2cCookie->errorCounter < 3) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::sendMessage: Failed to send data to I2C " sif::error << "I2cComIF::sendMessage: Failed to send data to I2C "
"device with error code " "device from " << deviceFile << " with error code "
<< errno << ". Error description: " << strerror(errno) << std::endl; << errno << ". Error description: " << strerror(errno) << std::endl;
#endif #endif
} }

View File

@@ -2,7 +2,6 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <fsfw_hal/linux/serial/SerialComIF.h>
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <fsfw_hal/linux/spi/SpiCookie.h> #include <fsfw_hal/linux/spi/SpiCookie.h>
#include "fsfw/ipc/MutexIF.h" #include "fsfw/ipc/MutexIF.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "fsfw_hal/common/gpio/GpioIF.h" #include "fsfw_hal/common/gpio/GpioIF.h"

View File

@@ -90,8 +90,6 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
* pulled high * pulled high
*/ */
MutexIF* csMutex = nullptr; MutexIF* csMutex = nullptr;
// MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
// uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT;
spi_ioc_transfer clockUpdateTransfer = {}; spi_ioc_transfer clockUpdateTransfer = {};
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>; using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;

View File

@@ -13,6 +13,7 @@ add_subdirectory(util)
add_subdirectory(container) add_subdirectory(container)
add_subdirectory(osal) add_subdirectory(osal)
add_subdirectory(pus) add_subdirectory(pus)
add_subdirectory(subsystem)
add_subdirectory(serialize) add_subdirectory(serialize)
add_subdirectory(datapoollocal) add_subdirectory(datapoollocal)
add_subdirectory(storagemanager) add_subdirectory(storagemanager)

View File

@@ -138,3 +138,10 @@ ReturnValue_t FilesystemMock::truncateFile(FilesystemParams params) {
truncateCalledOnFile = params.path; truncateCalledOnFile = params.path;
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t FilesystemMock::getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) {
return returnvalue::OK;
}
bool FilesystemMock::isDirectory(const char *path) { return false; }

View File

@@ -56,6 +56,10 @@ class FilesystemMock : public HasFileSystemIF {
std::string truncateCalledOnFile; std::string truncateCalledOnFile;
ReturnValue_t feedFile(const std::string &filename, std::ifstream &file); ReturnValue_t feedFile(const std::string &filename, std::ifstream &file);
ReturnValue_t getBaseFilename(FilesystemParams params, char *nameBuf, size_t maxLen,
size_t &baseNameLen) override;
bool isDirectory(const char *path) override;
bool fileExists(FilesystemParams params) override; bool fileExists(FilesystemParams params) override;
ReturnValue_t truncateFile(FilesystemParams params) override; ReturnValue_t truncateFile(FilesystemParams params) override;

View File

@@ -0,0 +1 @@
target_sources(${FSFW_TEST_TGT} PRIVATE testModeDef.cpp)

View File

@@ -0,0 +1,49 @@
#include <array>
#include <catch2/catch_test_macros.hpp>
#include "fsfw/subsystem/modes/ModeDefinitions.h"
TEST_CASE("Mode Definitions", "[mode]") {
ModeListEntry entry;
SECTION("Basic") {
entry.setMode(HasModesIF::MODE_OFF);
entry.setSubmode(2);
CHECK(entry.getMode() == HasModesIF::MODE_OFF);
CHECK(entry.getSubmode() == 2);
uint8_t mask;
CHECK(entry.submodesAllowed(&mask) == false);
}
SECTION("Allowed submode mask") {
entry.allowAllSubmodes();
uint8_t mask;
CHECK(entry.submodesAllowed(&mask) == true);
CHECK(mask == 0xff);
}
SECTION("Serialization") {
std::array<uint8_t, 32> buf{};
entry.setObject(0x1f2f3f4f);
entry.setMode(HasModesIF::MODE_ON);
entry.setSubmode(2);
entry.enableInheritSubmode();
entry.enableSubmodeAllowed(0x1f);
uint8_t* serPtr = buf.data();
size_t serLen = 0;
REQUIRE(entry.serialize(&serPtr, &serLen, buf.size(), SerializeIF::Endianness::NETWORK) ==
returnvalue::OK);
CHECK(buf[0] == 0x1f);
CHECK(buf[1] == 0x2f);
CHECK(buf[2] == 0x3f);
CHECK(buf[3] == 0x4f);
CHECK(buf[4] == 0);
CHECK(buf[5] == 0);
CHECK(buf[6] == 0);
CHECK(buf[7] == HasModesIF::MODE_ON);
CHECK(buf[8] == 2);
CHECK(buf[9] == (mode::SpecialSubmodeFlags::ALLOWED_MASK | mode::SpecialSubmodeFlags::INHERIT));
CHECK(buf[10] == 0x1f);
}
}

View File

@@ -1,15 +1,18 @@
#include <fsfw/timemanager/Countdown.h> #include <fsfw/timemanager/Countdown.h>
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <chrono>
#include <thread>
#include "CatchDefinitions.h" #include "CatchDefinitions.h"
static constexpr bool TEST_LONGER_CD = false;
TEST_CASE("Countdown Tests", "[TestCountdown]") { TEST_CASE("Countdown Tests", "[TestCountdown]") {
INFO("Countdown Tests"); INFO("Countdown Tests");
Countdown count(20); Countdown count(20);
REQUIRE(count.timeout == 20); REQUIRE(count.getTimeoutMs() == 20);
REQUIRE(count.setTimeout(100) == static_cast<uint16_t>(returnvalue::OK)); REQUIRE(count.setTimeout(100) == static_cast<uint16_t>(returnvalue::OK));
REQUIRE(count.timeout == 100); REQUIRE(count.getTimeoutMs() == 100);
REQUIRE(count.setTimeout(150) == static_cast<uint16_t>(returnvalue::OK)); REQUIRE(count.setTimeout(150) == static_cast<uint16_t>(returnvalue::OK));
REQUIRE(count.isBusy()); REQUIRE(count.isBusy());
REQUIRE(not count.hasTimedOut()); REQUIRE(not count.hasTimedOut());
@@ -25,4 +28,19 @@ TEST_CASE("Countdown Tests", "[TestCountdown]") {
count.resetTimer(); count.resetTimer();
REQUIRE(not count.hasTimedOut()); REQUIRE(not count.hasTimedOut());
REQUIRE(count.isBusy()); REQUIRE(count.isBusy());
count.setTimeout(100);
REQUIRE(not count.hasTimedOut());
std::this_thread::sleep_for(std::chrono::milliseconds(50));
REQUIRE(not count.hasTimedOut());
std::this_thread::sleep_for(std::chrono::milliseconds(50));
REQUIRE(count.hasTimedOut());
// Takes longer, disabled by default
if (TEST_LONGER_CD) {
count.setTimeout(2500);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
REQUIRE(not count.hasTimedOut());
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
REQUIRE(count.hasTimedOut());
}
} }