common/sensor/dev/adm1278.c (157 lines of code) (raw):

#include <stdio.h> #include <string.h> #include "sensor.h" #include "hal_i2c.h" #include "sensor_def.h" #define REG_PWR_MT_CFG 0xD4 #define ADM1278_EIN_ROLLOVER_CNT_MAX 0x10000 #define ADM1278_EIN_SAMPLE_CNT_MAX 0x1000000 #define ADM1278_EIN_ENERGY_CNT_MAX 0x800000 float adm1278_read_ein_ext(float rsense, float *val, uint8_t sensor_num) { I2C_MSG msg; uint8_t retry = 5; uint32_t energy = 0, rollover = 0, sample = 0; uint32_t pre_energy = 0, pre_rollover = 0, pre_sample = 0; uint32_t sample_diff = 0; double energy_diff = 0; static uint32_t last_energy = 0, last_rollover = 0, last_sample = 0; static bool pre_ein = false; msg.bus = sensor_config[SensorNum_SensorCfg_map[sensor_num]].port; msg.slave_addr = sensor_config[SensorNum_SensorCfg_map[sensor_num]].slave_addr; msg.tx_len = 1; msg.data[0] = sensor_config[SensorNum_SensorCfg_map[sensor_num]].offset; msg.rx_len = 8; if (i2c_master_read(&msg, retry)) return SENSOR_FAIL_TO_ACCESS; //record the previous data pre_energy = last_energy; pre_rollover = last_rollover; pre_sample = last_sample; //record the current data last_energy = energy = (msg.data[2] << 16) | (msg.data[1] << 8) | msg.data[0]; last_rollover = rollover = (msg.data[4] << 8) | msg.data[3]; last_sample = sample = (msg.data[7] << 16) | (msg.data[6] << 8) | msg.data[5]; //return since data isn't enough if (pre_ein == false) { pre_ein = true; return -1; } if ((pre_rollover > rollover) || ((pre_rollover == rollover) && (pre_energy > energy))) { rollover += ADM1278_EIN_ROLLOVER_CNT_MAX; } if (pre_sample > sample) { sample += ADM1278_EIN_SAMPLE_CNT_MAX; } energy_diff = (double)(rollover - pre_rollover) * ADM1278_EIN_ENERGY_CNT_MAX + (double)energy - (double)pre_energy; if (energy_diff < 0) { return -1; } sample_diff = sample - pre_sample; if (sample_diff == 0) { return -1; } *val = (float)((energy_diff / sample_diff / 256) * 100) / (6123 * rsense); return 0; } uint8_t adm1278_read(uint8_t sensor_num, int *reading) { if ((reading == NULL) || (sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args == NULL)) { return SENSOR_UNSPECIFIED_ERROR; } adm1278_init_arg *init_arg = (adm1278_init_arg *)sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args; if (init_arg->is_init == false) { printk("adm1278_read, device isn't initialized\n"); return SENSOR_UNSPECIFIED_ERROR; } if (!init_arg->r_sense) { printk("adm1278_read, Rsense hasn't given\n"); return SENSOR_UNSPECIFIED_ERROR; } float Rsense = init_arg->r_sense; float val; uint8_t retry = 5; I2C_MSG msg; int ret = 0; uint8_t offset = sensor_config[SensorNum_SensorCfg_map[sensor_num]].offset; if (offset != ADM1278_EIN_EXT_OFFSET) { msg.bus = sensor_config[SensorNum_SensorCfg_map[sensor_num]].port; msg.slave_addr = sensor_config[SensorNum_SensorCfg_map[sensor_num]].slave_addr; msg.tx_len = 1; msg.data[0] = offset; msg.rx_len = 2; if (i2c_master_read(&msg, retry)) return SENSOR_FAIL_TO_ACCESS; } switch (offset) { case ADM1278_VSOURCE_OFFSET: // m = +19599, b = 0, R = -2 val = (float)(((msg.data[1] << 8) | msg.data[0]) * 100 / 19599.0); break; case ADM1278_CURRENT_OFFSET: case ADM1278_PEAK_IOUT_OFFSET: // m = +800 * Rsense(mohm), b = +20475, R = -1 val = (float)(((msg.data[1] << 8) | msg.data[0]) * 10 - 20475) / (800 * Rsense); break; case ADM1278_TEMP_OFFSET: // m = +42, b = +31880, R = -1 val = (float)(((msg.data[1] << 8) | msg.data[0]) * 10 - 31880) / 42; break; case ADM1278_POWER_OFFSET: case ADM1278_PEAK_PIN_OFFSET: // m = +6123 * Rsense(mohm), b = 0, R = -2 val = (float)(((msg.data[1] << 8) | msg.data[0]) * 100) / (6123 * Rsense); break; case ADM1278_EIN_EXT_OFFSET: ret = adm1278_read_ein_ext(Rsense, &val, sensor_num); if (ret != 0) { return SENSOR_UNSPECIFIED_ERROR; } break; default: printf("Invalid sensor 0x%x\n", sensor_num); return SENSOR_UNSPECIFIED_ERROR; } sensor_val *sval = (sensor_val *)reading; sval->integer = (int)val & 0xFFFF; sval->fraction = (val - sval->integer) * 1000; return SENSOR_READ_SUCCESS; } uint8_t adm1278_init(uint8_t sensor_num) { if (!sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args) { printk("<error> ADM1278 init args not provide!\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } adm1278_init_arg *init_args = (adm1278_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; msg.bus = sensor_config[SensorNum_SensorCfg_map[sensor_num]].port; msg.slave_addr = sensor_config[SensorNum_SensorCfg_map[sensor_num]].slave_addr; msg.tx_len = 3; msg.data[0] = REG_PWR_MT_CFG; msg.data[1] = init_args->config.value & 0xFF; msg.data[2] = (init_args->config.value >> 8) & 0xFF; if (i2c_master_write(&msg, retry)) { printf("<error> ADM1278 initail failed while i2c writing\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } memset(&msg, 0, sizeof(msg)); msg.bus = sensor_config[SensorNum_SensorCfg_map[sensor_num]].port; msg.slave_addr = sensor_config[SensorNum_SensorCfg_map[sensor_num]].slave_addr; msg.tx_len = 1; msg.data[0] = REG_PWR_MT_CFG; msg.rx_len = 2; if (i2c_master_read(&msg, retry)) { printf("<error> ADM1278 initail failed while i2c reading\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } if ((msg.data[0] != (init_args->config.value & 0xFF)) || (msg.data[1] != ((init_args->config.value >> 8) & 0xFF))) { printf("<error> ADM1278 initail failed with wrong reading data\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } init_args->is_init = 1; skip_init: sensor_config[SensorNum_SensorCfg_map[sensor_num]].read = adm1278_read; return SENSOR_INIT_SUCCESS; }