6 Commits
1.1.2 ... 1.1.4

Author SHA1 Message Date
Marco Filho
38218b883e Merge branch 'ICSHWI-22046' into 'master'
Overwrite default initial values

See merge request epics-modules/adorca!30
2025-10-15 16:52:00 +02:00
marcofilho
77b5441d23 Overwrite default initial values 2025-10-15 16:48:35 +02:00
marcofilho
7ee6421657 Update example st.cmd
From this version onwards, it is possible to pass all the data to
ndpluginschemas and then to kafka newest versions, intead of passing
straight to kafka.
2025-10-15 13:09:47 +02:00
Marco Filho
def770e2f8 Merge branch 'improve-timestamp' into 'master'
Pass timestamp to epicsTS instead of timeStamp

See merge request epics-modules/adorca!29
2025-10-15 13:03:58 +02:00
marcofilho
cceb18989b Make epicsTS carry the proper EVR timestamp
epicsTS is the one passed to kafka: https://gitlab.esss.lu.se/epics-modules/ADPluginKafka/-/blob/2.0.2/adpluginkafkaApp/src/KafkaPlugin.cpp?ref_type=tags#L40
The documentation is a bit confusing on what is the difference between
epicsTS and timeStamp, but apparently both can be modified with no
problems.

After [this discussion](github.com/areaDetector/ADCore/issues?q=is%3Aissue%20state%3Aclosed)
I decided it was fine to keep the epicsTS in nanoseconds with the EVR
values.
2025-10-15 13:00:16 +02:00
marcofilho
e2d6d48cde Decrease image-timestamp latency.
The timestamp buffer is now filled unconditionally, always after
dcamcap_transferinfo is called. It is only used, however, if trigger
mode is external.

This reduces time between detecting an image and getting the timestamp
from around 1.6 ms to around 200 ns.
2025-10-10 16:48:07 +02:00
4 changed files with 28 additions and 15 deletions

View File

@@ -109,6 +109,14 @@ record("*", "$(P)$(R)AcquirePeriod_RBV") {
field(FLNK, "$(P)$(R)#EVRAcquireTime-S.PROC PP MS") field(FLNK, "$(P)$(R)#EVRAcquireTime-S.PROC PP MS")
} }
record("*", "$(P)$(R)AcquireTime") {
field(VAL, "0.9")
}
record("*", "$(P)$(R)AcquirePeriod") {
field(VAL, "1")
}
record(calcout, "$(P)$(R)#EVRAcquireTime-S") { record(calcout, "$(P)$(R)#EVRAcquireTime-S") {
field(DESC, "Set EVR acquire time in seconds") field(DESC, "Set EVR acquire time in seconds")
field(CALC, "A=0?B:A*B") field(CALC, "A=0?B:A*B")

View File

@@ -834,6 +834,7 @@ void Orca::imageTask() {
uint64_t prevAcquisitionCount = 0; uint64_t prevAcquisitionCount = 0;
DCAMCAP_TRANSFERINFO captransferinfo; DCAMCAP_TRANSFERINFO captransferinfo;
epicsTimeStamp prevAcqTime, currentAcqTime; epicsTimeStamp prevAcqTime, currentAcqTime;
epicsTimeStamp acqTimestamp;
epicsTimeStamp prev_trigger_time, current_trigger_time; epicsTimeStamp prev_trigger_time, current_trigger_time;
double elapsedTime; double elapsedTime;
int evr_counts = 0; int evr_counts = 0;
@@ -841,6 +842,7 @@ void Orca::imageTask() {
double maxAcqusitionTime, acqusitionRate; double maxAcqusitionTime, acqusitionRate;
int triggerMode = DCAMPROP_TRIGGERSOURCE__INTERNAL; int triggerMode = DCAMPROP_TRIGGERSOURCE__INTERNAL;
int triggerActive; int triggerActive;
char buf[256];
lock(); lock();
while (1) { while (1) {
@@ -875,7 +877,7 @@ void Orca::imageTask() {
// get image transfer status. // get image transfer status.
unlock(); unlock();
imageTransferStatus(m_hdcam, captransferinfo); imageTransferStatus(m_hdcam, captransferinfo, buf);
lock(); lock();
if (prevAcquisitionCount < (uint64_t)captransferinfo.nFrameCount) { if (prevAcquisitionCount < (uint64_t)captransferinfo.nFrameCount) {
@@ -926,18 +928,19 @@ void Orca::imageTask() {
// Update asyn parameters // Update asyn parameters
setIntegerParam(evrCountsSinceAcqStart, evr_counts_since_last_start); setIntegerParam(evrCountsSinceAcqStart, evr_counts_since_last_start);
setIntegerParam(evrTriggerDropped, evr_trigger_dropped); setIntegerParam(evrTriggerDropped, evr_trigger_dropped);
char buf[256];
getStringParam(evrTimeStamp, 256, buf);
// remember parsed timestamp values // remember parsed timestamp values
sscanf(buf, "%u.%u", &mTimeStampSec, &mTimeStampNsec); sscanf(buf, "%u.%u", &acqTimestamp.secPastEpoch, &acqTimestamp.nsec);
timestamp = mTimeStampSec + mTimeStampNsec / 1.e9; acqTimestamp.secPastEpoch -= POSIX_TIME_AT_EPICS_EPOCH;
FLOW_ARGS("mTimeStampSec: %u - mTimeStampNsec: %u\n", mTimeStampSec,
mTimeStampNsec); timestamp = acqTimestamp.secPastEpoch + acqTimestamp.nsec / 1.e9;
FLOW_ARGS("acqTimestamp.secPastEpoch: %u - acqTimestamp.nsec: %u\n", acqTimestamp.secPastEpoch,
acqTimestamp.nsec);
FLOW_ARGS("Timestamp from evr: %f\n", timestamp); FLOW_ARGS("Timestamp from evr: %f\n", timestamp);
} else { } else {
updateTimeStamp(&acqTimestamp);
timestamp = timestamp =
(ts_sec + ts_microsec / 1.0e6) - (exposure_time + readout_time); (ts_sec + ts_microsec / 1.0e6) - (exposure_time + readout_time);
FLOW_ARGS("Timestamp from camera: %f\n", timestamp); FLOW_ARGS("Timestamp from camera: %f\n", timestamp);
@@ -967,7 +970,7 @@ void Orca::imageTask() {
if (pImage) { if (pImage) {
pImage->uniqueId = count; pImage->uniqueId = count;
pImage->timeStamp = timestamp; pImage->timeStamp = timestamp;
updateTimeStamp(&pImage->epicsTS); pImage->epicsTS = acqTimestamp;
memcpy(pImage->pData, (epicsUInt16*)image, pImage->dataSize); memcpy(pImage->pData, (epicsUInt16*)image, pImage->dataSize);
@@ -1742,7 +1745,7 @@ void Orca::getImageInformation(HDCAM hdcam, int32& pixeltype, int32& width,
} }
asynStatus Orca::imageTransferStatus(HDCAM hdcam, asynStatus Orca::imageTransferStatus(HDCAM hdcam,
DCAMCAP_TRANSFERINFO& captransferinfo) { DCAMCAP_TRANSFERINFO& captransferinfo, char *buf) {
DCAMERR err; DCAMERR err;
const char* functionName = "imageTransferStatus"; const char* functionName = "imageTransferStatus";
memset(&captransferinfo, 0, sizeof(captransferinfo)); memset(&captransferinfo, 0, sizeof(captransferinfo));
@@ -1750,6 +1753,7 @@ asynStatus Orca::imageTransferStatus(HDCAM hdcam,
// get number of captured image // get number of captured image
err = dcamcap_transferinfo(m_hdcam, &captransferinfo); err = dcamcap_transferinfo(m_hdcam, &captransferinfo);
getStringParam(evrTimeStamp, 256, buf);
if (failed(err)) { if (failed(err)) {
ERR_ARGS("DCAMERR: 0x%08X [%s]", m_err, "dcamcap_transferinfo"); ERR_ARGS("DCAMERR: 0x%08X [%s]", m_err, "dcamcap_transferinfo");
return asynError; return asynError;

View File

@@ -189,9 +189,6 @@ class epicsShareClass Orca : public ADDriver {
int readParameter(int propertyID, bool processPV = true); int readParameter(int propertyID, bool processPV = true);
int readParameterStr(int paramIndex); int readParameterStr(int paramIndex);
epicsUInt32 mTimeStampSec;
epicsUInt32 mTimeStampNsec;
void imageTask(); void imageTask();
void temperatureTask(); void temperatureTask();
@@ -333,7 +330,7 @@ class epicsShareClass Orca : public ADDriver {
int32 rowbytes, int32 cx, int32 cy, int32 rowbytes, int32 cx, int32 cy,
epicsUInt32& ts_sec, epicsUInt32& ts_microsec); epicsUInt32& ts_sec, epicsUInt32& ts_microsec);
asynStatus imageTransferStatus(HDCAM hdcam, asynStatus imageTransferStatus(HDCAM hdcam,
DCAMCAP_TRANSFERINFO& captransferinfo); DCAMCAP_TRANSFERINFO& captransferinfo, char *buf);
// wrapper functions for dcamapi // wrapper functions for dcamapi
int allocateBuffers(unsigned int); int allocateBuffers(unsigned int);

View File

@@ -1,4 +1,5 @@
require adorca require adorca
require ndpluginschemas
require adpluginkafka require adpluginkafka
epicsEnvSet("PREFIX", "YMIR-Det1:") epicsEnvSet("PREFIX", "YMIR-Det1:")
@@ -34,6 +35,9 @@ NDPvaConfigure("PVA1", $(QSIZE), 0, "$(PORT)", 0, "$(PREFIX)Pva1:Image", 0, 0, 0
dbLoadRecords("$(adcore_DIR)/db/NDPva.template", "P=$(PREFIX),R=Pva1:, PORT=PVA1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=$(PORT)") dbLoadRecords("$(adcore_DIR)/db/NDPva.template", "P=$(PREFIX),R=Pva1:, PORT=PVA1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=$(PORT)")
# #
NDSchemasConfigure("Schemas1", "$(QSIZE)", 0, "$(PORT)", 0, 0, 0, "test-orca-lab", 0)
dbLoadRecords("$(ndpluginschemas_DB)/NDPluginSchemas.template", "P=$(PREFIX), R=schemas:, PORT=Schemas1, ADDR=0, TIMEOUT=1, NDARRAY_PORT=$(PORT)")
# Create a standard arrays plugin, set it to get data from orca driver. # Create a standard arrays plugin, set it to get data from orca driver.
NDStdArraysConfigure("Image1", "$(QSIZE)", 0, "$(PORT)", 0, 0) NDStdArraysConfigure("Image1", "$(QSIZE)", 0, "$(PORT)", 0, 0)
dbLoadRecords("NDStdArrays.template", "P=$(PREFIX),R=image1:,PORT=Image1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=$(PORT),TYPE=Int32,FTVL=LONG,NELEMENTS=$(NELEMENTS)") dbLoadRecords("NDStdArrays.template", "P=$(PREFIX),R=image1:,PORT=Image1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=$(PORT),TYPE=Int32,FTVL=LONG,NELEMENTS=$(NELEMENTS)")
@@ -44,8 +48,8 @@ epicsEnvSet("KFK_TOPIC", "ymir_camera")
# Kafka plugin # Kafka plugin
#epicsEnvSet("KFK_CONFIG_FILE_PATH", "/etc/kafka/kafka.conf") #epicsEnvSet("KFK_CONFIG_FILE_PATH", "/etc/kafka/kafka.conf")
#KafkaPluginConfigure("KFK1", 3, 1, "$(PORT)", 0, -1, "$(KFK_TOPIC)", "hama_kfk1","$(KFK_CONFIG_FILE_PATH)") KafkaPluginConfigure("Kafka1", 3, 1, "Schemas1", 0, -1, "$(KFK_TOPIC)","$(KFK_CONFIG_FILE_PATH)")
#dbLoadRecords("$(adpluginkafka_DIR)db/adpluginkafka.db", "P=$(PREFIX), R=Kfk1:, PORT=KFK1, ADDR=0, TIMEOUT=1, NDARRAY_PORT=$(PORT)") dbLoadRecords("$(adpluginkafka_DB)/adpluginkafka.db", "P=$(PREFIX), R=Kfk1:, PORT=Kafka1, ADDR=0, TIMEOUT=1, NDARRAY_PORT=Schemas1")
# startPVAServer # startPVAServer
iocInit() iocInit()