blob: c2af6c4a076c1f880f731d4b27771abdebb94b80 [file]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_CONTROLLER_STEPWISE_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_CONTROLLER_STEPWISE_H_
#include <limits>
#include <vector>
#include "thermal_config.pb.h"
namespace milotic_tlbmc {
namespace thermal {
/*
* `StepwiseThermalLoop` is a thermal control algorithm that outputs a value
* different from the last output only when the delta between the current and
* the last input that triggered an output search is large enough.
*
* If the delta is large enough, the triggered output search will return the
* corresponding `output` of the largest manually configured `threshold` that is
* smaller than or equal to `input`.
*
* This class is not thread-safe.
*
* This class is created and revised based on the stepwise structs at
* https://github.com/openbmc/phosphor-pid-control/blob/master/pid/ec/stepwise.hpp
* and the stepwise controller at
* https://github.com/openbmc/phosphor-pid-control/blob/master/pid/stepwisecontroller.hpp
*/
class StepwiseThermalLoop {
public:
StepwiseThermalLoop() = default;
explicit StepwiseThermalLoop(const StepwiseLoopConfig& stepwise_params)
: stepwise_params_(stepwise_params) {
if (stepwise_params.sample_time_sec() <= 0) {
stepwise_params_.set_sample_time_sec(1.0);
}
}
/*
* `ExecuteStepwiseLoop` performs exactly one iteration of a stepwise loop.
*
* If this is the first iteration, or the delta between the current and the
* last input is larger than the corresponding hysteresis value, it will
* proceed to the next step, otherwise, the last output will be returned.
*
* As the next step, it will output the corresponding `stepwise_output`
* of the largest manually configured `threshold` that is smaller than or
* equal to `input`.
*
* If no such critical point exists (i.e., `input` is smaller than the
* smallest `threshold`), it will output the `stepwise_output` of the first
* critical point by default.
*/
double ExecuteStepwiseLoop(double input);
void SetCriticalPoints(
const std::vector<StepwiseCriticalPoint>& critical_points) {
stepwise_params_.clear_critical_points();
for (const StepwiseCriticalPoint& critical_point : critical_points) {
*stepwise_params_.add_critical_points() = critical_point;
}
}
StepwiseCriticalPoint GetCriticalPointAt(int index) const {
return stepwise_params_.critical_points(index);
}
int GetCriticalPointsSize() const {
return stepwise_params_.critical_points_size();
}
void SetPositiveHysteresis(double positive_hysteresis) {
stepwise_params_.set_positive_hysteresis(positive_hysteresis);
}
double GetPositiveHysteresis() const {
return stepwise_params_.positive_hysteresis();
}
void SetNegativeHysteresis(double negative_hysteresis) {
stepwise_params_.set_negative_hysteresis(negative_hysteresis);
}
double GetNegativeHysteresis() const {
return stepwise_params_.negative_hysteresis();
}
void SetLastInput(double last_input) { last_input_ = last_input; }
double GetLastInput() const { return last_input_; }
void SetLastOutput(double last_output) { last_output_ = last_output; }
double GetLastOutput() const { return last_output_; }
double GetSampleTime() const { return stepwise_params_.sample_time_sec(); }
protected:
double FindStepwiseOutput(double input) const;
private:
double last_input_ = std::numeric_limits<double>::quiet_NaN();
double last_output_ = std::numeric_limits<double>::quiet_NaN();
StepwiseLoopConfig
stepwise_params_; // The parameters for this stepwise thermal loop.
};
} // namespace thermal
} // namespace milotic_tlbmc
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_THERMAL_CONTROLLER_STEPWISE_H_