mirror of
https://gitlab.dit.htwk-leipzig.de/phillip.kuehne/dezibot.git
synced 2025-05-19 02:51:47 +02:00
126 lines
4.6 KiB
C++
126 lines
4.6 KiB
C++
/**
|
|
* @file PowerScheduler.hpp
|
|
* @author Phillip Kühne
|
|
* @brief The actual power scheduler class, which keeps track of the power
|
|
* budget and allocates power to different components.
|
|
* @version 0.1
|
|
* @date 2024-12-21
|
|
*
|
|
* @copyright (c) 2024
|
|
*
|
|
*/
|
|
|
|
#include "PowerParameters.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include <Arduino.h>
|
|
#include <vector>
|
|
|
|
#ifndef PowerScheduler_h
|
|
#define PowerScheduler_h
|
|
|
|
class PowerScheduler {
|
|
private:
|
|
static constexpr uint16_t DEFAULT_SLACK_TIME_MS = 100;
|
|
PowerScheduler(float i_limit_ma, float i_max_ma);
|
|
|
|
public:
|
|
~PowerScheduler();
|
|
/// @brief Initialize the singleton instance of the power manager
|
|
/// @return reference to the power manager
|
|
static PowerScheduler &getPowerScheduler(float i_limit_ma = 0,
|
|
float i_max_ma = 0);
|
|
/// @brief Get the current free current budget (to C1 discharge)
|
|
/// @return the amount of power that is currently available (in mA)
|
|
float getFreeLimitCurrentBudget(void);
|
|
/// @brief Get the current hard maximum free current (to C2 discharge)
|
|
/// @return the maximum amount of power that can be allocated (in mA)
|
|
float getFreeMaximumCurrentBudget(void);
|
|
|
|
/// @brief Request an allowance of a certain number of milliamperes from the
|
|
/// power scheduler without waiting for it (meaning it will not be scheduled
|
|
/// for future allocation). Only one can be active per consumer.
|
|
/// @param neededCurrent the amount of current we want to be accounted for (in
|
|
/// mA)
|
|
/// @return whether the current could be successfully allocated
|
|
bool tryAccquireCurrentAllowance(PowerParameters::PowerConsumers consumer,
|
|
uint16_t neededcurrent,
|
|
uint16_t requestedDurationMs = 0);
|
|
/// @brief "Return" the current currently allocated to a consumer
|
|
/// @param consumer the active consumer to release the current for
|
|
void releaseCurrent(PowerParameters::PowerConsumers consumer);
|
|
|
|
/// @brief Wait for a certain amount of current to be available. This will
|
|
/// "reseve a spot in the queue". Only one can be active per consumer.
|
|
/// @param neededCurrent the amount of power we want to be accounted for (in
|
|
/// mW)
|
|
/// @param TicksToWait the amount of time to wait for the power to become
|
|
/// available
|
|
/// @return whether the power could be successfully allocatedy
|
|
bool waitForCurrentAllowance(PowerParameters::PowerConsumers consumer,
|
|
uint16_t neededCurrent,
|
|
uint16_t maxSlackTimeMs = DEFAULT_SLACK_TIME_MS,
|
|
uint16_t requestedDurationMs = 0);
|
|
/// @brief Put the ESP32 into deep sleep mode, without a method to wake up
|
|
/// again. Basically this is a shutdown.
|
|
void beginPermanentDeepSleep(void);
|
|
|
|
//// @brief Get currently granted power
|
|
/// @return the amount of power that is currently allocated (in mA)
|
|
float getCurrentCurrent(void);
|
|
|
|
/// @brief Power consumer data structure
|
|
struct CurrentAllowance {
|
|
PowerParameters::PowerConsumers consumer;
|
|
uint16_t maxSlackTimeMs;
|
|
uint16_t requestedDurationMs;
|
|
TaskHandle_t taskHandle;
|
|
uint16_t neededCurrent;
|
|
TickType_t requestedAt;
|
|
TickType_t grantedAt;
|
|
bool granted;
|
|
};
|
|
|
|
// @brief waiting task wakeup reasons
|
|
enum PowerWakeupReasons {
|
|
POWER_AVAILABLE = 1,
|
|
POWER_EXPIRED = 2,
|
|
};
|
|
// @brief Responsible for recalculating the current budgets
|
|
void recalculateCurrentBudgets(void);
|
|
|
|
// @brief Get current consumption of a consumer
|
|
float getConsumerCurrent(PowerParameters::PowerConsumers consumer);
|
|
|
|
// @brief Retrieve the current allowance for a given consumer
|
|
CurrentAllowance *
|
|
getCurrentAllowance(PowerParameters::PowerConsumers consumer);
|
|
// @brief Retrieve the current allowance for a given task
|
|
CurrentAllowance *getCurrentAllowance(TaskHandle_t taskHandle);
|
|
|
|
// @brief Retrieve the allowance that will expire next
|
|
CurrentAllowance *getNextExpiringAllowance(void);
|
|
|
|
protected:
|
|
// Current above which there will be no new scheduling
|
|
uint16_t limitCurrent;
|
|
// Absolute maximum current that can be allocated
|
|
uint16_t maximumCurrent;
|
|
|
|
// Current budget that is currently available to limitCurrent
|
|
int16_t freeLimitCurrentBudget;
|
|
// Current budget that is currently available to maximumCurrent
|
|
int16_t freeMaximumCurrentBudget;
|
|
|
|
// @brief Responsible for selecting the next task to be granted power
|
|
void checkWaitingTasks(void);
|
|
|
|
// @brief Mutex to protect the power scheduler from concurrent access
|
|
static portMUX_TYPE mux;
|
|
|
|
std::vector<PowerScheduler::CurrentAllowance> currentAllowances;
|
|
};
|
|
|
|
static PowerScheduler *powerSchedulerInstance;
|
|
|
|
#endif // PowerScheduler_h
|