From 69f361468ef78c77425c48d2e878465a77df1a9f Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Wed, 20 Feb 2019 08:45:34 +0100 Subject: [PATCH] ctb: power regulators (set dac, get dac, get adc of voltage and current) works --- slsDetectorServers/ctbDetectorServer/Makefile | 2 +- .../ctbDetectorServer/RegisterDefs.h | 2 + .../ctbDetectorServer/gitInfo.txt | 8 +- .../ctbDetectorServer/gitInfoCtb.h | 6 +- .../slsDetectorFunctionList.c | 22 ++- slsDetectorServers/slsDetectorServer/AD7689.h | 27 +-- slsDetectorServers/slsDetectorServer/I2C.h | 120 +++++++++++-- slsDetectorServers/slsDetectorServer/INA226.h | 163 ++++++++++++------ slsDetectorServers/slsDetectorServer/common.h | 6 +- .../slsDetector/slsDetectorCommand.cpp | 34 ++-- 10 files changed, 286 insertions(+), 104 deletions(-) diff --git a/slsDetectorServers/ctbDetectorServer/Makefile b/slsDetectorServers/ctbDetectorServer/Makefile index c9a810d32..0fc48fd87 100755 --- a/slsDetectorServers/ctbDetectorServer/Makefile +++ b/slsDetectorServers/ctbDetectorServer/Makefile @@ -1,6 +1,6 @@ CROSS = bfin-uclinux- CC = $(CROSS)gcc -CFLAGS += -Wall -DCHIPTESTBOARDD -DSTOP_SERVER -DDEBUG1 #-DJCTB -DVERBOSEI #-DVERBOSE +CFLAGS += -Wall -DCHIPTESTBOARDD -DSTOP_SERVER #-DDEBUG1 #-DJCTB -DVERBOSEI #-DVERBOSE LDLIBS += -lm -lstdc++ PROGS = ctbDetectorServer diff --git a/slsDetectorServers/ctbDetectorServer/RegisterDefs.h b/slsDetectorServers/ctbDetectorServer/RegisterDefs.h index 9c9d6158c..0982df71c 100644 --- a/slsDetectorServers/ctbDetectorServer/RegisterDefs.h +++ b/slsDetectorServers/ctbDetectorServer/RegisterDefs.h @@ -523,7 +523,9 @@ /** I2C Control register */ #define I2C_TRANSFER_COMMAND_FIFO_REG (0x100 << MEM_MAP_SHIFT) +#define I2C_RX_DATA_FIFO_REG (0x101 << MEM_MAP_SHIFT) #define I2C_CONTROL_REG (0x102 << MEM_MAP_SHIFT) +#define I2C_STATUS_REG (0x105 << MEM_MAP_SHIFT) #define I2C_RX_DATA_FIFO_LEVEL_REG (0x107 << MEM_MAP_SHIFT) #define I2C_SCL_LOW_COUNT_REG (0x108 << MEM_MAP_SHIFT) #define I2C_SCL_HIGH_COUNT_REG (0x109 << MEM_MAP_SHIFT) diff --git a/slsDetectorServers/ctbDetectorServer/gitInfo.txt b/slsDetectorServers/ctbDetectorServer/gitInfo.txt index 306ef576b..9bad94956 100644 --- a/slsDetectorServers/ctbDetectorServer/gitInfo.txt +++ b/slsDetectorServers/ctbDetectorServer/gitInfo.txt @@ -1,9 +1,9 @@ Path: slsDetectorPackage/slsDetectorServers/ctbDetectorServer URL: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git Repository Root: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git -Repsitory UUID: 501c579f6b5d63ceee66cd10285890bf65e44e8e -Revision: 17 +Repsitory UUID: c93f88b7e5afe231ec43c47d60278c6acdb520af +Revision: 19 Branch: refactor Last Changed Author: Dhanya_Thattil -Last Changed Rev: 4331 -Last Changed Date: 2019-02-14 09:37:20.000000002 +0100 ./RegisterDefs.h +Last Changed Rev: 4333 +Last Changed Date: 2019-02-20 08:12:50.000000002 +0100 ./RegisterDefs.h diff --git a/slsDetectorServers/ctbDetectorServer/gitInfoCtb.h b/slsDetectorServers/ctbDetectorServer/gitInfoCtb.h index fe6365147..d8a4de296 100644 --- a/slsDetectorServers/ctbDetectorServer/gitInfoCtb.h +++ b/slsDetectorServers/ctbDetectorServer/gitInfoCtb.h @@ -1,6 +1,6 @@ #define GITURL "git@github.com:slsdetectorgroup/slsDetectorPackage.git" -#define GITREPUUID "501c579f6b5d63ceee66cd10285890bf65e44e8e" +#define GITREPUUID "c93f88b7e5afe231ec43c47d60278c6acdb520af" #define GITAUTH "Dhanya_Thattil" -#define GITREV 0x4331 -#define GITDATE 0x20190214 +#define GITREV 0x4333 +#define GITDATE 0x20190220 #define GITBRANCH "refactor" diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 294268d4a..1f8b40a69 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -515,7 +515,7 @@ void setupDetector() { // power regulators // I2C - INA226_ConfigureI2CCore(I2C_SHUNT_RESISTER_OHMS, I2C_CONTROL_REG, I2C_RX_DATA_FIFO_LEVEL_REG, I2C_SCL_LOW_COUNT_REG, I2C_SCL_HIGH_COUNT_REG, I2C_SDA_HOLD_REG, I2C_TRANSFER_COMMAND_FIFO_REG); + INA226_ConfigureI2CCore(I2C_SHUNT_RESISTER_OHMS, I2C_CONTROL_REG, I2C_STATUS_REG, I2C_RX_DATA_FIFO_REG, I2C_RX_DATA_FIFO_LEVEL_REG, I2C_SCL_LOW_COUNT_REG, I2C_SCL_HIGH_COUNT_REG, I2C_SDA_HOLD_REG, I2C_TRANSFER_COMMAND_FIFO_REG); INA226_CalibrateCurrentRegister(I2C_POWER_VIO_DEVICE_ID); INA226_CalibrateCurrentRegister(I2C_POWER_VA_DEVICE_ID); INA226_CalibrateCurrentRegister(I2C_POWER_VB_DEVICE_ID); @@ -1138,6 +1138,7 @@ void setVchip(int val) { } int getVChipToSet(enum DACINDEX ind, int val) { + FILE_LOG(logDEBUG1, ("Calculating vchip to set\n")); // validate index & get adc index int adcIndex = getADCIndexFromDACIndex(ind); if (adcIndex == -1) { @@ -1286,15 +1287,17 @@ void setPower(enum DACINDEX ind, int val) { // get vchip to set vchip (calculated now before switching off power enable) int vchip = getVChipToSet(ind, val); + FILE_LOG(logDEBUG1, ("Vchip to set: %d\n", vchip)); // index problem of vchip calculation problem if (vchip == -1) return; // Switch off power enable + FILE_LOG(logDEBUG1, ("Switching off power enable\n")); bus_w(addr, bus_r(addr) & ~(mask)); // power down dac - FILE_LOG(logINFO, ("Powering off P%d (DAC %d)\n", adcIndex, ind)); + FILE_LOG(logDEBUG1, ("Powering off P%d (DAC %d)\n", adcIndex, ind)); setDAC(ind, LTC2620_PWR_DOWN_VAL, 0); // set vchip @@ -1310,6 +1313,11 @@ void setPower(enum DACINDEX ind, int val) { // convert it to dac (power off is anyway done with power enable) if (val != LTC2620_PWR_DOWN_VAL) { + FILE_LOG(logDEBUG1, ("Convert Power of %d mV to dac units\n", val)); +/* + val = (double)val * 0.95; + FILE_LOG(logDEBUG1, ("Convert new Power of %d mV to dac units\n", val)); +*/ int dacval = -1; // convert voltage to dac if (ConvertToDifferentRange(POWER_RGLTR_MIN, POWER_RGLTR_MAX, LTC2620_MAX_VAL, LTC2620_MIN_VAL, @@ -1318,14 +1326,20 @@ void setPower(enum DACINDEX ind, int val) { ind, val, POWER_RGLTR_MIN, vchip - VCHIP_POWER_INCRMNT)); return; } - +/* + if (dacval > LTC2620_MAX_VAL) + dacval = LTC2620_MAX_VAL; + FILE_LOG(logDEBUG1, ("Converted new dac val: %d\n", dacval)); +*/ // set and power on/ update dac FILE_LOG(logINFO, ("Setting P%d (DAC %d): %d dac (%d mV)\n", adcIndex, ind, dacval, val)); setDAC(ind, dacval, 0); // to be sure of valid conversion - if (dacval >= 0) + if (dacval >= 0) { + FILE_LOG(logDEBUG1, ("Switching on power enable\n")); bus_w(addr, bus_r(addr) | mask); + } } } } diff --git a/slsDetectorServers/slsDetectorServer/AD7689.h b/slsDetectorServers/slsDetectorServer/AD7689.h index 77e7703df..0adfbf46b 100755 --- a/slsDetectorServers/slsDetectorServer/AD7689.h +++ b/slsDetectorServers/slsDetectorServer/AD7689.h @@ -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( diff --git a/slsDetectorServers/slsDetectorServer/I2C.h b/slsDetectorServers/slsDetectorServer/I2C.h index 71402dccd..ad687003f 100755 --- a/slsDetectorServers/slsDetectorServer/I2C.h +++ b/slsDetectorServers/slsDetectorServer/I2C.h @@ -1,8 +1,11 @@ #pragma once #include "blackfin.h" +#include // 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")); } diff --git a/slsDetectorServers/slsDetectorServer/INA226.h b/slsDetectorServers/slsDetectorServer/INA226.h index d694303ab..71ba30b2e 100755 --- a/slsDetectorServers/slsDetectorServer/INA226.h +++ b/slsDetectorServers/slsDetectorServer/INA226.h @@ -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; } diff --git a/slsDetectorServers/slsDetectorServer/common.h b/slsDetectorServers/slsDetectorServer/common.h index a67d125ba..422f49967 100755 --- a/slsDetectorServers/slsDetectorServer/common.h +++ b/slsDetectorServers/slsDetectorServer/common.h @@ -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; } diff --git a/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp b/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp index 694b32008..505e9f1b6 100644 --- a/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/slsDetector/slsDetectorCommand.cpp @@ -3742,19 +3742,25 @@ std::string slsDetectorCommand::cmdDAC(int narg, char *args[], int action, int d dac = E_Vis; else if (cmd == "iodelay") dac = IO_DELAY; - else if (cmd == "v_a") + else if (cmd == "v_a") { dac = V_POWER_A; - else if (cmd == "v_b") + mode = 1; + } else if (cmd == "v_b") { dac = V_POWER_B; - else if (cmd == "v_c") + mode = 1; + } else if (cmd == "v_c") { dac = V_POWER_C; - else if (cmd == "v_d") + mode = 1; + } else if (cmd == "v_d") { dac = V_POWER_D; - else if (cmd == "v_io") + mode = 1; + } else if (cmd == "v_io") { dac = V_POWER_IO; - else if (cmd == "v_chip") + mode = 1; + } else if (cmd == "v_chip") { dac = V_POWER_CHIP; - else if (cmd == "v_limit") + mode = 1; + } else if (cmd == "v_limit") dac = V_LIMIT; else if (cmd == "vIpre") dac = M_vIpre; @@ -3803,10 +3809,10 @@ std::string slsDetectorCommand::cmdDAC(int narg, char *args[], int action, int d myDet->setDAC(val, dac, mode, detPos); } - - else if (narg >= 2) - if (!strcasecmp(args[1], "mv")) - mode = 1; + // get (dacs in dac units or mV) + else if ((narg >= 2) && (!strcasecmp(args[1], "mv"))) { + mode = 1; + } sprintf(answer, "%d", myDet->setDAC(-1, dac, mode, detPos)); if (mode) @@ -4064,9 +4070,11 @@ std::string slsDetectorCommand::cmdADC(int narg, char *args[], int action, int d //if ((adc == TEMPERATURE_ADC) || (adc == TEMPERATURE_FPGA)) if (adc < 100 || adc == SLOW_ADC_TEMP) - strcat(answer,"°C"); + strcat(answer," °C"); + else if (adc == I_POWER_A || adc == I_POWER_B || adc == I_POWER_C || adc == I_POWER_D || adc == I_POWER_IO) + strcat(answer," mA"); else - strcat(answer,"mV"); + strcat(answer," mV"); return std::string(answer);