diff --git a/main/TPS546.c b/main/TPS546.c index 5328e9141..7fbb6b236 100644 --- a/main/TPS546.c +++ b/main/TPS546.c @@ -150,7 +150,6 @@ static esp_err_t smb_read_block(uint8_t command, uint8_t *data, uint8_t len) } i2c_master_read_byte(cmd, &data[slave_len - 1], NACK_VALUE); i2c_master_stop(cmd); - i2c_set_timeout(I2C_MASTER_NUM, 20); ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT)); i2c_cmd_link_delete(cmd); @@ -208,7 +207,6 @@ static int slinear11_2_int(uint16_t value) // calculate result (mantissa * 2^exponent) result = mantissa * powf(2.0, exponent); - ESP_LOGI(TAG, "result: %f", result); return (int)result; } @@ -274,9 +272,6 @@ static uint16_t int_2_slinear11(int value) result = ((exponent << 11) & 0xF800) + mantissa; - //ESP_LOGI(TAG, "mantissa: %d, exponent: %d", mantissa, exponent); - //ESP_LOGI(TAG, "result: %04x", result); - return result; } @@ -313,9 +308,6 @@ static uint16_t float_2_slinear11(float value) result = (( (~exponent + 1) << 11) & 0xF800) + mantissa; - //ESP_LOGI(TAG, "mantissa: %d, exponent: -%d", mantissa, exponent); - //ESP_LOGI(TAG, "result: %04x", result); - return result; } @@ -339,8 +331,6 @@ static int ulinear16_2_float(uint16_t value) exponent = (voutmode & 0x1F); } - //ESP_LOGI(TAG, "value: %04x", value); - //ESP_LOGI(TAG, "mantissa: %d, exponent: %d", value, exponent); result = (value * powf(2.0, exponent)); return result; } @@ -366,7 +356,6 @@ static uint16_t float_2_ulinear16(float value) } result = (value / powf(2.0, exponent)); - ESP_LOGI(TAG, "result: %04x, exponent: %f", result, exponent); return result; } @@ -430,21 +419,22 @@ int TPS546_init(void) ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------"); /* Get voltage input (SLINEAR11) */ - smb_read_word(PMBUS_READ_VIN, &u16_value); - vin = slinear11_2_float(u16_value); - ESP_LOGI(TAG, "Vin measured: %2.3f V", vin); + //smb_read_word(PMBUS_READ_VIN, &u16_value); + //vin = slinear11_2_float(u16_value); + //ESP_LOGI(TAG, "Vin measured: %2.3f V", vin); + TPS546_get_vin(); /* Get output current (SLINEAR11) */ - smb_read_word(PMBUS_READ_IOUT, &u16_value); - iout = slinear11_2_float(u16_value); - ESP_LOGI(TAG, "Iout measured: %2.3f A", iout); + //smb_read_word(PMBUS_READ_IOUT, &u16_value); + //iout = slinear11_2_float(u16_value); + //ESP_LOGI(TAG, "Iout measured: %2.3f A", iout); + TPS546_get_iout(); /* Get voltage output (ULINEAR16) */ - // This gets a timeout, don't know why. clock stretching? - // Should take about 91 uS - smb_read_word(PMBUS_READ_VOUT, &u16_value); - vout = ulinear16_2_float(u16_value); - ESP_LOGI(TAG, "Vout measured: %2.3f V", vout); + //smb_read_word(PMBUS_READ_VOUT, &u16_value); + //vout = ulinear16_2_float(u16_value); + //ESP_LOGI(TAG, "Vout measured: %2.3f V", vout); + TPS546_get_vout(); ESP_LOGI(TAG, "-----------TIMING---------------------"); smb_read_word(PMBUS_TON_DELAY, &u16_value); @@ -530,12 +520,16 @@ void TPS546_write_entire_config(void) smb_write_word(PMBUS_VOUT_COMMAND, float_2_ulinear16(TPS546_INIT_VOUT_COMMAND)); ESP_LOGI(TAG, "VOUT_MAX"); smb_write_word(PMBUS_VOUT_MAX, float_2_ulinear16(TPS546_INIT_VOUT_MAX)); - ESP_LOGI(TAG, "VOUT_MAX_OV_FAULT_LIMIT"); + ESP_LOGI(TAG, "VOUT_OV_FAULT_LIMIT"); smb_write_word(PMBUS_VOUT_OV_FAULT_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_FAULT_LIMIT)); ESP_LOGI(TAG, "VOUT_OV_WARN_LIMIT"); - //smb_write_word(PMBUS_VOUT_OV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_WARN_LIMIT)); + smb_write_word(PMBUS_VOUT_OV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_OV_WARN_LIMIT)); + ESP_LOGI(TAG, "VOUT_MARGIN_HIGH"); + smb_write_word(PMBUS_VOUT_MARGIN_HIGH, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_HIGH)); + ESP_LOGI(TAG, "VOUT_MARGIN_LOW"); + smb_write_word(PMBUS_VOUT_MARGIN_LOW, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_LOW)); ESP_LOGI(TAG, "VOUT_UV_WARN_LIMIT"); - //smb_write_word(PMBUS_VOUT_UV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_WARN_LIMIT)); + smb_write_word(PMBUS_VOUT_UV_WARN_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_WARN_LIMIT)); ESP_LOGI(TAG, "VOUT_UV_FAULT_LIMIT"); smb_write_word(PMBUS_VOUT_UV_FAULT_LIMIT, float_2_ulinear16(TPS546_INIT_VOUT_UV_FAULT_LIMIT)); ESP_LOGI(TAG, "VOUT_MIN"); @@ -572,9 +566,6 @@ void TPS546_write_entire_config(void) //ESP_LOGI(TAG, "COMPENSATION"); //smb_write_block(PMBUS_COMPENSATION_CONFIG, COMPENSATION_CONFIG, 5); - /* Slave address */ - //smb_write_byte(PMBUS_SLAVE_ADDRESS, TPS546_I2CADDR); - /* configure the bootup behavior regarding pin detect values vs NVM values */ ESP_LOGI(TAG, "Setting PIN_DETECT_OVERRIDE"); smb_write_word(PMBUS_PIN_DETECT_OVERRIDE, INIT_PIN_DETECT_OVERRIDE); @@ -589,7 +580,7 @@ void TPS546_write_entire_config(void) /* store configuration in NVM */ ESP_LOGI(TAG, "---Saving new config---"); - //smb_write_byte(PMBUS_STORE_USER_ALL, 0xFF); + smb_write_byte(PMBUS_STORE_USER_ALL, 0x98); } @@ -635,6 +626,41 @@ int TPS546_get_temperature(void) return temp; } +float TPS546_get_vin(void) +{ + uint16_t u16_value; + float vin; + + /* Get voltage input (ULINEAR16) */ + smb_read_word(PMBUS_READ_VIN, &u16_value); + vin = slinear11_2_float(u16_value); + ESP_LOGI(TAG, "Got Vin: %2.3f V", vin); + return vin; +} + +float TPS546_get_iout(void) +{ + uint16_t u16_value; + float iout; + + /* Get current output (SLINEAR11) */ + smb_read_word(PMBUS_READ_IOUT, &u16_value); + iout = slinear11_2_float(u16_value); + ESP_LOGI(TAG, "Got Iout: %2.3f V", iout); + return iout; +} + +float TPS546_get_vout(void) +{ + uint16_t u16_value; + float vout; + + /* Get voltage output (ULINEAR16) */ + smb_read_word(PMBUS_READ_VOUT, &u16_value); + vout = ulinear16_2_float(u16_value); + ESP_LOGI(TAG, "Got Vout: %2.3f V", vout); + return vout; +} /** * @brief Sets the core voltage diff --git a/main/TPS546.h b/main/TPS546.h index c45fb4d4e..ce7b5ace2 100644 --- a/main/TPS546.h +++ b/main/TPS546.h @@ -25,16 +25,18 @@ /* vout voltage */ #define TPS546_INIT_SCALE_LOOP 0xC808 /* 0.125 */ -#define TPS546_INIT_VOUT_MAX 5.00 /* V */ -#define TPS546_INIT_VOUT_OV_FAULT_LIMIT 1.20 /* V relative to VOUT_COMMAND */ -#define TPS546_INIT_VOUT_OV_WARN_LIMIT 0.90 /* V relative to VOUT_COMMAND */ -#define TPS546_INIT_VOUT_COMMAND 3.60 /* V absolute value */ -#define TPS546_INIT_VOUT_UV_WARN_LIMIT 0.50 /* V relative to VOUT_COMMAND */ -#define TPS546_INIT_VOUT_UV_FAULT_LIMIT 0.60 /* V relative to VOUT_COMMAND */ -#define TPS546_INIT_VOUT_MIN 3.00 /* v */ +#define TPS546_INIT_VOUT_MAX 4.50 /* V */ +#define TPS546_INIT_VOUT_OV_FAULT_LIMIT 1.25 /* %/100 above VOUT_COMMAND */ +#define TPS546_INIT_VOUT_OV_WARN_LIMIT 1.1 /* %/100 above VOUT_COMMAND */ +#define TPS546_INIT_VOUT_MARGIN_HIGH 1.1 /* %/100 above VOUT */ +#define TPS546_INIT_VOUT_COMMAND 3.60 /* V absolute value */ +#define TPS546_INIT_VOUT_MARGIN_LOW 0.90 /* %/100 below VOUT */ +#define TPS546_INIT_VOUT_UV_WARN_LIMIT 0.90 /* %/100 below VOUT_COMMAND */ +#define TPS546_INIT_VOUT_UV_FAULT_LIMIT 0.75 /* %/100 below VOUT_COMMAND */ +#define TPS546_INIT_VOUT_MIN 2.5 /* v */ /* iout current */ -#define TPS546_INIT_IOUT_OC_WARN_LIMIT 25.00 /* A */ +#define TPS546_INIT_IOUT_OC_WARN_LIMIT 25.00 /* A */ #define TPS546_INIT_IOUT_OC_FAULT_LIMIT 30.00 /* A */ #define TPS546_INIT_IOUT_OC_FAULT_RESPONSE 0xC0 /* shut down, no retries */ @@ -73,6 +75,9 @@ void TPS546_write_entire_config(void); int TPS546_get_frequency(void); void TPS546_set_frequency(int); int TPS546_get_temperature(void); +float TPS546_get_vin(void); +float TPS546_get_iout(void); +float TPS546_get_vout(void); void TPS546_set_vout(int millivolts); void TPS546_show_voltage_settings(void); diff --git a/main/main.c b/main/main.c index 9954bf017..c7ce4314f 100644 --- a/main/main.c +++ b/main/main.c @@ -113,8 +113,18 @@ void app_main(void) GLOBAL_STATE.SYSTEM_MODULE.startup_done = true; xTaskCreate(USER_INPUT_task, "user input", 8192, (void *) &GLOBAL_STATE, 5, NULL); - xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL); + if (strcmp(GLOBAL_STATE.board_version, "302") == 0) { + // this is a HEX board + ESP_LOGI(TAG, "Starting HEX power management"); + xTaskCreate(POWER_MANAGEMENT_HEX_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL); + } else { + // this is NOT a HEX board + ESP_LOGI(TAG, "Starting BITAXE power management"); + xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL); + } + + ESP_LOGI(TAG, "Starting init functions"); if (GLOBAL_STATE.ASIC_functions.init_fn != NULL) { wifi_softap_off(); diff --git a/main/tasks/power_management_task.c b/main/tasks/power_management_task.c index 4f74873e7..6f36e7739 100644 --- a/main/tasks/power_management_task.c +++ b/main/tasks/power_management_task.c @@ -1,6 +1,8 @@ #include "DS4432U.h" #include "EMC2101.h" #include "INA260.h" +#include "TPS546.h" +#include "TMP1075.h" #include "bm1397.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -17,6 +19,8 @@ #define THROTTLE_TEMP 75.0 #define THROTTLE_TEMP_RANGE (MAX_TEMP - THROTTLE_TEMP) +#define TPS546_THROTTLE_TEMP 105.0 + #define VOLTAGE_START_THROTTLE 4900 #define VOLTAGE_MIN_THROTTLE 3500 #define VOLTAGE_RANGE (VOLTAGE_START_THROTTLE - VOLTAGE_MIN_THROTTLE) @@ -33,9 +37,29 @@ static float _fbound(float value, float lower_bound, float upper_bound) return value; } -void POWER_MANAGEMENT_task(void * pvParameters) +// Set the fan speed between 20% min and 100% max based on chip temperature as input. +// The fan speed increases from 20% to 100% proportionally to the temperature increase from 50 and THROTTLE_TEMP +static void automatic_fan_speed(float chip_temp) { + double result = 0.0; + double min_temp = 50.0; + double min_fan_speed = 20.0; + + if (chip_temp < min_temp) { + result = min_fan_speed; + } else if (chip_temp >= THROTTLE_TEMP) { + result = 100; + } else { + double temp_range = THROTTLE_TEMP - min_temp; + double fan_range = 100 - min_fan_speed; + result = ((chip_temp - min_temp) / temp_range) * fan_range + min_fan_speed; + } + + EMC2101_set_fan_speed((float) result / 100); +} +void POWER_MANAGEMENT_task(void * pvParameters) +{ GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters; PowerManagementModule * power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE; @@ -183,23 +207,80 @@ void POWER_MANAGEMENT_task(void * pvParameters) } } -// Set the fan speed between 20% min and 100% max based on chip temperature as input. -// The fan speed increases from 20% to 100% proportionally to the temperature increase from 50 and THROTTLE_TEMP -static void automatic_fan_speed(float chip_temp) + +void POWER_MANAGEMENT_HEX_task(void * pvParameters) { - double result = 0.0; - double min_temp = 50.0; - double min_fan_speed = 20.0; + GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters; - if (chip_temp < min_temp) { - result = min_fan_speed; - } else if (chip_temp >= THROTTLE_TEMP) { - result = 100; - } else { - double temp_range = THROTTLE_TEMP - min_temp; - double fan_range = 100 - min_fan_speed; - result = ((chip_temp - min_temp) / temp_range) * fan_range + min_fan_speed; - } + PowerManagementModule * power_management = &GLOBAL_STATE->POWER_MANAGEMENT_MODULE; - EMC2101_set_fan_speed((float) result / 100); + power_management->frequency_multiplier = 1; + + char * board_version = nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "unknown"); + power_management->HAS_POWER_EN = + (strcmp(board_version, "202") == 1 || strcmp(board_version, "203") == 1 || strcmp(board_version, "204") == 1); + power_management->HAS_PLUG_SENSE = strcmp(board_version, "204") == 1; + free(board_version); + + int last_frequency_increase = 0; + + uint16_t frequency_target = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY); + + uint16_t auto_fan_speed = nvs_config_get_u16(NVS_CONFIG_AUTO_FAN_SPEED, 1); + + // turn on ASIC core voltage (three domains in series) + TPS546_set_vout(3600); + + vTaskDelay(3000 / portTICK_PERIOD_MS); + + while (1) { + + // use TPS546_get_vin() for input voltage + + power_management->voltage = TPS546_get_vout(); + power_management->current = TPS546_get_iout(); + // calculate ASIC power consumed (in milliwatts) + power_management->power = (power_management->voltage * power_management->current) / 1000; + + // TODO fix fan driver + //power_management->fan_speed = EMC2101_get_fan_speed(); + + // Two board temperature sensors + ESP_LOGI(TAG, "Board Temp: %d, %d", TMP1075_read_temperature(0), TMP1075_read_temperature(1)); + + // get regulator internal temperature + power_management->chip_temp = (float)TPS546_get_temperature(); + ESP_LOGI(TAG, "TPS546 Temp: %f", power_management->chip_temp); + + // TODO figure out best way to detect overheating on the Hex + if (power_management->chip_temp > TPS546_THROTTLE_TEMP && + (power_management->frequency_value > 50 || power_management->voltage > 1000)) { + ESP_LOGE(TAG, "OVERHEAT"); + + // Turn off core voltage + TPS546_set_vout(0); + + nvs_config_set_u16(NVS_CONFIG_ASIC_VOLTAGE, 990); + nvs_config_set_u16(NVS_CONFIG_ASIC_FREQ, 50); + nvs_config_set_u16(NVS_CONFIG_FAN_SPEED, 100); + nvs_config_set_u16(NVS_CONFIG_AUTO_FAN_SPEED, 0); + exit(EXIT_FAILURE); + } + + // TODO fix fan driver + //if (auto_fan_speed == 1) { + // automatic_fan_speed(power_management->chip_temp); + //} else { + // EMC2101_set_fan_speed((float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100) / 100); + //} + + ESP_LOGI(TAG, "TPS546 VIN: %f, VOUT: %f, IOUT: %f", TPS546_get_vin(), TPS546_get_vout(), TPS546_get_iout()); + ESP_LOGI(TAG, "Regulator power: %f mW", power_management->power); + + //ESP_LOGI(TAG, "Frequency target %f, Freq %f", target_frequency, power_management->frequency_value); + ESP_LOGI(TAG, "Frequency %d", TPS546_get_frequency()); + + vTaskDelay(POLL_RATE / portTICK_PERIOD_MS); + } } + diff --git a/main/tasks/power_management_task.h b/main/tasks/power_management_task.h index 9d32b3ef4..23a7a83ce 100644 --- a/main/tasks/power_management_task.h +++ b/main/tasks/power_management_task.h @@ -16,5 +16,5 @@ typedef struct static void automatic_fan_speed(float chip_temp); void POWER_MANAGEMENT_task(void * pvParameters); - -#endif \ No newline at end of file +void POWER_MANAGEMENT_HEX_task(void * pvParameters); +#endif