From eaec6fbaaa0035378f44ddffeb0e2e05e7830077 Mon Sep 17 00:00:00 2001
From: Theodoros Katzalis <thodkatz@gmail.com>
Date: Wed, 20 Mar 2019 12:58:27 +0200
Subject: [PATCH] Implement the spare field

Added an error condition

Added tests for the spare field

Minor change in the documentation

Reimplement the spare field
---
 inc/ErrorHandler.hpp |  6 +++-
 inc/Message.hpp      | 26 +++++++++++---
 src/Message.cpp      |  5 +++
 test/Message.cpp     | 82 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 113 insertions(+), 6 deletions(-)

diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp
index 07c29093..8c6e5391 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 fc26623c..2e69b57b 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,21 @@ public:
 	 */
 	void appendBits(uint8_t numBits, uint16_t data);
 
+	/**
+	 * Define the spare field in telemetry and telecommand user data field (7.4.3.2.c and 7.4.4.2.c)
+	 *
+	 * 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 +111,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 +287,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 +449,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/src/Message.cpp b/src/Message.cpp
index 6c4f1fb6..d9b9b2c1 100644
--- a/src/Message.cpp
+++ b/src/Message.cpp
@@ -36,6 +36,11 @@ void Message::appendBits(uint8_t numBits, uint16_t data) {
 	}
 }
 
+void Message::finalize() {
+	if(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/test/Message.cpp b/test/Message.cpp
index f0b78e3c..01df6ce0 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);
+}
-- 
GitLab