diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 84bef2d4..e4afe855 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -3,6 +3,8 @@ SRCS "adc.c" "DS4432U.c" "EMC2101.c" + "EMC2302.c" + "TPS546.c" "fonts.c" "i2c_master.c" "INA260.c" diff --git a/main/EMC2302.h b/main/EMC2302.h index 5e950b82..0cfce295 100644 --- a/main/EMC2302.h +++ b/main/EMC2302.h @@ -60,17 +60,17 @@ */ typedef enum { - EMC2101_RATE_1_16_HZ, ///< 1_16_HZ - EMC2101_RATE_1_8_HZ, ///< 1_8_HZ - EMC2101_RATE_1_4_HZ, ///< 1_4_HZ - EMC2101_RATE_1_2_HZ, ///< 1_2_HZ - EMC2101_RATE_1_HZ, ///< 1_HZ - EMC2101_RATE_2_HZ, ///< 2_HZ - EMC2101_RATE_4_HZ, ///< 4_HZ - EMC2101_RATE_8_HZ, ///< 8_HZ - EMC2101_RATE_16_HZ, ///< 16_HZ - EMC2101_RATE_32_HZ, ///< 32_HZ -} emc2101_rate_t; + EMC2302_RATE_1_16_HZ, ///< 1_16_HZ + EMC2302_RATE_1_8_HZ, ///< 1_8_HZ + EMC2302_RATE_1_4_HZ, ///< 1_4_HZ + EMC2302_RATE_1_2_HZ, ///< 1_2_HZ + EMC2302_RATE_1_HZ, ///< 1_HZ + EMC2302_RATE_2_HZ, ///< 2_HZ + EMC2302_RATE_4_HZ, ///< 4_HZ + EMC2302_RATE_8_HZ, ///< 8_HZ + EMC2302_RATE_16_HZ, ///< 16_HZ + EMC2302_RATE_32_HZ, ///< 32_HZ +} emc2302_rate_t; void EMC2302_init(bool); void EMC2302_set_fan_speed(uint8_t, float); diff --git a/main/TPS546.c b/main/TPS546.c new file mode 100644 index 00000000..33944f7c --- /dev/null +++ b/main/TPS546.c @@ -0,0 +1,153 @@ +#include "driver/i2c.h" +#include "esp_log.h" +#include +#include +#include + +#include "pmbus_commands.h" +#include "TPS546.h" + +#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ + +#define WRITE_BIT I2C_MASTER_WRITE +#define READ_BIT I2C_MASTER_READ +#define ACK_CHECK true +#define NO_ACK_CHECK false +#define ACK_VALUE 0x0 +#define NACK_VALUE 0x1 +#define MAX_BLOCK_LEN 32 + +#define SMBUS_DEFAULT_TIMEOUT (1000 / portTICK_PERIOD_MS) + +static const char *TAG = "TPS546.c"; + + +/** + * @brief SMBus read byte + */ +esp_err_t smb_read_byte(uint8_t command, uint8_t *data) +{ + esp_err_t err = ESP_FAIL; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, TPS546_I2CADDR << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, TPS546_I2CADDR << 1 | READ_BIT, ACK_CHECK); + i2c_master_read_byte(cmd, data, NACK_VALUE); + i2c_master_stop(cmd); + ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT)); + i2c_cmd_link_delete(cmd); + + return err; +} + +/** + * @brief SMBus read word + */ +esp_err_t smb_read_word(uint8_t command, uint8_t *data) +{ + esp_err_t err = ESP_FAIL; + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, TPS546_I2CADDR << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, TPS546_I2CADDR << 1 | READ_BIT, ACK_CHECK); + i2c_master_read(cmd, &data[0], 1, ACK_VALUE); + i2c_master_read_byte(cmd, &data[1], NACK_VALUE); + i2c_master_stop(cmd); + ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT)); + i2c_cmd_link_delete(cmd); + + return err; +} + +/** + * @brief SMBus read block + */ +static esp_err_t smb_read_block(uint8_t command, uint8_t * data, uint8_t len) +{ + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, TPS546_I2CADDR << 1 | WRITE_BIT, ACK_CHECK); + i2c_master_write_byte(cmd, command, ACK_CHECK); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, TPS546_I2CADDR << 1 | READ_BIT, ACK_CHECK); + uint8_t slave_len = 0; + i2c_master_read_byte(cmd, &slave_len, ACK_VALUE); + ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT)); + i2c_cmd_link_delete(cmd); + + cmd = i2c_cmd_link_create(); + for (size_t i = 0; i < slave_len - 1; ++i) + { + i2c_master_read_byte(cmd, &data[i], ACK_VALUE); + } + i2c_master_read_byte(cmd, &data[slave_len - 1], NACK_VALUE); + i2c_master_stop(cmd); + ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT)); + i2c_cmd_link_delete(cmd); + + return 0; +} + +// Set up the TPS546 regulator and turn it on +void TPS546_init(void) +{ + uint8_t data[6]; + uint8_t u8_value; + uint16_t u16_value; + float temp; + int mantissa, exponent; + + ESP_LOGI(TAG, "Initializing the core voltage regulator"); + + smb_read_block(PMBUS_IC_DEVICE_ID, data, 6); + ESP_LOGI(TAG, "Device ID: %02x %02x %02x %02x %02x %02x", data[0], data[1], + data[2], data[3], data[4], data[5]); + + smb_read_byte(PMBUS_REVISION, &u8_value); + ESP_LOGI(TAG, "PMBus revision: %02x", u8_value); + + /* Get temperature (SLINEAR11) */ + ESP_LOGI(TAG, "--------------------------------"); + smb_read_word(PMBUS_READ_TEMPERATURE_1, data); + u16_value = (data[1] << 8) + data[0]; + ESP_LOGI(TAG, "Temperature raw: %04x", u16_value); + if (u16_value & 0x400) { + // mantissa is negative + mantissa = -1 * ((~u16_value & 0x07FF) + 1); + } else { + mantissa = (u16_value & 0x07FF); + } + if (u16_value & 0x8000) { + // exponent is negative + exponent = -1 * (((~u16_value >> 11) & 0x001F) + 1); + } else { + exponent = (u16_value >> 11); + } + ESP_LOGI(TAG, "exp: %04x, mant: %04x", exponent, mantissa); + temp = mantissa * powf(2.0, exponent); + ESP_LOGI(TAG, "Temp: %2.1f", temp); + + /* Get voltage setting (ULINEAR16) */ + ESP_LOGI(TAG, "--------------------------------"); + smb_read_byte(PMBUS_VOUT_MODE, &u8_value); + //ESP_LOGI(TAG, "VOUT mode: %02x", u8_value); + float mode_exponent = -1 * ((~u8_value & 0x1F) + 1); + //ESP_LOGI(TAG, "mode_exponent: %f", mode_exponent); + + smb_read_word(PMBUS_VOUT_COMMAND, data); + u16_value = (data[1] << 8) + data[0]; + //ESP_LOGI(TAG, "VOUT: %d", u16_value); + float scaler = powf(2.0, mode_exponent); + //ESP_LOGI(TAG, "scaler: %f", scaler); + int voltage = (u16_value * scaler) * 1000; + ESP_LOGI(TAG, "Vout: %d mV", voltage); + +} + + diff --git a/main/TPS546.h b/main/TPS546.h new file mode 100644 index 00000000..60d4fc66 --- /dev/null +++ b/main/TPS546.h @@ -0,0 +1,13 @@ +#ifndef TPS546_H_ +#define TPS546_H_ + +#define TPS546_I2CADDR 0x24 ///< TPS546 i2c address +#define TPS546_MANUFACTURER_ID 0xFE ///< Manufacturer ID +#define TPS546_REVISION 0xFF ///< Chip revision + + +void TPS546_init(void); +//void TPS546_set_voltage(float); +//void TPS546_get_status(void); + +#endif /* TPS546_H_ */ diff --git a/main/global_state.h b/main/global_state.h index b8aa95f3..c2e2ef28 100644 --- a/main/global_state.h +++ b/main/global_state.h @@ -23,6 +23,7 @@ typedef enum DEVICE_MAX = 0, DEVICE_ULTRA, DEVICE_SUPRA, + DEVICE_HEX, } DeviceModel; typedef enum @@ -103,4 +104,4 @@ typedef struct } GlobalState; -#endif /* GLOBAL_STATE_H_ */ \ No newline at end of file +#endif /* GLOBAL_STATE_H_ */ diff --git a/main/pmbus_commands.h b/main/pmbus_commands.h index 060352f2..761c804d 100644 --- a/main/pmbus_commands.h +++ b/main/pmbus_commands.h @@ -57,7 +57,7 @@ #define PMBUS_READ_VOUT 0x8B #define PMBUS_READ_IOUT 0x8C #define PMBUS_READ_TEMPERATURE_1 0x8D -#define PMBUS_PMBUS_REVISION 0x98 +#define PMBUS_REVISION 0x98 #define PMBUS_MFR_ID 0x99 #define PMBUS_MFR_MODEL 0x9A #define PMBUS_MFR_REVISION 0x9B diff --git a/main/system.c b/main/system.c index 8daf6d86..5172d3f7 100644 --- a/main/system.c +++ b/main/system.c @@ -4,6 +4,7 @@ #include "i2c_master.h" #include "EMC2101.h" +#include "EMC2302.h" #include "INA260.h" #include "adc.h" #include "connect.h" @@ -90,8 +91,15 @@ static void _init_system(GlobalState * GLOBAL_STATE) switch (GLOBAL_STATE->device_model) { case DEVICE_MAX: case DEVICE_ULTRA: - case DEVICE_SUPRA: + case DEVICE_ULTRA: EMC2101_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1)); + EMC2101_set_fan_speed(1); + break; + case DEVICE_HEX: + // Fan Tests + EMC2302_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1)); + EMC2302_set_fan_speed(0, (float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100) / 100); + EMC2302_set_fan_speed(1, (float) nvs_config_get_u16(NVS_CONFIG_FAN_SPEED, 100) / 100); break; default: } diff --git a/main/vcore.c b/main/vcore.c index c2ff5a73..ab4267fe 100644 --- a/main/vcore.c +++ b/main/vcore.c @@ -5,6 +5,7 @@ #include "vcore.h" #include "adc.h" #include "DS4432U.h" +#include "TPS546.h" #define TPS40305_VFB 0.6 @@ -20,7 +21,10 @@ static const char *TAG = "vcore.c"; -void VCORE_init(GlobalState * global_state) { +void VCORE_init(GlobalState global_state) { + if (global_state.device_model == DEVICE_HEX) { + TPS546_init(); + } ADC_init(); }