mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-05 09:30:40 +02:00
2. Dev/add jf pedestal feature (#807)
This commit is contained in:
parent
72bec5d62e
commit
d003a6d8e0
@ -11,6 +11,7 @@ pybind11_add_module(_slsdet
|
|||||||
src/current.cpp
|
src/current.cpp
|
||||||
src/duration.cpp
|
src/duration.cpp
|
||||||
src/DurationWrapper.cpp
|
src/DurationWrapper.cpp
|
||||||
|
src/pedestal.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(_slsdet PUBLIC
|
target_link_libraries(_slsdet PUBLIC
|
||||||
|
12
python/examples/use_pedestalmode.py
Normal file
12
python/examples/use_pedestalmode.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
from slsdet import Detector, pedestalParameters
|
||||||
|
|
||||||
|
p = pedestalParameters()
|
||||||
|
p.frames = 10
|
||||||
|
p.loops= 20
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
d = Detector()
|
||||||
|
d.pedestalmode = p
|
@ -35,6 +35,7 @@ ext_modules = [
|
|||||||
'src/scan.cpp',
|
'src/scan.cpp',
|
||||||
'src/duration.cpp',
|
'src/duration.cpp',
|
||||||
'src/DurationWrapper.cpp',
|
'src/DurationWrapper.cpp',
|
||||||
|
'src/pedestal.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,4 +27,5 @@ IpAddr = _slsdet.IpAddr
|
|||||||
MacAddr = _slsdet.MacAddr
|
MacAddr = _slsdet.MacAddr
|
||||||
scanParameters = _slsdet.scanParameters
|
scanParameters = _slsdet.scanParameters
|
||||||
currentSrcParameters = _slsdet.currentSrcParameters
|
currentSrcParameters = _slsdet.currentSrcParameters
|
||||||
DurationWrapper = _slsdet.DurationWrapper
|
DurationWrapper = _slsdet.DurationWrapper
|
||||||
|
pedestalParameters = _slsdet.pedestalParameters
|
@ -2866,7 +2866,27 @@ class Detector(CppDetectorApi):
|
|||||||
@filtercells.setter
|
@filtercells.setter
|
||||||
def filtercells(self, value):
|
def filtercells(self, value):
|
||||||
ut.set_using_dict(self.setNumberOfFilterCells, value)
|
ut.set_using_dict(self.setNumberOfFilterCells, value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
@element
|
||||||
|
def pedestalmode(self):
|
||||||
|
"""
|
||||||
|
[Jungfrau] Enables or disables pedestal mode. Pass in a pedestalParameters object
|
||||||
|
see python/examples/use_pedestalmode.py
|
||||||
|
|
||||||
|
Note
|
||||||
|
----
|
||||||
|
The number of frames or triggers is overwritten by #pedestal_frames x pedestal_loops x 2. \n
|
||||||
|
In auto timing mode or in trigger mode with #frames > 1, #frames is overwritten and #triggers = 1, else #triggers is overwritten and #frames = 1. \n
|
||||||
|
One cannot set #frames, #triggers or timing mode in pedestal mode (exception thrown).\n
|
||||||
|
Disabling pedestal mode will set back the normal mode values of #frames and #triggers."
|
||||||
|
"""
|
||||||
|
return self.getPedestalMode()
|
||||||
|
|
||||||
|
@pedestalmode.setter
|
||||||
|
def pedestalmode(self, value):
|
||||||
|
ut.set_using_dict(self.setPedestalMode, value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def maxclkphaseshift(self):
|
def maxclkphaseshift(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1270,6 +1270,16 @@ void init_det(py::module &m) {
|
|||||||
(void (Detector::*)(int, sls::Positions)) &
|
(void (Detector::*)(int, sls::Positions)) &
|
||||||
Detector::setNumberOfFilterCells,
|
Detector::setNumberOfFilterCells,
|
||||||
py::arg(), py::arg() = Positions{});
|
py::arg(), py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def(
|
||||||
|
"getPedestalMode",
|
||||||
|
(Result<defs::pedestalParameters>(Detector::*)(sls::Positions) const) &
|
||||||
|
Detector::getPedestalMode,
|
||||||
|
py::arg() = Positions{});
|
||||||
|
CppDetectorApi.def(
|
||||||
|
"setPedestalMode",
|
||||||
|
(void (Detector::*)(const defs::pedestalParameters, sls::Positions)) &
|
||||||
|
Detector::setPedestalMode,
|
||||||
|
py::arg(), py::arg() = Positions{});
|
||||||
CppDetectorApi.def("getROI",
|
CppDetectorApi.def("getROI",
|
||||||
(Result<defs::ROI>(Detector::*)(sls::Positions) const) &
|
(Result<defs::ROI>(Detector::*)(sls::Positions) const) &
|
||||||
Detector::getROI,
|
Detector::getROI,
|
||||||
|
@ -19,6 +19,8 @@ void init_pattern(py::module &);
|
|||||||
void init_scan(py::module &);
|
void init_scan(py::module &);
|
||||||
void init_source(py::module &);
|
void init_source(py::module &);
|
||||||
void init_duration(py::module &);
|
void init_duration(py::module &);
|
||||||
|
void init_pedestal(py::module &);
|
||||||
|
|
||||||
PYBIND11_MODULE(_slsdet, m) {
|
PYBIND11_MODULE(_slsdet, m) {
|
||||||
m.doc() = R"pbdoc(
|
m.doc() = R"pbdoc(
|
||||||
C/C++ API
|
C/C++ API
|
||||||
@ -37,6 +39,7 @@ PYBIND11_MODULE(_slsdet, m) {
|
|||||||
init_scan(m);
|
init_scan(m);
|
||||||
init_source(m);
|
init_source(m);
|
||||||
init_duration(m);
|
init_duration(m);
|
||||||
|
init_pedestal(m);
|
||||||
// init_experimental(m);
|
// init_experimental(m);
|
||||||
|
|
||||||
py::module io = m.def_submodule("io", "Submodule for io");
|
py::module io = m.def_submodule("io", "Submodule for io");
|
||||||
|
23
python/src/pedestal.cpp
Normal file
23
python/src/pedestal.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||||
|
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||||
|
|
||||||
|
#include "py_headers.h"
|
||||||
|
|
||||||
|
#include "sls/ToString.h"
|
||||||
|
#include "sls/sls_detector_defs.h"
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
void init_pedestal(py::module &m) {
|
||||||
|
|
||||||
|
using src = slsDetectorDefs::pedestalParameters;
|
||||||
|
py::class_<src> pedestalParameters(m, "pedestalParameters");
|
||||||
|
|
||||||
|
pedestalParameters.def(py::init());
|
||||||
|
pedestalParameters.def_readwrite("enable", &src::enable);
|
||||||
|
pedestalParameters.def_readwrite("frames", &src::frames);
|
||||||
|
pedestalParameters.def_readwrite("loops", &src::loops);
|
||||||
|
pedestalParameters.def(pybind11::self == pybind11::self);
|
||||||
|
|
||||||
|
pedestalParameters.def("__repr__",
|
||||||
|
[](const src &a) { return sls::ToString(a); });
|
||||||
|
}
|
@ -255,6 +255,17 @@
|
|||||||
#define PLL_CNTRL_ADDR_OFST (16)
|
#define PLL_CNTRL_ADDR_OFST (16)
|
||||||
#define PLL_CNTRL_ADDR_MSK (0x0000003F << PLL_CNTRL_ADDR_OFST)
|
#define PLL_CNTRL_ADDR_MSK (0x0000003F << PLL_CNTRL_ADDR_OFST)
|
||||||
|
|
||||||
|
|
||||||
|
/* Pedestal Mode Regiser */
|
||||||
|
#define PEDESTAL_MODE_REG (0x57 << MEM_MAP_SHIFT)
|
||||||
|
|
||||||
|
#define PEDESTAL_MODE_ITRTNS_OFST (0)
|
||||||
|
#define PEDESTAL_MODE_ITRTNS_MSK (0x0000FFFF << PEDESTAL_MODE_ITRTNS_OFST)
|
||||||
|
#define PEDESTAL_MODE_LNGTH_OFST (16)
|
||||||
|
#define PEDESTAL_MODE_LNGTH_MSK (0x000000FF << PEDESTAL_MODE_LNGTH_OFST)
|
||||||
|
#define PEDESTAL_MODE_ENBLE_OFST (31)
|
||||||
|
#define PEDESTAL_MODE_ENBLE_MSK (0x00000001 << PEDESTAL_MODE_ENBLE_OFST)
|
||||||
|
|
||||||
/* Config Register for chip 1.1 */
|
/* Config Register for chip 1.1 */
|
||||||
#define CONFIG_V11_REG (0x58 << MEM_MAP_SHIFT)
|
#define CONFIG_V11_REG (0x58 << MEM_MAP_SHIFT)
|
||||||
|
|
||||||
|
Binary file not shown.
@ -55,6 +55,9 @@ int32_t clkPhase[NUM_CLOCKS] = {};
|
|||||||
int detPos[4] = {};
|
int detPos[4] = {};
|
||||||
int chipConfigured = 0;
|
int chipConfigured = 0;
|
||||||
|
|
||||||
|
uint64_t normal_mode_frames = -1;
|
||||||
|
uint64_t normal_mode_triggers = -1;
|
||||||
|
|
||||||
int isInitCheckDone() { return initCheckDone; }
|
int isInitCheckDone() { return initCheckDone; }
|
||||||
|
|
||||||
int getInitResult(char **mess) {
|
int getInitResult(char **mess) {
|
||||||
@ -555,6 +558,13 @@ void setupDetector() {
|
|||||||
setFlipRows(DEFAULT_FLIP_ROWS);
|
setFlipRows(DEFAULT_FLIP_ROWS);
|
||||||
setReadNRows(MAX_ROWS_PER_READOUT);
|
setReadNRows(MAX_ROWS_PER_READOUT);
|
||||||
}
|
}
|
||||||
|
#ifdef VIRTUAL
|
||||||
|
// setting pedestalmode depends on previous values
|
||||||
|
bus_w(PEDESTAL_MODE_REG,
|
||||||
|
bus_r(PEDESTAL_MODE_REG) & ~PEDESTAL_MODE_ENBLE_MSK);
|
||||||
|
#endif
|
||||||
|
setPedestalMode(DEFAULT_PEDESTAL_MODE, DEFAULT_PEDESTAL_FRAMES,
|
||||||
|
DEFAULT_PEDESTAL_LOOPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int resetToDefaultDacs(int hardReset) {
|
int resetToDefaultDacs(int hardReset) {
|
||||||
@ -975,6 +985,9 @@ int getNextFrameNumber(uint64_t *retval) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setNumFrames(int64_t val) {
|
void setNumFrames(int64_t val) {
|
||||||
|
if (getPedestalMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (val > 0) {
|
if (val > 0) {
|
||||||
LOG(logINFO, ("Setting number of frames %lld\n", (long long int)val));
|
LOG(logINFO, ("Setting number of frames %lld\n", (long long int)val));
|
||||||
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||||
@ -986,6 +999,9 @@ int64_t getNumFrames() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setNumTriggers(int64_t val) {
|
void setNumTriggers(int64_t val) {
|
||||||
|
if (getPedestalMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (val > 0) {
|
if (val > 0) {
|
||||||
LOG(logINFO, ("Setting number of triggers %lld\n", (long long int)val));
|
LOG(logINFO, ("Setting number of triggers %lld\n", (long long int)val));
|
||||||
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||||
@ -1439,6 +1455,9 @@ void setSynchronization(int enable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setTiming(enum timingMode arg) {
|
void setTiming(enum timingMode arg) {
|
||||||
|
if (getPedestalMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case AUTO_TIMING:
|
case AUTO_TIMING:
|
||||||
LOG(logINFO, ("Set Timing: Auto\n"));
|
LOG(logINFO, ("Set Timing: Auto\n"));
|
||||||
@ -2513,6 +2532,81 @@ uint64_t getSelectCurrentSource() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getPedestalMode() {
|
||||||
|
return ((bus_r(PEDESTAL_MODE_REG) & PEDESTAL_MODE_ENBLE_MSK) >>
|
||||||
|
PEDESTAL_MODE_ENBLE_OFST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getPedestalParameters(uint8_t *frames, uint16_t *loops) {
|
||||||
|
uint32_t addr = PEDESTAL_MODE_REG;
|
||||||
|
*frames =
|
||||||
|
((bus_r(addr) & PEDESTAL_MODE_LNGTH_MSK) >> PEDESTAL_MODE_LNGTH_OFST);
|
||||||
|
*loops = ((bus_r(PEDESTAL_MODE_REG) & PEDESTAL_MODE_ITRTNS_MSK) >>
|
||||||
|
PEDESTAL_MODE_ITRTNS_OFST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPedestalMode(int enable, uint8_t frames, uint16_t loops) {
|
||||||
|
int prevPedestalEnable = getPedestalMode();
|
||||||
|
uint32_t addr = PEDESTAL_MODE_REG;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
LOG(logINFOBLUE, ("Enabling pedestal mode [frames: %hhu, loops: %hu]\n",
|
||||||
|
frames, loops));
|
||||||
|
// enable
|
||||||
|
bus_w(addr, bus_r(addr) | PEDESTAL_MODE_ENBLE_MSK);
|
||||||
|
// frames
|
||||||
|
bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_LNGTH_MSK);
|
||||||
|
bus_w(addr, bus_r(addr) | ((frames << PEDESTAL_MODE_LNGTH_OFST) &
|
||||||
|
PEDESTAL_MODE_LNGTH_MSK));
|
||||||
|
// loops
|
||||||
|
bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_ITRTNS_MSK);
|
||||||
|
bus_w(addr, bus_r(addr) | ((loops << PEDESTAL_MODE_ITRTNS_OFST) &
|
||||||
|
PEDESTAL_MODE_ITRTNS_MSK));
|
||||||
|
|
||||||
|
// if it was switched off before, remember the #frames and #triggers
|
||||||
|
if (prevPedestalEnable == 0) {
|
||||||
|
normal_mode_frames = getNumFrames();
|
||||||
|
normal_mode_triggers = getNumTriggers();
|
||||||
|
LOG(logINFO, ("\tRemembering Normal mode #frames and "
|
||||||
|
"#triggers[%lld, %lld]\n",
|
||||||
|
normal_mode_frames, normal_mode_triggers));
|
||||||
|
}
|
||||||
|
|
||||||
|
// overwrite #frames and #triggers to new values
|
||||||
|
int64_t expFrames = -1;
|
||||||
|
int64_t expTriggers = -1;
|
||||||
|
enum timingMode timing = getTiming();
|
||||||
|
if (timing == AUTO_TIMING ||
|
||||||
|
(timing == TRIGGER_EXPOSURE && normal_mode_frames > 1)) {
|
||||||
|
expFrames = frames * loops * 2;
|
||||||
|
expTriggers = 1;
|
||||||
|
} else {
|
||||||
|
expFrames = 1;
|
||||||
|
expTriggers = frames * loops * 2;
|
||||||
|
}
|
||||||
|
LOG(logINFO, ("\tOverwriting [#frames: %lld, #triggers: %lld]\n",
|
||||||
|
expFrames, expTriggers));
|
||||||
|
set64BitReg(expFrames, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||||
|
set64BitReg(expTriggers, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LOG(logINFOBLUE, ("Disabling pedestal mode\n"));
|
||||||
|
bus_w(addr, bus_r(addr) & ~PEDESTAL_MODE_ENBLE_MSK);
|
||||||
|
|
||||||
|
// if it was switched on before, reset the normal mode #frames and
|
||||||
|
// #triggers
|
||||||
|
if (prevPedestalEnable == 1) {
|
||||||
|
LOG(logINFO,
|
||||||
|
("\tResetting to Normal mode [#frames:%lld, #triggers:%lld\n",
|
||||||
|
normal_mode_frames, normal_mode_triggers));
|
||||||
|
set64BitReg(normal_mode_frames, SET_FRAMES_LSB_REG,
|
||||||
|
SET_FRAMES_MSB_REG);
|
||||||
|
set64BitReg(normal_mode_triggers, SET_CYCLES_LSB_REG,
|
||||||
|
SET_CYCLES_MSB_REG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int getTenGigaFlowControl() {
|
int getTenGigaFlowControl() {
|
||||||
return ((bus_r(CONFIG_REG) & CONFIG_ETHRNT_FLW_CNTRL_MSK) >>
|
return ((bus_r(CONFIG_REG) & CONFIG_ETHRNT_FLW_CNTRL_MSK) >>
|
||||||
CONFIG_ETHRNT_FLW_CNTRL_OFST);
|
CONFIG_ETHRNT_FLW_CNTRL_OFST);
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include "sls/sls_detector_defs.h"
|
#include "sls/sls_detector_defs.h"
|
||||||
|
|
||||||
#define MIN_REQRD_VRSN_T_RD_API 0x171220
|
#define MIN_REQRD_VRSN_T_RD_API 0x171220
|
||||||
#define REQRD_FRMWRE_VRSN_BOARD2 0x230516 // 1.0 pcb (version = 010)
|
#define REQRD_FRMWRE_VRSN_BOARD2 0x230920 // 1.0 pcb (version = 010)
|
||||||
#define REQRD_FRMWRE_VRSN 0x230515 // 2.0 pcb (version = 011)
|
#define REQRD_FRMWRE_VRSN 0x230921 // 2.0 pcb (version = 011)
|
||||||
|
|
||||||
#define NUM_HARDWARE_VERSIONS (2)
|
#define NUM_HARDWARE_VERSIONS (2)
|
||||||
#define HARDWARE_VERSION_NUMBERS \
|
#define HARDWARE_VERSION_NUMBERS \
|
||||||
@ -52,6 +52,9 @@
|
|||||||
#define DEFAULT_FLIP_ROWS (0)
|
#define DEFAULT_FLIP_ROWS (0)
|
||||||
#define DEFAULT_FILTER_RESISTOR (1) // higher resistor
|
#define DEFAULT_FILTER_RESISTOR (1) // higher resistor
|
||||||
#define DEFAULT_FILTER_CELL (0)
|
#define DEFAULT_FILTER_CELL (0)
|
||||||
|
#define DEFAULT_PEDESTAL_MODE (0)
|
||||||
|
#define DEFAULT_PEDESTAL_FRAMES (1)
|
||||||
|
#define DEFAULT_PEDESTAL_LOOPS (1)
|
||||||
|
|
||||||
#define HIGHVOLTAGE_MIN (60)
|
#define HIGHVOLTAGE_MIN (60)
|
||||||
#define HIGHVOLTAGE_MAX (200)
|
#define HIGHVOLTAGE_MAX (200)
|
||||||
|
@ -556,6 +556,9 @@ int getCurrentSource();
|
|||||||
int getFixCurrentSource();
|
int getFixCurrentSource();
|
||||||
int getNormalCurrentSource();
|
int getNormalCurrentSource();
|
||||||
uint64_t getSelectCurrentSource();
|
uint64_t getSelectCurrentSource();
|
||||||
|
int getPedestalMode();
|
||||||
|
void getPedestalParameters(uint8_t *frames, uint16_t *loops);
|
||||||
|
void setPedestalMode(int enable, uint8_t frames, uint16_t loops);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// eiger specific - iodelay, pulse, rate, temp, activate, delay nw parameter
|
// eiger specific - iodelay, pulse, rate, temp, activate, delay nw parameter
|
||||||
|
@ -327,3 +327,5 @@ int getRow();
|
|||||||
int setRow(int);
|
int setRow(int);
|
||||||
int getColumn();
|
int getColumn();
|
||||||
int setColumn(int);
|
int setColumn(int);
|
||||||
|
int get_pedestal_mode(int);
|
||||||
|
int set_pedestal_mode(int);
|
||||||
|
@ -486,6 +486,8 @@ void function_table() {
|
|||||||
flist[F_SET_ROW] = &set_row;
|
flist[F_SET_ROW] = &set_row;
|
||||||
flist[F_GET_COLUMN] = &get_column;
|
flist[F_GET_COLUMN] = &get_column;
|
||||||
flist[F_SET_COLUMN] = &set_column;
|
flist[F_SET_COLUMN] = &set_column;
|
||||||
|
flist[F_GET_PEDESTAL_MODE] = &get_pedestal_mode;
|
||||||
|
flist[F_SET_PEDESTAL_MODE] = &set_pedestal_mode;
|
||||||
|
|
||||||
// check
|
// check
|
||||||
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
|
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
|
||||||
@ -724,7 +726,18 @@ int set_timing_mode(int file_des) {
|
|||||||
case GATED:
|
case GATED:
|
||||||
case TRIGGER_GATED:
|
case TRIGGER_GATED:
|
||||||
#endif
|
#endif
|
||||||
setTiming(arg);
|
#if JUNGFRAUD
|
||||||
|
// cannot set in pedestal mode
|
||||||
|
if (getPedestalMode()) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(mess,
|
||||||
|
"Cannot set timing mode in pedestal mode. Switch off "
|
||||||
|
"pedestal mode to change timing mode.\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (ret == OK)
|
||||||
|
setTiming(arg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
modeNotImplemented("Timing mode", (int)arg);
|
modeNotImplemented("Timing mode", (int)arg);
|
||||||
@ -1935,57 +1948,59 @@ int acquire(int blocking, int file_des) {
|
|||||||
#ifdef EIGERD
|
#ifdef EIGERD
|
||||||
// check for hardware mac and hardware ip
|
// check for hardware mac and hardware ip
|
||||||
if (udpDetails[0].srcmac != getDetectorMAC()) {
|
if (udpDetails[0].srcmac != getDetectorMAC()) {
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
uint64_t sourcemac = getDetectorMAC();
|
uint64_t sourcemac = getDetectorMAC();
|
||||||
char src_mac[MAC_ADDRESS_SIZE];
|
char src_mac[MAC_ADDRESS_SIZE];
|
||||||
getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac);
|
getMacAddressinString(src_mac, MAC_ADDRESS_SIZE, sourcemac);
|
||||||
sprintf(mess,
|
sprintf(
|
||||||
|
mess,
|
||||||
"Invalid udp source mac address for this detector. Must be "
|
"Invalid udp source mac address for this detector. Must be "
|
||||||
"same as hardware detector mac address %s\n",
|
"same as hardware detector mac address %s\n",
|
||||||
src_mac);
|
src_mac);
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
} else if (!enableTenGigabitEthernet(GET_FLAG) &&
|
} else if (!enableTenGigabitEthernet(GET_FLAG) &&
|
||||||
(udpDetails[0].srcip != getDetectorIP())) {
|
(udpDetails[0].srcip != getDetectorIP())) {
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
uint32_t sourceip = getDetectorIP();
|
uint32_t sourceip = getDetectorIP();
|
||||||
char src_ip[INET_ADDRSTRLEN];
|
char src_ip[INET_ADDRSTRLEN];
|
||||||
getIpAddressinString(src_ip, sourceip);
|
getIpAddressinString(src_ip, sourceip);
|
||||||
sprintf(mess,
|
sprintf(
|
||||||
|
mess,
|
||||||
"Invalid udp source ip address for this detector. Must be "
|
"Invalid udp source ip address for this detector. Must be "
|
||||||
"same as hardware detector ip address %s in 1G readout "
|
"same as hardware detector ip address %s in 1G readout "
|
||||||
"mode \n",
|
"mode \n",
|
||||||
src_ip);
|
src_ip);
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (configured == FAIL) {
|
if (configured == FAIL) {
|
||||||
ret = FAIL;
|
|
||||||
strcpy(mess, "Could not start acquisition because ");
|
|
||||||
strcat(mess, configureMessage);
|
|
||||||
LOG(logERROR, (mess));
|
|
||||||
} else if (sharedMemory_getScanStatus() == RUNNING) {
|
|
||||||
ret = FAIL;
|
|
||||||
strcpy(mess, "Could not start acquisition because a scan is "
|
|
||||||
"already running!\n");
|
|
||||||
LOG(logERROR, (mess));
|
|
||||||
} else {
|
|
||||||
memset(scanErrMessage, 0, MAX_STR_LENGTH);
|
|
||||||
sharedMemory_setScanStop(0);
|
|
||||||
sharedMemory_setScanStatus(IDLE); // if it was error
|
|
||||||
if (pthread_create(&pthread_tid, NULL, &start_state_machine,
|
|
||||||
&blocking)) {
|
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
strcpy(mess, "Could not start acquisition thread!\n");
|
strcpy(mess, "Could not start acquisition because ");
|
||||||
|
strcat(mess, configureMessage);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
} else if (sharedMemory_getScanStatus() == RUNNING) {
|
||||||
|
ret = FAIL;
|
||||||
|
strcpy(mess, "Could not start acquisition because a scan is "
|
||||||
|
"already running!\n");
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
} else {
|
} else {
|
||||||
// wait for blocking always (scan or not)
|
memset(scanErrMessage, 0, MAX_STR_LENGTH);
|
||||||
// non blocking-no scan also wait (for error message)
|
sharedMemory_setScanStop(0);
|
||||||
// non blcoking-scan dont wait (there is scanErrorMessage)
|
sharedMemory_setScanStatus(IDLE); // if it was error
|
||||||
if (blocking || !scan) {
|
if (pthread_create(&pthread_tid, NULL, &start_state_machine,
|
||||||
pthread_join(pthread_tid, NULL);
|
&blocking)) {
|
||||||
|
ret = FAIL;
|
||||||
|
strcpy(mess, "Could not start acquisition thread!\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
} else {
|
||||||
|
// wait for blocking always (scan or not)
|
||||||
|
// non blocking-no scan also wait (for error message)
|
||||||
|
// non blcoking-scan dont wait (there is scanErrorMessage)
|
||||||
|
if (blocking || !scan) {
|
||||||
|
pthread_join(pthread_tid, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Server_SendResult(file_des, INT32, NULL, 0);
|
return Server_SendResult(file_des, INT32, NULL, 0);
|
||||||
}
|
}
|
||||||
@ -2211,6 +2226,14 @@ int set_num_frames(int file_des) {
|
|||||||
(long long unsigned int)arg, MAX_FRAMES_IN_BURST_MODE);
|
(long long unsigned int)arg, MAX_FRAMES_IN_BURST_MODE);
|
||||||
LOG(logERROR, (mess));
|
LOG(logERROR, (mess));
|
||||||
}
|
}
|
||||||
|
#elif JUNGFRAUD
|
||||||
|
// cannot set in pedestal mode
|
||||||
|
if (getPedestalMode()) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(mess, "Cannot set frames in pedestal mode. It is "
|
||||||
|
"overwritten anyway.\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ret == OK) {
|
if (ret == OK) {
|
||||||
setNumFrames(arg);
|
setNumFrames(arg);
|
||||||
@ -2247,10 +2270,22 @@ int set_num_triggers(int file_des) {
|
|||||||
|
|
||||||
// only set
|
// only set
|
||||||
if (Server_VerifyLock() == OK) {
|
if (Server_VerifyLock() == OK) {
|
||||||
setNumTriggers(arg);
|
#if JUNGFRAUD
|
||||||
int64_t retval = getNumTriggers();
|
// cannot set in pedestal mode
|
||||||
LOG(logDEBUG1, ("retval num triggers %lld\n", (long long int)retval));
|
if (getPedestalMode()) {
|
||||||
validate64(&ret, mess, arg, retval, "set number of triggers", DEC);
|
ret = FAIL;
|
||||||
|
sprintf(mess, "Cannot set triggers in pedestal mode. It is "
|
||||||
|
"overwritten anyway.\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (ret == OK) {
|
||||||
|
setNumTriggers(arg);
|
||||||
|
int64_t retval = getNumTriggers();
|
||||||
|
LOG(logDEBUG1,
|
||||||
|
("retval num triggers %lld\n", (long long int)retval));
|
||||||
|
validate64(&ret, mess, arg, retval, "set number of triggers", DEC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Server_SendResult(file_des, INT64, NULL, 0);
|
return Server_SendResult(file_des, INT64, NULL, 0);
|
||||||
}
|
}
|
||||||
@ -7791,62 +7826,20 @@ int set_scan(int file_des) {
|
|||||||
int stop = args[3];
|
int stop = args[3];
|
||||||
int step = args[4];
|
int step = args[4];
|
||||||
|
|
||||||
// disable scan
|
#ifdef JUNGFRAUD
|
||||||
if (enable == 0) {
|
if (getPedestalMode()) {
|
||||||
LOG(logINFOBLUE, ("Disabling scan"));
|
ret = FAIL;
|
||||||
scan = 0;
|
strcpy(mess, "Cannot set scan when in pedestal mode.\n");
|
||||||
numScanSteps = 0;
|
LOG(logERROR, (mess));
|
||||||
// setting number of frames to 1
|
|
||||||
int64_t arg = 1;
|
|
||||||
setNumFrames(arg);
|
|
||||||
retval = getNumFrames();
|
|
||||||
LOG(logDEBUG1, ("retval num frames %lld\n", (long long int)retval));
|
|
||||||
validate64(&ret, mess, arg, retval, "set number of frames", DEC);
|
|
||||||
}
|
}
|
||||||
// enable scan
|
#endif
|
||||||
else {
|
if (ret == OK) {
|
||||||
if ((start < stop && step <= 0) || (stop < start && step >= 0)) {
|
// disable scan
|
||||||
ret = FAIL;
|
if (enable == 0) {
|
||||||
sprintf(mess, "Invalid scan parameters\n");
|
LOG(logINFOBLUE, ("Disabling scan"));
|
||||||
LOG(logERROR, (mess));
|
scan = 0;
|
||||||
} else {
|
numScanSteps = 0;
|
||||||
// trimbit scan
|
// setting number of frames to 1
|
||||||
if (index == TRIMBIT_SCAN) {
|
|
||||||
LOG(logINFOBLUE, ("Trimbit scan enabled\n"));
|
|
||||||
scanTrimbits = 1;
|
|
||||||
scanGlobalIndex = index;
|
|
||||||
scanSettleTime_ns = dacTime;
|
|
||||||
}
|
|
||||||
// dac scan
|
|
||||||
else {
|
|
||||||
// validate index
|
|
||||||
getDACIndex(index);
|
|
||||||
if (ret == OK) {
|
|
||||||
LOG(logINFOBLUE, ("Dac [%d] scan enabled\n", index));
|
|
||||||
scanTrimbits = 0;
|
|
||||||
scanGlobalIndex = index;
|
|
||||||
scanSettleTime_ns = dacTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// valid scan
|
|
||||||
if (ret == OK) {
|
|
||||||
scan = 1;
|
|
||||||
numScanSteps = (abs(stop - start) / abs(step)) + 1;
|
|
||||||
if (scanSteps != NULL) {
|
|
||||||
free(scanSteps);
|
|
||||||
}
|
|
||||||
scanSteps = malloc(numScanSteps * sizeof(int));
|
|
||||||
for (int i = 0; i != numScanSteps; ++i) {
|
|
||||||
scanSteps[i] = start + i * step;
|
|
||||||
LOG(logDEBUG1, ("scansteps[%d]:%d\n", i, scanSteps[i]));
|
|
||||||
}
|
|
||||||
LOG(logINFOBLUE, ("Enabling scan for %s, start[%d], stop[%d], "
|
|
||||||
"step[%d], nsteps[%d]\n",
|
|
||||||
scanTrimbits == 1 ? "trimbits" : "dac", start,
|
|
||||||
stop, step, numScanSteps));
|
|
||||||
|
|
||||||
// setting number of frames to scansteps
|
|
||||||
int64_t arg = 1;
|
int64_t arg = 1;
|
||||||
setNumFrames(arg);
|
setNumFrames(arg);
|
||||||
retval = getNumFrames();
|
retval = getNumFrames();
|
||||||
@ -7854,7 +7847,63 @@ int set_scan(int file_des) {
|
|||||||
("retval num frames %lld\n", (long long int)retval));
|
("retval num frames %lld\n", (long long int)retval));
|
||||||
validate64(&ret, mess, arg, retval, "set number of frames",
|
validate64(&ret, mess, arg, retval, "set number of frames",
|
||||||
DEC);
|
DEC);
|
||||||
retval = numScanSteps;
|
}
|
||||||
|
// enable scan
|
||||||
|
else {
|
||||||
|
if ((start < stop && step <= 0) ||
|
||||||
|
(stop < start && step >= 0)) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(mess, "Invalid scan parameters\n");
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
} else {
|
||||||
|
// trimbit scan
|
||||||
|
if (index == TRIMBIT_SCAN) {
|
||||||
|
LOG(logINFOBLUE, ("Trimbit scan enabled\n"));
|
||||||
|
scanTrimbits = 1;
|
||||||
|
scanGlobalIndex = index;
|
||||||
|
scanSettleTime_ns = dacTime;
|
||||||
|
}
|
||||||
|
// dac scan
|
||||||
|
else {
|
||||||
|
// validate index
|
||||||
|
getDACIndex(index);
|
||||||
|
if (ret == OK) {
|
||||||
|
LOG(logINFOBLUE,
|
||||||
|
("Dac [%d] scan enabled\n", index));
|
||||||
|
scanTrimbits = 0;
|
||||||
|
scanGlobalIndex = index;
|
||||||
|
scanSettleTime_ns = dacTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// valid scan
|
||||||
|
if (ret == OK) {
|
||||||
|
scan = 1;
|
||||||
|
numScanSteps = (abs(stop - start) / abs(step)) + 1;
|
||||||
|
if (scanSteps != NULL) {
|
||||||
|
free(scanSteps);
|
||||||
|
}
|
||||||
|
scanSteps = malloc(numScanSteps * sizeof(int));
|
||||||
|
for (int i = 0; i != numScanSteps; ++i) {
|
||||||
|
scanSteps[i] = start + i * step;
|
||||||
|
LOG(logDEBUG1, ("scansteps[%d]:%d\n", i, scanSteps[i]));
|
||||||
|
}
|
||||||
|
LOG(logINFOBLUE,
|
||||||
|
("Enabling scan for %s, start[%d], stop[%d], "
|
||||||
|
"step[%d], nsteps[%d]\n",
|
||||||
|
scanTrimbits == 1 ? "trimbits" : "dac", start, stop,
|
||||||
|
step, numScanSteps));
|
||||||
|
|
||||||
|
// setting number of frames to scansteps
|
||||||
|
int64_t arg = 1;
|
||||||
|
setNumFrames(arg);
|
||||||
|
retval = getNumFrames();
|
||||||
|
LOG(logDEBUG1,
|
||||||
|
("retval num frames %lld\n", (long long int)retval));
|
||||||
|
validate64(&ret, mess, arg, retval, "set number of frames",
|
||||||
|
DEC);
|
||||||
|
retval = numScanSteps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10740,4 +10789,108 @@ int setColumn(int value) {
|
|||||||
memcpy(pos, getDetectorPosition(), sizeof(pos));
|
memcpy(pos, getDetectorPosition(), sizeof(pos));
|
||||||
pos[X] = value;
|
pos[X] = value;
|
||||||
return setDetectorPosition(pos);
|
return setDetectorPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_pedestal_mode(int file_des) {
|
||||||
|
ret = OK;
|
||||||
|
memset(mess, 0, sizeof(mess));
|
||||||
|
int retvalEnable = -1;
|
||||||
|
uint8_t retvalFrames = -1;
|
||||||
|
uint16_t retvalLoops = -1;
|
||||||
|
LOG(logDEBUG1, ("Getting pedestal mode\n"));
|
||||||
|
|
||||||
|
#if !defined(JUNGFRAUD)
|
||||||
|
functionNotImplemented();
|
||||||
|
#else
|
||||||
|
retvalEnable = getPedestalMode();
|
||||||
|
getPedestalParameters(&retvalFrames, &retvalLoops);
|
||||||
|
LOG(logDEBUG1, ("pedestal mode retval: [enable:%d frames:%hhu, "
|
||||||
|
"loops:%hu]\n",
|
||||||
|
retvalEnable, retvalFrames, retvalLoops));
|
||||||
|
#endif
|
||||||
|
Server_SendResult(file_des, INT32, NULL, 0);
|
||||||
|
if (ret != FAIL) {
|
||||||
|
sendData(file_des, &retvalEnable, sizeof(retvalEnable), INT32);
|
||||||
|
sendData(file_des, &retvalFrames, sizeof(retvalFrames), OTHER);
|
||||||
|
sendData(file_des, &retvalLoops, sizeof(retvalLoops), INT16);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_pedestal_mode(int file_des) {
|
||||||
|
ret = OK;
|
||||||
|
memset(mess, 0, sizeof(mess));
|
||||||
|
int enable = -1;
|
||||||
|
uint8_t frames = -1;
|
||||||
|
uint16_t loops = -1;
|
||||||
|
|
||||||
|
if (receiveData(file_des, &enable, sizeof(enable), INT32) < 0)
|
||||||
|
return printSocketReadError();
|
||||||
|
if (receiveData(file_des, &frames, sizeof(frames), OTHER) < 0)
|
||||||
|
return printSocketReadError();
|
||||||
|
if (receiveData(file_des, &loops, sizeof(loops), INT16) < 0)
|
||||||
|
return printSocketReadError();
|
||||||
|
LOG(logDEBUG1, ("Setting pedestal mode: enable:%d frames:%hhu, "
|
||||||
|
"loops:%hu]\n",
|
||||||
|
enable, frames, loops));
|
||||||
|
|
||||||
|
#if !defined(JUNGFRAUD)
|
||||||
|
functionNotImplemented();
|
||||||
|
#else
|
||||||
|
// only set
|
||||||
|
if (Server_VerifyLock() == OK) {
|
||||||
|
if (check_detector_idle("set pedestal mode") == OK) {
|
||||||
|
if (enable != 0 && enable != 1) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(
|
||||||
|
mess,
|
||||||
|
"Could not set pedestal mode. Invalid enable argument %d. "
|
||||||
|
"Options: [0, 1]\n",
|
||||||
|
enable);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
} else if (enable == 1 && (frames == 0 || loops == 0)) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(mess,
|
||||||
|
"Could not set pedestal mode. Frames and loops cannot "
|
||||||
|
"be 0. [%hhu, %hu].\n",
|
||||||
|
frames, loops);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
} else {
|
||||||
|
setPedestalMode(enable, frames, loops);
|
||||||
|
int retvalEnable = getPedestalMode();
|
||||||
|
LOG(logDEBUG1, ("pedestal mode retval: %d\n", retvalEnable));
|
||||||
|
if (enable != retvalEnable) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(
|
||||||
|
mess,
|
||||||
|
"Could not set pedestal mode. Tried to %s, but is %s\n",
|
||||||
|
(enable ? "enable" : "disable"),
|
||||||
|
(retvalEnable ? "enabled" : "disabled"));
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
}
|
||||||
|
if (enable) {
|
||||||
|
uint8_t retvalFrames = -1;
|
||||||
|
uint16_t retvalLoops = -1;
|
||||||
|
getPedestalParameters(&retvalFrames, &retvalLoops);
|
||||||
|
LOG(logDEBUG1,
|
||||||
|
("pedestal mode retval: [enable:%d frames:%hhu, "
|
||||||
|
"loops:%hu]\n",
|
||||||
|
retvalEnable, retvalFrames, retvalLoops));
|
||||||
|
if (frames != retvalFrames || loops != retvalLoops) {
|
||||||
|
ret = FAIL;
|
||||||
|
sprintf(
|
||||||
|
mess,
|
||||||
|
"Could not set pedestal mode. Tried to set "
|
||||||
|
"[enable: %d, frames: %hhu, loops: %hu], but got "
|
||||||
|
"[enable: %d, frames: %hhu, loops: %hu].\n",
|
||||||
|
enable, frames, loops, retvalEnable, retvalFrames,
|
||||||
|
retvalLoops);
|
||||||
|
LOG(logERROR, (mess));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return Server_SendResult(file_des, INT32, NULL, 0);
|
||||||
|
}
|
||||||
|
@ -1359,6 +1359,20 @@ class Detector {
|
|||||||
*/
|
*/
|
||||||
void setNumberOfFilterCells(int cell, Positions pos = {});
|
void setNumberOfFilterCells(int cell, Positions pos = {});
|
||||||
|
|
||||||
|
/** [Jungfrau] */
|
||||||
|
Result<defs::pedestalParameters> getPedestalMode(Positions pos = {}) const;
|
||||||
|
|
||||||
|
/** [Jungfrau] In pedestal mode, the number of frames or triggers is
|
||||||
|
* overwritten by \n(#pedestal_frames x #pedestal_loops x 2). \nIn
|
||||||
|
* auto timing mode or in trigger mode with #frames > 1, #frames is
|
||||||
|
* overwritten and #triggers = 1, \nelse #triggers is overwritten and
|
||||||
|
* #frames = 1. One cannot set #frames, #triggers or timing mode in pedestal
|
||||||
|
* mode (it will throw an exception). Disabling pedestal mode will set back
|
||||||
|
* the original values of #frames and #triggers
|
||||||
|
*/
|
||||||
|
void setPedestalMode(const defs::pedestalParameters par,
|
||||||
|
Positions pos = {});
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/** @name Gotthard Specific */
|
/** @name Gotthard Specific */
|
||||||
|
@ -2105,6 +2105,55 @@ std::string CmdProxy::TemperatureEvent(int action) {
|
|||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CmdProxy::PedestalMode(int action) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << cmd << ' ';
|
||||||
|
if (action == defs::HELP_ACTION) {
|
||||||
|
os << " [frames<uint8_t>] [loops<uint16_t>]\n\t\t[Jungfrau] "
|
||||||
|
"Enable pedestal mode. \n\t\tThe number of frames or triggers is "
|
||||||
|
"overwritten by: \n\t\t(#pedestal_frames x #pedestal_loops x 2). "
|
||||||
|
"\n\t\tIn auto timing mode or in trigger mode with #frames > 1, "
|
||||||
|
"\n\t\t#frames is overwritten and #triggers = 1, \n\t\telse "
|
||||||
|
"#triggers is overwritten and #frames = 1. \n\t\tOne cannot set "
|
||||||
|
"#frames, #triggers or timing mode in pedestal mode (exception "
|
||||||
|
"thrown).\n\n";
|
||||||
|
os << cmd
|
||||||
|
<< " [0]\n\t\t[Jungfrau] Disable pedestal "
|
||||||
|
"mode.\n\t\tDisabling pedestal mode will set back the normal "
|
||||||
|
"mode values of #frames and #triggers."
|
||||||
|
<< '\n';
|
||||||
|
} else if (action == defs::GET_ACTION) {
|
||||||
|
if (args.size() != 0) {
|
||||||
|
WrongNumberOfParameters(0);
|
||||||
|
}
|
||||||
|
auto t = det->getPedestalMode(std::vector<int>{det_id});
|
||||||
|
os << OutString(t) << '\n';
|
||||||
|
} else if (action == defs::PUT_ACTION) {
|
||||||
|
// disable
|
||||||
|
if (args.size() == 1) {
|
||||||
|
if (args[0] != "0") {
|
||||||
|
throw RuntimeError(
|
||||||
|
"Unknown argument " + args[0] +
|
||||||
|
". Did you mean '0' to disable pedestal mode?");
|
||||||
|
}
|
||||||
|
det->setPedestalMode(defs::pedestalParameters());
|
||||||
|
}
|
||||||
|
// enable
|
||||||
|
else if (args.size() == 2) {
|
||||||
|
uint8_t frames = StringTo<uint8_t>(args[0]);
|
||||||
|
uint16_t loops = StringTo<uint16_t>(args[1]);
|
||||||
|
det->setPedestalMode(defs::pedestalParameters(frames, loops));
|
||||||
|
} else {
|
||||||
|
throw RuntimeError(
|
||||||
|
"Invalid number of parareters for this command.");
|
||||||
|
}
|
||||||
|
os << ToString(args) << '\n';
|
||||||
|
} else {
|
||||||
|
throw RuntimeError("Unknown action");
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
/* Gotthard Specific */
|
/* Gotthard Specific */
|
||||||
|
|
||||||
std::string CmdProxy::ROI(int action) {
|
std::string CmdProxy::ROI(int action) {
|
||||||
|
@ -1187,6 +1187,7 @@ class CmdProxy {
|
|||||||
{"storagecell_delay", &CmdProxy::storagecell_delay},
|
{"storagecell_delay", &CmdProxy::storagecell_delay},
|
||||||
{"gainmode", &CmdProxy::gainmode},
|
{"gainmode", &CmdProxy::gainmode},
|
||||||
{"filtercells", &CmdProxy::filtercells},
|
{"filtercells", &CmdProxy::filtercells},
|
||||||
|
{"pedestalmode", &CmdProxy::PedestalMode},
|
||||||
|
|
||||||
/* Gotthard Specific */
|
/* Gotthard Specific */
|
||||||
{"roi", &CmdProxy::ROI},
|
{"roi", &CmdProxy::ROI},
|
||||||
@ -1399,6 +1400,7 @@ class CmdProxy {
|
|||||||
std::string DataStream(int action);
|
std::string DataStream(int action);
|
||||||
/* Jungfrau Specific */
|
/* Jungfrau Specific */
|
||||||
std::string TemperatureEvent(int action);
|
std::string TemperatureEvent(int action);
|
||||||
|
std::string PedestalMode(int action);
|
||||||
/* Gotthard Specific */
|
/* Gotthard Specific */
|
||||||
std::string ROI(int action);
|
std::string ROI(int action);
|
||||||
/* Gotthard2 Specific */
|
/* Gotthard2 Specific */
|
||||||
|
@ -1760,6 +1760,16 @@ void Detector::setNumberOfFilterCells(int cell, Positions pos) {
|
|||||||
pimpl->Parallel(&Module::setNumberOfFilterCells, pos, cell);
|
pimpl->Parallel(&Module::setNumberOfFilterCells, pos, cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<defs::pedestalParameters>
|
||||||
|
Detector::getPedestalMode(Positions pos) const {
|
||||||
|
return pimpl->Parallel(&Module::getPedestalMode, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Detector::setPedestalMode(const defs::pedestalParameters par,
|
||||||
|
Positions pos) {
|
||||||
|
pimpl->Parallel(&Module::setPedestalMode, pos, par);
|
||||||
|
}
|
||||||
|
|
||||||
// Gotthard Specific
|
// Gotthard Specific
|
||||||
|
|
||||||
Result<defs::ROI> Detector::getROI(Positions pos) const {
|
Result<defs::ROI> Detector::getROI(Positions pos) const {
|
||||||
|
@ -1940,6 +1940,20 @@ void Module::setNumberOfFilterCells(int value) {
|
|||||||
sendToDetector(F_SET_NUM_FILTER_CELLS, value, nullptr);
|
sendToDetector(F_SET_NUM_FILTER_CELLS, value, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defs::pedestalParameters Module::getPedestalMode() const {
|
||||||
|
return sendToDetector<defs::pedestalParameters>(F_GET_PEDESTAL_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::setPedestalMode(const defs::pedestalParameters par) {
|
||||||
|
sendToDetector(F_SET_PEDESTAL_MODE, par, nullptr);
|
||||||
|
if (shm()->useReceiverFlag) {
|
||||||
|
auto value = getNumberOfFrames();
|
||||||
|
sendToReceiver(F_RECEIVER_SET_NUM_FRAMES, value, nullptr);
|
||||||
|
value = getNumberOfTriggers();
|
||||||
|
sendToReceiver(F_SET_RECEIVER_NUM_TRIGGERS, value, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Gotthard Specific
|
// Gotthard Specific
|
||||||
|
|
||||||
slsDetectorDefs::ROI Module::getROI() const {
|
slsDetectorDefs::ROI Module::getROI() const {
|
||||||
|
@ -419,6 +419,8 @@ class Module : public virtual slsDetectorDefs {
|
|||||||
void setGainMode(const gainMode mode);
|
void setGainMode(const gainMode mode);
|
||||||
int getNumberOfFilterCells() const;
|
int getNumberOfFilterCells() const;
|
||||||
void setNumberOfFilterCells(int value);
|
void setNumberOfFilterCells(int value);
|
||||||
|
defs::pedestalParameters getPedestalMode() const;
|
||||||
|
void setPedestalMode(defs::pedestalParameters par);
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* *
|
* *
|
||||||
|
@ -506,6 +506,161 @@ TEST_CASE("filtercells", "[.cmd]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("pedestalmode", "[.cmd]") {
|
||||||
|
Detector det;
|
||||||
|
CmdProxy proxy(&det);
|
||||||
|
auto det_type = det.getDetectorType().squash();
|
||||||
|
if (det_type == defs::JUNGFRAU) {
|
||||||
|
auto prev_val = det.getPedestalMode();
|
||||||
|
auto prev_frames = det.getNumberOfFrames().tsquash(
|
||||||
|
"Inconsistent number of frames to test");
|
||||||
|
auto prev_triggers = det.getNumberOfTriggers().tsquash(
|
||||||
|
"Inconsistent number of triggers to test");
|
||||||
|
auto prev_timingmode =
|
||||||
|
det.getTimingMode().tsquash("Inconsistent timing mode to test");
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("pedestalmode", {}, 0, GET));
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("pedestalmode", {}, -1, GET));
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {"0"}, -1, GET));
|
||||||
|
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {"256", "10"}, -1, PUT));
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {"-1", "10"}, 0, PUT));
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {"20", "65536"}, 0, PUT));
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {"20", "-1"}, 0, PUT));
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
proxy.Call("pedestalmode", {"30", "1000"}, -1, PUT, oss);
|
||||||
|
REQUIRE(oss.str() == "pedestalmode [30, 1000]\n");
|
||||||
|
}
|
||||||
|
// cannot change any of these in pedestal mode
|
||||||
|
REQUIRE_THROWS_WITH(proxy.Call("frames", {"200"}, -1, PUT),
|
||||||
|
"Detector returned: Cannot set frames in pedestal "
|
||||||
|
"mode. It is overwritten anyway.\n");
|
||||||
|
REQUIRE_THROWS_WITH(proxy.Call("triggers", {"200"}, -1, PUT),
|
||||||
|
"Detector returned: Cannot set triggers in "
|
||||||
|
"pedestal mode. It is overwritten anyway.\n");
|
||||||
|
REQUIRE_THROWS_WITH(
|
||||||
|
proxy.Call("timing", {"auto"}, -1, PUT),
|
||||||
|
"Detector returned: Cannot set timing mode in pedestal mode. "
|
||||||
|
"Switch off pedestal mode to change timing mode.\n");
|
||||||
|
REQUIRE_THROWS_WITH(
|
||||||
|
proxy.Call("scan", {"vb_comp", "500", "1500", "10"}, -1, PUT),
|
||||||
|
"Detector returned: Cannot set scan when in pedestal mode.\n");
|
||||||
|
REQUIRE_THROWS_WITH(
|
||||||
|
proxy.Call("scan", {"0"}, -1, PUT),
|
||||||
|
"Detector returned: Cannot set scan when in pedestal mode.\n");
|
||||||
|
// should not throw to get these values though
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("frames", {}, -1, GET));
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("triggers", {}, -1, GET));
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("timing", {}, -1, GET));
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("scan", {}, -1, GET));
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
proxy.Call("pedestalmode", {"50", "500"}, -1, PUT, oss);
|
||||||
|
REQUIRE(oss.str() == "pedestalmode [50, 500]\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
proxy.Call("pedestalmode", {}, -1, GET, oss);
|
||||||
|
REQUIRE(oss.str() == "pedestalmode [enabled, 50, 500]\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto pedemode = det.getPedestalMode().tsquash(
|
||||||
|
"Inconsistent pedestal mode to test");
|
||||||
|
REQUIRE(pedemode.enable == true);
|
||||||
|
REQUIRE(pedemode.frames == 50);
|
||||||
|
REQUIRE(pedemode.loops == 500);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
proxy.Call("pedestalmode", {"0"}, -1, PUT, oss);
|
||||||
|
REQUIRE(oss.str() == "pedestalmode [0]\n");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
proxy.Call("pedestalmode", {}, -1, GET, oss);
|
||||||
|
REQUIRE(oss.str() == "pedestalmode [disabled]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t pedestalFrames = 50;
|
||||||
|
uint16_t pedestalLoops = 1000;
|
||||||
|
int64_t expNumFrames = pedestalFrames * pedestalLoops * 2;
|
||||||
|
auto origFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
auto origTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
|
||||||
|
// auto mode
|
||||||
|
det.setTimingMode(defs::AUTO_TIMING);
|
||||||
|
REQUIRE_NOTHROW(proxy.Call(
|
||||||
|
"pedestalmode",
|
||||||
|
{std::to_string(pedestalFrames), std::to_string(pedestalLoops)}, -1,
|
||||||
|
PUT));
|
||||||
|
auto numTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
auto numFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
REQUIRE(numFrames == expNumFrames);
|
||||||
|
REQUIRE(numTriggers == 1);
|
||||||
|
|
||||||
|
// pedestal mode off
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("pedestalmode", {"0"}, -1, PUT));
|
||||||
|
numTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
numFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
REQUIRE(numFrames == origFrames);
|
||||||
|
REQUIRE(numTriggers == origTriggers);
|
||||||
|
|
||||||
|
// trigger mode (frames > 1)
|
||||||
|
REQUIRE_NOTHROW(det.setTimingMode(defs::TRIGGER_EXPOSURE));
|
||||||
|
origFrames = 5;
|
||||||
|
REQUIRE_NOTHROW(det.setNumberOfFrames(origFrames));
|
||||||
|
REQUIRE_NOTHROW(proxy.Call(
|
||||||
|
"pedestalmode",
|
||||||
|
{std::to_string(pedestalFrames), std::to_string(pedestalLoops)}, -1,
|
||||||
|
PUT));
|
||||||
|
numTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
numFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
REQUIRE(numFrames == expNumFrames);
|
||||||
|
REQUIRE(numTriggers == 1);
|
||||||
|
|
||||||
|
// pedestal mode off
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("pedestalmode", {"0"}, -1, PUT));
|
||||||
|
numTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
numFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
REQUIRE(numFrames == origFrames);
|
||||||
|
REQUIRE(numTriggers == origTriggers);
|
||||||
|
|
||||||
|
// trigger mode (frames = 1)
|
||||||
|
origFrames = 1;
|
||||||
|
REQUIRE_NOTHROW(det.setNumberOfFrames(origFrames));
|
||||||
|
origTriggers = 10;
|
||||||
|
REQUIRE_NOTHROW(det.setNumberOfTriggers(origTriggers));
|
||||||
|
REQUIRE_NOTHROW(proxy.Call(
|
||||||
|
"pedestalmode",
|
||||||
|
{std::to_string(pedestalFrames), std::to_string(pedestalLoops)}, -1,
|
||||||
|
PUT));
|
||||||
|
numTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
numFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
REQUIRE(numFrames == 1);
|
||||||
|
REQUIRE(numTriggers == expNumFrames);
|
||||||
|
|
||||||
|
// pedestal mode off
|
||||||
|
REQUIRE_NOTHROW(proxy.Call("pedestalmode", {"0"}, -1, PUT));
|
||||||
|
numTriggers = det.getNumberOfTriggers().squash(-1);
|
||||||
|
numFrames = det.getNumberOfFrames().squash(-1);
|
||||||
|
REQUIRE(numFrames == origFrames);
|
||||||
|
REQUIRE(numTriggers == origTriggers);
|
||||||
|
|
||||||
|
det.setNumberOfFrames(prev_frames);
|
||||||
|
det.setNumberOfTriggers(prev_triggers);
|
||||||
|
det.setTimingMode(prev_timingmode);
|
||||||
|
for (int i = 0; i != det.size(); ++i) {
|
||||||
|
det.setPedestalMode(prev_val[i], {i});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {}, -1, GET));
|
||||||
|
REQUIRE_THROWS(proxy.Call("pedestalmode", {"0"}, -1, PUT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("sync", "[.cmd]") {
|
TEST_CASE("sync", "[.cmd]") {
|
||||||
Detector det;
|
Detector det;
|
||||||
CmdProxy proxy(&det);
|
CmdProxy proxy(&det);
|
||||||
|
@ -58,6 +58,9 @@ std::ostream &operator<<(std::ostream &os,
|
|||||||
std::string ToString(const slsDetectorDefs::currentSrcParameters &r);
|
std::string ToString(const slsDetectorDefs::currentSrcParameters &r);
|
||||||
std::ostream &operator<<(std::ostream &os,
|
std::ostream &operator<<(std::ostream &os,
|
||||||
const slsDetectorDefs::currentSrcParameters &r);
|
const slsDetectorDefs::currentSrcParameters &r);
|
||||||
|
std::string ToString(const slsDetectorDefs::pedestalParameters &r);
|
||||||
|
std::ostream &operator<<(std::ostream &os,
|
||||||
|
const slsDetectorDefs::pedestalParameters &r);
|
||||||
const std::string &ToString(const std::string &s);
|
const std::string &ToString(const std::string &s);
|
||||||
|
|
||||||
/** Convert std::chrono::duration with specified output unit */
|
/** Convert std::chrono::duration with specified output unit */
|
||||||
@ -316,6 +319,7 @@ template <> defs::vetoAlgorithm StringTo(const std::string &s);
|
|||||||
template <> defs::gainMode StringTo(const std::string &s);
|
template <> defs::gainMode StringTo(const std::string &s);
|
||||||
template <> defs::polarity StringTo(const std::string &s);
|
template <> defs::polarity StringTo(const std::string &s);
|
||||||
|
|
||||||
|
template <> uint8_t StringTo(const std::string &s);
|
||||||
template <> uint16_t StringTo(const std::string &s);
|
template <> uint16_t StringTo(const std::string &s);
|
||||||
template <> uint32_t StringTo(const std::string &s);
|
template <> uint32_t StringTo(const std::string &s);
|
||||||
template <> uint64_t StringTo(const std::string &s);
|
template <> uint64_t StringTo(const std::string &s);
|
||||||
|
@ -547,6 +547,29 @@ enum streamingInterface {
|
|||||||
}
|
}
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct pedestalParameters {
|
||||||
|
int enable;
|
||||||
|
uint8_t frames;
|
||||||
|
uint16_t loops;
|
||||||
|
|
||||||
|
/** [Jungfrau] disable */
|
||||||
|
pedestalParameters() : enable(0), frames(0), loops(0) {}
|
||||||
|
|
||||||
|
/** [Jungfrau] enable */
|
||||||
|
pedestalParameters(uint8_t pedestalFrames, uint16_t pedestalLoops)
|
||||||
|
: enable(1), frames(pedestalFrames), loops(pedestalLoops) {
|
||||||
|
if (frames == 0 || loops == 0) {
|
||||||
|
throw sls::RuntimeError(
|
||||||
|
"Pedestal frames or loops cannot be 0.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const pedestalParameters &other) const {
|
||||||
|
return ((enable == other.enable) && (frames == other.frames) &&
|
||||||
|
(loops == other.loops));
|
||||||
|
}
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* structure to udpate receiver
|
* structure to udpate receiver
|
||||||
*/
|
*/
|
||||||
|
@ -290,6 +290,8 @@ enum detFuncs {
|
|||||||
F_SET_ROW,
|
F_SET_ROW,
|
||||||
F_GET_COLUMN,
|
F_GET_COLUMN,
|
||||||
F_SET_COLUMN,
|
F_SET_COLUMN,
|
||||||
|
F_GET_PEDESTAL_MODE,
|
||||||
|
F_SET_PEDESTAL_MODE,
|
||||||
|
|
||||||
NUM_DET_FUNCTIONS,
|
NUM_DET_FUNCTIONS,
|
||||||
RECEIVER_ENUM_START = 512, /**< detector function should not exceed this
|
RECEIVER_ENUM_START = 512, /**< detector function should not exceed this
|
||||||
@ -687,6 +689,8 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
|
|||||||
case F_SET_ROW: return "F_SET_ROW";
|
case F_SET_ROW: return "F_SET_ROW";
|
||||||
case F_GET_COLUMN: return "F_GET_COLUMN";
|
case F_GET_COLUMN: return "F_GET_COLUMN";
|
||||||
case F_SET_COLUMN: return "F_SET_COLUMN";
|
case F_SET_COLUMN: return "F_SET_COLUMN";
|
||||||
|
case F_GET_PEDESTAL_MODE: return "F_GET_PEDESTAL_MODE";
|
||||||
|
case F_SET_PEDESTAL_MODE: return "F_SET_PEDESTAL_MODE";
|
||||||
|
|
||||||
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
|
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
|
||||||
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";
|
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
#define RELEASE "developer"
|
#define RELEASE "developer"
|
||||||
#define APILIB "developer 0x230224"
|
#define APILIB "developer 0x230224"
|
||||||
#define APIRECEIVER "developer 0x230224"
|
#define APIRECEIVER "developer 0x230224"
|
||||||
#define APICTB "developer 0x230922"
|
#define APICTB "developer 0x230922"
|
||||||
#define APIGOTTHARD "developer 0x230922"
|
#define APIGOTTHARD "developer 0x230922"
|
||||||
#define APIGOTTHARD2 "developer 0x230922"
|
#define APIGOTTHARD2 "developer 0x230922"
|
||||||
#define APIJUNGFRAU "developer 0x230922"
|
#define APIMYTHEN3 "developer 0x230922"
|
||||||
#define APIMYTHEN3 "developer 0x230922"
|
#define APIMOENCH "developer 0x230922"
|
||||||
#define APIMOENCH "developer 0x230922"
|
#define APIEIGER "developer 0x230922"
|
||||||
#define APIEIGER "developer 0x230922"
|
#define APIJUNGFRAU "developer 0x230928"
|
||||||
|
@ -155,6 +155,23 @@ std::ostream &operator<<(std::ostream &os,
|
|||||||
return os << ToString(r);
|
return os << ToString(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ToString(const slsDetectorDefs::pedestalParameters &r) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << '[';
|
||||||
|
if (r.enable)
|
||||||
|
oss << "enabled, " << std::to_string(r.frames) << ", " << r.loops;
|
||||||
|
else
|
||||||
|
oss << "disabled";
|
||||||
|
|
||||||
|
oss << ']';
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os,
|
||||||
|
const slsDetectorDefs::pedestalParameters &r) {
|
||||||
|
return os << ToString(r);
|
||||||
|
}
|
||||||
|
|
||||||
std::string ToString(const defs::runStatus s) {
|
std::string ToString(const defs::runStatus s) {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case defs::ERROR:
|
case defs::ERROR:
|
||||||
@ -1083,6 +1100,17 @@ template <> defs::polarity StringTo(const std::string &s) {
|
|||||||
throw RuntimeError("Unknown polarity mode " + s);
|
throw RuntimeError("Unknown polarity mode " + s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> uint8_t StringTo(const std::string &s) {
|
||||||
|
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||||
|
int value = std::stoi(s, nullptr, base);
|
||||||
|
if (value < std::numeric_limits<uint8_t>::min() ||
|
||||||
|
value > std::numeric_limits<uint8_t>::max()) {
|
||||||
|
throw RuntimeError("Cannot scan uint8_t from string '" + s +
|
||||||
|
"'. Value must be in range 0 - 255.");
|
||||||
|
}
|
||||||
|
return static_cast<uint8_t>(value);
|
||||||
|
}
|
||||||
|
|
||||||
template <> uint16_t StringTo(const std::string &s) {
|
template <> uint16_t StringTo(const std::string &s) {
|
||||||
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
int base = s.find("0x") != std::string::npos ? 16 : 10;
|
||||||
int value = std::stoi(s, nullptr, base);
|
int value = std::stoi(s, nullptr, base);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user