mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-22 01:27:59 +02:00
ctb: power regulators (set dac, get dac, get adc of voltage and current) works
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "commonServerFunctions.h" // blackfin.h, ansi.h
|
||||
#include "common.h"
|
||||
|
||||
/* AD7689 ADC DEFINES */
|
||||
|
||||
@ -62,8 +63,10 @@
|
||||
#define AD7689_ADC_DATA_NUMBITS (16)
|
||||
#define AD7689_NUM_CHANNELS (7)
|
||||
#define AD7689_NUM_INVALID_CONVERSIONS (3)
|
||||
|
||||
#define AD7689_INT_REF_MAX_MV (2500) // chosen using reference buffer selection in config reg
|
||||
#define AD7689_INT_REF_MIN_MV (0)
|
||||
#define AD7689_INT_MAX_STEPS (0xFFFF + 1)
|
||||
#define AD7689_TMP_C_FOR_1_MV (25.00 / 283)
|
||||
|
||||
|
||||
@ -144,17 +147,17 @@ int AD7689_GetTemperature() {
|
||||
AD7689_CFG_CFG_OVRWRTE_VAL);
|
||||
|
||||
// FIXME: do we have to read it 8 times?? (sequencer is disabled anyway) or are we sequencing, then we read only last channel
|
||||
uint16_t regval = AD7689_Get();
|
||||
int regval = AD7689_Get();
|
||||
|
||||
// value in mV FIXME: page 17? reference voltage temperature coefficient or t do with -40 to 85 °C
|
||||
uint16_t vmin = AD7689_INT_REF_MIN_MV;
|
||||
uint16_t vmax = AD7689_INT_REF_MAX_MV;
|
||||
uint16_t nsteps = (2 ^ AD7689_ADC_DATA_NUMBITS);
|
||||
uint16_t retval = (vmin + (vmax - vmin) * regval / (nsteps - 1));
|
||||
int retval = 0;
|
||||
ConvertToDifferentRange(0, AD7689_INT_MAX_STEPS,
|
||||
AD7689_INT_REF_MIN_MV, AD7689_INT_REF_MAX_MV,
|
||||
regval, &retval);
|
||||
FILE_LOG(logDEBUG1, ("\tvoltage read for temp: 0x%d mV\n", retval));
|
||||
|
||||
// value in °C
|
||||
uint16_t temp = AD7689_TMP_C_FOR_1_MV * retval;
|
||||
int temp = AD7689_TMP_C_FOR_1_MV * retval;
|
||||
FILE_LOG(logDEBUG1, ("\ttemp read: 0x%d °C\n", temp));
|
||||
|
||||
return temp;
|
||||
@ -191,13 +194,13 @@ int AD7689_GetChannel(int ichan) {
|
||||
AD7689_CFG_CFG_OVRWRTE_VAL);
|
||||
|
||||
// FIXME: do we have to read it 8 times?? (sequencer is disabled anyway) or are we sequencing, then we read only last channel
|
||||
uint16_t regval = AD7689_Get();
|
||||
int regval = AD7689_Get();
|
||||
|
||||
// value in mV
|
||||
uint16_t vmin = AD7689_INT_REF_MIN_MV;
|
||||
uint16_t vmax = AD7689_INT_REF_MAX_MV;
|
||||
uint16_t nsteps = (2 ^ AD7689_ADC_DATA_NUMBITS);
|
||||
uint16_t retval = (vmin + (vmax - vmin) * regval / (nsteps - 1));
|
||||
int retval = 0;
|
||||
ConvertToDifferentRange(0, AD7689_INT_MAX_STEPS,
|
||||
AD7689_INT_REF_MIN_MV, AD7689_INT_REF_MAX_MV,
|
||||
regval, &retval);
|
||||
FILE_LOG(logINFO, ("\tvoltage read for chan %d: 0x%d mV\n", retval));
|
||||
|
||||
return retval;
|
||||
@ -210,7 +213,7 @@ void AD7689_Configure(){
|
||||
FILE_LOG(logINFOBLUE, ("Configuring AD7689 (Slow ADCs): \n"));
|
||||
|
||||
// from power up, 3 invalid conversions
|
||||
FILE_LOG(logINFO, ("3 times due to invalid conversions from power up\n"));
|
||||
FILE_LOG(logINFO, ("\tConfiguring %d x due to invalid conversions from power up\n", AD7689_NUM_INVALID_CONVERSIONS));
|
||||
int i = 0;
|
||||
for (i = 0; i < AD7689_NUM_INVALID_CONVERSIONS; ++i) {
|
||||
AD7689_Set(
|
||||
|
@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "blackfin.h"
|
||||
#include <unistd.h> // usleep
|
||||
|
||||
/**
|
||||
* Intel: Embedded Peripherals IP User Guide
|
||||
* https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_embedded_ip.pdf
|
||||
* To be defined
|
||||
*
|
||||
* (in blackfin.h)
|
||||
@ -13,8 +16,10 @@
|
||||
* I2C_SCL_HIGH_COUNT_REG
|
||||
* I2C_SDA_HOLD_REG
|
||||
* I2C_CONTROL_REG
|
||||
* I2C_STATUS_REG
|
||||
* I2C_TRANSFER_COMMAND_FIFO_REG
|
||||
* I2C_RX_DATA_FIFO_LEVEL_REG
|
||||
* I2C_RX_DATA_FIFO_REG
|
||||
*/
|
||||
|
||||
|
||||
@ -53,12 +58,37 @@
|
||||
#define I2C_TFR_CMD_DATA_FR_WR_OFST (0)
|
||||
#define I2C_TFR_CMD_DATA_FR_WR_MSK (0x000000FF << I2C_TFR_CMD_DATA_FR_WR_OFST)
|
||||
#define I2C_TFR_CMD_STOP_OFST (8)
|
||||
#define I2C_TFR_CMD_STOP_MSK (0x00000001 << I2C_TFR_CMD_ADDR_OFST)
|
||||
#define I2C_TFR_CMD_STOP_MSK (0x00000001 << I2C_TFR_CMD_STOP_OFST)
|
||||
#define I2C_TFR_CMD_RPTD_STRT_OFST (9)
|
||||
#define I2C_TFR_CMD_RPTD_STRT_MSK (0x00000001 << I2C_TFR_CMD_RPTD_STRT_OFST)
|
||||
|
||||
/** Receive DataFifo register */
|
||||
#define I2C_RX_DATA_FIFO_RXDATA_OFST (0)
|
||||
#define I2C_RX_DATA_FIFO_RXDATA_MSK (0x000000FF << I2C_RX_DATA_FIFO_RXDATA_OFST)
|
||||
|
||||
/** Status register */
|
||||
#define I2C_STATUS_BUSY_OFST (0)
|
||||
#define I2C_STATUS_BUSY_MSK (0x00000001 << I2C_STATUS_BUSY_OFST)
|
||||
|
||||
/** SCL Low Count register */
|
||||
#define I2C_SCL_LOW_COUNT_PERIOD_OFST (0)
|
||||
#define I2C_SCL_LOW_COUNT_PERIOD_MSK (0x0000FFFF << I2C_SCL_LOW_COUNT_PERIOD_OFST)
|
||||
|
||||
/** SCL High Count register */
|
||||
#define I2C_SCL_HIGH_COUNT_PERIOD_OFST (0)
|
||||
#define I2C_SCL_HIGH_COUNT_PERIOD_MSK (0x0000FFFF << I2C_SCL_HIGH_COUNT_PERIOD_OFST)
|
||||
|
||||
/** SDA Hold Count register */
|
||||
#define I2C_SDA_HOLD_COUNT_PERIOD_OFST (0)
|
||||
#define I2C_SDA_HOLD_COUNT_PERIOD_MSK (0x0000FFFF << I2C_SDA_HOLD_COUNT_PERIOD_OFST)
|
||||
|
||||
/** Receive Data Fifo Level register */
|
||||
//#define I2C_RX_DATA_FIFO_LVL_OFST (0)
|
||||
//#define I2C_RX_DATA_FIFO_LVL_MSK (0x000000FF << I2C_RX_DATA_FIFO_LVL_OFST)
|
||||
|
||||
uint32_t I2C_Control_Reg = 0x0;
|
||||
uint32_t I2C_Status_Reg = 0x0;
|
||||
uint32_t I2C_Rx_Data_Fifo_Reg = 0x0;
|
||||
uint32_t I2C_Rx_Data_Fifo_Level_Reg = 0x0;
|
||||
uint32_t I2C_Scl_Low_Count_Reg = 0x0;
|
||||
uint32_t I2C_Scl_High_Count_Reg = 0x0;
|
||||
@ -70,24 +100,34 @@ uint32_t I2C_Transfer_Command_Fifo_Reg = 0x0;
|
||||
* Enable core and
|
||||
* Calibrate the calibration register for current readout
|
||||
* @param creg control register (defined in RegisterDefs.h)
|
||||
* @param rreg rx data fifo level register (defined in RegisterDefs.h)
|
||||
* @param sreg status register (defined in RegisterDefs.h)
|
||||
* @param rreg rx data fifo register (defined in RegisterDefs.h)
|
||||
* @param rlvlreg rx data fifo level register (defined in RegisterDefs.h)
|
||||
* @param slreg scl low count register (defined in RegisterDefs.h)
|
||||
* @param shreg scl high count register (defined in RegisterDefs.h)
|
||||
* @param sdreg sda hold register (defined in RegisterDefs.h)
|
||||
* @param treg transfer command fifo register (defined in RegisterDefs.h)
|
||||
*/
|
||||
void I2C_ConfigureI2CCore(uint32_t creg, uint32_t rreg, uint32_t slreg, uint32_t shreg, uint32_t sdreg, uint32_t treg) {
|
||||
void I2C_ConfigureI2CCore(uint32_t creg, uint32_t sreg,
|
||||
uint32_t rreg, uint32_t rlvlreg,
|
||||
uint32_t slreg, uint32_t shreg, uint32_t sdreg, uint32_t treg) {
|
||||
FILE_LOG(logINFO, ("\tConfiguring I2C Core for %d kbps:\n", I2C_DATA_RATE_KBPS));
|
||||
FILE_LOG(logDEBUG1,("controlreg,:0x%x, statusreg,:0x%x, "
|
||||
"rxrdatafiforeg: 0x%x, rxdatafifocountreg,:0x%x, "
|
||||
"scllow,:0x%x, sclhighreg,:0x%x, sdaholdreg,:0x%x, transfercmdreg,:0x%x\n",
|
||||
creg, sreg, rreg, rlvlreg, slreg, shreg, sdreg, treg));
|
||||
|
||||
I2C_Control_Reg = creg;
|
||||
I2C_Rx_Data_Fifo_Level_Reg = rreg;
|
||||
I2C_Status_Reg = sreg;
|
||||
I2C_Rx_Data_Fifo_Reg = rreg;
|
||||
I2C_Rx_Data_Fifo_Level_Reg = rlvlreg;
|
||||
I2C_Scl_Low_Count_Reg = slreg;
|
||||
I2C_Scl_High_Count_Reg = shreg;
|
||||
I2C_Sda_Hold_Reg = sdreg;
|
||||
I2C_Transfer_Command_Fifo_Reg = treg;
|
||||
|
||||
// calculate scl low and high period count
|
||||
uint32_t sclPeriodNs = ((1000.00 * 1000.00) / (double)I2C_DATA_RATE_KBPS);
|
||||
uint32_t sclPeriodNs = ((1000.00 * 1000.00 * 1000.00) / ((double)I2C_DATA_RATE_KBPS * 1000.00));
|
||||
// scl low period same as high period
|
||||
uint32_t sclLowPeriodNs = sclPeriodNs / 2;
|
||||
// convert to us, then to clock (defined in blackfin.h)
|
||||
@ -99,16 +139,25 @@ void I2C_ConfigureI2CCore(uint32_t creg, uint32_t rreg, uint32_t slreg, uint32_t
|
||||
uint32_t sdaDataHoldCount = ((sdaDataHoldTimeNs / 1000.00) * I2C_CLOCK_MHZ);
|
||||
|
||||
FILE_LOG(logINFO, ("\tSetting SCL Low Period: %d ns (%d clocks)\n", sclLowPeriodNs, sclLowPeriodCount));
|
||||
bus_w(I2C_Scl_Low_Count_Reg, sclLowPeriodCount);
|
||||
bus_w(I2C_Scl_Low_Count_Reg, bus_r(I2C_Scl_Low_Count_Reg) |
|
||||
((sclLowPeriodCount << I2C_SCL_LOW_COUNT_PERIOD_OFST) & I2C_SCL_LOW_COUNT_PERIOD_MSK));
|
||||
FILE_LOG(logDEBUG1, ("SCL Low reg:0x%x\n", bus_r(I2C_Scl_Low_Count_Reg)));
|
||||
|
||||
FILE_LOG(logINFO, ("\tSetting SCL High Period: %d ns (%d clocks)\n", sclLowPeriodNs, sclLowPeriodCount));
|
||||
bus_w(I2C_Scl_High_Count_Reg, sclLowPeriodCount);
|
||||
bus_w(I2C_Scl_High_Count_Reg, bus_r(I2C_Scl_High_Count_Reg) |
|
||||
((sclLowPeriodCount << I2C_SCL_HIGH_COUNT_PERIOD_OFST) & I2C_SCL_HIGH_COUNT_PERIOD_MSK));
|
||||
FILE_LOG(logDEBUG1, ("SCL High reg:0x%x\n", bus_r(I2C_Scl_High_Count_Reg)));
|
||||
|
||||
FILE_LOG(logINFO, ("\tSetting SDA Hold Time: %d ns (%d clocks)\n", sdaDataHoldTimeNs, sdaDataHoldCount));
|
||||
bus_w(I2C_Sda_Hold_Reg, (uint32_t)sdaDataHoldCount);
|
||||
bus_w(I2C_Sda_Hold_Reg, bus_r(I2C_Sda_Hold_Reg) |
|
||||
((sdaDataHoldCount << I2C_SDA_HOLD_COUNT_PERIOD_OFST) & I2C_SDA_HOLD_COUNT_PERIOD_MSK));
|
||||
FILE_LOG(logDEBUG1, ("SDA Hold reg:0x%x\n", bus_r(I2C_Sda_Hold_Reg)));
|
||||
|
||||
FILE_LOG(logINFO, ("\tEnabling core\n"));
|
||||
bus_w(I2C_Control_Reg, I2C_CTRL_ENBLE_CORE_MSK | I2C_CTRL_BUS_SPEED_FAST_400_VAL);// fixme: (works?)
|
||||
FILE_LOG(logINFO, ("\tEnabling core and bus speed to fast (up to 400 kbps)\n"));
|
||||
bus_w(I2C_Control_Reg, bus_r(I2C_Control_Reg) |
|
||||
I2C_CTRL_ENBLE_CORE_MSK | I2C_CTRL_BUS_SPEED_FAST_400_VAL);// fixme: (works?)
|
||||
FILE_LOG(logDEBUG1, ("Control reg:0x%x\n", bus_r(I2C_Control_Reg)));
|
||||
//The INA226 supports the transmission protocol for fast mode (1 kHz to 400 kHz) and high-speed mode (1 kHz to 2.94 MHz).
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,27 +167,59 @@ void I2C_ConfigureI2CCore(uint32_t creg, uint32_t rreg, uint32_t slreg, uint32_t
|
||||
* @returns value read from register
|
||||
*/
|
||||
uint32_t I2C_Read(uint32_t devId, uint32_t addr) {
|
||||
FILE_LOG(logDEBUG1, ("\tReading from I2C device 0x%x and reg 0x%x\n", devId, addr));
|
||||
FILE_LOG(logDEBUG1, (" ================================================\n"));
|
||||
FILE_LOG(logDEBUG1, (" Reading from I2C device 0x%x and reg 0x%x\n", devId, addr));
|
||||
// device Id mask
|
||||
uint32_t devIdMask = ((devId << I2C_TFR_CMD_ADDR_OFST) & I2C_TFR_CMD_ADDR_MSK);
|
||||
FILE_LOG(logDEBUG1, (" devId:0x%x\n", devIdMask));
|
||||
|
||||
// write I2C ID
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, (devIdMask & ~(I2C_TFR_CMD_RW_MSK)));
|
||||
FILE_LOG(logDEBUG1, (" write devID and R/-W:0x%x\n", (devIdMask & ~(I2C_TFR_CMD_RW_MSK))));
|
||||
|
||||
// write register addr
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, addr);
|
||||
FILE_LOG(logDEBUG1, (" write addr:0x%x\n", addr));
|
||||
|
||||
// repeated start with read
|
||||
// repeated start with read (repeated start needed here because it was in write operation mode earlier, for the device ID)
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, (devIdMask | I2C_TFR_CMD_RPTD_STRT_MSK | I2C_TFR_CMD_RW_READ_VAL));
|
||||
FILE_LOG(logDEBUG1, (" repeated start:0x%x\n", (devIdMask | I2C_TFR_CMD_RPTD_STRT_MSK | I2C_TFR_CMD_RW_READ_VAL)));
|
||||
|
||||
// continue reading
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, 0x0);
|
||||
FILE_LOG(logDEBUG1, (" continue reading:0x%x\n", 0x0));
|
||||
|
||||
// stop reading
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, I2C_TFR_CMD_STOP_MSK);
|
||||
FILE_LOG(logDEBUG1, (" stop reading:0x%x\n", I2C_TFR_CMD_STOP_MSK));
|
||||
|
||||
// read value
|
||||
return bus_r(I2C_Rx_Data_Fifo_Level_Reg);
|
||||
uint32_t retval = 0;
|
||||
|
||||
//In case one wants to do something more general (INA226 receives only 2 bytes)
|
||||
// wait till status is idle
|
||||
int status = 1;
|
||||
while(status) {
|
||||
status = bus_r(I2C_Status_Reg) & I2C_STATUS_BUSY_MSK;
|
||||
FILE_LOG(logDEBUG1, (" status:%d\n", status));
|
||||
usleep(0);
|
||||
}
|
||||
// get rx fifo level (get number of bytes to be received)
|
||||
int level = bus_r(I2C_Rx_Data_Fifo_Level_Reg);
|
||||
FILE_LOG(logDEBUG1, (" level:%d\n", level));
|
||||
|
||||
int iloop = level - 1;
|
||||
|
||||
// level bytes to read, read 1 byte at a time
|
||||
for (iloop = level - 1; iloop >= 0; --iloop) {
|
||||
u_int16_t byte = bus_r(I2C_Rx_Data_Fifo_Reg) & I2C_RX_DATA_FIFO_RXDATA_MSK;
|
||||
FILE_LOG(logDEBUG1, (" byte nr %d:0x%x\n", iloop, byte));
|
||||
// push by 1 byte at a time
|
||||
retval |= (byte << (8 * iloop));
|
||||
}
|
||||
FILE_LOG(logDEBUG1, (" retval:0x%x\n", retval));
|
||||
FILE_LOG(logDEBUG1, (" ================================================\n"));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,27 +229,34 @@ uint32_t I2C_Read(uint32_t devId, uint32_t addr) {
|
||||
* @param data data to be written (16 bit)
|
||||
*/
|
||||
void I2C_Write(uint32_t devId, uint32_t addr, uint16_t data) {
|
||||
FILE_LOG(logDEBUG1, ("Writing to I2C (Device:0x%x, reg:0x%x, data:%d)\n", devId, addr, data));
|
||||
FILE_LOG(logDEBUG1, (" ================================================\n"));
|
||||
FILE_LOG(logDEBUG1, (" Writing to I2C (Device:0x%x, reg:0x%x, data:%d)\n", devId, addr, data));
|
||||
// device Id mask
|
||||
uint32_t devIdMask = ((devId << I2C_TFR_CMD_ADDR_OFST) & I2C_TFR_CMD_ADDR_MSK);
|
||||
FILE_LOG(logDEBUG1, (" devId:0x%x\n", devId));
|
||||
|
||||
// write I2C ID
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, (devIdMask & ~(I2C_TFR_CMD_RW_MSK)));
|
||||
FILE_LOG(logDEBUG1, (" write devID and R/-W:0x%x\n", (devIdMask & ~(I2C_TFR_CMD_RW_MSK))));
|
||||
|
||||
// write register addr
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, addr);
|
||||
FILE_LOG(logDEBUG1, (" write addr:0x%x\n", addr));
|
||||
|
||||
// repeated start with write
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, ((devIdMask | I2C_TFR_CMD_RPTD_STRT_MSK) & ~(I2C_TFR_CMD_RW_MSK)));
|
||||
// do not do the repeated start as it is already in write operation mode (else it wont work)
|
||||
|
||||
uint8_t msb = (uint8_t)((data & 0xFF00) >> 8);
|
||||
uint8_t lsb = (uint8_t)(data & 0x00FF);
|
||||
FILE_LOG(logDEBUG1, (" msb:0x%02x, lsb:0x%02x\n", msb, lsb));
|
||||
|
||||
// writing data MSB
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, ((msb << I2C_TFR_CMD_DATA_FR_WR_OFST) & I2C_TFR_CMD_DATA_FR_WR_MSK));
|
||||
FILE_LOG(logDEBUG1, (" write msb:0x%02x\n", ((msb << I2C_TFR_CMD_DATA_FR_WR_OFST) & I2C_TFR_CMD_DATA_FR_WR_MSK)));
|
||||
|
||||
// writing data LSB and stop writing bit
|
||||
bus_w(I2C_Transfer_Command_Fifo_Reg, ((lsb << I2C_TFR_CMD_DATA_FR_WR_OFST) & I2C_TFR_CMD_DATA_FR_WR_MSK) | I2C_TFR_CMD_STOP_MSK);
|
||||
FILE_LOG(logDEBUG1, (" write lsb and stop writing:0x%x\n", ((lsb << I2C_TFR_CMD_DATA_FR_WR_OFST) & I2C_TFR_CMD_DATA_FR_WR_MSK) | I2C_TFR_CMD_STOP_MSK));
|
||||
FILE_LOG(logDEBUG1, (" ================================================\n"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,35 +13,43 @@
|
||||
/** INA226 defines */
|
||||
|
||||
/** Register set */
|
||||
#define INA226_CONFIGURATION_REG (0x00) //R/W
|
||||
#define INA226_SHUNT_VOLTAGE_REG (0x01) //R
|
||||
#define INA226_BUS_VOLTAGE_REG (0x02) //R
|
||||
#define INA226_POWER_REG (0x03) //R
|
||||
#define INA226_CURRENT_REG (0x04) //R
|
||||
#define INA226_CALIBRATION_REG (0x05) //R/W
|
||||
#define INA226_MASK_ENABLE_REG (0x06) //R/W
|
||||
#define INA226_ALERT_LIMIT_REG (0x07) //R/W
|
||||
#define INA226_MANUFACTURER_ID_REG (0xFE) //R
|
||||
#define INA226_DIE_ID_REG (0xFF) //R
|
||||
#define INA226_CONFIGURATION_REG (0x00) //R/W
|
||||
#define INA226_SHUNT_VOLTAGE_REG (0x01) //R
|
||||
#define INA226_BUS_VOLTAGE_REG (0x02) //R
|
||||
#define INA226_POWER_REG (0x03) //R
|
||||
#define INA226_CURRENT_REG (0x04) //R
|
||||
#define INA226_CALIBRATION_REG (0x05) //R/W
|
||||
#define INA226_MASK_ENABLE_REG (0x06) //R/W
|
||||
#define INA226_ALERT_LIMIT_REG (0x07) //R/W
|
||||
#define INA226_MANUFACTURER_ID_REG (0xFE) //R
|
||||
#define INA226_DIE_ID_REG (0xFF) //R
|
||||
|
||||
/** bus voltage register */
|
||||
#define INA226_BUS_VOLTAGE_VMIN_UV (1250) // 1.25mV
|
||||
#define INA226_BUS_VOLTAGE_MX_STPS (0x7FFF + 1)
|
||||
#define INA226_BUS_VOLTAGE_VMAX_UV (INA226_BUS_VOLTAGE_VMIN_UV * INA226_BUS_VOLTAGE_MX_STPS) // 40960000uV, 40.96V
|
||||
#define INA226_BUS_VOLTAGE_VMIN_UV (1250) // 1.25mV
|
||||
#define INA226_BUS_VOLTAGE_MX_STPS (0x7FFF + 1)
|
||||
#define INA226_BUS_VOLTAGE_VMAX_UV (INA226_BUS_VOLTAGE_VMIN_UV * INA226_BUS_VOLTAGE_MX_STPS) // 40960000uV, 40.96V
|
||||
|
||||
/** current register */
|
||||
#define INA226_CURRENT_IMIN_UA (100) //100uA can be changed
|
||||
#define INA226_CURRENT_MX_STPS (0x7FFF + 1)
|
||||
#define INA226_CURRENT_IMAX_UA (INA226_CURRENT_IMIN_UA * INA226_CURRENT_MX_STPS)
|
||||
|
||||
/** shunt voltage register */
|
||||
#define INA226_SHUNT_VOLTAGE_VMIN_NV (2500) // 2.5uV
|
||||
#define INA226_SHUNT_VOLTAGE_MX_STPS (0x7FFF + 1)
|
||||
#define INA226_SHUNT_VOLTAGE_VMAX_NV (INA226_SHUNT_VOLTAGE_VMIN_NV * INA226_SHUNT_VOLTAGE_MX_STPS) // 81920000nV, 81.92mV
|
||||
#define INA226_SHUNT_NEGATIVE_MSK (1 << 15)
|
||||
#define INA226_SHUNT_ABS_VALUE_MSK (0x7FFF)
|
||||
|
||||
|
||||
|
||||
/** current precision for calibration register */
|
||||
#define INA226_CURRENT_IMIN_UA (100) //100uA can be changed
|
||||
|
||||
/** calibration register */
|
||||
#define INA226_CALIBRATION_MSK (0x7FFF)
|
||||
#define INA226_CALIBRATION_MSK (0x7FFF)
|
||||
|
||||
/** get calibration register value to be set */
|
||||
#define INA226_getCalibrationValue(rOhm) (0.00512 /(INA226_CURRENT_IMIN_UA * 1e-6 * rOhm))
|
||||
#define INA226_getCalibrationValue(rOhm) (0.00512 /(INA226_CURRENT_IMIN_UA * 1e-6 * rOhm))
|
||||
|
||||
/** get current unit */
|
||||
#define INA226_getConvertedCurrentUnits(shuntVReg, calibReg) (shuntVReg * calibReg / 2048)
|
||||
#define INA226_getConvertedCurrentUnits(shuntV, calibReg) ((double)shuntV * (double)calibReg / (double)2048)
|
||||
|
||||
double INA226_Shunt_Resistor_Ohm = 0.0;
|
||||
|
||||
@ -50,18 +58,22 @@ double INA226_Shunt_Resistor_Ohm = 0.0;
|
||||
* Configure the I2C core and Enable core
|
||||
* @param rOhm shunt resister value in Ohms (defined in slsDetectorServer_defs.h)
|
||||
* @param creg control register (defined in RegisterDefs.h)
|
||||
* @param rreg rx data fifo level register (defined in RegisterDefs.h)
|
||||
* @param sreg status register (defined in RegisterDefs.h)
|
||||
* @param rreg rx data fifo register (defined in RegisterDefs.h)
|
||||
* @param rlvlreg rx data fifo level register (defined in RegisterDefs.h)
|
||||
* @param slreg scl low count register (defined in RegisterDefs.h)
|
||||
* @param shreg scl high count register (defined in RegisterDefs.h)
|
||||
* @param sdreg sda hold register (defined in RegisterDefs.h)
|
||||
* @param treg transfer command fifo register (defined in RegisterDefs.h)
|
||||
*/
|
||||
void INA226_ConfigureI2CCore(double rOhm, uint32_t creg, uint32_t rreg, uint32_t slreg, uint32_t shreg, uint32_t sdreg, uint32_t treg) {
|
||||
void INA226_ConfigureI2CCore(double rOhm, uint32_t creg, uint32_t sreg,
|
||||
uint32_t rreg, uint32_t rlvlreg,
|
||||
uint32_t slreg, uint32_t shreg, uint32_t sdreg, uint32_t treg) {
|
||||
FILE_LOG(logINFOBLUE, ("Configuring INA226\n"));
|
||||
|
||||
FILE_LOG(logDEBUG1, ("Shunt ohm resistor: %f\n", rOhm));
|
||||
INA226_Shunt_Resistor_Ohm = rOhm;
|
||||
|
||||
I2C_ConfigureI2CCore(creg, rreg, slreg, shreg, sdreg, treg);
|
||||
I2C_ConfigureI2CCore(creg, sreg, rreg, rlvlreg, slreg, shreg, sdreg, treg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,6 +88,12 @@ void INA226_CalibrateCurrentRegister(uint32_t deviceId) {
|
||||
|
||||
// calibrate current register
|
||||
I2C_Write(deviceId, INA226_CALIBRATION_REG, calVal);
|
||||
|
||||
// read back calibration register
|
||||
int retval = I2C_Read(deviceId, INA226_CALIBRATION_REG);
|
||||
if (retval != calVal) {
|
||||
FILE_LOG(logERROR, ("Cannot set calibration register for I2C. Set 0x%x, read 0x%x\n", calVal, retval));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,24 +102,23 @@ void INA226_CalibrateCurrentRegister(uint32_t deviceId) {
|
||||
* @returns voltage in mV
|
||||
*/
|
||||
int INA226_ReadVoltage(uint32_t deviceId) {
|
||||
FILE_LOG(logDEBUG1, ("\tReading voltage\n"));
|
||||
FILE_LOG(logDEBUG1, (" Reading voltage\n"));
|
||||
uint32_t regval = I2C_Read(deviceId, INA226_BUS_VOLTAGE_REG);
|
||||
FILE_LOG(logDEBUG1, ("\tvoltage read: 0x%08x\n", regval));
|
||||
|
||||
// value converted in mv
|
||||
uint32_t vmin = INA226_BUS_VOLTAGE_VMIN_UV;
|
||||
uint32_t vmax = INA226_BUS_VOLTAGE_VMAX_UV;
|
||||
uint32_t nsteps = INA226_BUS_VOLTAGE_MX_STPS;
|
||||
FILE_LOG(logDEBUG1, (" bus voltage reg: 0x%08x\n", regval));
|
||||
|
||||
// value in uV
|
||||
int retval = (vmin + (vmax - vmin) * regval / (nsteps - 1));
|
||||
FILE_LOG(logDEBUG1, ("\tvoltage read: 0x%d uV\n", retval));
|
||||
int voltageuV = 0;
|
||||
ConvertToDifferentRange(0, INA226_BUS_VOLTAGE_MX_STPS,
|
||||
INA226_BUS_VOLTAGE_VMIN_UV, INA226_BUS_VOLTAGE_VMAX_UV,
|
||||
regval, &voltageuV);
|
||||
FILE_LOG(logDEBUG1, (" voltage: 0x%d uV\n", voltageuV));
|
||||
|
||||
// value in mV
|
||||
retval /= 1000;
|
||||
FILE_LOG(logDEBUG1, ("\tvoltage read: %d mV\n", retval));
|
||||
int voltagemV = voltageuV / 1000;
|
||||
FILE_LOG(logDEBUG1, (" voltage: %d mV\n", voltagemV));
|
||||
FILE_LOG(logINFO, ("Voltage via I2C (Device: 0x%x): %d mV\n", deviceId, voltagemV));
|
||||
|
||||
return retval;
|
||||
return voltagemV;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,29 +127,79 @@ int INA226_ReadVoltage(uint32_t deviceId) {
|
||||
* @returns current in mA
|
||||
*/
|
||||
int INA226_ReadCurrent(uint32_t deviceId) {
|
||||
FILE_LOG(logDEBUG1, ("\tReading current\n"));
|
||||
FILE_LOG(logDEBUG1, (" Reading current\n"));
|
||||
|
||||
// read shunt voltage register
|
||||
FILE_LOG(logDEBUG1, ("\tReading shunt voltage reg\n"));
|
||||
FILE_LOG(logDEBUG1, (" Reading shunt voltage reg\n"));
|
||||
uint32_t shuntVoltageRegVal = I2C_Read(deviceId, INA226_SHUNT_VOLTAGE_REG);
|
||||
FILE_LOG(logDEBUG1, ("\tshunt voltage reg: 0x%08x\n", shuntVoltageRegVal));
|
||||
FILE_LOG(logDEBUG1, (" shunt voltage reg: 0x%x\n", shuntVoltageRegVal));
|
||||
|
||||
// read it once more as this error has occured once
|
||||
if (shuntVoltageRegVal == 0xFFFF) {
|
||||
FILE_LOG(logDEBUG1, (" Reading shunt voltage reg again\n"));
|
||||
shuntVoltageRegVal = I2C_Read(deviceId, INA226_SHUNT_VOLTAGE_REG);
|
||||
FILE_LOG(logDEBUG1, (" shunt voltage reg: 0x%x\n", shuntVoltageRegVal));
|
||||
}
|
||||
|
||||
// get absolute value and if negative
|
||||
int negative = (shuntVoltageRegVal & INA226_SHUNT_NEGATIVE_MSK) ? 1: 0;
|
||||
int shuntabsnV = shuntVoltageRegVal & INA226_SHUNT_ABS_VALUE_MSK;
|
||||
FILE_LOG(logDEBUG1, (" negative: %d, absolute: 0x%x\n", negative, shuntabsnV));
|
||||
|
||||
// negative, convert absolute to 2s complement
|
||||
if (negative) {
|
||||
shuntabsnV = ((~shuntabsnV) + 1);
|
||||
FILE_LOG(logDEBUG1, (" new absolute for negative (2's comple): 0x%x\n", shuntabsnV));
|
||||
}
|
||||
|
||||
// calculate shunt voltage
|
||||
int shuntVoltagenV = 0;
|
||||
ConvertToDifferentRange(0, INA226_SHUNT_VOLTAGE_MX_STPS,
|
||||
INA226_SHUNT_VOLTAGE_VMIN_NV, INA226_SHUNT_VOLTAGE_VMAX_NV,
|
||||
shuntabsnV, &shuntVoltagenV);
|
||||
// if negative, put the sign
|
||||
if (negative)
|
||||
shuntVoltagenV = -(shuntVoltagenV);
|
||||
FILE_LOG(logDEBUG1, (" shunt voltage: %d nV\n", shuntVoltagenV));
|
||||
int shuntVoltageUV = shuntVoltagenV / 1000;
|
||||
FILE_LOG(logDEBUG1, (" shunt voltage: %d uV\n\n", shuntVoltageUV));
|
||||
|
||||
// read calibration register
|
||||
FILE_LOG(logDEBUG1, ("\tReading calibration reg\n"));
|
||||
FILE_LOG(logDEBUG1, (" Reading calibration reg\n"));
|
||||
uint32_t calibrationRegVal = I2C_Read(deviceId, INA226_CALIBRATION_REG);
|
||||
FILE_LOG(logDEBUG1, ("\tcalibration reg: 0x%08x\n", calibrationRegVal));
|
||||
FILE_LOG(logDEBUG1, (" calibration reg: 0x%08x\n\n", calibrationRegVal));
|
||||
|
||||
// read it once more as this error has occured once
|
||||
if (calibrationRegVal == 0xFFFF) {
|
||||
FILE_LOG(logDEBUG1, (" Reading calibration reg again\n"));
|
||||
calibrationRegVal = I2C_Read(deviceId, INA226_CALIBRATION_REG);
|
||||
FILE_LOG(logDEBUG1, (" calibration reg: 0x%x\n", calibrationRegVal));
|
||||
}
|
||||
|
||||
// value for current
|
||||
uint32_t retval = INA226_getConvertedCurrentUnits(shuntVoltageRegVal, calibrationRegVal);
|
||||
FILE_LOG(logDEBUG1, ("\tcurrent unit value: %d\n", retval));
|
||||
int retval = INA226_getConvertedCurrentUnits(shuntVoltageUV, calibrationRegVal);
|
||||
FILE_LOG(logDEBUG1, (" current unit value: %d\n", retval));
|
||||
|
||||
FILE_LOG(logDEBUG1, (" To TEST: should be same as curent unit value\n"
|
||||
" Reading current reg\n"));
|
||||
int cuurentRegVal = I2C_Read(deviceId, INA226_CURRENT_REG);
|
||||
FILE_LOG(logDEBUG1, (" current reg: 0x%x\n", cuurentRegVal));
|
||||
// read it once more as this error has occured once
|
||||
if (cuurentRegVal >= 0xFFF0) {
|
||||
FILE_LOG(logDEBUG1, (" Reading current reg again\n"));
|
||||
cuurentRegVal = I2C_Read(deviceId, INA226_CURRENT_REG);
|
||||
FILE_LOG(logDEBUG1, (" current reg: 0x%x\n", cuurentRegVal));
|
||||
}
|
||||
|
||||
// current in uA
|
||||
retval *= INA226_CURRENT_IMIN_UA;
|
||||
FILE_LOG(logDEBUG1, ("\tcurrent: %d uA\n", retval));
|
||||
int currentuA = retval * INA226_CURRENT_IMIN_UA;
|
||||
FILE_LOG(logDEBUG1, (" current: %d uA\n", currentuA));
|
||||
|
||||
// current in mA
|
||||
retval /= 1000;
|
||||
FILE_LOG(logDEBUG1, ("\tcurrent: %d mA\n", retval));
|
||||
int currentmA = currentuA / 1000;
|
||||
FILE_LOG(logDEBUG1, (" current: %d mA\n", currentmA));
|
||||
|
||||
return retval;
|
||||
FILE_LOG(logINFO, ("Current via I2C (Device: 0x%x): %d mA\n", deviceId, currentmA));
|
||||
|
||||
return currentmA;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin, int outputMax,
|
||||
int inputValue, int* outputValue) {
|
||||
FILE_LOG(logDEBUG1, ("Input Value: %d (Input:(%d - %d), Output:(%d - %d))\n",
|
||||
FILE_LOG(logDEBUG1, (" Input Value: %d (Input:(%d - %d), Output:(%d - %d))\n",
|
||||
inputValue, inputMin, inputMax, outputMin, outputMax));
|
||||
|
||||
// validate within bounds
|
||||
@ -29,7 +29,7 @@ int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin, int outpu
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
double value = (double)((inputValue - inputMin) * (outputMax - outputMin))
|
||||
double value = ((double)(inputValue - inputMin) * (double)(outputMax - outputMin))
|
||||
/ (double)(inputMax - inputMin) + outputMin;
|
||||
|
||||
// double to integer conversion (if decimal places, round to integer)
|
||||
@ -38,7 +38,7 @@ int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin, int outpu
|
||||
}
|
||||
*outputValue = value;
|
||||
|
||||
FILE_LOG(logDEBUG1, ("Converted Ouput Value: %d\n", *outputValue));
|
||||
FILE_LOG(logDEBUG1, (" Converted Ouput Value: %d\n", *outputValue));
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user