Improve fan curve

- Implement fan cooldown and heatup periods
- Add fan get/set commands
- Fix compilation with logging level lower than debug
This commit is contained in:
Jeremy Soller
2020-04-03 19:25:25 -06:00
parent 4fdb9ecbdc
commit 62a909ee81
13 changed files with 350 additions and 46 deletions

View File

@ -7,6 +7,12 @@
#include <ec/gpio.h>
#include <ec/pwm.h>
// Fan speed is the lowest requested over HEATUP seconds
#define HEATUP 5
// Fan speed is the highest HEATUP speed over COOLDOWN seconds
#define COOLDOWN 10
// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
#define T_JUNCTION 100
@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = {
FAN_POINT(70, 45),
FAN_POINT(75, 55),
FAN_POINT(80, 75),
FAN_POINT(84, 100),
FAN_POINT(84, 100)
};
// Get duty cycle based on temperature, adapted from
@ -51,12 +57,14 @@ uint8_t fan_duty(int16_t temp) {
// If in between current temp and previous temp, interpolate
if (temp > prev->temp) {
int16_t dtemp = (cur->temp - prev->temp);
int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
return (uint8_t)(
((int16_t)prev->duty) +
((temp - prev->temp) * dduty) / dtemp
);
return prev->duty;
// int16_t dtemp = (cur->temp - prev->temp);
// int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
// return (uint8_t)(
// ((int16_t)prev->duty) +
// ((temp - prev->temp) * dduty) / dtemp
// );
}
}
}
@ -66,6 +74,40 @@ uint8_t fan_duty(int16_t temp) {
return PWM_DUTY(100);
}
uint8_t fan_heatup(uint8_t duty) {
static uint8_t history[HEATUP] = { 0 };
uint8_t lowest = duty;
int i;
for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) {
uint8_t value = history[i + 1];
if (value < lowest) {
lowest = value;
}
history[i] = value;
}
history[i] = duty;
return lowest;
}
uint8_t fan_cooldown(uint8_t duty) {
static uint8_t history[COOLDOWN] = { 0 };
uint8_t highest = duty;
int i;
for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) {
uint8_t value = history[i + 1];
if (value > highest) {
highest = value;
}
history[i] = value;
}
history[i] = duty;
return highest;
}
void peci_init(void) {
// Allow PECI pin to be used
GCR2 |= (1 << 4);
@ -123,8 +165,10 @@ void peci_event(void) {
peci_duty = PWM_DUTY(0);
}
if (peci_duty != DCR2) {
DCR2 = peci_duty;
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty);
uint8_t heatup_duty = fan_heatup(peci_duty);
uint8_t cooldown_duty = fan_cooldown(heatup_duty);
if (cooldown_duty != DCR2) {
DCR2 = cooldown_duty;
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty);
}
}

View File

@ -386,11 +386,10 @@ void power_event(void) {
// state is S3
static bool ack_last = false;
bool ack_new = gpio_get(&SUSWARN_N);
if (ack_new && !ack_last) {
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
}
#if LEVEL >= LEVEL_DEBUG
else if (!ack_new && ack_last) {
if (ack_new && !ack_last) {
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
} else if (!ack_new && ack_last) {
DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
}
#endif

View File

@ -9,6 +9,7 @@
#include <common/command.h>
#include <common/macro.h>
#include <common/version.h>
#include <ec/pwm.h>
// Shared memory host semaphore
volatile uint8_t __xdata __at(0x1022) SMHSR;
@ -143,6 +144,30 @@ static enum Result cmd_reset(void) {
return RES_ERR;
}
static enum Result cmd_fan_get(void) {
// If setting fan 0
if (smfi_cmd[2] == 0) {
// Get duty of fan 0
smfi_cmd[3] = DCR2;
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_fan_set(void) {
// If setting fan 0
if (smfi_cmd[2] == 0) {
// Set duty cycle of fan 0
DCR2 = smfi_cmd[3];
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
void smfi_event(void) {
if (smfi_cmd[0]) {
switch (smfi_cmd[0]) {
@ -174,6 +199,14 @@ void smfi_event(void) {
case CMD_RESET:
smfi_cmd[1] = cmd_reset();
break;
#ifndef __SCRATCH__
case CMD_FAN_GET:
smfi_cmd[1] = cmd_fan_get();
break;
case CMD_FAN_SET:
smfi_cmd[1] = cmd_fan_set();
break;
#endif // __SCRATCH__
default:
// Command not found
smfi_cmd[1] = RES_ERR;

View File

@ -7,6 +7,12 @@
#include <ec/gpio.h>
#include <ec/pwm.h>
// Fan speed is the lowest requested over HEATUP seconds
#define HEATUP 5
// Fan speed is the highest HEATUP speed over COOLDOWN seconds
#define COOLDOWN 10
// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
#define T_JUNCTION 100
@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = {
FAN_POINT(70, 45),
FAN_POINT(75, 55),
FAN_POINT(80, 75),
FAN_POINT(84, 100),
FAN_POINT(84, 100)
};
// Get duty cycle based on temperature, adapted from
@ -51,12 +57,14 @@ uint8_t fan_duty(int16_t temp) {
// If in between current temp and previous temp, interpolate
if (temp > prev->temp) {
int16_t dtemp = (cur->temp - prev->temp);
int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
return (uint8_t)(
((int16_t)prev->duty) +
((temp - prev->temp) * dduty) / dtemp
);
return prev->duty;
// int16_t dtemp = (cur->temp - prev->temp);
// int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
// return (uint8_t)(
// ((int16_t)prev->duty) +
// ((temp - prev->temp) * dduty) / dtemp
// );
}
}
}
@ -66,6 +74,40 @@ uint8_t fan_duty(int16_t temp) {
return PWM_DUTY(100);
}
uint8_t fan_heatup(uint8_t duty) {
static uint8_t history[HEATUP] = { 0 };
uint8_t lowest = duty;
int i;
for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) {
uint8_t value = history[i + 1];
if (value < lowest) {
lowest = value;
}
history[i] = value;
}
history[i] = duty;
return lowest;
}
uint8_t fan_cooldown(uint8_t duty) {
static uint8_t history[COOLDOWN] = { 0 };
uint8_t highest = duty;
int i;
for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) {
uint8_t value = history[i + 1];
if (value > highest) {
highest = value;
}
history[i] = value;
}
history[i] = duty;
return highest;
}
void peci_init(void) {
// Allow PECI pin to be used
GCR2 |= (1 << 4);
@ -123,8 +165,10 @@ void peci_event(void) {
peci_duty = PWM_DUTY(0);
}
if (peci_duty != DCR2) {
DCR2 = peci_duty;
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty);
uint8_t heatup_duty = fan_heatup(peci_duty);
uint8_t cooldown_duty = fan_cooldown(heatup_duty);
if (cooldown_duty != DCR2) {
DCR2 = cooldown_duty;
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty);
}
}

View File

@ -383,11 +383,10 @@ void power_event(void) {
// state is S3
static bool ack_last = false;
bool ack_new = gpio_get(&SUSWARN_N);
if (ack_new && !ack_last) {
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
}
#if LEVEL >= LEVEL_DEBUG
else if (!ack_new && ack_last) {
if (ack_new && !ack_last) {
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
} else if (!ack_new && ack_last) {
DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
}
#endif

View File

@ -9,6 +9,7 @@
#include <common/command.h>
#include <common/macro.h>
#include <common/version.h>
#include <ec/pwm.h>
// Shared memory host semaphore
volatile uint8_t __xdata __at(0x1022) SMHSR;
@ -143,6 +144,30 @@ static enum Result cmd_reset(void) {
return RES_ERR;
}
static enum Result cmd_fan_get(void) {
// If setting fan 0
if (smfi_cmd[2] == 0) {
// Get duty of fan 0
smfi_cmd[3] = DCR2;
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_fan_set(void) {
// If setting fan 0
if (smfi_cmd[2] == 0) {
// Set duty cycle of fan 0
DCR2 = smfi_cmd[3];
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
void smfi_event(void) {
if (smfi_cmd[0]) {
switch (smfi_cmd[0]) {
@ -174,6 +199,14 @@ void smfi_event(void) {
case CMD_RESET:
smfi_cmd[1] = cmd_reset();
break;
#ifndef __SCRATCH__
case CMD_FAN_GET:
smfi_cmd[1] = cmd_fan_get();
break;
case CMD_FAN_SET:
smfi_cmd[1] = cmd_fan_set();
break;
#endif // __SCRATCH__
default:
// Command not found
smfi_cmd[1] = RES_ERR;

View File

@ -7,6 +7,12 @@
#include <ec/gpio.h>
#include <ec/pwm.h>
// Fan speed is the lowest requested over HEATUP seconds
#define HEATUP 5
// Fan speed is the highest HEATUP speed over COOLDOWN seconds
#define COOLDOWN 10
// Tjunction = 100C for i7-8565U (and probably the same for all WHL-U)
#define T_JUNCTION 100
@ -30,7 +36,7 @@ struct FanPoint __code FAN_POINTS[] = {
FAN_POINT(70, 45),
FAN_POINT(75, 55),
FAN_POINT(80, 75),
FAN_POINT(84, 100),
FAN_POINT(84, 100)
};
// Get duty cycle based on temperature, adapted from
@ -51,12 +57,14 @@ uint8_t fan_duty(int16_t temp) {
// If in between current temp and previous temp, interpolate
if (temp > prev->temp) {
int16_t dtemp = (cur->temp - prev->temp);
int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
return (uint8_t)(
((int16_t)prev->duty) +
((temp - prev->temp) * dduty) / dtemp
);
return prev->duty;
// int16_t dtemp = (cur->temp - prev->temp);
// int16_t dduty = ((int16_t)cur->duty) - ((int16_t)prev->duty);
// return (uint8_t)(
// ((int16_t)prev->duty) +
// ((temp - prev->temp) * dduty) / dtemp
// );
}
}
}
@ -66,6 +74,40 @@ uint8_t fan_duty(int16_t temp) {
return PWM_DUTY(100);
}
uint8_t fan_heatup(uint8_t duty) {
static uint8_t history[HEATUP] = { 0 };
uint8_t lowest = duty;
int i;
for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) {
uint8_t value = history[i + 1];
if (value < lowest) {
lowest = value;
}
history[i] = value;
}
history[i] = duty;
return lowest;
}
uint8_t fan_cooldown(uint8_t duty) {
static uint8_t history[COOLDOWN] = { 0 };
uint8_t highest = duty;
int i;
for (i = 0; (i + 1) < ARRAY_SIZE(history); i++) {
uint8_t value = history[i + 1];
if (value > highest) {
highest = value;
}
history[i] = value;
}
history[i] = duty;
return highest;
}
void peci_init(void) {
// Allow PECI pin to be used
GCR2 |= (1 << 4);
@ -123,8 +165,10 @@ void peci_event(void) {
peci_duty = PWM_DUTY(0);
}
if (peci_duty != DCR2) {
DCR2 = peci_duty;
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, peci_duty);
uint8_t heatup_duty = fan_heatup(peci_duty);
uint8_t cooldown_duty = fan_cooldown(heatup_duty);
if (cooldown_duty != DCR2) {
DCR2 = cooldown_duty;
DEBUG("PECI offset=%d, temp=%d = %d\n", peci_offset, peci_temp, cooldown_duty);
}
}

View File

@ -383,11 +383,10 @@ void power_event(void) {
// state is S3
static bool ack_last = false;
bool ack_new = gpio_get(&SUSWARN_N);
if (ack_new && !ack_last) {
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
}
#if LEVEL >= LEVEL_DEBUG
else if (!ack_new && ack_last) {
if (ack_new && !ack_last) {
DEBUG("%02X: SUSPWRDNACK asserted\n", main_cycle);
} else if (!ack_new && ack_last) {
DEBUG("%02X: SUSPWRDNACK de-asserted\n", main_cycle);
}
#endif

View File

@ -9,6 +9,7 @@
#include <common/command.h>
#include <common/macro.h>
#include <common/version.h>
#include <ec/pwm.h>
// Shared memory host semaphore
volatile uint8_t __xdata __at(0x1022) SMHSR;
@ -143,6 +144,30 @@ static enum Result cmd_reset(void) {
return RES_ERR;
}
static enum Result cmd_fan_get(void) {
// If setting fan 0
if (smfi_cmd[2] == 0) {
// Get duty of fan 0
smfi_cmd[3] = DCR2;
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
static enum Result cmd_fan_set(void) {
// If setting fan 0
if (smfi_cmd[2] == 0) {
// Set duty cycle of fan 0
DCR2 = smfi_cmd[3];
return RES_OK;
}
// Failed if fan not found
return RES_ERR;
}
void smfi_event(void) {
if (smfi_cmd[0]) {
switch (smfi_cmd[0]) {
@ -174,6 +199,14 @@ void smfi_event(void) {
case CMD_RESET:
smfi_cmd[1] = cmd_reset();
break;
#ifndef __SCRATCH__
case CMD_FAN_GET:
smfi_cmd[1] = cmd_fan_get();
break;
case CMD_FAN_SET:
smfi_cmd[1] = cmd_fan_set();
break;
#endif // __SCRATCH__
default:
// Command not found
smfi_cmd[1] = RES_ERR;

View File

@ -16,6 +16,10 @@ enum Command {
CMD_SPI = 5,
// Reset EC
CMD_RESET = 6,
// Get fan speeds
CMD_FAN_GET = 7,
// Set fan speeds
CMD_FAN_SET = 8,
//TODO
};