mrfioc2  2.3.0
mrmSeq.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2016 Michael Davidsaver
3 * mrfioc2 is distributed subject to a Software License Agreement found
4 * in file LICENSE that is included with this distribution.
5 \*************************************************************************/
6 
7 #if defined(__rtems__)
8 # include <rtems.h>
9 #endif
10 
11 #include <stdio.h>
12 
13 #include <epicsMath.h>
14 #include <epicsMutex.h>
15 #include <errlog.h>
16 
17 #include <mrfCommonIO.h>
18 
19 #include "mrmSeq.h"
20 
21 #include <epicsExport.h>
22 
23 #define EVG_SEQ_RAM_RUNNING 0x02000000 /* Sequence RAM is Running (read only) */
24 #define EVG_SEQ_RAM_ENABLED 0x01000000 /* Sequence RAM is Enabled (read only) */
25 
26 //TODO: external enable/trigger bits and hanlding?
27 #define EVG_SEQ_RAM_SW_TRIG 0x00200000 /* Sequence RAM Software Trigger Bit */
28 #define EVG_SEQ_RAM_RESET 0x00040000 /* Sequence RAM Reset */
29 #define EVG_SEQ_RAM_DISABLE 0x00020000 /* Sequence RAM Disable (and stop) */
30 #define EVG_SEQ_RAM_ARM 0x00010000 /* Sequence RAM Enable/Arm */
31 
32 #define EVG_SEQ_RAM_WRITABLE_MASK 0x00ffffff
33 #define EVG_SEQ_RAM_REPEAT_MASK 0x00180000 /* Sequence RAM Repeat Mode Mask */
34 #define EVG_SEQ_RAM_NORMAL 0x00000000 /* Normal Mode: Repeat every trigger */
35 #define EVG_SEQ_RAM_SINGLE 0x00100000 /* Single-Shot Mode: Disable on completion */
36 #define EVG_SEQ_RAM_RECYCLE 0x00080000 /* Continuous Mode: Repeat on completion */
37 
38 #define EVG_SEQ_RAM_SRC_MASK 0x000000ff
39 
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)
44 #else
45 # define DEBUG(LVL, ARGS) do{if(SeqManagerDebug>=(LVL)) {printf ARGS ;}}while(0)
46 #endif
47 
48 namespace {
49 
50 enum RunMode {Normal=0, Single=2};
51 
52 }//namespace
53 
54 struct SoftSequence;
55 
56 struct SeqHW
57 {
58  SeqManager * const owner;
59  const unsigned idx;
60  volatile void * const ctrlreg,
61  * const rambase;
62 
63  // guarded by interruptLock
64 
68  bool running;
69 
70  epicsUInt32 ctrlreg_user,
71  ctrlreg_hw;
72 
74  unsigned i,
75  volatile void *ctrl,
76  volatile void *ram)
77  :owner(o)
78  ,idx(i)
79  ,ctrlreg(ctrl)
80  ,rambase(ram)
81  ,loaded(0)
82  ,running(false)
83  ,ctrlreg_user(0u)
84  ,ctrlreg_hw(0u)
85  {
86  switch(owner->type) {
88  ctrlreg_user |= 31;
89  break;
91  ctrlreg_user |= 63;
92  break;
93  default:
94  return;
95  }
96  ctrlreg_hw = ctrlreg_user;
97 
98  nat_iowrite32(ctrlreg, ctrlreg_hw | EVG_SEQ_RAM_RESET);
99  }
100 
101  // call with interruptLock
102  void arm()
103  {
104  ctrlreg_hw = ctrlreg_user;
105  nat_iowrite32(ctrlreg, ctrlreg_hw | EVG_SEQ_RAM_ARM);
106  }
107 
108  // call with interruptLock
109  bool disarm()
110  {
111 
112  // EVG_SEQ_RAM_DISABLE is really "stop"
113  // to avoid aborting a potentially running sequencer, switch the trigger source to disable
114 
115  ctrlreg_hw &= ~(EVG_SEQ_RAM_SRC_MASK);
116 
117  switch(owner->type) {
118  case SeqManager::TypeEVG:
119  ctrlreg_hw |= 31;
120  break;
121  case SeqManager::TypeEVR:
122  ctrlreg_hw |= 63;
123  break;
124  }
125 
126  nat_iowrite32(ctrlreg, ctrlreg_hw);
127  bool isrun = nat_ioread32(ctrlreg) & EVG_SEQ_RAM_RUNNING;
128 
129  return isrun;
130  }
131 };
132 
133 struct SoftSequence : public mrf::ObjectInst<SoftSequence>
134 {
136 
137  SoftSequence(SeqManager *o, const std::string& name);
138  virtual ~SoftSequence();
139 
140  virtual void lock() const { mutex.lock(); }
141  virtual void unlock() const { mutex.unlock(); }
142 
143  std::string getErr() const { SCOPED_LOCK(mutex); return last_err; }
144  IOSCANPVT getErrScan() const { return onErr; }
145 
146  epicsUInt32 getTimestampResolution() const
147  {
148  SCOPED_LOCK(mutex);
149  return timeScale;
150  }
151  void setTimestampResolution(epicsUInt32 val)
152  {
153  {
154  SCOPED_LOCK(mutex);
155  timeScale = val;
156  }
157  DEBUG(4, ("Set time scale\n"));
158  scanIoRequest(changed);
159  }
160 
161 private:
162  double getTimeScale() const
163  {
164  double tmult = 1.0;
165  SCOPED_LOCK(mutex);
166  if(timeScale) {
167  double freq = owner->getClkFreq(); // in ticks/sec
168  /* tscale==1 -> seconds
169  * tscale==1000 -> milliseconds
170  * ...
171  */
172  tmult = freq/timeScale;
173  }
174  return tmult;
175  }
176 public:
177 
178  // dset actions
179  // update scratch
180  // read back committed
181 
182  void setTimestamp(const double *arr, epicsUInt32 count)
183  {
184  const double tmult = getTimeScale();
185  times_t times(count);
186  // check for monotonic
187  // TODO: not handling overflow (HW supports controlled rollover w/ special 0xffffffff times)
188  for(epicsUInt32 i=0; i<count; i++)
189  {
190  if(!finite(arr[i]) || arr[i]<0.0)
191  throw std::runtime_error("times must be finite >=0");
192 
193  times[i] = (arr[i]*tmult)+0.5;
194 
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");
199  }
200  {
201  SCOPED_LOCK(mutex);
202  scratch.times.swap(times);
203  is_committed = false;
204  }
205  DEBUG(4, ("Set times\n"));
206  scanIoRequest(changed);
207  }
208 
209  epicsUInt32 getTimestamp(double* arr, epicsUInt32 count) const
210  {
211  SCOPED_LOCK(mutex);
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;
216  }
217  return ret;
218  }
219 
220  void setEventCode(const epicsUInt8* arr, epicsUInt32 count)
221  {
222  codes_t codes(count);
223  std::copy(arr,
224  arr+count,
225  codes.begin());
226  {
227  SCOPED_LOCK(mutex);
228  scratch.codes.swap(codes);
229  is_committed = false;
230  }
231  DEBUG(4, ("Set events\n"));
232  scanIoRequest(changed);
233  }
234 
235  epicsUInt32 getEventCode(epicsUInt8* arr, epicsUInt32 count) const
236  {
237  SCOPED_LOCK(mutex);
238  epicsUInt32 ret = std::min(size_t(count), committed.codes.size());
239  std::copy(committed.codes.begin(),
240  committed.codes.begin()+ret,
241  arr);
242  return ret;
243  }
244 
245  void setTrigSrc(epicsUInt32 src)
246  {
247  DEBUG(4, ("Setting trig src %x\n", (unsigned)src));
248  {
249  SCOPED_LOCK(mutex);
250  scratch.src = src;
251  is_committed = false;
252  }
253  DEBUG(4, ("Set trig src %x\n", (unsigned)src));
254  scanIoRequest(changed);
255  }
256 
257  epicsUInt32 getTrigSrcCt() const
258  {
259  SCOPED_LOCK(mutex);
260  return committed.src;
261  }
262 
263  void setRunMode(epicsUInt32 mode)
264  {
265  switch(mode) {
266  case Single:
267  case Normal:
268  break;
269  default:
270  throw std::runtime_error("Unknown sequencer run mode");
271  }
272 
273  {
274  SCOPED_LOCK(mutex);
275  scratch.mode = (RunMode)mode;
276  is_committed = false;
277  }
278  DEBUG(4, ("Set run mode %u\n", (unsigned)mode));
279  scanIoRequest(changed);
280  }
281 
282  epicsUInt32 getRunModeCt() const
283  {
284  SCOPED_LOCK(mutex);
285  return committed.mode;
286  }
287 
288  // dset actions
289  // control/status
290 
291  bool isLoaded() const { SCOPED_LOCK(mutex); return hw; }
292  bool isEnabled() const { SCOPED_LOCK(mutex); return is_enabled; }
293  bool isCommited() const { SCOPED_LOCK(mutex); return is_committed; }
294  IOSCANPVT stateChange() const { return changed; }
295 
296  void load();
297  void unload();
298  void commit();
299  void enable();
300  void disable();
301  void softTrig();
302 
303  epicsUInt32 counterStart() const { interruptLock L; return numStart; }
304  IOSCANPVT counterStartScan() const { return onStart; }
305  epicsUInt32 counterEnd() const { interruptLock L; return numEnd; }
306  IOSCANPVT counterEndScan() const { return onEnd; }
307 
308  // internal
309 
310  void sync();
311 
312  SeqManager * const owner;
313 
318 
319  mutable epicsMutex mutex;
320 
321  typedef std::vector<epicsUInt64> times_t;
322  typedef std::vector<epicsUInt8> codes_t;
323 
324  struct Config {
325  times_t times;
326  codes_t codes;
328  epicsUInt32 src;
330  :mode(Single)
331  ,src(0x03000000) // code for Disable
332  {}
333  void swap(Config& o)
334  {
335  std::swap(times, o.times);
336  std::swap(codes, o.codes);
337  std::swap(mode, o.mode);
338  std::swap(src, o.src);
339  }
340  } scratch, // guarded by our mutex only
341  committed; // guarded by interruptLock only
342 
349  bool is_insync;
350 
352  epicsUInt32 numStart, numEnd;
353 
354  epicsUInt32 timeScale;
355 
356  IOSCANPVT changed, onStart, onEnd, onErr;
357 
358  std::string last_err;
359 };
360 
371  OBJECT_PROP1("DISABLE", &SoftSequence::disable);
372  OBJECT_PROP1("COMMITTED", &SoftSequence::isCommited);
375  OBJECT_PROP1("SOFT_TRIG", &SoftSequence::softTrig);
390 
391 SoftSequence::SoftSequence(SeqManager *o, const std::string& name)
392  :base_t(name)
393  ,owner(o)
394  ,hw(0)
395  ,is_enabled(false)
396  ,is_committed(false)
397  ,is_insync(false)
398  ,numStart(0u)
399  ,numEnd(0u)
400  ,timeScale(0u) // raw/ticks
401 {
402  scanIoInit(&changed);
403  scanIoInit(&onStart);
404  scanIoInit(&onEnd);
405  scanIoInit(&onErr);
406 }
407 
409 
411 {
412  DEBUG(3, ("SW Triggering\n") );
413  SCOPED_LOCK(mutex);
414  if(!hw || !is_enabled) {DEBUG(3, ("Skip\n")); return;}
415 
416  {
417  interruptLock L;
418  nat_iowrite32(hw->ctrlreg, hw->ctrlreg_hw | EVG_SEQ_RAM_SW_TRIG);
419  }
420  DEBUG(2, ("SW Triggered\n") );
421 }
422 
424 {
425  SCOPED_LOCK(mutex);
426  DEBUG(3, ("Loading %c\n", hw ? 'L' : 'U') );
427  if(hw) {DEBUG(3, ("Skip\n")); return;}
428 
429  // find unused SeqHW
430  {
431  interruptLock L;
432 
433  is_insync = false; // paranoia
434 
435  for(size_t i=0, N=owner->hw.size(); i<N; i++) {
436  SeqHW *temp = owner->hw[i];
437  if(temp && !temp->loaded) {
438  temp->loaded = this;
439  hw = temp;
440  break;
441  }
442  }
443 
444  if(hw) {
445  // paranoia: disable any external trigger mappings
446  owner->mapTriggerSrc(hw->idx, 0x02000000);
447 
448  if(!hw->disarm())
449  sync();
450  }
451  }
452 
453  if(!hw) {
454  last_err = "All HW Seq. in use";
455  scanIoRequest(onErr);
456  throw alarm_exception(MAJOR_ALARM, WRITE_ALARM);
457  }
458 
459  scanIoRequest(changed);
460  DEBUG(1, ("Loaded\n") );
461 }
462 
464 {
465  SCOPED_LOCK(mutex);
466  DEBUG(3, ("Unloading %c\n", hw ? 'L' : 'U') );
467 
468  if(!hw) {DEBUG(3, ("Skip\n")); return;}
469 
470  assert(hw->loaded=this);
471 
472  {
473  interruptLock L;
474 
475  hw->disarm();
476 
477  hw->loaded = NULL;
478  hw = NULL;
479 
480  is_insync = false;
481  }
482 
483  scanIoRequest(changed);
484  DEBUG(1, ("Unloaded\n") );
485 
486 }
487 
489 {
490  SCOPED_LOCK(mutex);
491  DEBUG(3, ("Committing %c\n", is_committed ? 'Y' : 'N') );
492 
493  if(is_committed) {DEBUG(3, ("Skip\n")); return;}
494 
495  // scratch.times already check for monotonic
496 
497  Config conf(scratch); // vector copies
498 
499  size_t buflen = std::min(conf.codes.size(),
500  conf.times.size());
501  conf.codes.resize(buflen);
502  conf.times.resize(buflen);
503 
504  // ensure presence of trailing end of sequence marker event 0x7f
505  if(conf.codes.empty() || conf.codes.back()!=0x7f)
506  {
507  if(!conf.times.empty() && conf.times.back()==0xffffffff)
508  throw std::runtime_error("Wow, input array is missing 0x7f and maxing out times");
509 
510  conf.codes.push_back(0x7f);
511 
512  if(conf.times.empty())
513  conf.times.push_back(0);
514  else
515  conf.times.push_back(conf.times.back()+1);
516  }
517 
518  if(conf.times.size()>2048)
519  throw std::runtime_error("Sequence too long");
520 
521  assert(!hw || hw->loaded==this);
522 
523  {
524  interruptLock L;
525  committed.swap(conf);
526  is_committed = true;
527  is_insync = false;
528 
529  if(hw && !hw->disarm())
530  sync();
531  }
532 
533  scanIoRequest(changed);
534  DEBUG(1, ("Committed\n") );
535 }
536 
538 {
539  SCOPED_LOCK(mutex);
540  DEBUG(3, ("Enabling %c\n", is_enabled ? 'Y' : 'N') );
541  if(is_enabled)
542  {DEBUG(3, ("Skip\n")); return;}
543 
544  is_enabled = true;
545 
546  if(hw) {
547  interruptLock I;
548 
549  hw->arm();
550  }
551  scanIoRequest(changed);
552  DEBUG(1, ("Enabled\n") );
553 }
554 
556 {
557  SCOPED_LOCK(mutex);
558  DEBUG(3, ("Disabling %c\n", is_enabled ? 'Y' : 'N') );
559  if(!is_enabled)
560  {DEBUG(3, ("Skip\n")); return;}
561 
562  is_enabled = false;
563 
564  if(hw) {
565  interruptLock L;
566  hw->disarm();
567  }
568 
569  scanIoRequest(changed);
570  DEBUG(1, ("Disabled\n") );
571 }
572 
573 // Called from ISR context
575 {
576  DEBUG(3, ("Syncing %c\n", is_insync ? 'Y' : 'N') );
577  if(is_insync)
578  {DEBUG(3, ("Skip\n")); return;}
579 
580  assert(hw);
581 
582  if(nat_ioread32(hw->ctrlreg)&EVG_SEQ_RAM_RUNNING) {
583  // we may still be _ENABLED at this point, but the trigger source is set to
584  // Disabled, so this makes no difference.
585  epicsInterruptContextMessage("SoftSequence::sync() while running\n");
586  return;
587  }
588 
589  // At this point the sequencer is not running and effectively disabled.
590  // From paranoia, reset it anyway
591  nat_iowrite32(hw->ctrlreg, hw->ctrlreg_hw | EVG_SEQ_RAM_RESET);
592 
593  hw->ctrlreg_user &= ~(EVG_SEQ_RAM_REPEAT_MASK|EVG_SEQ_RAM_SRC_MASK);
594 
595  switch(committed.mode) {
596  case Single:
597  hw->ctrlreg_user |= EVG_SEQ_RAM_SINGLE;
598  break;
599  case Normal:
600  hw->ctrlreg_user |= EVG_SEQ_RAM_NORMAL;
601  break;
602  }
603 
604  epicsUInt8 src;
605 
606  // default to disabled
607  switch(owner->type) {
608  case SeqManager::TypeEVG:
609  src = 31;
610  break;
611  case SeqManager::TypeEVR:
612  src = 63;
613  break;
614  default:
615  return;
616  }
617 
618  // paranoia: disable any external trigger mappings
619  owner->mapTriggerSrc(hw->idx, 0x02000000);
620 
621  // map trigger source codes
622  // MSB governs the type of mapping
623  switch(committed.src&0xff000000) {
624  case 0x00000000: // raw mapping
625  DEBUG(5, (" Raw mapping %x\n", committed.src));
626  // LSB is code
627  src = committed.src&0xff;
628  break;
629  case 0x01000000: // software trigger mapping
630  DEBUG(5, (" SW mapping %x\n", committed.src));
631  // ignore 0x00ffffff
632  switch(owner->type) {
633  case SeqManager::TypeEVG:
634  src = 17+hw->idx;
635  break;
636  case SeqManager::TypeEVR:
637  src = 61;
638  break;
639  }
640  break;
641  case 0x02000000: // external trigger
642  DEBUG(5, (" EXT mapping %x\n", committed.src));
644  // pass through to sub-class
645  owner->mapTriggerSrc(hw->idx, committed.src);
646  src = 24+hw->idx;
647  }
648  break;
649  case 0x03000000: // disable trigger
650  DEBUG(5, (" NO mapping %x\n", committed.src));
651  // use default
652  break;
653  default:
654  DEBUG(0, ("unknown sequencer trigger code %08x\n", (unsigned)committed.src));
655  break;
656  }
657  DEBUG(5, (" Trig Src %x\n", src));
658 
659  hw->ctrlreg_user |= src;
660 
661  // write out the RAM
662  volatile epicsUInt32 *ram = static_cast<volatile epicsUInt32 *>(hw->rambase);
663  for(size_t i=0, N=committed.codes.size(); i<N; i++)
664  {
665  nat_iowrite32(ram++, committed.times[i]);
666  nat_iowrite32(ram++, committed.codes[i]);
667  if(committed.codes[i]==0x7f)
668  break;
669  }
670 
671  {
672  epicsUInt32 ctrl = hw->ctrlreg_hw = hw->ctrlreg_user;
673  if(is_enabled)
674  ctrl |= EVG_SEQ_RAM_ARM;
675  else
676  ctrl |= EVG_SEQ_RAM_DISABLE; // paranoia
677 
678  DEBUG(3, (" SeqCtrl %x\n", ctrl));
679  nat_iowrite32(hw->ctrlreg, ctrl);
680  }
681 
682  is_insync = true;
683  DEBUG(3, ("In Sync\n") );
684 }
685 
686 
687 SeqManager::SeqManager(const std::string &name, Type t)
688  :base_t(name)
689  ,type(t)
690 {
691  switch(type) {
692  case TypeEVG:
693  case TypeEVR:
694  break;
695  default:
696  throw std::invalid_argument("Bad SeqManager type");
697  }
698 }
699 
701 
703 SeqManager::buildSW(const std::string& name, const std::string& klass, const mrf::Object::create_args_t& args)
704 {
705  (void)klass;
706 
707  mrf::Object::create_args_t::const_iterator it=args.find("PARENT");
708  if(it==args.end())
709  throw std::runtime_error("No PARENT= (EVG) specified");
710 
711  mrf::Object *mgrobj = mrf::Object::getObject(it->second);
712  if(!mgrobj)
713  throw std::runtime_error("No such PARENT object");
714 
715  SeqManager *mgr = dynamic_cast<SeqManager*>(mgrobj);
716  if(!mgr)
717  throw std::runtime_error("PARENT is not a SeqManager");
718 
719  return new SoftSequence(mgr, name);
720 }
721 
722 // Called from ISR context
724 {
725  assert(i<hw.size());
726  SeqHW* HW = hw[i];
727  HW->running = true;
728 
729  SoftSequence *seq = HW->loaded;
730 
731  if(!seq) return;
732 
733  seq->numStart++;
734 
735  scanIoRequest(seq->onStart);
736 }
737 
738 // Called from ISR context
740 {
741  assert(i<hw.size());
742  SeqHW* HW = hw[i];
743 
744  HW->running = false;
745 
746  SoftSequence *seq = HW->loaded;
747 
748  if(!seq) return;
749 
750  if(seq->committed.mode==Single) {
751  seq->is_enabled = false;
752  }
753 
754  seq->numEnd++;
755 
756  scanIoRequest(seq->onEnd);
757 
758  if(!seq->is_insync)
759  seq->sync();
760 
761  if(seq->committed.mode==Single)
762  scanIoRequest(seq->changed);
763 }
764 
765 void SeqManager::addHW(unsigned i,
766  volatile void *ctrl,
767  volatile void *ram)
768 {
769  hw.resize(std::max(hw.size(), size_t(i+1)), 0);
770  assert(!hw[i]);
771  hw[i] = new SeqHW(this, i, ctrl, ram);
772 }
773 
775 
779 
780 extern "C" {
782 }
SeqHW * hw
Definition: mrmSeq.cpp:317
const Type type
Definition: mrmSeq.h:36
bool is_enabled
Whether user has requested enable.
Definition: mrmSeq.cpp:344
std::map< std::string, std::string > create_args_t
Definition: object.h:422
mrf::ObjectInst< SoftSequence > base_t
Definition: mrmSeq.cpp:135
OBJECT_FACTORY(SeqManager::buildSW)
bool is_insync
Definition: mrmSeq.cpp:349
bool disarm()
Definition: mrmSeq.cpp:109
bool isLoaded() const
Definition: mrmSeq.cpp:291
bool isEnabled() const
Definition: mrmSeq.cpp:292
void softTrig()
Definition: mrmSeq.cpp:410
#define DEBUG(LVL, ARGS)
Definition: mrmSeq.cpp:45
#define EVG_SEQ_RAM_RESET
Definition: mrmSeq.cpp:28
virtual ~SeqManager()
Definition: mrmSeq.cpp:700
bool is_committed
clear when scratch and commited sequences differ
Definition: mrmSeq.cpp:346
INLINE void nat_iowrite32(volatile void *addr, epicsUInt32 val)
Definition: mrfIoOpsDef.h:55
void swap(Config &o)
Definition: mrmSeq.cpp:333
void sync()
Definition: mrmSeq.cpp:574
epicsUInt32 src
Definition: mrmSeq.cpp:328
void doStartOfSequence(unsigned i)
Call from ISR.
Definition: mrmSeq.cpp:723
Definition: evrdump.c:37
epicsUInt32 counterStart() const
Definition: mrmSeq.cpp:303
void disable()
Definition: mrmSeq.cpp:555
epicsExportAddress(int, SeqManagerDebug)
epicsMutex mutex
Definition: mrmSeq.cpp:319
#define EVG_SEQ_RAM_RUNNING
Definition: mrmSeq.cpp:23
int SeqManagerDebug
Definition: mrmSeq.cpp:774
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
Definition: mrfIoOpsDef.h:48
epicsUInt32 counterEnd() const
Definition: mrmSeq.cpp:305
SeqManager *const owner
Definition: mrmSeq.cpp:58
bool running
between SoS and EoS
Definition: mrmSeq.cpp:68
static mrf::Object * buildSW(const std::string &name, const std::string &klass, const mrf::Object::create_args_t &args)
Definition: mrmSeq.cpp:703
epicsMutex mutex
Definition: spi.cpp:56
Base object inspection.
Definition: object.h:378
RunMode
Definition: mrmSeq.cpp:50
epicsUInt32 getRunModeCt() const
Definition: mrmSeq.cpp:282
static Object * getObject(const std::string &name)
Definition: object.cpp:107
void setRunMode(epicsUInt32 mode)
Definition: mrmSeq.cpp:263
#define OBJECT_BEGIN(klass)
Definition: object.h:513
OBJECT_PROP1("ERROR", &SoftSequence::getErr)
IOSCANPVT getErrScan() const
Definition: mrmSeq.cpp:144
void doEndOfSequence(unsigned i)
Call from ISR.
Definition: mrmSeq.cpp:739
friend struct SoftSequence
Definition: mrmSeq.h:71
#define EVG_SEQ_RAM_SW_TRIG
Definition: mrmSeq.cpp:27
void enable()
Definition: mrmSeq.cpp:537
std::vector< epicsUInt64 > times_t
Definition: mrmSeq.cpp:321
User implementation hook.
Definition: object.h:459
void commit()
Definition: mrmSeq.cpp:488
#define OBJECT_END(klass)
Definition: object.h:523
void arm()
Definition: mrmSeq.cpp:102
#define EVG_SEQ_RAM_SRC_MASK
Definition: mrmSeq.cpp:38
epicsUInt32 getEventCode(epicsUInt8 *arr, epicsUInt32 count) const
Definition: mrmSeq.cpp:235
virtual ~SoftSequence()
Definition: mrmSeq.cpp:408
epicsUInt32 numEnd
Definition: mrmSeq.cpp:352
#define EVG_SEQ_RAM_REPEAT_MASK
Definition: mrmSeq.cpp:33
IOSCANPVT changed
Definition: mrmSeq.cpp:356
epicsUInt32 getTimestampResolution() const
Definition: mrmSeq.cpp:146
#define EVG_SEQ_RAM_DISABLE
Definition: mrmSeq.cpp:29
#define EVG_SEQ_RAM_ARM
Definition: mrmSeq.cpp:30
virtual double getClkFreq() const =0
epicsUInt32 timeScale
Definition: mrmSeq.cpp:354
void setTrigSrc(epicsUInt32 src)
Definition: mrmSeq.cpp:245
const std::string & name() const
Definition: object.h:393
void load()
Definition: mrmSeq.cpp:423
volatile void *const ctrlreg
Definition: mrmSeq.cpp:60
volatile void *const *const rambase
Definition: mrmSeq.cpp:60
struct SoftSequence::Config committed
const unsigned idx
Definition: mrmSeq.cpp:59
#define EVG_SEQ_RAM_NORMAL
Definition: mrmSeq.cpp:34
IOSCANPVT stateChange() const
Definition: mrmSeq.cpp:294
IOSCANPVT counterStartScan() const
Definition: mrmSeq.cpp:304
epicsUInt32 getTrigSrcCt() const
Definition: mrmSeq.cpp:257
void addHW(unsigned i, volatile void *ctrl, volatile void *ram)
Definition: mrmSeq.cpp:765
void setTimestampResolution(epicsUInt32 val)
Definition: mrmSeq.cpp:151
std::string getErr() const
Definition: mrmSeq.cpp:143
OBJECT_PROP2("TIMES", &SoftSequence::getTimestamp, &SoftSequence::setTimestamp)
Definition: mrmSeq.cpp:56
IOSCANPVT onEnd
Definition: mrmSeq.cpp:356
#define EVG_SEQ_RAM_SINGLE
Definition: mrmSeq.cpp:35
void unload()
Definition: mrmSeq.cpp:463
void setTimestamp(const double *arr, epicsUInt32 count)
Definition: mrmSeq.cpp:182
std::vector< epicsUInt8 > codes_t
Definition: mrmSeq.cpp:322
SeqManager *const owner
Definition: mrmSeq.cpp:312
SoftSequence * loaded
current association. may be NULL
Definition: mrmSeq.cpp:66
virtual void unlock() const
Definition: mrmSeq.cpp:141
SeqHW(SeqManager *o, unsigned i, volatile void *ctrl, volatile void *ram)
Definition: mrmSeq.cpp:73
epicsUInt32 ctrlreg_hw
current in HW. either same as _user or trigger disabled
Definition: mrmSeq.cpp:70
std::string last_err
Definition: mrmSeq.cpp:358
epicsUInt32 ctrlreg_user
user requested (based on commited sequence)
Definition: mrmSeq.cpp:70
IOSCANPVT onStart
Definition: mrmSeq.cpp:356
epicsUInt32 getTimestamp(double *arr, epicsUInt32 count) const
Definition: mrmSeq.cpp:209
epicsUInt32 numStart
Guarded by interruptLock only.
Definition: mrmSeq.cpp:352
IOSCANPVT counterEndScan() const
Definition: mrmSeq.cpp:306
SeqManager(const std::string &name, Type t)
Definition: mrmSeq.cpp:687
bool isCommited() const
Definition: mrmSeq.cpp:293
virtual void lock() const
Definition: mrmSeq.cpp:140
virtual void mapTriggerSrc(unsigned i, unsigned src)=0
void setEventCode(const epicsUInt8 *arr, epicsUInt32 count)
Definition: mrmSeq.cpp:220