Fix compiler warnings (#381)

Fix all compiler warnings and migrate off depreciated ADC and I2C libraries.
---------
Co-authored-by: Erik Olof Gunnar Andersson <eandersson@users.noreply.github.com>
This commit is contained in:
Skot 2024-10-08 10:27:32 -05:00 committed by GitHub
parent 3d15c25a07
commit e1bf30b26e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 816 additions and 563 deletions

View File

@ -6,6 +6,7 @@ SRCS
"bm1397.c"
"serial.c"
"crc.c"
"common.c"
INCLUDE_DIRS
"include"

View File

@ -516,13 +516,13 @@ static void _reset(void)
vTaskDelay(100 / portTICK_PERIOD_MS);
}
static void _send_read_address(void)
{
// static void _send_read_address(void)
// {
unsigned char read_address[2] = {0x00, 0x00};
// send serial data
_send_BM1366((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1366_SERIALTX_DEBUG);
}
// unsigned char read_address[2] = {0x00, 0x00};
// // send serial data
// _send_BM1366((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1366_SERIALTX_DEBUG);
// }
uint8_t BM1366_init(uint64_t frequency, uint16_t asic_count)
{
@ -625,7 +625,7 @@ void BM1366_send_work(void * pvParameters, bm_job * next_bm_job)
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
#endif
_send_BM1366((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), &job, sizeof(BM1366_job), BM1366_DEBUG_WORK);
_send_BM1366((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1366_job), BM1366_DEBUG_WORK);
}
asic_result * BM1366_receive_work(void)

View File

@ -365,7 +365,7 @@ void BM1368_send_work(void * pvParameters, bm_job * next_bm_job)
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
#endif
_send_BM1368((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), &job, sizeof(BM1368_job), BM1368_DEBUG_WORK);
_send_BM1368((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1368_job), BM1368_DEBUG_WORK);
}
asic_result * BM1368_receive_work(void)

View File

@ -327,13 +327,13 @@ static void _reset(void)
vTaskDelay(100 / portTICK_PERIOD_MS);
}
static void _send_read_address(void)
{
// static void _send_read_address(void)
// {
unsigned char read_address[2] = {0x00, 0x00};
// send serial data
_send_BM1370((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1370_SERIALTX_DEBUG);
}
// unsigned char read_address[2] = {0x00, 0x00};
// // send serial data
// _send_BM1370((TYPE_CMD | GROUP_ALL | CMD_READ), read_address, 2, BM1370_SERIALTX_DEBUG);
// }
uint8_t BM1370_init(uint64_t frequency, uint16_t asic_count)
{
@ -432,7 +432,7 @@ void BM1370_send_work(void * pvParameters, bm_job * next_bm_job)
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
#endif
_send_BM1370((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), &job, sizeof(BM1370_job), BM1370_DEBUG_WORK);
_send_BM1370((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(BM1370_job), BM1370_DEBUG_WORK);
}
asic_result * BM1370_receive_work(void)

View File

@ -394,7 +394,7 @@ void BM1397_send_work(void *pvParameters, bm_job *next_bm_job)
ESP_LOGI(TAG, "Send Job: %02X", job.job_id);
#endif
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), &job, sizeof(job_packet), BM1397_DEBUG_WORK);
_send_BM1397((TYPE_JOB | GROUP_SINGLE | CMD_WRITE), (uint8_t *)&job, sizeof(job_packet), BM1397_DEBUG_WORK);
}
asic_result *BM1397_receive_work(void)

27
components/asic/common.c Normal file
View File

@ -0,0 +1,27 @@
#include "common.h"
unsigned char _reverse_bits(unsigned char num)
{
unsigned char reversed = 0;
int i;
for (i = 0; i < 8; i++) {
reversed <<= 1; // Left shift the reversed variable by 1
reversed |= num & 1; // Use bitwise OR to set the rightmost bit of reversed to the current bit of num
num >>= 1; // Right shift num by 1 to get the next bit
}
return reversed;
}
int _largest_power_of_two(int num)
{
int power = 0;
while (num > 1) {
num = num >> 1;
power++;
}
return 1 << power;
}

View File

@ -10,30 +10,7 @@ typedef struct __attribute__((__packed__))
uint32_t rolled_version;
} task_result;
static unsigned char _reverse_bits(unsigned char num)
{
unsigned char reversed = 0;
int i;
for (i = 0; i < 8; i++) {
reversed <<= 1; // Left shift the reversed variable by 1
reversed |= num & 1; // Use bitwise OR to set the rightmost bit of reversed to the current bit of num
num >>= 1; // Right shift num by 1 to get the next bit
}
return reversed;
}
static int _largest_power_of_two(int num)
{
int power = 0;
while (num > 1) {
num = num >> 1;
power++;
}
return 1 << power;
}
unsigned char _reverse_bits(unsigned char num);
int _largest_power_of_two(int num);
#endif

View File

@ -201,7 +201,7 @@ void wifi_init(const char * wifi_ssid, const char * wifi_pass, const char * host
/* Initialize AP */
ESP_LOGI(TAG, "ESP_WIFI Access Point On");
esp_netif_t * esp_netif_ap = wifi_init_softap();
wifi_init_softap();
/* Initialize STA */
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");

View File

@ -310,7 +310,7 @@ int STRATUM_V1_subscribe(int socket, char * model)
{
// Subscribe
char subscribe_msg[BUFFER_SIZE];
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
const esp_app_desc_t *app_desc = esp_app_get_description();
const char *version = app_desc->version;
sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe/%s/%s\"]}\n", send_uid++, model, version);
debug_stratum_tx(subscribe_msg);

View File

@ -4,14 +4,13 @@ SRCS
"DS4432U.c"
"EMC2101.c"
"fonts.c"
"i2c_master.c"
"i2c_bitaxe.c"
"INA260.c"
"led_controller.c"
"main.c"
"nvs_config.c"
"oled.c"
"system.c"
"TMP1075.c"
"TPS546.c"
"vcore.c"
"work_queue.c"
@ -47,6 +46,7 @@ PRIV_REQUIRES
"nvs_flash"
"spiffs"
"vfs"
"esp_driver_i2c"
)
set(WEB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/http_server/axe-os")

View File

@ -2,8 +2,7 @@
#include <math.h>
#include "esp_log.h"
#include "i2c_master.h"
#include "i2c_bitaxe.h"
#include "DS4432U.h"
// DS4432U+ -- Adjustable current DAC
@ -13,6 +12,17 @@
static const char *TAG = "DS4432U";
static i2c_master_dev_handle_t ds4432u_dev_handle;
/**
* @brief Initialize the DS4432U+ sensor.
*
* @return esp_err_t ESP_OK on success, or an error code on failure.
*/
esp_err_t DS4432U_init(void) {
return i2c_bitaxe_add_device(DS4432U_SENSOR_ADDR, &ds4432u_dev_handle);
}
/**
* @brief Set the current DAC code for a specific DS4432U output.
*
@ -22,7 +32,7 @@ static const char *TAG = "DS4432U";
*/
esp_err_t DS4432U_set_current_code(uint8_t output, uint8_t code) {
uint8_t reg = (output == 0) ? DS4432U_OUT0_REG : DS4432U_OUT1_REG;
return i2c_master_register_write_byte(DS4432U_SENSOR_ADDR, reg, code);
return i2c_bitaxe_register_write_byte(ds4432u_dev_handle, reg, code);
}
/**
@ -34,7 +44,7 @@ esp_err_t DS4432U_set_current_code(uint8_t output, uint8_t code) {
*/
esp_err_t DS4432U_get_current_code(uint8_t output, uint8_t *code) {
uint8_t reg = (output == 0) ? DS4432U_OUT0_REG : DS4432U_OUT1_REG;
return i2c_master_register_read(DS4432U_SENSOR_ADDR, reg, code, 1);
return i2c_bitaxe_register_read(ds4432u_dev_handle, reg, code, 1);
}
bool DS4432U_test(void)
@ -42,7 +52,7 @@ bool DS4432U_test(void)
uint8_t data;
/* Read the DS4432U+ WHO_AM_I register, on power up the register should have the value 0x00 */
esp_err_t register_result = i2c_master_register_read(DS4432U_SENSOR_ADDR, DS4432U_OUT0_REG, &data, 1);
esp_err_t register_result = i2c_bitaxe_register_read(ds4432u_dev_handle, DS4432U_OUT0_REG, &data, 1);
ESP_LOGI(TAG, "DS4432U+ OUT0 = 0x%02X", data);
return register_result == ESP_OK;
}

View File

@ -7,6 +7,7 @@
#define DS4432_VRFS 0.997
bool DS4432U_test(void);
esp_err_t DS4432U_init(void);
esp_err_t DS4432U_set_current_code(uint8_t output, uint8_t code);
esp_err_t DS4432U_get_current_code(uint8_t output, uint8_t *code);

View File

@ -1,22 +1,36 @@
#include "esp_log.h"
#include <stdio.h>
#include "esp_log.h"
#include "i2c_bitaxe.h"
#include "EMC2101.h"
static const char * TAG = "EMC2101";
// static const char *TAG = "EMC2101.c";
// run this first. sets up the config register
void EMC2101_init(bool invertPolarity)
{
static i2c_master_dev_handle_t emc2101_dev_handle;
/**
* @brief Initialize the EMC2101 sensor.
*
* @return esp_err_t ESP_OK on success, or an error code on failure.
*/
esp_err_t EMC2101_init(bool invertPolarity) {
if (i2c_bitaxe_add_device(EMC2101_I2CADDR_DEFAULT, &emc2101_dev_handle) != ESP_OK) {
ESP_LOGE(TAG, "Failed to add device");
return ESP_FAIL;
}
// set the TACH input
ESP_ERROR_CHECK(i2c_master_register_write_byte(EMC2101_I2CADDR_DEFAULT, EMC2101_REG_CONFIG, 0x04));
ESP_ERROR_CHECK(i2c_bitaxe_register_write_byte(emc2101_dev_handle, EMC2101_REG_CONFIG, 0x04));
if (invertPolarity) {
ESP_ERROR_CHECK(i2c_master_register_write_byte(EMC2101_I2CADDR_DEFAULT, EMC2101_FAN_CONFIG, 0b00100011));
ESP_ERROR_CHECK(i2c_bitaxe_register_write_byte(emc2101_dev_handle, EMC2101_FAN_CONFIG, 0b00100011));
}
return ESP_OK;
}
// takes a fan speed percent
@ -25,7 +39,7 @@ void EMC2101_set_fan_speed(float percent)
uint8_t speed;
speed = (uint8_t) (63.0 * percent);
ESP_ERROR_CHECK(i2c_master_register_write_byte(EMC2101_I2CADDR_DEFAULT, EMC2101_REG_FAN_SETTING, speed));
ESP_ERROR_CHECK(i2c_bitaxe_register_write_byte(emc2101_dev_handle, EMC2101_REG_FAN_SETTING, speed));
}
// RPM = 5400000/reading
@ -35,8 +49,8 @@ uint16_t EMC2101_get_fan_speed(void)
uint16_t reading;
uint16_t RPM;
ESP_ERROR_CHECK(i2c_master_register_read(EMC2101_I2CADDR_DEFAULT, EMC2101_TACH_LSB, &tach_lsb, 1));
ESP_ERROR_CHECK(i2c_master_register_read(EMC2101_I2CADDR_DEFAULT, EMC2101_TACH_MSB, &tach_msb, 1));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(emc2101_dev_handle, EMC2101_TACH_LSB, &tach_lsb, 1));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(emc2101_dev_handle, EMC2101_TACH_MSB, &tach_msb, 1));
// ESP_LOGI(TAG, "Raw Fan Speed = %02X %02X", tach_msb, tach_lsb);
@ -55,8 +69,8 @@ float EMC2101_get_external_temp(void)
uint8_t temp_msb, temp_lsb;
uint16_t reading;
ESP_ERROR_CHECK(i2c_master_register_read(EMC2101_I2CADDR_DEFAULT, EMC2101_EXTERNAL_TEMP_MSB, &temp_msb, 1));
ESP_ERROR_CHECK(i2c_master_register_read(EMC2101_I2CADDR_DEFAULT, EMC2101_EXTERNAL_TEMP_LSB, &temp_lsb, 1));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(emc2101_dev_handle, EMC2101_EXTERNAL_TEMP_MSB, &temp_msb, 1));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(emc2101_dev_handle, EMC2101_EXTERNAL_TEMP_LSB, &temp_lsb, 1));
reading = temp_lsb | (temp_msb << 8);
reading >>= 5;
@ -80,6 +94,6 @@ float EMC2101_get_external_temp(void)
uint8_t EMC2101_get_internal_temp(void)
{
uint8_t temp;
ESP_ERROR_CHECK(i2c_master_register_read(EMC2101_I2CADDR_DEFAULT, EMC2101_INTERNAL_TEMP, &temp, 1));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(emc2101_dev_handle, EMC2101_INTERNAL_TEMP, &temp, 1));
return temp;
}

View File

@ -1,7 +1,7 @@
#ifndef EMC2101_H_
#define EMC2101_H_
#include "i2c_master.h"
#include "i2c_bitaxe.h"
#define EMC2101_I2CADDR_DEFAULT 0x4C ///< EMC2101 default i2c address
#define EMC2101_CHIP_ID 0x16 ///< EMC2101 default device id from part id
@ -88,7 +88,7 @@ typedef enum
void EMC2101_set_fan_speed(float);
// void EMC2101_read(void);
uint16_t EMC2101_get_fan_speed(void);
void EMC2101_init(bool);
esp_err_t EMC2101_init(bool);
float EMC2101_get_external_temp(void);
uint8_t EMC2101_get_internal_temp(void);
#endif /* EMC2101_H_ */

View File

@ -1,21 +1,33 @@
#include <stdio.h>
#include "esp_log.h"
#include "i2c_bitaxe.h"
#include "INA260.h"
// static const char *TAG = "INA260.c";
static i2c_master_dev_handle_t ina260_dev_handle;
/**
* @brief Initialize the INA260 sensor.
*
* @return esp_err_t ESP_OK on success, or an error code on failure.
*/
esp_err_t INA260_init(void) {
return i2c_bitaxe_add_device(INA260_I2CADDR_DEFAULT, &ina260_dev_handle);
}
bool INA260_installed(void)
{
uint8_t data[2];
return i2c_master_register_read(INA260_I2CADDR_DEFAULT, INA260_REG_BUSVOLTAGE, data, 2) == ESP_OK;
return i2c_bitaxe_register_read(ina260_dev_handle, INA260_REG_BUSVOLTAGE, data, 2) == ESP_OK;
}
float INA260_read_current(void)
{
uint8_t data[2];
ESP_ERROR_CHECK(i2c_master_register_read(INA260_I2CADDR_DEFAULT, INA260_REG_CURRENT, data, 2));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(ina260_dev_handle, INA260_REG_CURRENT, data, 2));
// ESP_LOGI(TAG, "Raw Current = %02X %02X", data[1], data[0]);
return (uint16_t)(data[1] | (data[0] << 8)) * 1.25;
@ -25,7 +37,7 @@ float INA260_read_voltage(void)
{
uint8_t data[2];
ESP_ERROR_CHECK(i2c_master_register_read(INA260_I2CADDR_DEFAULT, INA260_REG_BUSVOLTAGE, data, 2));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(ina260_dev_handle, INA260_REG_BUSVOLTAGE, data, 2));
// ESP_LOGI(TAG, "Raw Voltage = %02X %02X", data[1], data[0]);
return (uint16_t)(data[1] | (data[0] << 8)) * 1.25;
@ -35,7 +47,7 @@ float INA260_read_power(void)
{
uint8_t data[2];
ESP_ERROR_CHECK(i2c_master_register_read(INA260_I2CADDR_DEFAULT, INA260_REG_POWER, data, 2));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(ina260_dev_handle, INA260_REG_POWER, data, 2));
// ESP_LOGI(TAG, "Raw Power = %02X %02X", data[1], data[0]);
return (data[1] | (data[0] << 8)) * 10;

View File

@ -1,7 +1,7 @@
#ifndef INA260_H_
#define INA260_H_
#include "i2c_master.h"
#include "i2c_bitaxe.h"
#define INA260_I2CADDR_DEFAULT 0x40 ///< INA260 default i2c address
#define INA260_REG_CONFIG 0x00 ///< Configuration register
@ -104,6 +104,8 @@ typedef enum _alert_latch
INA260_ALERT_LATCH_TRANSPARENT = 0x0, /**< Alert will reset when fault is
cleared **/
} INA260_AlertLatch;
esp_err_t INA260_init(void);
bool INA260_installed(void);
float INA260_read_current(void);
float INA260_read_voltage(void);

View File

@ -1,13 +1,21 @@
#include <stdio.h>
#include "esp_log.h"
#include "i2c_master.h"
#include "i2c_bitaxe.h"
#include "TMP1075.h"
static const char *TAG = "TMP1075.c";
// static const char *TAG = "TMP1075.c";
bool TMP1075_installed(int);
uint8_t TMP1075_read_temperature(int);
static i2c_master_dev_handle_t tmp1075_dev_handle;
/**
* @brief Initialize the TMP1075 sensor.
*
* @return esp_err_t ESP_OK on success, or an error code on failure.
*/
esp_err_t TMP1075_init(void) {
return i2c_bitaxe_add_device(TMP1075_I2CADDR_DEFAULT, &tmp1075_dev_handle);
}
bool TMP1075_installed(int device_index)
{
@ -16,7 +24,7 @@ bool TMP1075_installed(int device_index)
// read the configuration register
//ESP_LOGI(TAG, "Reading configuration register");
ESP_ERROR_CHECK(i2c_master_register_read(TMP1075_I2CADDR_DEFAULT + device_index, TMP1075_CONFIG_REG, data, 2));
result = i2c_bitaxe_register_read(tmp1075_dev_handle, TMP1075_CONFIG_REG, data, 2);
//ESP_LOGI(TAG, "Configuration[%d] = %02X %02X", device_index, data[0], data[1]);
return (result == ESP_OK?true:false);
@ -26,7 +34,7 @@ uint8_t TMP1075_read_temperature(int device_index)
{
uint8_t data[2];
ESP_ERROR_CHECK(i2c_master_register_read(TMP1075_I2CADDR_DEFAULT + device_index, TMP1075_TEMP_REG, data, 2));
ESP_ERROR_CHECK(i2c_bitaxe_register_read(tmp1075_dev_handle, TMP1075_TEMP_REG, data, 2));
//ESP_LOGI(TAG, "Raw Temperature = %02X %02X", data[0], data[1]);
//ESP_LOGI(TAG, "Temperature[%d] = %d", device_index, data[0]);
return data[0];

View File

@ -10,5 +10,6 @@
bool TMP1075_installed(int);
uint8_t TMP1075_read_temperature(int);
esp_err_t TMP1075_init(void);
#endif /* TMP1075_H_ */

View File

@ -1,13 +1,15 @@
#include "driver/i2c.h"
#include "esp_log.h"
#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
@ -29,153 +31,105 @@ 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 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)
{
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);
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);
// return get an actual error status
return err;
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)
{
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_write_byte(cmd, data, ACK_CHECK);
i2c_master_stop(cmd);
ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, SMBUS_DEFAULT_TIMEOUT));
i2c_cmd_link_delete(cmd);
// TODO return an actual error status
return err;
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];
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);
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);
*result = (data[1] << 8) + data[0];
// TODO return an actual error status
return err;
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)
{
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_write_byte(cmd, (uint8_t)(data & 0x00FF), ACK_CHECK);
i2c_master_write_byte(cmd, (uint8_t)((data & 0xFF00) >> 8), 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);
// TODO return an actual error status
return err;
return i2c_bitaxe_register_write_word(tps546_dev_handle, command, data);
}
/**
* @brief SMBus read block
* @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)
{
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);
//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;
}
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);
//copy the data into the buffer
memcpy(data, buf+1, len);
free(buf);
// TODO return an actual error status
return 0;
return ESP_OK;
}
/**
* @brief SMBus write block
* @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)
{
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_write_byte(cmd, len, ACK_CHECK);
for (size_t i = 0; i < len; ++i)
{
i2c_master_write_byte(cmd, data[i], ACK_CHECK);
}
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);
//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);
// TODO return an actual error status
return 0;
//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)
{
@ -206,6 +160,7 @@ static int slinear11_2_int(uint16_t value)
/**
* @brief Convert an SLINEAR11 value into an int
* @param value The SLINEAR11 value to convert
*/
static float slinear11_2_float(uint16_t value)
{
@ -236,6 +191,7 @@ static float slinear11_2_float(uint16_t value)
/**
* @brief Convert an int value into an SLINEAR11
* @param value The int value to convert
*/
static uint16_t int_2_slinear11(int value)
{
@ -271,6 +227,7 @@ static uint16_t int_2_slinear11(int value)
/**
* @brief Convert a float value into an SLINEAR11
* @param value The float value to convert
*/
static uint16_t float_2_slinear11(float value)
{
@ -310,6 +267,7 @@ static uint16_t float_2_slinear11(float value)
* 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)
{
@ -334,7 +292,8 @@ static float ulinear16_2_float(uint16_t value)
* 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;
@ -356,29 +315,33 @@ static uint16_t float_2_ulinear16(float value)
/*--- Public TPS546 functions ---*/
// Set up the TPS546 regulator and turn it on
/**
* @brief Set up the TPS546 regulator and turn it on
*/
int TPS546_init(void)
{
uint8_t data[6];
uint8_t data[7];
uint8_t u8_value;
uint16_t u16_value;
float vin;
float iout;
float vout;
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);
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_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_LOGI(TAG, "ERROR- cannot find TPS546 regulator");
ESP_LOGE(TAG, "Cannot find TPS546 regulator - Device ID mismatch");
return -1;
}
@ -391,7 +354,7 @@ int TPS546_init(void)
/* Read version number and see if it matches */
TPS546_read_mfr_info(read_mfr_revision);
// if (memcmp(read_mfr_revision, MFR_REVISION, 3) != 0) {
uint8_t voutmode;
// 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");
@ -401,24 +364,26 @@ int TPS546_init(void)
TPS546_write_entire_config();
//}
/* Show temperature */
ESP_LOGI(TAG, "--------------------------------");
ESP_LOGI(TAG, "Temp: %d", TPS546_get_temperature());
// /* Show temperature */
// ESP_LOGI(TAG, "--------------------------------");
// ESP_LOGI(TAG, "Temp: %d", TPS546_get_temperature());
/* Show switching frequency */
TPS546_get_frequency();
TPS546_set_frequency(650);
// /* Show switching frequency */
// TPS546_get_frequency();
// TPS546_set_frequency(650);
/* Show voltage settings */
TPS546_show_voltage_settings();
ESP_LOGI(TAG, "-----------VOLTAGE/CURRENT---------------------");
/* Get voltage input (SLINEAR11) */
TPS546_get_vin();
/* Get output current (SLINEAR11) */
TPS546_get_iout();
/* Get voltage output (ULINEAR16) */
TPS546_get_vout();
//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);
@ -441,7 +406,10 @@ int TPS546_init(void)
ESP_LOGI(TAG, "--------------------------------------");
// Read the compensation config registers
smb_read_block(PMBUS_COMPENSATION_CONFIG, comp_config, 5);
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]);
@ -449,18 +417,30 @@ int TPS546_init(void)
return 0;
}
/* Read the manufacturer model and revision */
/**
* @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");
smb_read_block(PMBUS_MFR_ID, read_mfr_id, 3);
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;
smb_read_block(PMBUS_MFR_MODEL, read_mfr_model, 3);
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;
smb_read_block(PMBUS_MFR_REVISION, read_mfr_revision, 3);
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);
@ -468,7 +448,9 @@ void TPS546_read_mfr_info(uint8_t *read_mfr_revision)
read_mfr_revision[1], read_mfr_revision[2]);
}
/* Write the manufacturer ID and revision to NVM */
/**
* @brief Write the manufacturer ID and revision to NVM
*/
void TPS546_set_mfr_info(void)
{
ESP_LOGI(TAG, "Setting MFR info");
@ -477,46 +459,55 @@ void TPS546_set_mfr_info(void)
smb_write_block(PMBUS_MFR_REVISION, MFR_REVISION, 3);
}
/* Set all the relevant config registers for normal operation */
/**
* @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");
smb_write_byte(PMBUS_ON_OFF_CONFIG, TPS546_INIT_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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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");
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 */
@ -527,23 +518,26 @@ void TPS546_write_entire_config(void)
/* temperature */
ESP_LOGI(TAG, "Setting TEMPERATURE");
ESP_LOGI(TAG, "OT_WARN_LIMIT");
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");
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");
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");
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");
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");
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 */
@ -587,7 +581,7 @@ int TPS546_get_frequency(void)
void TPS546_set_frequency(int newfreq)
{
uint16_t value;
int freq;
//int freq;
ESP_LOGI(TAG, "Writing new frequency: %d", newfreq);
value = int_2_slinear11(newfreq);
@ -615,12 +609,16 @@ float TPS546_get_vin(void)
float vin;
/* Get voltage input (ULINEAR16) */
smb_read_word(PMBUS_READ_VIN, &u16_value);
vin = slinear11_2_float(u16_value);
#ifdef _DEBUG_LOG_
ESP_LOGI(TAG, "Got Vin: %2.3f V", vin);
#endif
return vin;
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)
@ -629,14 +627,18 @@ float TPS546_get_iout(void)
float iout;
/* Get current output (SLINEAR11) */
smb_read_word(PMBUS_READ_IOUT, &u16_value);
iout = slinear11_2_float(u16_value);
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
#ifdef _DEBUG_LOG_
ESP_LOGI(TAG, "Got Iout: %2.3f A", iout);
#endif
return iout;
return iout;
}
}
float TPS546_get_vout(void)
@ -645,12 +647,39 @@ float TPS546_get_vout(void)
float vout;
/* Get voltage output (ULINEAR16) */
smb_read_word(PMBUS_READ_VOUT, &u16_value);
vout = ulinear16_2_float(u16_value);
#ifdef _DEBUG_LOG_
ESP_LOGI(TAG, "Got Vout: %2.3f V", vout);
#endif
return vout;
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);
}
}
/**
@ -659,6 +688,7 @@ float TPS546_get_vout(void)
* 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)
{
@ -666,19 +696,26 @@ void TPS546_set_vout(float volts)
if (volts == 0) {
/* turn off output */
smb_write_byte(PMBUS_OPERATION, OPERATION_OFF);
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_LOGI(TAG, "ERR- Voltage requested (%f V) is out of range", volts);
ESP_LOGE(TAG, "Voltage requested (%f V) is out of range", volts);
} else {
/* set the output voltage */
value = float_2_ulinear16(volts);
smb_write_word(PMBUS_VOUT_COMMAND, value);
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 */
smb_write_byte(PMBUS_OPERATION, OPERATION_ON);
if (smb_write_byte(PMBUS_OPERATION, OPERATION_ON) != ESP_OK) {
ESP_LOGE(TAG, "Could not turn on Vout");
}
}
}
}
@ -692,56 +729,56 @@ void TPS546_show_voltage_settings(void)
/* 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: %f", f_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: %f", f_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: %f V", f_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: %f V", f_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: %f V", f_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: %f V", f_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: %f V", f_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: %f V", f_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: %f V", f_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: %f V", f_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: %f V", f_value);
ESP_LOGI(TAG, "Vout Min set to: %.2f V", f_value);
}

View File

@ -81,5 +81,6 @@ float TPS546_get_iout(void);
float TPS546_get_vout(void);
void TPS546_set_vout(float volts);
void TPS546_show_voltage_settings(void);
void TPS546_print_status(void);
#endif /* TPS546_H_ */

View File

@ -1,19 +1,106 @@
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_log.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
// static const char *TAG = "adc.c";
static esp_adc_cal_characteristics_t adc1_chars;
#define ADC_ATTEN ADC_ATTEN_DB_12
#define ADC_CHANNEL ADC_CHANNEL_1
static const char * TAG = "ADC";
static adc_cali_handle_t adc1_cali_chan1_handle;
static adc_oneshot_unit_handle_t adc1_handle;
/*---------------------------------------------------------------
ADC Calibration
---------------------------------------------------------------*/
static bool adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle)
{
adc_cali_handle_t handle = NULL;
esp_err_t ret = ESP_FAIL;
bool calibrated = false;
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
if (!calibrated) {
ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
adc_cali_curve_fitting_config_t cali_config = {
.unit_id = unit,
.chan = channel,
.atten = atten,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
if (ret == ESP_OK) {
calibrated = true;
}
}
#endif
#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
if (!calibrated) {
ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
adc_cali_line_fitting_config_t cali_config = {
.unit_id = unit,
.atten = atten,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
if (ret == ESP_OK) {
calibrated = true;
}
}
#endif
*out_handle = handle;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Calibration Success");
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
} else {
ESP_LOGE(TAG, "Invalid arg or no memory");
}
return calibrated;
}
// Sets up the ADC to read Vcore. Run this before ADC_get_vcore()
void ADC_init(void)
{
adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_DB_11);
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
// adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_DB_12);
// esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
//-------------ADC1 Init---------------//
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
//-------------ADC1 Config---------------//
adc_oneshot_chan_cfg_t config = {
.atten = ADC_ATTEN,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL, &config));
//-------------ADC1 Calibration Init---------------//
adc_calibration_init(ADC_UNIT_1, ADC_CHANNEL, ADC_ATTEN, &adc1_cali_chan1_handle);
}
// returns the ADC voltage in mV
uint16_t ADC_get_vcore(void)
{
adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
return esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC1_CHANNEL_1), &adc1_chars);
int adc_raw[2][10];
int voltage[2][10];
// adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
// return esp_adc_cal_raw_to_voltage(adc1_get_raw(ADC_CHANNEL), &adc1_chars);
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL, &adc_raw[0][1]));
//ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, ADC_CHANNEL, adc_raw[0][1]);
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_chan1_handle, adc_raw[0][1], &voltage[0][1]));
//ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, ADC_CHANNEL, voltage[0][1]);
return (uint16_t)voltage[0][1];
}

View File

@ -464,9 +464,9 @@ static esp_err_t GET_system_info(httpd_req_t * req)
free(fallbackStratumUser);
free(board_version);
const char * sys_info = cJSON_Print(root);
const char * sys_info = cJSON_Print(root);
httpd_resp_sendstr(req, sys_info);
free(sys_info);
free((char *)sys_info);
cJSON_Delete(root);
return ESP_OK;
}
@ -563,7 +563,7 @@ esp_err_t POST_OTA_update(httpd_req_t * req)
return ESP_OK;
}
void log_to_queue(const char * format, va_list args)
int log_to_queue(const char * format, va_list args)
{
va_list args_copy;
va_copy(args_copy, args);
@ -575,7 +575,7 @@ void log_to_queue(const char * format, va_list args)
// Allocate the buffer dynamically
char * log_buffer = (char *) calloc(needed_size + 2, sizeof(char)); // +2 for potential \n and \0
if (log_buffer == NULL) {
return;
return 0;
}
// Format the string into the allocated buffer
@ -599,6 +599,8 @@ void log_to_queue(const char * format, va_list args)
free((void*)log_buffer);
}
}
return 0;
}
void send_log_to_websocket(char *message)

100
main/i2c_bitaxe.c Normal file
View File

@ -0,0 +1,100 @@
#include "esp_event.h"
#include "esp_log.h"
#include "i2c_bitaxe.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_FREQ_HZ 100000 /*!< 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 */
static i2c_master_bus_handle_t i2c_bus_handle;
/**
* @brief i2c master initialization
*/
esp_err_t i2c_bitaxe_init(void)
{
i2c_master_bus_config_t i2c_bus_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = I2C_MASTER_NUM,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_io_num = I2C_MASTER_SDA_IO,
.glitch_ignore_cnt = 7,
.flags.enable_internal_pullup = true,
};
return i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
}
/**
* @brief Add a new I2C Device
* @param device_address The I2C device address
* @param dev_handle The I2C device handle
*/
esp_err_t i2c_bitaxe_add_device(uint8_t device_address, i2c_master_dev_handle_t * dev_handle)
{
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = device_address,
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
};
return i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, dev_handle);
}
/**
* @brief Read a sequence of I2C bytes
* @param dev_handle The I2C device handle
* @param reg_addr The register address to read from
* @param read_buf The buffer to store the read data
* @param len The number of bytes to read
*/
esp_err_t i2c_bitaxe_register_read(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t * read_buf, size_t len)
{
// return i2c_master_write_read_device(I2C_MASTER_NUM, device_address, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
//ESP_LOGI("I2C", "Reading %d bytes from register 0x%02X", len, reg_addr);
return i2c_master_transmit_receive(dev_handle, &reg_addr, 1, read_buf, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}
/**
* @brief Write a byte to a I2C register
* @param dev_handle The I2C device handle
* @param reg_addr The register address to write to
* @param data The data to write
*/
esp_err_t i2c_bitaxe_register_write_byte(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t data)
{
uint8_t write_buf[2] = {reg_addr, data};
//return i2c_master_write_to_device(I2C_MASTER_NUM, device_address, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
return i2c_master_transmit(dev_handle, write_buf, 2, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}
/**
* @brief Write a bytes to a I2C register
* @param dev_handle The I2C device handle
* @param data The data to write
* @param len The number of bytes to write
*/
esp_err_t i2c_bitaxe_register_write_bytes(i2c_master_dev_handle_t dev_handle, uint8_t * data, uint8_t len)
{
return i2c_master_transmit(dev_handle, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}
/**
* @brief Write a word to a I2C register
* @param dev_handle The I2C device handle
* @param reg_addr The register address to write to
* @param data The data to write
*/
esp_err_t i2c_bitaxe_register_write_word(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t data)
{
uint8_t write_buf[3] = {reg_addr, (uint8_t)(data & 0x00FF), (uint8_t)((data & 0xFF00) >> 8)};
//return i2c_master_write_to_device(I2C_MASTER_NUM, device_address, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
return i2c_master_transmit(dev_handle, write_buf, 3, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

19
main/i2c_bitaxe.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef I2C_MASTER_H_
#define I2C_MASTER_H_
#include "driver/i2c_master.h"
//#include "driver/i2c.h"
#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_TIMEOUT_MS 1000
esp_err_t i2c_bitaxe_init(void);
esp_err_t i2c_bitaxe_add_device(uint8_t device_address, i2c_master_dev_handle_t * dev_handle);
esp_err_t i2c_bitaxe_register_read(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t * read_buf, size_t len);
esp_err_t i2c_bitaxe_register_write_byte(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t data);
esp_err_t i2c_bitaxe_register_write_bytes(i2c_master_dev_handle_t dev_handle, uint8_t * data, uint8_t len);
esp_err_t i2c_bitaxe_register_write_word(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t data);
#endif /* I2C_MASTER_H_ */

View File

@ -1,73 +0,0 @@
#include "i2c_master.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_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 */
/**
* @brief i2c master initialization
*/
esp_err_t i2c_master_init(void)
{
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
*/
esp_err_t i2c_master_delete(void)
{
return i2c_driver_delete(I2C_MASTER_NUM);
}
/**
* @brief Read a sequence of I2C bytes
*/
esp_err_t i2c_master_register_read(uint8_t device_address, uint8_t reg_addr, uint8_t * data, size_t len)
{
return i2c_master_write_read_device(I2C_MASTER_NUM, device_address, &reg_addr, 1, data, len,
I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}
/**
* @brief Write a byte to a I2C register
*/
esp_err_t i2c_master_register_write_byte(uint8_t device_address, 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, device_address, write_buf, sizeof(write_buf),
I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
return ret;
}
/**
* @brief Write a word to a I2C register
*/
esp_err_t i2c_master_register_write_word(uint8_t device_address, uint8_t reg_addr, uint16_t data)
{
int ret;
uint8_t write_buf[3] = {reg_addr, (data >> 8) & 0xFF, data & 0xFF};
ret = i2c_master_write_to_device(I2C_MASTER_NUM, device_address, write_buf, sizeof(write_buf),
I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
return ret;
}

View File

@ -1,15 +0,0 @@
#ifndef I2C_MASTER_H_
#define I2C_MASTER_H_
#include "driver/i2c.h"
#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_TIMEOUT_MS 1000
esp_err_t i2c_master_init(void);
esp_err_t i2c_master_delete(void);
esp_err_t i2c_master_register_read(uint8_t device_address, uint8_t reg_addr, uint8_t * data, size_t len);
esp_err_t i2c_master_register_write_byte(uint8_t device_address, uint8_t reg_addr, uint8_t data);
esp_err_t i2c_master_register_write_word(uint8_t device_address, uint8_t reg_addr, uint16_t data);
#endif /* I2C_MASTER_H_ */

View File

@ -16,6 +16,7 @@
#include "serial.h"
#include "stratum_task.h"
#include "user_input_task.h"
#include "i2c_bitaxe.h"
static GlobalState GLOBAL_STATE = {
.extranonce_str = NULL,
@ -31,6 +32,14 @@ static const double NONCE_SPACE = 4294967296.0; // 2^32
void app_main(void)
{
ESP_LOGI(TAG, "Welcome to the bitaxe - hack the planet!");
// Init I2C
ESP_ERROR_CHECK(i2c_bitaxe_init());
ESP_LOGI(TAG, "I2C initialized successfully");
//wait for I2C to init
vTaskDelay(100 / portTICK_PERIOD_MS);
ESP_ERROR_CHECK(nvs_flash_init());
GLOBAL_STATE.POWER_MANAGEMENT_MODULE.frequency_value = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
@ -144,9 +153,6 @@ void app_main(void)
vTaskDelay(60 * 60 * 1000 / portTICK_PERIOD_MS);
}
xTaskCreate(SYSTEM_task, "SYSTEM_task", 4096, (void *) &GLOBAL_STATE, 3, NULL);
xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL);
// pull the wifi credentials and hostname out of NVS
char * wifi_ssid = nvs_config_get_string(NVS_CONFIG_WIFI_SSID, WIFI_SSID);
char * wifi_pass = nvs_config_get_string(NVS_CONFIG_WIFI_PASS, WIFI_PASS);
@ -189,6 +195,11 @@ void app_main(void)
free(wifi_pass);
free(hostname);
SYSTEM_init_system(&GLOBAL_STATE);
xTaskCreate(SYSTEM_task, "SYSTEM_task", 4096, (void *) &GLOBAL_STATE, 3, NULL);
xTaskCreate(POWER_MANAGEMENT_task, "power mangement", 8192, (void *) &GLOBAL_STATE, 10, NULL);
// set the startup_done flag
GLOBAL_STATE.SYSTEM_MODULE.startup_done = true;
GLOBAL_STATE.new_stratum_version_rolling_msg = false;

View File

@ -15,16 +15,18 @@
// A copy of the display memory is maintained by this code so that single pixel
// writes can occur without having to read from the display controller.
#include "i2c_master.h"
#include "esp_err.h"
#include "esp_log.h"
#include "nvs_config.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "nvs_config.h"
#include "i2c_bitaxe.h"
#include "oled.h"
#define OLED_I2C_ADDR 0x3C
extern unsigned char ucSmallFont[];
static int iScreenOffset; // current write offset of screen data
static unsigned char ucScreen[1024]; // local copy of the image buffer
@ -35,9 +37,17 @@ static esp_err_t write(uint8_t *, uint8_t);
static bool oled_active;
static i2c_master_dev_handle_t ssd1306_dev_handle;
// Initialialize the OLED Screen
bool OLED_init(void)
esp_err_t OLED_init(void)
{
//init the I2C device
if (i2c_bitaxe_add_device(OLED_I2C_ADDR, &ssd1306_dev_handle) != ESP_OK) {
return ESP_FAIL;
}
uint8_t oled32_initbuf[] = {0x00,
0xae, // cmd: display off
0xd5, // cmd: set display clock
@ -281,9 +291,7 @@ bool OLED_status(void)
*/
static esp_err_t write(uint8_t * data, uint8_t len)
{
int ret;
//return i2c_master_write_to_device(I2C_MASTER_NUM, 0x3C, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
ret = i2c_master_write_to_device(I2C_MASTER_NUM, 0x3C, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
return ret;
return i2c_bitaxe_register_write_bytes(ssd1306_dev_handle, data, len);
}

View File

@ -27,7 +27,7 @@ typedef enum
// Optionally enable inverted or flipped mode
// returns 0 for success, 1 for failure
//
bool OLED_init(void);
esp_err_t OLED_init(void);
// Turns off the display and closes the I2C handle
void OLED_shutdown(void);

View File

@ -1,4 +1,4 @@
#include "i2c_master.h"
#include "i2c_bitaxe.h"
#include "DS4432U.h"
#include "EMC2101.h"
#include "INA260.h"
@ -137,7 +137,7 @@ void self_test(void * pvParameters)
}
// Init I2C
ESP_ERROR_CHECK(i2c_master_init());
ESP_ERROR_CHECK(i2c_bitaxe_init());
ESP_LOGI(TAG, "I2C initialized successfully");

View File

@ -2,10 +2,9 @@
#include "esp_log.h"
#include "i2c_master.h"
#include "i2c_bitaxe.h"
#include "EMC2101.h"
#include "INA260.h"
#include "TMP1075.h"
//#include "INA260.h"
#include "adc.h"
#include "connect.h"
#include "led_controller.h"
@ -41,22 +40,23 @@ static esp_netif_ip_info_t ip_info;
QueueHandle_t user_input_queue;
static esp_err_t ensure_overheat_mode_config() {
uint16_t overheat_mode = nvs_config_get_u16(NVS_CONFIG_OVERHEAT_MODE, UINT16_MAX);
//local function prototypes
static esp_err_t ensure_overheat_mode_config();
static void _show_overheat_screen(GlobalState * GLOBAL_STATE);
static void _update_hashrate(GlobalState * GLOBAL_STATE);
static void _update_shares(GlobalState * GLOBAL_STATE);
static void _clear_display(GlobalState * GLOBAL_STATE);
static void _init_connection(GlobalState * GLOBAL_STATE);
static void _update_connection(GlobalState * GLOBAL_STATE);
static void _update_system_performance(GlobalState * GLOBAL_STATE);
static void _update_system_info(GlobalState * GLOBAL_STATE);
static void _update_esp32_info(GlobalState * GLOBAL_STATE);
static void show_ap_information(const char * error, GlobalState * GLOBAL_STATE);
if (overheat_mode == UINT16_MAX) {
// Key doesn't exist or couldn't be read, set the default value
nvs_config_set_u16(NVS_CONFIG_OVERHEAT_MODE, 0);
ESP_LOGI(TAG, "Default value for overheat_mode set to 0");
} else {
// Key exists, log the current value
ESP_LOGI(TAG, "Existing overheat_mode value: %d", overheat_mode);
}
static void _check_for_best_diff(GlobalState * GLOBAL_STATE, double diff, uint8_t job_id);
static void _suffix_string(uint64_t val, char * buf, size_t bufsiz, int sigdigits);
return ESP_OK;
}
static void _init_system(GlobalState * GLOBAL_STATE)
void SYSTEM_init_system(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
@ -99,15 +99,6 @@ static void _init_system(GlobalState * GLOBAL_STATE)
// set the wifi_status to blank
memset(module->wifi_status, 0, 20);
// test the LEDs
// ESP_LOGI(TAG, "Init LEDs!");
// ledc_init();
// led_set();
// Init I2C
ESP_ERROR_CHECK(i2c_master_init());
ESP_LOGI(TAG, "I2C initialized successfully");
// Initialize the core voltage regulator
VCORE_init(GLOBAL_STATE);
VCORE_set_voltage(nvs_config_get_u16(NVS_CONFIG_ASIC_VOLTAGE, CONFIG_ASIC_VOLTAGE) / 1000.0, GLOBAL_STATE);
@ -148,8 +139,81 @@ static void _init_system(GlobalState * GLOBAL_STATE)
}
netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
user_input_queue = xQueueCreate(10, sizeof(char[10])); // Create a queue to handle user input events
_clear_display(GLOBAL_STATE);
_init_connection(GLOBAL_STATE);
}
void SYSTEM_task(void * pvParameters)
{
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
//_init_system(GLOBAL_STATE);
char input_event[10];
ESP_LOGI(TAG, "SYSTEM_task started");
while (GLOBAL_STATE->ASIC_functions.init_fn == NULL) {
show_ap_information("ASIC MODEL INVALID", GLOBAL_STATE);
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
// show the connection screen
while (!module->startup_done) {
_update_connection(GLOBAL_STATE);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
while (1) {
// Check for overheat mode
if (module->overheat_mode == 1) {
_show_overheat_screen(GLOBAL_STATE);
vTaskDelay(5000 / portTICK_PERIOD_MS); // Update every 5 seconds
SYSTEM_update_overheat_mode(GLOBAL_STATE); // Check for changes
continue; // Skip the normal screen cycle
}
// Automatically cycle through screens
for (int screen = 0; screen < 3; screen++) {
_clear_display(GLOBAL_STATE);
module->screen_page = screen;
switch (module->screen_page) {
case 0:
_update_system_performance(GLOBAL_STATE);
break;
case 1:
_update_system_info(GLOBAL_STATE);
break;
case 2:
_update_esp32_info(GLOBAL_STATE);
break;
}
// Wait for 10 seconds or until a button press
for (int i = 0; i < 10; i++) {
if (xQueueReceive(user_input_queue, &input_event, pdMS_TO_TICKS(1000))) {
if (strcmp(input_event, "SHORT") == 0) {
ESP_LOGI(TAG, "Short button press detected, switching to next screen");
screen = (screen + 1) % 3; // Move to next screen
break;
} else if (strcmp(input_event, "LONG") == 0) {
ESP_LOGI(TAG, "Long button press detected, toggling WiFi SoftAP");
toggle_wifi_softap(); // Toggle AP
}
}
}
}
}
}
void SYSTEM_update_overheat_mode(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
@ -161,6 +225,92 @@ void SYSTEM_update_overheat_mode(GlobalState * GLOBAL_STATE)
}
}
void SYSTEM_notify_accepted_share(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
module->shares_accepted++;
_update_shares(GLOBAL_STATE);
}
void SYSTEM_notify_rejected_share(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
module->shares_rejected++;
_update_shares(GLOBAL_STATE);
}
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
module->duration_start = esp_timer_get_time();
}
void SYSTEM_notify_new_ntime(GlobalState * GLOBAL_STATE, uint32_t ntime)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
// Hourly clock sync
if (module->lastClockSync + (60 * 60) > ntime) {
return;
}
ESP_LOGI(TAG, "Syncing clock");
module->lastClockSync = ntime;
struct timeval tv;
tv.tv_sec = ntime;
tv.tv_usec = 0;
settimeofday(&tv, NULL);
}
void SYSTEM_notify_found_nonce(GlobalState * GLOBAL_STATE, double found_diff, uint8_t job_id)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
// Calculate the time difference in seconds with sub-second precision
// hashrate = (nonce_difficulty * 2^32) / time_to_find
module->historical_hashrate[module->historical_hashrate_rolling_index] = GLOBAL_STATE->initial_ASIC_difficulty;
module->historical_hashrate_time_stamps[module->historical_hashrate_rolling_index] = esp_timer_get_time();
module->historical_hashrate_rolling_index = (module->historical_hashrate_rolling_index + 1) % HISTORY_LENGTH;
// ESP_LOGI(TAG, "nonce_diff %.1f, ttf %.1f, res %.1f", nonce_diff, duration,
// historical_hashrate[historical_hashrate_rolling_index]);
if (module->historical_hashrate_init < HISTORY_LENGTH) {
module->historical_hashrate_init++;
} else {
module->duration_start =
module->historical_hashrate_time_stamps[(module->historical_hashrate_rolling_index + 1) % HISTORY_LENGTH];
}
double sum = 0;
for (int i = 0; i < module->historical_hashrate_init; i++) {
sum += module->historical_hashrate[i];
}
double duration = (double) (esp_timer_get_time() - module->duration_start) / 1000000;
double rolling_rate = (sum * 4294967296) / (duration * 1000000000);
if (module->historical_hashrate_init < HISTORY_LENGTH) {
module->current_hashrate = rolling_rate;
} else {
// More smoothing
module->current_hashrate = ((module->current_hashrate * 9) + rolling_rate) / 10;
}
_update_hashrate(GLOBAL_STATE);
// logArrayContents(historical_hashrate, HISTORY_LENGTH);
// logArrayContents(historical_hashrate_time_stamps, HISTORY_LENGTH);
_check_for_best_diff(GLOBAL_STATE, found_diff, job_id);
}
///
/// LOCAL FUNCTIONS
///
static void _show_overheat_screen(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
@ -542,152 +692,17 @@ static void _suffix_string(uint64_t val, char * buf, size_t bufsiz, int sigdigit
}
}
void SYSTEM_task(void * pvParameters)
{
GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters;
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
static esp_err_t ensure_overheat_mode_config() {
uint16_t overheat_mode = nvs_config_get_u16(NVS_CONFIG_OVERHEAT_MODE, UINT16_MAX);
_init_system(GLOBAL_STATE);
user_input_queue = xQueueCreate(10, sizeof(char[10])); // Create a queue to handle user input events
_clear_display(GLOBAL_STATE);
_init_connection(GLOBAL_STATE);
char input_event[10];
ESP_LOGI(TAG, "SYSTEM_task started");
while (GLOBAL_STATE->ASIC_functions.init_fn == NULL) {
show_ap_information("ASIC MODEL INVALID", GLOBAL_STATE);
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
// show the connection screen
while (!module->startup_done) {
_update_connection(GLOBAL_STATE);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
while (1) {
// Check for overheat mode
if (module->overheat_mode == 1) {
_show_overheat_screen(GLOBAL_STATE);
vTaskDelay(5000 / portTICK_PERIOD_MS); // Update every 5 seconds
SYSTEM_update_overheat_mode(GLOBAL_STATE); // Check for changes
continue; // Skip the normal screen cycle
}
// Automatically cycle through screens
for (int screen = 0; screen < 3; screen++) {
_clear_display(GLOBAL_STATE);
module->screen_page = screen;
switch (module->screen_page) {
case 0:
_update_system_performance(GLOBAL_STATE);
break;
case 1:
_update_system_info(GLOBAL_STATE);
break;
case 2:
_update_esp32_info(GLOBAL_STATE);
break;
}
// Wait for 10 seconds or until a button press
for (int i = 0; i < 10; i++) {
if (xQueueReceive(user_input_queue, &input_event, pdMS_TO_TICKS(1000))) {
if (strcmp(input_event, "SHORT") == 0) {
ESP_LOGI(TAG, "Short button press detected, switching to next screen");
screen = (screen + 1) % 3; // Move to next screen
break;
} else if (strcmp(input_event, "LONG") == 0) {
ESP_LOGI(TAG, "Long button press detected, toggling WiFi SoftAP");
toggle_wifi_softap(); // Toggle AP
}
}
}
}
}
}
void SYSTEM_notify_accepted_share(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
module->shares_accepted++;
_update_shares(GLOBAL_STATE);
}
void SYSTEM_notify_rejected_share(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
module->shares_rejected++;
_update_shares(GLOBAL_STATE);
}
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
module->duration_start = esp_timer_get_time();
}
void SYSTEM_notify_new_ntime(GlobalState * GLOBAL_STATE, uint32_t ntime)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
// Hourly clock sync
if (module->lastClockSync + (60 * 60) > ntime) {
return;
}
ESP_LOGI(TAG, "Syncing clock");
module->lastClockSync = ntime;
struct timeval tv;
tv.tv_sec = ntime;
tv.tv_usec = 0;
settimeofday(&tv, NULL);
}
void SYSTEM_notify_found_nonce(GlobalState * GLOBAL_STATE, double found_diff, uint8_t job_id)
{
SystemModule * module = &GLOBAL_STATE->SYSTEM_MODULE;
// Calculate the time difference in seconds with sub-second precision
// hashrate = (nonce_difficulty * 2^32) / time_to_find
module->historical_hashrate[module->historical_hashrate_rolling_index] = GLOBAL_STATE->initial_ASIC_difficulty;
module->historical_hashrate_time_stamps[module->historical_hashrate_rolling_index] = esp_timer_get_time();
module->historical_hashrate_rolling_index = (module->historical_hashrate_rolling_index + 1) % HISTORY_LENGTH;
// ESP_LOGI(TAG, "nonce_diff %.1f, ttf %.1f, res %.1f", nonce_diff, duration,
// historical_hashrate[historical_hashrate_rolling_index]);
if (module->historical_hashrate_init < HISTORY_LENGTH) {
module->historical_hashrate_init++;
if (overheat_mode == UINT16_MAX) {
// Key doesn't exist or couldn't be read, set the default value
nvs_config_set_u16(NVS_CONFIG_OVERHEAT_MODE, 0);
ESP_LOGI(TAG, "Default value for overheat_mode set to 0");
} else {
module->duration_start =
module->historical_hashrate_time_stamps[(module->historical_hashrate_rolling_index + 1) % HISTORY_LENGTH];
}
double sum = 0;
for (int i = 0; i < module->historical_hashrate_init; i++) {
sum += module->historical_hashrate[i];
// Key exists, log the current value
ESP_LOGI(TAG, "Existing overheat_mode value: %d", overheat_mode);
}
double duration = (double) (esp_timer_get_time() - module->duration_start) / 1000000;
double rolling_rate = (sum * 4294967296) / (duration * 1000000000);
if (module->historical_hashrate_init < HISTORY_LENGTH) {
module->current_hashrate = rolling_rate;
} else {
// More smoothing
module->current_hashrate = ((module->current_hashrate * 9) + rolling_rate) / 10;
}
_update_hashrate(GLOBAL_STATE);
// logArrayContents(historical_hashrate, HISTORY_LENGTH);
// logArrayContents(historical_hashrate_time_stamps, HISTORY_LENGTH);
_check_for_best_diff(GLOBAL_STATE, found_diff, job_id);
return ESP_OK;
}

View File

@ -3,6 +3,7 @@
#include "global_state.h"
void SYSTEM_init_system(GlobalState * GLOBAL_STATE);
void SYSTEM_task(void * parameters);
void SYSTEM_notify_accepted_share(GlobalState * GLOBAL_STATE);
@ -11,4 +12,7 @@ void SYSTEM_notify_found_nonce(GlobalState * GLOBAL_STATE, double found_diff, ui
void SYSTEM_notify_mining_started(GlobalState * GLOBAL_STATE);
void SYSTEM_notify_new_ntime(GlobalState * GLOBAL_STATE, uint32_t ntime);
void SYSTEM_update_overheat_mode(GlobalState * GLOBAL_STATE);
#endif /* SYSTEM_H_ */

View File

@ -9,7 +9,6 @@
#include "mining.h"
#include "nvs_config.h"
#include "serial.h"
#include "TMP1075.h"
#include "TPS546.h"
#include "vcore.h"
#include <string.h>
@ -31,15 +30,15 @@
static const char * TAG = "power_management";
static float _fbound(float value, float lower_bound, float upper_bound)
{
if (value < lower_bound)
return lower_bound;
if (value > upper_bound)
return upper_bound;
// static float _fbound(float value, float lower_bound, float upper_bound)
// {
// if (value < lower_bound)
// return lower_bound;
// if (value > upper_bound)
// return upper_bound;
return value;
}
// return value;
// }
// 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
@ -84,9 +83,8 @@ void POWER_MANAGEMENT_task(void * pvParameters)
power_management->HAS_POWER_EN = GLOBAL_STATE->board_version == 202 || GLOBAL_STATE->board_version == 203 || GLOBAL_STATE->board_version == 204;
power_management->HAS_PLUG_SENSE = GLOBAL_STATE->board_version == 204;
int last_frequency_increase = 0;
uint16_t frequency_target = nvs_config_get_u16(NVS_CONFIG_ASIC_FREQ, CONFIG_ASIC_FREQUENCY);
//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);
@ -118,7 +116,7 @@ void POWER_MANAGEMENT_task(void * pvParameters)
default:
}
vTaskDelay(4000 / portTICK_PERIOD_MS);
vTaskDelay(500 / portTICK_PERIOD_MS);
uint16_t last_core_voltage = 0.0;
uint16_t last_asic_frequency = power_management->frequency_value;
@ -135,10 +133,14 @@ void POWER_MANAGEMENT_task(void * pvParameters)
power_management->power = (TPS546_get_vout() * power_management->current) / 1000;
// The power reading from the TPS546 is only it's output power. So the rest of the Bitaxe power is not accounted for.
power_management->power += SUPRA_POWER_OFFSET; // Add offset for the rest of the Bitaxe power. TODO: this better.
} else if (INA260_installed() == true) {
power_management->voltage = INA260_read_voltage();
power_management->current = INA260_read_current();
power_management->power = INA260_read_power() / 1000;
} else {
INA260_init();
if (INA260_installed() == true) {
power_management->voltage = INA260_read_voltage();
power_management->current = INA260_read_current();
power_management->power = INA260_read_power() / 1000;
}
}
break;

View File

@ -79,6 +79,8 @@ bool VCORE_set_voltage(float core_voltage, GlobalState * global_state)
ESP_LOGI(TAG, "Set ASIC voltage = %.3fV", core_voltage);
TPS546_set_vout(core_voltage * (float)global_state->voltage_domain);
} else {
DS4432U_init();
uint8_t reg_setting = ds4432_tps40305_bitaxe_voltage_to_reg(core_voltage * (float)global_state->voltage_domain);
ESP_LOGI(TAG, "Set ASIC voltage = %.3fV [0x%02X]", core_voltage, reg_setting);
DS4432U_set_current_code(0, reg_setting); /// eek!