mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-03-18 13:52:07 +01:00
Fix all compiler warnings and migrate off depreciated ADC and I2C libraries. --------- Co-authored-by: Erik Olof Gunnar Andersson <eandersson@users.noreply.github.com>
785 lines
25 KiB
C
785 lines
25 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include "esp_log.h"
|
|
#include "pmbus_commands.h"
|
|
|
|
#include "i2c_bitaxe.h"
|
|
#include "TPS546.h"
|
|
|
|
//#define _DEBUG_LOG_ 1
|
|
|
|
#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";
|
|
|
|
static uint8_t DEVICE_ID1[] = {0x54, 0x49, 0x54, 0x6B, 0x24, 0x41}; // TPS546D24A
|
|
static uint8_t DEVICE_ID2[] = {0x54, 0x49, 0x54, 0x6D, 0x24, 0x41}; // TPS546D24A
|
|
static uint8_t DEVICE_ID3[] = {0x54, 0x49, 0x54, 0x6D, 0x24, 0x62}; // TPS546D24S
|
|
static uint8_t MFR_ID[] = {'B', 'A', 'X'};
|
|
static uint8_t MFR_MODEL[] = {'H', 'E', 'X'};
|
|
static uint8_t MFR_REVISION[] = {0x00, 0x00, 0x01};
|
|
|
|
//static uint8_t COMPENSATION_CONFIG[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
|
|
static i2c_master_dev_handle_t tps546_dev_handle;
|
|
|
|
/**
|
|
* @brief SMBus read byte
|
|
* @param command The command to read
|
|
* @param data Pointer to store the read data
|
|
*/
|
|
static esp_err_t smb_read_byte(uint8_t command, uint8_t *data)
|
|
{
|
|
return i2c_bitaxe_register_read(tps546_dev_handle, command, data, 1);
|
|
}
|
|
|
|
/**
|
|
* @brief SMBus write byte
|
|
* @param command The command to write
|
|
* @param data The data to write
|
|
*/
|
|
static esp_err_t smb_write_byte(uint8_t command, uint8_t data)
|
|
{
|
|
return i2c_bitaxe_register_write_byte(tps546_dev_handle, command, data);
|
|
}
|
|
|
|
/**
|
|
* @brief SMBus read word
|
|
* @param command The command to read
|
|
* @param result Pointer to store the read data
|
|
*/
|
|
static esp_err_t smb_read_word(uint8_t command, uint16_t *result)
|
|
{
|
|
uint8_t data[2];
|
|
if (i2c_bitaxe_register_read(tps546_dev_handle, command, data, 2) != ESP_OK) {
|
|
return ESP_FAIL;
|
|
} else {
|
|
*result = (data[1] << 8) + data[0];
|
|
return ESP_OK;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief SMBus write word
|
|
* @param command The command to write
|
|
* @param data The data to write
|
|
*/
|
|
static esp_err_t smb_write_word(uint8_t command, uint16_t data)
|
|
{
|
|
return i2c_bitaxe_register_write_word(tps546_dev_handle, command, data);
|
|
}
|
|
|
|
/**
|
|
* @brief SMBus read block -- SMBus is funny in that the first byte returned is the length of data??
|
|
* @param command The command to read
|
|
* @param data Pointer to store the read data
|
|
* @param len The number of bytes to read
|
|
*/
|
|
static esp_err_t smb_read_block(uint8_t command, uint8_t *data, uint8_t len)
|
|
{
|
|
//malloc a buffer len+1 to store the length byte
|
|
uint8_t *buf = (uint8_t *)malloc(len+1);
|
|
if (i2c_bitaxe_register_read(tps546_dev_handle, command, buf, len+1) != ESP_OK) {
|
|
free(buf);
|
|
return ESP_FAIL;
|
|
}
|
|
//copy the data into the buffer
|
|
memcpy(data, buf+1, len);
|
|
free(buf);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief SMBus write block - don;t forget the length byte first :P
|
|
* @param command The command to write
|
|
* @param data The data to write
|
|
* @param len The number of bytes to write
|
|
*/
|
|
static esp_err_t smb_write_block(uint8_t command, uint8_t *data, uint8_t len)
|
|
{
|
|
//malloc a buffer len+2 to store the command byte and then the length byte
|
|
uint8_t *buf = (uint8_t *)malloc(len+2);
|
|
buf[0] = command;
|
|
buf[1] = len;
|
|
//copy the data into the buffer
|
|
memcpy(buf+2, data, len);
|
|
|
|
//write it all
|
|
if (i2c_bitaxe_register_write_bytes(tps546_dev_handle, buf, len+2) != ESP_OK) {
|
|
free(buf);
|
|
return ESP_FAIL;
|
|
} else {
|
|
free(buf);
|
|
return ESP_OK;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Convert an SLINEAR11 value into an int
|
|
* @param value The SLINEAR11 value to convert
|
|
*/
|
|
static int slinear11_2_int(uint16_t value)
|
|
{
|
|
int exponent, mantissa;
|
|
float result;
|
|
|
|
// First 5 bits is exponent in twos-complement
|
|
// check the first bit of the exponent to see if its negative
|
|
if (value & 0x8000) {
|
|
// exponent is negative
|
|
exponent = -1 * (((~value >> 11) & 0x001F) + 1);
|
|
} else {
|
|
exponent = (value >> 11);
|
|
}
|
|
// last 11 bits is the mantissa in twos-complement
|
|
// check the first bit of the mantissa to see if its negative
|
|
if (value & 0x400) {
|
|
// mantissa is negative
|
|
mantissa = -1 * ((~value & 0x03FF) + 1);
|
|
} else {
|
|
mantissa = (value & 0x03FF);
|
|
}
|
|
|
|
// calculate result (mantissa * 2^exponent)
|
|
result = mantissa * powf(2.0, exponent);
|
|
return (int)result;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert an SLINEAR11 value into an int
|
|
* @param value The SLINEAR11 value to convert
|
|
*/
|
|
static float slinear11_2_float(uint16_t value)
|
|
{
|
|
int exponent, mantissa;
|
|
float result;
|
|
|
|
// First 5 bits is exponent in twos-complement
|
|
// check the first bit of the exponent to see if its negative
|
|
if (value & 0x8000) {
|
|
// exponent is negative
|
|
exponent = -1 * (((~value >> 11) & 0x001F) + 1);
|
|
} else {
|
|
exponent = (value >> 11);
|
|
}
|
|
// last 11 bits is the mantissa in twos-complement
|
|
// check the first bit of the mantissa to see if its negative
|
|
if (value & 0x400) {
|
|
// mantissa is negative
|
|
mantissa = -1 * ((~value & 0x03FF) + 1);
|
|
} else {
|
|
mantissa = (value & 0x03FF);
|
|
}
|
|
|
|
// calculate result (mantissa * 2^exponent)
|
|
result = mantissa * powf(2.0, exponent);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert an int value into an SLINEAR11
|
|
* @param value The int value to convert
|
|
*/
|
|
static uint16_t int_2_slinear11(int value)
|
|
{
|
|
int mantissa;
|
|
int exponent = 0;
|
|
uint16_t result = 0;
|
|
int i;
|
|
|
|
// First see if the exponent is positive or negative
|
|
if (value >= 0) {
|
|
// exponent is positive
|
|
for (i=0; i<=15; i++) {
|
|
mantissa = value / powf(2.0, i);
|
|
if (mantissa < 1024) {
|
|
exponent = i;
|
|
break;
|
|
}
|
|
}
|
|
if (i == 16) {
|
|
ESP_LOGI(TAG, "Could not find a solution");
|
|
return 0;
|
|
}
|
|
} else {
|
|
// value is negative
|
|
ESP_LOGI(TAG, "No negative numbers at this time");
|
|
return 0;
|
|
}
|
|
|
|
result = ((exponent << 11) & 0xF800) + mantissa;
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert a float value into an SLINEAR11
|
|
* @param value The float value to convert
|
|
*/
|
|
static uint16_t float_2_slinear11(float value)
|
|
{
|
|
int mantissa;
|
|
int exponent = 0;
|
|
uint16_t result = 0;
|
|
int i;
|
|
|
|
// First see if the exponent is positive or negative
|
|
if (value > 0) {
|
|
// exponent is negative
|
|
for (i=0; i<=15; i++) {
|
|
mantissa = value * powf(2.0, i);
|
|
if (mantissa >= 1024) {
|
|
exponent = i-1;
|
|
mantissa = value * powf(2.0, exponent);
|
|
break;
|
|
}
|
|
}
|
|
if (i == 16) {
|
|
ESP_LOGI(TAG, "Could not find a solution");
|
|
return 0;
|
|
}
|
|
} else {
|
|
// value is negative
|
|
ESP_LOGI(TAG, "No negative numbers at this time");
|
|
return 0;
|
|
}
|
|
|
|
result = (( (~exponent + 1) << 11) & 0xF800) + mantissa;
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert a ULINEAR16 value into a float
|
|
* the exponent comes from the VOUT_MODE bits[4..0]
|
|
* stored in twos-complement
|
|
* The mantissa occupies the full 16-bits of the value
|
|
* @param value The ULINEAR16 value to convert
|
|
*/
|
|
static float ulinear16_2_float(uint16_t value)
|
|
{
|
|
uint8_t voutmode;
|
|
int exponent;
|
|
float result;
|
|
|
|
smb_read_byte(PMBUS_VOUT_MODE, &voutmode);
|
|
|
|
if (voutmode & 0x10) {
|
|
// exponent is negative
|
|
exponent = -1 * ((~voutmode & 0x1F) + 1);
|
|
} else {
|
|
exponent = (voutmode & 0x1F);
|
|
}
|
|
result = (value * powf(2.0, exponent));
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Convert a float value into a ULINEAR16
|
|
* the exponent comes from the VOUT_MODE bits[4..0]
|
|
* stored in twos-complement
|
|
* The mantissa occupies the full 16-bits of the result
|
|
* @param value The float value to convert
|
|
*/
|
|
static uint16_t float_2_ulinear16(float value)
|
|
{
|
|
uint8_t voutmode;
|
|
float exponent;
|
|
uint16_t result;
|
|
|
|
smb_read_byte(PMBUS_VOUT_MODE, &voutmode);
|
|
if (voutmode & 0x10) {
|
|
// exponent is negative
|
|
exponent = -1 * ((~voutmode & 0x1F) + 1);
|
|
} else {
|
|
exponent = (voutmode & 0x1F);
|
|
}
|
|
|
|
result = (value / powf(2.0, exponent));
|
|
|
|
return result;
|
|
}
|
|
|
|
/*--- Public TPS546 functions ---*/
|
|
|
|
/**
|
|
* @brief Set up the TPS546 regulator and turn it on
|
|
*/
|
|
int TPS546_init(void)
|
|
{
|
|
uint8_t data[7];
|
|
uint8_t u8_value;
|
|
uint16_t u16_value;
|
|
uint8_t read_mfr_revision[4];
|
|
int temp;
|
|
uint8_t comp_config[5];
|
|
uint8_t voutmode;
|
|
|
|
ESP_LOGI(TAG, "Initializing the core voltage regulator");
|
|
|
|
if (i2c_bitaxe_add_device(TPS546_I2CADDR, &tps546_dev_handle) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to add I2C device");
|
|
return -1;
|
|
}
|
|
|
|
/* Establish communication with regulator */
|
|
smb_read_block(PMBUS_IC_DEVICE_ID, data, 6); //the DEVICE_ID block first byte is the length.
|
|
ESP_LOGI(TAG, "Device ID: %02x %02x %02x %02x %02x %02x", data[0], data[1], data[2], data[3], data[4], data[5]);
|
|
/* There's 3 different known device IDs observed so far */
|
|
if ( (memcmp(data, DEVICE_ID1, 6) != 0) && (memcmp(data, DEVICE_ID2, 6) != 0) && (memcmp(data, DEVICE_ID3, 6) != 0))
|
|
{
|
|
ESP_LOGE(TAG, "Cannot find TPS546 regulator - Device ID mismatch");
|
|
return -1;
|
|
}
|
|
|
|
/* Make sure power is turned off until commanded */
|
|
u8_value = ON_OFF_CONFIG_CMD | ON_OFF_CONFIG_PU | ON_OFF_CONFIG_CP |
|
|
ON_OFF_CONFIG_POLARITY | ON_OFF_CONFIG_DELAY;
|
|
ESP_LOGI(TAG, "Power config-ON_OFF_CONFIG: %02x", u8_value);
|
|
smb_write_byte(PMBUS_ON_OFF_CONFIG, u8_value);
|
|
|
|
/* Read version number and see if it matches */
|
|
TPS546_read_mfr_info(read_mfr_revision);
|
|
// if (memcmp(read_mfr_revision, MFR_REVISION, 3) != 0) {
|
|
|
|
// If it doesn't match, then write all the registers and set new version number
|
|
// ESP_LOGI(TAG, "--------------------------------");
|
|
// ESP_LOGI(TAG, "Config version mismatch, writing new config values");
|
|
ESP_LOGI(TAG, "Writing new config values");
|
|
smb_read_byte(PMBUS_VOUT_MODE, &voutmode);
|
|
ESP_LOGI(TAG, "VOUT_MODE: %02x", voutmode);
|
|
TPS546_write_entire_config();
|
|
//}
|
|
|
|
// /* Show temperature */
|
|
// ESP_LOGI(TAG, "--------------------------------");
|
|
// ESP_LOGI(TAG, "Temp: %d", TPS546_get_temperature());
|
|
|
|
// /* Show switching frequency */
|
|
// TPS546_get_frequency();
|
|
// TPS546_set_frequency(650);
|
|
|
|
/* Show voltage settings */
|
|
TPS546_show_voltage_settings();
|
|
|
|
//TPS546_print_status();
|
|
|
|
// ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
|
|
// /* Get voltage input (SLINEAR11) */
|
|
// ESP_LOGI(TAG, "READ_VIN: %.2fV", TPS546_get_vin());
|
|
// /* Get output current (SLINEAR11) */
|
|
// ESP_LOGI(TAG, "READ_IOUT: %.2fA", TPS546_get_iout());
|
|
// /* Get voltage output (ULINEAR16) */
|
|
// ESP_LOGI(TAG, "READ_VOUT: %.2fV", TPS546_get_vout());
|
|
|
|
ESP_LOGI(TAG, "-----------TIMING---------------------");
|
|
smb_read_word(PMBUS_TON_DELAY, &u16_value);
|
|
temp = slinear11_2_int(u16_value);
|
|
ESP_LOGI(TAG, "TON_DELAY: %d", temp);
|
|
smb_read_word(PMBUS_TON_RISE, &u16_value);
|
|
temp = slinear11_2_int(u16_value);
|
|
ESP_LOGI(TAG, "TON_RISE: %d", temp);
|
|
smb_read_word(PMBUS_TON_MAX_FAULT_LIMIT, &u16_value);
|
|
temp = slinear11_2_int(u16_value);
|
|
ESP_LOGI(TAG, "TON_MAX_FAULT_LIMIT: %d", temp);
|
|
smb_read_byte(PMBUS_TON_MAX_FAULT_RESPONSE, &u8_value);
|
|
ESP_LOGI(TAG, "TON_MAX_FAULT_RESPONSE: %02x", u8_value);
|
|
smb_read_word(PMBUS_TOFF_DELAY, &u16_value);
|
|
temp = slinear11_2_int(u16_value);
|
|
ESP_LOGI(TAG, "TOFF_DELAY: %d", temp);
|
|
smb_read_word(PMBUS_TOFF_FALL, &u16_value);
|
|
temp = slinear11_2_int(u16_value);
|
|
ESP_LOGI(TAG, "TOFF_FALL: %d", temp);
|
|
ESP_LOGI(TAG, "--------------------------------------");
|
|
|
|
// Read the compensation config registers
|
|
if (smb_read_block(PMBUS_COMPENSATION_CONFIG, comp_config, 5) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to read COMPENSATION CONFIG");
|
|
return -1;
|
|
}
|
|
ESP_LOGI(TAG, "COMPENSATION CONFIG");
|
|
ESP_LOGI(TAG, "%02x %02x %02x %02x %02x", comp_config[0], comp_config[1],
|
|
comp_config[2], comp_config[3], comp_config[4]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Read the manufacturer model and revision
|
|
* @param read_mfr_revision Pointer to store the read revision
|
|
*/
|
|
void TPS546_read_mfr_info(uint8_t *read_mfr_revision)
|
|
{
|
|
uint8_t read_mfr_id[4];
|
|
uint8_t read_mfr_model[4];
|
|
|
|
ESP_LOGI(TAG, "Reading MFR info");
|
|
if (smb_read_block(PMBUS_MFR_ID, read_mfr_id, 3) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to read MFR ID");
|
|
return;
|
|
}
|
|
read_mfr_id[3] = 0x00;
|
|
if (smb_read_block(PMBUS_MFR_MODEL, read_mfr_model, 3) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to read MFR MODEL");
|
|
return;
|
|
}
|
|
read_mfr_model[3] = 0x00;
|
|
if (smb_read_block(PMBUS_MFR_REVISION, read_mfr_revision, 3) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to read MFR REVISION");
|
|
return;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "MFR_ID: %s", read_mfr_id);
|
|
ESP_LOGI(TAG, "MFR_MODEL: %s", read_mfr_model);
|
|
ESP_LOGI(TAG, "MFR_REVISION: %d%d%d ", read_mfr_revision[0],
|
|
read_mfr_revision[1], read_mfr_revision[2]);
|
|
}
|
|
|
|
/**
|
|
* @brief Write the manufacturer ID and revision to NVM
|
|
*/
|
|
void TPS546_set_mfr_info(void)
|
|
{
|
|
ESP_LOGI(TAG, "Setting MFR info");
|
|
smb_write_block(PMBUS_MFR_ID, MFR_ID, 3);
|
|
smb_write_block(PMBUS_MFR_MODEL, MFR_MODEL, 3);
|
|
smb_write_block(PMBUS_MFR_REVISION, MFR_REVISION, 3);
|
|
}
|
|
|
|
/**
|
|
* @brief Set all the relevant config registers for normal operation
|
|
*/
|
|
void TPS546_write_entire_config(void)
|
|
{
|
|
ESP_LOGI(TAG, "---Writing new config values to TPS546---");
|
|
/* set up the ON_OFF_CONFIG */
|
|
ESP_LOGI(TAG, "Setting ON_OFF_CONFIG");
|
|
if (smb_write_byte(PMBUS_ON_OFF_CONFIG, TPS546_INIT_ON_OFF_CONFIG) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Failed to write ON_OFF_CONFIG");
|
|
return;
|
|
}
|
|
|
|
/* Switch frequency */
|
|
ESP_LOGI(TAG, "Setting FREQUENCY");
|
|
smb_write_word(PMBUS_FREQUENCY_SWITCH, int_2_slinear11(TPS546_INIT_FREQUENCY));
|
|
|
|
/* vin voltage */
|
|
ESP_LOGI(TAG, "Setting VIN_ON: %.2f", TPS546_INIT_VIN_ON);
|
|
smb_write_word(PMBUS_VIN_ON, float_2_slinear11(TPS546_INIT_VIN_ON));
|
|
ESP_LOGI(TAG, "Setting VIN_OFF: %.2f", TPS546_INIT_VIN_OFF);
|
|
smb_write_word(PMBUS_VIN_OFF, float_2_slinear11(TPS546_INIT_VIN_OFF));
|
|
ESP_LOGI(TAG, "Setting VIN_UV_WARN_LIMIT: %.2f", TPS546_INIT_VIN_UV_WARN_LIMIT);
|
|
smb_write_word(PMBUS_VIN_UV_WARN_LIMIT, float_2_slinear11(TPS546_INIT_VIN_UV_WARN_LIMIT));
|
|
ESP_LOGI(TAG, "Setting VIN_OV_FAULT_LIMIT: %.2f", TPS546_INIT_VIN_OV_FAULT_LIMIT);
|
|
smb_write_word(PMBUS_VIN_OV_FAULT_LIMIT, float_2_slinear11(TPS546_INIT_VIN_OV_FAULT_LIMIT));
|
|
ESP_LOGI(TAG, "Setting VIN_OV_FAULT_RESPONSE: %02X", TPS546_INIT_VIN_OV_FAULT_RESPONSE);
|
|
smb_write_byte(PMBUS_VIN_OV_FAULT_RESPONSE, TPS546_INIT_VIN_OV_FAULT_RESPONSE);
|
|
|
|
/* vout voltage */
|
|
ESP_LOGI(TAG, "Setting VOUT SCALE: %.2f", TPS546_INIT_SCALE_LOOP);
|
|
smb_write_word(PMBUS_VOUT_SCALE_LOOP, float_2_slinear11(TPS546_INIT_SCALE_LOOP));
|
|
ESP_LOGI(TAG, "VOUT_COMMAND: %.2f", TPS546_INIT_VOUT_COMMAND);
|
|
smb_write_word(PMBUS_VOUT_COMMAND, float_2_ulinear16(TPS546_INIT_VOUT_COMMAND));
|
|
ESP_LOGI(TAG, "VOUT_MAX: %d", TPS546_INIT_VOUT_MAX);
|
|
smb_write_word(PMBUS_VOUT_MAX, float_2_ulinear16(TPS546_INIT_VOUT_MAX));
|
|
ESP_LOGI(TAG, "VOUT_OV_FAULT_LIMIT: %.2f", TPS546_INIT_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: %.2f", 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: %.2f", TPS546_INIT_VOUT_MARGIN_HIGH);
|
|
smb_write_word(PMBUS_VOUT_MARGIN_HIGH, float_2_ulinear16(TPS546_INIT_VOUT_MARGIN_HIGH));
|
|
ESP_LOGI(TAG, "VOUT_MARGIN_LOW: %.2f", TPS546_INIT_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: %.2f", 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: %.2f", TPS546_INIT_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: %d", TPS546_INIT_VOUT_MIN);
|
|
smb_write_word(PMBUS_VOUT_MIN, float_2_ulinear16(TPS546_INIT_VOUT_MIN));
|
|
|
|
/* iout current */
|
|
ESP_LOGI(TAG, "Setting IOUT");
|
|
smb_write_word(PMBUS_IOUT_OC_WARN_LIMIT, float_2_slinear11(TPS546_INIT_IOUT_OC_WARN_LIMIT));
|
|
smb_write_word(PMBUS_IOUT_OC_FAULT_LIMIT, float_2_slinear11(TPS546_INIT_IOUT_OC_FAULT_LIMIT));
|
|
smb_write_byte(PMBUS_IOUT_OC_FAULT_RESPONSE, TPS546_INIT_IOUT_OC_FAULT_RESPONSE);
|
|
|
|
/* temperature */
|
|
ESP_LOGI(TAG, "Setting TEMPERATURE");
|
|
ESP_LOGI(TAG, "OT_WARN_LIMIT: %d", TPS546_INIT_OT_WARN_LIMIT);
|
|
smb_write_word(PMBUS_OT_WARN_LIMIT, int_2_slinear11(TPS546_INIT_OT_WARN_LIMIT));
|
|
ESP_LOGI(TAG, "OT_FAULT_LIMIT: %d", TPS546_INIT_OT_FAULT_LIMIT);
|
|
smb_write_word(PMBUS_OT_FAULT_LIMIT, int_2_slinear11(TPS546_INIT_OT_FAULT_LIMIT));
|
|
ESP_LOGI(TAG, "OT_FAULT_RESPONSE: %02x", TPS546_INIT_OT_FAULT_RESPONSE);
|
|
smb_write_byte(PMBUS_OT_FAULT_RESPONSE, TPS546_INIT_OT_FAULT_RESPONSE);
|
|
|
|
/* timing */
|
|
ESP_LOGI(TAG, "Setting TIMING");
|
|
ESP_LOGI(TAG, "TON_DELAY: %d", TPS546_INIT_TON_DELAY);
|
|
smb_write_word(PMBUS_TON_DELAY, int_2_slinear11(TPS546_INIT_TON_DELAY));
|
|
ESP_LOGI(TAG, "TON_RISE: %d", TPS546_INIT_TON_RISE);
|
|
smb_write_word(PMBUS_TON_RISE, int_2_slinear11(TPS546_INIT_TON_RISE));
|
|
ESP_LOGI(TAG, "TON_MAX_FAULT_LIMIT: %d", TPS546_INIT_TON_MAX_FAULT_LIMIT);
|
|
smb_write_word(PMBUS_TON_MAX_FAULT_LIMIT, int_2_slinear11(TPS546_INIT_TON_MAX_FAULT_LIMIT));
|
|
ESP_LOGI(TAG, "TON_MAX_FAULT_RESPONSE: %02x", TPS546_INIT_TON_MAX_FAULT_RESPONSE);
|
|
smb_write_byte(PMBUS_TON_MAX_FAULT_RESPONSE, TPS546_INIT_TON_MAX_FAULT_RESPONSE);
|
|
ESP_LOGI(TAG, "TOFF_DELAY: %d", TPS546_INIT_TOFF_DELAY);
|
|
smb_write_word(PMBUS_TOFF_DELAY, int_2_slinear11(TPS546_INIT_TOFF_DELAY));
|
|
ESP_LOGI(TAG, "TOFF_FALL: %d", TPS546_INIT_TOFF_FALL);
|
|
smb_write_word(PMBUS_TOFF_FALL, int_2_slinear11(TPS546_INIT_TOFF_FALL));
|
|
|
|
/* Compensation config */
|
|
//ESP_LOGI(TAG, "COMPENSATION");
|
|
//smb_write_block(PMBUS_COMPENSATION_CONFIG, COMPENSATION_CONFIG, 5);
|
|
|
|
/* 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);
|
|
|
|
/* TODO write new MFR_REVISION number to reflect these parameters */
|
|
ESP_LOGI(TAG, "Writing MFR ID");
|
|
smb_write_block(PMBUS_MFR_ID, MFR_ID, 3);
|
|
ESP_LOGI(TAG, "Writing MFR MODEL");
|
|
smb_write_block(PMBUS_MFR_ID, MFR_MODEL, 3);
|
|
ESP_LOGI(TAG, "Writing MFR REVISION");
|
|
smb_write_block(PMBUS_MFR_ID, MFR_REVISION, 3);
|
|
|
|
/*
|
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
// Never write this to NVM as it can corrupt the TPS in an unrecoverable state, just do it on boot every time
|
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
*/
|
|
/* store configuration in NVM */
|
|
// ESP_LOGI(TAG, "---Saving new config---");
|
|
// smb_write_byte(PMBUS_STORE_USER_ALL, 0x98);
|
|
|
|
}
|
|
|
|
int TPS546_get_frequency(void)
|
|
{
|
|
uint16_t value;
|
|
int freq;
|
|
|
|
smb_read_word(PMBUS_FREQUENCY_SWITCH, &value);
|
|
freq = slinear11_2_int(value);
|
|
|
|
return (int)freq;
|
|
}
|
|
|
|
void TPS546_set_frequency(int newfreq)
|
|
{
|
|
uint16_t value;
|
|
//int freq;
|
|
|
|
ESP_LOGI(TAG, "Writing new frequency: %d", newfreq);
|
|
value = int_2_slinear11(newfreq);
|
|
//ESP_LOGI(TAG, "New value: 0x%04x", value);
|
|
smb_write_word(PMBUS_FREQUENCY_SWITCH, value);
|
|
|
|
//ESP_LOGI(TAG, "Checking conversion...");
|
|
//freq = slinear11_2_int(value);
|
|
//ESP_LOGI(TAG, "Converted value: %d", freq);
|
|
}
|
|
|
|
int TPS546_get_temperature(void)
|
|
{
|
|
uint16_t value;
|
|
int temp;
|
|
|
|
smb_read_word(PMBUS_READ_TEMPERATURE_1, &value);
|
|
temp = slinear11_2_int(value);
|
|
return temp;
|
|
}
|
|
|
|
float TPS546_get_vin(void)
|
|
{
|
|
uint16_t u16_value;
|
|
float vin;
|
|
|
|
/* Get voltage input (ULINEAR16) */
|
|
if (smb_read_word(PMBUS_READ_VIN, &u16_value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not read VIN");
|
|
return 0;
|
|
} else {
|
|
vin = slinear11_2_float(u16_value);
|
|
#ifdef _DEBUG_LOG_
|
|
ESP_LOGI(TAG, "Got Vin: %2.3f V", vin);
|
|
#endif
|
|
return vin;
|
|
}
|
|
}
|
|
|
|
float TPS546_get_iout(void)
|
|
{
|
|
uint16_t u16_value;
|
|
float iout;
|
|
|
|
/* Get current output (SLINEAR11) */
|
|
if (smb_read_word(PMBUS_READ_IOUT, &u16_value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not read Iout");
|
|
return 0;
|
|
} else {
|
|
iout = slinear11_2_float(u16_value);
|
|
|
|
#ifdef _DEBUG_LOG_
|
|
ESP_LOGI(TAG, "Got Iout: %2.3f A", iout);
|
|
#endif
|
|
|
|
return iout;
|
|
}
|
|
}
|
|
|
|
float TPS546_get_vout(void)
|
|
{
|
|
uint16_t u16_value;
|
|
float vout;
|
|
|
|
/* Get voltage output (ULINEAR16) */
|
|
if (smb_read_word(PMBUS_READ_VOUT, &u16_value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not read Vout");
|
|
return 0;
|
|
} else {
|
|
vout = ulinear16_2_float(u16_value);
|
|
#ifdef _DEBUG_LOG_
|
|
ESP_LOGI(TAG, "Got Vout: %2.3f V", vout);
|
|
#endif
|
|
return vout;
|
|
}
|
|
}
|
|
|
|
void TPS546_print_status(void) {
|
|
uint16_t u16_value;
|
|
uint8_t u8_value;
|
|
|
|
if (smb_read_word(PMBUS_STATUS_WORD, &u16_value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not read STATUS_WORD");
|
|
} else {
|
|
ESP_LOGI(TAG, "TPS546 Status: %04X", u16_value);
|
|
}
|
|
|
|
if (smb_read_byte(PMBUS_STATUS_VOUT, &u8_value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not read STATUS_VOUT");
|
|
} else {
|
|
ESP_LOGI(TAG, "TPS546 VOUT Status: %02X", u8_value);
|
|
}
|
|
|
|
if (smb_read_byte(PMBUS_STATUS_INPUT, &u8_value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not read STATUS_INPUT");
|
|
} else {
|
|
ESP_LOGI(TAG, "TPS546 INPUT Status: %02X", u8_value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the core voltage
|
|
* this function controls the regulator ontput state
|
|
* send it the desired output in millivolts
|
|
* A value between TPS546_INIT_VOUT_MIN and TPS546_INIT_VOUT_MAX
|
|
* send a 0 to turn off the output
|
|
* @param volts The desired output voltage
|
|
**/
|
|
void TPS546_set_vout(float volts)
|
|
{
|
|
uint16_t value;
|
|
|
|
if (volts == 0) {
|
|
/* turn off output */
|
|
if (smb_write_byte(PMBUS_OPERATION, OPERATION_OFF) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not turn off Vout");
|
|
}
|
|
} else {
|
|
/* make sure we're in range */
|
|
if ((volts < TPS546_INIT_VOUT_MIN) || (volts > TPS546_INIT_VOUT_MAX)) {
|
|
ESP_LOGE(TAG, "Voltage requested (%f V) is out of range", volts);
|
|
} else {
|
|
/* set the output voltage */
|
|
value = float_2_ulinear16(volts);
|
|
if (smb_write_word(PMBUS_VOUT_COMMAND, value) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not set Vout to %1.2f V", volts);
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Vout changed to %1.2f V", volts);
|
|
|
|
/* turn on output */
|
|
if (smb_write_byte(PMBUS_OPERATION, OPERATION_ON) != ESP_OK) {
|
|
ESP_LOGE(TAG, "Could not turn on Vout");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TPS546_show_voltage_settings(void)
|
|
{
|
|
uint16_t u16_value;
|
|
float f_value;
|
|
|
|
ESP_LOGI(TAG, "-----------VOLTAGE---------------------");
|
|
/* VIN_ON SLINEAR11 */
|
|
smb_read_word(PMBUS_VIN_ON, &u16_value);
|
|
f_value = slinear11_2_float(u16_value);
|
|
ESP_LOGI(TAG, "VIN ON set to: %.2f", f_value);
|
|
|
|
/* VIN_OFF SLINEAR11 */
|
|
smb_read_word(PMBUS_VIN_OFF, &u16_value);
|
|
f_value = slinear11_2_float(u16_value);
|
|
ESP_LOGI(TAG, "VIN OFF set to: %.2f", f_value);
|
|
|
|
/* VOUT_MAX */
|
|
smb_read_word(PMBUS_VOUT_MAX, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout Max set to: %.2f V", f_value);
|
|
|
|
/* VOUT_OV_FAULT_LIMIT */
|
|
smb_read_word(PMBUS_VOUT_OV_FAULT_LIMIT, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout OV Fault Limit: %.2f V", f_value);
|
|
|
|
/* VOUT_OV_WARN_LIMIT */
|
|
smb_read_word(PMBUS_VOUT_OV_WARN_LIMIT, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout OV Warn Limit: %.2f V", f_value);
|
|
|
|
/* VOUT_MARGIN_HIGH */
|
|
smb_read_word(PMBUS_VOUT_MARGIN_HIGH, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout Margin HIGH: %.2f V", f_value);
|
|
|
|
/* --- VOUT_COMMAND --- */
|
|
smb_read_word(PMBUS_VOUT_COMMAND, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout set to: %.2f V", f_value);
|
|
|
|
/* VOUT_MARGIN_LOW */
|
|
smb_read_word(PMBUS_VOUT_MARGIN_LOW, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout Margin LOW: %.2f V", f_value);
|
|
|
|
/* VOUT_UV_WARN_LIMIT */
|
|
smb_read_word(PMBUS_VOUT_UV_WARN_LIMIT, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout UV Warn Limit: %.2f V", f_value);
|
|
|
|
/* VOUT_UV_FAULT_LIMIT */
|
|
smb_read_word(PMBUS_VOUT_UV_FAULT_LIMIT, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout UV Fault Limit: %.2f V", f_value);
|
|
|
|
/* VOUT_MIN */
|
|
smb_read_word(PMBUS_VOUT_MIN, &u16_value);
|
|
f_value = ulinear16_2_float(u16_value);
|
|
ESP_LOGI(TAG, "Vout Min set to: %.2f V", f_value);
|
|
}
|
|
|