Compare commits

..

36 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
46 changed files with 651 additions and 424 deletions

View File

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

View File

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

View File

@ -15,12 +15,12 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
{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) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
}
EventManager::~EventManager() {

View File

@ -21,9 +21,9 @@ extern const char* translateEvents(Event event);
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
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();
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);
break;
case ParameterIds::TIMEOUT:
parameterWrapper->set(timer.timeout);
parameterWrapper->set(timer.getTimeoutMs());
break;
default:
return INVALID_IDENTIFIER_ID;

View File

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

View File

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

View File

@ -20,9 +20,9 @@
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
const std::string &udpServerPort_, object_id_t tmStoreId,
object_id_t tcStoreId)
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) {
uint32_t msgQueueDepth, const std::string &udpServerPort_,
object_id_t tmStoreId, object_id_t tcStoreId)
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
if (udpServerPort_.empty()) {
udpServerPort = DEFAULT_SERVER_PORT;
} 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. */
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,
object_id_t tcStoreId = objects::TC_STORE);
~UdpTmTcBridge() override;

View File

@ -47,7 +47,32 @@ ReturnValue_t Clock::setClock(const timeval* time) {
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)
auto now = std::chrono::system_clock::now();
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
@ -75,6 +100,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
#endif
}
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
if (time == nullptr) {
return returnvalue::FAILED;

View File

@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
ReturnValue_t Clock::getClock(timeval* time) {
timespec timeUnix{};
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
@ -53,6 +53,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal);
@ -64,6 +66,17 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
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 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
// Linux specific file read but more precise.
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_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.

View File

@ -1,5 +1,7 @@
#include "DummyPowerSwitcher.h"
#include <utility>
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
size_t numberOfFuses, bool registerGlobally,
uint32_t switchDelayMs)
@ -9,11 +11,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
switchDelayMs(switchDelayMs) {}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList;
this->switcherList = std::move(switcherList);
}
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) {

View File

@ -68,6 +68,9 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
ReturnValue_t result = returnvalue::OK;
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): {
if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
return CommandingServiceBase::INVALID_TC;
}
HealthSetCommand healthCommand;
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {

View File

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

View File

@ -56,6 +56,7 @@ class PoolManager : public LocalPool {
protected:
//! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20;
static constexpr char LOCK_CTX[] = "PoolManager";
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,
Submode_t targetSubmode) {
using namespace mode;
std::map<object_id_t, ChildInfo>::iterator childIter;
for (; tableIter.value != NULL; ++tableIter) {
@ -34,13 +35,21 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry
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()) {
submodeToCheckAgainst = targetSubmode;
}
if (childIter->second.submode != submodeToCheckAgainst) {
return returnvalue::FAILED;
if (submodesAllowedMask) {
if ((childIter->second.submode | mask) != mask) {
return returnvalue::FAILED;
}
} else {
if (childIter->second.submode != submodeToCheckAgainst) {
return returnvalue::FAILED;
}
}
}
return returnvalue::OK;

View File

@ -1,111 +1,126 @@
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#include "../../modes/HasModesIF.h"
#include "../../objectmanager/SystemObjectIF.h"
#include "../../serialize/SerialLinkedListAdapter.h"
#include "../../serialize/SerializeIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serialize/SerialLinkedListAdapter.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:
ModeListEntry() : LinkedElement<ModeListEntry>(this) {}
static constexpr uint8_t ALL_SUBMODES_ALLOWED_MASK = 0xff;
uint32_t value1 = 0;
uint32_t value2 = 0;
uint8_t value3 = 0;
uint8_t value4 = 0;
ModeListEntry() : SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) { setLinks(); }
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result;
SerializeElement<uint32_t> value1 = 0;
SerializeElement<uint32_t> value2 = 0;
SerializeElement<uint8_t> value3 = 0;
SerializeElement<uint8_t> value4 = 0;
SerializeElement<uint8_t> value5 = 0;
result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
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;
ModeListEntry(const ModeListEntry& other)
: SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) {
value1.entry = other.value1.entry;
value2.entry = other.value2.entry;
value3.entry = other.value3.entry;
value4.entry = other.value4.entry;
value5.entry = other.value5.entry;
setLinks();
}
virtual size_t getSerializedSize() const {
return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4);
ModeListEntry& operator=(const ModeListEntry& other) {
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,
Endianness streamEndianness) {
ReturnValue_t result;
result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness);
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;
void setLinks() {
setStart(&value1);
value1.setNext(&value2);
value2.setNext(&value3);
value3.setNext(&value4);
value4.setNext(&value5);
}
// 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
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; }
void setInheritSubmode(bool inherit) {
if (inherit) {
value4 = 1;
} else {
value4 = 0;
bool inheritSubmode() const {
return (value4.entry & mode::SpecialSubmodeFlags::INHERIT) ==
mode::SpecialSubmodeFlags::INHERIT;
}
bool submodesAllowed(uint8_t* mask) const {
bool submodesAllowed = (value4.entry & mode::SpecialSubmodeFlags::ALLOWED_MASK) ==
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

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

View File

@ -49,6 +49,13 @@ class Clock {
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/
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.
* 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.
* @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

View File

@ -1,49 +1,62 @@
#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) {
setTimeout(initialTimeout);
} 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 returnValue = Clock::getUptime(&startTime);
timeout = milliseconds;
return returnValue;
timeout.tv_sec = milliseconds / 1000;
timeout.tv_usec = (milliseconds % 1000) * 1000;
return Clock::getClockMonotonic(&startTime);
}
bool Countdown::hasTimedOut() const {
if (uint32_t(this->getCurrentTime() - startTime) >= timeout) {
// Account for system clock going back in time.
if (getCurrentTime() < startTime) {
return true;
} else {
return false;
}
if (getCurrentTime() - startTime >= timeout) {
return true;
}
return false;
}
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; }
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()) {
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 currentTime;
Clock::getUptime(&currentTime);
uint32_t Countdown::timevalToMs(timeval &tv) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; }
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;
}

View File

@ -6,6 +6,10 @@
/**
*
* 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::setTimeout sets a new countdown duration and resets.
@ -39,6 +43,8 @@ class Countdown {
* @return Returnvalue from Clock::getUptime
*/
ReturnValue_t setTimeout(uint32_t milliseconds);
ReturnValue_t setTimeoutTv(timeval tv);
/**
* Returns true if the countdown duration has passed.
*
@ -61,22 +67,31 @@ class Countdown {
* Returns the remaining milliseconds (0 if timeout)
*/
uint32_t getRemainingMillis() const;
uint32_t getTimeoutMs() const;
timeval getTimeout() const;
/**
* Makes hasTimedOut() return true
*/
void timeOut();
/**
* Internal countdown duration in milliseconds
*/
uint32_t timeout;
static inline uint32_t timevalToMs(timeval& tv);
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_ */

View File

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

View File

@ -8,7 +8,7 @@
#define TMTCBRIDGE_WIRETAPPING 0
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),
name(name),
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));
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); }

View File

@ -15,7 +15,6 @@ class TmTcBridge : public AcceptsTelemetryIF,
public ExecutableObjectIF,
public SystemObject {
public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
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;
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;
/**

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
#ifndef 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/globalfunctions/PeriodicOperationDivider.h"
@ -66,7 +67,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
LocalDataPoolManager &poolManager) override;
private:
MGMLIS3MDL::MgmPrimaryDataset dataset;
mgmLis3::MgmPrimaryDataset dataset;
// Length a single command SPI answer
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
size_t singleComandSize = 2;
// 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 absLimitY = 100;
@ -85,7 +86,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
* registers when we want to change something.
* --> 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;
bool goToNormalMode = false;
@ -107,35 +108,6 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
/*------------------------------------------------------------------------*/
/* 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

View File

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

View File

@ -1,7 +1,8 @@
#ifndef 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/globalfunctions/PeriodicOperationDivider.h"
@ -69,19 +70,19 @@ class MgmRM3100Handler : public DeviceHandlerBase {
};
InternalState internalState = InternalState::NONE;
bool commandExecuted = false;
RM3100::Rm3100PrimaryDataset primaryDataset;
mgmRm3100::Rm3100PrimaryDataset primaryDataset;
uint8_t commandBuffer[10];
uint8_t commandBufferLen = 0;
uint8_t cmmRegValue = RM3100::CMM_VALUE;
uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE;
uint16_t cycleCountRegValueX = RM3100::CYCLE_COUNT_VALUE;
uint16_t cycleCountRegValueY = RM3100::CYCLE_COUNT_VALUE;
uint16_t cycleCountRegValueZ = RM3100::CYCLE_COUNT_VALUE;
float scaleFactorX = 1.0 / RM3100::DEFAULT_GAIN;
float scaleFactorY = 1.0 / RM3100::DEFAULT_GAIN;
float scaleFactorZ = 1.0 / RM3100::DEFAULT_GAIN;
uint8_t cmmRegValue = mgmRm3100::CMM_VALUE;
uint8_t tmrcRegValue = mgmRm3100::TMRC_DEFAULT_VALUE;
uint16_t cycleCountRegValueX = mgmRm3100::CYCLE_COUNT_VALUE;
uint16_t cycleCountRegValueY = mgmRm3100::CYCLE_COUNT_VALUE;
uint16_t cycleCountRegValueZ = mgmRm3100::CYCLE_COUNT_VALUE;
float scaleFactorX = 1.0 / mgmRm3100::DEFAULT_GAIN;
float scaleFactorY = 1.0 / mgmRm3100::DEFAULT_GAIN;
float scaleFactorZ = 1.0 / mgmRm3100::DEFAULT_GAIN;
bool goToNormalModeAtStartup = false;
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>
namespace L3GD20H {
namespace l3gd20h {
float ctrlReg4ToSensitivity(uint8_t reg);
/* Actual size is 15 but we round up a bit */
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 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;
enum GyroPoolIds : lp_id_t { ANG_VELOC_X, ANG_VELOC_Y, ANG_VELOC_Z, TEMPERATURE };
} // namespace L3GD20H
} // namespace l3gd20h
class GyroPrimaryDataset : public StaticLocalDataSet<5> {
public:
/** Constructor for data users like controllers */
GyroPrimaryDataset(object_id_t mgmId)
: StaticLocalDataSet(sid_t(mgmId, L3GD20H::GYRO_DATASET_ID)) {
: StaticLocalDataSet(sid_t(mgmId, l3gd20h::GYRO_DATASET_ID)) {
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 */
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_ */

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>
namespace MGMLIS3MDL {
namespace mgmLis3 {
enum Set { ON, OFF };
enum OpMode { LOW, MEDIUM, HIGH, ULTRA };
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 */
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);
};
} // namespace MGMLIS3MDL
} // namespace mgmLis3
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MGMLIS3HANDLERDEFS_H_ */

View File

@ -8,7 +8,7 @@
#include <cstdint>
namespace RM3100 {
namespace mgmRm3100 {
/* Actually 10, we round up a little bit */
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);
};
} // namespace RM3100
} // namespace mgmRm3100
#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;
}
path path(params.path());
if (not exists(path)) {
std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
}
// 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;
}
path path(params.path());
if (not exists(path)) {
std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
}
ifstream file(path);
@ -59,7 +61,8 @@ ReturnValue_t HostFilesystem::createFile(FilesystemParams params, const uint8_t
return returnvalue::FAILED;
}
path path(params.path);
if (exists(path)) {
std::error_code e;
if (exists(path, e)) {
return HasFileSystemIF::FILE_ALREADY_EXISTS;
}
ofstream file(path);
@ -74,7 +77,8 @@ ReturnValue_t HostFilesystem::removeFile(const char *path_, FileSystemArgsIF *ar
return returnvalue::FAILED;
}
path path(path_);
if (not exists(path)) {
std::error_code e;
if (not exists(path, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
}
if (remove(path, errorCode)) {
@ -89,7 +93,8 @@ ReturnValue_t HostFilesystem::createDirectory(FilesystemParams params, bool crea
}
path dirPath(params.path);
if (exists(dirPath)) {
std::error_code e;
if (exists(dirPath, e)) {
return HasFileSystemIF::DIRECTORY_ALREADY_EXISTS;
}
@ -110,7 +115,8 @@ ReturnValue_t HostFilesystem::removeDirectory(FilesystemParams params, bool dele
return returnvalue::FAILED;
}
path dirPath(params.path);
if (not exists(dirPath)) {
std::error_code e;
if (not exists(dirPath, e)) {
return HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST;
}
if (is_regular_file(dirPath)) {
@ -149,12 +155,14 @@ ReturnValue_t HostFilesystem::rename(const char *oldPath_, const char *newPath_,
bool HostFilesystem::fileExists(FilesystemParams params) {
path path(params.path);
return filesystem::exists(path);
std::error_code e;
return filesystem::exists(path, e);
}
ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) {
path path(params.path);
if (not filesystem::exists(path)) {
std::error_code e;
if (not filesystem::exists(path, e)) {
return FILE_DOES_NOT_EXIST;
}
ofstream of(path);

View File

@ -17,7 +17,7 @@ ReturnValue_t CommandExecutor::load(std::string command, bool blocking, bool pri
return COMMAND_PENDING;
}
currentCmd = command;
currentCmd = std::move(command);
this->blocking = blocking;
this->printOutput = printOutput;
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 FSFW_CPP_OSTREAM_ENABLED == 1
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;
#endif
}

View File

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

View File

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

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 <catch2/catch_test_macros.hpp>
#include <chrono>
#include <thread>
#include "CatchDefinitions.h"
static constexpr bool TEST_LONGER_CD = false;
TEST_CASE("Countdown Tests", "[TestCountdown]") {
INFO("Countdown Tests");
Countdown count(20);
REQUIRE(count.timeout == 20);
REQUIRE(count.getTimeoutMs() == 20);
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.isBusy());
REQUIRE(not count.hasTimedOut());
@ -25,4 +28,19 @@ TEST_CASE("Countdown Tests", "[TestCountdown]") {
count.resetTimer();
REQUIRE(not count.hasTimedOut());
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());
}
}