Compare commits

..

2 Commits

Author SHA1 Message Date
c09f92b043 xilinx: setDAC and setPower returns, setPower cannot set < vmin or 0, setDAC ensures dac value for power regulators cannot be power down value, remove virtual isTransceiverAligned to always return 1 2026-01-13 14:16:14 +01:00
0ba1139741 remove hardcoded MH02 startup
All checks were successful
Build on RHEL9 / build (push) Successful in 3m45s
Build on RHEL8 / build (push) Successful in 4m51s
Build on local RHEL9 / build (push) Successful in 1m25s
Build on local RHEL8 / build (push) Successful in 3m32s
2026-01-13 11:05:37 +01:00
8 changed files with 85 additions and 111 deletions

View File

@@ -1,6 +1,5 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
import pathlib
from ._slsdet import CppDetectorApi from ._slsdet import CppDetectorApi
from ._slsdet import slsDetectorDefs from ._slsdet import slsDetectorDefs
from ._slsdet import IpAddr, MacAddr from ._slsdet import IpAddr, MacAddr
@@ -3767,13 +3766,9 @@ class Detector(CppDetectorApi):
raise NotImplementedError("Pattern is set only") raise NotImplementedError("Pattern is set only")
@pattern.setter @pattern.setter
def pattern(self, name_or_pattern): def pattern(self, fname):
# If passed a file path, convert to string representation fname = ut.make_string_path(fname)
# with the path expanded. Otherwise it's probably a sls::Pattern ut.set_using_dict(self.setPattern, fname)
# and we can pass it directly.
if isinstance(name_or_pattern, (pathlib.Path, str)):
name_or_pattern = ut.make_string_path(name_or_pattern)
ut.set_using_dict(self.setPattern, name_or_pattern)
@property @property
def patfname(self): def patfname(self):

View File

@@ -373,6 +373,8 @@ int getOnChipDAC(enum ONCHIP_DACINDEX ind, int chipIndex);
void setDAC(enum DACINDEX ind, int val, int mV, int counterEnableCheck); void setDAC(enum DACINDEX ind, int val, int mV, int counterEnableCheck);
void setGeneralDAC(enum DACINDEX ind, int val, int mV); void setGeneralDAC(enum DACINDEX ind, int val, int mV);
void setVthDac(int index, int enable); void setVthDac(int index, int enable);
#elif defined(XILINX_CHIPTESTBOARDD)
int setDAC(enum DACINDEX ind, int val, int mV);
#else #else
void setDAC(enum DACINDEX ind, int val, int mV); void setDAC(enum DACINDEX ind, int val, int mV);
#endif #endif
@@ -401,7 +403,7 @@ void powerOff();
int getBitOffsetFromDACIndex(enum DACINDEX ind); 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); int setPower(enum DACINDEX ind, int val);
#endif #endif
#if defined(MYTHEN3D) || defined(GOTTHARD2D) || defined(XILINX_CHIPTESTBOARDD) #if defined(MYTHEN3D) || defined(GOTTHARD2D) || defined(XILINX_CHIPTESTBOARDD)

View File

@@ -1302,7 +1302,17 @@ int validateAndSetDac(enum dacIndex ind, int val, int mV) {
} }
else { else {
#ifdef XILINX_CHIPTESTBOARDD
ret = setPower(serverDacIndex, val);
if (ret == FAIL) {
sprintf(mess,
"Setting power regulator %d to value %d failed.\n",
serverDacIndex, val);
LOG(logERROR, (mess));
}
#else
setPower(serverDacIndex, val); setPower(serverDacIndex, val);
#endif
} }
} }
if (ret == OK) { if (ret == OK) {
@@ -1393,6 +1403,15 @@ int validateAndSetDac(enum dacIndex ind, int val, int mV) {
#ifdef MYTHEN3D #ifdef MYTHEN3D
// ignore counter enable to force vth dac values // ignore counter enable to force vth dac values
setDAC(serverDacIndex, val, mV, 0); setDAC(serverDacIndex, val, mV, 0);
#elif defined(XILINX_CHIPTESTBOARDD)
{
ret = setDAC(serverDacIndex, val, mV);
if (ret == FAIL) {
sprintf(mess, "Setting dac %d to value %d failed.\n",
serverDacIndex, val);
LOG(logERROR, (mess));
}
}
#else #else
setDAC(serverDacIndex, val, mV); setDAC(serverDacIndex, val, mV);
#endif #endif

View File

@@ -1,24 +1 @@
# Prepare MH02 configuration # nothing
reg 0xC00C 0x00040041
reg 0xC010 0x01200004
# configure Matterhorn SPI
setbit 0xC014 0
# wait till config is done
pollbit 0xC014 3 0
# reset transceiver
reg 0xC120 0x0
reg 0xC120 0x1
reg 0xC120 0x0
# set MSB LSB inversions and polarity for transceiver
reg 0xC120 0x1e0
# Enable MH02 PLL clock
pattern enable_clock_pattern.pyat
# start the flow
setbit 0xB030 0
clearbit 0xB030 0
sleep 1

View File

@@ -1,39 +1,2 @@
# turn off clock # nothing
clearbit 0xB018 15
setbit 0xB010 15
sleep 1
# reset Matterhorn periphery
setbit 0xC014 1
sleep 1
# turn on clock
clearbit 0xB010 15
sleep 1
# reset rx transceiver datapath
setbit 0xC120 4
sleep 1
# reset 8b10b counters
setbit 0xC120 9
setbit 0xC120 10
setbit 0xC120 11
setbit 0xC120 12
sleep 1
clearbit 0xC120 9
clearbit 0xC120 10
# reset buffer fifos
reg 0x9024 0xFFFFFFFF
reg 0x9028 0xFFFFFFFF
reg 0x902C 0xFFFFFFFF
reg 0x9024 0x0
reg 0x9028 0x0
reg 0x902C 0x0
setbit 0xA000 18
# load default pattern
pattern readout_pattern.pyat

View File

@@ -413,9 +413,13 @@ void setupDetector() {
} }
LOG(logINFOBLUE, ("Powering down all dacs\n")); LOG(logINFOBLUE, ("Powering down all dacs\n"));
for (int idac = 0; idac < NDAC; ++idac) { for (int idac = 0; idac < NDAC_ONLY; ++idac) {
setDAC(idac, LTC2620_D_GetPowerDownValue(), 0); setDAC(idac, LTC2620_D_GetPowerDownValue(), 0);
} }
LOG(logINFOBLUE, ("Defaulting all power regulators to 0 mV.\n"));
for (int idac = NDAC_ONLY; idac < NDAC; ++idac) {
setDAC(idac, 0, 0);
}
resetFlow(); resetFlow();
cleanFifos(); cleanFifos();
@@ -509,9 +513,6 @@ void setTransceiverAlignment(int align) {
#endif #endif
int isTransceiverAligned() { int isTransceiverAligned() {
#ifdef VIRTUAL
return 1;
#endif
int times = 0; int times = 0;
int retval = bus_r(TRANSCEIVERSTATUS2) & RXLOCKED_MSK; int retval = bus_r(TRANSCEIVERSTATUS2) & RXLOCKED_MSK;
while (retval) { while (retval) {
@@ -1151,19 +1152,42 @@ int64_t getMeasurementTime() {
/* parameters - dac, adc, hv */ /* parameters - dac, adc, hv */
void setDAC(enum DACINDEX ind, int val, int mV) { int setDAC(enum DACINDEX ind, int val, int mV) {
// Cannot use power down value for power regulators
if (val == LTC2620_D_GetPowerDownValue()) {
switch (ind) {
case D_PWR_D:
case D_PWR_EMPTY:
case D_PWR_IO:
case D_PWR_A:
case D_PWR_B:
case D_PWR_C:
LOG(logERROR, ("Cannot power down Power regulators.\n"));
return FAIL;
default:
break;
}
}
char dacName[MAX_STR_LENGTH] = {0}; char dacName[MAX_STR_LENGTH] = {0};
memset(dacName, 0, MAX_STR_LENGTH); memset(dacName, 0, MAX_STR_LENGTH);
sprintf(dacName, "dac%d", (int)ind); sprintf(dacName, "dac%d", (int)ind);
if (val < 0 && val != LTC2620_D_GetPowerDownValue()) if (val < 0 && val != LTC2620_D_GetPowerDownValue()) {
return; LOG(logERROR,
("Invalid value %d for dac[%d - %s]\n", val, (int)ind, dacName));
return FAIL;
}
LOG(logDEBUG1, ("Setting dac[%d - %s]: %d %s \n", (int)ind, dacName, val, LOG(logDEBUG1, ("Setting dac[%d - %s]: %d %s \n", (int)ind, dacName, val,
(mV ? "mV" : "dac units"))); (mV ? "mV" : "dac units")));
int dacval = val; int dacval = val;
if (LTC2620_D_SetDACValue((int)ind, val, mV, dacName, &dacval) == OK) if (LTC2620_D_SetDACValue((int)ind, val, mV, dacName, &dacval) == FAIL)
dacValues[ind] = dacval; return FAIL;
dacValues[ind] = dacval;
return OK;
} }
int getDAC(enum DACINDEX ind, int mV) { int getDAC(enum DACINDEX ind, int mV) {
@@ -1243,8 +1267,7 @@ int isPowerValid(enum DACINDEX ind, int val) {
} }
// not power_rgltr_max because it is allowed only upto vchip max - 200 // not power_rgltr_max because it is allowed only upto vchip max - 200
if (val != 0 && (val != LTC2620_D_GetPowerDownValue()) && if (val != 0 && (val < min || val > POWER_RGLTR_MAX)) {
(val < min || val > POWER_RGLTR_MAX)) {
LOG(logERROR, LOG(logERROR,
("Invalid value of %d mV for Power V%s. Is not between %d and " ("Invalid value of %d mV for Power V%s. Is not between %d and "
"%d mV\n", "%d mV\n",
@@ -1295,44 +1318,36 @@ int getPower(enum DACINDEX ind) {
return retval; return retval;
} }
void setPower(enum DACINDEX ind, int val) { int setPower(enum DACINDEX ind, int val) {
// validate index and get bit offset in ctrl register // validate index and get bit offset in ctrl register
int bitOffset = getBitOffsetFromDACIndex(ind); int bitOffset = getBitOffsetFromDACIndex(ind);
if (bitOffset == -1) { if (bitOffset == -1) {
return; return FAIL;
} }
uint32_t addr = CTRL_REG; uint32_t addr = CTRL_REG;
uint32_t mask = (1 << bitOffset); 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)); 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", return FAIL;
powerNames[pwrIndex], val));
return;
} }
// Switch off power enable // Switch off power enable
LOG(logDEBUG1, ("Switching off power enable\n")); LOG(logDEBUG1, ("\tSwitching off power enable\n"));
bus_w(addr, bus_r(addr) & ~(mask)); bus_w(addr, bus_r(addr) & ~(mask));
// power down dac // power down dac (Cannot use power down value for power regulators)
LOG(logINFO, ("\tPowering down V%d\n", powerNames[pwrIndex])); if (setDAC(ind, 0, 0) == FAIL) {
setDAC(ind, LTC2620_D_GetPowerDownValue(), 0); return FAIL;
}
//(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()) {
// convert voltage to dac
if (val != 0) {
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(),
@@ -1342,20 +1357,23 @@ void setPower(enum DACINDEX ind, int val) {
"mV. Is not between " "mV. Is not between "
"%d and %d mV\n", "%d and %d mV\n",
powerNames[pwrIndex], val, POWER_RGLTR_MIN, POWER_RGLTR_MAX)); powerNames[pwrIndex], val, POWER_RGLTR_MIN, POWER_RGLTR_MAX));
return; return FAIL;
} }
// set and power on/ update dac LOG(logINFO, ("\tSetting DAC 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); if (setDAC(ind, dacval, 0) == FAIL) {
LOG(logERROR,
// if valid, enable power ("Could not set dac for Power V%s\n", powerNames[pwrIndex]));
if (dacval >= 0) { return FAIL;
LOG(logDEBUG1, ("Switching on power enable\n"));
bus_w(addr, bus_r(addr) | mask);
} }
LOG(logDEBUG1, ("\tSwitching on power enable for Power V%s\n",
powerNames[pwrIndex]));
bus_w(addr, bus_r(addr) | mask);
} }
return OK;
} }
int getADC(enum ADCINDEX ind, int *value) { int getADC(enum ADCINDEX ind, int *value) {

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 0x260106" #define APIXILINXCTB "0.0.0 0x260113"
#define APIJUNGFRAU "0.0.0 0x250909" #define APIJUNGFRAU "0.0.0 0x250909"
#define APIMYTHEN3 "0.0.0 0x250922" #define APIMYTHEN3 "0.0.0 0x250922"