diff --git a/src/boards/Groundstation/Automated/Leds/Leds.cpp b/src/boards/Groundstation/Automated/Leds/Leds.cpp index bd0794da4ce2c178df9184bc282bf166d7097076..ff5069823bb31ba2b3661356bd295b69ce33e9f0 100644 --- a/src/boards/Groundstation/Automated/Leds/Leds.cpp +++ b/src/boards/Groundstation/Automated/Leds/Leds.cpp @@ -24,58 +24,18 @@ #include <mutex> -using namespace std; using namespace Boardcore; namespace Antennas { -Leds::Leds(TaskScheduler* scheduler) : scheduler(scheduler) +LedThread::LedThread(LedColor color) + : ActiveObject(miosix::STACK_DEFAULT_FOR_PTHREAD, 0), color(color), + state(LedState::OFF) { - for (size_t i = 0; i < led_states.size(); i++) - { - led_states[i] = LedState::OFF; - led_mutexes[i] = make_unique<mutex>(); - led_cvs[i] = make_unique<condition_variable>(); - } } -bool Leds::start() -{ - size_t result; - bool ok = true; - - // turn off all leds - miosix::ledOff(); - - // start the blinking thread for red led - result = scheduler->addTask( - std::bind(&Leds::ledThread, this, LedColor::RED, 100), 0, - TaskScheduler::Policy::ONE_SHOT); - ok &= result != 0; - - // start the blinking thread for yellow led - result = scheduler->addTask( - std::bind(&Leds::ledThread, this, LedColor::YELLOW, 50), 0, - TaskScheduler::Policy::ONE_SHOT); - ok &= result != 0; - - // start the blinking thread for orange led - result = scheduler->addTask( - std::bind(&Leds::ledThread, this, LedColor::ORANGE, 50), 0, - TaskScheduler::Policy::ONE_SHOT); - ok &= result != 0; - - // start the blinking thread for green led - result = scheduler->addTask( - std::bind(&Leds::ledThread, this, LedColor::GREEN, 50), 0, - TaskScheduler::Policy::ONE_SHOT); - ok &= result != 0; - - return ok; -} - -void Leds::ledOn(LedColor color) +void LedThread::ledOn(LedColor color) { #ifdef _BOARD_STM32F767ZI_AUTOMATED_ANTENNAS switch (color) @@ -93,10 +53,26 @@ void Leds::ledOn(LedColor color) miosix::led1On(); break; } +#else + switch (color) + { + case LedColor::RED: + miosix::ledOn(); + break; + case LedColor::YELLOW: + miosix::led2On(); + break; + case LedColor::ORANGE: + miosix::led3On(); + break; + case LedColor::GREEN: + miosix::led1On(); + break; + } #endif } -void Leds::ledOff(LedColor color) +void LedThread::ledOff(LedColor color) { #ifdef _BOARD_STM32F767ZI_AUTOMATED_ANTENNAS switch (color) @@ -114,21 +90,34 @@ void Leds::ledOff(LedColor color) miosix::led1Off(); break; } +#else + switch (color) + { + case LedColor::RED: + miosix::ledOff(); + break; + case LedColor::YELLOW: + miosix::led2Off(); + break; + case LedColor::ORANGE: + miosix::led3Off(); + break; + case LedColor::GREEN: + miosix::led1Off(); + break; + } #endif } -/** - * @brief Thread function that actuate leds based on state - * @param color led color to actuate - * @param blinking_interval blinking time interval [ms] - */ -void Leds::ledThread(LedColor color, uint32_t blinking_interval) +void LedThread::run() { + LedState old = state; while (true) { - unique_lock<mutex> lock(*mutexRef(color)); - cvRef(color)->wait(lock); - switch (*ledRef(color)) + std::unique_lock<std::mutex> lock(mutex); + cv.wait(lock, [&] { return state != old; }); + old = state; + switch (state) { case LedState::BLINKING: { @@ -138,47 +127,85 @@ void Leds::ledThread(LedColor color, uint32_t blinking_interval) miosix::Thread::sleep(blinking_interval); ledOff(color); miosix::Thread::sleep(blinking_interval); - } while (*ledRef(color) == LedState::BLINKING); + } while (state == LedState::BLINKING); break; } case LedState::ON: { ledOn(color); + break; } case LedState::OFF: { ledOff(color); + break; } } } } -void Leds::setBlinking(LedColor color) +void LedThread::setBlinking(uint32_t ms_interval) +{ + { + std::lock_guard<std::mutex> lock(mutex); + state = LedState::BLINKING; + } + cv.notify_one(); +} + +void LedThread::setOn() +{ + { + std::lock_guard<std::mutex> lock(mutex); + state = LedState::ON; + } + cv.notify_one(); +} + +void LedThread::setOff() +{ + { + std::lock_guard<std::mutex> lock(mutex); + state = LedState::OFF; + } + cv.notify_one(); +} + +Leds::Leds() { - lock_guard<mutex> lock(*mutexRef(color)); - *ledRef(color) = LedState::BLINKING; - cvRef(color)->notify_one(); + for (size_t i = 0; i < leds.size(); i++) + { + leds[i] = std::make_unique<LedThread>(static_cast<LedColor>(i)); + } } -void Leds::setOn(LedColor color) +bool Leds::start() { - lock_guard<mutex> lock(*mutexRef(color)); - *ledRef(color) = LedState::ON; - cvRef(color)->notify_one(); + bool ok = true; + + // turn off all leds + miosix::ledOff(); + + for (size_t i = 0; i < leds.size(); i++) + { + ok &= leds[i]->start(); + } + + return ok; } -void Leds::setOff(LedColor color) +void Leds::setBlinking(LedColor color, uint32_t ms_interval) { - lock_guard<mutex> lock(*mutexRef(color)); - *ledRef(color) = LedState::OFF; - cvRef(color)->notify_one(); + ledRef(color)->setBlinking(ms_interval); } +void Leds::setOn(LedColor color) { ledRef(color)->setOn(); } + +void Leds::setOff(LedColor color) { ledRef(color)->setOff(); } + void Leds::endlessBlink(LedColor color) { - lock_guard<mutex> lock(*mutexRef(color)); - *ledRef(color) = LedState::BLINKING; - cvRef(color)->notify_one(); + ledRef(color)->setBlinking(100); miosix::Thread::wait(); // wait forever } diff --git a/src/boards/Groundstation/Automated/Leds/Leds.h b/src/boards/Groundstation/Automated/Leds/Leds.h index 5ae10c5c4e7d14af4e7086d79f378f6c6de25864..27830e4c95775335781a7d8596bbe9c7bcd150a1 100644 --- a/src/boards/Groundstation/Automated/Leds/Leds.h +++ b/src/boards/Groundstation/Automated/Leds/Leds.h @@ -22,11 +22,10 @@ #pragma once -#include <scheduler/TaskScheduler.h> +#include <ActiveObject.h> #include <array> #include <condition_variable> -#include <map> #include <mutex> #include <utils/ModuleManager/ModuleManager.hpp> @@ -41,6 +40,45 @@ enum class LedColor : uint8_t GREEN }; +class LedThread : public Boardcore::ActiveObject +{ +public: + explicit LedThread(LedColor color); + + /** + * @brief non-blocking action to set a led to blink in a loop + */ + void setBlinking(uint32_t ms_interval); + + /** + * @brief non-blocking action to set on the led + */ + void setOn(); + + /** + * @brief non-blocking action to set off the led + */ + void setOff(); + +private: + enum class LedState : uint8_t + { + OFF = 0, + ON, + BLINKING + }; + + void ledOn(LedColor color); + void ledOff(LedColor color); + void run() override; + + LedColor color; + LedState state; + std::mutex mutex; + std::condition_variable cv; + uint32_t blinking_interval = 100; // [ms] +}; + /** * @brief Utility to handle blinking leds with non-blocking sleep * (useful for state machines states that need to blink leds without blocking) @@ -48,20 +86,20 @@ enum class LedColor : uint8_t class Leds : public Boardcore::Module { public: - explicit Leds(Boardcore::TaskScheduler* scheduler); + explicit Leds(); /** - * @brief Start the blinking LED thread + * @brief Start all the blinking LED thread */ bool start(); /** * @brief non-blocking action to set a led to blink in a loop */ - void setBlinking(LedColor color); + void setBlinking(LedColor color, uint32_t ms_interval); /** - * @brief blocking action to set on a led + * @brief non-blocking action to set on a led */ void setOn(LedColor color); @@ -75,37 +113,13 @@ public: */ void endlessBlink(LedColor color); -protected: - enum class LedState : uint8_t - { - OFF = 0, - ON, - BLINKING - }; - - void ledOn(LedColor color); - void ledOff(LedColor color); - void ledThread(LedColor color, uint32_t ms_interval); - - LedState* ledRef(LedColor color) - { - return &led_states[static_cast<uint8_t>(color)]; - } - - std::mutex* mutexRef(LedColor color) - { - return led_mutexes[static_cast<uint8_t>(color)].get(); - } - - std::condition_variable* cvRef(LedColor color) +private: + LedThread* ledRef(LedColor color) { - return led_cvs[static_cast<uint8_t>(color)].get(); + return leds[static_cast<uint8_t>(color)].get(); } - Boardcore::TaskScheduler* scheduler; - std::array<LedState, 4> led_states; - std::array<unique_ptr<std::mutex>, 4> led_mutexes; - std::array<unique_ptr<std::condition_variable>, 4> led_cvs; + std::array<std::unique_ptr<LedThread>, 4> leds; }; } // namespace Antennas diff --git a/src/boards/Groundstation/Automated/SMController/SMController.cpp b/src/boards/Groundstation/Automated/SMController/SMController.cpp index d47796b71aa71f6e32d67cff76ef014743c0e145..817829659f4716f3a96abfe771bbd619dc1fdb39 100644 --- a/src/boards/Groundstation/Automated/SMController/SMController.cpp +++ b/src/boards/Groundstation/Automated/SMController/SMController.cpp @@ -370,8 +370,8 @@ State SMController::state_init_error(const Event& event) case EV_ENTRY: { logStatus(SMControllerState::INIT_ERROR); - ModuleManager::getInstance().get<Leds>()->setBlinking( - LedColor::RED); + ModuleManager::getInstance().get<Leds>()->setBlinking(LedColor::RED, + 100); return HANDLED; } case EV_EXIT: @@ -583,7 +583,7 @@ State SMController::state_fix_antennas(const Event& event) { logStatus(SMControllerState::FIX_ANTENNAS); ModuleManager::getInstance().get<Leds>()->setBlinking( - LedColor::ORANGE); + LedColor::ORANGE, 50); return HANDLED; } case EV_EXIT: @@ -623,7 +623,7 @@ State SMController::state_fix_rocket(const Event& event) { logStatus(SMControllerState::FIX_ROCKET); ModuleManager::getInstance().get<Leds>()->setBlinking( - LedColor::YELLOW); + LedColor::YELLOW, 50); return HANDLED; } case EV_EXIT: @@ -776,7 +776,7 @@ State SMController::state_fix_rocket_nf(const Event& event) { logStatus(SMControllerState::FIX_ROCKET_NF); ModuleManager::getInstance().get<Leds>()->setBlinking( - LedColor::YELLOW); + LedColor::YELLOW, 50); return HANDLED; } case EV_EXIT: diff --git a/src/entrypoints/Groundstation/Automated/automated-antennas-entry.cpp b/src/entrypoints/Groundstation/Automated/automated-antennas-entry.cpp index e2f3e35f1ae7258142a6396f8a3eed246b78c2c0..6cb204db05f1a50c6e54cb00a35bb6934a558f83 100644 --- a/src/entrypoints/Groundstation/Automated/automated-antennas-entry.cpp +++ b/src/entrypoints/Groundstation/Automated/automated-antennas-entry.cpp @@ -97,9 +97,8 @@ int main() }); ButtonHandler::getInstance().start(); - TaskScheduler *scheduler_low = new TaskScheduler(0); TaskScheduler *scheduler_high = new TaskScheduler(); - Leds *leds = new Leds(scheduler_low); + Leds *leds = new Leds(); Hub *hub = new Hub(); Buses *buses = new Buses(); Serial *serial = new Serial(); @@ -140,7 +139,6 @@ int main() #ifndef NO_SD_LOGGING START_MODULE("Logger", [&] { return Logger::getInstance().start(); }); #endif - START_MODULE("Scheduler", [&] { return scheduler_low->start(); }); START_MODULE("Scheduler", [&] { return scheduler_high->start(); }); START_MODULE("Serial", [&] { return serial->start(); }); START_MODULE("Main Radio", [&] { return radio_main->start(); });