diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 1001e4beb..2e2b4cf83 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" "INA260.c" "led_controller.c" diff --git a/main/EMC2302.h b/main/EMC2302.h index 5e950b82a..0cfce2955 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 000000000..b727a4659 --- /dev/null +++ b/main/TPS546.c @@ -0,0 +1,184 @@ +#include "driver/i2c.h" +#include "esp_log.h" +#include +#include +#include + +#include "pmbus_commands.h" +#include "TPS546.h" + +#define I2C_MASTER_SCL_IO 48 /*!< GPIO number used for I2C master clock */ +#define I2C_MASTER_SDA_IO 47 /*!< GPIO number used for I2C master data */ +#define I2C_MASTER_NUM \ + 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ +#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */ +#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ +#define I2C_MASTER_TIMEOUT_MS 1000 + +#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; +} + + +/** + * @brief Read a sequence of I2C bytes + */ +static esp_err_t register_read(uint8_t reg_addr, uint8_t * data, size_t len) +{ + return i2c_master_write_read_device(I2C_MASTER_NUM, TPS546_I2CADDR, ®_addr, 1, data, len, + I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); +} + +/** + * @brief Write a byte to a I2C register + */ +static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data) +{ + int ret; + uint8_t write_buf[2] = {reg_addr, data}; + + ret = i2c_master_write_to_device(I2C_MASTER_NUM, TPS546_I2CADDR, write_buf, sizeof(write_buf), + I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + + return ret; +} + +// 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 000000000..60d4fc66d --- /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 51184fb0d..922df9ebd 100644 --- a/main/global_state.h +++ b/main/global_state.h @@ -13,6 +13,11 @@ #define STRATUM_USER CONFIG_STRATUM_USER +/* Use platform ID to decide which drivers to use */ +#define PLATFORM_BITAXE 0x01 +#define PLATFORM_ULTRA 0x02 +#define PLATFORM_HEX 0x03 + typedef struct { void (*init_fn)(u_int64_t); @@ -24,6 +29,8 @@ typedef struct typedef struct { + int platform_id; + char * asic_model; AsicFunctions ASIC_functions; double asic_job_frequency_ms; @@ -50,4 +57,4 @@ typedef struct } GlobalState; -#endif /* GLOBAL_STATE_H_ */ \ No newline at end of file +#endif /* GLOBAL_STATE_H_ */ diff --git a/main/main.c b/main/main.c index a05b909c0..910315e56 100644 --- a/main/main.c +++ b/main/main.c @@ -25,6 +25,12 @@ void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); + /* we need to populate the platform_id here, but it doesn't exist in NVS yet */ + /* TODO read the platform ID from the NVS */ + /* TODO bitaxetool will need to be modified to include it */ + /* use hard-coded value for now */ + GLOBAL_STATE.platform_id = PLATFORM_HEX; + ESP_LOGI(TAG, "NVS_CONFIG_ASIC_FREQ %f", (float) nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY)); GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY); diff --git a/main/pmbus_commands.h b/main/pmbus_commands.h index 060352f29..761c804d5 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 45c87094a..f43e30323 100644 --- a/main/system.c +++ b/main/system.c @@ -3,7 +3,9 @@ #include "esp_log.h" #include "DS4432U.h" +#include "TPS546.h" #include "EMC2101.h" +#include "EMC2302.h" #include "INA260.h" #include "adc.h" #include "connect.h" @@ -75,11 +77,28 @@ static void _init_system(GlobalState * global_state, SystemModule * module) ADC_init(); - // DS4432U tests - DS4432U_set_vcore(nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE) / 1000.0); - - EMC2101_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1)); - EMC2101_set_fan_speed(1); + /* perform platform init based on the platform ID */ + /* TODO add other platforms besides HEX */ + switch (global_state->platform_id) { + case PLATFORM_BITAXE: + case PLATFORM_ULTRA: + // DS4432U tests + DS4432U_set_vcore(nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE) / 1000.0); + + EMC2101_init(nvs_config_get_u16(NVS_CONFIG_INVERT_FAN_POLARITY, 1)); + EMC2101_set_fan_speed(1); + break; + case PLATFORM_HEX: + // Initialize the core voltage regulator + TPS546_init(); + // 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: + ESP_LOGI(TAG, "ERROR- invalid platform ID"); + } vTaskDelay(500 / portTICK_PERIOD_MS);