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:
		| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
| }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								tool/src/.ec.rs.swp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tool/src/.ec.rs.swp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -19,12 +19,14 @@ pub enum Cmd { | ||||
|     Print = 4, | ||||
|     Spi = 5, | ||||
|     Reset = 6, | ||||
|     FanGet = 7, | ||||
|     FanSet = 8, | ||||
| } | ||||
|  | ||||
| pub const CMD_SPI_FLAG_READ: u8 = (1 << 0); | ||||
| pub const CMD_SPI_FLAG_DISABLE: u8 = (1 << 1); | ||||
| pub const CMD_SPI_FLAG_SCRATCH: u8 = (1 << 2); | ||||
| pub const CMD_SPI_FLAG_BACKUP: u8 = (1 << 3); | ||||
| pub const CMD_SPI_FLAG_READ: u8 = 1 << 0; | ||||
| pub const CMD_SPI_FLAG_DISABLE: u8 = 1 << 1; | ||||
| pub const CMD_SPI_FLAG_SCRATCH: u8 = 1 << 2; | ||||
| pub const CMD_SPI_FLAG_BACKUP: u8 = 1 << 3; | ||||
|  | ||||
| pub struct Ec<T: Timeout> { | ||||
|     cmd: u16, | ||||
| @@ -181,6 +183,18 @@ impl<T: Timeout> Ec<T> { | ||||
|     pub unsafe fn reset(&mut self) -> Result<(), Error> { | ||||
|         self.command(Cmd::Reset) | ||||
|     } | ||||
|  | ||||
|     pub unsafe fn fan_get(&mut self, index: u8) -> Result<u8, Error> { | ||||
|         self.write(2, index); | ||||
|         self.command(Cmd::FanGet)?; | ||||
|         Ok(self.read(3)) | ||||
|     } | ||||
|  | ||||
|     pub unsafe fn fan_set(&mut self, index: u8, duty: u8) -> Result<(), Error> { | ||||
|         self.write(2, index); | ||||
|         self.write(3, duty); | ||||
|         self.command(Cmd::FanSet) | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct EcSpi<'a, T: Timeout> { | ||||
|   | ||||
| @@ -274,9 +274,33 @@ unsafe fn print(message: &[u8]) -> Result<(), Error> { | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| unsafe fn fan_get(index: u8) -> Result<(), Error> { | ||||
|     iopl(); | ||||
|  | ||||
|     let mut ec = Ec::new( | ||||
|         StdTimeout::new(Duration::new(1, 0)), | ||||
|     )?; | ||||
|  | ||||
|     let duty = ec.fan_get(index)?; | ||||
|     eprintln!("{}", duty); | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| unsafe fn fan_set(index: u8, duty: u8) -> Result<(), Error> { | ||||
|     iopl(); | ||||
|  | ||||
|     let mut ec = Ec::new( | ||||
|         StdTimeout::new(Duration::new(1, 0)), | ||||
|     )?; | ||||
|  | ||||
|     ec.fan_set(index, duty) | ||||
| } | ||||
|  | ||||
| fn usage() { | ||||
|     eprintln!("  console"); | ||||
|     eprintln!("  flash [file]"); | ||||
|     eprintln!("  fan [index] <duty>"); | ||||
|     eprintln!("  info"); | ||||
|     eprintln!("  print [message]"); | ||||
| } | ||||
| @@ -293,6 +317,40 @@ fn main() { | ||||
|                     process::exit(1); | ||||
|                 }, | ||||
|             }, | ||||
|             "fan" => match args.next() { | ||||
|                 Some(index_str) => match index_str.parse::<u8>() { | ||||
|                     Ok(index) => match args.next() { | ||||
|                         Some(duty_str) => match duty_str.parse::<u8>() { | ||||
|                             Ok(duty) => match unsafe { fan_set(index, duty) } { | ||||
|                                 Ok(()) => (), | ||||
|                                 Err(err) => { | ||||
|                                     eprintln!("failed to set fan {} to {}: {:X?}", index, duty, err); | ||||
|                                     process::exit(1); | ||||
|                                 }, | ||||
|                             }, | ||||
|                             Err(err) => { | ||||
|                                 eprintln!("failed to parse '{}': {:X?}", duty_str, err); | ||||
|                                 process::exit(1); | ||||
|                             }, | ||||
|                         }, | ||||
|                         None => match unsafe { fan_get(index) } { | ||||
|                             Ok(()) => (), | ||||
|                             Err(err) => { | ||||
|                                 eprintln!("failed to get fan {}: {:X?}", index, err); | ||||
|                                 process::exit(1); | ||||
|                             }, | ||||
|                         }, | ||||
|                     }, | ||||
|                     Err(err) => { | ||||
|                         eprintln!("failed to parse '{}': {:X?}", index_str, err); | ||||
|                         process::exit(1); | ||||
|                     }, | ||||
|                 }, | ||||
|                 None => { | ||||
|                     eprintln!("no index provided"); | ||||
|                     process::exit(1); | ||||
|                 }, | ||||
|             }, | ||||
|             "flash" => match args.next() { | ||||
|                 Some(path) => match unsafe { flash(&path) } { | ||||
|                     Ok(()) => (), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user