From a8daf28e2a6c784497de5f7e46a5901a9d5522a3 Mon Sep 17 00:00:00 2001
From: kongr45gpen <electrovesta@gmail.com>
Date: Fri, 9 Aug 2019 03:31:04 +0300
Subject: [PATCH] Implement message type counting

---
 inc/ServicePool.hpp | 21 +++++++++++++++++++++
 src/Message.cpp     |  7 ++++++-
 src/ServicePool.cpp |  5 +++++
 test/Message.cpp    | 37 +++++++++++++++++++++++++++++++++++++
 4 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/inc/ServicePool.hpp b/inc/ServicePool.hpp
index 97fbed7f..707ae91f 100644
--- a/inc/ServicePool.hpp
+++ b/inc/ServicePool.hpp
@@ -20,6 +20,15 @@
  * @todo Find a way to disable services which are not used
  */
 class ServicePool {
+	/**
+	 * A counter for messages
+	 *
+	 * Each key-value pair corresponds to one MessageType within a Service. The most significant 8 bits are the number
+	 * of the service, while the least significant 8 bits are the number of the Message.
+	 *
+	 * @todo Update this according to the final number of Services and Messages
+	 */
+	etl::map<uint16_t, uint16_t, 10*20> messageTypeCounter;
 public:
 	RequestVerificationService requestVerification;
 	EventReportService eventReport;
@@ -44,6 +53,18 @@ public:
 	 * Services already stored as values will point to the "new" Services after a reset.
 	 */
 	void reset();
+
+	/**
+	 * Get and increase the "message type counter" for the next message of a type
+	 *
+	 * The message type counter counts the type of generated messages per destination, according to requirement
+	 * 5.4.2.1j. If the value reaches its max, it is wrapped back to 0.
+	 *
+	 * @param serviceType The service type ID
+	 * @param messageType The message type ID
+	 * @return The message type count
+	 */
+	uint16_t getMessageTypeCounter(uint8_t serviceType, uint8_t messageType);
 };
 
 /**
diff --git a/src/Message.cpp b/src/Message.cpp
index efedb65c..7fb5974e 100644
--- a/src/Message.cpp
+++ b/src/Message.cpp
@@ -2,6 +2,7 @@
 #include "macros.hpp"
 #include <cstring>
 #include <ErrorHandler.hpp>
+#include <ServicePool.hpp>
 
 Message::Message(uint8_t serviceType, uint8_t messageType, Message::PacketType packetType, uint16_t applicationId)
     : serviceType(serviceType), messageType(messageType), packetType(packetType), applicationId(applicationId) {}
@@ -36,11 +37,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;
+		data[dataSize] = 0; // Make sure that the last bit is zero
 		dataSize++;
 	}
+
+	if (packetType == PacketType::TM) {
+		messageTypeCounter = Services.getMessageTypeCounter(serviceType, messageType);
+	}
 }
 
 void Message::appendByte(uint8_t value) {
diff --git a/src/ServicePool.cpp b/src/ServicePool.cpp
index f76e2ee7..7c203e7f 100644
--- a/src/ServicePool.cpp
+++ b/src/ServicePool.cpp
@@ -12,3 +12,8 @@ void ServicePool::reset() {
 	// statically allocated from before.
 	new (this) ServicePool();
 }
+
+uint16_t ServicePool::getMessageTypeCounter(uint8_t serviceType, uint8_t messageType) {
+	uint16_t key = (serviceType << 8u) | messageType; // Create the key of the map
+	return (messageTypeCounter[key])++; // Fetch and increase the value
+}
diff --git a/test/Message.cpp b/test/Message.cpp
index 25f09832..8088d945 100644
--- a/test/Message.cpp
+++ b/test/Message.cpp
@@ -253,3 +253,40 @@ TEST_CASE("Spare field", "[message]") {
 
 	CHECK(message9.dataSize == 3);
 }
+
+TEST_CASE("Message type counter", "[message]") {
+	SECTION("Message counting") {
+		Message message1(0, 0, Message::TM, 0);
+		message1.finalize();
+		CHECK(message1.messageTypeCounter == 0);
+
+		Message message2(0, 0, Message::TM, 0);
+		message2.finalize();
+		CHECK(message2.messageTypeCounter == 1);
+	}
+
+	SECTION("Different message types") {
+		Message message1(0, 1, Message::TM, 0);
+		message1.finalize();
+		CHECK(message1.messageTypeCounter == 0);
+
+		Message message2(0, 2, Message::TM, 0);
+		message2.finalize();
+		CHECK(message2.messageTypeCounter == 0);
+	}
+
+	SECTION("Message counter overflow") {
+		for (int i = 0; i <= 65534; i++) {
+			Message message(0, 3, Message::TM, 0);
+			message.finalize();
+		}
+
+		Message message1(0, 3, Message::TM, 0);
+		message1.finalize();
+		CHECK(message1.messageTypeCounter == 65535);
+
+		Message message2(0, 3, Message::TM, 0);
+		message2.finalize();
+		CHECK(message2.messageTypeCounter == 0);
+	}
+}
-- 
GitLab