diff --git a/src/PeriodicTask.cpp b/src/PeriodicTask.cpp deleted file mode 100644 index 5a5d3621..00000000 --- a/src/PeriodicTask.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "PeriodicTask.h" -#include "Periodic.h" -PeriodicScheduler periodicScheduler; - -PeriodicTask::PeriodicTask(uint32_t initialPeriod) : period(initialPeriod) {} - -void PeriodicTask::setup() -{ - periodicScheduler.schedule(this); -} - -/// call this from loop -void PeriodicScheduler::loop() -{ - meshtastic::LockGuard lg(&lock); - - uint32_t now = millis(); - for (auto t : tasks) { - if (t->period && (now - t->lastMsec) >= t->period) { - - t->doTask(); - t->lastMsec = now; - } - } -} - -void PeriodicScheduler::schedule(PeriodicTask *t) -{ - meshtastic::LockGuard lg(&lock); - tasks.insert(t); -} - -void PeriodicScheduler::unschedule(PeriodicTask *t) -{ - meshtastic::LockGuard lg(&lock); - tasks.erase(t); -} - -void Periodic::doTask() -{ - uint32_t p = callback(); - setPeriod(p); -} diff --git a/src/concurrency/Lock.h b/src/concurrency/Lock.h index c52b629c..63dce772 100644 --- a/src/concurrency/Lock.h +++ b/src/concurrency/Lock.h @@ -4,7 +4,9 @@ namespace concurrency { -// Simple wrapper around FreeRTOS API for implementing a mutex lock. +/** + * @brief Simple wrapper around FreeRTOS API for implementing a mutex lock + */ class Lock { public: diff --git a/src/concurrency/LockGuard.h b/src/concurrency/LockGuard.h index 6c35982a..dc09f40f 100644 --- a/src/concurrency/LockGuard.h +++ b/src/concurrency/LockGuard.h @@ -4,7 +4,9 @@ namespace concurrency { -// RAII lock guard. +/** + * @brief RAII lock guard + */ class LockGuard { public: diff --git a/src/concurrency/NotifiedWorkerThread.h b/src/concurrency/NotifiedWorkerThread.h index 4fd05326..5ab5a58e 100644 --- a/src/concurrency/NotifiedWorkerThread.h +++ b/src/concurrency/NotifiedWorkerThread.h @@ -5,7 +5,7 @@ namespace concurrency { /** - * A worker thread that waits on a freertos notification + * @brief A worker thread that waits on a freertos notification */ class NotifiedWorkerThread : public WorkerThread { diff --git a/src/Periodic.h b/src/concurrency/Periodic.h similarity index 52% rename from src/Periodic.h rename to src/concurrency/Periodic.h index c717b570..e380eb34 100644 --- a/src/Periodic.h +++ b/src/concurrency/Periodic.h @@ -1,12 +1,12 @@ #pragma once #include "PeriodicTask.h" -#include + +namespace concurrency { /** - * Periodically invoke a callback. - * - * This just provides C style callback conventions rather than a virtual function - FIXME, remove? + * @brief Periodically invoke a callback. This just provides C-style callback conventions + * rather than a virtual function - FIXME, remove? */ class Periodic : public PeriodicTask { @@ -17,5 +17,10 @@ class Periodic : public PeriodicTask Periodic(uint32_t (*_callback)()) : callback(_callback) {} protected: - void doTask(); + void doTask() { + uint32_t p = callback(); + setPeriod(p); + } }; + +} // namespace concurrency diff --git a/src/concurrency/PeriodicScheduler.cpp b/src/concurrency/PeriodicScheduler.cpp new file mode 100644 index 00000000..a6a7518c --- /dev/null +++ b/src/concurrency/PeriodicScheduler.cpp @@ -0,0 +1,35 @@ +#include "PeriodicScheduler.h" +#include "PeriodicTask.h" +#include "LockGuard.h" +#include "../time.h" + +namespace concurrency { + +/// call this from loop +void PeriodicScheduler::loop() +{ + LockGuard lg(&lock); + + uint32_t now = time::millis(); + for (auto t : tasks) { + if (t->period && (now - t->lastMsec) >= t->period) { + + t->doTask(); + t->lastMsec = now; + } + } +} + +void PeriodicScheduler::schedule(PeriodicTask *t) +{ + LockGuard lg(&lock); + tasks.insert(t); +} + +void PeriodicScheduler::unschedule(PeriodicTask *t) +{ + LockGuard lg(&lock); + tasks.erase(t); +} + +} // namespace concurrency diff --git a/src/concurrency/PeriodicScheduler.h b/src/concurrency/PeriodicScheduler.h new file mode 100644 index 00000000..943da17c --- /dev/null +++ b/src/concurrency/PeriodicScheduler.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Lock.h" +#include +#include + +namespace concurrency { + +class PeriodicTask; + +/** + * @brief Runs all PeriodicTasks in the system. Currently called from main loop() + * but eventually should be its own thread blocked on a freertos timer. + */ +class PeriodicScheduler +{ + friend class PeriodicTask; + + /** + * This really should be some form of heap, and when the period gets changed on a task it should get + * rescheduled in that heap. Currently it is just a dumb array and everytime we run loop() we check + * _every_ tasks. If it was a heap we'd only have to check the first task. + */ + std::unordered_set tasks; + + // Protects the above variables. + Lock lock; + + public: + /// Run any next tasks which are due for execution + void loop(); + + private: + void schedule(PeriodicTask *t); + void unschedule(PeriodicTask *t); +}; + +extern PeriodicScheduler periodicScheduler; + +} // namespace concurrency diff --git a/src/concurrency/PeriodicTask.cpp b/src/concurrency/PeriodicTask.cpp new file mode 100644 index 00000000..40c6a4ed --- /dev/null +++ b/src/concurrency/PeriodicTask.cpp @@ -0,0 +1,16 @@ +#include "PeriodicTask.h" +#include "Periodic.h" +#include "LockGuard.h" + +namespace concurrency { + +PeriodicScheduler periodicScheduler; + +PeriodicTask::PeriodicTask(uint32_t initialPeriod) : period(initialPeriod) {} + +void PeriodicTask::setup() +{ + periodicScheduler.schedule(this); +} + +} // namespace concurrency diff --git a/src/PeriodicTask.h b/src/concurrency/PeriodicTask.h similarity index 55% rename from src/PeriodicTask.h rename to src/concurrency/PeriodicTask.h index 951b8cbb..f5e107ef 100644 --- a/src/PeriodicTask.h +++ b/src/concurrency/PeriodicTask.h @@ -1,41 +1,9 @@ #pragma once -#include "lock.h" -#include -#include -#include +#include "PeriodicScheduler.h" +#include "../time.h" -class PeriodicTask; - -/** - * Runs all PeriodicTasks in the system. - * - * Currently called from main loop() but eventually should be its own thread blocked on a freertos timer. - */ -class PeriodicScheduler -{ - friend class PeriodicTask; - - /** - * This really should be some form of heap, and when the period gets changed on a task it should get - * rescheduled in that heap. Currently it is just a dumb array and everytime we run loop() we check - * _every_ tasks. If it was a heap we'd only have to check the first task. - */ - std::unordered_set tasks; - - // Protects the above variables. - meshtastic::Lock lock; - - public: - /// Run any next tasks which are due for execution - void loop(); - - private: - void schedule(PeriodicTask *t); - void unschedule(PeriodicTask *t); -}; - -extern PeriodicScheduler periodicScheduler; +namespace concurrency { /** * A base class for tasks that want their doTask() method invoked periodically @@ -69,7 +37,7 @@ class PeriodicTask */ void setPeriod(uint32_t p) { - lastMsec = millis(); // reset starting from now + lastMsec = time::millis(); // reset starting from now period = p; } @@ -83,3 +51,5 @@ class PeriodicTask protected: virtual void doTask() = 0; }; + +} // namespace concurrency diff --git a/src/concurrency/Thread.h b/src/concurrency/Thread.h index e8a710eb..b297e40d 100644 --- a/src/concurrency/Thread.h +++ b/src/concurrency/Thread.h @@ -4,6 +4,9 @@ namespace concurrency { +/** + * @brief Base threading + */ class Thread { protected: diff --git a/src/concurrency/WorkerThread.h b/src/concurrency/WorkerThread.h index 0ae3060a..66111e7d 100644 --- a/src/concurrency/WorkerThread.h +++ b/src/concurrency/WorkerThread.h @@ -5,11 +5,10 @@ namespace concurrency { /** - * This wraps threading (FreeRTOS for now) with a blocking API intended for efficiently converting onlyschool arduino loop() code. + * @brief This wraps threading (FreeRTOS for now) with a blocking API intended for efficiently converting + * old-school arduino loop() code. Use as a mixin base class for the classes you want to convert. * - * Use as a mixin base class for the classes you want to convert. - * - * https://www.freertos.org/RTOS_Task_Notification_As_Mailbox.html + * @link https://www.freertos.org/RTOS_Task_Notification_As_Mailbox.html */ class WorkerThread : public Thread { diff --git a/src/gps/GPS.h b/src/gps/GPS.h index b2d1916d..97d69698 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -1,7 +1,6 @@ #pragma once #include "Observer.h" -#include "PeriodicTask.h" #include "sys/time.h" /// If we haven't yet set our RTC this boot, set it from a GPS derived time diff --git a/src/main.cpp b/src/main.cpp index 667c1069..fe306906 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,7 +25,7 @@ #include "MeshService.h" #include "NEMAGPS.h" #include "NodeDB.h" -#include "Periodic.h" +#include "concurrency/Periodic.h" #include "PowerFSM.h" #include "UBloxGPS.h" #include "configuration.h" @@ -124,7 +124,7 @@ static uint32_t ledBlinker() return powerStatus.charging ? 1000 : (ledOn ? 2 : 1000); } -Periodic ledPeriodic(ledBlinker); +concurrency::Periodic ledPeriodic(ledBlinker); // Prepare for button presses #ifdef BUTTON_PIN @@ -316,7 +316,7 @@ uint32_t axpDebugRead() return 30 * 1000; } -Periodic axpDebugOutput(axpDebugRead); +concurrency::Periodic axpDebugOutput(axpDebugRead); axpDebugOutput.setup(); #endif diff --git a/src/screen.cpp b/src/screen.cpp index b98138fc..6a210beb 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -529,7 +529,7 @@ void Screen::handleSetOn(bool on) void Screen::setup() { - PeriodicTask::setup(); + concurrency::PeriodicTask::setup(); // We don't set useDisplay until setup() is called, because some boards have a declaration of this object but the device // is never found when probing i2c and therefore we don't call setup and never want to do (invalid) accesses to this device. @@ -746,7 +746,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 char channelStr[20]; { - LockGuard guard(&lock); + concurrency::LockGuard guard(&lock); snprintf(channelStr, sizeof(channelStr), "#%s", channelName.c_str()); // Display power status diff --git a/src/screen.h b/src/screen.h index 6d4d8b37..55399501 100644 --- a/src/screen.h +++ b/src/screen.h @@ -10,9 +10,9 @@ #include #endif -#include "PeriodicTask.h" +#include "concurrency/PeriodicTask.h" #include "TypedQueue.h" -#include "lock.h" +#include "concurrency/Lock.h" #include "power.h" #include @@ -32,7 +32,7 @@ class DebugInfo /// Sets user statistics. void setNodeNumbersStatus(int online, int total) { - LockGuard guard(&lock); + concurrency::LockGuard guard(&lock); nodesOnline = online; nodesTotal = total; } @@ -40,7 +40,7 @@ class DebugInfo /// Sets the name of the channel. void setChannelNameStatus(const char *name) { - LockGuard guard(&lock); + concurrency::LockGuard guard(&lock); channelName = name; } @@ -48,7 +48,7 @@ class DebugInfo // void setPowerStatus(const PowerStatus &status) { - LockGuard guard(&lock); + concurrency::LockGuard guard(&lock); powerStatus = status; } @@ -59,7 +59,7 @@ class DebugInfo // TODO(girts): figure out what the format should be. void setGPSStatus(const char *status) { - LockGuard guard(&lock); + concurrency::LockGuard guard(&lock); gpsStatus = status; } @@ -81,7 +81,7 @@ class DebugInfo std::string gpsStatus; /// Protects all of internal state. - Lock lock; + concurrency::Lock lock; }; /// Deals with showing things on the screen of the device. @@ -91,7 +91,7 @@ class DebugInfo // // This class is thread-safe (as long as drawFrame is not called multiple times // simultaneously). -class Screen : public PeriodicTask +class Screen : public concurrency::PeriodicTask { public: Screen(uint8_t address, int sda = -1, int scl = -1); diff --git a/src/time.h b/src/time.h new file mode 100644 index 00000000..9decfabe --- /dev/null +++ b/src/time.h @@ -0,0 +1,11 @@ +#pragma once + +#include "freertos.h" + +namespace time { + + uint32_t millis() { + return xTaskGetTickCount(); + } + +} // namespace time \ No newline at end of file