diff --git a/crazyCART.sh b/crazyCART.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e6547e49183cf914864829165fffcbffbc930d85
--- /dev/null
+++ b/crazyCART.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+function handler()
+{
+    kill -s SIGINT $CFPID
+    kill -s SIGINT $APID
+    kill -s SIGINT $BPID
+}
+
+cd ./crazyflie_groundstation
+#xterm -hold -e './crazyflieGroundStation' &
+./crazyflieGroundStation &
+CFPID=$!
+echo "Waiting for crazyflie groundstation to be created..."
+cf_gs=crazyflie_groundstation.socket
+while [ ! -S "$cf_gs"  ]
+do
+    sleep 1
+done
+cd ../groundStation/adapters/crazyflie
+sleep 1
+./bin/cf_adapter &
+APID=$!
+sleep 1
+cd ../..
+./BackEnd &
+BPID=$!
+
+trap handler INT
+
+wait
\ No newline at end of file
diff --git a/crazyflie_groundstation/.gitignore b/crazyflie_groundstation/.gitignore
index 245a8f80ebc0134dfbe67cec806e74803aef375b..28e2026088a5c9e92889acf2da7bd03cb5c90312 100644
--- a/crazyflie_groundstation/.gitignore
+++ b/crazyflie_groundstation/.gitignore
@@ -1,2 +1,3 @@
 crazyflieGroundStation
 test_connection
+logs/*
diff --git a/crazyflie_groundstation/inc/CCrazyflie.h b/crazyflie_groundstation/inc/CCrazyflie.h
index 62281cefe605649fa2dda02e1b3936608f747665..b1a738f6b2891df219c50a728d299781d5a9a477 100644
--- a/crazyflie_groundstation/inc/CCrazyflie.h
+++ b/crazyflie_groundstation/inc/CCrazyflie.h
@@ -313,6 +313,8 @@ class CCrazyflie {
    */
   void openLogFile(char *baseFileName);
 
+  void printUpdatedHeader();
+
   bool loadLoggingBlocksFromFile(std::string blockFileName);
 
   bool resetLoggingBlocks();
diff --git a/crazyflie_groundstation/inc/CTOC.h b/crazyflie_groundstation/inc/CTOC.h
index 22da31fdc714abab28da81ba2704772eadc341d9..fd96360f7b41207504cf9f149e7e4c25063dac5c 100644
--- a/crazyflie_groundstation/inc/CTOC.h
+++ b/crazyflie_groundstation/inc/CTOC.h
@@ -39,6 +39,7 @@
 #include <cstdlib>
 #include <iostream>
 #include <fstream>
+#include <vector>
 
 // Private
 #include "CCrazyRadio.h"
@@ -67,6 +68,7 @@ struct LoggingBlock {
   int nID;
   double dFrequency;
   std::list<int> lstElementIDs;
+  bool isActive;
 };
 
 // Backward declaration of the CCrazyflie and CCrazyradio class to make the compiler happy
@@ -82,6 +84,8 @@ class CTOC {
   int m_nItemCount;
   std::list<struct TOCElement> m_lstTOCElements;
   std::list<struct LoggingBlock> m_lstLoggingBlocks;
+  std::vector<std::string> m_lstActiveLogging;
+  int updateAmount = 0;
   std::ofstream param_toc_file;
   std::ofstream log_toc_file;
   std::string paramfilename;
@@ -116,6 +120,7 @@ class CTOC {
   // For loggable variables only
   bool registerLoggingBlock(std::string strName, double dFrequency);
   bool unregisterLoggingBlock(std::string strName);
+  bool unregisterLoggingBlocks();
   struct LoggingBlock loggingBlockForName(std::string strName, bool& bFound);
   struct LoggingBlock loggingBlockForID(int nID, bool& bFound);
 
@@ -127,6 +132,8 @@ class CTOC {
 
   bool enableLogging(std::string strBlockName);
   bool disableLogging(std::string strBlockName);
+  void setBlockActive(int nID, bool activity);
+  std::string createActiveHeader();
 
 //  void processPackets(std::list<CCRTPPacket*> lstPackets);
   void processPackets(CCRTPPacket *crtpPacket);
@@ -140,6 +147,9 @@ class CTOC {
   void openParamTOCFile(char *baseFileName);
   std::string getLogTOCFile();
   std::string getParamTOCFile();
+
+  std::string activeLogName(int index);
+  int sizeOfActiveList();
 };
 
 
diff --git a/crazyflie_groundstation/src/CTOC.cpp b/crazyflie_groundstation/src/CTOC.cpp
index d609404474455edb9c44127000cad972ba0a5ac6..27c1cf444cd3b99d808785d828cb0716fb62b803 100644
--- a/crazyflie_groundstation/src/CTOC.cpp
+++ b/crazyflie_groundstation/src/CTOC.cpp
@@ -30,10 +30,10 @@
 
 #include <limits>
 
-static const char *param_header = "Param ID\tType\t\tGroup\t\t"
+static const char *param_header = "Param ID\tType\tGroup\t"
 						   "Identifier Name";
 
-static const char *log_header = "Log ID\tType\t\tGroup\t\t"
+static const char *log_header = "Log ID\tType\tGroup\t"
 						   "Identifier Name";
 
 CTOC::CTOC(CCrazyRadio *crRadio, CCrazyflie *crazyflie, int radioChannel, int nPort) {
@@ -172,6 +172,7 @@ bool CTOC::downloadTOC() {
 			printf("Parameter Progress: %i / %i\n", nI+1, m_nItemCount);
 			this->requestItem(nI);
 		}
+		param_toc_file.close();
 	}
 	else {
 		this->requestMetaData();
@@ -179,6 +180,7 @@ bool CTOC::downloadTOC() {
 			printf("Logging Progress: %i / %i\n", nI+1, m_nItemCount);
 			this->requestItem(nI);
 		}
+		log_toc_file.close();
 	}
 	if( ALL_THE_DEBUG ) printf( "Exit: %s\n", __FUNCTION__);
 	return true;
@@ -219,10 +221,10 @@ bool CTOC::processItem(CCRTPPacket* crtpItem) {
 				if(ALL_THE_DEBUG) printf("Group.Name: %s.%s ID: %i Type: %i ", strGroup.c_str(), strIdentifier.c_str(), nID, nType);
 
 				if(m_nPort == 0x02) {
-					this->param_toc_file << teNew.nID << "\t\t" << teNew.nType << "\t\t" << teNew.strGroup << "\t\t" << teNew.strIdentifier << std::endl;
+					this->param_toc_file << teNew.nID << "\t" << teNew.nType << "\t" << teNew.strGroup << "\t" << teNew.strIdentifier << std::endl;
 				}
 				else if(m_nPort = 0x05) {
-					this->log_toc_file << teNew.nID << "\t\t" << teNew.nType << "\t\t" << teNew.strGroup << "\t\t" << teNew.strIdentifier << std::endl;
+					this->log_toc_file << teNew.nID << "\t" << teNew.nType << "\t" << teNew.strGroup << "\t" << teNew.strIdentifier << std::endl;
 				}
 
 				m_lstTOCElements.push_back(teNew);
@@ -561,6 +563,45 @@ void CTOC::printLoggingBlocksInitialized() {
 	}
 }
 
+bool compare_id(const struct LoggingBlock& first, const struct LoggingBlock& second) {
+	return (first.nID < second.nID);
+}
+
+std::string CTOC::createActiveHeader() {
+	std::string header = "#" + std::to_string(updateAmount) + ": " + "\t";
+	header = header + "time" + "\t";
+	std::string element = "";
+	m_lstActiveLogging.clear();
+	m_lstLoggingBlocks.sort(compare_id);
+	bool bFound = false;
+	for (std::list<struct LoggingBlock>::iterator itBlock = m_lstLoggingBlocks.begin();
+		 itBlock != m_lstLoggingBlocks.end();
+		 itBlock++) {
+		struct LoggingBlock lbCurrent = *itBlock;
+
+		if(lbCurrent.isActive) {
+			for(int i = 0; i < lbCurrent.lstElementIDs.size(); i++) {
+				int elementID = this->elementIDinBlock(lbCurrent.nID, i);
+				struct TOCElement teCurrent = this->elementForID(elementID,
+					bFound);
+				element = teCurrent.strGroup + "." + teCurrent.strIdentifier;
+				header = header + element + "\t";
+				m_lstActiveLogging.push_back(element);
+			}
+		}			
+	}
+	updateAmount++;
+	return header;
+}
+
+std::string CTOC::activeLogName(int index) {
+	return m_lstActiveLogging.at(index);
+}
+
+int CTOC::sizeOfActiveList() {
+	return m_lstActiveLogging.size();
+}
+
 struct LoggingBlock CTOC::loggingBlockForName(std::string strName,
 		bool& bFound) {
     if( ALL_THE_DEBUG ) printf( "%s\n", __FUNCTION__);
@@ -667,6 +708,7 @@ bool CTOC::enableLogging(std::string strBlockName) {
 	struct LoggingBlock lbCurrent = this->loggingBlockForName(strBlockName,
 			bFound);
 	if (bFound) {
+		this->setBlockActive(lbCurrent.nID, true);
 		uint8_t logPeriod= (uint8_t) ( (1 / lbCurrent.dFrequency) * 1000 );
 		char cPayload[3] = { 0x03, (char)lbCurrent.nID, logPeriod }; // JRB: A little concerned about this cast from double to char
 
@@ -692,6 +734,7 @@ bool CTOC::disableLogging(std::string strBlockName) {
 			bFound);
 
 	if (bFound) {
+		this->setBlockActive(lbCurrent.nID, false);
 		char cPayload[2] = { 0x04, (char)lbCurrent.nID }; // JRB: A little concerned about this cast from double to char
 
 		CCRTPPacket* crtpEnable = new CCRTPPacket(cPayload, 2, 1);
@@ -721,6 +764,31 @@ bool CTOC::unregisterLoggingBlock(std::string strName) {
 	return false;
 }
 
+bool CTOC::unregisterLoggingBlocks() {
+    if( ALL_THE_DEBUG ) printf( "%s\n", __FUNCTION__);
+	bool bFound;
+
+	char cPayload[1] = { 0x05 };
+
+	CCRTPPacket* resetBlock = new CCRTPPacket(cPayload, 1, 1);
+	resetBlock->setPort(0x05);
+	resetBlock->setChannel(1);
+
+	CCRTPPacket* crtpReceived = m_crRadio->sendAndReceive(resetBlock, m_nRadioChannel, m_crazyflie);
+
+	delete resetBlock;
+
+	if (crtpReceived) {
+		delete crtpReceived;
+		for(std::list<struct LoggingBlock>::iterator itBlock = m_lstLoggingBlocks.begin(); itBlock != m_lstLoggingBlocks.end(); itBlock++) {
+			itBlock = m_lstLoggingBlocks.erase(itBlock);
+		}
+		return true;
+	}
+
+	return false;
+}
+
 bool CTOC::unregisterLoggingBlockID(int nID) {
     if( ALL_THE_DEBUG ) printf( "%s\n", __FUNCTION__);
 	char cPayload[2] = { 0x02, (char)nID };
@@ -945,8 +1013,9 @@ void CTOC::openParamTOCFile(char *baseFileName) {
 	printf("Opening param toc file %s  for quadcopter %d...", logFileName, (this->m_crazyflie->getQuadcopterNumber() + 1));
 
 	try {
-		char dir[250];
-		getcwd(dir, 250);
+		char dir[256];
+		dir[0] = '/';
+		getcwd(&dir[1], 255);
 		std::string fullFilePath(dir);
 		fullFilePath += "/";
 		fullFilePath += logFileName;
@@ -985,8 +1054,9 @@ void CTOC::openLogTOCFile(char *baseFileName) {
 	printf("Opening param toc file %s  for quadcopter %d...", logFileName, (this->m_crazyflie->getQuadcopterNumber() + 1));
 
 	try {
-		char dir[250];
-		getcwd(dir, 250);
+		char dir[256];
+		dir[0] = '/';
+		getcwd(&dir[1], 255);
 		std::string fullFilePath(dir);
 		fullFilePath += "/";
 		fullFilePath += logFileName;
@@ -1021,4 +1091,15 @@ std::string CTOC::getParamTOCFile() {
 	else {
 		return this->paramfilename;
 	}
+}
+
+void CTOC::setBlockActive(int nID, bool activity) {
+    if( ALL_THE_DEBUG ) printf( "Enter: %s\n", __FUNCTION__);
+	for(std::list<struct LoggingBlock>::iterator itBlock = m_lstLoggingBlocks.begin(); itBlock != m_lstLoggingBlocks.end(); itBlock++) {
+		struct LoggingBlock &lbCurrent = *itBlock;
+		if (nID == lbCurrent.nID) {
+			lbCurrent.isActive = activity;
+			return;
+		}
+	}
 }
\ No newline at end of file
diff --git a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp
index 7916a1100f664fc88eac2306b9364e754e08ad3f..2a3e4cf021544c214007bf32ddb47470b752e08f 100644
--- a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp
+++ b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp
@@ -179,7 +179,7 @@ bool CCrazyflie::parseReceivedUserCommand() {
 	
 	case ACMD_GETPARAM:
 		{
-			int nSize = 1;
+			int nSize = 2;
 			char cBuffer[nSize];
 
 			CCRTPPacket *crtpPacket = new CCRTPPacket(cBuffer, nSize, CRTP_PORT_PARAM);
@@ -187,13 +187,15 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			CCRTPPacket *crtpReceived;
 
 			//int id = (char) command.payload;
-			char id = (char) command.payload[2];
+			//char id = (char) command.payload[2];
+			uint16_t id;
+			memcpy(&id, &command.payload[2], sizeof(uint16_t));
+			memcpy(cBuffer, &command.payload[2], sizeof(uint16_t));
 			//float fvalue = build_float(&command.payload[4]);
 			//uint16_t pvalue = (uint16_t) fvalue;
 			bool bFound = false;
 			struct TOCElement element = this->m_tocParameters->elementForID(id, bFound);
 
-			cBuffer[0] = id;
 			//memcpy(&cBuffer[1 * sizeof(uint16_t)], &pvalue, sizeof(uint16_t));
 			crtpPacket->setData(cBuffer, nSize);
 			crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
@@ -208,7 +210,7 @@ bool CCrazyflie::parseReceivedUserCommand() {
 
 	case ACMD_SETPARAM:
 		{
-		int nSize = sizeof(double) + 1;
+		int nSize = sizeof(double) + 2;
 		char cBuffer[nSize];
 
 		CCRTPPacket *crtpPacket = new CCRTPPacket(cBuffer, nSize, CRTP_PORT_PARAM);
@@ -216,7 +218,10 @@ bool CCrazyflie::parseReceivedUserCommand() {
 		CCRTPPacket *crtpReceived;
 
 		//int id = (char) command.payload;
-		char pid = (char) command.payload[2];
+		//char pid = (char) command.payload[2];
+		uint16_t pid;
+		memcpy(&pid, &command.payload[2], 2);
+		memcpy(cBuffer, &command.payload[2], 2);
 		bool bFound = false;
 		struct TOCElement element = this->m_tocParameters->elementForID(pid, bFound);
 		uint8_t pType = element.nType;
@@ -226,9 +231,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				uint8_t pvalue = (uint8_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(uint8_t));
-				nSize = 1 + sizeof(uint8_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(uint8_t));
+				nSize = 2 + sizeof(uint8_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -237,9 +241,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				uint16_t pvalue = (uint16_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(uint16_t));
-				nSize = 1 + sizeof(uint16_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(uint16_t));
+				nSize = 2 + sizeof(uint16_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -248,9 +251,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				uint32_t pvalue = (uint32_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(uint32_t));
-				nSize = 1 + sizeof(uint32_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(uint32_t));
+				nSize = 2 + sizeof(uint32_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -259,9 +261,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				uint64_t pvalue = (uint64_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(uint64_t));
-				nSize = 1 + sizeof(uint64_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(uint64_t));
+				nSize = 2 + sizeof(uint64_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -270,9 +271,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				int8_t pvalue = (int8_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(int8_t));
-				nSize = 1 + sizeof(int8_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(int8_t));
+				nSize = 2 + sizeof(int8_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -281,9 +281,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				int16_t pvalue = (int16_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(int16_t));
-				nSize = 1 + sizeof(int16_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(int16_t));
+				nSize = 2 + sizeof(int16_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -292,9 +291,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				int32_t pvalue = (uint32_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(int32_t));
-				nSize = 1 + sizeof(int32_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(int32_t));
+				nSize = 2 + sizeof(int32_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -303,9 +301,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				int64_t pvalue = (int64_t) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(int64_t));
-				nSize = 1 + sizeof(int64_t);
+				memcpy(&cBuffer[2], &pvalue, sizeof(int64_t));
+				nSize = 2 + sizeof(int64_t);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -314,9 +311,8 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				float pvalue = fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(float));
-				nSize = 1 + sizeof(float);
+				memcpy(&cBuffer[2], &pvalue, sizeof(float));
+				nSize = 2 + sizeof(float);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
@@ -325,16 +321,13 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			{
 				double pvalue = (double) fvalue;
 
-				cBuffer[0] = pid;
-				memcpy(&cBuffer[1], &pvalue, sizeof(double));
-				nSize = 1 + sizeof(double);
+				memcpy(&cBuffer[2], &pvalue, sizeof(double));
+				nSize = 2 + sizeof(double);
 				crtpPacket->setData(cBuffer, nSize);
 				crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this);
 				break;
 			}
 		}
-		
-		
 		break;
 		}
 
@@ -345,41 +338,45 @@ bool CCrazyflie::parseReceivedUserCommand() {
 			float yaw = build_float(&command.payload[17]);
 			float fthrust = build_float(&command.payload[5]);
 			float ftime = build_float(&command.payload[1]);
+			int nSize = 4 * sizeof(float) + sizeof(char);
+			char cBuffer[nSize];
 			if(command.payload[0] == 1) {
-				short thrust = (short) fthrust;
-				this->sendSetpoint(roll, pitch, yaw, thrust);
+				cBuffer[0] = 9;
 			}
 			else if(command.payload[0] == 2) {
-				int nSize = 4 * sizeof(float) + sizeof(char);
-				char cBuffer[nSize];
 				cBuffer[0] = 8;
-				memcpy(&cBuffer[0 * sizeof(float) + 1], &roll, sizeof(float));
-				memcpy(&cBuffer[1 * sizeof(float) + 1], &pitch, sizeof(float));
-				memcpy(&cBuffer[2 * sizeof(float) + 1], &yaw, sizeof(float));
-				memcpy(&cBuffer[3 * sizeof(float) + 1], &fthrust, sizeof(float));
-
-				CCRTPPacket *crtpPacket = new CCRTPPacket(cBuffer, nSize, 7);
-				crtpPacket->setChannel(0x00);
-				int milliseconds = ftime*1000;
-				CCRTPPacket *crtpReceived = NULL;
-				if(ftime == 0) {
+			}
+			else {
+				break;
+			}
+			memcpy(&cBuffer[0 * sizeof(float) + 1], &roll, sizeof(float));
+			memcpy(&cBuffer[1 * sizeof(float) + 1], &pitch, sizeof(float));
+			memcpy(&cBuffer[2 * sizeof(float) + 1], &yaw, sizeof(float));
+			memcpy(&cBuffer[3 * sizeof(float) + 1], &fthrust, sizeof(float));
+
+			CCRTPPacket *crtpPacket = new CCRTPPacket(cBuffer, nSize, 7);
+			crtpPacket->setChannel(0x00);
+			int milliseconds = ftime*1000;
+			CCRTPPacket *crtpReceived = NULL;
+			if(ftime == 0) {
+				crtpReceived = m_crRadio->sendPacket(m_nRadioChannel, crtpPacket, this);
+			}
+			else {
+				auto start = std::chrono::high_resolution_clock::now();
+				auto timeNow = std::chrono::high_resolution_clock::now();
+				auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow-start);
+				while(duration.count() < milliseconds) {
+					usleep(10);
 					crtpReceived = m_crRadio->sendPacket(m_nRadioChannel, crtpPacket, this);
+					timeNow = std::chrono::high_resolution_clock::now();
+					duration = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow-start);
 				}
-				else {
-					auto start = std::chrono::high_resolution_clock::now();
-					auto timeNow = std::chrono::high_resolution_clock::now();
-					auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow-start);
-					while(duration.count() < milliseconds) {
-						usleep(10);
-						crtpReceived = m_crRadio->sendPacket(m_nRadioChannel, crtpPacket, this);
-						timeNow = std::chrono::high_resolution_clock::now();
-						duration = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow-start);
-					}
-				}
-
-				
-				delete crtpPacket;
+				cBuffer[0] = 0;
+				nSize = sizeof(char);
+				crtpPacket->setData(cBuffer, nSize);
+				crtpReceived = m_crRadio->sendPacket(m_nRadioChannel, crtpPacket, this);
 			}
+			delete crtpPacket;
 			break;
 		}
 	case ACMD_GETLOGFILE:
@@ -425,34 +422,40 @@ bool CCrazyflie::parseReceivedUserCommand() {
 				case 0:
 				{
 					this->resetLoggingBlocks();
+					this->printUpdatedHeader();
 					break;
 				}
 				case 1:
 				{
 					this->resetLoggingBlocks();
 					this->loadLoggingBlocksFromFile("loggingBlocks.txt");
+					this->printUpdatedHeader();
 					break;
 				}
 				case 2:
 				{
 					this->loadLoggingBlocksFromFile("loggingBlocks.txt");
+					this->printUpdatedHeader();
 					break;
 				}
 				case 3:
 				{
 					this->m_tocLogs->unregisterLoggingBlockID(id);
+					this->printUpdatedHeader();
 					break;
 				}
 				case 4:
 				{
 					struct LoggingBlock block = this->m_tocLogs->loggingBlockForID(id, found);
 					this->enableLogging(block.strName);
+					this->printUpdatedHeader();
 					break;
 				}
 				case 5:
 				{
 					struct LoggingBlock block = this->m_tocLogs->loggingBlockForID(id, found);
 					this->disableLogging(block.strName);
+					this->printUpdatedHeader();
 					break;
 				}
 			}
diff --git a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp
index 293470194d98e1370fb7bb0780ab3e79a69f7f7b..a786c9f4eaa67e0aa673f1623ea16aff62e63398 100644
--- a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp
+++ b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp
@@ -52,8 +52,9 @@ void CCrazyflie::openLogFile(char *baseFileName) {
 	printf("Opening log file %s  for quadcopter %d...", logFileName, (m_quadNum + 1));
 
 	try {
-		char dir[250];
-		getcwd(dir, 250);
+		char dir[256];
+		dir[0] = '/';
+		getcwd(&dir[1], 255);
 		std::string fullFilePath(dir);
 		fullFilePath += "/";
 		fullFilePath += logFileName;
@@ -68,9 +69,9 @@ void CCrazyflie::openLogFile(char *baseFileName) {
 	file_log << "#Crazyflie" << std::endl;
 
 	// Add the controller type to the logfile
-	file_log << "#" << this->getControllerTypeString() << std::endl;
-	file_log << variables << std::endl;
-	file_log << units << std::endl;
+	file_log << "#" << this->getControllerTypeString();
+	//file_log << variables << std::endl;
+	//file_log << units << std::endl;
 
 	std::cout << " Complete" << std::endl;
 }
@@ -79,7 +80,7 @@ void CCrazyflie::openLogFile(char *baseFileName) {
  * Write data to the log file
  */
 void CCrazyflie::writeLogData() {
-	// Make a new line
+	/* Make a new line
 	file_log << std::endl;
 
 	// Print the time
@@ -110,6 +111,12 @@ void CCrazyflie::writeLogData() {
 	file_log << "\t\t" << this->sensorDoubleValue("ctrlStdnt.rollRate");
 
 	file_log << "\t\t" << this->sensorDoubleValue("testStand");
+	*/
+	file_log << std::endl;
+	file_log << this->currentTime();
+	for(int i = 0; i < m_tocLogs->sizeOfActiveList(); i++) {
+		file_log << "\t" << this->sensorDoubleValue(m_tocLogs->activeLogName(i));
+	}
 }
 
 
@@ -165,22 +172,8 @@ bool CCrazyflie::addLoggingBlock(const char *name, uint16_t frequency) {
 
 bool CCrazyflie::resetLoggingBlocks() {
 	if( ALL_THE_DEBUG ) printf( "%s\n", __FUNCTION__);
-	char cPayload[1] = { 0x05 };
-
-	CCRTPPacket* resetBlock = new CCRTPPacket(cPayload, 2, 1);
-	resetBlock->setPort(0x05);
-	resetBlock->setChannel(1);
-
-	CCRTPPacket* crtpReceived = m_crRadio->sendAndReceive(resetBlock, m_nRadioChannel, this);
-
-	delete resetBlock;
-
-	if (crtpReceived) {
-		delete crtpReceived;
-		return true;
-	}
-
-	return false;
+	bool result = m_tocLogs->unregisterLoggingBlocks();
+	return result;
 }
 
 void CCrazyflie::removeLoggingBlock(const char *name) {
@@ -295,7 +288,7 @@ bool CCrazyflie::loadLoggingBlocksFromFile(std::string blockFileName) {
 		else if(!line.compare("END BLOCK")) {
 			enableLogging(curName);
 			blockLinesRead = 0;
-			int curId = -1;
+			curId = -1;
 			curFreq = 0;
 			curName = "";
 			curEntryName = "";
@@ -304,6 +297,16 @@ bool CCrazyflie::loadLoggingBlocksFromFile(std::string blockFileName) {
 		else if(blockLinesRead == 1) {
 			try {
 				curId = std::stoi(line);
+				bool found = false;
+				m_tocLogs->loggingBlockForID(curId, found);
+				if(found) {
+					blockLinesRead = 0;
+					curId = -1;
+					curFreq = 0;
+					curName = "";
+					curEntryName = "";
+					continue;
+				}
 			}
 			catch(std::invalid_argument& e) {
 				std::cout << "Error: invalid ID. Skipping Block" << std::endl;
@@ -343,4 +346,9 @@ bool CCrazyflie::loadLoggingBlocksFromFile(std::string blockFileName) {
 	}
 	blockFile.close();
 	return true;
+}
+
+void CCrazyflie::printUpdatedHeader() {
+	file_log << std::endl;
+	file_log << m_tocLogs->createActiveHeader();
 }
\ No newline at end of file
diff --git a/crazyflie_groundstation/src/crazyflieGroundStation.cpp b/crazyflie_groundstation/src/crazyflieGroundStation.cpp
index acf54773031a0250c67da9d145339f0cea419a96..c3f2a930fb523a7a47683886dcb80e8fa7036336 100644
--- a/crazyflie_groundstation/src/crazyflieGroundStation.cpp
+++ b/crazyflie_groundstation/src/crazyflieGroundStation.cpp
@@ -368,6 +368,7 @@ int main(int argc, char **argv) {
 		*/
 
 		crazyflie_info[i].cflieCopter->loadLoggingBlocksFromFile("loggingBlocks.txt");
+		crazyflie_info[i].cflieCopter->printUpdatedHeader();
 
 		crazyflie_info[i].cflieCopter->displayLoggingBlocksInitialized();
 
diff --git a/crazyflie_software/crazyflie-firmware-2021.06/src/modules/src/crtp_commander_generic.c b/crazyflie_software/crazyflie-firmware-2021.06/src/modules/src/crtp_commander_generic.c
index 9d038cc5cef93c1fedca5e75ffc24ea7ad3e9524..a4b1f55c47b4b46387a0a6fd2fb5348b3465c9e1 100644
--- a/crazyflie_software/crazyflie-firmware-2021.06/src/modules/src/crtp_commander_generic.c
+++ b/crazyflie_software/crazyflie-firmware-2021.06/src/modules/src/crtp_commander_generic.c
@@ -72,6 +72,7 @@ enum packet_type {
   fullStateType     = 6,
   positionType      = 7,
   attitudeRateType  = 8,
+  attitudeType      = 9,
 };
 
 /* ---===== 2 - Decoding functions =====--- */
@@ -399,6 +400,37 @@ static void attitudeRateDecoder(setpoint_t *setpoint, uint8_t type, const void *
   setpoint->thrust = values->thrust;
 }
 
+/*
+ * Custom Attitude decoder, bypasses the normal attitude control path,
+ * packet contains the desired attitude angle in addition to the thrust value
+ */
+struct attitudePacket_s{
+  float rollAngle;   // deg
+  float pitchAngle;  // deg
+  float yawAngle;    // deg
+  float thrust;     // thrust percentage 0 - 60,000 
+} __attribute__((packed));
+static void attitudeDecoder(setpoint_t *setpoint, uint8_t type, const void *data, size_t datalen){
+  
+  const struct attitudePacket_s *values = data;
+
+  ASSERT(datalen == sizeof(struct attitudePacket_s));
+
+  setpoint->mode.x = modeDisable;
+  setpoint->mode.y = modeDisable;
+  setpoint->mode.z = modeDisable;
+
+  setpoint->mode.roll = modeAbs;
+  setpoint->mode.pitch = modeAbs;
+  setpoint->mode.yaw = modeAbs;
+  
+  setpoint->attitude.roll = values->rollAngle;
+  setpoint->attitude.pitch = values->pitchAngle;
+  setpoint->attitude.yaw = values->yawAngle;
+  
+  setpoint->thrust = values->thrust;
+}
+
  /* ---===== 3 - packetDecoders array =====--- */
 const static packetDecoder_t packetDecoders[] = {
   [stopType]          = stopDecoder,
@@ -410,6 +442,7 @@ const static packetDecoder_t packetDecoders[] = {
   [fullStateType]     = fullStateDecoder,
   [positionType]      = positionDecoder,
   [attitudeRateType]  = attitudeRateDecoder,
+  [attitudeType]      = attitudeDecoder,
 };
 
 /* Decoder switch */
diff --git a/groundStation/.gitignore b/groundStation/.gitignore
index 8a84dfc99eef1e265992a59c95b64e44e3b8cbd4..d79f2ff263194e6e7781caf076590450e9638831 100644
--- a/groundStation/.gitignore
+++ b/groundStation/.gitignore
@@ -56,11 +56,4 @@ setparam
 gettrackable
 settrackable
 
-#Qt
-gui/MicroCART/Makefile
-gui/MicroCART/MicroCART
-gui/MicroCART/MicroCART.pro*
-gui/MicroCART/moc*
-gui/MicroCART/qrc_resources.cpp
-gui/MicroCART/ui_mainwindow.h
 
diff --git a/groundStation/adapters/crazyflie/src/cf_adapter.c b/groundStation/adapters/crazyflie/src/cf_adapter.c
index eaf8f428756186c289296f22fbc8192e2def7ddb..84871e5b427c5df325c72d548198dfb3439a1567 100644
--- a/groundStation/adapters/crazyflie/src/cf_adapter.c
+++ b/groundStation/adapters/crazyflie/src/cf_adapter.c
@@ -5,7 +5,7 @@
 
 //socket that the crazyflie groundstation will read from, check the README for information
 //on how to setup this path.
-#define DEFAULT_ADAPTER_SOCKET "/home/bitcraze/projects/crazyflie_groundstation.socket"
+#define DEFAULT_ADAPTER_SOCKET "../../../crazyflie_groundstation/crazyflie_groundstation.socket"
 //#define DEFAULT_ADAPTER_SOCKET "./crazyflie_groundstation.socket"
 #define SOCKET_ENV "ADAPTER_SOCKET"
 
diff --git a/groundStation/gui/MicroCART/.gitignore b/groundStation/gui/MicroCART/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d5ce34de5297da99798e7d40d2d85f383424787e
--- /dev/null
+++ b/groundStation/gui/MicroCART/.gitignore
@@ -0,0 +1,54 @@
+# C++ objects and libs
+*.slo
+*.lo
+*.o
+*.a
+*.la
+*.lai
+*.so
+*.so.*
+*.dll
+*.dylib
+
+# Qt-es
+object_script.*.Release
+object_script.*.Debug
+*_plugin_import.cpp
+/.qmake.cache
+/.qmake.stash
+*.pro.user
+*.pro.user.*
+*.qbs.user
+*.qbs.user.*
+*.moc
+moc_*.cpp
+moc_*.h
+qrc_*.cpp
+ui_*.h
+*.qmlc
+*.jsc
+Makefile*
+*build-*
+*.qm
+*.prl
+
+# Qt unit tests
+target_wrapper.*
+
+# QtCreator
+*.autosave
+
+# QtCreator Qml
+*.qmlproject.user
+*.qmlproject.user.*
+
+# QtCreator CMake
+CMakeLists.txt.user*
+
+# QtCreator 4.8< compilation database
+compile_commands.json
+
+# QtCreator local machine specific files for imported projects
+*creator.user*
+
+*_qmlcache.qrc
\ No newline at end of file
diff --git a/groundStation/gui/MicroCART/MicroCART.cflags b/groundStation/gui/MicroCART/MicroCART.cflags
new file mode 100644
index 0000000000000000000000000000000000000000..68d51653007222e0f75ee44e0b2330af6e9b7b2d
--- /dev/null
+++ b/groundStation/gui/MicroCART/MicroCART.cflags
@@ -0,0 +1 @@
+-std=c17
\ No newline at end of file
diff --git a/groundStation/gui/MicroCART/MicroCART.config b/groundStation/gui/MicroCART/MicroCART.config
new file mode 100644
index 0000000000000000000000000000000000000000..e0284f42573a21b9d3f32775068f4dc233bf1c27
--- /dev/null
+++ b/groundStation/gui/MicroCART/MicroCART.config
@@ -0,0 +1,2 @@
+// Add predefined macros for your project here. For example:
+// #define THE_ANSWER 42
diff --git a/groundStation/gui/MicroCART/MicroCART.creator b/groundStation/gui/MicroCART/MicroCART.creator
new file mode 100644
index 0000000000000000000000000000000000000000..e94cbbd3027df32cb00f4fca093d5c72d9696a85
--- /dev/null
+++ b/groundStation/gui/MicroCART/MicroCART.creator
@@ -0,0 +1 @@
+[General]
diff --git a/groundStation/gui/MicroCART/MicroCART.cxxflags b/groundStation/gui/MicroCART/MicroCART.cxxflags
new file mode 100644
index 0000000000000000000000000000000000000000..6435dfce2fbb9c120633cbc667f028badd3e17c2
--- /dev/null
+++ b/groundStation/gui/MicroCART/MicroCART.cxxflags
@@ -0,0 +1 @@
+-std=c++17
\ No newline at end of file
diff --git a/groundStation/gui/MicroCART/MicroCART.files b/groundStation/gui/MicroCART/MicroCART.files
new file mode 100644
index 0000000000000000000000000000000000000000..0ce8141d43852df971238ce1de596c4f643e6bfb
--- /dev/null
+++ b/groundStation/gui/MicroCART/MicroCART.files
@@ -0,0 +1,40 @@
+MicroCART
+MicroCART.pro
+README.md
+controlworker.cpp
+controlworker.h
+crazyflieworker.cpp
+crazyflieworker.h
+gamepadmonitor.cpp
+gamepadmonitor.h
+gridlines.gif
+main.cpp
+mainwindow.cpp
+mainwindow.h
+mainwindow.ui
+moc_controlworker.cpp
+moc_crazyflieworker.cpp
+moc_mainwindow.cpp
+moc_predefs.h
+moc_qFlightInstruments.cpp
+moc_qattitudeindicator.cpp
+moc_qcustomplot.cpp
+moc_quaditem.cpp
+moc_slotprocess.cpp
+moc_trackerworker.cpp
+qFlightInstruments.cpp
+qFlightInstruments.h
+qcustomplot.cpp
+qcustomplot.h
+qrc_resources.cpp
+quad.png
+quaditem.cpp
+quaditem.h
+resources.qrc
+setpoint.cpp
+setpoint.h
+slotprocess.cpp
+slotprocess.h
+trackerworker.cpp
+trackerworker.h
+ui_mainwindow.h
diff --git a/groundStation/gui/MicroCART/MicroCART.includes b/groundStation/gui/MicroCART/MicroCART.includes
new file mode 100644
index 0000000000000000000000000000000000000000..9c558e357c41674e39880abb6c3209e539de42e2
--- /dev/null
+++ b/groundStation/gui/MicroCART/MicroCART.includes
@@ -0,0 +1 @@
+.
diff --git a/groundStation/gui/MicroCART/MicroCART.pro b/groundStation/gui/MicroCART/MicroCART.pro
index 3548b01aab3ffb98b73ad450bf45eb0744e4683c..d38edbeee72bb9f4e95a72c0dd93931435e438cb 100644
--- a/groundStation/gui/MicroCART/MicroCART.pro
+++ b/groundStation/gui/MicroCART/MicroCART.pro
@@ -4,7 +4,7 @@
 #
 #-------------------------------------------------
 
-QT       += core gui
+QT       += core gui gamepad
 
 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
 
@@ -23,7 +23,8 @@ SOURCES += main.cpp\
     qFlightInstruments.cpp\
     qcustomplot.cpp\
     crazyflieworker.cpp\
-    setpoint.cpp
+    setpoint.cpp\
+    gamepadmonitor.cpp
 
 HEADERS  += mainwindow.h \
     trackerworker.h \
@@ -34,7 +35,8 @@ HEADERS  += mainwindow.h \
     qFlightInstruments.h\
     qcustomplot.h\
     crazyflieworker.h\
-    setpoint.h
+    setpoint.h\
+    gamepadmonitor.h
 
 FORMS    += mainwindow.ui
 
diff --git a/groundStation/gui/MicroCART/crazyflieworker.cpp b/groundStation/gui/MicroCART/crazyflieworker.cpp
index d51f2ce766ac4ce7c70c452076b42ed7adee9dae..8894c2c63b265fc749ec2f122a7d885abef96f52 100644
--- a/groundStation/gui/MicroCART/crazyflieworker.cpp
+++ b/groundStation/gui/MicroCART/crazyflieworker.cpp
@@ -1,7 +1,9 @@
 #include "crazyflieworker.h"
 #include <iostream>
+#include <unistd.h>
+#include <sys/stat.h>
 
-CrazyflieWorker::CrazyflieWorker(QObject *parent) : QObject(parent)
+CrazyflieWorker::CrazyflieWorker(QObject *parent) : QObject(parent), conn(NULL)
 {
 }
 
@@ -22,8 +24,16 @@ void CrazyflieWorker::connectBackend()
         conn = ucart_backendConnect();
         emit (connected());
     } else {
-        qInfo() << "Attempted to connect trackerworker when already connected!";
+        qInfo() << "Attempted to connect crazyflieworker when already connected!";
     }
+    loadParamIds();
+    loadLogIds();
+    QStringList paramGroupList;
+    for(int i = 0; i < paramGroups.size(); i++) {
+        QString qgName(paramGroups.at(i).groupName.c_str());
+        paramGroupList.append(qgName);
+    }
+    emit(gotParamGroups(paramGroupList));
 }
 
 /**
@@ -49,12 +59,12 @@ void CrazyflieWorker::setCurrAttSetpoint(float roll, float pitch, float yaw, flo
     currAttitudeSetpoint.throttle = throttle;
 }
 
-void CrazyflieWorker::setCurrAttRateSetpoint(float rollRate, float pitchRate, float yawRate, float throttleRate)
+void CrazyflieWorker::setCurrAttRateSetpoint(float rollRate, float pitchRate, float yawRate, float throttle)
 {
     currAttitudeRateSetpoint.roll = rollRate;
     currAttitudeRateSetpoint.pitch = pitchRate;
     currAttitudeRateSetpoint.yaw = yawRate;
-    currAttitudeRateSetpoint.throttle = throttleRate;
+    currAttitudeRateSetpoint.throttle = throttle;
 }
 
 
@@ -62,7 +72,7 @@ void CrazyflieWorker::sendAttRateSetpoint()
 {
     struct frontend_override_data data;
     data.enable = 2;    //attitude rate
-    data.time = 0.2;    //hold setpoint for 0.2 seconds TODO
+    data.time = 0.2;    //hold setpoint for 0.2 seconds TODO check if this amount of time is good?
     data.throttle = currAttitudeRateSetpoint.throttle;
     data.roll = currAttitudeRateSetpoint.roll;
     data.pitch = currAttitudeRateSetpoint.pitch;
@@ -88,18 +98,175 @@ void CrazyflieWorker::sendAttSetpoint()
 }
 
 void CrazyflieWorker::getParamValue(QString paramName){
-    struct frontend_param_data data = paramNameLookup(paramName);
+    struct toc_info info = paramNameLookup(paramName);
+
+    struct frontend_param_data data;
+    data.block = 0;
+    data.param = info.id;
+    data.value = info.value;
 
     if(frontend_getparam(conn, &data) == 0){
         emit(gotParamValue(paramName, data.value));
     }
 }
 
-struct frontend_param_data CrazyflieWorker::paramNameLookup(QString paramName){
-    //TODO
-    //if param is in cache, use that else lookup from file
-    struct frontend_param_data paramData;
+void CrazyflieWorker::setParamValue(QString paramName, double value) {
+    struct toc_info info = paramNameLookup(paramName);
+
+    struct frontend_param_data data;
+    data.block = 0;
+    data.param = info.id;
+    data.value = (float) value;
+    
+    if(frontend_setparam(conn, &data) != 0){
+        //emit(gotParamValue(paramName, data.value));
+        qInfo() << "setParamError";
+    }
+}
+
+struct toc_info CrazyflieWorker::paramNameLookup(QString paramName){
+    struct toc_info paramData = paramIds.value(paramName);
     return paramData;
 }
 
+std::string CrazyflieWorker::getLogFile(int type) {
+    struct frontend_getlogfile_data logfile;
+    char fname[256];
+    logfile.command = type;
+    logfile.name = fname;
+    if(frontend_getlogfile(conn, &logfile)) {
+        return "";
+    }
+    std::string result(logfile.name, strlen(logfile.name));
+    return result;
+}
+
+void CrazyflieWorker::loadParamIds() {
+    std::string filename = getLogFile(1);
+    std::ifstream paramTOCFile;
+    paramTOCFile.open(filename.c_str());
+    std::string line;
+    //header and top line
+    std::getline(paramTOCFile, line);
+    std::getline(paramTOCFile, line);
+    //actual values;
+    while(std::getline(paramTOCFile, line)) {
+        struct toc_info values;
+        std::stringstream ss(line);
+        std::string temp_str;
+        for(int i = 0; i < 4; i++) {
+            std::getline(ss, temp_str, '\t');
+            if(i == 0) {
+                values.id = (int16_t) stoi(temp_str);
+            }
+            else if(i == 1) {
+                values.dataType = (int8_t) stoi(temp_str);
+            }
+            else if(i == 2) {
+                values.strGroup = temp_str;
+            }
+            else if(i == 3) {
+                values.strName = temp_str;
+            }
+        }
+        values.value = 0;
+
+        int gFound = findParamGroup(values.strGroup);
+        if(gFound == -1) {
+            struct toc_group groupx;
+            groupx.groupName = values.strGroup;
+            groupx.entryNames.push_back(values.strName);
+            paramGroups.push_back(groupx);
+        }
+        else {
+            paramGroups.at(gFound).entryNames.push_back(values.strName);
+        }
+
+        std::string identifier = values.strGroup + "." + values.strName;
+        QString Qidentifier(identifier.c_str());
+        paramIds.insert(Qidentifier, values);
+    }
+    paramTOCFile.close();
+}
 
+void CrazyflieWorker::loadLogIds() {
+    std::string filename = getLogFile(2);
+    std::ifstream logTOCFile;
+    logTOCFile.open(filename.c_str());
+    std::string line;
+    //top line
+    std::getline(logTOCFile, line);
+    std::getline(logTOCFile, line);
+    //actual values;
+    while(std::getline(logTOCFile, line)) {
+        struct toc_info values;
+        std::stringstream ss(line);
+        std::string temp_str;
+        for(int i = 0; i < 4; i++) {
+            std::getline(ss, temp_str, '\t');
+            if(i == 0) {
+                values.id = (int16_t) stoi(temp_str);
+            }
+            else if(i == 1) {
+                values.dataType = (int8_t) stoi(temp_str);
+            }
+            else if(i == 2) {
+                values.strGroup = temp_str;
+            }
+            else if(i == 3) {
+                values.strName = temp_str;
+            }
+        }
+        values.value = 0;
+
+        int gFound = findLogGroup(values.strGroup);
+        if(gFound == -1) {
+            struct toc_group groupx;
+            groupx.groupName = values.strGroup;
+            groupx.entryNames.push_back(values.strName);
+            logGroups.push_back(groupx);
+        }
+        else {
+            logGroups.at(gFound).entryNames.push_back(values.strName);;
+        }
+
+        std::string identifier = values.strGroup + "." + values.strName;
+        QString Qidentifier(identifier.c_str());
+        logIds.insert(Qidentifier, values);
+    }
+    logTOCFile.close();
+}
+
+int CrazyflieWorker::findParamGroup(std::string gName) {
+    int result = -1;
+    for(int i = 0; i < paramGroups.size(); i++) {
+        if(!paramGroups.at(i).groupName.compare(gName)) {
+            result = i;
+            break;
+        }
+    }
+    return result;
+}
+
+int CrazyflieWorker::findLogGroup(std::string gName) {
+    int result = -1;
+    for(int i = 0; i < logGroups.size(); i++) {
+        if(!logGroups.at(i).groupName.compare(gName)) {
+            result = i;
+            break;
+        }
+    }
+    return result;
+}
+
+void CrazyflieWorker::getGroupEntries(int box, QString gName) {
+    std::string name = gName.toStdString();
+    int index = findParamGroup(name);
+    std::vector<std::string> entries = paramGroups.at(index).entryNames;
+    QStringList entryList;
+    for(int i = 0; i < entries.size(); i++) {
+        QString cur(entries.at(i).c_str());
+        entryList.append(cur);
+    }
+    emit(gotGroupEntries(box, entryList));
+}
diff --git a/groundStation/gui/MicroCART/crazyflieworker.h b/groundStation/gui/MicroCART/crazyflieworker.h
index f22f24135ce5ae1dc1f93939c83ba8adde3412a2..104d37b86b3659fecdf0bcd248a438ade64060a8 100644
--- a/groundStation/gui/MicroCART/crazyflieworker.h
+++ b/groundStation/gui/MicroCART/crazyflieworker.h
@@ -2,12 +2,29 @@
 #define CRAZYFLIEWORKER_H
 
 #include <QObject>
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <QStringList>
 #include "frontend_common.h"
 #include "frontend_param.h"
 #include "frontend_override.h"
+#include "frontend_logfile.h"
 #include "setpoint.h"
 #include <QDebug>
 
+struct toc_info {
+    int16_t id;
+    int8_t dataType;
+    std::string strGroup;
+    std::string strName;
+    float value;
+};
+
+struct toc_group {
+    std::string groupName;
+    std::vector<std::string> entryNames;
+};
 
 /**
  * @brief The crazyflieworker class
@@ -24,6 +41,8 @@ public:
 
 signals:
     void gotParamValue(QString paramName, float value);
+    void gotParamGroups(QStringList paramGroupList);
+    void gotGroupEntries(int box, QStringList groupEntries);
     void connected();
     void disconnected();
 
@@ -36,6 +55,8 @@ public slots:
     void getParamValue(QString paramName);
     void setCurrAttSetpoint(float roll, float pitch, float yaw, float throttle);
     void setCurrAttRateSetpoint(float rollRate, float pitchRate, float yawRate, float throttleRate);
+    void setParamValue(QString paramName, double value);
+    void getGroupEntries(int box, QString gName);
 
 private:
     struct backend_conn * conn;
@@ -43,9 +64,16 @@ private:
     Setpoint currAttitudeRateSetpoint;
     void sendAttitudeSetpoint();
     void sendAttitudeRateSetpoint();
-    struct frontend_param_data paramNameLookup(QString paramName);
-
-
+    std::string getLogFile(int type);
+    void loadParamIds();
+    void loadLogIds();
+    int findParamGroup(std::string gName);
+    int findLogGroup(std::string gName);
+    struct toc_info paramNameLookup(QString paramName);
+    QMap<QString, struct toc_info> paramIds;
+    QMap<QString, struct toc_info> logIds;
+    std::vector<struct toc_group> paramGroups;
+    std::vector<struct toc_group> logGroups;
 };
 
 #endif // CRAZYFLIEWORKER_H
diff --git a/groundStation/gui/MicroCART/gamepadmonitor.cpp b/groundStation/gui/MicroCART/gamepadmonitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..09f936fc56062f8b9f92e4c24f58974d87256312
--- /dev/null
+++ b/groundStation/gui/MicroCART/gamepadmonitor.cpp
@@ -0,0 +1,81 @@
+#include "gamepadmonitor.h"
+#include <QDebug>
+
+GamepadMonitor::GamepadMonitor(QObject *parent) : QObject(parent)
+{
+    m_gamepadManager = QGamepadManager::instance();
+
+    rollScale = 20;  //-20 to 20 deg/s
+    pitchScale = 20;
+    yawScale = 30;
+    thrustScale = 30000; //0 to 60,000 thrust
+
+    connect(m_gamepadManager, SIGNAL(gamepadConnected(int)), this, SLOT(gamepadConnectedHandler(int)));
+    connect(m_gamepadManager, SIGNAL(gamepadDisconnected(int)), this, SLOT(gamepadDisconnectedHandler(int)));
+
+    auto gamepads = m_gamepadManager->connectedGamepads();
+    if (gamepads.isEmpty()) {
+        // Did not find any connected gamepads creating default gamepad;
+        m_gamepad = new QGamepad();
+        return;
+    }
+
+    m_gamepad = new QGamepad(*gamepads.begin(), this);
+    qInfo() << "gamepad is connected, deviceId = " << m_gamepad->deviceId();
+}
+
+void GamepadMonitor::gamepadConnectedHandler(int deviceId){
+    emit(gamepadConnected());
+    qInfo() << "gamepad is connected, deviceId = " << deviceId;
+    m_gamepad = new QGamepad(deviceId, this);
+}
+
+void GamepadMonitor::gamepadDisconnectedHandler(int deviceId){
+    emit(gamepadDisconnected());
+    qInfo() << "gamepad disconnected";
+}
+
+bool GamepadMonitor::isGamepadConnected(){
+    return m_gamepad->isConnected();
+}
+
+void GamepadMonitor::resetConfig(){
+    qInfo() << "gamepad config reset";
+    m_gamepadManager->resetConfiguration(m_gamepad->deviceId());
+}
+
+void GamepadMonitor::configureAxis(QString axisName){
+    if(axisName == "roll"){
+        m_gamepadManager->configureAxis(m_gamepad->deviceId(), QGamepadManager::AxisRightX);
+        qInfo() << "roll configured";
+    }else if(axisName == "yaw"){
+        m_gamepadManager->configureAxis(m_gamepad->deviceId(), QGamepadManager::AxisLeftX);
+        qInfo() << "yaw configured";
+    }else if(axisName == "pitch"){
+        m_gamepadManager->configureAxis(m_gamepad->deviceId(), QGamepadManager::AxisRightY);
+        qInfo() << "pitch configured";
+    }else if(axisName == "thrust"){
+        m_gamepadManager->configureAxis(m_gamepad->deviceId(), QGamepadManager::AxisLeftY);
+        qInfo() << "thrust configured";
+    }
+}
+
+float GamepadMonitor::getRoll(){
+    return (float) m_gamepad->axisRightX() * rollScale;
+}
+
+float GamepadMonitor::getYaw(){
+    return (float) m_gamepad->axisLeftX() * yawScale;
+}
+
+float GamepadMonitor::getPitch(){
+    return (float) m_gamepad->axisRightY() * pitchScale;
+}
+
+float GamepadMonitor::getThrust(){
+    return (float) (m_gamepad->axisLeftY() + 1) * thrustScale;
+}
+
+GamepadMonitor::~GamepadMonitor(){
+
+}
diff --git a/groundStation/gui/MicroCART/gamepadmonitor.h b/groundStation/gui/MicroCART/gamepadmonitor.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b3ef05cd76daef5ce874c70d814876876aaa3fc
--- /dev/null
+++ b/groundStation/gui/MicroCART/gamepadmonitor.h
@@ -0,0 +1,42 @@
+#ifndef GAMEPADMONITOR_H
+#define GAMEPADMONITOR_H
+
+#include <QObject>
+#include <QtGamepad/QGamepad>
+
+
+class GamepadMonitor : public QObject
+{
+    Q_OBJECT
+public:
+    explicit GamepadMonitor(QObject *parent = nullptr);
+    ~GamepadMonitor();
+
+    bool isGamepadConnected();
+
+    float getRoll();
+    float getYaw();
+    float getPitch();
+    float getThrust();
+    void configureAxis(QString axisName);
+    void resetConfig();
+
+
+private:
+    QGamepad *m_gamepad;
+    QGamepadManager *m_gamepadManager;
+
+    float rollScale;
+    float pitchScale;
+    float yawScale;
+    float thrustScale;
+
+signals:
+    void gamepadConnected();
+    void gamepadDisconnected();
+public slots:
+    void gamepadConnectedHandler(int deviceId);
+    void gamepadDisconnectedHandler(int deviceId);
+};
+
+#endif // GAMEPADMONITOR_H
diff --git a/groundStation/gui/MicroCART/mainwindow.cpp b/groundStation/gui/MicroCART/mainwindow.cpp
index 26cf536a50696027659177431a0b8d478a214089..26cd4162ec2ee856c5a9d92e39b0c4cd4db7268c 100644
--- a/groundStation/gui/MicroCART/mainwindow.cpp
+++ b/groundStation/gui/MicroCART/mainwindow.cpp
@@ -10,6 +10,7 @@
 #include <QProcessEnvironment>
 #include <QPixmap>
 #include <QProcess>
+#include <QDebug>
 
 #include "trackerworker.h"
 #include "controlworker.h"
@@ -34,8 +35,10 @@ MainWindow::MainWindow(QWidget *parent) :
     crazyflieTimer(new QTimer(this)),
     backendProcess(new QProcess(this)),
     matlabProcess(new QProcess(this)),
+    pollGamepadTimer(new QTimer(this)),
     connectedWorkers(0)
 {
+
     ui->setupUi(this);
 
     QGraphicsScene *posScene = new QGraphicsScene(this);
@@ -78,21 +81,6 @@ MainWindow::MainWindow(QWidget *parent) :
     ControlWorker * controlWorker = new ControlWorker();
     controlWorker->moveToThread(cwThread);
 
-    /*Create worker for the crazyflie and moves it to new thread*/
-    QThread * crazyflieThread = new QThread(this);
-    CrazyflieWorker * crazyflieWorker = new CrazyflieWorker();
-    controlWorker->moveToThread(crazyflieThread);
-
-    /*sgnals from crazyflie worker*/
-    
-    /*signals to crazyflie worker*/
-    connect(this, SIGNAL (rateSetpointSignal(float, float, float, float)), crazyflieWorker, SLOT (setCurrAttSetpoint(float, float, float, float)));
-    connect(this, SIGNAL (angleSetpointSignal(float, float, float, float)), crazyflieWorker, SLOT (setCurrAttRateSetpoint(float, float, float, float)));
-    //dont knwo if i need next line
-    crazyflieTimer->setSingleShot(true);
-    connect(crazyflieTimer, SIGNAL(timeout()), this, SLOT (on_stopSetpointButton_clicked()));
-
-
     /* Connect signals from control worker */
     connect(controlWorker, SIGNAL (gotNodes(QStringList)), this, SLOT (newNodes(QStringList)));
     connect(controlWorker, SIGNAL (gotParams(QStringList)), this, SLOT (newParams(QStringList)));
@@ -109,6 +97,29 @@ MainWindow::MainWindow(QWidget *parent) :
     connect(this, SIGNAL (setParamValue(QString, QString, float)), controlWorker, SLOT (setParamValue(QString, QString, float)));
     connect(this, SIGNAL (getNodeOutput(QString)), controlWorker, SLOT (getNodeOutput(QString)));
 
+    /* Create another work for the crazyflie communication */
+    QThread * cfThread = new QThread(this);
+    crazyflieWorker = new CrazyflieWorker();
+    crazyflieWorker->moveToThread(cfThread);
+
+    /* connect signals for crazyflie worker */
+    connect(this, SIGNAL (rateSetpointSignal(float, float, float, float)), crazyflieWorker, SLOT (setCurrAttSetpoint(float, float, float, float)));
+    connect(this, SIGNAL (angleSetpointSignal(float, float, float, float)), crazyflieWorker, SLOT (setCurrAttRateSetpoint(float, float, float, float)));
+    crazyflieTimer->setSingleShot(true);
+    connect(crazyflieTimer, SIGNAL(timeout()), this, SLOT (on_stopSetpointButton_clicked()));
+    connect(crazyflieWorker, SIGNAL (gotParamGroups(QStringList)), this, SLOT (setParamGroups(QStringList)));
+    connect(ui->paramGroupComboBox, SIGNAL (currentIndexChanged(int)), this, SLOT (getGroupBoxChange(int)));
+    connect(ui->paramGroupComboBox_2, SIGNAL (currentIndexChanged(int)), this, SLOT (getGroupBox2Change(int)));
+    connect(ui->paramEntriesComboBox, SIGNAL (currentIndexChanged(int)), this, SLOT (getEntryBoxChange(int)));
+    connect(ui->paramEntriesComboBox_2, SIGNAL (currentIndexChanged(int)), this, SLOT (getEntryBoxChange2(int)));
+    connect(ui->pb_getParam, SIGNAL (clicked()), this, SLOT (on_pb_getParam_click()));
+    connect(ui->pb_setParam, SIGNAL (clicked()), this, SLOT (on_pb_setParam_click()));
+    connect(crazyflieWorker, SIGNAL (gotGroupEntries(int, QStringList)), this, SLOT (newGroupEntries(int, QStringList)));
+    connect(this, SIGNAL (getGroupEntries(int, QString)), crazyflieWorker, SLOT (getGroupEntries(int, QString)));
+    connect(this, SIGNAL (getParamValue(QString)), crazyflieWorker, SLOT (getParamValue(QString)));
+    connect(this, SIGNAL (setParamValue(QString, double)), crazyflieWorker, SLOT (setParamValue(QString, double)));
+    connect(crazyflieWorker, SIGNAL (gotParamValue(QString, float)), this, SLOT (displayParamValue(QString, float)));
+
     /* Connect and disconnect from backend when signals emitted */
     connect(workerStartTimer, SIGNAL (timeout()), trackerWorker, SLOT (connectBackend()));
     connect(workerStartTimer, SIGNAL (timeout()), controlWorker, SLOT (connectBackend()));
@@ -149,16 +160,38 @@ MainWindow::MainWindow(QWidget *parent) :
     trackerTimer->start(100);
     workerThread->start();
     cwThread->start();
-    crazyflieThread->start();
+    cfThread->start();
     matlabProcess->start();
 
     /* Connect the setpointlist to the model */
     // ui->setpointList->setModel(setpointList);
 
+    ui->pb_getParam->setEnabled(false);
+    ui->pb_setParam->setEnabled(false);
+    ui->setValueSpin->setMaximum(10000.00);
+    ui->setValueSpin->setMinimum(-10000.00);
+    ui->setValueSpin->setSingleStep(0.01);
+    ui->setValueSpin->setValue(0);
+
     /* Connect various things that can result in sending setpoints */
     // connect(ui->pbSendSetpoint, SIGNAL (clicked()), this, SLOT (sendSetpoints()));
     // connect(ui->setpointList, SIGNAL (doubleClicked(QModelIndex)), this, SLOT (sendSelectedSetpoint()));
 
+    /* start gamepad monitor */
+    gamepadMonitor = new GamepadMonitor();
+    if(gamepadMonitor->isGamepadConnected()){
+        onGamepadConnect();
+    }else{
+        onGamepadDisconnect();
+    }
+
+    connect(gamepadMonitor, SIGNAL(gamepadDisconnected()), this, SLOT(onGamepadDisconnect()));
+    connect(gamepadMonitor, SIGNAL(gamepadConnected()), this, SLOT(onGamepadConnect()));
+    connect(ui->pb_configRoll, SIGNAL(clicked()), this, SLOT(on_pb_configRoll_clicked()));
+    connect(pollGamepadTimer, SIGNAL(timeout()), this, SLOT(updateGamepad()));
+    pollGamepadTimer->start(50);
+
+
     /* Populate scripts list */
     QDir scriptsDir("scripts/");
     QStringList scripts = scriptsDir.entryList();
@@ -168,7 +201,6 @@ MainWindow::MainWindow(QWidget *parent) :
         scriptProcess->setProgram(scriptsDir.filePath(scripts[i]));
         connect(action, SIGNAL (triggered()), scriptProcess, SLOT (startProcess()));
     }
-
 }
 
 MainWindow::~MainWindow()
@@ -299,6 +331,98 @@ void MainWindow::newNodes(QStringList blocks)
     // this->ui->noGraphWarningLine->setVisible(false);
 }
 
+void MainWindow::setParamGroups(QStringList groupNames) {
+    ui->paramGroupComboBox->addItem("");
+    ui->paramGroupComboBox->addItems(groupNames);
+    ui->paramGroupComboBox_2->addItem("");
+    ui->paramGroupComboBox_2->addItems(groupNames);
+}
+
+void MainWindow::getGroupBoxChange(int index) {
+    // for(int i = 0; i < ui->paramGroupComboBox->count(); i++) {
+    //     ui->paramEntriesComboBox->removeItem(i);
+    // }
+    ui->paramEntriesComboBox->clear();
+    QString qStrGroup = ui->paramGroupComboBox->itemText(index);
+    std::string check = qStrGroup.toStdString();
+    ui->valueVallabel->clear();
+    if(!check.compare("")) {
+        ui->pb_getParam->setEnabled(false);
+    }
+    else {
+        emit(getGroupEntries(1, qStrGroup));
+    }
+}
+
+void MainWindow::getGroupBox2Change(int index) {
+    // for(int i = 0; i < ui->paramGroupComboBox->count(); i++) {
+    //     ui->paramEntriesComboBox->removeItem(i);
+    // }
+    ui->paramEntriesComboBox_2->clear();
+    QString qStrGroup = ui->paramGroupComboBox_2->itemText(index);
+    std::string check = qStrGroup.toStdString();
+    if(!check.compare("")) {
+        ui->pb_setParam->setEnabled(false);
+    }
+    else {
+        emit(getGroupEntries(2, qStrGroup));
+    }
+}
+
+void MainWindow::getEntryBoxChange(int index) {
+    QString qStrGroup = ui->paramEntriesComboBox->itemText(index);
+    std::string check = qStrGroup.toStdString();
+    ui->valueVallabel->clear();
+    if(!check.compare("")) {
+        ui->pb_getParam->setEnabled(false);
+    }
+    else {
+        ui->pb_getParam->setEnabled(true);
+    }
+}
+
+void MainWindow::getEntryBoxChange2(int index) {
+    QString qStrGroup = ui->paramEntriesComboBox_2->itemText(index);
+    std::string check = qStrGroup.toStdString();
+    if(!check.compare("")) {
+        ui->pb_setParam->setEnabled(false);
+    }
+    else {
+        ui->pb_setParam->setEnabled(true);
+    }
+}
+
+void MainWindow::newGroupEntries(int box, QStringList entries) {
+    if(box == 1) {
+        ui->paramEntriesComboBox->addItem("");
+        ui->paramEntriesComboBox->addItems(entries);
+    }
+    else {
+        ui->paramEntriesComboBox_2->addItem("");
+        ui->paramEntriesComboBox_2->addItems(entries);
+    }    
+}
+
+void MainWindow::on_pb_getParam_click() {
+    ui->valueVallabel->clear();
+    QString group = ui->paramGroupComboBox->currentText();
+    QString entry = ui->paramEntriesComboBox->currentText();
+    QString key = group + "." + entry;
+    emit(getParamValue(key));
+}
+
+void MainWindow::on_pb_setParam_click() {
+    QString group = ui->paramGroupComboBox_2->currentText();
+    QString entry = ui->paramEntriesComboBox_2->currentText();
+    QString key = group + "." + entry;
+    double value = ui->setValueSpin->value();
+    emit(setParamValue(key, value));
+}
+
+void MainWindow::displayParamValue(QString key, float value) {
+    ui->valueVallabel->setNum(value);
+}
+
 void MainWindow::newConstantBlocks(QStringList blocks)
 {
     // ui->xSetpointSelect->clear();
@@ -629,20 +753,15 @@ void MainWindow::on_applySetpointButton_clicked()
     sp_roll   = ui->rollSetpointBox->text().toFloat();
     sp_pitch  = ui->pitchSetpointBox->text().toFloat();
     sp_yaw    = ui->yawSetpointBox->text().toFloat();
-    sp_thrust = ui->thrustSetpointBox->text().toFloat();
+    sp_thrust = ui->tActual -> value();
 
     crazyflieTimer -> start(10000);
 
-    //testing print statements
-    std::cout << "roll: " << sp_roll << std::endl;
-    std::cout << "pitch: " << sp_pitch << std::endl;
-    std::cout << "yaw: " << sp_yaw << std::endl;
-
-    if(ui->angleRadioButton->isCheckable()) {
+    if(ui->angleRadioButton->isChecked()) {
         //send as angle setpoint
         emit(angleSetpointSignal(sp_roll, sp_pitch, sp_yaw, sp_thrust));
     }
-    else if (ui->rateRadioButton->isCheckable()) {
+    else if (ui->rateRadioButton->isChecked()) {
         //send as rate setpoint
         emit(rateSetpointSignal(sp_roll, sp_pitch, sp_yaw, sp_thrust));
     }
@@ -656,17 +775,126 @@ void MainWindow::on_stopSetpointButton_clicked()
     sp_pitch  = 0.0;
     sp_yaw    = 0.0;
     sp_thrust = 0.0;
-    //debug prints
-    std::cout << "roll: " << sp_roll << std::endl;
-    std::cout << "pitch: " << sp_pitch << std::endl;
-    std::cout << "yaw: " << sp_yaw << std::endl;
 
-    if(ui->angleRadioButton->isCheckable()) {
+    if(ui->angleRadioButton->isChecked()) {
         //send as angle setpoint
         emit(angleSetpointSignal(sp_roll, sp_pitch, sp_yaw, sp_thrust));
     }
-    else if (ui->rateRadioButton->isCheckable()) {
+    else if (ui->rateRadioButton->isChecked()) {
         //send as rate setpoint
         emit(rateSetpointSignal(sp_roll, sp_pitch, sp_yaw, sp_thrust));
     }
 }
+void MainWindow::on_tActual_sliderMoved(int position)
+{
+    QToolTip::showText(QCursor::pos(), QString::number(position), nullptr);
+
+}
+
+
+/******** Gamepad handlers ********/
+
+void MainWindow::onGamepadDisconnect(){
+    crazyflieWorker->setCurrAttRateSetpoint(0,0,0,0);
+    ui->pitchSetpointBox->setText("0");
+    ui->rollSetpointBox->setText("0");
+    ui->yawSetpointBox->setText("0");
+    ui->tActual->setValue(0);
+
+    ui->noGamepadWarning->show();
+    ui->rbGamepadControl->setEnabled(false);
+    ui->pb_configPitch->setEnabled(false);
+    ui->pb_configRoll->setEnabled(false);
+    ui->pb_configYaw->setEnabled(false);
+    ui->pb_configThrust->setEnabled(false);
+    ui->pb_resetConfig->setEnabled(false);
+    ui->rbManualSetpoint->setChecked(true);
+}
+
+void MainWindow::onGamepadConnect(){
+    ui->noGamepadWarning->hide();
+    ui->rbGamepadControl->setEnabled(true);
+    ui->pb_configPitch->setEnabled(true);
+    ui->pb_configRoll->setEnabled(true);
+    ui->pb_configYaw->setEnabled(true);
+    ui->pb_configThrust->setEnabled(true);
+    ui->pb_resetConfig->setEnabled(true);
+}
+
+void MainWindow::updateGamepad(){
+    if(ui->tabWidget->currentWidget() == ui->Gamepad){
+        //on gamepad tab
+        ui->rollVizBar->setValue((int) gamepadMonitor->getRoll());
+        ui->yawVizBar->setValue((int) gamepadMonitor->getYaw());
+        ui->pitchVizBar->setValue((int) gamepadMonitor->getPitch());
+        ui->thrustVizBar->setValue((int) gamepadMonitor->getThrust());
+    }else if(ui->tabWidget->currentWidget() == ui->navigation){
+        if(ui->rbGamepadControl->isChecked()){
+            float roll = gamepadMonitor->getRoll();
+            float pitch = gamepadMonitor->getPitch();
+            float yaw = gamepadMonitor->getYaw();
+            float thrust = gamepadMonitor->getThrust();
+
+            crazyflieWorker->setCurrAttRateSetpoint(roll, pitch, yaw, thrust);
+            ui->rollSetpointBox->setText(QString::number(roll));
+            ui->pitchSetpointBox->setText(QString::number(pitch));
+            ui->yawSetpointBox->setText(QString::number(yaw));
+            ui->tActual->setValue((int) thrust);
+        }
+    }
+}
+
+void MainWindow::on_pb_resetConfig_clicked()
+{
+    gamepadMonitor->resetConfig();
+}
+
+void MainWindow::on_pb_configRoll_clicked()
+{
+    gamepadMonitor->configureAxis("roll");
+}
+
+void MainWindow::on_pb_configYaw_clicked()
+{
+    gamepadMonitor->configureAxis("yaw");
+}
+
+void MainWindow::on_pb_configPitch_clicked()
+{
+    gamepadMonitor->configureAxis("pitch");
+}
+
+void MainWindow::on_pb_configThrust_clicked()
+{
+    gamepadMonitor->configureAxis("thrust");
+}
+
+
+
+void MainWindow::on_rbManualSetpoint_toggled(bool checked)
+{
+    if(checked) {
+        crazyflieWorker->setCurrAttRateSetpoint(0,0,0,0);
+        ui->pitchSetpointBox->setText("0");
+        ui->rollSetpointBox->setText("0");
+        ui->yawSetpointBox->setText("0");
+        ui->tActual->setValue(0);
+        ui->rollSetpointBox-> setEnabled(true);
+        ui->pitchSetpointBox-> setEnabled(true);
+        ui->yawSetpointBox-> setEnabled(true);
+        ui->tActual-> setEnabled(true);
+        ui->angleRadioButton-> setEnabled(true);
+        ui->rateRadioButton-> setEnabled(true);
+    }
+}
+
+void MainWindow::on_rbGamepadControl_toggled(bool checked)
+{
+    ui->rollSetpointBox-> setEnabled(false);
+    ui->pitchSetpointBox-> setEnabled(false);
+    ui->yawSetpointBox-> setEnabled(false);
+    ui->tActual-> setEnabled(false);
+    ui->angleRadioButton-> setEnabled(false);
+    ui->rateRadioButton-> setEnabled(false);
+    ui->rateRadioButton-> setChecked(true);
+}
diff --git a/groundStation/gui/MicroCART/mainwindow.h b/groundStation/gui/MicroCART/mainwindow.h
index 194eaa03295e0ef8eac41d6165a7072f494a3379..725a74d3cc53e878ee86cbf8ef8bd963dcbb620e 100644
--- a/groundStation/gui/MicroCART/mainwindow.h
+++ b/groundStation/gui/MicroCART/mainwindow.h
@@ -6,6 +6,9 @@
 #include <QStandardItemModel>
 #include <QGraphicsScene>
 #include "quaditem.h"
+#include "gamepadmonitor.h"
+#include "crazyflieworker.h"
+
 
 namespace Ui {
 class MainWindow;
@@ -23,11 +26,14 @@ signals:
     void connectWorkers();
     void disconnectWorkers();
     void getParamValue(QString node, QString param);
+    void getParamValue(QString key);
     void getNodeOutput(QString node);
     void setParamValue(QString node, QString param, float value);
+    void setParamValue(QString key, double value);
     void getPosAttFromBackend();
     void rateSetpointSignal(float roll, float pitch, float yaw, float throttle);
     void angleSetpointSignal(float roll, float pitch, float yaw, float throttle);
+    void getGroupEntries(int box, QString gName);
 
 private slots:
     void on_pbStart_clicked();
@@ -47,6 +53,11 @@ private slots:
     void newParamValue(QString node, QString param, float val);
     void newNodeOutput(QString node, float output);
     void newConstantBlocks(QStringList blocks);
+    void newGroupEntries(int box, QStringList entries);
+
+    void on_pb_getParam_click();
+
+    void on_pb_setParam_click();
 
     void on_paramSelect_currentIndexChanged(const QString &arg1);
 
@@ -96,6 +107,31 @@ private slots:
     void on_applySetpointButton_clicked();
 
     void on_stopSetpointButton_clicked();
+    void setParamGroups(QStringList groupNames);
+    void getGroupBoxChange(int index);
+    void getGroupBox2Change(int index);
+    void displayParamValue(QString param, float value);
+    void getEntryBoxChange(int index);
+    void getEntryBoxChange2(int index);
+
+    void onGamepadDisconnect();
+    void onGamepadConnect();
+    void on_pb_configRoll_clicked();
+    void updateGamepad();
+
+    void on_pb_resetConfig_clicked();
+
+    void on_pb_configYaw_clicked();
+
+    void on_pb_configThrust_clicked();
+
+    void on_pb_configPitch_clicked();
+
+    void on_tActual_sliderMoved(int position);
+
+    void on_rbGamepadControl_toggled(bool checked);
+
+    void on_rbManualSetpoint_toggled(bool checked);
 
 private:
     Ui::MainWindow *ui;
@@ -108,9 +144,12 @@ private:
     QTimer * trackerTimer;
     QTimer * workerStartTimer;
     QTimer * crazyflieTimer;
+    QTimer *pollGamepadTimer;
     QProcess * backendProcess;
     QProcess * matlabProcess;
     int connectedWorkers;
+    GamepadMonitor *gamepadMonitor;
+    CrazyflieWorker *crazyflieWorker;
 };
 
 #endif // MAINWINDOW_H
diff --git a/groundStation/gui/MicroCART/mainwindow.ui b/groundStation/gui/MicroCART/mainwindow.ui
index b76c0b0ed3182238043c080937c72a3a8b44e6f8..34a29f907a8b4e15df6e2f97b7a952d8c9f41269 100644
--- a/groundStation/gui/MicroCART/mainwindow.ui
+++ b/groundStation/gui/MicroCART/mainwindow.ui
@@ -134,11 +134,422 @@
        <attribute name="title">
         <string>Param</string>
        </attribute>
+       <widget class="QComboBox" name="paramGroupComboBox">
+        <property name="geometry">
+         <rect>
+          <x>420</x>
+          <y>100</y>
+          <width>201</width>
+          <height>25</height>
+         </rect>
+        </property>
+       </widget>
+       <widget class="QComboBox" name="paramEntriesComboBox">
+        <property name="geometry">
+         <rect>
+          <x>420</x>
+          <y>150</y>
+          <width>201</width>
+          <height>25</height>
+         </rect>
+        </property>
+       </widget>
+       <widget class="QLabel" name="groupLabel">
+        <property name="geometry">
+         <rect>
+          <x>350</x>
+          <y>100</y>
+          <width>54</width>
+          <height>31</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Group:</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="getParamLabel">
+        <property name="geometry">
+         <rect>
+          <x>480</x>
+          <y>40</y>
+          <width>71</width>
+          <height>17</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Get Param</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="label">
+        <property name="geometry">
+         <rect>
+          <x>350</x>
+          <y>150</y>
+          <width>54</width>
+          <height>17</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Entry:</string>
+        </property>
+       </widget>
+       <widget class="Line" name="line">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>279</y>
+          <width>1111</width>
+          <height>31</height>
+         </rect>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+       </widget>
+       <widget class="QLabel" name="setParamLabel">
+        <property name="geometry">
+         <rect>
+          <x>480</x>
+          <y>310</y>
+          <width>71</width>
+          <height>17</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Set Param</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="valueLabel">
+        <property name="geometry">
+         <rect>
+          <x>350</x>
+          <y>240</y>
+          <width>54</width>
+          <height>17</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Value:</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="valueVallabel">
+        <property name="geometry">
+         <rect>
+          <x>420</x>
+          <y>240</y>
+          <width>201</width>
+          <height>20</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+       </widget>
+       <widget class="QLabel" name="groupLabel_set">
+        <property name="geometry">
+         <rect>
+          <x>350</x>
+          <y>360</y>
+          <width>54</width>
+          <height>31</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Group:</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="label_5">
+        <property name="geometry">
+         <rect>
+          <x>350</x>
+          <y>400</y>
+          <width>54</width>
+          <height>17</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Entry:</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="valueLabel_2">
+        <property name="geometry">
+         <rect>
+          <x>350</x>
+          <y>450</y>
+          <width>54</width>
+          <height>17</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Value:</string>
+        </property>
+       </widget>
+       <widget class="QComboBox" name="paramGroupComboBox_2">
+        <property name="geometry">
+         <rect>
+          <x>420</x>
+          <y>360</y>
+          <width>201</width>
+          <height>25</height>
+         </rect>
+        </property>
+       </widget>
+       <widget class="QComboBox" name="paramEntriesComboBox_2">
+        <property name="geometry">
+         <rect>
+          <x>420</x>
+          <y>400</y>
+          <width>201</width>
+          <height>25</height>
+         </rect>
+        </property>
+       </widget>
+       <widget class="QPushButton" name="pb_getParam">
+        <property name="geometry">
+         <rect>
+          <x>480</x>
+          <y>200</y>
+          <width>80</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Get Param</string>
+        </property>
+       </widget>
+       <widget class="QPushButton" name="pb_setParam">
+        <property name="geometry">
+         <rect>
+          <x>480</x>
+          <y>500</y>
+          <width>80</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Set Param</string>
+        </property>
+       </widget>
+       <widget class="QDoubleSpinBox" name="setValueSpin">
+        <property name="geometry">
+         <rect>
+          <x>470</x>
+          <y>450</y>
+          <width>111</width>
+          <height>26</height>
+         </rect>
+        </property>
+       </widget>
       </widget>
-      <widget class="QWidget" name="controller">
+      <widget class="QWidget" name="Gamepad">
        <attribute name="title">
-        <string>Controller</string>
+        <string>Gamepad</string>
        </attribute>
+       <widget class="QPushButton" name="pb_configRoll">
+        <property name="geometry">
+         <rect>
+          <x>720</x>
+          <y>130</y>
+          <width>141</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Configure Roll</string>
+        </property>
+       </widget>
+       <widget class="QSlider" name="rollVizBar">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="geometry">
+         <rect>
+          <x>710</x>
+          <y>160</y>
+          <width>160</width>
+          <height>16</height>
+         </rect>
+        </property>
+        <property name="minimum">
+         <number>-20</number>
+        </property>
+        <property name="maximum">
+         <number>20</number>
+        </property>
+        <property name="value">
+         <number>0</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+       </widget>
+       <widget class="QPushButton" name="pb_resetConfig">
+        <property name="geometry">
+         <rect>
+          <x>440</x>
+          <y>90</y>
+          <width>191</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Reset Configuration</string>
+        </property>
+       </widget>
+       <widget class="QPushButton" name="pb_configYaw">
+        <property name="geometry">
+         <rect>
+          <x>160</x>
+          <y>140</y>
+          <width>141</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Configure Yaw</string>
+        </property>
+       </widget>
+       <widget class="QSlider" name="yawVizBar">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="geometry">
+         <rect>
+          <x>150</x>
+          <y>170</y>
+          <width>160</width>
+          <height>16</height>
+         </rect>
+        </property>
+        <property name="minimum">
+         <number>-30</number>
+        </property>
+        <property name="maximum">
+         <number>30</number>
+        </property>
+        <property name="value">
+         <number>0</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+       </widget>
+       <widget class="QSlider" name="thrustVizBar">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="geometry">
+         <rect>
+          <x>220</x>
+          <y>190</y>
+          <width>16</width>
+          <height>160</height>
+         </rect>
+        </property>
+        <property name="maximum">
+         <number>60000</number>
+        </property>
+        <property name="value">
+         <number>50</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+       </widget>
+       <widget class="QSlider" name="pitchVizBar">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="geometry">
+         <rect>
+          <x>780</x>
+          <y>180</y>
+          <width>16</width>
+          <height>160</height>
+         </rect>
+        </property>
+        <property name="minimum">
+         <number>-20</number>
+        </property>
+        <property name="maximum">
+         <number>20</number>
+        </property>
+        <property name="value">
+         <number>0</number>
+        </property>
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+       </widget>
+       <widget class="QPushButton" name="pb_configThrust">
+        <property name="geometry">
+         <rect>
+          <x>250</x>
+          <y>260</y>
+          <width>141</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Configure Thrust</string>
+        </property>
+       </widget>
+       <widget class="QPushButton" name="pb_configPitch">
+        <property name="geometry">
+         <rect>
+          <x>810</x>
+          <y>250</y>
+          <width>141</width>
+          <height>25</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Configure Pitch</string>
+        </property>
+       </widget>
+       <widget class="QLabel" name="noGamepadWarning">
+        <property name="geometry">
+         <rect>
+          <x>360</x>
+          <y>10</y>
+          <width>381</width>
+          <height>61</height>
+         </rect>
+        </property>
+        <property name="font">
+         <font>
+          <pointsize>20</pointsize>
+         </font>
+        </property>
+        <property name="text">
+         <string>No Gamepad Detected</string>
+        </property>
+        <property name="scaledContents">
+         <bool>false</bool>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+       </widget>
+       <widget class="QLabel" name="label_6">
+        <property name="geometry">
+         <rect>
+          <x>450</x>
+          <y>130</y>
+          <width>181</width>
+          <height>91</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Select the input to bind then move the joystick that will control that input</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="wordWrap">
+         <bool>true</bool>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="plots">
        <attribute name="title">
@@ -157,14 +568,52 @@
             <item>
              <widget class="QLabel" name="label_1">
               <property name="sizePolicy">
-               <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+               <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
                 <horstretch>0</horstretch>
                 <verstretch>0</verstretch>
                </sizepolicy>
               </property>
+              <property name="font">
+               <font>
+                <weight>75</weight>
+                <bold>true</bold>
+               </font>
+              </property>
               <property name="text">
                <string>Send Setpoint</string>
               </property>
+              <property name="alignment">
+               <set>Qt::AlignCenter</set>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="rbManualSetpoint">
+              <property name="text">
+               <string>Manual Setpoint</string>
+              </property>
+              <property name="checkable">
+               <bool>true</bool>
+              </property>
+              <property name="checked">
+               <bool>true</bool>
+              </property>
+              <attribute name="buttonGroup">
+               <string notr="true">buttonGroup_2</string>
+              </attribute>
+             </widget>
+            </item>
+            <item>
+             <widget class="QRadioButton" name="rbGamepadControl">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
+              <property name="text">
+               <string>Gamepad Control</string>
+              </property>
+              <attribute name="buttonGroup">
+               <string notr="true">buttonGroup_2</string>
+              </attribute>
              </widget>
             </item>
             <item>
@@ -190,6 +639,9 @@
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
+                <property name="text">
+                 <string>0</string>
+                </property>
                </widget>
               </item>
               <item row="1" column="0">
@@ -210,6 +662,9 @@
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
+                <property name="text">
+                 <string>0</string>
+                </property>
                </widget>
               </item>
               <item row="2" column="0">
@@ -230,26 +685,50 @@
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
+                <property name="text">
+                 <string>0</string>
+                </property>
                </widget>
               </item>
               <item row="3" column="0">
-               <widget class="QLabel" name="thrustlabel">
+               <widget class="QLabel" name="tLabel">
                 <property name="text">
                  <string>Thrust</string>
                 </property>
                </widget>
               </item>
               <item row="3" column="1">
-               <widget class="QLineEdit" name="thrustSetpointBox">
+               <widget class="QSlider" name="tActual">
                 <property name="enabled">
                  <bool>true</bool>
                 </property>
                 <property name="sizePolicy">
-                 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
                   <horstretch>0</horstretch>
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
+                <property name="minimumSize">
+                 <size>
+                  <width>140</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="toolTipDuration">
+                 <number>-1</number>
+                </property>
+                <property name="maximum">
+                 <number>60000</number>
+                </property>
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="tickPosition">
+                 <enum>QSlider::TicksBelow</enum>
+                </property>
+                <property name="tickInterval">
+                 <number>30000</number>
+                </property>
                </widget>
               </item>
               <item row="4" column="0">
@@ -257,6 +736,12 @@
                 <property name="text">
                  <string>Angle</string>
                 </property>
+                <property name="checked">
+                 <bool>true</bool>
+                </property>
+                <attribute name="buttonGroup">
+                 <string notr="true">AngleRateButtonGroup</string>
+                </attribute>
                </widget>
               </item>
               <item row="4" column="1">
@@ -264,6 +749,9 @@
                 <property name="text">
                  <string>Rate</string>
                 </property>
+                <attribute name="buttonGroup">
+                 <string notr="true">AngleRateButtonGroup</string>
+                </attribute>
                </widget>
               </item>
              </layout>
@@ -308,7 +796,7 @@
                </widget>
               </item>
               <item row="0" column="1">
-               <widget class="QLabel" name="tsActual">
+               <widget class="QLabel" name="currThrustLabel">
                 <property name="text">
                  <string>N/A</string>
                 </property>
@@ -460,4 +948,8 @@
  </customwidgets>
  <resources/>
  <connections/>
+ <buttongroups>
+  <buttongroup name="AngleRateButtonGroup"/>
+  <buttongroup name="buttonGroup_2"/>
+ </buttongroups>
 </ui>
diff --git a/groundStation/src/backend/config.c b/groundStation/src/backend/config.c
index a7287220f5130a2abff03cf3e530fb9480bcbc5e..444e15734ce86eadaf923996773b6ddda5ef2846 100644
--- a/groundStation/src/backend/config.c
+++ b/groundStation/src/backend/config.c
@@ -23,8 +23,8 @@ trackable_t trackables[] = {
         0,
         //Adapter Variables
         1,
-        "/home/bitcraze/projects/microCART/MicroCART/groundStation/adapters/crazyflie/", 
-        "/home/bitcraze/projects/microCART/MicroCART/groundStation/adapters/crazyflie/cf_adapter.socket", 
+        "./adapters/crazyflie/", 
+        "./adapters/crazyflie/cf_adapter.socket", 
         NULL,
         //Local Communication Variables
         0, //Set to 1 if Intending to use local Fifo
diff --git a/groundStation/src/backend/param.c b/groundStation/src/backend/param.c
index bb0dc1a9d3ea33249a9164b85f961c99ab4125cf..b31241cef73c440ae45d48ee2bbdc34176525fb7 100644
--- a/groundStation/src/backend/param.c
+++ b/groundStation/src/backend/param.c
@@ -129,8 +129,10 @@ ssize_t EncodeResponseParam(
 	data[RESP_BLOCK_ID_L] = 0;
 	data[RESP_BLOCK_ID_H] = 0;
 
-	data[RESP_PARAM_ID_L] = msg[1];
-	data[RESP_PARAM_ID_H] = 0;
+	//data[RESP_PARAM_ID_L] = msg[1];
+	//data[RESP_PARAM_ID_H] = msg[2];
+
+	memcpy(&data[RESP_PARAM_ID_L], &msg[1], sizeof(uint16_t));
 
 	float fl = -1;
 
@@ -138,70 +140,70 @@ ssize_t EncodeResponseParam(
 		case 8:
 		{
 			uint8_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(uint8_t));
+			memcpy(&pvalue, &msg[4], sizeof(uint8_t));
 			fl = pvalue;
 			break;
 		}
 		case 9:
 		{
 			uint16_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(uint16_t));
+			memcpy(&pvalue, &msg[4], sizeof(uint16_t));
 			fl = pvalue;
 			break;
 		}
 		case 10:
 		{
 			uint32_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(uint32_t));
+			memcpy(&pvalue, &msg[4], sizeof(uint32_t));
 			fl = pvalue;
 			break;
 		}
 		case 11:
 		{
 			uint64_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(uint64_t));
+			memcpy(&pvalue, &msg[4], sizeof(uint64_t));
 			fl = pvalue;
 			break;
 		}
 		case 0:
 		{
 			int8_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(int8_t));
+			memcpy(&pvalue, &msg[4], sizeof(int8_t));
 			fl = pvalue;
 			break;
 		}
 		case 1:
 		{
 			int16_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(int16_t));
+			memcpy(&pvalue, &msg[4], sizeof(int16_t));
 			fl = pvalue;
 			break;
 		}
 		case 2:
 		{
 			int32_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(int32_t));
+			memcpy(&pvalue, &msg[4], sizeof(int32_t));
 			fl = pvalue;
 			break;
 		}
 		case 3:
 		{
 			int64_t pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(int64_t));
+			memcpy(&pvalue, &msg[4], sizeof(int64_t));
 			fl = pvalue;
 			break;
 		}
 		case 6:
 		{
 			float pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(float));
+			memcpy(&pvalue, &msg[4], sizeof(float));
 			fl = pvalue;
 			break;
 		}
 		case 7:
 		{
 			double pvalue;
-			memcpy(&pvalue, &msg[2], sizeof(double));
+			memcpy(&pvalue, &msg[4], sizeof(double));
 			fl = pvalue;
 			break;
 		}
@@ -231,9 +233,12 @@ int DecodeResponseParam(
 		return -1;
 	}
 
+	uint16_t id;
+	memcpy(&id, &data[RESP_PARAM_ID_L], sizeof(uint16_t));
+
 	return snprintf(msg, max_len, "getparam %" PRId16 " %" PRId16 " %f\n",
 		BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]),
-		BytesTo16(data[RESP_PARAM_ID_L], data[RESP_PARAM_ID_H]),
+		id,
 		BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2],
 			data[RESP_VAL_3], data[RESP_VAL_4]));
 }