diff --git a/CMakeLists.txt b/CMakeLists.txt
index 40f819b605d47ef1805b71809de9e16eb927f141..91e767a62033766d2b6104eb2e0907f86e9981b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,14 +15,19 @@ add_custom_target(check
 
 # Specify the .cpp files for the executables
 add_executable(ecss_services src/main.cpp src/Message.cpp src/Service.cpp
-        src/Services/TestService.cpp src/Services/MemoryManagementService.cpp
-        src/Services/RequestVerificationService.cpp)
+    src/Services/TestService.cpp src/Services/RequestVerificationService.cpp
+    src/Services/MemoryManagementService.cpp src/Services/ParameterService.cpp
+    src/Services/TestService.cpp
+    src/Services/RequestVerificationService.cpp)
 
 IF(EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt")
     add_subdirectory(lib/Catch2)
-    add_executable(tests src/Message.cpp src/Services/TestService.cpp
-    src/Services/RequestVerificationService.cpp src/Services/MemoryManagementService.cpp
-    test/tests.cpp test/Message.cpp test/TestPlatform.cpp test/Services/TestService.cpp
-    test/Services/MemoryManagementService.cpp test/Services/RequestVerificationService.cpp)
+    add_executable(tests src/Message.cpp src/Services/TestService.cpp 
+    src/Services/RequestVerificationService.cpp src/Services/ParameterService.cpp 
+    src/Services/MemoryManagementService.cpp test/tests.cpp test/Message.cpp 
+    test/TestPlatform.cpp test/Services/TestService.cpp 
+    test/Services/RequestVerificationService.cpp 
+    test/Services/ParameterService.cpp test/Services/MemoryManagementService.cpp)
+
     target_link_libraries(tests Catch2::Catch2)
 ENDIF()
diff --git a/inc/Service.hpp b/inc/Service.hpp
index 55aa5f83a4964eafef4e37ba0bc15efbd30cb9fa..3afd67fa73d6ce148555bd03ead9a8743666364c 100644
--- a/inc/Service.hpp
+++ b/inc/Service.hpp
@@ -16,7 +16,7 @@ class Service {
 private:
 	uint16_t messageTypeCounter = 0;
 protected:
-	uint8_t serviceType;
+	uint8_t serviceType{};
 
 	/**
 	 * Creates a new empty telemetry package originating from this service
diff --git a/inc/Services/ParameterService.hpp b/inc/Services/ParameterService.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c331ae2743d7ffbd4e137d043889515f491d0372
--- /dev/null
+++ b/inc/Services/ParameterService.hpp
@@ -0,0 +1,89 @@
+#ifndef ECSS_SERVICES_PARAMETERSERVICE_HPP
+#define ECSS_SERVICES_PARAMETERSERVICE_HPP
+
+#include "Service.hpp"
+// #include "Services/RequestVerificationService.hpp"
+
+#define CONFIGLENGTH 5
+
+/**
+ * Implementation of the ST[20] parameter management service,
+ * as defined in ECSS-E-ST-70-41C
+ *
+ * @author Grigoris Pavlakis <grigpavl@ece.auth.gr>
+ */
+
+/**
+ * Generic parameter structure
+ * PTC and PFC for each parameter shall be specified as in
+ * ECSS-E-ST-70-41C, chapter 7.3
+ */
+struct Parameter {
+	uint8_t ptc;            // Packet field type code (PTC)
+	uint8_t pfc;            // Packet field format code (PFC)
+	uint16_t paramId;       // Unique ID of the parameter
+
+	uint32_t settingData;
+	// Actual data defining the operation of a peripheral or subsystem.
+	// Peripheral-dependent normally (void* maybe?) (it's a memory address according to spec).
+	// Dummy int for now.
+};
+
+/**
+ * Parameter manager - ST[20]
+ * Holds the list with the parameters and provides functions
+ * for parameter reporting and modification.
+ *
+ * @todo Ensure that the parameter list is sorted by ID
+ */
+
+class ParameterService : public Service {
+private:
+	Parameter paramsList[CONFIGLENGTH];
+	// CONFIGLENGTH is just a dummy number for now, this should be statically set
+	static uint16_t numOfValidIds(Message idMsg);  //count the valid ids in a given TC[20, 1]
+
+public:
+	/**
+	 * Initializes the parameter list with some dummy values for now.
+	 */
+	ParameterService();
+
+	/**
+	 * This function receives a TC[20, 1] packet and returns a TM[20, 2] packet
+	 * containing the current configuration
+	 * **for the parameters specified in the carried valid IDs**.
+	 *
+	 * No sophisticated error checking for now, just whether the package is of the correct type
+	 * and whether the requested IDs are valid, ignoring the invalid ones. If no IDs are correct,
+	 * the returned message shall be empty.
+	 *
+	 * @param paramId: a valid TC[20, 1] packet carrying the requested parameter IDs
+	 * @return None (messages are stored using storeMessage())
+	 *
+	 * @todo Generate failure notifs where needed when ST[01] is ready
+	 *
+	 * NOTES:
+	 * Method for valid ID counting is a hack (clones the message and figures out the number
+	 * separately, due to message access being non-random). Should be enough for now.
+	 *
+	 * Everything apart from the setting data is uint16 (setting data are uint32 for now)
+	 */
+	void reportParameterIds(Message paramIds);
+
+	/**
+	 * This function receives a TC[20, 3] message and after checking whether its type is correct,
+	 * iterates over all contained parameter IDs and replaces the settings for each valid parameter,
+	 * while ignoring all invalid IDs.
+	 *
+	 * @param newParamValues: a valid TC[20, 3] message carrying parameter ID and replacement value
+	 * @return None
+	 *
+	 * @todo Generate failure notifications where needed (eg. when an invalid ID is encountered)
+	 * @todo Use pointers for changing and storing addresses to comply with the standard
+	 */
+	void setParameterIds(Message newParamValues);
+
+};
+
+#endif //ECSS_SERVICES_PARAMETERSERVICE_HPP
diff --git a/src/Services/ParameterService.cpp b/src/Services/ParameterService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bf19881992e6265b8254ae0c09bc118a665a780f
--- /dev/null
+++ b/src/Services/ParameterService.cpp
@@ -0,0 +1,94 @@
+#include "Services/ParameterService.hpp"
+
+#define DEMOMODE
+
+#ifdef DEMOMODE
+
+#include <ctime>
+#include <cstdlib>
+
+#endif
+
+ParameterService::ParameterService() {
+#ifdef DEMOMODE
+	// Test code, setting up some of the parameter fields
+
+	time_t currTime = time(nullptr);
+	struct tm *today = localtime(&currTime);
+
+	paramsList[0].paramId = 0;                     // random parameter ID
+	paramsList[0].settingData = today->tm_hour;    // the current hour
+	paramsList[0].ptc = 3;                         // unsigned int
+	paramsList[0].pfc = 14;                        // 32 bits
+
+	paramsList[1].paramId = 1;                     // random parameter ID
+	paramsList[1].settingData = today->tm_min;     // the current minute
+	paramsList[1].ptc = 3;                         // unsigned int
+	paramsList[1].pfc = 14;                        // 32 bits
+#endif
+}
+
+void ParameterService::reportParameterIds(Message paramIds) {
+	Message reqParam(20, 2, Message::TM, 1);    // empty TM[20, 2] parameter report message
+
+	if (paramIds.packetType == Message::TC && paramIds.serviceType == 20 &&
+	    paramIds.messageType == 1) {
+		uint16_t ids = paramIds.readUint16();
+		reqParam.appendUint16(numOfValidIds(paramIds));   // include the number of valid IDs
+
+		for (int i = 0; i < ids; i++) {
+			uint16_t currId = paramIds.readUint16();      // current ID to be appended
+
+			if (currId < CONFIGLENGTH) {  // check to prevent out-of-bounds access due to invalid id
+				reqParam.appendUint16(currId);
+				reqParam.appendUint32(paramsList[currId].settingData);
+			} else {
+								// generate failure of execution notification for ST[06]
+				continue;       //ignore the invalid ID
+			}
+		}
+	}
+
+	storeMessage(reqParam);
+}
+
+void ParameterService::setParameterIds(Message newParamValues) {
+	if (newParamValues.packetType == Message::TC && newParamValues.serviceType == 20 &&
+	newParamValues.messageType == 3) {
+		uint16_t ids = newParamValues.readUint16();  //get number of ID's
+
+		for (int i = 0; i < ids; i++) {
+			uint16_t currId = newParamValues.readUint16();
+
+			if (currId < CONFIGLENGTH) {
+				paramsList[currId].settingData = newParamValues.readUint32();
+			} else {
+								// generate failure of execution notification for ST[06]
+				continue;       // ignore the invalid ID
+			}
+		}
+	}
+}
+
+uint16_t ParameterService::numOfValidIds(Message idMsg) {
+	idMsg.resetRead();
+	// start reading from the beginning of the idMsg object
+	// (original obj. will not be influenced if this is called by value)
+
+	uint16_t ids = idMsg.readUint16();        // first 16bits of the packet are # of IDs
+	uint16_t validIds = 0;
+
+	for (int i = 0; i < ids; i++) {
+		uint16_t currId = idMsg.readUint16();
+
+		if (idMsg.messageType == 3) {
+			idMsg.readUint32();   //skip the 32bit settings blocks, we need only the IDs
+		}
+
+		if (currId < CONFIGLENGTH) {
+			validIds++;
+		}
+	}
+
+	return validIds;
+}
diff --git a/src/main.cpp b/src/main.cpp
index a65e88ca40567509f00b257cadd5445286980ef2..d0f0ff29bc763ded60421813adf2cd78dc7c8959 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
-#include <Services/TestService.hpp>
-#include <Services/RequestVerificationService.hpp>
+#include "Services/TestService.hpp"
+#include "Services/ParameterService.hpp"
+#include "Services/RequestVerificationService.hpp"
 #include "Message.hpp"
 #include "Services/MemoryManagementService.hpp"
 
@@ -30,7 +31,29 @@ int main() {
 	receivedPacket.appendUint16(7);
 	testService.onBoardConnection(receivedPacket);
 
-	// ST[06] testing
+
+	// ST[20] test
+	ParameterService paramService;
+
+	// Test code for reportParameter
+	Message sentPacket = Message(20, 1, Message::TC, 1);  //application id is a dummy number (1)
+	sentPacket.appendUint16(2);  //number of contained IDs
+	sentPacket.appendUint16(0);  //first ID
+	sentPacket.appendUint16(1);  //second ID
+	paramService.reportParameterIds(sentPacket);
+
+	// Test code for setParameter
+	Message sentPacket2 = Message(20, 3, Message::TC, 1);  //application id is a dummy number (1)
+	sentPacket2.appendUint16(2);  //number of contained IDs
+	sentPacket2.appendUint16(0);  //first parameter ID
+	sentPacket2.appendUint32(63238);  //settings for first parameter
+	sentPacket2.appendUint16(1);  //2nd parameter ID
+	sentPacket2.appendUint32(45823);  //settings for 2nd parameter
+
+	paramService.setParameterIds(sentPacket2);
+	paramService.reportParameterIds(sentPacket);
+
+// ST[06] testing
 	char anotherStr[8] = "Fgthred";
 	char yetAnotherStr[2] = "F";
 	char *pStr = static_cast<char *>(malloc(4));
@@ -62,6 +85,7 @@ int main() {
 	rcvPack.appendUint64(reinterpret_cast<uint64_t >(pStr + 1)); // Start address
 	rcvPack.appendOctetString(1, data);
 	memMangService.rawDataMemorySubservice.loadRawData(rcvPack);
+	
 
 	// ST[01] test
 	// parameters take random values and works as expected
@@ -71,6 +95,5 @@ int main() {
 	reqVerifService.successExecutionVerification(Message::TC, true, 2, 2, 10);
 	reqVerifService.failExecutionVerification(Message::TC, true, 2, 2, 10, 6);
 	reqVerifService.failRoutingVerification(Message::TC, true, 2, 2, 10, 7);
-
 	return 0;
 }
diff --git a/test/Services/ParameterService.cpp b/test/Services/ParameterService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dbf1820b51e3d1d13f13f70e5f3eb7e139289894
--- /dev/null
+++ b/test/Services/ParameterService.cpp
@@ -0,0 +1,77 @@
+#include "catch2/catch.hpp"
+#include "Services/ParameterService.hpp"
+#include "Message.hpp"
+#include "ServiceTests.hpp"
+
+#define CATCH_CONFIG_MAIN
+
+TEST_CASE("Parameter Report Subservice") {
+	ParameterService pserv;
+
+	SECTION("Faulty Instruction Handling Test") {
+		Message request(20, 1, Message::TC, 1);
+		Message report(20, 2, Message::TM, 1);
+
+		request.appendUint16(2);      // number of requested IDs
+		request.appendUint16(34672);  // faulty ID in this context
+		request.appendUint16(3);      // valid
+
+		pserv.reportParameterIds(request);
+		report = ServiceTests::get(0);
+		request.resetRead();
+
+		report.readUint16();
+		request.readUint16();
+
+		while (report.readPosition <= report.dataSize) {
+			CHECK_FALSE(report.readUint16() == 34672);  //fail if faulty ID is present in report
+			report.readUint32();                   //ignore the carried settings
+		}
+	}
+
+	SECTION("Wrong Message Type Handling Test") {
+		Message falseRequest(15, 3, Message::TM, 1);   // a totally wrong message
+
+		pserv.reportParameterIds(falseRequest);
+		Message response = ServiceTests::get(0);
+		CHECK(response.messageType == 2);
+		CHECK(response.serviceType == 20);
+		CHECK(response.packetType == Message::TM);
+		CHECK(response.readPosition == 0);   // if empty, this should't change from 0
+	}
+}
+
+TEST_CASE("Parameter Setting Subservice") {
+	ParameterService pserv;
+
+	SECTION("Faulty Instruction Handling Test") {
+		Message setRequest(20, 3, Message::TC, 1);
+		Message reportRequest(20, 1, Message::TC, 1);
+
+		setRequest.appendUint16(2);           // correct number of IDs
+		setRequest.appendUint16(3);           // correct ID
+		setRequest.appendUint32(3735928559);  // 0xDEADBEEF in hex (new setting)
+		setRequest.appendUint16(16742);       // faulty ID in this context
+		setRequest.appendUint32(3131746989);  // 0xBAAAAAAD (this shouldn't be found in the report)
+
+		reportRequest.appendUint16(2);
+		reportRequest.appendUint16(16742);
+		reportRequest.appendUint16(3);
+
+		pserv.reportParameterIds(reportRequest);
+		Message before = ServiceTests::get(0);
+
+		pserv.setParameterIds(setRequest);
+
+		pserv.reportParameterIds(reportRequest);
+		Message after = ServiceTests::get(1);
+
+		before.readUint16();
+		after.readUint16();                    // skip the number of IDs
+
+		while (after.readPosition <= after.dataSize) {
+			CHECK(before.readUint16() == after.readUint16());   // check if all IDs are present
+			CHECK_FALSE(after.readUint32() == 0xBAAAAAAD);   // fail if any settings are BAAAAAAD :P
+		}
+	}
+}