2023-01-16 17:55:16 -05:00
|
|
|
#include <stdio.h>
|
2023-01-17 00:07:21 -05:00
|
|
|
#include <math.h>
|
2023-01-16 17:55:16 -05:00
|
|
|
#include "esp_log.h"
|
|
|
|
#include "driver/i2c.h"
|
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
#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
|
|
|
|
|
|
|
|
// DS4432U+ -- Adjustable current DAC for use with the TPS40305 voltage regulator
|
|
|
|
// address: 0x90
|
|
|
|
#define DS4432U_SENSOR_ADDR 0x48 // Slave address of the DS4432U+
|
|
|
|
#define DS4432U_OUT0_REG 0xF8 // register for current output 0
|
|
|
|
#define DS4432U_OUT1_REG 0xF9 // register for current output 1
|
|
|
|
|
|
|
|
// DS4432U Transfer function constants
|
2023-01-17 00:07:21 -05:00
|
|
|
#define VFB 0.6
|
|
|
|
#define IFS 0.000098921 // (Vrfs / Rfs) x (127/16) -> Vrfs = 0.997, Rfs = 80000
|
2023-08-26 12:28:17 -04:00
|
|
|
#define RA 4750.0 // R14
|
|
|
|
#define RB 3320.0 // R15
|
|
|
|
#define NOMINAL 1.451 // this is with the current DAC set to 0. Should be pretty close to (VFB*(RA+RB))/RB
|
2023-01-17 00:07:21 -05:00
|
|
|
#define MAXV 2.39
|
|
|
|
#define MINV 0.046
|
|
|
|
|
2023-01-16 17:55:16 -05:00
|
|
|
static const char *TAG = "DS4432U.c";
|
|
|
|
|
2023-01-17 00:07:21 -05:00
|
|
|
/**
|
|
|
|
* @brief voltage_to_reg takes a voltage and returns a register setting for the DS4432U to get that voltage on the TPS40305
|
|
|
|
* careful with this one!!
|
|
|
|
*/
|
2023-08-26 12:28:17 -04:00
|
|
|
static uint8_t voltage_to_reg(float vout)
|
|
|
|
{
|
|
|
|
float change;
|
2023-01-17 00:07:21 -05:00
|
|
|
uint8_t reg;
|
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
// make sure the requested voltage is in within range of MINV and MAXV
|
|
|
|
if (vout > MAXV || vout < MINV)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2023-01-17 00:07:21 -05:00
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
// this is the transfer function. comes from the DS4432U+ datasheet
|
|
|
|
change = fabs((((VFB / RB) - ((vout - VFB) / RA)) / IFS) * 127);
|
|
|
|
reg = (uint8_t)ceil(change);
|
2023-01-17 00:07:21 -05:00
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
// Set the MSB high if the requested voltage is BELOW nominal
|
|
|
|
if (vout < NOMINAL)
|
|
|
|
{
|
|
|
|
reg |= 0x80;
|
|
|
|
}
|
2023-01-17 00:07:21 -05:00
|
|
|
|
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
2023-01-16 17:55:16 -05:00
|
|
|
/**
|
|
|
|
* @brief i2c master initialization
|
|
|
|
*/
|
2023-08-26 12:28:17 -04:00
|
|
|
esp_err_t i2c_master_init(void)
|
|
|
|
{
|
2023-01-16 17:55:16 -05:00
|
|
|
int i2c_master_port = I2C_MASTER_NUM;
|
|
|
|
|
|
|
|
i2c_config_t conf = {
|
|
|
|
.mode = I2C_MODE_MASTER,
|
|
|
|
.sda_io_num = I2C_MASTER_SDA_IO,
|
|
|
|
.scl_io_num = I2C_MASTER_SCL_IO,
|
|
|
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
|
|
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
|
|
|
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
|
|
|
};
|
|
|
|
|
|
|
|
i2c_param_config(i2c_master_port, &conf);
|
|
|
|
|
|
|
|
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief i2c master delete
|
|
|
|
*/
|
2023-08-26 12:28:17 -04:00
|
|
|
esp_err_t i2c_master_delete(void)
|
|
|
|
{
|
2023-01-16 17:55:16 -05:00
|
|
|
return i2c_driver_delete(I2C_MASTER_NUM);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Read a sequence of I2C bytes
|
|
|
|
*/
|
2023-08-26 12:28:17 -04:00
|
|
|
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, DS4432U_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
2023-01-16 17:55:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Write a byte to a I2C register
|
|
|
|
*/
|
2023-08-26 12:28:17 -04:00
|
|
|
static esp_err_t register_write_byte(uint8_t reg_addr, uint8_t data)
|
|
|
|
{
|
2023-01-17 00:07:21 -05:00
|
|
|
int ret;
|
|
|
|
uint8_t write_buf[2] = {reg_addr, data};
|
2023-01-16 17:55:16 -05:00
|
|
|
|
2023-08-16 16:55:10 +02:00
|
|
|
ret = i2c_master_write_to_device(I2C_MASTER_NUM, DS4432U_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
2023-01-16 17:55:16 -05:00
|
|
|
|
2023-01-17 00:07:21 -05:00
|
|
|
return ret;
|
|
|
|
}
|
2023-01-16 17:55:16 -05:00
|
|
|
|
2024-03-18 00:46:59 -04:00
|
|
|
bool DS4432U_test(void)
|
|
|
|
{
|
|
|
|
uint8_t data[3];
|
|
|
|
|
|
|
|
/* Read the DS4432U+ WHO_AM_I register, on power up the register should have the value 0x00 */
|
|
|
|
esp_err_t register_result = register_read(DS4432U_OUT0_REG, data, 1);
|
|
|
|
ESP_LOGI(TAG, "DS4432U+ OUT1 = 0x%02X", data[0]);
|
|
|
|
return register_result == ESP_OK;
|
|
|
|
}
|
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
void DS4432U_read(void)
|
|
|
|
{
|
2023-01-16 17:55:16 -05:00
|
|
|
uint8_t data[3];
|
2023-01-17 00:07:21 -05:00
|
|
|
|
2023-01-16 17:55:16 -05:00
|
|
|
/* Read the DS4432U+ WHO_AM_I register, on power up the register should have the value 0x00 */
|
2023-01-17 00:07:21 -05:00
|
|
|
ESP_ERROR_CHECK(register_read(DS4432U_OUT0_REG, data, 1));
|
2023-01-16 17:55:16 -05:00
|
|
|
ESP_LOGI(TAG, "DS4432U+ OUT1 = 0x%02X", data[0]);
|
2023-01-17 00:07:21 -05:00
|
|
|
}
|
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
static void DS4432U_set(uint8_t val)
|
|
|
|
{
|
2023-01-17 00:07:21 -05:00
|
|
|
ESP_LOGI(TAG, "Writing 0x%02X", val);
|
|
|
|
ESP_ERROR_CHECK(register_write_byte(DS4432U_OUT0_REG, val));
|
2023-01-19 23:45:31 -05:00
|
|
|
}
|
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
bool DS4432U_set_vcore(float core_voltage)
|
|
|
|
{
|
2023-01-19 23:45:31 -05:00
|
|
|
uint8_t reg_setting;
|
|
|
|
|
|
|
|
reg_setting = voltage_to_reg(core_voltage);
|
|
|
|
|
2024-03-17 15:37:41 -04:00
|
|
|
ESP_LOGI(TAG, "Set ASIC voltage = %.3fV [0x%02X]", core_voltage, reg_setting);
|
2023-01-19 23:45:31 -05:00
|
|
|
|
2023-08-26 12:28:17 -04:00
|
|
|
DS4432U_set(reg_setting); /// eek!
|
2023-01-19 23:45:31 -05:00
|
|
|
|
|
|
|
return true;
|
2023-01-16 17:55:16 -05:00
|
|
|
}
|