2
* thd_model.h: thermal model class implementation
4
* Copyright (C) 2012 Intel Corporation. All rights reserved.
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License version
8
* 2 or later as published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
* Author Name <Srinivas.Pandruvada@linux.intel.com>
25
#include "thd_model.h"
26
#include "thd_engine.h"
39
* Dynamically adjust set point based on the amount of time spent on hot zone.
41
cthd_model::cthd_model(std::string _zone_type, bool use_pid) :
42
zone_type(_zone_type), trend_increase_start(0), max_temp(
43
def_max_temperature), set_point(def_max_temperature), hot_zone(
44
0), last_temp(0), trend_decrease_start(0), max_temp_reached(0), current_angle(
45
0), set_point_reached(false), delay_cnt(0), max_temp_seen(
46
false), updated_set_point(false), use_pid_param(use_pid), set_point_delay_start(
47
0), user_forced_set_point_change(false) {
49
// set default pid parameters
58
unsigned int cthd_model::update_set_point(unsigned int curr_temp) {
61
double delta_x = (max_temp_reached - trend_increase_start) * 1000;
62
double delta_y = max_temp - hot_zone;
67
if (delta_y > 0 && delta_x > 0) {
68
slope = delta_y / delta_x;
69
radians = atan(slope);
70
thd_log_info("current slope %g angle before %g (%g degree)\n",
71
slope, radians, 57.2957795 * radians);
72
radians += (0.01746 * (current_angle + angle_increment));
73
thd_log_info("current slope %g angle before %g (%g degree)\n",
74
slope, radians, 57.2957795 * radians);
75
arc_len = delta_x * tan(radians);
76
_setpoint = max_temp - (unsigned int) (arc_len - delta_y);
77
_setpoint = _setpoint - _setpoint % 1000;
78
thd_log_info("** set point x:%g y:%g arc_len:%g set_point %d\n",
79
delta_x, delta_y, arc_len, _setpoint);
81
|| (abs(set_point - _setpoint) > max_compensation))
82
set_point -= max_compensation;
84
set_point = _setpoint;
86
if (set_point < hot_zone)
89
current_angle += angle_increment;
102
time_t timeChange = (now - last_time);
104
int error = curr_temp - max_temp;
105
err_sum += (error * timeChange);
107
d_err = (error - last_err) / timeChange;
111
/*Compute PID Output*/
112
output = kp * error + ki * err_sum + kd * d_err;
113
_setpoint = max_temp - (unsigned int) output;
114
thd_log_info("update_pid %ld %ld %d %g %d\n", now, last_time, error,
116
if ((_setpoint < 0) || (abs(set_point - _setpoint) > max_compensation))
117
set_point -= max_compensation;
119
set_point = _setpoint;
121
/*Remember some variables for next time*/
129
void cthd_model::add_sample(int temperature) {
133
updated_set_point = false;
134
if (trend_increase_start == 0 && temperature > hot_zone) {
135
trend_increase_start = tm;
136
thd_log_debug("Trend increase start %ld\n", trend_increase_start);
137
} else if (trend_increase_start && temperature < hot_zone) {
139
thd_log_debug("Trend increase stopped %ld\n", trend_increase_start);
140
trend_increase_start = 0;
141
_set_point = read_set_point(); // Restore set point to a calculated max
142
if (_set_point > set_point) {
143
set_point = _set_point;
144
updated_set_point = true;
147
err_sum = last_err = 0.0;
151
if (temperature > max_temp) {
152
max_temp_reached = tm;
153
// Very first time when we reached max temp
154
// then we need to start tuning
155
if (!max_temp_seen) {
157
update_set_point(temperature);
158
_set_point = read_set_point();
159
// Update only if the current set point is more than
161
if (_set_point == 0 || set_point > _set_point)
163
max_temp_seen = true;
165
// Give some time to cooling device to cool, after that set next set point
166
if (set_point_delay_start
167
&& (tm - set_point_delay_start) >= set_point_delay_tm
168
&& (last_temp < temperature))
169
update_set_point(temperature);
171
if (!set_point_delay_start)
172
set_point_delay_start = tm;
173
set_point_reached = true;
175
set_point_reached = false;
177
set_point_delay_start = 0;
179
if (user_forced_set_point_change) {
180
user_forced_set_point_change = false;
181
set_point_reached = true;
183
last_temp = temperature;
184
thd_log_debug("update_set_point %u,%d,%u\n", last_temp, current_angle,
188
void cthd_model::store_set_point() {
189
std::stringstream filename;
191
filename << TDRUNDIR << "/" << "thermal_set_point." << zone_type << "."
193
std::ofstream fout(filename.str().c_str());
197
thd_log_info("storing set point %d\n", set_point);
201
int cthd_model::read_set_point() {
202
std::stringstream filename;
203
unsigned int _set_point = 0;
205
filename << TDRUNDIR << "/" << "thermal_set_point." << zone_type << "."
207
std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
212
thd_log_info("Read set point %u\n", _set_point);
217
void cthd_model::set_max_temperature(int temp) {
219
int user_defined_max;
221
max_temp = temp - safety_margin;
222
user_defined_max = read_user_set_max_temp();
223
if (user_defined_max > 0)
224
max_temp = user_defined_max;
225
_set_point = read_set_point();
226
if (_set_point > 0 && _set_point < max_temp) {
227
set_point = _set_point;
229
set_point = max_temp;
231
hot_zone = max_temp - ((max_temp * hot_zone_percent) / 100);
234
bool cthd_model::update_user_set_max_temp() {
235
std::stringstream filename;
236
bool present = false;
239
filename << TDRUNDIR << "/" << "thd_user_set_max." << zone_type << "."
241
std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
246
set_point = max_temp;
247
hot_zone = max_temp - ((max_temp * hot_zone_percent) / 100);
250
user_forced_set_point_change = true;
251
thd_log_info("User forced maximum temperature is %d\n", max_temp);
259
int cthd_model::read_user_set_max_temp() {
260
std::stringstream filename;
261
unsigned int user_max = 0;
263
filename << TDRUNDIR << "/" << "thd_user_set_max." << zone_type << "."
265
std::ifstream ifs(filename.str().c_str(), std::ifstream::in);
268
thd_log_info("User defined max temperature %u\n", user_max);