ICP  1
sim_detector_card.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
3 #include "sim_detector_card.h"
4 #include "vme_simulation.h"
5 #include "isisvme.h"
6 #include "dae_events.h"
7 
8 #define DET_MEM_LEN (32*1024*1024) // 128Mb
9 //#define DET_MEM_LEN (16*1024*1024) // 64Mb
10 
11 template <class DetCardPolicy>
13 
14 template <class DetCardPolicy>
15 SIMDetectorCard<DetCardPolicy>::SIMDetectorCard(int position, VMESimulationIface* vme, bool shared, FaultMode fault_mode, bool neutron_data, DAEstatus& status) :
16  SIMDAE2Card(position, vme, (1 << 31), false, Working, status)
17 {
18  setLoggerName("SIMDetectorCard");
19  m_neutron_data = neutron_data;
20  m_type = DetCard;
21  if (shared)
22  {
23  if (m_shared_detMemory == NULL)
24  {
26  }
28  }
29  else
30  {
32  }
33  m_poslutMemory = new isisU32_t[DCPOSLUTSIZE];
34  m_tcglutMemory = new isisU32_t[DCTCGLUTSIZE];
35  isisU32_t* tcg_access = NULL;
36  if (isRegisterUsed(DCTAC))
37  {
38  tcg_access = &m_tcgAccessRegister;
39  addMapping(ISISVME::TransferIORegisterSpace, DCTAC, 1, &m_tcgAccessRegister, "", true, true, NULL, 0, false, false, fault_mode);
40  }
41  addMapping(ISISVME::TransferIORegisterSpace, DCTCGTBL, 1, &m_tcgTimeBinLimitRegister, "", true, true, NULL, 0, false, false, fault_mode);
42 // addMapping(ISISVME::TransferIORegisterSpace, DCTCGLUT, DCTCGLUTSIZE, m_tcglutMemory, "", true, true, tcg_access, DCTTCGLUT, false, false, fault_mode);
43  addMapping(ISISVME::TransferLUTSpace, DCTCGLUT, DCTCGLUTSIZE, m_tcglutMemory, "", true, true, NULL, 0, false, false, fault_mode);
44  addMapping(ISISVME::TransferIORegisterSpace, DCDESCR, 1, &m_descriptorTimeBinLimitRegister, "", true, true, tcg_access, DCTDESCR, false, false, fault_mode);
45  addMapping(ISISVME::TransferIORegisterSpace, DCDESCRX, 1, &m_descriptorTimeBinLimitRegister, "", true, true, NULL, 0, false, false, fault_mode);
46  addMapping(ISISVME::TransferLUTSpace, DCPOSLUT, DCPOSLUTSIZE, m_poslutMemory, "", true, true, tcg_access, DCTPOSLUT, false, false, fault_mode);
47  addMapping(ISISVME::TransferIORegisterSpace, DCVETOENABLE, 1, &m_vetoEnableRegister, "", true, true, NULL, 0, false, false, fault_mode);
48  addMapping(ISISVME::TransferIORegisterSpace, DCVETOFLAG, 1, &m_vetoFlagRegister, "", true, true, NULL, 0, false, false, fault_mode);
49  addMapping(ISISVME::TransferIORegisterSpace, DCPERSIZE0, 1, &m_periodSizeLow, "", true, true, NULL, 0, false, false, fault_mode);
50  addMapping(ISISVME::TransferIORegisterSpace, DCPERSIZE1, 1, &m_periodSizeHigh, "", true, true, NULL, 0, false, false, fault_mode);
51  addMapping(ISISVME::TransferIORegisterSpace, DCPERCNT0, 1, &m_periodCounterLow, "", true, true, NULL, 0, false, false, fault_mode);
52  addMapping(ISISVME::TransferIORegisterSpace, DCPERCNT1, 1, &m_periodCounterHigh, "", true, true, NULL, 0, false, false, fault_mode);
53  addMapping(ISISVME::TransferIORegisterSpace, DCTOTCNTS, 1, &m_totalCounts, "", true, true, NULL, 0, false, false, fault_mode);
54  addMapping(ISISVME::TransferRunMemorySpace, DCMEMSTART, DET_MEM_LEN, m_detMemory, "", true, true, NULL, 0, true, false, fault_mode);
55  addMapping(ISISVME::TransferIORegisterSpace, DCFSDEL0, 1, &m_fsdelay0, "", true, true, NULL, 0, false, false, fault_mode);
56  addMapping(ISISVME::TransferIORegisterSpace, DCFSDEL1, 1, &m_fsdelay1, "", true, true, NULL, 0, false, false, fault_mode);
57 
58  addMapping(ISISVME::TransferIORegisterSpace, DCEVNTMD, 1, &m_eventModeReg, "", true, true, NULL, 0, false, false, fault_mode);
59  addMapping(ISISVME::TransferIORegisterSpace, DCNXFRMR, 1, &m_nextFrameMarker, "", true, false, NULL, 0, false, false, fault_mode);
60  addMapping(ISISVME::TransferIORegisterSpace, DCNXMEMWR, 1, &m_nextMemoryWrite, "", true, false, NULL, 0, false, false, fault_mode);
61  addMapping(ISISVME::TransferIORegisterSpace, DCNMEMWR, 1, &m_numMemoryWraps, "", true, false, NULL, 0, false, false, fault_mode);
62  addMapping(ISISVME::TransferIORegisterSpace, DCADDLRR, 1, &m_lastReadAddr, "", true, true, NULL, 0, false, false, fault_mode);
63 
64  addMapping(ISISVME::TransferIORegisterSpace, DCOPMODE, 1, &m_dcopmode, "", true, true, NULL, 0, false, false, fault_mode);
65  addMapping(ISISVME::TransferIORegisterSpace, DCMUONSTEP, 1, &m_dcmuonstep, "", true, true, NULL, 0, false, false, fault_mode);
66 
67  addMapping(ISISVME::TransferIORegisterSpace, DCRUNMEMCLEAR, 1, &m_runMemoryClear, "", true, true, NULL, 0, false, false, fault_mode);
68 
69 
72 
74 
76  m_lastReadAddr -= 4;
77  LOGSTR_INFORMATION("SIMDetector card at position " << m_position << " for " << (m_neutron_data ? "neutron" : "sample environment") << " data");
78 }
79 
80 template <class DetCardPolicy>
82 {
83  increment2(1, m_periodCounterLow, m_periodCounterHigh);
84  return 0;
85 }
86 
87 template <class DetCardPolicy>
89 {
90  m_periodCounterLow = m_periodCounterHigh = 0;
91  return 0;
92 }
93 
94 template <class DetCardPolicy>
96 {
97  os << "SIMDetector card at position " << m_position << " for " << (m_neutron_data ? "neutron" : "sample environment") << " data using policy " << DetCardPolicy::det_card_policy_name;
98 }
99 
100 template <class DetCardPolicy>
102 {
103  if (m_detMemory != m_shared_detMemory)
104  {
105  delete []m_detMemory;
106  }
107  delete []m_poslutMemory;
108  delete []m_tcglutMemory;
109 }
110 
111 template <class DetCardPolicy>
113 {
114  static bool simspec0 = Poco::Util::Application::instance().config().getBool("isisicp.simulation.simulatespec0", true);
115  static bool simbin0 = Poco::Util::Application::instance().config().getBool("isisicp.simulation.simulatebin0", true);
116  static bool simulate_data = Poco::Util::Application::instance().config().getBool("isisicp.simulation.simulatedata", false);
117  if (simulate_data)
118  {
119  if ((m_eventModeReg & EventModeRegister<DetCardPolicy>::EventMode) > 0)
120  {
121  simulateEventMode(delay, simspec0, simbin0);
122  }
123  else
124  {
125  simulateHistogramMode(delay, simspec0, simbin0);
126  }
127  }
128 }
129 
131 template <class DetCardPolicy>
133 {
134  unsigned chan = 0, ntc = m_tcgTimeBinLimitRegister;
135  unsigned tof_pulses = static_cast<unsigned>(tof * 32.0);
136  for(unsigned i=0; i<ntc; ++i)
137  {
138  if ( (tof_pulses >= m_tcglutMemory[i]) && (tof_pulses < m_tcglutMemory[i+1]) )
139  {
140  chan = i + 1;
141  }
142  }
143  return chan;
144 }
145 
146 template <class DetCardPolicy>
147 void SIMDetectorCard<DetCardPolicy>::simulateHistogramMode(int /*delay*/, bool simspec0, bool simbin0)
148 {
149  isisU32_t period_size = m_periodSizeLow + (m_periodSizeHigh << 16);
150  isisU32_t period = m_periodCounterLow + (m_periodCounterHigh << 16);
151 // need to do period properly
152  isisU32_t offset;
153  float tof;
154 // fill DAE2 spectra 0, 2, 4 in current period
155  isisU32_t start_spec = (simspec0 ? 0 : 2);
156  if (!m_neutron_data)
157  {
158 // LOGSTR_ERROR("Invalid simulation mode - cannot histogram non neutron data");
159  Poco::Thread::sleep(50);
160  return;
161  }
162  if (m_vme->isRunning() && !m_vme->isVetoing())
163  {
164  for(unsigned card_spectrum=start_spec; card_spectrum <= start_spec+4; card_spectrum += 2)
165  {
166  offset = card_spectrum * m_descriptorTimeBinLimitRegister + period_size * period;
167  offset %= DET_MEM_LEN; // "% DET_MEM_LEN" to stop crash if silly values in period counters etc.
168 // the next line will increment bin 0 (junk bin) - this will be ignored
169 // when individual spectra are read, but will show up in a "sum all spectra"
170  if (simbin0)
171  {
172  ++(m_detMemory[offset]);
173  }
174  for(unsigned j=10; j<=20; j++) // fill bins 10 to 20
175  {
176 // i = (unsigned)(((double)rand() / (double)(RAND_MAX+1)) * DET_MEM_LEN);
177 // add "% DET_MEM_LEN" to stop crash if silly values in period counters etc.
178  tof = j * 10;
179  ++(m_detMemory[(getTimeChannelIndex(tof) + offset) % (unsigned)DET_MEM_LEN ]);
180  m_totalCounts++;
181  }
182  // make bin 15 a spike
183  tof = 15 * 10;
184  ++(m_detMemory[(getTimeChannelIndex(tof) + offset) % (unsigned)DET_MEM_LEN ]);
185  m_totalCounts++;
186  }
187  }
188 }
189 
190 // write a 32bit word integer data
191 template <class DetCardPolicy>
193 {
194  float tof;
195  unsigned char device_id = 30;
196  static uint32_t data_word_val = 10;
197  union { uint32_t u; unsigned char b[4]; } data_word;
198  data_word_val += 100;
199  data_word.u = data_word_val;
200  header.num_events = 5; // device id + 4 data bytes
201  writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&header), DAE_EVENT_HEADER_WORDS);
202  DetectorEvent32 ev;
203  tof = 15.0;
204  ev.spectrum = (device_id & 0xff) | (0x0 << 8);
205  ev.time_channel = getTimeChannelIndex(tof);
206  writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&ev), sizeof(ev) / sizeof(isisU32_t));
207  m_totalCounts++;
208  for(int i=0; i<4; ++i)
209  {
210  ev.spectrum = (data_word.b[i] & 0xff) | ((i+1) << 8);
211  ++(ev.time_channel); // these values should be ignored
212  writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&ev), sizeof(ev) / sizeof(isisU32_t));
213  m_totalCounts++;
214  }
215 }
216 
217 template <class DetCardPolicy>
219 {
220  static bool spreadsimevents = Poco::Util::Application::instance().config().getBool("isisicp.simulation.spreadsimevents", true);
221  float tof;
222  writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&header), DAE_EVENT_HEADER_WORDS);
223  DetectorEvent32 ev;
224  for(int i=0; i<2*header.num_events; i += 2)
225  {
226  unsigned card_spectrum = (spreadsimevents ? m_poslutMemory[i % DCPOSLUTSIZE] : 2);
227  ev.spectrum = card_spectrum;
228 // the next line will increment bin 0 (junk bin) - this will be ignored
229 // when individual spectra are read, but will show up in a "sum all spectra"
230 // if (simbin0)
231 // {
232 // ev.time_channel = 0;
233 // writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&ev), sizeof(ev) / sizeof(isisU32_t));
234 // }
235 // for(unsigned j=10; j<=20; j++) // fill bins 10 to 20
236 // {
237 // tof = j * 10;
238 // ev.time_channel = getTimeChannelIndex(tof);
239 // writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&ev), sizeof(ev) / sizeof(isisU32_t));
240 // m_totalCounts++;
241 // }
242  // make bin 15 a spike
243  tof = 15 * 10;
244  ev.time_channel = getTimeChannelIndex(tof);
245  writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&ev), sizeof(ev) / sizeof(isisU32_t));
246  m_totalCounts++;
247  }
248 }
249 
250 template <class DetCardPolicy>
251 void SIMDetectorCard<DetCardPolicy>::simulateEventMode(int delay, bool simspec0, bool simbin0)
252 {
253 // isisU32_t period_size = m_periodSizeLow + (m_periodSizeHigh << 16);
254  static int n_events_sim = Poco::Util::Application::instance().config().getInt("isisicp.simulation.neventssim", 5);
255  isisU32_t period = m_periodCounterLow + (m_periodCounterHigh << 16);
256  delay = 20; // we don't want to add more than 1 frame at a time now, so no scaling to 50Hz
257  int proton_incr = (int)( 180.0 * (double)delay / (1000.0 * 3600.0 * 1.738e-6) ) ; // 180uA current if 50Hz
258  SYSTEMTIME systime;
259  GetSystemTime(&systime);
260  DAEEventHeader::DAETime daetime;
261  DAEEventList::SystemTimeToDAETime(systime, daetime);
262 // need to do periods properly
263 
265  {
266  m_end_sent = false;
267  DAEEventHeader header;
268  memset(&header, 0 , sizeof(header));
269  header.frame_number = m_vme->frameNumber();
273  header.period = period;
274  header.num_events = n_events_sim;
275  header.protons = proton_incr;
276  header.time.low = daetime.low;
277  header.time.high = daetime.high;
278  header.info.header_type = ((m_eventModeReg >> 8) & 0x0f);
279  if (m_neutron_data)
280  {
281  simulateEventModeDetector(header, simspec0, simbin0);
282  }
283  else
284  {
285  simulateEventModeDataDae(header, simspec0, simbin0);
286  }
287  m_nextFrameMarker = m_nextMemoryWrite;
288  LOGSTR_DEBUG("Card " << position() << " next frame address " << m_nextFrameMarker
289  << " next mem " << m_nextMemoryWrite << " end sent " << m_end_sent);
290  }
291  if (!VMESimulationIface::isRunning() && !m_end_sent)
292  {
293  m_end_sent = true;
294  DAEEventHeader header;
295  memset(&header, 0 , sizeof(header));
296  header.frame_number = m_vme->frameNumber();
298  header.marker1 = EndOfRunMarker;
300  header.period = period;
301  header.num_events = 0;
302  header.protons = 0;
303  header.time.low = daetime.low;
304  header.time.high = daetime.high;
305  header.info.header_type = ((m_eventModeReg >> 8) & 0x0f);
306  LOGSTR_DEBUG("card " << position() << " sending end header for frame " << header.frame_number);
307  writeToMemoryWrapped(reinterpret_cast<isisU32_t*>(&header), DAE_EVENT_HEADER_WORDS);
308  LOGSTR_DEBUG("Card " << position() << " next frame address " << m_nextFrameMarker
309  << " next mem " << m_nextMemoryWrite << " end sent " << m_end_sent);
310  }
311 }
312 
313 template <class DetCardPolicy>
315 {
316  int i = 0, nretry = 3;
317  while(i < len)
318  {
319  while( (4 * DET_MEM_LEN + m_lastReadAddr - m_nextMemoryWrite) % (4 * DET_MEM_LEN) <= 1 )
320  {
321  if ( --nretry < 0 )
322  {
323  LOGSTR_WARNING("abandoning write");
324  return;
325  }
326  LOGSTR_WARNING("memory full, waiting " << m_lastReadAddr);
327  Sleep(3000);
328  }
329  m_detMemory[m_nextMemoryWrite / 4] = data[i];
330  m_nextMemoryWrite += 4;
331  if (m_nextMemoryWrite >= 4 * DET_MEM_LEN)
332  {
333  ++m_numMemoryWraps;
334  m_nextMemoryWrite = 0;
335  }
336  ++i;
337  }
338 }
339 
340 
341 #if 0
342 static void det_junk_fill(void* arg)
343 {
344  unsigned i, j, k;
345  isisU32_t* pVal;
347  for(k=1; k<=NSIMDETCARDS; k++)
348  {
349  for(i=0; i<(unsigned)dae->m_detMemoryLength; i += 417)
350  {
351  pVal = dae->m_detMemory[k] + i % dae->m_detMemoryLength;
352  j = (unsigned)(((double)rand() / (double)(RAND_MAX+1)) * 1000.0);
353  *pVal = *pVal + j;
354  }
355  }
356 }
357 #endif
358 
359 template <class DetCardPolicy>
361 {
362  if ( (isRegisterUsed(DCRUNMEMCLEAR) && (m_runMemoryClear != 0)) || (isRegisterUsed(DCTAC) && (m_tcgAccessRegister & DCTHISCLE)) )
363  {
364  memset(m_detMemory, 0, DET_MEM_LEN * sizeof(isisU32_t));
365  // add in a random patters for testing
366  //for(int i=0; i<DET_MEM_LEN; i++)
367  //{
368  // m_detMemory[i] = (i + 3 * m_position) % 17;
369  //}
370  m_tcgAccessRegister &= ~DCTHISCLE;
371  m_nextFrameMarker = m_nextMemoryWrite = m_numMemoryWraps = m_lastReadAddr = 0;
372  m_lastReadAddr -= 4;
373  m_runMemoryClear = 0;
374  }
375  if ( isRegisterUsed(DCTAC) && (m_tcgAccessRegister & DCTTOTCNTSCLE) )
376  {
377  m_totalCounts = 0;
378  }
379 }
380 
381 // this is here just so we can set a breakpoint easily on a card read
382 template <class DetCardPolicy>
384 {
385 }
386 
389 
isisU32_t m_tcgAccessRegister
SIMDetectorCard(int position, VMESimulationIface *vme, bool shared, FaultMode fault_mode, bool neutron_data, DAEstatus &status)
isisU32_t m_periodCounterLow
virtual void printStatus(std::ostream &os)
isisU32_t m_descriptorTimeBinLimitRegister
unsigned header_type
Definition: dae_events.h:10
virtual void simulate(int delay)
uint32_t num_events
Definition: dae_events.h:60
isisU32_t * m_poslutMemory
isisU32_t m_numMemoryWraps
virtual void updateCardAfterWrite(DAEstatus &status)
uint32_t marker1
should always be DAEEventHeaderFixedMarker
Definition: dae_events.h:47
fixed header marker for DAEEventHeader
Definition: dae_events.h:44
unsigned long isisU32_t
Definition: isisvme_types.h:8
isisU32_t m_totalCounts
unsigned period
Definition: dae_events.h:57
virtual void updateCardAfterRead(DAEstatus &status)
static const int DAEEventHeaderFixedMarker
Definition: dae_events.h:40
int addMapping(ISISVME::TransferProps props, isisU32_t address, int n, isisU32_t *var, const char *name, bool readable, bool writable, isisU32_t *access_reg, unsigned access_bit, bool wrap, bool sixteen_bit_access, FaultMode fault_mode)
#define LOGSTR_DEBUG(__arg)
Definition: IsisBase.h:71
void writeToMemoryWrapped(isisU32_t *data, int len)
unsigned header_length
Definition: dae_events.h:11
isisU32_t m_vetoFlagRegister
static ISISDAE * dae
Definition: daeset.cpp:7
#define LOGSTR_WARNING(__arg)
Definition: IsisBase.h:92
static isisU32_t * m_shared_detMemory
bool isRegisterUsed(const T &address)
registers are either &quot;unsigned&quot; or &quot;unused_t&quot;
Definition: dae_policy.h:8
unsigned protons
Definition: dae_events.h:63
isisU32_t m_eventModeReg
static void SystemTimeToDAETime(const SYSTEMTIME &systime, DAEEventHeader::DAETime &daetime)
Definition: dae_events.cpp:202
DAEEventHeaderInfo info
should be DAEEventHeaderMarker
Definition: dae_events.h:48
bit assignmments for DAE2DetCardPolicy::DCEVNTMD
Definition: detector_card.h:21
isisU32_t * m_tcglutMemory
#define LOGSTR_INFORMATION(__arg)
Definition: IsisBase.h:78
uint32_t marker0
Definition: dae_events.h:46
static bool isRunning()
struct DAEEventHeader::DAETime time
#define DET_MEM_LEN
isisU32_t m_periodCounterHigh
isisU32_t m_lastReadAddr
virtual void simulateEventMode(int delay, bool simspec0, bool simbin0)
isisU32_t m_nextFrameMarker
unsigned time_channel
Definition: dae_events.h:78
uint32_t frame_number
Definition: dae_events.h:49
static const unsigned DAE_EVENT_HEADER_WORDS
Definition: dae_events.h:102
isisU32_t m_tcgTimeBinLimitRegister
unsigned spectrum
Definition: dae_events.h:79
static bool isVetoing()
unsigned getTimeChannelIndex(float tof)
tof in microseconds
isisU32_t m_periodSizeLow
isisU32_t m_nextMemoryWrite
void setLoggerName(const std::string &logger_name)
Definition: IsisBase.h:17
isisU32_t m_periodSizeHigh
isisU32_t m_runMemoryClear
virtual void simulateEventModeDetector(DAEEventHeader &header, bool simspec0, bool simbin0)
virtual void simulateEventModeDataDae(DAEEventHeader &header, bool simspec0, bool simbin0)
FaultMode
Definition: sim_dae2_card.h:10
isisU32_t * m_detMemory
isisU32_t m_vetoEnableRegister
isisU32_t m_dcmuonstep
virtual void simulateHistogramMode(int delay, bool simspec0, bool simbin0)