diff --git a/src/ConRIG/Buttons/Buttons.cpp b/src/ConRIG/Buttons/Buttons.cpp
index 8390a9494aaeeccff1c67dcba0a204da15672c8c..c4b5a98d179e46698949a65174c12c55c5e4c504 100644
--- a/src/ConRIG/Buttons/Buttons.cpp
+++ b/src/ConRIG/Buttons/Buttons.cpp
@@ -32,11 +32,10 @@ using namespace miosix;
using namespace Boardcore;
using namespace ConRIG;
-Buttons::Buttons() : state() {}
-
bool Buttons::start()
{
- TaskScheduler& scheduler = getModule<BoardScheduler>()->getRadioScheduler();
+ TaskScheduler& scheduler =
+ getModule<BoardScheduler>()->getButtonsScheduler();
return scheduler.addTask([this]() { periodicStatusCheck(); },
Config::Buttons::BUTTON_SAMPLE_PERIOD) != 0;
@@ -44,131 +43,43 @@ bool Buttons::start()
mavlink_conrig_state_tc_t Buttons::getState() { return state; }
-void Buttons::resetState()
-{
- // Preserve the arm switch state
- auto armSwitch = state.arm_switch;
- state = {};
- state.arm_switch = armSwitch;
-}
-
void Buttons::periodicStatusCheck()
{
+#define CHECK_BUTTON(cond, btn) \
+ if (cond) \
+ { \
+ if (guard.btn > Config::Buttons::GUARD_THRESHOLD) \
+ { \
+ guard.btn = 0; \
+ state.btn = true; \
+ LOG_DEBUG(logger, #btn " button pressed"); \
+ } \
+ else \
+ { \
+ guard.btn++; \
+ } \
+ } \
+ else \
+ { \
+ guard.btn = 0; \
+ state.btn = false; \
+ }
+
state.arm_switch = btns::arm::value();
- if (!btns::ignition::value() && state.arm_switch)
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ignition_btn = true;
- LOG_DEBUG(logger, "Ignition button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2o_filling::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_filling_btn = true;
- LOG_DEBUG(logger, "ox filling button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2o_release::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_release_btn = true;
- LOG_DEBUG(logger, "ox release button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_release::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_release_btn = true;
- LOG_DEBUG(logger, "n2 release button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2o_venting::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_venting_btn = true;
- LOG_DEBUG(logger, "ox venting button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_detach::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_detach_btn = true;
- LOG_DEBUG(logger, "n2 detach button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_filling::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_filling_btn = true;
- LOG_DEBUG(logger, "n2 filling button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::nitrogen::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.nitrogen_btn = true;
- LOG_DEBUG(logger, "nitrogen button pressed");
- }
- else
- {
- guard++;
- }
- }
- else
- {
- // Reset all the states and guard
- guard = 0;
- resetState();
- }
+ CHECK_BUTTON(!btns::ignition::value() && state.arm_switch, ignition_btn);
+ CHECK_BUTTON(btns::n2o_filling::value(), ox_filling_btn);
+ CHECK_BUTTON(btns::n2o_release::value(), ox_release_btn);
+ CHECK_BUTTON(btns::n2_release::value(), n2_release_btn);
+ CHECK_BUTTON(btns::n2o_venting::value(), ox_venting_btn);
+ CHECK_BUTTON(btns::n2_detach::value(), n2_detach_btn);
+ CHECK_BUTTON(btns::n2_filling::value(), n2_filling_btn);
+ CHECK_BUTTON(btns::nitrogen::value(), nitrogen_btn);
+
+#undef CHECK_BUTTON
// Set the internal button state in Radio module
- getModule<Radio>()->setButtonsState(state);
+ getModule<Radio>()->updateButtonState(state);
}
void Buttons::enableIgnition() { ui::armedLed::high(); }
diff --git a/src/ConRIG/Buttons/Buttons.h b/src/ConRIG/Buttons/Buttons.h
index ecd160f2fd7d43d43d0c08e8de4aba4aee57a0bf..2d6fff4ae199923019fe7a44d52ae447647899e2 100644
--- a/src/ConRIG/Buttons/Buttons.h
+++ b/src/ConRIG/Buttons/Buttons.h
@@ -36,8 +36,6 @@ class Radio;
class Buttons : public Boardcore::InjectableWithDeps<BoardScheduler, Radio>
{
public:
- Buttons();
-
[[nodiscard]] bool start();
mavlink_conrig_state_tc_t getState();
@@ -46,14 +44,11 @@ public:
void disableIgnition();
private:
- void resetState();
-
void periodicStatusCheck();
- mavlink_conrig_state_tc_t state;
-
+ mavlink_conrig_state_tc_t state{};
// Counter guard to avoid spurious triggers
- uint8_t guard = 0;
+ mavlink_conrig_state_tc_t guard{};
Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("buttons");
};
diff --git a/src/ConRIG/Radio/Radio.cpp b/src/ConRIG/Radio/Radio.cpp
index f6b4807cbd0339bfdeaccc703c1a15a239ae5d88..cb88b002b6c0144edfdb1d90bde806f7e54c1b92 100644
--- a/src/ConRIG/Radio/Radio.cpp
+++ b/src/ConRIG/Radio/Radio.cpp
@@ -80,9 +80,8 @@ void Radio::handleMessage(const mavlink_message_t& msg)
// we assume this ack is about the last sent message
if (id == MAVLINK_MSG_ID_CONRIG_STATE_TC)
{
- Lock<FastMutex> lock{buttonsMutex};
// Reset the internal button state
- buttonState = {};
+ resetButtonState();
}
break;
@@ -156,11 +155,11 @@ void Radio::loopBuzzer()
}
}
-void Radio::setButtonsState(mavlink_conrig_state_tc_t state)
+void Radio::updateButtonState(const mavlink_conrig_state_tc_t& state)
{
Lock<FastMutex> lock{buttonsMutex};
- // The OR operator is introduced to make sure that the receiver
- // understood the command
+ // Merge the new state with the old one, an extra-dumb way to ensure
+ // that we don't lose any button pressess
buttonState.ox_filling_btn |= state.ox_filling_btn;
buttonState.ox_release_btn |= state.ox_release_btn;
buttonState.n2_filling_btn |= state.n2_filling_btn;
@@ -170,11 +169,24 @@ void Radio::setButtonsState(mavlink_conrig_state_tc_t state)
buttonState.nitrogen_btn |= state.nitrogen_btn;
buttonState.ox_detach_btn |= state.ox_detach_btn;
buttonState.n2_quenching_btn |= state.n2_quenching_btn;
- buttonState.n2_3way_btn |= state.n2_3way_btn;
buttonState.tars3_btn |= state.tars3_btn;
buttonState.tars3m_btn |= state.tars3m_btn;
buttonState.ignition_btn |= state.ignition_btn;
- buttonState.arm_switch |= state.arm_switch;
+
+ // Don't merge lever states
+ buttonState.n2_3way_btn = state.n2_3way_btn;
+ buttonState.arm_switch = state.arm_switch;
+}
+
+void Radio::resetButtonState()
+{
+ Lock<FastMutex> lock{buttonsMutex};
+ // Save and restore lever states
+ auto n2_3way_btn = buttonState.n2_3way_btn;
+ auto arm_switch = buttonState.arm_switch;
+ buttonState = {};
+ buttonState.n2_3way_btn = n2_3way_btn;
+ buttonState.arm_switch = arm_switch;
}
bool Radio::start()
@@ -229,5 +241,3 @@ bool Radio::start()
}
MavlinkStatus Radio::getMavlinkStatus() { return mavDriver->getStatus(); }
-
-Radio::Radio() : buttonState() {}
diff --git a/src/ConRIG/Radio/Radio.h b/src/ConRIG/Radio/Radio.h
index f9d5edb293ce01516b11dfd26ea984318950b110..949df5f99e067bdcd269e69a34599eddd98a4694 100644
--- a/src/ConRIG/Radio/Radio.h
+++ b/src/ConRIG/Radio/Radio.h
@@ -49,13 +49,11 @@ class Radio : public Boardcore::InjectableWithDeps<Buses, BoardScheduler,
Buttons, Serial>
{
public:
- Radio();
-
[[nodiscard]] bool start();
Boardcore::MavlinkStatus getMavlinkStatus();
- void setButtonsState(mavlink_conrig_state_tc_t state);
+ void updateButtonState(const mavlink_conrig_state_tc_t& state);
bool enqueueMessage(const mavlink_message_t& msg);
@@ -64,6 +62,8 @@ private:
void loopBuzzer();
void handleMessage(const mavlink_message_t& msg);
+ void resetButtonState();
+
std::unique_ptr<Boardcore::SX1278Lora> radio;
std::unique_ptr<MavDriver> mavDriver;
@@ -72,10 +72,10 @@ private:
messageQueue;
miosix::FastMutex queueMutex;
- miosix::FastMutex buttonsMutex;
// Button internal state
- mavlink_conrig_state_tc_t buttonState;
+ miosix::FastMutex buttonsMutex;
+ mavlink_conrig_state_tc_t buttonState{};
std::thread buzzerLooper;
diff --git a/src/ConRIGv2/Buttons/Buttons.cpp b/src/ConRIGv2/Buttons/Buttons.cpp
index e7056ab79167ecda0e60e0254917e566461ca41e..f30478643745bf43486aa25a24b2980da0fd1913 100644
--- a/src/ConRIGv2/Buttons/Buttons.cpp
+++ b/src/ConRIGv2/Buttons/Buttons.cpp
@@ -1,5 +1,5 @@
/* Copyright (c) 2025 Skyward Experimental Rocketry
- * Author: Ettore Pane
+ * Authors: Ettore Pane, Niccolò Betto
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,15 +32,10 @@ using namespace miosix;
using namespace Boardcore;
using namespace ConRIGv2;
-Buttons::Buttons()
-{
- resetState();
- state.arm_switch = false;
-}
-
bool Buttons::start()
{
- TaskScheduler& scheduler = getModule<BoardScheduler>()->getRadioScheduler();
+ TaskScheduler& scheduler =
+ getModule<BoardScheduler>()->getButtonsScheduler();
return scheduler.addTask([this]() { periodicStatusCheck(); },
Config::Buttons::BUTTON_SAMPLE_PERIOD) != 0;
@@ -48,196 +43,48 @@ bool Buttons::start()
mavlink_conrig_state_tc_t Buttons::getState() { return state; }
-void Buttons::resetState()
-{
- // Preserve the arm switch state
- auto armSwitch = state.arm_switch;
- state = {};
- state.arm_switch = armSwitch;
-}
-
void Buttons::periodicStatusCheck()
{
- state.arm_switch = btns::arm::value();
-
- if (!btns::ignition::value() && state.arm_switch)
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ignition_btn = true;
- LOG_DEBUG(logger, "Ignition button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::ox_filling::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_filling_btn = true;
- LOG_DEBUG(logger, "Ox filling button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::ox_release::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_release_btn = true;
- LOG_DEBUG(logger, "Ox release button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::ox_detach::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_detach_btn = true;
- LOG_DEBUG(logger, "Ox detach button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_3way::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_detach_btn = true;
- LOG_DEBUG(logger, "n2 3way button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_filling::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_filling_btn = true;
- LOG_DEBUG(logger, "N2 filling button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_release::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_release_btn = true;
- LOG_DEBUG(logger, "N2 release button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_detach::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_detach_btn = true;
- LOG_DEBUG(logger, "N2 detach button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::nitrogen::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.nitrogen_btn = true;
- LOG_DEBUG(logger, "Nitrogen button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::ox_venting::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.ox_venting_btn = true;
- LOG_DEBUG(logger, "Ox venting button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::n2_quenching::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.n2_quenching_btn = true;
- LOG_DEBUG(logger, "N2 quenching button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::tars3::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.tars3_btn = true;
- LOG_DEBUG(logger, "Tars3 button pressed");
- }
- else
- {
- guard++;
- }
- }
- else if (btns::tars3m::value())
- {
- if (guard > Config::Buttons::GUARD_THRESHOLD)
- {
- guard = 0;
- state.tars3m_btn = true;
- LOG_DEBUG(logger, "Tars3m button pressed");
- }
- else
- {
- guard++;
- }
- }
- else
- {
- // Reset all the states and guard
- guard = 0;
- resetState();
+#define CHECK_BUTTON(cond, btn) \
+ if (cond) \
+ { \
+ if (guard.btn > Config::Buttons::GUARD_THRESHOLD) \
+ { \
+ guard.btn = 0; \
+ state.btn = true; \
+ LOG_DEBUG(logger, #btn " button pressed"); \
+ } \
+ else \
+ { \
+ guard.btn++; \
+ } \
+ } \
+ else \
+ { \
+ guard.btn = 0; \
+ state.btn = false; \
}
+ state.arm_switch = btns::arm::value();
+ state.n2_3way_btn = btns::n2_3way::value();
+
+ CHECK_BUTTON(!btns::ignition::value() && state.arm_switch, ignition_btn);
+ CHECK_BUTTON(btns::ox_filling::value(), ox_filling_btn);
+ CHECK_BUTTON(btns::ox_release::value(), ox_release_btn);
+ CHECK_BUTTON(btns::ox_detach::value(), ox_detach_btn);
+ CHECK_BUTTON(btns::ox_venting::value(), ox_venting_btn);
+ CHECK_BUTTON(btns::n2_filling::value(), n2_filling_btn);
+ CHECK_BUTTON(btns::n2_release::value(), n2_release_btn);
+ CHECK_BUTTON(btns::n2_detach::value(), n2_detach_btn);
+ CHECK_BUTTON(btns::n2_quenching::value(), n2_quenching_btn);
+ CHECK_BUTTON(btns::nitrogen::value(), nitrogen_btn);
+ CHECK_BUTTON(btns::tars3::value(), tars3_btn);
+ CHECK_BUTTON(btns::tars3m::value(), tars3m_btn);
+
+#undef CHECK_BUTTON
+
// Set the internal button state in Radio module
- getModule<Radio>()->setButtonsState(state);
+ getModule<Radio>()->updateButtonState(state);
}
void Buttons::enableIgnition() { ui::armedLed::high(); }
diff --git a/src/ConRIGv2/Buttons/Buttons.h b/src/ConRIGv2/Buttons/Buttons.h
index 5d2c26d0e205475718628903b21934478dfb8c6e..2c4d5440825d41614c65c8dc960fa64bd26fe4fc 100644
--- a/src/ConRIGv2/Buttons/Buttons.h
+++ b/src/ConRIGv2/Buttons/Buttons.h
@@ -36,8 +36,6 @@ class Radio;
class Buttons : public Boardcore::InjectableWithDeps<BoardScheduler, Radio>
{
public:
- Buttons();
-
[[nodiscard]] bool start();
mavlink_conrig_state_tc_t getState();
@@ -46,14 +44,11 @@ public:
void disableIgnition();
private:
- void resetState();
-
void periodicStatusCheck();
- mavlink_conrig_state_tc_t state;
-
+ mavlink_conrig_state_tc_t state{};
// Counter guard to avoid spurious triggers
- uint8_t guard = 0;
+ mavlink_conrig_state_tc_t guard{};
Boardcore::PrintLogger logger = Boardcore::Logging::getLogger("buttons");
};
diff --git a/src/ConRIGv2/Radio/Radio.cpp b/src/ConRIGv2/Radio/Radio.cpp
index 8e7ebb8436e7f309b9cc74e4bb1e0665e72c250a..328df566ad8998cc4558d832d574df9797ed240e 100644
--- a/src/ConRIGv2/Radio/Radio.cpp
+++ b/src/ConRIGv2/Radio/Radio.cpp
@@ -1,5 +1,5 @@
/* Copyright (c) 2025 Skyward Experimental Rocketry
- * Author: Ettore Pane
+ * Authors: Ettore Pane, Niccolò Betto
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -80,9 +80,8 @@ void Radio::handleMessage(const mavlink_message_t& msg)
// we assume this ack is about the last sent message
if (id == MAVLINK_MSG_ID_CONRIG_STATE_TC)
{
- Lock<FastMutex> lock{buttonsMutex};
// Reset the internal button state
- buttonState = {};
+ resetButtonState();
}
break;
@@ -164,11 +163,11 @@ void Radio::buzzerTask()
}
}
-void Radio::setButtonsState(const mavlink_conrig_state_tc_t& state)
+void Radio::updateButtonState(const mavlink_conrig_state_tc_t& state)
{
Lock<FastMutex> lock{buttonsMutex};
- // The OR operator is introduced to make sure that the receiver
- // understood the command
+ // Merge the new state with the old one, an extra-dumb way to ensure
+ // that we don't lose any button pressess
buttonState.ox_filling_btn |= state.ox_filling_btn;
buttonState.ox_release_btn |= state.ox_release_btn;
buttonState.n2_filling_btn |= state.n2_filling_btn;
@@ -178,11 +177,24 @@ void Radio::setButtonsState(const mavlink_conrig_state_tc_t& state)
buttonState.nitrogen_btn |= state.nitrogen_btn;
buttonState.ox_detach_btn |= state.ox_detach_btn;
buttonState.n2_quenching_btn |= state.n2_quenching_btn;
- buttonState.n2_3way_btn |= state.n2_3way_btn;
buttonState.tars3_btn |= state.tars3_btn;
buttonState.tars3m_btn |= state.tars3m_btn;
buttonState.ignition_btn |= state.ignition_btn;
- buttonState.arm_switch |= state.arm_switch;
+
+ // Don't merge lever states
+ buttonState.n2_3way_btn = state.n2_3way_btn;
+ buttonState.arm_switch = state.arm_switch;
+}
+
+void Radio::resetButtonState()
+{
+ Lock<FastMutex> lock{buttonsMutex};
+ // Save and restore lever states
+ auto n2_3way_btn = buttonState.n2_3way_btn;
+ auto arm_switch = buttonState.arm_switch;
+ buttonState = {};
+ buttonState.n2_3way_btn = n2_3way_btn;
+ buttonState.arm_switch = arm_switch;
}
bool Radio::start()
@@ -239,7 +251,7 @@ bool Radio::start()
MavlinkStatus Radio::getMavlinkStatus() { return mavDriver->getStatus(); }
-Radio::Radio() : buzzer(MIOSIX_BUZZER_TIM, 523), buttonState()
+Radio::Radio() : buzzer(MIOSIX_BUZZER_TIM, 523)
{
buzzer.setDutyCycle(TimerUtils::Channel::MIOSIX_BUZZER_CHANNEL, 0.5);
}
diff --git a/src/ConRIGv2/Radio/Radio.h b/src/ConRIGv2/Radio/Radio.h
index 399eb42fba46ada9bbf87528b16a6d8b04091493..9d8c8bb476e8ccacd5a2e4b63d2a9b617fa47c32 100644
--- a/src/ConRIGv2/Radio/Radio.h
+++ b/src/ConRIGv2/Radio/Radio.h
@@ -56,7 +56,7 @@ public:
Boardcore::MavlinkStatus getMavlinkStatus();
- void setButtonsState(const mavlink_conrig_state_tc_t& state);
+ void updateButtonState(const mavlink_conrig_state_tc_t& state);
bool enqueueMessage(const mavlink_message_t& msg);
@@ -65,6 +65,8 @@ private:
void buzzerTask();
void handleMessage(const mavlink_message_t& msg);
+ void resetButtonState();
+
std::unique_ptr<Boardcore::SX1278Lora> radio;
std::unique_ptr<MavDriver> mavDriver;
@@ -81,10 +83,10 @@ private:
messageQueue;
miosix::FastMutex queueMutex;
- miosix::FastMutex buttonsMutex;
// Button internal state
- mavlink_conrig_state_tc_t buttonState;
+ miosix::FastMutex buttonsMutex;
+ mavlink_conrig_state_tc_t buttonState{};
std::atomic<uint8_t> messagesReceived{0};
std::atomic<bool> isArmed{false};