mrfioc2  2.3.0
drvemPulser.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * mrfioc2 is distributed subject to a Software License Agreement found
5 * in file LICENSE that is included with this distribution.
6 \*************************************************************************/
7 /*
8  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
9  */
10 
11 #include "evrRegMap.h"
12 #include "drvem.h"
13 
14 #include <stdexcept>
15 #include <cstring>
16 
17 #include <errlog.h>
18 #include <dbDefs.h>
19 #include <epicsMath.h>
20 
21 #include "mrfCommonIO.h"
22 #include "mrfBitOps.h"
23 
24 
25 
26 #include "drvemPulser.h"
27 
28 MRMPulser::MRMPulser(const std::string& n, epicsUInt32 i, EVRMRM& o)
29  :base_t(n)
30  ,id(i)
31  ,owner(o)
32 {
33  if(id>31)
34  throw std::out_of_range("pulser id is out of range");
35 
36  std::memset(&this->mapped, 0, NELEMENTS(this->mapped));
37 }
38 
39 void MRMPulser::lock() const{owner.lock();};
40 void MRMPulser::unlock() const{owner.unlock();};
41 
42 bool
44 {
45  return READ32(owner.base, PulserCtrl(id)) & PulserCtrl_ena;
46 }
47 
48 void
50 {
51  if(s)
52  BITSET(NAT,32,owner.base, PulserCtrl(id),
54  else
55  BITCLR(NAT,32,owner.base, PulserCtrl(id),
57 }
58 
59 void
60 MRMPulser::setDelayRaw(epicsUInt32 v)
61 {
62  WRITE32(owner.base, PulserDely(id), v);
63 }
64 
65 void
67 {
68  double scal=double(prescaler());
69  if (scal<=0) scal=1;
70  double clk=owner.clock(); // in MHz. MTicks/second
71 
72  epicsUInt32 ticks=roundToUInt((v*clk)/scal);
73 
74  setDelayRaw(ticks);
75 }
76 
77 epicsUInt32
79 {
80  return READ32(owner.base,PulserDely(id));
81 }
82 
83 double
85 {
86  double scal=double(prescaler());
87  double ticks=double(delayRaw());
88  double clk=owner.clock(); // in MHz. MTicks/second
89  if (scal<=0) scal=1;
90 
91  return (ticks*scal)/clk;
92 }
93 
94 void
95 MRMPulser::setWidthRaw(epicsUInt32 v)
96 {
97  WRITE32(owner.base, PulserWdth(id), v);
98 }
99 
100 void
102 {
103  double scal=double(prescaler());
104  double clk=owner.clock(); // in MHz. MTicks/second
105  if (scal<=0) scal=1;
106 
107  epicsUInt32 ticks=roundToUInt((v*clk)/scal);
108 
109  setWidthRaw(ticks);
110 }
111 
112 epicsUInt32
114 {
115  return READ32(owner.base,PulserWdth(id));
116 }
117 
118 double
120 {
121  double scal=double(prescaler());
122  double ticks=double(widthRaw());
123  double clk=owner.clock(); // in MHz. MTicks/second
124  if (scal<=0) scal=1;
125 
126  return (ticks*scal)/clk;
127 }
128 
129 epicsUInt32
131 {
132  return READ32(owner.base,PulserScal(id));
133 }
134 
135 void
137 {
138  WRITE32(owner.base, PulserScal(id), v);
139 }
140 
141 bool
143 {
144  return (READ32(owner.base, PulserCtrl(id)) & PulserCtrl_pol) != 0;
145 }
146 
147 void
149 {
150  if(s)
151  BITSET(NAT,32,owner.base, PulserCtrl(id), PulserCtrl_pol);
152  else
153  BITCLR(NAT,32,owner.base, PulserCtrl(id), PulserCtrl_pol);
154 }
155 
156 epicsUInt32 MRMPulser::enables() const
157 {
158  return (READ32(owner.base, PulserCtrl(id)) & PulserCtrl_enables)>>PulserCtrl_enables_shift;
159 }
160 
161 void MRMPulser::setEnables(epicsUInt32 inps)
162 {
163  epicsUInt32 reg = READ32(owner.base, PulserCtrl(id));
164 
165  inps <<= PulserCtrl_enables_shift;
166  inps &= PulserCtrl_enables;
167 
168  reg &= ~(PulserCtrl_enables);
169 
170  WRITE32(owner.base, PulserCtrl(id), reg|inps);
171 
172  epicsUInt32 rereg = READ32(owner.base, PulserCtrl(id));
173 
174  if((rereg&PulserCtrl_enables)!=inps)
175  throw std::runtime_error("FW doesn't support Pulser enable-gates");
176 }
177 
178 epicsUInt32 MRMPulser::masks() const
179 {
180  return (READ32(owner.base, PulserCtrl(id)) & PulserCtrl_masks)>>PulserCtrl_masks_shift;
181 }
182 
183 void MRMPulser::setMasks(epicsUInt32 inps)
184 {
185  epicsUInt32 reg = READ32(owner.base, PulserCtrl(id));
186 
187  inps <<= PulserCtrl_masks_shift;
188  inps &= PulserCtrl_masks;
189 
190  reg &= ~(PulserCtrl_masks);
191 
192  WRITE32(owner.base, PulserCtrl(id), reg|inps);
193 
194  epicsUInt32 rereg = READ32(owner.base, PulserCtrl(id));
195 
196  if((rereg&PulserCtrl_masks)!=inps)
197  throw std::runtime_error("FW doesn't support Pulser masking");
198 }
199 
201 MRMPulser::mappedSource(epicsUInt32 evt) const
202 {
203  if(evt>255)
204  throw std::out_of_range("Event code is out of range");
205 
206  if(evt==0)
207  return MapType::None;
208 
209  epicsUInt32 map[3];
210 
211  map[0]=READ32(owner.base, MappingRam(0,evt,Trigger));
212  map[1]=READ32(owner.base, MappingRam(0,evt,Set));
213  map[2]=READ32(owner.base, MappingRam(0,evt,Reset));
214 
215  epicsUInt32 pmask=1<<id, insanity=0;
216 
218 
219  if(map[0]&pmask){
220  ret=MapType::Trigger;
221  insanity++;
222  }
223  if(map[1]&pmask){
224  ret=MapType::Set;
225  insanity++;
226  }
227  if(map[2]&pmask){
228  ret=MapType::Reset;
229  insanity++;
230  }
231  if(insanity>1){
232  errlogPrintf("EVR %s pulser #%d code %02x maps too many actions %08x %08x %08x\n",
233  owner.name().c_str(),id,evt,map[0],map[1],map[2]);
234  }
235 
236  if( (ret==MapType::None) ^ _ismap(evt) ){
237  errlogPrintf("EVR %s pulser #%d code %02x mapping (%08x %08x %08x) is out of sync with view (%d)\n",
238  owner.name().c_str(),id,evt,map[0],map[1],map[2],_ismap(evt));
239  }
240 
241  return ret;
242 }
243 
244 void
245 MRMPulser::sourceSetMap(epicsUInt32 evt,MapType::type action)
246 {
247  if(evt>255)
248  throw std::out_of_range("Event code is out of range");
249 
250  if(evt==0)
251  return;
252 
253  epicsUInt32 pmask=1<<id;
254 
255  if( (action!=MapType::None) && _ismap(evt) )
256  throw std::runtime_error("Ignore request for duplicate mapping");
257 
258  if(action!=MapType::None)
259  _map(evt);
260  else
261  _unmap(evt);
262 
263  if(action==MapType::Trigger)
264  BITSET(NAT,32, owner.base, MappingRam(0,evt,Trigger), pmask);
265  else
266  BITCLR(NAT,32, owner.base, MappingRam(0,evt,Trigger), pmask);
267 
268  if(action==MapType::Set)
269  BITSET(NAT,32, owner.base, MappingRam(0,evt,Set), pmask);
270  else
271  BITCLR(NAT,32, owner.base, MappingRam(0,evt,Set), pmask);
272 
273  if(action==MapType::Reset)
274  BITSET(NAT,32, owner.base, MappingRam(0,evt,Reset), pmask);
275  else
276  BITCLR(NAT,32, owner.base, MappingRam(0,evt,Reset), pmask);
277 }
278 
#define BITCLR(ord, len, base, offset, mask)
Definition: mrfBitOps.h:26
#define PulserCtrl_mtrg
Definition: evrRegMap.h:208
#define READ32(base, offset)
Definition: mrfCommonIO.h:114
virtual double clock() const OVERRIDE FINAL
Definition: drvem.h:141
volatile unsigned char *const base
Definition: drvem.h:223
epicsUInt32 masks() const
virtual epicsUInt32 delayRaw() const OVERRIDE FINAL
Definition: drvemPulser.cpp:78
#define PulserCtrl_ena
Definition: evrRegMap.h:207
virtual void enable(bool) OVERRIDE FINAL
Definition: drvemPulser.cpp:49
OBJECT_PROP2("Masks", &MRMPulser::masks, &MRMPulser::setMasks)
virtual double width() const OVERRIDE FINAL
virtual void setDelayRaw(epicsUInt32) OVERRIDE FINAL
Definition: drvemPulser.cpp:60
#define PulserCtrl_pol
Definition: evrRegMap.h:211
virtual void setPrescaler(epicsUInt32) OVERRIDE FINAL
#define OBJECT_BEGIN2(klass, Base)
Definition: object.h:507
#define PulserCtrl_enables
Definition: evrRegMap.h:205
virtual epicsUInt32 prescaler() const OVERRIDE FINAL
Modular Register Map Event Receivers.
Definition: drvem.h:86
virtual void unlock() const OVERRIDE FINAL
Definition: drvemPulser.cpp:40
virtual epicsUInt32 widthRaw() const OVERRIDE FINAL
virtual bool enabled() const OVERRIDE FINAL
Definition: drvemPulser.cpp:43
virtual void setDelay(double) OVERRIDE FINAL
Definition: drvemPulser.cpp:66
virtual bool polarityInvert() const OVERRIDE FINAL
virtual void setWidth(double) OVERRIDE FINAL
virtual void lock() const OVERRIDE FINAL
Definition: drvem.h:121
A programmable delay unit.
Definition: pulser.h:38
virtual MapType::type mappedSource(epicsUInt32 src) const OVERRIDE FINAL
What action is source &#39;src&#39; mapped to?
MRMPulser(const std::string &n, epicsUInt32, EVRMRM &)
Definition: drvemPulser.cpp:28
#define PulserCtrl_enables_shift
Definition: evrRegMap.h:206
#define PulserCtrl_mset
Definition: evrRegMap.h:209
#define OBJECT_END(klass)
Definition: object.h:523
#define PulserCtrl_masks
Definition: evrRegMap.h:203
type
Definition: pulser.h:21
virtual void sourceSetMap(epicsUInt32 src, MapType::type action) OVERRIDE FINAL
Set mapping of source &#39;src&#39;.
void setEnables(epicsUInt32 inps)
virtual void setPolarityInvert(bool) OVERRIDE FINAL
const std::string & name() const
Definition: object.h:393
virtual void lock() const OVERRIDE FINAL
Definition: drvemPulser.cpp:39
#define PulserCtrl_masks_shift
Definition: evrRegMap.h:204
epicsUInt32 roundToUInt(double val, epicsUInt32 max)
Definition: mrfCommon.cpp:43
void setMasks(epicsUInt32 inps)
#define BITSET(ord, len, base, offset, mask)
Definition: mrfBitOps.h:21
epicsUInt32 enables() const
#define PulserCtrl_mrst
Definition: evrRegMap.h:210
virtual double delay() const OVERRIDE FINAL
Definition: drvemPulser.cpp:84
#define WRITE32(base, offset, value)
Definition: mrfCommonIO.h:119
virtual void setWidthRaw(epicsUInt32) OVERRIDE FINAL
Definition: drvemPulser.cpp:95
virtual void unlock() const OVERRIDE FINAL
Definition: drvem.h:122