diff --git a/evrApp/Db/Makefile b/evrApp/Db/Makefile index d74d6d1a..8899801c 100644 --- a/evrApp/Db/Makefile +++ b/evrApp/Db/Makefile @@ -14,6 +14,9 @@ DB += evrcml.db DB += evrcmlgun.db DB += evrcmlextra.db DB += evrevent.db +ifdef BASE_7_0 +DB += evreventutag.db +endif DB += evrevent-cycle.db DB += evrsoftgate.db DB += evralias.db diff --git a/evrApp/Db/evrcml.db b/evrApp/Db/evrcml.db index 56412a7c..43bf69c2 100644 --- a/evrApp/Db/evrcml.db +++ b/evrApp/Db/evrcml.db @@ -532,13 +532,13 @@ record(bo, "$(ON)BunchTrain$(s=:)Ena-SP") { record(longout, "$(ON)BunchTrain$(s=:)Size-SP") { field(PINI, "YES") - field(OUT , "$(ON)BunchTrain$(s=:)ASub_.A PP") + field(OUT , "$(ON)BunchTrain-ASub_.A PP") field(UDF , "0") field(VAL , "1") info(autosaveFields_pass0, "VAL") } -record(aSub, "$(ON)BunchTrain$(s=:)ASub_") { +record(aSub, "$(ON)BunchTrain-ASub_") { field(SDIS, "$(ON)BunchTrain$(s=:)Ena-SP") field(DISV, "0") field(SNAM, "Bunch Train") diff --git a/evrApp/Db/evreventutag.db b/evrApp/Db/evreventutag.db new file mode 100644 index 00000000..237d0041 --- /dev/null +++ b/evrApp/Db/evreventutag.db @@ -0,0 +1,27 @@ +# Usage of "evreventutag.db" +## Timestaming + UTAG support: import "evreventutag.db" instead of "evrevent.db". +## Timestaming support only: import "evrevent.db" and ignore "evreventutag.db". + +# Macros: +# EN = record name prefix +# OBJ = EVR devObj name +# CODE = Event code (hardware) + +record(int64out, "$(EN)-SP") { + field(DTYP, "EVR Event Utag") + field(SCAN, "I/O Intr") + field(OUT , "@OBJ=$(OBJ),Code=$(CODE)") + field(VAL , "0") + field(TSE , "-2") # from device support + field(FLNK, "$(EN)Cnt-I") + info(autosaveFields_pass0, "OUT") +} + +record(calc, "$(EN)Cnt-I") { + field(DESC, "TS and UTAG source") + #field(SDIS, "$(EN)-SP") + #field(DISV, "0") + field(CALC, "A+1") + field(INPA, "$(EN)Cnt-I NPP") + field(TSEL, "$(EN)-SP.TIME") +} diff --git a/evrApp/src/Makefile b/evrApp/src/Makefile index 9b3fb6da..a337cc96 100644 --- a/evrApp/src/Makefile +++ b/evrApp/src/Makefile @@ -28,6 +28,10 @@ evr_SRCS += evrGTIF.cpp evr_SRCS += devEvrStringIO.cpp +ifdef BASE_7_0 +evr_SRCS += devEvrEventUtag.cpp +endif + evr_SRCS += devEvrEvent.cpp evr_SRCS += devEvrMapping.cpp @@ -53,6 +57,9 @@ evrtest_LIBS += evr mrfCommon evrtest_DBD += base.dbd evrtest_DBD += evrSupport.dbd +ifdef BASE_7_0 +evrtest_DBD += evrSupportBase7.dbd +endif ifneq ($(GENERAL_TIME),) evrtest_LIBS += generalTime diff --git a/evrApp/src/devEvrEventUtag.cpp b/evrApp/src/devEvrEventUtag.cpp new file mode 100644 index 00000000..fb5016d3 --- /dev/null +++ b/evrApp/src/devEvrEventUtag.cpp @@ -0,0 +1,198 @@ +/*************************************************************************\ +* Copyright (c) 2023 European Spallation Source ERIC (ESS), Lund, Sweden +* mrfioc2 is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Date: 5.12.2023 + * Authors: Joao Paulo Martins + * Jerzy Jamroz + */ + +#include +#include +#include +#include +#include +#include +#include // For S_dev_* +#include +#include + +#include +#include + +#include "devObj.h" +#include "evr/evr.h" + +#include "linkoptions.h" + +#include +#include + +/***************** Event *****************/ + +struct priv +{ + EVR *evr; + char obj[30]; + int event; +}; + +static const linkOptionDef eventdef[] = + { + linkString(priv, obj, "OBJ", 1, 0), + linkInt32(priv, event, "Code", 1, 0), + linkOptionEnd}; + +static long add_record(struct dbCommon *prec, struct link *link) +{ + long ret = 0; + try + { + assert(link->type == INST_IO); + + mrf::auto_ptr p(new priv); + p->event = 0; + + if (linkOptionsStore(eventdef, p.get(), link->value.instio.string, 0)) + throw std::runtime_error("Couldn't parse link string"); + + mrf::Object *O = mrf::Object::getObject(p->obj); + if (!O) + { + errlogPrintf("%s: failed to find object '%s'\n", prec->name, p->obj); + return S_db_errArg; + } + p->evr = dynamic_cast(O); + if (!p->evr) + throw std::runtime_error("Failed to lookup device"); + + if (!p->evr->interestedInEvent(p->event, true)) + throw std::runtime_error("Failed to register interest"); + + prec->dpvt = (void *)p.release(); + + return 0; + } + catch (std::runtime_error &e) + { + recGblRecordError(S_dev_noDevice, (void *)prec, e.what()); + ret = S_dev_noDevice; + } + catch (std::exception &e) + { + recGblRecordError(S_db_noMemory, (void *)prec, e.what()); + ret = S_db_noMemory; + } + return ret; +} + +static long del_record(struct dbCommon *prec) +{ + priv *p = static_cast(prec->dpvt); + long ret = 0; + if (!p) + return 0; + try + { + + p->evr->interestedInEvent(p->event, false); + delete p; + prec->dpvt = 0; + } + catch (std::runtime_error &e) + { + recGblRecordError(S_dev_noDevice, (void *)prec, e.what()); + ret = S_dev_noDevice; + } + catch (std::exception &e) + { + recGblRecordError(S_db_noMemory, (void *)prec, e.what()); + ret = S_db_noMemory; + } + return ret; +} + +static long get_ioint_info(int, dbCommon *prec, IOSCANPVT *io) +{ + if (!prec->dpvt) + return S_db_errArg; + priv *p = static_cast(prec->dpvt); + long ret = 0; + try + { + + if (!p) + return 1; + + *io = p->evr->eventOccurred(p->event); + + return 0; + } + catch (std::runtime_error &e) + { + recGblRecordError(S_dev_noDevice, (void *)prec, e.what()); + ret = S_dev_noDevice; + } + catch (std::exception &e) + { + recGblRecordError(S_db_noMemory, (void *)prec, e.what()); + ret = S_db_noMemory; + } + *io = NULL; + return ret; +} + +static long process_int64out(int64outRecord *prec) +{ + priv *p = static_cast(prec->dpvt); + long ret = 0; + try + { + + if (p->event >= 0 && p->event <= 255) + post_event(p->event); + + if (prec->tse == epicsTimeEventDeviceTime) + { + p->evr->getTimeStamp(&prec->time, p->event); +#ifdef DBR_UTAG + prec->utag = static_cast(prec->val); + p->evr->setUtag(prec->utag, p->event); +#endif + } + + return 0; + } + catch (std::runtime_error &e) + { + recGblRecordError(S_dev_noDevice, (void *)prec, e.what()); + ret = S_dev_noDevice; + } + catch (std::exception &e) + { + recGblRecordError(S_db_noMemory, (void *)prec, e.what()); + ret = S_db_noMemory; + } + return ret; +} + +static long add_int64out(struct dbCommon *precord) +{ + return add_record(precord, &((struct int64outRecord *)precord)->out); +} + +dsxt dxtI64OEventUtagEVR = {add_int64out, del_record}; +static common_dset devI64OEventUtagEVR = { + 6, NULL, + dset_cast(&init_dset<&dxtI64OEventUtagEVR>), + (DEVSUPFUN)init_record_empty, + (DEVSUPFUN)&get_ioint_info, + dset_cast(&process_int64out), + NULL}; + +extern "C" +{ + epicsExportAddress(dset, devI64OEventUtagEVR); +} diff --git a/evrApp/src/evr/evr.h b/evrApp/src/evr/evr.h index 0cf97556..f42164cd 100644 --- a/evrApp/src/evr/evr.h +++ b/evrApp/src/evr/evr.h @@ -191,6 +191,17 @@ class epicsShareClass EVR : public mrf::ObjectInst epicsUInt32 SourceTSraw() const{return (TSSource)SourceTS();}; /*@}*/ +#ifdef DBR_UTAG + /**\defgroup utagman UTAG Management + * + * Get/Set UTAG value for specific event + */ + /*@{*/ + virtual epicsUTag getUtag(const epicsUInt32 event) const {return 0;}; + virtual void setUtag(epicsUTag tag, const epicsUInt32 event) {}; + /*@}*/ +#endif + private: bus_configuration busConfiguration; }; // class EVR diff --git a/evrApp/src/evrSupportBase7.dbd b/evrApp/src/evrSupportBase7.dbd new file mode 100644 index 00000000..5f1c8c30 --- /dev/null +++ b/evrApp/src/evrSupportBase7.dbd @@ -0,0 +1,2 @@ +# '@C=..., Code=hweventnum' +device(int64out, INST_IO, devI64OEventUtagEVR, "EVR Event Utag") diff --git a/evrMrmApp/src/drvem.cpp b/evrMrmApp/src/drvem.cpp index 44fe9022..9bbce899 100644 --- a/evrMrmApp/src/drvem.cpp +++ b/evrMrmApp/src/drvem.cpp @@ -356,6 +356,10 @@ try{ if(busConfig.busType==busType_pci) mrf::SPIDevice::registerDev(n+":FLASH", mrf::SPIDevice(this, 1)); + #ifndef DBR_UTAG + std::cout << "WARNING EVRMRM::EVRMRM epicsUTag not supported." << std::endl; + #endif + } catch (std::exception& e) { printf("Aborting EVR initializtion: %s\n", e.what()); cleanup(); @@ -1563,3 +1567,27 @@ EVRMRM::seconds_tick(void *raw, epicsUInt32) callbackRequest(&evr->timeSrc_cb); } } + +#ifdef DBR_UTAG +// Get UTAG value for specific event +epicsUTag +EVRMRM::getUtag(const epicsUInt32 event) const { + if(event==0) return 0; + else if(event>255) throw std::runtime_error("Event code out of range"); + SCOPED_LOCK(evrLock); + + return events[event].utag; +} + +// Set UTAG value for specific event +void +EVRMRM::setUtag(epicsUTag tag, const epicsUInt32 event) { + if(event==0) return; + else if(event>255) throw std::runtime_error("Event code out of range"); + SCOPED_LOCK(evrLock); + + // set UTAG value to particular event + events[event].utag = tag; + return; +} +#endif diff --git a/evrMrmApp/src/drvem.h b/evrMrmApp/src/drvem.h index d4bcc8af..46673363 100644 --- a/evrMrmApp/src/drvem.h +++ b/evrMrmApp/src/drvem.h @@ -72,12 +72,19 @@ struct eventCode { size_t waitingfor; bool again; + // UTAG associated to event +#ifdef DBR_UTAG + epicsUTag utag; +#endif eventCode():owner(0), interested(0), last_sec(0) ,last_evt(0), waitingfor(0), again(false) +#ifdef DBR_UTAG + ,utag(0) +#endif { scanIoInit(&occured); // done_cb - initialized in EVRMRM::EVRMRM() - } + } }; /**@brief Modular Register Map Event Receivers @@ -192,7 +199,10 @@ class epicsShareClass EVRMRM : public mrf::ObjectInst, {SCOPED_LOCK(evrLock);return count_FIFO_sw_overrate;} virtual epicsUInt32 FIFOEvtCount() const OVERRIDE FINAL {return count_fifo_events;} virtual epicsUInt32 FIFOLoopCount() const OVERRIDE FINAL {return count_fifo_loops;} - +#ifdef DBR_UTAG + virtual epicsUTag getUtag(const epicsUInt32 event) const OVERRIDE FINAL; + virtual void setUtag(epicsUTag tag, const epicsUInt32 event) OVERRIDE FINAL; +#endif void enableIRQ(void); bool dcEnabled() const;