Skip to content

Commit

Permalink
Adding more options of time stamp generator
Browse files Browse the repository at this point in the history
  • Loading branch information
rhong authored and gabrielfedel committed Jun 13, 2024
1 parent efeef76 commit 0a07c88
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 2 deletions.
59 changes: 58 additions & 1 deletion evgMrmApp/Db/evgMrm.db
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ record(bo, "$(P)SimTimestamp-Sel") {
field(ONAM, "Simulate")
}

record(bo, "$(P)SoftTickSecond-Cmd") {
field(DTYP, "Obj Prop command")
field(DESC, "Tick second via EPICS scan")
field(OUT , "@OBJ=$(OBJ), PROP=SoftTick")
field(DISV, 0)
field(SDIS, "$(P)PpsInp1-MbbiDir_.BF")
field(SCAN, "1 second")
}

record(ai, "$(P)TimeErr-I") {
field(DTYP, "Obj Prop double")
field(INP , "@OBJ=$(OBJ), PROP=Time Error")
Expand Down Expand Up @@ -160,13 +169,14 @@ record(mbbo, "$(P)PpsInp1-Sel") {
field(THST, "UnivInp13")
field(FRST, "UnivInp14")
field(FVST, "UnivInp15")
field(SXST, "EPICS Scan")
field(ZRVL, "0x0")
field(ONVL, "0x1")
field(TWVL, "0x2")
field(THVL, "0x4")
field(FRVL, "0x8")
field(FVVL, "0x10")
field(SXSV, "INVALID")
field(SXVL, "0x8000")
field(SVSV, "INVALID")
field(EISV, "INVALID")
field(NISV, "INVALID")
Expand Down Expand Up @@ -197,3 +207,50 @@ record(longin, "$(P)DbusStatus-RB" ) {
field(INP , "@OBJ=$(OBJ), PROP=DbusStatus")
info(autosaveFields_pass0, "SCAN")
}

#
# Timestamp Generator Select
#
record(mbbo, "$(P)TSGen-SP") {
field(DESC, "EVG TS Generator")
field(DTYP, "Obj Prop uint16")
field(OUT, "@OBJ=$(OBJ), PROP=TS Generator")
field(PINI, "YES")
field(UDF, "0")
field(VAL, "0")
field(ZRST, "Software")
field(ONST, "Internal")
field(TWST, "External")
field(ZRVL, "0x0")
field(ONVL, "0x1")
field(TWVL, "0x2")
field(THSV, "INVALID")
field(FRSV, "INVALID")
field(FVSV, "INVALID")
field(SXSV, "INVALID")
field(SVSV, "INVALID")
field(EISV, "INVALID")
field(NISV, "INVALID")
field(TESV, "INVALID")
field(ELSV, "INVALID")
field(TVSV, "INVALID")
field(TTSV, "INVALID")
field(FTSV, "INVALID")
field(FFSV, "INVALID")
field(UNSV, "INVALID")
field(IVOA, "Don't drive outputs")
field(FLNK, "$(P)TSGen-RB")
info(autosaveFields_pass0, "VAL")
}

record(mbbi, "$(P)TSGen-RB") {
field(DESC, "EVG TS Generator")
field(DTYP, "Obj Prop uint16")
field(INP, "@OBJ=$(OBJ), PROP=TS Generator")
field(ZRST, "Software")
field(ONST, "Internal")
field(TWST, "External")
field(ZRVL, "0x0")
field(ONVL, "0x1")
field(TWVL, "0x2")
}
2 changes: 2 additions & 0 deletions evgMrmApp/src/evg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ OBJECT_BEGIN(evgMrm) {
OBJECT_PROP1("Sw Version", &evgMrm::getSwVersion);
OBJECT_PROP1("CommitHash", &evgMrm::getCommitHash);
OBJECT_PROP2("EvtCode", &evgMrm::writeonly, &evgMrm::setEvtCode);
OBJECT_PROP2("TS Generator", &evgMrm::getTSGenerator, &evgMrm::setTSGenerator);
{
bool (evgMrm::*getter)() const = &evgMrm::isSoftSeconds;
void (evgMrm::*setter)(bool) = &evgMrm::softSecondsSrc;
Expand All @@ -65,6 +66,7 @@ OBJECT_BEGIN(evgMrm) {
std::string (evgMrm::*getter)() const = &evgMrm::nextSecond;
OBJECT_PROP1("NextSecond", getter);
}
OBJECT_PROP1("SoftTick", &evgMrm::postSoftSecondsSrc);
{
double (evgMrm::*getter)() const = &evgMrm::deltaSeconds;
OBJECT_PROP1("Time Error", getter);
Expand Down
75 changes: 74 additions & 1 deletion evgMrmApp/src/evgMrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ evgMrm::evgMrm(const std::string& id,
m_fracSynFreq(0),
m_RFDiv(1u),
m_ClkSrc(ClkSrcInternal),
m_TSGenerator(0),
m_seq(this, pReg),
m_acTrig(id+":AcTrig", pReg),
shadowIrqEnable(READ32(m_pReg, IrqEnable))
Expand Down Expand Up @@ -202,6 +203,10 @@ evgMrm::evgMrm(const std::string& id,
evrd.reset(new EVRMRM(id+":EVRD", busConfig, &evm_evrd_conf, pReg+0x20000, 0x10000));
evru.reset(new EVRMRM(id+":EVRU", busConfig, &evm_evru_conf, pReg+0x30000, 0x10000));
}

//Use software generator as default
BITCLR32(m_pReg,DBusTSEvt,TSDBusEvt_MASK);
BITCLR32(m_pReg,TSControl,TSGenerator_ena_MASK);
}

evgMrm::~evgMrm() {
Expand Down Expand Up @@ -425,17 +430,85 @@ evgMrm::process_inp_cb(CALLBACK *pCallback) {
evg->irqExtInp_queued=0;
}

evg->tickSecond();
evg->tsHandler();
scanIoRequest(evg->ioScanTimestamp);
}

void
evgMrm::postSoftSecondsSrc()
{
setEvtCode(0x7d);
tickSecond();
scanIoRequest(ioScanTimestamp);
}

void
evgMrm::tsHandler()
{
epicsUInt32 tsInternal = 0;
epicsUInt32 tsUpdated = 0;
switch(m_TSGenerator) {
case 0:
tickSecond();
break;
case 1:
tsInternal = READ32(m_pReg,TSValue);
tsUpdated = 0;

tsUpdated = updateSecond(tsInternal);
if ( tsInternal != tsUpdated){
WRITE32(m_pReg,TSValue,tsUpdated);
BITSET32(m_pReg,TSControl,TSValuse_load_MASK);
}
break;
case 2:
//TODO: In the External mode, the EVM may not be able to catch the TS set by the DBus 6 and 7. For now, we may not able to show the TS
//of the EVM in this mode.
break;
default:
throw std::runtime_error("Invalid TS Generator. Valid range: 0 - 2.");
break;
}
}

/** TS Generator **/
/* 0 - Software: Upon the 1PPS interrupt, 0x70 and 0x71 events are generated by the tickSecond fuction. Event 0x7d must be configured as a
* trigger Event with the same 1PPS source
* 1 - Internal: DBus5 generates the event 0x7d synchronized to DBus4. EVM increments its internal second counter and sends events 0x70 and
* 0x71 automatically. DBus5 must be triggered by the same 1PPS source.
* 2 - External: DBus5 generates the event 0x7d synchronized to DBus4. Events 0x70 and 0x71 are generated by an external source via DBus6 and 7 **/

void
evgMrm::setTSGenerator(epicsUInt16 TSGen)
{
m_TSGenerator = TSGen;

switch(m_TSGenerator) {
case 0:
BITCLR32(m_pReg,DBusTSEvt,TSDBusEvt_MASK);
BITCLR32(m_pReg,TSControl,TSGenerator_ena_MASK);
break;
case 1:
BITCLR32(m_pReg,DBusTSEvt,TSDBusEvt_MASK);
BITSET32(m_pReg,DBusTSEvt,(0x01 << TSDBusEvt_SHIFT) & TSDBusEvt_MASK);
BITSET32(m_pReg,TSControl,TSGenerator_ena_MASK);
break;
case 2:
BITSET32(m_pReg,DBusTSEvt,(0x07 << TSDBusEvt_SHIFT) & TSDBusEvt_MASK);
BITCLR32(m_pReg,TSControl,TSGenerator_ena_MASK);
break;
default:
throw std::runtime_error("Invalid TS Generator. Valid range: 0 - 2.");
break;
}
}

epicsUInt16
evgMrm::getTSGenerator() const
{
return m_TSGenerator;
}

void
evgMrm::setEvtCode(epicsUInt32 evtCode) {
if(evtCode > 255)
Expand Down
7 changes: 7 additions & 0 deletions evgMrmApp/src/evgMrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ class evgMrm : public mrf::ObjectInst<evgMrm>,
static void init_cb(CALLBACK*, int, void(*)(CALLBACK*), void*);
static void process_inp_cb(CALLBACK*);

/** Timestamp Source Select **/
void tsHandler();
epicsUInt16 getTSGenerator() const;
void setTSGenerator(epicsUInt16 TSGen);

/** Soft Event Set **/
void setEvtCode(epicsUInt32);

// use w/ Object properties for which no getter is necessary
Expand Down Expand Up @@ -167,6 +173,7 @@ class evgMrm : public mrf::ObjectInst<evgMrm>,
epicsFloat64 m_fracSynFreq; // In MHz
unsigned m_RFDiv;
ClkSrc m_ClkSrc;
epicsUInt16 m_TSGenerator; //Timestamp Generator
void recalcRFDiv();

EvgSeqManager m_seq;
Expand Down
14 changes: 14 additions & 0 deletions evgMrmApp/src/evgRegMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@
//
#define U32_DataBufferControl 0x0020 // Data Buffer Control Register
#define U32_DBusSrc 0x0024 // Distributed Data Bus Mapping Register
#define U32_DBusTSEvt 0x0028 // Timestamp events configure for the distributed Data BusD

#define TSDBusEvt_MASK 0x000000E0
#define TSDBusEvt_SHIFT 5

//=====================
// FPGA Firmware Version
Expand All @@ -108,6 +112,16 @@
#define FPGAVersion_TYPE_SHIFT 28
#define FPGAVersion_VER_MASK 0x000000FF

//=====================
// Timestamp Control
//
#define U32_TSControl 0x0034 // TS Control register
#define TSGenerator_ena_MASK 0x01
#define TSGenerator_ena_SHIFT 0
#define TSValuse_load_MASK 0x02
#define TSValuse_load_SHIFT 1
#define U32_TSValue 0x0038 // TS Value to transmit

//=====================
// Event Clock Control
//
Expand Down
59 changes: 59 additions & 0 deletions mrmShared/src/mrmtimesrc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,47 @@ void TimeStampSource::tickSecond()
}
}

epicsUInt32 TimeStampSource::updateSecond(epicsUInt32 ts_in)
{
epicsUInt32 toUpdate = ts_in;
bool ok;

epicsTimeStamp ts;
bool valid = epicsTimeOK == generalTimeGetExceptPriority(&ts, 0, ER_PROVIDER_PRIORITY);

{
Guard G(impl->mutex);

ok = impl->okCnt>=5;

/* delay re-sync request until 1Hz is stable, valid system time is available */
if(ok && valid && impl->resync) {
toUpdate = ts.secPastEpoch+POSIX_TIME_AT_EPICS_EPOCH+1;
impl->resync = false;
}

impl->next = toUpdate;

if(ok && valid) {
impl->lastError = double(toUpdate) - (ts.secPastEpoch+POSIX_TIME_AT_EPICS_EPOCH);
} else {
impl->lastError = -1.0;
}

if(!impl->timeout.get()) {
// lazy start of timestamp timeout thread
impl->timeout.reset(new epicsThread(impl->timeoutRun,
"TimeStampTimeout",
epicsThreadGetStackSize(epicsThreadStackSmall)));
impl->timeout->start();
}
}

impl->wakeup.signal();

return toUpdate;
}

bool TimeStampSource::validSeconds() const
{
Guard G(impl->mutex);
Expand Down Expand Up @@ -287,3 +328,21 @@ std::string TimeStampSource::nextSecond() const

return std::string(&buf[0], buf.size());
}

std::string TimeStampSource::currentSecond() const
{
epicsTimeStamp raw;
{
Guard G(impl->mutex);
raw.secPastEpoch = impl->next - POSIX_TIME_AT_EPICS_EPOCH -1;
raw.nsec = 0;
}
epicsTime time(raw);

std::vector<char> buf(40);

buf.resize(time.strftime(&buf[0], buf.size(), "%a, %d %b %Y %H:%M:%S"));
// buf.size() doesn't include trailing nil

return std::string(&buf[0], buf.size());
}
4 changes: 4 additions & 0 deletions mrmShared/src/mrmtimesrc.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class epicsShareClass TimeStampSource
//! Whether tickSecond() has been called for the past 5 seconds
bool validSeconds() const;

//! Update the second counter and return the same value or the resynchronized second
epicsUInt32 updateSecond(epicsUInt32 ts_in);

//! last difference between
double deltaSeconds() const;

Expand All @@ -38,6 +41,7 @@ class epicsShareClass TimeStampSource
bool isSoftSeconds() const;

std::string nextSecond() const;
std::string currentSecond() const;

protected:
virtual void setEvtCode(epicsUInt32 evtCode) =0;
Expand Down

0 comments on commit 0a07c88

Please sign in to comment.