Skip to content

Commit

Permalink
fan: Track table level, split up/down curves
Browse files Browse the repository at this point in the history
Replace calculating the duty on every update with tracking the level in
the fan tables to use. A second temperature column is added to the table
to allow different curves for heating up and cooling down.

Signed-off-by: Tim Crawford <[email protected]>
  • Loading branch information
crawfxrd committed Aug 6, 2024
1 parent 17050c4 commit e7e4670
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 71 deletions.
104 changes: 59 additions & 45 deletions src/board/system76/common/fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@

bool fan_max = false;

static uint8_t fan1_level = 0;
#ifdef FAN2_PWM
static uint8_t fan2_level = 0;
#endif

struct FanInfo fan1_info = {
.pwm_actual = 0,
.pwm_target = 0,
Expand Down Expand Up @@ -38,29 +43,6 @@ void fan_reset(void) {
fan_max = false;
}

// Get duty cycle based on temperature
static uint8_t fan_duty(const struct Fan *const fan, int16_t temp) {
for (uint8_t i = 0; i < fan->points_size; i++) {
const struct FanPoint *cur = &fan->points[i];

// If exactly the current temp, return the current duty
if (temp == cur->temp) {
return cur->duty;
} else if (temp < cur->temp) {
// If lower than first temp, return 0%
if (i == 0) {
return 0;
} else {
const struct FanPoint *prev = &fan->points[i - 1];
return prev->duty;
}
}
}

// If no point is found, return 100%
return CTR0;
}

static uint16_t fan_get_tach0_rpm(void) {
uint16_t rpm = (F1TMRR << 8) | F1TLRR;

Expand Down Expand Up @@ -92,26 +74,42 @@ void fan_event(void) {
// Enabling fan max toggle and exiting S0 will cause duty to immediately
// change instead of ramping to provide the desired effects.

// Get FAN1 target duty
if (fan1_level < FAN1.levels_size) {
if (sys_temp >= FAN1.levels[fan1_level].temp_up) {
fan1_level++;
}
}
if (fan1_level > 0) {
if (sys_temp <= FAN1.levels[fan1_level].temp_down) {
fan1_level--;
}
}

fan1_info.pwm_target = FAN1.levels[fan1_level].duty;

// Set FAN1 duty
fan1_info.pwm_target = fan_duty(&FAN1, sys_temp);
if (fan_max) {
fan1_info.pwm_target = CTR0;
fan1_info.pwm_actual = CTR0;
} else if (power_state != POWER_STATE_S0) {
fan1_info.pwm_target = 0;
fan1_info.pwm_actual = 0;
} else if (fan1_info.pwm_actual < fan1_info.pwm_target) {
if (fan1_info.pwm_actual < CTR0) {
fan1_info.pwm_actual++;
if (fan1_info.pwm_actual < FAN1.pwm_min) {
fan1_info.pwm_actual = FAN1.pwm_min;
} else {
if (fan1_info.pwm_actual < fan1_info.pwm_target) {
if (fan1_info.pwm_actual < CTR0) {
fan1_info.pwm_actual++;
if (fan1_info.pwm_actual < FAN1.pwm_min) {
fan1_info.pwm_actual = FAN1.pwm_min;
}
}
}
} else if (fan1_info.pwm_actual > fan1_info.pwm_target) {
if (fan1_info.pwm_actual > 0) {
fan1_info.pwm_actual--;
if (fan1_info.pwm_actual < FAN1.pwm_min) {
fan1_info.pwm_actual = 0;
if (fan1_info.pwm_actual > fan1_info.pwm_target) {
if (fan1_info.pwm_actual > 0) {
fan1_info.pwm_actual--;
if (fan1_info.pwm_actual < FAN1.pwm_min) {
fan1_info.pwm_actual = 0;
}
}
}
}
Expand All @@ -120,26 +118,42 @@ void fan_event(void) {
fan1_info.rpm = fan_get_tach0_rpm();

#ifdef FAN2_PWM
// Get FAN2 target duty
if (fan2_level < FAN2.levels_size) {
if (sys_temp >= FAN2.levels[fan2_level].temp_up) {
fan2_level++;
}
}
if (fan2_level > 0) {
if (sys_temp <= FAN2.levels[fan2_level].temp_down) {
fan2_level--;
}
}

fan2_info.pwm_target = FAN2.levels[fan2_level].duty;

// set FAN2 duty
fan2_info.pwm_target = fan_duty(&FAN2, sys_temp);
if (fan_max) {
fan2_info.pwm_target = CTR0;
fan2_info.pwm_actual = CTR0;
} else if (power_state != POWER_STATE_S0) {
fan2_info.pwm_target = 0;
fan2_info.pwm_actual = 0;
} else if (fan2_info.pwm_actual < fan2_info.pwm_target) {
if (fan2_info.pwm_actual < CTR0) {
fan2_info.pwm_actual++;
if (fan2_info.pwm_actual < FAN2.pwm_min) {
fan2_info.pwm_actual = FAN2.pwm_min;
} else {
if (fan2_info.pwm_actual < fan2_info.pwm_target) {
if (fan2_info.pwm_actual < CTR0) {
fan2_info.pwm_actual++;
if (fan2_info.pwm_actual < FAN2.pwm_min) {
fan2_info.pwm_actual = FAN2.pwm_min;
}
}
}
} else if (fan2_info.pwm_actual > fan2_info.pwm_target) {
if (fan2_info.pwm_actual > 0) {
fan2_info.pwm_actual--;
if (fan2_info.pwm_actual < FAN2.pwm_min) {
fan2_info.pwm_actual = 0;
if (fan2_info.pwm_actual > fan2_info.pwm_target) {
if (fan2_info.pwm_actual > 0) {
fan2_info.pwm_actual--;
if (fan2_info.pwm_actual < FAN2.pwm_min) {
fan2_info.pwm_actual = 0;
}
}
}
}
Expand Down
11 changes: 5 additions & 6 deletions src/board/system76/common/include/board/fan.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@

#define PWM_DUTY(X) ((uint8_t)(((((uint16_t)(X)) * 255) + 99) / 100))

struct FanPoint {
const int16_t temp;
struct FanLevel {
const int16_t temp_up;
const int16_t temp_down;
const uint8_t duty;
};

#define FAN_POINT(T, D) { .temp = (int16_t)(T), .duty = PWM_DUTY(D) }

struct Fan {
const struct FanPoint *const points;
const uint8_t points_size;
const struct FanLevel *const levels;
const uint8_t levels_size;
const uint8_t pwm_min;
};

Expand Down
42 changes: 22 additions & 20 deletions src/board/system76/oryp6/fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,36 @@
#include <board/fan.h>
#include <common/macro.h>

static const struct FanPoint __code FAN1_POINTS[] = {
FAN_POINT(55, 25),
FAN_POINT(65, 30),
FAN_POINT(70, 40),
FAN_POINT(75, 60),
FAN_POINT(80, 75),
FAN_POINT(85, 90),
FAN_POINT(90, 100),
static const struct FanLevel __code fan1_table[] = {
{ 55, 0, PWM_DUTY(0) },
{ 60, 52, PWM_DUTY(25) },
{ 65, 60, PWM_DUTY(30) },
{ 70, 65, PWM_DUTY(40) },
{ 75, 70, PWM_DUTY(60) },
{ 80, 75, PWM_DUTY(75) },
{ 85, 80, PWM_DUTY(90) },
{ 90, 85, PWM_DUTY(100) },
};

const struct Fan __code FAN1 = {
.points = FAN1_POINTS,
.points_size = ARRAY_SIZE(FAN1_POINTS),
.levels = fan1_table,
.levels_size = ARRAY_SIZE(fan1_table),
.pwm_min = PWM_DUTY(25),
};

static const struct FanPoint __code FAN2_POINTS[] = {
FAN_POINT(55, 25),
FAN_POINT(65, 30),
FAN_POINT(70, 40),
FAN_POINT(75, 60),
FAN_POINT(80, 75),
FAN_POINT(85, 90),
FAN_POINT(90, 100),
static const struct FanLevel __code fan2_table[] = {
{ 55, 0, PWM_DUTY(0) },
{ 60, 52, PWM_DUTY(25) },
{ 65, 60, PWM_DUTY(30) },
{ 70, 65, PWM_DUTY(40) },
{ 75, 70, PWM_DUTY(60) },
{ 80, 75, PWM_DUTY(75) },
{ 85, 80, PWM_DUTY(90) },
{ 90, 85, PWM_DUTY(100) },
};

const struct Fan __code FAN2 = {
.points = FAN2_POINTS,
.points_size = ARRAY_SIZE(FAN2_POINTS),
.levels = fan2_table,
.levels_size = ARRAY_SIZE(fan2_table),
.pwm_min = PWM_DUTY(25),
};

0 comments on commit e7e4670

Please sign in to comment.