My Project
drvem.h
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * Copyright (c) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
5 * Copyright (c) 2022 Cosylab d.d.
6 * mrfioc2 is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
11  */
12 
13 #ifndef EVRMRML_H_INC
14 #define EVRMRML_H_INC
15 
16 #include "evr/evr.h"
17 
18 #include <string>
19 #include <vector>
20 #include <set>
21 #include <list>
22 #include <map>
23 #include <utility>
24 
25 #include <dbScan.h>
26 #include <epicsTime.h>
27 #include <epicsThread.h>
28 #include <epicsMessageQueue.h>
29 #include <callback.h>
30 #include <epicsMutex.h>
31 
32 #include "drvemInput.h"
33 #include "drvemOutput.h"
34 #include "drvemPrescaler.h"
35 #include "drvemPulser.h"
36 #include "drvemCML.h"
37 #include "drvemTSBuffer.h"
38 #include "delayModule.h"
39 #include "drvemRxBuf.h"
40 #include "mrmevrseq.h"
41 #include "mrmspi.h"
42 
43 #include "mrmGpio.h"
44 #include "mrmtimesrc.h"
45 #include "mrmDataBufTx.h"
46 #include "sfp.h"
47 #include "configurationInfo.h"
48 
49 class EVRMRM;
50 
51 struct eventCode {
52  epicsUInt8 code; // constant
53  EVRMRM* owner;
54 
55  // For efficiency events will only
56  // be mapped into the FIFO when this
57  // counter is non-zero.
58  size_t interested;
59 
60  epicsUInt32 last_sec;
61  epicsUInt32 last_evt;
62 
63  typedef std::set<EVRMRMTSBuffer*> tbufs_t;
64  tbufs_t tbufs;
65 
66  IOSCANPVT occured;
67 
68  typedef std::list<std::pair<EVR::eventCallback,void*> > notifiees_t;
69  notifiees_t notifiees;
70 
71  CALLBACK done_cb;
72  size_t waitingfor;
73  bool again;
74 
75  // UTAG associated to event
76 #ifdef DBR_UTAG
77  epicsUTag utag;
78 #endif
79  eventCode():owner(0), interested(0), last_sec(0)
80  ,last_evt(0), waitingfor(0), again(false)
81 #ifdef DBR_UTAG
82  ,utag(0)
83 #endif
84  {
85  scanIoInit(&occured);
86  // done_cb - initialized in EVRMRM::EVRMRM()
87  }
88 };
89 
94 class epicsShareClass EVRMRM : public mrf::ObjectInst<EVRMRM, EVR>,
95  public MRMSPI,
96  public TimeStampSource
97 {
99 public:
104  mutable epicsMutex evrLock;
105 
106  struct Config {
107  const char *model;
108  size_t nPul; // number of pulsers
109  size_t nPS; // number of prescalers
110  // # of outputs (Front panel, FP Universal, Rear transition module, Backplane)
111  size_t nOFP, nOFPUV, nORB, nOBack;
112  size_t nOFPDly; // # of slots== # of delay modules. Some of the FP Universals have GPIOs. Each FPUV==2 GPIO pins, 2 FPUVs in one slot = 4 GPIO pins. One dly module uses 4 GPIO pins.
113  // # of CML outputs
114  size_t nCML;
115  MRMCML::outkind kind;
116  // # of FP inputs
117  size_t nIFP;
118  };
119 
120  EVRMRM(const std::string& n, bus_configuration& busConfig,
121  const Config *c,
122  volatile unsigned char*,epicsUInt32);
123 
124  virtual ~EVRMRM();
125 private:
126  void cleanup();
127 public:
128 
129  virtual void lock() const OVERRIDE FINAL {evrLock.lock();}
130  virtual void unlock() const OVERRIDE FINAL {evrLock.unlock();};
131 
132  virtual std::string model() const OVERRIDE FINAL;
133  epicsUInt32 fpgaFirmware();
134  formFactor getFormFactor();
135  std::string formFactorStr();
136  virtual MRFVersion version() const OVERRIDE FINAL;
137 
138 
139  virtual bool enabled() const OVERRIDE FINAL;
140  virtual void enable(bool v) OVERRIDE FINAL;
141 
142  virtual bool mappedOutputState() const OVERRIDE FINAL;
143 
144  MRMGpio* gpio();
145 
146  virtual bool specialMapped(epicsUInt32 code, epicsUInt32 func) const OVERRIDE FINAL;
147  virtual void specialSetMap(epicsUInt32 code, epicsUInt32 func,bool) OVERRIDE FINAL;
148 
149  virtual double clock() const OVERRIDE FINAL
150  {SCOPED_LOCK(evrLock);return eventClock;}
151  virtual void clockSet(double) OVERRIDE FINAL;
152 
153  epicsUInt16 clockMode() const;
154  void clockModeSet(epicsUInt16 mode);
155 
156  virtual bool pllLocked() const OVERRIDE FINAL;
157 
158  virtual void setPLLBandwidth(epicsUInt16 pllBandwidth);
159  virtual epicsUInt16 getPLLBandwidth() const;
160 
161  virtual epicsUInt32 irqCount() const OVERRIDE FINAL {return count_hardware_irq;}
162 
163  virtual bool linkStatus() const OVERRIDE FINAL;
164  virtual IOSCANPVT linkChanged() const OVERRIDE FINAL{return IRQrxError;}
165  virtual epicsUInt32 recvErrorCount() const OVERRIDE FINAL{return count_recv_error;}
166 
167  virtual epicsUInt32 uSecDiv() const OVERRIDE FINAL;
168 
170  virtual bool extInhib() const OVERRIDE FINAL;
171  virtual void setExtInhib(bool) OVERRIDE FINAL;
172 
173  virtual epicsUInt32 tsDiv() const OVERRIDE FINAL
174  {SCOPED_LOCK(evrLock);return shadowCounterPS;}
175 
176  virtual void setSourceTS(TSSource) OVERRIDE FINAL;
177  virtual TSSource SourceTS() const OVERRIDE FINAL
178  {SCOPED_LOCK(evrLock);return shadowSourceTS;}
179  virtual double clockTS() const OVERRIDE FINAL;
180  virtual void clockTSSet(double) OVERRIDE FINAL;
181  virtual bool interestedInEvent(epicsUInt32 event,bool set) OVERRIDE FINAL;
182 
183  virtual bool TimeStampValid() const OVERRIDE FINAL;
184  virtual IOSCANPVT TimeStampValidEvent() const OVERRIDE FINAL {return timestampValidChange;}
185 
186  virtual bool getTimeStamp(epicsTimeStamp *ts,epicsUInt32 event) OVERRIDE FINAL;
187  virtual bool getTicks(epicsUInt32 *tks) OVERRIDE FINAL;
188  virtual IOSCANPVT eventOccurred(epicsUInt32 event) const OVERRIDE FINAL;
189  virtual void eventNotifyAdd(epicsUInt32, eventCallback, void*) OVERRIDE FINAL;
190  virtual void eventNotifyDel(epicsUInt32, eventCallback, void*) OVERRIDE FINAL;
191 
192  bool convertTS(epicsTimeStamp* ts);
193 
194  virtual epicsUInt16 dbus() const OVERRIDE FINAL;
195 
196  virtual epicsUInt32 heartbeatTIMOCount() const OVERRIDE FINAL {return count_heartbeat;}
197  virtual IOSCANPVT heartbeatTIMOOccured() const OVERRIDE FINAL {return IRQheartbeat;}
198 
199  virtual epicsUInt32 FIFOFullCount() const OVERRIDE FINAL
200  {SCOPED_LOCK(evrLock);return count_FIFO_overflow;}
201  virtual epicsUInt32 FIFOOverRate() const OVERRIDE FINAL
202  {SCOPED_LOCK(evrLock);return count_FIFO_sw_overrate;}
203  virtual epicsUInt32 FIFOEvtCount() const OVERRIDE FINAL {return count_fifo_events;}
204  virtual epicsUInt32 FIFOLoopCount() const OVERRIDE FINAL {return count_fifo_loops;}
205 #ifdef DBR_UTAG
206  virtual epicsUTag getUtag(const epicsUInt32 event) const OVERRIDE FINAL;
207  virtual void setUtag(epicsUTag tag, const epicsUInt32 event) OVERRIDE FINAL;
208 #endif
209  void enableIRQ(void);
210 
211  bool dcEnabled() const;
212  void dcEnable(bool v);
213  double dcTarget() const;
214  void dcTargetSet(double);
216  double dcRx() const;
218  double dcInternal() const;
219  epicsUInt32 dcStatusRaw() const;
220  epicsUInt32 topId() const;
221 
222  bool psPolarity() const;
223  void psPolaritySet(bool v);
224 
225  epicsUInt32 dummy() const { return 0; }
226  void setEvtCode(epicsUInt32 code) OVERRIDE FINAL;
227 
228  epicsUInt32 timeSrc() const;
229  void setTimeSrc(epicsUInt32 mode);
230 
231  static void isr(EVRMRM *evr, bool pci);
232  static void isr_pci(void*);
233  static void isr_vme(void*);
234  static void isr_poll(void*);
235 #if defined(__linux__) || defined(_WIN32)
236  const void *isrLinuxPvt;
237 #endif
238 
239  const Config * const conf;
240  volatile unsigned char * const base;
241  epicsUInt32 baselen;
242  mrmDataBufTx buftx;
243  mrmBufRx bufrx;
244  mrf::auto_ptr<SFP> sfp;
245 private:
246 
247  // Set by ISR
248  volatile epicsUInt32 count_recv_error;
249  volatile epicsUInt32 count_hardware_irq;
250  volatile epicsUInt32 count_heartbeat;
251  volatile epicsUInt32 count_fifo_events;
252  volatile epicsUInt32 count_fifo_loops;
253 
254  epicsUInt32 shadowIRQEna;
255 
256  // Guarded by evrLock
257  epicsUInt32 count_FIFO_overflow;
258 
259  // scanIoRequest() from ISR or callback
260  IOSCANPVT IRQmappedEvent; // Hardware mapped IRQ
261  IOSCANPVT IRQheartbeat; // Heartbeat timeout
262  IOSCANPVT IRQrxError; // Rx link state change
263  IOSCANPVT IRQfifofull; // Fifo overflow
264 
265  // Software events
266  IOSCANPVT timestampValidChange;
267 
268  // Set by ctor, not changed after
269 
270  typedef std::vector<MRMInput*> inputs_t;
271  inputs_t inputs;
272 
273  typedef std::map<std::pair<OutputType,epicsUInt32>,MRMOutput*> outputs_t;
274  outputs_t outputs;
275 
276  std::vector<DelayModule*> delays;
277 
278  typedef std::vector<MRMPreScaler*> prescalers_t;
279  prescalers_t prescalers;
280 
281  typedef std::vector<MRMPulser*> pulsers_t;
282  pulsers_t pulsers;
283 
284  typedef std::vector<MRMCML*> shortcmls_t;
285  shortcmls_t shortcmls;
286 
287  MRMGpio gpio_;
288 
289  mrf::auto_ptr<EvrSeqManager> seq;
290 
291  // run when FIFO not-full IRQ is received
292  void drain_fifo();
293  epicsThreadRunableMethod<EVRMRM, &EVRMRM::drain_fifo> drain_fifo_method;
294  epicsThread drain_fifo_task;
295  epicsMessageQueue drain_fifo_wakeup;
296  static void sentinel_done(CALLBACK*);
297 
298  epicsUInt32 count_FIFO_sw_overrate;
299 
300  eventCode events[256];
301 
302  // Buffer received
303  CALLBACK data_rx_cb;
304 
305  // Periodic callback to detect when link state goes from down to up
306  CALLBACK poll_link_cb;
307  static void poll_link(CALLBACK*);
308 
309  enum timeSrcMode_t {
310  Disable, // do nothing
311  External, // shift out TS on upstream when reset (125) received on downstream
312  SysClk, // generate reset (125) from software timer, shift out TS on upstream
313  } timeSrcMode;
314  /* in practice
315  * timeSrcMode!=Disable -> listen for 125, react by sending shift 0/1 codes
316  * timeSrcMode==SysClk -> send soft 125 events
317  */
318  CALLBACK timeSrc_cb;
319 
320  // Set by clockTSSet() with IRQ disabled
321  double stampClock;
322  TSSource shadowSourceTS;
323  epicsUInt32 shadowCounterPS;
324  double eventClock;
325 
326  epicsUInt32 timestampValid;
327  epicsUInt32 lastInvalidTimestamp;
328  epicsUInt32 lastValidTimestamp;
329  static void seconds_tick(void*, epicsUInt32);
330 
331  // bit map of which event #'s are mapped
332  // used as a safty check to avoid overloaded mappings
333  epicsUInt32 _mapped[256];
334 
335  void _map(epicsUInt8 evt, epicsUInt8 func) { _mapped[evt] |= 1<<(func); }
336  void _unmap(epicsUInt8 evt, epicsUInt8 func) { _mapped[evt] &= ~( 1<<(func) );}
337  bool _ismap(epicsUInt8 evt, epicsUInt8 func) const { return (_mapped[evt] & 1<<(func)) != 0; }
338 
339  friend struct EVRMRMTSBuffer;
340 }; // class EVRMRM
341 
342 #endif // EVRMRML_H_INC
Modular Register Map Event Receivers.
Definition: drvem.h:97
epicsMutex evrLock
Guards access to instance All callers must take this lock before any operations on this object.
Definition: drvem.h:104
Definition: drvemOutput.h:27
User implementation hook.
Definition: object.h:460
Definition: mrmDataBufTx.h:20