diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp index 07c290934b7f5bc3b2e86c2d56324ccb2169c4c0..8c6e53917275c434e0f5d3182b2335585895b2a0 100644 --- a/inc/ErrorHandler.hpp +++ b/inc/ErrorHandler.hpp @@ -62,6 +62,11 @@ public: * Asked a Message type that doesn't exist */ UnknownMessageType = 7, + + /** + * Asked to append unnecessary spare bits + */ + InvalidSpareBits = 8, }; /** @@ -183,7 +188,6 @@ public: * * Note that these errors correspond to bugs or faults in the software, and should be treated * differently. Such an error may prompt a task or software reset. - * */ static void reportInternalError(InternalErrorType errorCode); diff --git a/inc/Message.hpp b/inc/Message.hpp index fc26623c5014612932681b5b72597dff83de3dc2..c6ee50067e4b67cddb0e263feae6100ec62cf2ce 100644 --- a/inc/Message.hpp +++ b/inc/Message.hpp @@ -21,7 +21,7 @@ class Message; */ class Message { public: - Message () = default; + Message() = default; enum PacketType { TM = 0, // Telemetry @@ -63,6 +63,7 @@ public: // Next byte to read for read...() functions uint16_t readPosition = 0; + /** * Appends the least significant \p numBits from \p data to the message * @@ -70,6 +71,19 @@ public: */ void appendBits(uint8_t numBits, uint16_t data); + /** + * Appends the remaining bits to complete a byte, in case the appendBits() is the last call + * and the packet data field isn't integer multiple of bytes + * + * @note Actually we should append the bits so the total length of the packets is an integer + * multiple of the padding word size declared for the application process + * @todo Confirm that the overall packet size is an integer multiple of the padding word size + * declared for every application process + * @todo check if wee need to define the spare field for the telemetry and telecommand + * secondary headers + */ + void finalize(); + /** * Appends 1 byte to the message */ @@ -95,7 +109,7 @@ public: * @param string The string to insert */ template<const size_t SIZE> - void appendString(const String<SIZE> & string); + void appendString(const String<SIZE> &string); /** * Reads the next \p numBits bits from the the message in a big-endian format @@ -271,10 +285,10 @@ public: * PTC = 7, PFC = 0 */ template<const size_t SIZE> - void appendOctetString(const String<SIZE> & string) { + void appendOctetString(const String<SIZE> &string) { // Make sure that the string is large enough to count assertI(string.size() <= (std::numeric_limits<uint16_t>::max)(), - ErrorHandler::StringTooLarge); + ErrorHandler::StringTooLarge); appendUint16(string.size()); appendString(string); @@ -433,7 +447,7 @@ public: }; template<const size_t SIZE> -inline void Message::appendString(const String<SIZE> & string) { +inline void Message::appendString(const String<SIZE> &string) { assertI(dataSize + string.size() < ECSS_MAX_MESSAGE_SIZE, ErrorHandler::MessageTooLarge); // TODO: Do we need to keep this check? How does etl::string handle it? assertI(string.size() < string.capacity(), ErrorHandler::StringTooLarge); diff --git a/inc/Service.hpp b/inc/Service.hpp index 09937508303e6a1b19dffca76e68db0266299802..fbd1aff83534859397e0cf935601f149e7922872 100644 --- a/inc/Service.hpp +++ b/inc/Service.hpp @@ -44,7 +44,7 @@ protected: * Note: For now, since we don't have any mechanisms to queue messages and send them later, * we just print the message to the screen */ - void storeMessage(const Message &message); + void storeMessage(Message &message); /** * This function declared only to remind us that every service must have a function like @@ -56,20 +56,21 @@ protected: * Default protected constructor for this Service */ Service() = default; + public: /** * @brief Unimplemented copy constructor * * Does not allow Services should be copied. There should be only one instance for each Service. */ - Service (Service const&) = delete; + Service(Service const &) = delete; /** * Unimplemented assignment operation * * Does not allow changing the instances of Services, as Services are singletons. */ - void operator=(Service const&) = delete; + void operator=(Service const &) = delete; /** * Default destructor @@ -79,12 +80,12 @@ public: /** * Default move constructor */ - Service(Service && service) noexcept = default; + Service(Service &&service) noexcept = default; /** * Default move assignment operator */ - Service & operator=(Service && service) noexcept = default; + Service &operator=(Service &&service) noexcept = default; }; diff --git a/src/Message.cpp b/src/Message.cpp index 6c4f1fb613f6e0a46f767f1a436e91e67cc34f2d..e6b6834b8932cf929d18576fcf884c26c9a452ec 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -36,6 +36,15 @@ void Message::appendBits(uint8_t numBits, uint16_t data) { } } +void Message::finalize() { + // Define the spare field in telemetry and telecommand user data field (7.4.3.2.c and 7.4.4.2.c) + + if (currentBit != 0) { + currentBit = 0; + dataSize++; + } +} + void Message::appendByte(uint8_t value) { assertI(dataSize < ECSS_MAX_MESSAGE_SIZE, ErrorHandler::MessageTooLarge); assertI(currentBit == 0, ErrorHandler::ByteBetweenBits); diff --git a/src/Platform/x86/Service.cpp b/src/Platform/x86/Service.cpp index ff9d9d95de57f749996cb8a2fcd7853cebda7813..6a251f27d1d3a70713833baa949bdcc5a787ec0d 100644 --- a/src/Platform/x86/Service.cpp +++ b/src/Platform/x86/Service.cpp @@ -2,7 +2,10 @@ #include <iomanip> #include "Service.hpp" -void Service::storeMessage(const Message &message) { +void Service::storeMessage(Message &message) { + // appends the remaining bits to complete a byte + message.finalize(); + // Just print it to the screen std::cout << "New " << ((message.packetType == Message::TM) ? "TM" : "TC") << "[" << std::hex diff --git a/test/Message.cpp b/test/Message.cpp index f0b78e3c5af4a8e330282c3c6cbd4ef571c0fb37..01df6ce0f149d21a9d2c9c381e372fb7ab904e0b 100644 --- a/test/Message.cpp +++ b/test/Message.cpp @@ -173,3 +173,85 @@ TEST_CASE("Requirement 7.3.13 (Packet)", "[message][ecss]") { CHECK(static_cast<int>(telemetry.packetType) == 0); CHECK(static_cast<int>(telecommand.packetType) == 1); } + +TEST_CASE("Spare field", "[message]") { + Message message1(0, 0, Message::TM, 0); + + message1.appendByte(1); + message1.appendHalfword(2); + message1.appendBits(1, 5); + message1.finalize(); + + CHECK(message1.dataSize == 4); + + Message message2(0, 0, Message::TM, 0); + message2.appendByte(1); + message2.appendHalfword(2); + message2.appendBits(2, 5); + message2.finalize(); + + CHECK(message2.dataSize == 4); + + Message message3(0, 0, Message::TM, 0); + + message3.appendByte(1); + message3.appendHalfword(2); + message3.appendBits(3, 5); + message3.finalize(); + + CHECK(message3.dataSize == 4); + + Message message4(0, 0, Message::TM, 0); + + message4.appendByte(1); + message4.appendHalfword(2); + message4.appendBits(4, 5); + message4.finalize(); + + CHECK(message4.dataSize == 4); + + Message message5(0, 0, Message::TM, 0); + + message5.appendByte(1); + message5.appendHalfword(2); + message5.appendBits(5, 5); + message5.finalize(); + + CHECK(message5.dataSize == 4); + + Message message6(0, 0, Message::TM, 0); + + message6.appendByte(1); + message6.appendHalfword(2); + message6.appendBits(6, 5); + message6.finalize(); + + CHECK(message6.dataSize == 4); + + Message message7(0, 0, Message::TM, 0); + + message7.appendByte(1); + message7.appendHalfword(2); + message7.appendBits(7, 5); + message7.finalize(); + + CHECK(message7.dataSize == 4); + + Message message8(0, 0, Message::TM, 0); + + message8.appendByte(1); + message8.appendHalfword(2); + message8.appendBits(8, 5); + message8.finalize(); + + CHECK(message8.dataSize == 4); + + Message message9(0, 0, Message::TM, 0); + + message9.appendByte(1); + message9.appendHalfword(2); + message9.appendBits(0, 5); + message9.finalize(); + + CHECK(message9.dataSize == 3); +} diff --git a/test/TestPlatform.cpp b/test/TestPlatform.cpp index 0880d64ea865d220846ac5659068606cbce65d62..f6297918c4bd8f09fe7e93a7902bf8ac9833963e 100644 --- a/test/TestPlatform.cpp +++ b/test/TestPlatform.cpp @@ -19,7 +19,7 @@ std::multimap<std::pair<ErrorHandler::ErrorSource, uint16_t>, bool> ServiceTests std::multimap<std::pair<ErrorHandler::ErrorSource, uint16_t>, bool>(); bool ServiceTests::expectingErrors = false; -void Service::storeMessage(const Message &message) { +void Service::storeMessage(Message &message) { // Just add the message to the queue ServiceTests::queue(message); }