Dev/xilinx set power (#1316)
Some checks failed
Build on RHEL9 / build (push) Failing after 3m5s
Build on RHEL8 / build (push) Failing after 5m10s

* ctb updates not in release notes

* xilinx power similar to ctb,except no vchip
This commit is contained in:
2025-10-16 13:57:11 +02:00
committed by GitHub
parent d2560aa7f1
commit 5041fd7fef
6 changed files with 103 additions and 98 deletions

View File

@@ -26,11 +26,7 @@ This document describes the differences between vx.x.x and vx.0.2
1 New, Changed or Resolved Features 1 New, Changed or Resolved Features
===================================== =====================================
1.8 Gui
----------
Bug Fix:
Plotting specific ADC as waveform plots correct data
2 On-board Detector Server Compatibility 2 On-board Detector Server Compatibility

View File

@@ -398,8 +398,8 @@ int getPower();
void setPower(enum DACINDEX ind, int val); void setPower(enum DACINDEX ind, int val);
void powerOff(); void powerOff();
#elif XILINX_CHIPTESTBOARDD #elif XILINX_CHIPTESTBOARDD
int getBitOffsetFromDACIndex(enum DACINDEX ind);
int isPowerValid(enum DACINDEX ind, int val); int isPowerValid(enum DACINDEX ind, int val);
int getPower(); int getPower();
void setPower(enum DACINDEX ind, int val); void setPower(enum DACINDEX ind, int val);
#endif #endif

View File

@@ -1205,6 +1205,26 @@ void setVLimit(int l) {
vLimit = l; vLimit = l;
} }
int getBitOffsetFromDACIndex(enum DACINDEX ind) {
switch (ind) {
case D_PWR_IO:
return POWER_VIO_OFST;
case D_PWR_A:
return POWER_VCC_A_OFST;
case D_PWR_B:
return POWER_VCC_B_OFST;
case D_PWR_C:
return POWER_VCC_C_OFST;
case D_PWR_D:
return POWER_VCC_D_OFST;
default:
LOG(logERROR,
("DAC index %d is not defined to get offset in ctrl register\n",
ind));
return -1;
}
}
int isPowerValid(enum DACINDEX ind, int val) { int isPowerValid(enum DACINDEX ind, int val) {
char *powerNames[] = {PWR_NAMES}; char *powerNames[] = {PWR_NAMES};
int pwrIndex = (int)(ind - D_PWR_D); int pwrIndex = (int)(ind - D_PWR_D);
@@ -1227,10 +1247,23 @@ int isPowerValid(enum DACINDEX ind, int val) {
} }
int getPower(enum DACINDEX ind) { int getPower(enum DACINDEX ind) {
// get bit offset in ctrl register
int bitOffset = getBitOffsetFromDACIndex(ind);
if (bitOffset == -1) {
return -1;
}
// powered enable off
{
uint32_t addr = CTRL_REG;
uint32_t mask = (1 << bitOffset);
if (!(bus_r(addr) & mask))
return 0;
}
char *powerNames[] = {PWR_NAMES}; char *powerNames[] = {PWR_NAMES};
int pwrIndex = (int)(ind - D_PWR_D); int pwrIndex = (int)(ind - D_PWR_D);
// check dac value
// not set yet // not set yet
if (dacValues[ind] == -1) { if (dacValues[ind] == -1) {
LOG(logERROR, LOG(logERROR,
@@ -1240,7 +1273,8 @@ int getPower(enum DACINDEX ind) {
// dac powered off // dac powered off
if (dacValues[ind] == LTC2620_D_GetPowerDownValue()) { if (dacValues[ind] == LTC2620_D_GetPowerDownValue()) {
LOG(logWARNING, ("Power V%s is powered down\n", powerNames[pwrIndex])); LOG(logWARNING, ("Power V%s enabled, but voltage is at minimum or 0.\n",
powerNames[pwrIndex]));
return LTC2620_D_GetPowerDownValue(); return LTC2620_D_GetPowerDownValue();
} }
@@ -1254,26 +1288,43 @@ int getPower(enum DACINDEX ind) {
} }
void setPower(enum DACINDEX ind, int val) { void setPower(enum DACINDEX ind, int val) {
// validate index and get bit offset in ctrl register
int bitOffset = getBitOffsetFromDACIndex(ind);
if (bitOffset == -1) {
return;
}
uint32_t addr = CTRL_REG;
uint32_t mask = (1 << bitOffset);
if (val == -1)
return;
char *powerNames[] = {PWR_NAMES}; char *powerNames[] = {PWR_NAMES};
int pwrIndex = (int)(ind - D_PWR_D); int pwrIndex = (int)(ind - D_PWR_D);
LOG(logINFO, ("Setting Power V%s to %d mV\n", powerNames[pwrIndex], val));
// power down dac
if (val == LTC2620_D_GetPowerDownValue()) {
LOG(logINFO, ("\tPowering down V%d\n", powerNames[pwrIndex]));
setDAC(ind, LTC2620_D_GetPowerDownValue(), 0);
}
// set dac
else if (val >= 0) {
LOG(logINFO,
("Setting Power V%s to %d mV\n", powerNames[pwrIndex], val));
// validate value (already checked at tcp (funcs.c)) // validate value (already checked at tcp (funcs.c))
if (!isPowerValid(ind, val)) { if (!isPowerValid(ind, val)) {
LOG(logERROR, ("Invalid power value for V%s: %d mV\n",
powerNames[pwrIndex], val));
return; return;
} }
// convert voltage to dac // Switch off power enable
LOG(logDEBUG1, ("Switching off power enable\n"));
bus_w(addr, bus_r(addr) & ~(mask));
// power down dac
LOG(logINFO, ("\tPowering down V%d\n", powerNames[pwrIndex]));
setDAC(ind, LTC2620_D_GetPowerDownValue(), 0);
//(power off is anyway done with power enable)
if (val == 0)
val = LTC2620_D_GetPowerDownValue();
// convert voltage to dac (power off is anyway done with power enable)
if (val != LTC2620_D_GetPowerDownValue()) {
int dacval = -1; int dacval = -1;
if (ConvertToDifferentRange( if (ConvertToDifferentRange(
POWER_RGLTR_MIN, POWER_RGLTR_MAX, LTC2620_D_GetMaxInput(), POWER_RGLTR_MIN, POWER_RGLTR_MAX, LTC2620_D_GetMaxInput(),
@@ -1290,6 +1341,12 @@ void setPower(enum DACINDEX ind, int val) {
LOG(logINFO, ("Setting Power V%s: %d mV (%d dac)\n", LOG(logINFO, ("Setting Power V%s: %d mV (%d dac)\n",
powerNames[pwrIndex], val, dacval)); powerNames[pwrIndex], val, dacval));
setDAC(ind, dacval, 0); setDAC(ind, dacval, 0);
// if valid, enable power
if (dacval >= 0) {
LOG(logDEBUG1, ("Switching on power enable\n"));
bus_w(addr, bus_r(addr) | mask);
}
} }
} }

View File

@@ -1025,92 +1025,44 @@ TEST_CASE("dbitclk", "[.cmdcall]") {
} }
} }
TEST_CASE("v_a", "[.cmdcall]") { TEST_CASE("v_abcd", "[.cmdcall]") {
Detector det; Detector det;
Caller caller(&det); Caller caller(&det);
auto det_type = det.getDetectorType().squash(); auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) { std::vector<std::string> cmds{"v_a", "v_b", "v_c", "v_d"};
auto prev_val = det.getPower(defs::V_POWER_A); std::vector<defs::dacIndex> indices{defs::V_POWER_A, defs::V_POWER_B,
{ defs::V_POWER_C, defs::V_POWER_D};
std::ostringstream oss1, oss2;
caller.call("v_a", {"1200"}, -1, PUT, oss1); if (det.isVirtualDetectorServer().tsquash("Inconsistent virtual servers")) {
REQUIRE(oss1.str() == "v_a 1200\n"); cmds.push_back("v_io");
caller.call("v_a", {}, -1, GET, oss2); indices.push_back(defs::V_POWER_IO);
REQUIRE(oss2.str() == "v_a 1200\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setPower(defs::V_POWER_A, prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("v_a", {}, -1, GET));
}
} }
TEST_CASE("v_b", "[.cmdcall]") { for (size_t i = 0; i < cmds.size(); ++i) {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD || if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) { det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getPower(defs::V_POWER_B); auto prev_val = det.getPower(indices[i]);
{
std::ostringstream oss;
caller.call(cmds[i], {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == cmds[i] + " 0\n");
}
{ {
std::ostringstream oss1, oss2; std::ostringstream oss1, oss2;
caller.call("v_b", {"1200"}, -1, PUT, oss1); caller.call(cmds[i], {"1200"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "v_b 1200\n"); REQUIRE(oss1.str() == cmds[i] + " 1200\n");
caller.call("v_b", {}, -1, GET, oss2); caller.call(cmds[i], {}, -1, GET, oss2);
REQUIRE(oss2.str() == "v_b 1200\n"); REQUIRE(oss2.str() == cmds[i] + " 1200\n");
} }
for (int i = 0; i != det.size(); ++i) { for (int i = 0; i != det.size(); ++i) {
det.setPower(defs::V_POWER_B, prev_val[i], {i}); det.setPower(indices[i], prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("v_b", {}, -1, GET));
}
} }
TEST_CASE("v_c", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getPower(defs::V_POWER_C);
{
std::ostringstream oss1, oss2;
caller.call("v_c", {"1200"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "v_c 1200\n");
caller.call("v_c", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "v_c 1200\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setPower(defs::V_POWER_C, prev_val[i], {i});
}
} else { } else {
REQUIRE_THROWS(caller.call("v_c", {}, -1, GET)); REQUIRE_THROWS(caller.call(cmds[i], {}, -1, GET));
} }
} }
TEST_CASE("v_d", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_val = det.getPower(defs::V_POWER_D);
{
std::ostringstream oss1, oss2;
caller.call("v_d", {"1200"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "v_d 1200\n");
caller.call("v_d", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "v_d 1200\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setPower(defs::V_POWER_D, prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("v_d", {}, -1, GET));
}
} }
TEST_CASE("v_io", "[.cmdcall]") { TEST_CASE("v_io", "[.cmdcall]") {

View File

@@ -7,6 +7,6 @@
#define APIGOTTHARD2 "0.0.0 0x250909" #define APIGOTTHARD2 "0.0.0 0x250909"
#define APIMOENCH "0.0.0 0x250909" #define APIMOENCH "0.0.0 0x250909"
#define APIEIGER "0.0.0 0x250909" #define APIEIGER "0.0.0 0x250909"
#define APIXILINXCTB "0.0.0 0x250930" #define APIXILINXCTB "0.0.0 0x251015"
#define APIJUNGFRAU "0.0.0 0x250909" #define APIJUNGFRAU "0.0.0 0x250909"
#define APIMYTHEN3 "0.0.0 0x250922" #define APIMYTHEN3 "0.0.0 0x250922"