13 #include <epicsMath.h> 14 #include <epicsMutex.h> 21 #include <epicsExport.h> 23 #define EVG_SEQ_RAM_RUNNING 0x02000000 24 #define EVG_SEQ_RAM_ENABLED 0x01000000 27 #define EVG_SEQ_RAM_SW_TRIG 0x00200000 28 #define EVG_SEQ_RAM_RESET 0x00040000 29 #define EVG_SEQ_RAM_DISABLE 0x00020000 30 #define EVG_SEQ_RAM_ARM 0x00010000 32 #define EVG_SEQ_RAM_WRITABLE_MASK 0x00ffffff 33 #define EVG_SEQ_RAM_REPEAT_MASK 0x00180000 34 #define EVG_SEQ_RAM_NORMAL 0x00000000 35 #define EVG_SEQ_RAM_SINGLE 0x00100000 36 #define EVG_SEQ_RAM_RECYCLE 0x00080000 38 #define EVG_SEQ_RAM_SRC_MASK 0x000000ff 40 #if defined(__rtems__) 41 # define DEBUG(LVL, ARGS) do{if(SeqManagerDebug>=(LVL)) {printk ARGS ;}}while(0) 42 #elif defined(vxWorks) 43 # define DEBUG(LVL, ARGS) do{}while(0) 45 # define DEBUG(LVL, ARGS) do{if(SeqManagerDebug>=(LVL)) {printf ARGS ;}}while(0) 117 switch(owner->
type) {
143 std::string
getErr()
const { SCOPED_LOCK(
mutex);
return last_err; }
157 DEBUG(4, (
"Set time scale\n"));
158 scanIoRequest(changed);
162 double getTimeScale()
const 172 tmult = freq/timeScale;
184 const double tmult = getTimeScale();
188 for(epicsUInt32 i=0; i<count; i++)
190 if(!finite(arr[i]) || arr[i]<0.0)
191 throw std::runtime_error(
"times must be finite >=0");
193 times[i] = (arr[i]*tmult)+0.5;
195 if(i>0 && times[i]<=times[i-1])
196 throw std::runtime_error(
"Non-monotonic timestamp array");
197 else if(times[i]==0xffffffff)
198 throw std::runtime_error(
"Time overflow, rollover not supported");
202 scratch.times.swap(times);
203 is_committed =
false;
205 DEBUG(4, (
"Set times\n"));
206 scanIoRequest(changed);
212 const double tmult = getTimeScale();
213 epicsUInt32 ret = std::min(
size_t(count), committed.times.size());
214 for(epicsUInt32 i=0; i<ret; i++) {
215 arr[i] = committed.times[i]/tmult;
228 scratch.codes.swap(codes);
229 is_committed =
false;
231 DEBUG(4, (
"Set events\n"));
232 scanIoRequest(changed);
238 epicsUInt32 ret = std::min(
size_t(count), committed.codes.size());
239 std::copy(committed.codes.begin(),
240 committed.codes.begin()+ret,
247 DEBUG(4, (
"Setting trig src %x\n", (
unsigned)src));
251 is_committed =
false;
253 DEBUG(4, (
"Set trig src %x\n", (
unsigned)src));
254 scanIoRequest(changed);
260 return committed.src;
270 throw std::runtime_error(
"Unknown sequencer run mode");
276 is_committed =
false;
278 DEBUG(4, (
"Set run mode %u\n", (
unsigned)mode));
279 scanIoRequest(changed);
285 return committed.mode;
305 epicsUInt32
counterEnd()
const { interruptLock L;
return numEnd; }
335 std::swap(times, o.
times);
336 std::swap(codes, o.
codes);
337 std::swap(mode, o.
mode);
338 std::swap(src, o.
src);
402 scanIoInit(&changed);
403 scanIoInit(&onStart);
412 DEBUG(3, (
"SW Triggering\n") );
414 if(!hw || !is_enabled) {
DEBUG(3, (
"Skip\n"));
return;}
420 DEBUG(2, (
"SW Triggered\n") );
426 DEBUG(3, (
"Loading %c\n", hw ?
'L' :
'U') );
427 if(hw) {
DEBUG(3, (
"Skip\n"));
return;}
435 for(
size_t i=0,
N=
owner->hw.size(); i<
N; i++) {
437 if(temp && !temp->
loaded) {
454 last_err =
"All HW Seq. in use";
455 scanIoRequest(onErr);
459 scanIoRequest(changed);
460 DEBUG(1, (
"Loaded\n") );
466 DEBUG(3, (
"Unloading %c\n", hw ?
'L' :
'U') );
468 if(!hw) {
DEBUG(3, (
"Skip\n"));
return;}
470 assert(hw->loaded=
this);
483 scanIoRequest(changed);
484 DEBUG(1, (
"Unloaded\n") );
491 DEBUG(3, (
"Committing %c\n", is_committed ?
'Y' :
'N') );
493 if(is_committed) {
DEBUG(3, (
"Skip\n"));
return;}
499 size_t buflen = std::min(conf.
codes.size(),
501 conf.
codes.resize(buflen);
502 conf.
times.resize(buflen);
505 if(conf.
codes.empty() || conf.
codes.back()!=0x7f)
507 if(!conf.
times.empty() && conf.
times.back()==0xffffffff)
508 throw std::runtime_error(
"Wow, input array is missing 0x7f and maxing out times");
510 conf.
codes.push_back(0x7f);
512 if(conf.
times.empty())
513 conf.
times.push_back(0);
518 if(conf.
times.size()>2048)
519 throw std::runtime_error(
"Sequence too long");
521 assert(!hw || hw->loaded==
this);
525 committed.swap(conf);
529 if(hw && !hw->disarm())
533 scanIoRequest(changed);
534 DEBUG(1, (
"Committed\n") );
540 DEBUG(3, (
"Enabling %c\n", is_enabled ?
'Y' :
'N') );
542 {
DEBUG(3, (
"Skip\n"));
return;}
551 scanIoRequest(changed);
552 DEBUG(1, (
"Enabled\n") );
558 DEBUG(3, (
"Disabling %c\n", is_enabled ?
'Y' :
'N') );
560 {
DEBUG(3, (
"Skip\n"));
return;}
569 scanIoRequest(changed);
570 DEBUG(1, (
"Disabled\n") );
576 DEBUG(3, (
"Syncing %c\n", is_insync ?
'Y' :
'N') );
578 {
DEBUG(3, (
"Skip\n"));
return;}
585 epicsInterruptContextMessage(
"SoftSequence::sync() while running\n");
595 switch(committed.mode) {
623 switch(committed.src&0xff000000) {
625 DEBUG(5, (
" Raw mapping %x\n", committed.src));
627 src = committed.src&0xff;
630 DEBUG(5, (
" SW mapping %x\n", committed.src));
642 DEBUG(5, (
" EXT mapping %x\n", committed.src));
650 DEBUG(5, (
" NO mapping %x\n", committed.src));
654 DEBUG(0, (
"unknown sequencer trigger code %08x\n", (
unsigned)committed.src));
657 DEBUG(5, (
" Trig Src %x\n", src));
659 hw->ctrlreg_user |= src;
662 volatile epicsUInt32 *ram =
static_cast<volatile epicsUInt32 *
>(hw->rambase);
663 for(
size_t i=0,
N=committed.codes.size(); i<
N; i++)
667 if(committed.codes[i]==0x7f)
672 epicsUInt32 ctrl = hw->ctrlreg_hw = hw->ctrlreg_user;
678 DEBUG(3, (
" SeqCtrl %x\n", ctrl));
683 DEBUG(3, (
"In Sync\n") );
696 throw std::invalid_argument(
"Bad SeqManager type");
707 mrf::Object::create_args_t::const_iterator it=args.find(
"PARENT");
709 throw std::runtime_error(
"No PARENT= (EVG) specified");
713 throw std::runtime_error(
"No such PARENT object");
717 throw std::runtime_error(
"PARENT is not a SeqManager");
756 scanIoRequest(seq->
onEnd);
769 hw.resize(std::max(hw.size(), size_t(i+1)), 0);
771 hw[i] =
new SeqHW(
this, i, ctrl, ram);
bool is_enabled
Whether user has requested enable.
std::map< std::string, std::string > create_args_t
mrf::ObjectInst< SoftSequence > base_t
OBJECT_FACTORY(SeqManager::buildSW)
#define EVG_SEQ_RAM_RESET
bool is_committed
clear when scratch and commited sequences differ
INLINE void nat_iowrite32(volatile void *addr, epicsUInt32 val)
void doStartOfSequence(unsigned i)
Call from ISR.
epicsUInt32 counterStart() const
epicsExportAddress(int, SeqManagerDebug)
#define EVG_SEQ_RAM_RUNNING
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
epicsUInt32 counterEnd() const
bool running
between SoS and EoS
static mrf::Object * buildSW(const std::string &name, const std::string &klass, const mrf::Object::create_args_t &args)
epicsUInt32 getRunModeCt() const
static Object * getObject(const std::string &name)
void setRunMode(epicsUInt32 mode)
#define OBJECT_BEGIN(klass)
OBJECT_PROP1("ERROR", &SoftSequence::getErr)
IOSCANPVT getErrScan() const
void doEndOfSequence(unsigned i)
Call from ISR.
friend struct SoftSequence
#define EVG_SEQ_RAM_SW_TRIG
std::vector< epicsUInt64 > times_t
User implementation hook.
#define OBJECT_END(klass)
#define EVG_SEQ_RAM_SRC_MASK
epicsUInt32 getEventCode(epicsUInt8 *arr, epicsUInt32 count) const
#define EVG_SEQ_RAM_REPEAT_MASK
epicsUInt32 getTimestampResolution() const
#define EVG_SEQ_RAM_DISABLE
virtual double getClkFreq() const =0
void setTrigSrc(epicsUInt32 src)
const std::string & name() const
volatile void *const ctrlreg
volatile void *const *const rambase
struct SoftSequence::Config committed
#define EVG_SEQ_RAM_NORMAL
IOSCANPVT stateChange() const
IOSCANPVT counterStartScan() const
epicsUInt32 getTrigSrcCt() const
void addHW(unsigned i, volatile void *ctrl, volatile void *ram)
void setTimestampResolution(epicsUInt32 val)
std::string getErr() const
OBJECT_PROP2("TIMES", &SoftSequence::getTimestamp, &SoftSequence::setTimestamp)
#define EVG_SEQ_RAM_SINGLE
void setTimestamp(const double *arr, epicsUInt32 count)
std::vector< epicsUInt8 > codes_t
SoftSequence * loaded
current association. may be NULL
virtual void unlock() const
SeqHW(SeqManager *o, unsigned i, volatile void *ctrl, volatile void *ram)
epicsUInt32 ctrlreg_hw
current in HW. either same as _user or trigger disabled
epicsUInt32 ctrlreg_user
user requested (based on commited sequence)
epicsUInt32 getTimestamp(double *arr, epicsUInt32 count) const
epicsUInt32 numStart
Guarded by interruptLock only.
IOSCANPVT counterEndScan() const
SeqManager(const std::string &name, Type t)
virtual void lock() const
virtual void mapTriggerSrc(unsigned i, unsigned src)=0
void setEventCode(const epicsUInt8 *arr, epicsUInt32 count)