mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
The existing algorithm makes several assumptions for a particular thermistor circuit. This patch introduces a more generic version that can be used for multiple thermistors on a single board. The idea is to approximate a curve produced by solving for voltage measued by an ADC using the Steinhart-Hart equation. For a straight line one only needs two data points. For a steady curve data points can be distributed evenly. For the most part, though, data points should be provided after a significant change in slope. More data points give more accuracy at the expense of memory, and we mostly only care about accuracy in the range between "warm" and "too hot" so only a few data points should be used. BUG=chrome-os-partner:54818 BRANCH=none TEST=added unit test, needs real testing Change-Id: I046e61dbfd1e8c26c2a533777f222f5413938556 Signed-off-by: David Hendricks <dhendrix@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/344781 Reviewed-by: Shawn N <shawnn@chromium.org>
660 lines
14 KiB
C
660 lines
14 KiB
C
/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
* Test thermal engine.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "console.h"
|
|
#include "driver/temp_sensor/thermistor.h"
|
|
#include "fan.h"
|
|
#include "hooks.h"
|
|
#include "host_command.h"
|
|
#include "printf.h"
|
|
#include "temp_sensor.h"
|
|
#include "test_util.h"
|
|
#include "thermal.h"
|
|
#include "timer.h"
|
|
#include "util.h"
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Exported data */
|
|
|
|
struct ec_thermal_config thermal_params[TEMP_SENSOR_COUNT];
|
|
|
|
/* The tests below make some assumptions. */
|
|
BUILD_ASSERT(TEMP_SENSOR_COUNT == 4);
|
|
BUILD_ASSERT(EC_TEMP_THRESH_COUNT == 3);
|
|
|
|
/*****************************************************************************/
|
|
/* Mock functions */
|
|
|
|
static int mock_temp[TEMP_SENSOR_COUNT];
|
|
static int host_throttled;
|
|
static int cpu_throttled;
|
|
static int cpu_shutdown;
|
|
static int fan_pct;
|
|
static int no_temps_read;
|
|
|
|
int dummy_temp_get_val(int idx, int *temp_ptr)
|
|
{
|
|
if (mock_temp[idx] >= 0) {
|
|
*temp_ptr = mock_temp[idx];
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
return EC_ERROR_NOT_POWERED;
|
|
}
|
|
|
|
void chipset_force_shutdown(void)
|
|
{
|
|
cpu_shutdown = 1;
|
|
}
|
|
|
|
void chipset_throttle_cpu(int throttled)
|
|
{
|
|
cpu_throttled = throttled;
|
|
}
|
|
|
|
void host_throttle_cpu(int throttled)
|
|
{
|
|
host_throttled = throttled;
|
|
}
|
|
|
|
void fan_set_percent_needed(int fan, int pct)
|
|
{
|
|
fan_pct = pct;
|
|
}
|
|
|
|
void smi_sensor_failure_warning(void)
|
|
{
|
|
no_temps_read = 1;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* Test utilities */
|
|
|
|
static void set_temps(int t0, int t1, int t2, int t3)
|
|
{
|
|
mock_temp[0] = t0;
|
|
mock_temp[1] = t1;
|
|
mock_temp[2] = t2;
|
|
mock_temp[3] = t3;
|
|
}
|
|
|
|
static void all_temps(int t)
|
|
{
|
|
set_temps(t, t, t, t);
|
|
}
|
|
|
|
static void reset_mocks(void)
|
|
{
|
|
/* Ignore all sensors */
|
|
memset(thermal_params, 0, sizeof(thermal_params));
|
|
|
|
/* All sensors report error anyway */
|
|
set_temps(-1, -1 , -1, -1);
|
|
|
|
/* Reset expectations */
|
|
host_throttled = 0;
|
|
cpu_throttled = 0;
|
|
cpu_shutdown = 0;
|
|
fan_pct = 0;
|
|
no_temps_read = 0;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Tests */
|
|
|
|
static int test_init_val(void)
|
|
{
|
|
reset_mocks();
|
|
sleep(2);
|
|
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
TEST_ASSERT(no_temps_read);
|
|
|
|
sleep(2);
|
|
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
TEST_ASSERT(no_temps_read);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_sensors_can_be_read(void)
|
|
{
|
|
reset_mocks();
|
|
mock_temp[2] = 100;
|
|
|
|
sleep(2);
|
|
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
TEST_ASSERT(no_temps_read == 0);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
|
|
static int test_one_fan(void)
|
|
{
|
|
reset_mocks();
|
|
thermal_params[2].temp_fan_off = 100;
|
|
thermal_params[2].temp_fan_max = 200;
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(101);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 1);
|
|
|
|
all_temps(130);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 30);
|
|
|
|
all_temps(150);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
all_temps(170);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 70);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(300);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_two_fans(void)
|
|
{
|
|
reset_mocks();
|
|
|
|
thermal_params[1].temp_fan_off = 120;
|
|
thermal_params[1].temp_fan_max = 160;
|
|
thermal_params[2].temp_fan_off = 100;
|
|
thermal_params[2].temp_fan_max = 200;
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(101);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 1);
|
|
|
|
all_temps(130);
|
|
sleep(2);
|
|
/* fan 2 is still higher */
|
|
TEST_ASSERT(fan_pct == 30);
|
|
|
|
all_temps(150);
|
|
sleep(2);
|
|
/* now fan 1 is higher: 150 = 75% of [120-160] */
|
|
TEST_ASSERT(fan_pct == 75);
|
|
|
|
all_temps(170);
|
|
sleep(2);
|
|
/* fan 1 is maxed now */
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(300);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_all_fans(void)
|
|
{
|
|
reset_mocks();
|
|
|
|
thermal_params[0].temp_fan_off = 20;
|
|
thermal_params[0].temp_fan_max = 60;
|
|
thermal_params[1].temp_fan_off = 120;
|
|
thermal_params[1].temp_fan_max = 160;
|
|
thermal_params[2].temp_fan_off = 100;
|
|
thermal_params[2].temp_fan_max = 200;
|
|
thermal_params[3].temp_fan_off = 300;
|
|
thermal_params[3].temp_fan_max = 500;
|
|
|
|
set_temps(1, 1, 1, 1);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
/* Each sensor has its own range */
|
|
set_temps(40, 0, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(0, 140, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(0, 0, 150, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(0, 0, 0, 400);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
set_temps(60, 0, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
set_temps(0, 160, 0, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
set_temps(0, 0, 200, 0);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
set_temps(0, 0, 0, 500);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
/* But sensor 0 needs the most cooling */
|
|
all_temps(20);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 0);
|
|
|
|
all_temps(21);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 2);
|
|
|
|
all_temps(30);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 25);
|
|
|
|
all_temps(40);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 50);
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 75);
|
|
|
|
all_temps(60);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
all_temps(65);
|
|
sleep(2);
|
|
TEST_ASSERT(fan_pct == 100);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_one_limit(void)
|
|
{
|
|
reset_mocks();
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_WARN] = 100;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HALT] = 300;
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(101);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(100);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(99);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(199);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(201);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(200);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(199);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(99);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(201);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(99);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
all_temps(301);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
|
|
/* We probably won't be able to read the CPU temp while shutdown,
|
|
* so nothing will change. */
|
|
all_temps(-1);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
/* cpu_shutdown is only set for testing purposes. The thermal task
|
|
* doesn't do anything that could clear it. */
|
|
|
|
all_temps(50);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
static int test_several_limits(void)
|
|
{
|
|
reset_mocks();
|
|
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_WARN] = 150;
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[1].temp_host[EC_TEMP_THRESH_HALT] = 250;
|
|
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_WARN] = 100;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HIGH] = 200;
|
|
thermal_params[2].temp_host[EC_TEMP_THRESH_HALT] = 300;
|
|
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_WARN] = 20;
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_HIGH] = 30;
|
|
thermal_params[3].temp_host[EC_TEMP_THRESH_HALT] = 40;
|
|
|
|
set_temps(500, 100, 150, 10);
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1); /* 1=low, 2=warn, 3=low */
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 50, -1, 10); /* 1=low, 2=X, 3=low */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 170, 210, 10); /* 1=warn, 2=high, 3=low */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 100, 50, 40); /* 1=low, 2=low, 3=high */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 0);
|
|
|
|
set_temps(500, 100, 50, 41); /* 1=low, 2=low, 3=shutdown */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 1);
|
|
TEST_ASSERT(cpu_throttled == 1);
|
|
TEST_ASSERT(cpu_shutdown == 1);
|
|
|
|
all_temps(0); /* reset from shutdown */
|
|
sleep(2);
|
|
TEST_ASSERT(host_throttled == 0);
|
|
TEST_ASSERT(cpu_throttled == 0);
|
|
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
/* Tests for ncp15wb thermistor ADC-to-temp calculation */
|
|
#define LOW_ADC_TEST_VALUE 887 /* 0 C */
|
|
#define HIGH_ADC_TEST_VALUE 100 /* > 100C */
|
|
|
|
static int test_ncp15wb_adc_to_temp(void)
|
|
{
|
|
int i;
|
|
uint8_t temp;
|
|
uint8_t new_temp;
|
|
|
|
/* ADC value to temperature table, data from datasheet */
|
|
struct {
|
|
int adc;
|
|
int temp;
|
|
} adc_temp_datapoints[] = {
|
|
{ 615, 30 },
|
|
{ 561, 35 },
|
|
{ 508, 40 },
|
|
{ 407, 50 },
|
|
{ 315, 60 },
|
|
{ 243, 70 },
|
|
{ 186, 80 },
|
|
{ 140, 90 },
|
|
{ 107, 100 },
|
|
};
|
|
|
|
|
|
/*
|
|
* Verify that calculated temp is decreasing for entire ADC range,
|
|
* and that a tick down in ADC value results in no more than 1C
|
|
* decrease.
|
|
*/
|
|
i = LOW_ADC_TEST_VALUE;
|
|
temp = ncp15wb_calculate_temp(i);
|
|
|
|
while (--i > HIGH_ADC_TEST_VALUE) {
|
|
new_temp = ncp15wb_calculate_temp(i);
|
|
TEST_ASSERT(new_temp == temp ||
|
|
new_temp == temp + 1);
|
|
temp = new_temp;
|
|
}
|
|
|
|
/* Verify several datapoints are within 1C accuracy */
|
|
for (i = 0; i < ARRAY_SIZE(adc_temp_datapoints); ++i) {
|
|
temp = ncp15wb_calculate_temp(adc_temp_datapoints[i].adc);
|
|
ASSERT(temp >= adc_temp_datapoints[i].temp - 1 &&
|
|
temp <= adc_temp_datapoints[i].temp + 1);
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
#define THERMISTOR_SCALING_FACTOR 13
|
|
static int test_thermistor_linear_interpolate(void)
|
|
{
|
|
int i, t, t0;
|
|
uint16_t mv;
|
|
/* Simple test case - a straight line. */
|
|
struct thermistor_data_pair line_data[] = {
|
|
{ 0, 0 }, { 100, 100 }
|
|
};
|
|
struct thermistor_info line_info = {
|
|
.scaling_factor = 1,
|
|
.num_pairs = ARRAY_SIZE(line_data),
|
|
.data = line_data,
|
|
};
|
|
/*
|
|
* Modelled test case - Data derived from Seinhart-Hart equation in a
|
|
* resistor divider circuit with Vdd=3300mV, R = 51.1Kohm, and Murata
|
|
* NCP15WB-series thermistor (B = 4050, T0 = 298.15, nominal
|
|
* resistance (R0) = 47Kohm).
|
|
*/
|
|
struct thermistor_data_pair data[] = {
|
|
{ 787 / THERMISTOR_SCALING_FACTOR, 0 },
|
|
{ 1142 / THERMISTOR_SCALING_FACTOR, 10 },
|
|
{ 1528 / THERMISTOR_SCALING_FACTOR, 20 },
|
|
{ 1901 / THERMISTOR_SCALING_FACTOR, 30 },
|
|
{ 2229 / THERMISTOR_SCALING_FACTOR, 40 },
|
|
{ 2497 / THERMISTOR_SCALING_FACTOR, 50 },
|
|
{ 2703 / THERMISTOR_SCALING_FACTOR, 60 },
|
|
{ 2857 / THERMISTOR_SCALING_FACTOR, 70 },
|
|
{ 2970 / THERMISTOR_SCALING_FACTOR, 80 },
|
|
{ 3053 / THERMISTOR_SCALING_FACTOR, 90 },
|
|
{ 3113 / THERMISTOR_SCALING_FACTOR, 100 },
|
|
};
|
|
struct thermistor_info info = {
|
|
.scaling_factor = THERMISTOR_SCALING_FACTOR,
|
|
.num_pairs = ARRAY_SIZE(data),
|
|
.data = data,
|
|
};
|
|
/*
|
|
* Reference data points to compare accuracy, taken from same set
|
|
* of derived values but at temp - 1, temp + 1, and in between.
|
|
*/
|
|
struct {
|
|
uint16_t mv; /* not scaled */
|
|
int temp;
|
|
} cmp[] = {
|
|
{ 820, 1 }, { 958, 5 }, { 1104, 9 },
|
|
{ 1180, 11 }, { 1334, 15 }, { 1489, 19 },
|
|
{ 1566, 21 }, { 1718, 25 }, { 1866, 29 },
|
|
{ 1937, 31 }, { 2073, 35 }, { 2199, 39 },
|
|
{ 2259, 41 }, { 2371, 45 }, { 2473, 49 },
|
|
{ 2520, 51 }, { 2607, 55 }, { 2685, 59 },
|
|
{ 2720, 61 }, { 2786, 65 }, { 2844, 69 },
|
|
{ 2870, 71 }, { 2918, 75 }, { 2960, 79 },
|
|
{ 2980, 81 }, { 3015, 85 }, { 3045, 89 },
|
|
{ 3060, 91 }, { 3085, 95 }, { 3107, 99 },
|
|
};
|
|
|
|
/* Return lowest temperature in data set if voltage is too low. */
|
|
mv = (data[0].mv * info.scaling_factor) - 1;
|
|
t = thermistor_linear_interpolate(mv, &info);
|
|
TEST_ASSERT(t == data[0].temp);
|
|
|
|
/* Return highest temperature in data set if voltage is too high. */
|
|
mv = (data[info.num_pairs - 1].mv * info.scaling_factor) + 1;
|
|
t = thermistor_linear_interpolate(mv, &info);
|
|
TEST_ASSERT(t == data[info.num_pairs - 1].temp);
|
|
|
|
/* Simple line test */
|
|
for (mv = line_data[0].mv;
|
|
mv < line_data[line_info.num_pairs - 1].mv;
|
|
mv++) {
|
|
t = thermistor_linear_interpolate(mv, &line_info);
|
|
TEST_ASSERT(mv == t);
|
|
}
|
|
|
|
/*
|
|
* Verify that calculated temperature monotonically
|
|
* increases with voltage (0-5V, 10mV steps).
|
|
*/
|
|
for (mv = data[0].mv * info.scaling_factor, t0 = data[0].temp;
|
|
mv < data[info.num_pairs - 1].mv;
|
|
mv += 10) {
|
|
int t1 = thermistor_linear_interpolate(mv, &info);
|
|
|
|
TEST_ASSERT(t1 >= t0);
|
|
t0 = t1;
|
|
}
|
|
|
|
/* Verify against modelled data, +/- 1C due to scaling. */
|
|
for (i = 0; i < info.num_pairs; i++) {
|
|
mv = data[i].mv * info.scaling_factor;
|
|
|
|
t = thermistor_linear_interpolate(mv, &info);
|
|
TEST_ASSERT(t >= data[i].temp - 1 && t <= data[i].temp + 1);
|
|
}
|
|
|
|
/*
|
|
* Verify data points that are interpolated by algorithm, allowing
|
|
* 1C of inaccuracy.
|
|
*/
|
|
for (i = 0; i < ARRAY_SIZE(cmp); i++) {
|
|
t = thermistor_linear_interpolate(cmp[i].mv, &info);
|
|
TEST_ASSERT(t >= cmp[i].temp - 1 && t <= cmp[i].temp + 1);
|
|
}
|
|
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
void run_test(void)
|
|
{
|
|
RUN_TEST(test_init_val);
|
|
RUN_TEST(test_sensors_can_be_read);
|
|
RUN_TEST(test_one_fan);
|
|
RUN_TEST(test_two_fans);
|
|
RUN_TEST(test_all_fans);
|
|
|
|
RUN_TEST(test_one_limit);
|
|
RUN_TEST(test_several_limits);
|
|
|
|
RUN_TEST(test_ncp15wb_adc_to_temp);
|
|
RUN_TEST(test_thermistor_linear_interpolate);
|
|
test_print_result();
|
|
}
|