blob: 877871930bfaaa7e9a2cdcf3d399e2a8078092b4 [file] [log] [blame]
Patrick Ventured8012182018-03-08 08:21:38 -08001/**
2 * Copyright 2017 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "thermalcontroller.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070018
James Feist734f9532018-11-15 12:13:18 -080019#include "errors/exception.hpp"
Bonnie Loc51ba912022-10-12 14:07:22 +080020#include "tuning.hpp"
Patrick Ventured8012182018-03-08 08:21:38 -080021#include "util.hpp"
22#include "zone.hpp"
23
Patrick Venturee94bdc42018-11-15 18:41:21 -080024#include <algorithm>
Josh Lehanca791152020-09-20 23:41:39 -070025#include <cmath>
26#include <iostream>
Patrick Venturee94bdc42018-11-15 18:41:21 -080027
Patrick Venturea0764872020-08-08 07:48:43 -070028namespace pid_control
29{
30
Patrick Venturee94bdc42018-11-15 18:41:21 -080031ThermalType getThermalType(const std::string& typeString)
32{
33 /* Currently it only supports the two types. */
34 return (typeString == "temp") ? ThermalType::absolute : ThermalType::margin;
35}
36
37bool isThermalType(const std::string& typeString)
38{
39 static const std::vector<std::string> thermalTypes = {"temp", "margin"};
40 return std::count(thermalTypes.begin(), thermalTypes.end(), typeString);
41}
42
Patrick Venture563a3562018-10-30 09:31:26 -070043std::unique_ptr<PIDController> ThermalController::createThermalPid(
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070044 ZoneInterface* owner, const std::string& id,
Patrick Venture5f59c0f2018-11-11 12:55:14 -080045 const std::vector<std::string>& inputs, double setpoint,
James Feist734f9532018-11-15 12:13:18 -080046 const ec::pidinfo& initial, const ThermalType& type)
Patrick Ventured8012182018-03-08 08:21:38 -080047{
James Feist734f9532018-11-15 12:13:18 -080048 // ThermalController requires at least 1 input
49 if (inputs.empty())
Patrick Venture3349ef22018-06-12 14:09:29 -070050 {
James Feist734f9532018-11-15 12:13:18 -080051 throw ControllerBuildException("Thermal controller missing inputs");
Patrick Venture3349ef22018-06-12 14:09:29 -070052 return nullptr;
53 }
54
James Feist734f9532018-11-15 12:13:18 -080055 auto thermal = std::make_unique<ThermalController>(id, inputs, type, owner);
Patrick Ventured8012182018-03-08 08:21:38 -080056
Patrick Venture563a3562018-10-30 09:31:26 -070057 ec::pid_info_t* info = thermal->getPIDInfo();
58 thermal->setSetpoint(setpoint);
Patrick Ventured8012182018-03-08 08:21:38 -080059
Patrick Venture7af157b2018-10-30 11:24:40 -070060 initializePIDStruct(info, initial);
Patrick Ventured8012182018-03-08 08:21:38 -080061
62 return thermal;
63}
64
Patrick Venture5f59c0f2018-11-11 12:55:14 -080065// bmc_host_sensor_value_double
66double ThermalController::inputProc(void)
Patrick Ventured8012182018-03-08 08:21:38 -080067{
James Feist734f9532018-11-15 12:13:18 -080068 double value;
69 const double& (*compare)(const double&, const double&);
70 if (type == ThermalType::margin)
71 {
72 value = std::numeric_limits<double>::max();
73 compare = std::min<double>;
74 }
75 else
76 {
77 value = std::numeric_limits<double>::lowest();
78 compare = std::max<double>;
79 }
80
Josh Lehanca791152020-09-20 23:41:39 -070081 bool acceptable = false;
James Feist734f9532018-11-15 12:13:18 -080082 for (const auto& in : _inputs)
83 {
Josh Lehanca791152020-09-20 23:41:39 -070084 double cachedValue = _owner->getCachedValue(in);
85
86 // Less than 0 is perfectly OK for temperature, but must not be NAN
87 if (!(std::isfinite(cachedValue)))
88 {
89 continue;
90 }
91
92 value = compare(value, cachedValue);
93 acceptable = true;
94 }
95
96 if (!acceptable)
97 {
98 // While not optimal, zero is better than garbage
99 value = 0;
James Feist734f9532018-11-15 12:13:18 -0800100 }
101
Bonnie Loc51ba912022-10-12 14:07:22 +0800102 if (debugEnabled)
103 {
104 std::cerr << getID() << " choose the temperature value: " << value
105 << "\n";
106 }
107
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800108 return value;
Patrick Ventured8012182018-03-08 08:21:38 -0800109}
110
111// bmc_get_setpt
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800112double ThermalController::setptProc(void)
Patrick Ventured8012182018-03-08 08:21:38 -0800113{
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800114 double setpoint = getSetpoint();
Patrick Ventured8012182018-03-08 08:21:38 -0800115
116 /* TODO(venture): Thermal setpoint invalid? */
117#if 0
118 if (-1 == setpoint)
119 {
120 return 0.0f;
121 }
122 else
123 {
124 return setpoint;
125 }
126#endif
127 return setpoint;
128}
129
130// bmc_set_pid_output
Patrick Venture5f59c0f2018-11-11 12:55:14 -0800131void ThermalController::outputProc(double value)
Patrick Ventured8012182018-03-08 08:21:38 -0800132{
Nirav Shahccc8bb62022-02-17 21:06:51 -0800133 _owner->addSetPoint(value, _id);
Patrick Ventured8012182018-03-08 08:21:38 -0800134
Bonnie Loc51ba912022-10-12 14:07:22 +0800135 if (debugEnabled)
136 {
137 std::cerr << getID() << " pid output pwm: " << value << "\n";
138 }
139
Patrick Ventured8012182018-03-08 08:21:38 -0800140 return;
141}
Patrick Venturea0764872020-08-08 07:48:43 -0700142
143} // namespace pid_control