common/sensor/dev/isl28022.c (108 lines of code) (raw):

#include <stdio.h> #include <string.h> #include "sensor.h" #include "hal_i2c.h" #define ISL28022_CONFIG_REG 0 #define ISL28022_BUS_VOLTAGE_REG 2 #define ISL28022_POWER_REG 3 #define ISL28022_CURRENT_REG 4 #define ISL28022_CALIBRATION_REG 5 uint8_t isl28022_read(uint8_t sensor_num, int *reading) { if ((reading == NULL) || (sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args == NULL)) { return SENSOR_UNSPECIFIED_ERROR; } isl28022_init_arg *init_arg = (isl28022_init_arg *)sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args; if (init_arg->is_init == false) { printk("isl28022_read, device isn't initialized\n"); return SENSOR_UNSPECIFIED_ERROR; } uint8_t retry = 5; I2C_MSG msg; uint8_t offset = sensor_config[SensorNum_SensorCfg_map[sensor_num]].offset; sensor_val *sval = (sensor_val *)reading; memset(sval, 0, sizeof(sensor_val)); 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.rx_len = 2; msg.data[0] = offset; if (i2c_master_read(&msg, retry)) { /* read fail */ return SENSOR_FAIL_TO_ACCESS; } if (offset == ISL28022_BUS_VOLTAGE_REG) { /* unsigned */ uint16_t read_mv; if ((init_arg->config.fields.BRNG == 0b11) || (init_arg->config.fields.BRNG == 0b10)) { read_mv = ((msg.data[0] << 6) | (msg.data[1] >> 2)) * 4; } else if (init_arg->config.fields.BRNG == 0b01) { read_mv = ((msg.data[0] << 5) | (msg.data[1] >> 3)) * 4; } else { read_mv = (((msg.data[0] & BIT_MASK(7)) << 5) | (msg.data[1] >> 3)) * 4; } sval->integer = read_mv / 1000; sval->fraction = read_mv % 1000; } else if (offset == ISL28022_CURRENT_REG) { /* signed */ float read_current = ((int16_t)(msg.data[0] << 8) | msg.data[1]) * init_arg->current_LSB; sval->integer = read_current; sval->fraction = (read_current - sval->integer) * 1000; } else if (offset == ISL28022_POWER_REG) { /* unsigned */ float read_power = ((msg.data[0] << 8) | msg.data[1]) * init_arg->current_LSB * 20; sval->integer = read_power; sval->fraction = ((read_power - sval->integer) * 1000); } else { return SENSOR_FAIL_TO_ACCESS; } return SENSOR_READ_SUCCESS; } uint8_t isl28022_init(uint8_t sensor_num) { if (sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args == NULL) { printk("isl28022_init: init_arg is NULL\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } sensor_config[SensorNum_SensorCfg_map[sensor_num]].read = isl28022_read; isl28022_init_arg *init_arg = (isl28022_init_arg *)sensor_config[SensorNum_SensorCfg_map[sensor_num]].init_args; if (init_arg->is_init == true) { return SENSOR_INIT_SUCCESS; } I2C_MSG msg; uint8_t retry = 5; /* set configuration register */ 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] = ISL28022_CONFIG_REG; msg.data[1] = (init_arg->config.value >> 8) & 0xFF; msg.data[2] = init_arg->config.value & 0xFF; if (i2c_master_write(&msg, retry)) { printk("isl28022_init, set configuration register fail\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } /* calculate and set calibration */ uint16_t v_shunt_fs, adc_res, calibration; v_shunt_fs = 40 << (init_arg->config.fields.PG); if (!(init_arg->config.fields.SADC & BIT(3)) && ((init_arg->config.fields.SADC & BIT_MASK(2)) < 3)) { adc_res = 1 << (12 + (init_arg->config.fields.SADC & BIT_MASK(2))); } else { adc_res = 32768; } init_arg->current_LSB = (float)v_shunt_fs / (init_arg->r_shunt * adc_res); calibration = (40.96 / (init_arg->current_LSB * init_arg->r_shunt)); calibration = calibration << 1; /* 15 bits, bit[0] is fix to 0 */ 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] = ISL28022_CALIBRATION_REG; msg.data[1] = (calibration >> 8) & 0xFF; msg.data[2] = calibration & 0xFF; if (i2c_master_write(&msg, retry)) { printk("isl28022_init, set calibration register fail\n"); return SENSOR_INIT_UNSPECIFIED_ERROR; } init_arg->is_init = true; return SENSOR_INIT_SUCCESS; }