2828#define TPS546_THROTTLE_TEMP 105.0
2929#define TPS546_MAX_TEMP 145.0
3030
31+ #define THERMAL_CTRL_STEP_MHZ 25.0f
32+ #define THERMAL_CTRL_MIN_MHZ 400.0f
33+ #define THERMAL_CTRL_MAX_MHZ 650.0f
34+ #define THERMAL_CTRL_HYSTERESIS 3.0f
35+ #define THERMAL_TARGET_DEFAULT 65
36+
3137static const char * TAG = "power_management" ;
3238
3339static bool even = false;
@@ -85,6 +91,55 @@ static double automatic_fan_speed(float chip_temp, float vr_temp, GlobalState *
8591 return result ;
8692}
8793
94+ // Adjust ASIC frequency to maintain target temperature.
95+ // Uses max(chip_temp_max, vr_temp_normalized) as effective temperature.
96+ // VR range 60-85°C is mapped to ASIC 45-75°C scale.
97+ static void thermal_control_adjust_frequency (PowerManagementModule * pm , float nvs_base_freq , GlobalState * GLOBAL_STATE )
98+ {
99+ // Get max ASIC chip temperature
100+ float chip_max = 0.0f ;
101+ if (pm -> chip_temp [0 ] > 0.0f && pm -> chip_temp [1 ] > 0.0f ) {
102+ chip_max = (pm -> chip_temp [0 ] > pm -> chip_temp [1 ]) ? pm -> chip_temp [0 ] : pm -> chip_temp [1 ];
103+ } else if (pm -> chip_temp [0 ] > 0.0f ) {
104+ chip_max = pm -> chip_temp [0 ];
105+ } else if (pm -> chip_temp [1 ] > 0.0f ) {
106+ chip_max = pm -> chip_temp [1 ];
107+ } else {
108+ chip_max = 50.0f ; // fallback if both sensors zero
109+ }
110+
111+ // Normalize VR temp to ASIC scale: 60-85°C → 45-75°C
112+ float vr_normalized = 45.0f + (pm -> vr_temp - 60.0f ) * (30.0f / 25.0f );
113+ float effective_temp = (chip_max > vr_normalized ) ? chip_max : vr_normalized ;
114+
115+ uint16_t target = nvs_config_get_u16 (NVS_CONFIG_THERMAL_TARGET , THERMAL_TARGET_DEFAULT );
116+ // Clamp target to valid range
117+ if (target < 45 ) target = 45 ;
118+ if (target > 72 ) target = 72 ;
119+
120+ float new_freq = pm -> thermal_freq ;
121+
122+ if (effective_temp > (float )target ) {
123+ new_freq -= THERMAL_CTRL_STEP_MHZ ;
124+ if (new_freq < THERMAL_CTRL_MIN_MHZ ) new_freq = THERMAL_CTRL_MIN_MHZ ;
125+ } else if (effective_temp < (float )target - THERMAL_CTRL_HYSTERESIS ) {
126+ new_freq += THERMAL_CTRL_STEP_MHZ ;
127+ float ceiling = (nvs_base_freq < THERMAL_CTRL_MAX_MHZ ) ? nvs_base_freq : THERMAL_CTRL_MAX_MHZ ;
128+ if (new_freq > ceiling ) new_freq = ceiling ;
129+ } else {
130+ return ; // within dead band, no change
131+ }
132+
133+ ESP_LOGI (TAG , "ThermalCtrl: eff=%.1f°C target=%u°C freq %.0f->%.0f MHz" ,
134+ effective_temp , target , pm -> thermal_freq , new_freq );
135+
136+ bool success = ASIC_set_frequency (GLOBAL_STATE , new_freq );
137+ if (success ) {
138+ pm -> thermal_freq = new_freq ;
139+ pm -> frequency_value = new_freq ;
140+ }
141+ }
142+
88143void POWER_MANAGEMENT_task (void * pvParameters )
89144{
90145 ESP_LOGI (TAG , "Starting" );
@@ -95,13 +150,12 @@ void POWER_MANAGEMENT_task(void * pvParameters)
95150 SystemModule * sys_module = & GLOBAL_STATE -> SYSTEM_MODULE ;
96151
97152 power_management -> frequency_multiplier = 1 ;
98-
99- //int last_frequency_increase = 0;
100- //uint16_t frequency_target = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
153+ power_management -> thermal_freq = (float )nvs_config_get_u16 (NVS_CONFIG_ASIC_FREQ , CONFIG_ASIC_FREQUENCY );
154+ uint16_t last_thermal_ctrl = nvs_config_get_u16 (NVS_CONFIG_THERMAL_CTRL , 0 );
101155
102156 vTaskDelay (500 / portTICK_PERIOD_MS );
103157 uint16_t last_core_voltage = 0.0 ;
104- uint16_t last_asic_frequency = power_management -> frequency_value ;
158+ uint16_t last_asic_frequency = nvs_config_get_u16 ( NVS_CONFIG_ASIC_FREQ , CONFIG_ASIC_FREQUENCY ) ;
105159
106160 while (1 ) {
107161 PAC9544_selectChannel (even + 2U );
@@ -189,7 +243,7 @@ void POWER_MANAGEMENT_task(void * pvParameters)
189243 Thermal_setFanSpeedPercent ((float ) fs / 100.0 );
190244 }
191245
192- // New voltage and frequency adjustment code
246+ // Voltage adjustment
193247 uint16_t core_voltage = nvs_config_get_u16 (NVS_CONFIG_ASIC_VOLTAGE , CONFIG_ASIC_VOLTAGE );
194248 uint16_t asic_frequency = nvs_config_get_u16 (NVS_CONFIG_ASIC_FREQ , CONFIG_ASIC_FREQUENCY );
195249
@@ -199,17 +253,37 @@ void POWER_MANAGEMENT_task(void * pvParameters)
199253 last_core_voltage = core_voltage ;
200254 }
201255
202- if (asic_frequency != last_asic_frequency ) {
203- ESP_LOGI (TAG , "New ASIC frequency requested: %uMHz (current: %uMHz)" , asic_frequency , last_asic_frequency );
204-
205- bool success = ASIC_set_frequency (GLOBAL_STATE , (float )asic_frequency );
206-
207- if (success ) {
208- power_management -> frequency_value = (float )asic_frequency ;
256+ // Thermal control / frequency adjustment
257+ uint16_t thermal_ctrl_enabled = nvs_config_get_u16 (NVS_CONFIG_THERMAL_CTRL , 0 );
258+
259+ if (thermal_ctrl_enabled ) {
260+ // Clamp thermal_freq ceiling to current NVS base freq in case user lowered it
261+ if (power_management -> thermal_freq > (float )asic_frequency ) {
262+ power_management -> thermal_freq = (float )asic_frequency ;
263+ }
264+ thermal_control_adjust_frequency (power_management , (float )asic_frequency , GLOBAL_STATE );
265+ last_asic_frequency = (uint16_t )power_management -> thermal_freq ;
266+ } else {
267+ if (last_thermal_ctrl ) {
268+ // Thermal control was just disabled — restore NVS base frequency
269+ ESP_LOGI (TAG , "ThermalCtrl disabled, restoring NVS freq %uMHz" , asic_frequency );
270+ bool success = ASIC_set_frequency (GLOBAL_STATE , (float )asic_frequency );
271+ if (success ) {
272+ power_management -> frequency_value = (float )asic_frequency ;
273+ power_management -> thermal_freq = (float )asic_frequency ;
274+ }
275+ last_asic_frequency = asic_frequency ;
276+ } else if (asic_frequency != last_asic_frequency ) {
277+ ESP_LOGI (TAG , "New ASIC frequency requested: %uMHz (current: %uMHz)" , asic_frequency , last_asic_frequency );
278+ bool success = ASIC_set_frequency (GLOBAL_STATE , (float )asic_frequency );
279+ if (success ) {
280+ power_management -> frequency_value = (float )asic_frequency ;
281+ power_management -> thermal_freq = (float )asic_frequency ;
282+ }
283+ last_asic_frequency = asic_frequency ;
209284 }
210-
211- last_asic_frequency = asic_frequency ;
212285 }
286+ last_thermal_ctrl = thermal_ctrl_enabled ;
213287
214288 // Check for changing of overheat mode
215289 uint16_t new_overheat_mode = nvs_config_get_u16 (NVS_CONFIG_OVERHEAT_MODE , 0 );
0 commit comments