diff --git a/.vscode/settings.json b/.vscode/settings.json
index ae73470616491339b1b4dd30234db922365b8e12..ad3a4cc6e27d76d6fbb77d88dcc67532033ebcfe 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -186,11 +186,6 @@
     "cmake.configureSettings": {
         "CMAKE_C_COMPILER_LAUNCHER": "ccache",
         "CMAKE_CXX_COMPILER_LAUNCHER": "ccache"
-<<<<<<< HEAD
     },
     "compilerexplorer.compilationDirectory": "${workspaceFolder}/build"
 }
-=======
-    }
-}
->>>>>>> 170759b0 ([vscode] Add cspell words to workspace dictionary)
diff --git a/src/boards/Groundstation/Automated/SMController/SMController.cpp b/src/boards/Groundstation/Automated/SMController/SMController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c4966d5d649bff3a2170247ee3e30779fb73ecdc
--- /dev/null
+++ b/src/boards/Groundstation/Automated/SMController/SMController.cpp
@@ -0,0 +1,639 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Federico Lolli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "SMController.h"
+
+#include <common/Events.h>
+#include <drivers/timer/TimestampTimer.h>
+
+#include "SMControllerData.h"
+
+using namespace Boardcore;
+using namespace Common;
+using namespace miosix;
+
+namespace Antennas
+{
+
+SMController::SMController() : HSM(&SMController::state_config)
+{
+    EventBroker::getInstance().subscribe(this, TOPIC_ARP);
+    EventBroker::getInstance().subscribe(this, TOPIC_TMTC);
+}
+
+// Super state
+Boardcore::State SMController::state_config(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::CONFIG);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_top);
+        }
+        case EV_INIT:
+        {
+            return transition(&SMController::state_init);
+        }
+        case TMTC_ARP_RESET_BOARD:
+        {
+            reboot();
+            return HANDLED;
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+// Super state
+Boardcore::State SMController::state_feedback(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::FEEDBACK);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_top);
+        }
+        case EV_INIT:
+        {
+            return transition(&SMController::state_armed);
+        }
+        case TMTC_ARP_DISARM:
+        {
+            return transition(&SMController::state_init_done);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+// Super state
+Boardcore::State SMController::state_no_feedback(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::NO_FEEDBACK);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_top);
+        }
+        case EV_INIT:
+        {
+            return transition(&SMController::state_armed_nf);
+        }
+        case TMTC_ARP_DISARM:
+        {
+            return transition(&SMController::state_insert_info);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_init(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::INIT);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_config);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case ARP_INIT_OK:
+        {
+            return transition(&SMController::state_init_done);
+        }
+        case ARP_INIT_ERROR:
+        {
+            return transition(&SMController::state_init_error);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_init_error(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::INIT_ERROR);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_config);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_FORCE_NO_FEEDBACK:
+        {
+            return transition(&SMController::state_insert_info);
+        }
+        case TMTC_ARP_FORCE_INIT:
+        {
+            return transition(&SMController::state_init_done);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_init_done(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::INIT_DONE);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_config);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_FORCE_NO_FEEDBACK:
+        {
+            return transition(&SMController::state_insert_info);
+        }
+        case TMTC_ARP_ARM:
+        {
+            return transition(&SMController::state_feedback);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_insert_info(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::INSERT_INFO);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_config);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_ARM:
+        {
+            return transition(&SMController::state_no_feedback);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_armed(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::ARMED);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_ENTER_TEST_MODE:
+        {
+            return transition(&SMController::state_test);
+        }
+        case TMTC_ARP_CALIBRATE:
+        {
+            return transition(&SMController::state_calibrate);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_test(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::TEST);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_EXIT_TEST_MODE:
+        {
+            return transition(&SMController::state_armed);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_calibrate(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::CALIBRATE);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case ARP_CAL_DONE:
+        {
+            return transition(&SMController::state_fix_antennas);
+        }
+        case TMTC_ARP_RESET_ALGORITHM:
+        {
+            return transition(&SMController::state_armed);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_fix_antennas(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::FIX_ANTENNAS);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case ARP_FIX_ANTENNAS:
+        {
+            return transition(&SMController::state_fix_rocket);
+        }
+        case TMTC_ARP_RESET_ALGORITHM:
+        {
+            return transition(&SMController::state_armed);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_fix_rocket(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::FIX_ROCKET);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case ARP_FIX_ROCKET:
+        {
+            return transition(&SMController::state_active);
+        }
+        case TMTC_ARP_RESET_ALGORITHM:
+        {
+            return transition(&SMController::state_armed);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_active(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::ACTIVE);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_RESET_ALGORITHM:
+        {
+            return transition(&SMController::state_armed);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_armed_nf(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::ARMED_NF);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_no_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_ENTER_TEST_MODE:
+        {
+            return transition(&SMController::state_test_nf);
+        }
+        case TMTC_ARP_CALIBRATE:
+        {
+            return transition(&SMController::state_fix_rocket_nf);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_test_nf(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::TEST_NF);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_no_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_EXIT_TEST_MODE:
+        {
+            return transition(&SMController::state_armed_nf);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_fix_rocket_nf(
+    const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::FIX_ROCKET_NF);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_no_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case ARP_FIX_ROCKET:
+        {
+            return transition(&SMController::state_active_nf);
+        }
+        case TMTC_ARP_RESET_ALGORITHM:
+        {
+            return transition(&SMController::state_armed_nf);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+Boardcore::State SMController::state_active_nf(const Boardcore::Event& event)
+{
+    switch (event)
+    {
+        case EV_ENTRY:
+        {
+            logStatus(SMControllerState::ACTIVE_NF);
+            return HANDLED;
+        }
+        case EV_EXIT:
+        {
+            return HANDLED;
+        }
+        case EV_EMPTY:
+        {
+            return tranSuper(&SMController::state_no_feedback);
+        }
+        case EV_INIT:
+        {
+            return HANDLED;
+        }
+        case TMTC_ARP_RESET_ALGORITHM:
+        {
+            return transition(&SMController::state_armed_nf);
+        }
+        default:
+        {
+            return UNHANDLED;
+        }
+    }
+}
+
+void SMController::logStatus(SMControllerState state)
+{
+    {
+        PauseKernelLock lock;
+        status.timestamp = TimestampTimer::getTimestamp();
+        status.state     = state;
+    }
+
+    Logger::getInstance().log(status);
+}
+
+}  // namespace Antennas
diff --git a/src/boards/Groundstation/Automated/SMController/SMController.h b/src/boards/Groundstation/Automated/SMController/SMController.h
new file mode 100644
index 0000000000000000000000000000000000000000..f48e7957b86f5e62ff8cdc22b0f528344e4a3394
--- /dev/null
+++ b/src/boards/Groundstation/Automated/SMController/SMController.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Federico Lolli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <events/EventBroker.h>
+#include <events/HSM.h>
+
+#include <utils/ModuleManager/ModuleManager.hpp>
+
+#include "SMControllerData.h"
+
+namespace Antennas
+{
+
+class SMController : public Boardcore::Module,
+                     public Boardcore::HSM<SMController>
+{
+public:
+    SMController();
+
+    // FSM States
+    Boardcore::State state_config(const Boardcore::Event& event);
+    Boardcore::State state_feedback(const Boardcore::Event& event);
+    Boardcore::State state_no_feedback(const Boardcore::Event& event);
+    Boardcore::State state_init(const Boardcore::Event& event);
+    Boardcore::State state_init_error(const Boardcore::Event& event);
+    Boardcore::State state_init_done(const Boardcore::Event& event);
+    Boardcore::State state_insert_info(const Boardcore::Event& event);
+    Boardcore::State state_armed(const Boardcore::Event& event);
+    Boardcore::State state_test(const Boardcore::Event& event);
+    Boardcore::State state_calibrate(const Boardcore::Event& event);
+    Boardcore::State state_fix_antennas(const Boardcore::Event& event);
+    Boardcore::State state_fix_rocket(const Boardcore::Event& event);
+    Boardcore::State state_active(const Boardcore::Event& event);
+    Boardcore::State state_armed_nf(const Boardcore::Event& event);
+    Boardcore::State state_test_nf(const Boardcore::Event& event);
+    Boardcore::State state_fix_rocket_nf(const Boardcore::Event& event);
+    Boardcore::State state_active_nf(const Boardcore::Event& event);
+
+private:
+    /**
+     * @brief Logs the current state of the FSM
+     * @param state The current FSM state
+     */
+    void logStatus(SMControllerState state);
+
+    SMControllerStatus status;
+
+    Boardcore::PrintLogger logger =
+        Boardcore::Logging::getLogger("SMController");
+};
+
+}  // namespace Antennas
diff --git a/src/boards/Groundstation/Automated/SMController/SMControllerData.h b/src/boards/Groundstation/Automated/SMController/SMControllerData.h
new file mode 100644
index 0000000000000000000000000000000000000000..98b3fa259acdf35868893b9d6d784dca04d32a3c
--- /dev/null
+++ b/src/boards/Groundstation/Automated/SMController/SMControllerData.h
@@ -0,0 +1,79 @@
+/* Copyright (c) 2024 Skyward Experimental Rocketry
+ * Author: Federico Lolli
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <iostream>
+#include <string>
+
+namespace Antennas
+{
+
+enum class SMControllerState : uint8_t
+{
+    INIT = 0,
+    INIT_ERROR,
+    INIT_DONE,
+    INSERT_INFO,
+    ARMED,
+    ARMED_NF,
+    TEST,
+    TEST_NF,
+    CALIBRATE,
+    FIX_ANTENNAS,
+    FIX_ROCKET,
+    FIX_ROCKET_NF,
+    ACTIVE,
+    ACTIVE_NF,
+    /**
+     * @brief macro state for configuration (init, init_error,
+     * init_done, state_insert_info)
+     */
+    CONFIG,
+    /**
+     * @brief macro state for feedback (armed, test, calibrate,
+     * fix_antennas, fix_rocket, active)
+     */
+    FEEDBACK,
+    /**
+     * @brief macro state for no feedback (armed_nf, test_nf,
+     * fix_rocket_nf, active_nf)
+     */
+    NO_FEEDBACK
+};
+
+struct SMControllerStatus
+{
+    uint64_t timestamp;
+    SMControllerState state;
+
+    static std::string header() { return "timestamp,state\n"; }
+
+    void print(std::ostream& os) const
+    {
+        os << timestamp << "," << (int)state << "\n";
+    }
+};
+
+}  // namespace Antennas