common/sensor/dev/mp5990.c (100 lines of code) (raw):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sensor.h"
#include "hal_i2c.h"
#include "pal.h"
#define I2C_DATA_SIZE 5
uint8_t mp5990_read(uint8_t sensor_num, int *reading)
{
if ((reading == NULL) ||
(sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args == NULL)) {
return SENSOR_UNSPECIFIED_ERROR;
}
mp5990_init_arg *init_arg =
(mp5990_init_arg *)sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args;
if (init_arg->is_init == false) {
printf("[%s], device isn't initialized\n", __func__);
return SENSOR_UNSPECIFIED_ERROR;
}
uint8_t retry = 5;
double val;
I2C_MSG msg = { 0 };
sensor_cfg *cfg = &sensor_config[SensorNum_SensorCfg_map[sensor_num]];
msg.bus = cfg->port;
msg.slave_addr = cfg->slave_addr;
msg.tx_len = 1;
msg.rx_len = 2;
msg.data[0] = cfg->offset;
if (i2c_master_read(&msg, retry))
return SENSOR_FAIL_TO_ACCESS;
switch (cfg->offset) {
case PMBUS_READ_VIN:
case PMBUS_READ_VOUT:
/* 31.25 mv/LSB */
val = ((msg.data[1] << 8) | msg.data[0]) * 31.25 / 1000;
break;
case PMBUS_READ_IOUT:
/* 62.5 mA/LSB */
val = ((msg.data[1] << 8) | msg.data[0]) * 62.5 / 1000;
break;
case PMBUS_READ_TEMPERATURE_1:
/* 1 degree c/LSB */
val = msg.data[0];
break;
case PMBUS_READ_POUT:
case PMBUS_READ_PIN:
/* 1 W/LSB */
val = ((msg.data[1] << 8) | msg.data[0]);
break;
default:
return SENSOR_NOT_FOUND;
}
sensor_val *sval = (sensor_val *)reading;
memset(sval, 0, sizeof(*sval));
sval->integer = (int32_t)val;
sval->fraction = (int32_t)(val * 1000) % 1000;
return SENSOR_READ_SUCCESS;
}
uint8_t mp5990_init(uint8_t sensor_num)
{
if (!sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args) {
printf("<error> MP5990 init args are not provided!\n");
return SENSOR_INIT_UNSPECIFIED_ERROR;
}
mp5990_init_arg *init_args =
(mp5990_init_arg *)sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args;
if (init_args->is_init)
goto skip_init;
uint8_t retry = 5;
I2C_MSG msg;
char *data = (uint8_t *)malloc(I2C_DATA_SIZE * sizeof(uint8_t));
if (data == NULL) {
printf("Failed to allocate memory for I2C data.\n");
return SENSOR_INIT_UNSPECIFIED_ERROR;
}
uint8_t bus = sensor_config[SensorNum_SensorCfg_map[sensor_num]].port;
uint8_t slave_addr = sensor_config[SensorNum_SensorCfg_map[sensor_num]].slave_addr;
uint8_t tx_len = 3;
uint8_t rx_len = 0;
data[0] = PMBUS_IOUT_CAL_GAIN;
data[1] = init_args->iout_cal_gain & 0xFF;
data[2] = (init_args->iout_cal_gain >> 8) & 0xFF;
msg = construct_i2c_message(bus, slave_addr, tx_len, data, rx_len);
if (i2c_master_write(&msg, retry) != 0) {
printf("Failed to write MP5990 register(0x%x)\n", data[0]);
goto cleanup;
}
tx_len = 3;
rx_len = 0;
data[0] = PMBUS_IOUT_OC_FAULT_LIMIT;
data[1] = init_args->iout_oc_fault_limit & 0xFF;
data[2] = (init_args->iout_oc_fault_limit >> 8) & 0xFF;
msg = construct_i2c_message(bus, slave_addr, tx_len, data, rx_len);
if (i2c_master_write(&msg, retry) != 0) {
printf("Failed to write MP5990 register(0x%x)\n", data[0]);
goto cleanup;
}
init_args->is_init = true;
cleanup:
SAFE_FREE(data);
skip_init:
sensor_config[SensorNum_SensorCfg_map[sensor_num]].read = mp5990_read;
return SENSOR_INIT_SUCCESS;
}