MIDAS
Loading...
Searching...
No Matches
wdfe.cxx
Go to the documentation of this file.
1/********************************************************************\
2
3 Name: wdfe.cxx
4 Created by: Stefan Ritt
5
6 Contents: Example front-end for standalone WaveDREAM board
7
8\********************************************************************/
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <string.h>
14#include <iostream>
15#include "midas.h"
16#include "mfe.h"
17#include "experim.h"
18
19#include "WDBLib.h"
20#include "DCBLib.h"
21
22/*-- Globals -------------------------------------------------------*/
23
24/* The frontend name (client name) as seen by other MIDAS clients */
25const char *frontend_name = "WD Frontend";
26/* The frontend file name, don't change it */
28
29/* frontend_loop is called periodically if this variable is TRUE */
31
32/* a frontend status page is displayed with this frequency in ms */
34
35/* maximum event size produced by this frontend */
36INT max_event_size = 1024 * 1014;
37
38/* maximum event size for fragmented events (EQ_FRAGMENTED) */
40
41/* buffer size to hold events */
43
44
45/*-- Function declarations -----------------------------------------*/
46
47INT frontend_init(void);
48INT frontend_exit(void);
49INT begin_of_run(INT run_number, char *error);
50INT end_of_run(INT run_number, char *error);
51INT pause_run(INT run_number, char *error);
52INT resume_run(INT run_number, char *error);
53INT frontend_loop(void);
54
55INT read_trigger_event(char *pevent, INT off);
56INT read_periodic_event(char *pevent, INT off);
57
59INT interrupt_configure(INT cmd, INT source, POINTER_T adr);
60
61/*-- Equipment list ------------------------------------------------*/
62
64
66
67 {"Trigger", /* equipment name */
68 {1, 0, /* event ID, trigger mask */
69 "SYSTEM", /* event buffer */
70 EQ_POLLED, /* equipment type */
71 0, /* event source */
72 "MIDAS", /* format */
73 TRUE, /* enabled */
74 RO_RUNNING, /* read only when running */
75 100, /* poll for 100ms */
76 0, /* stop run after this event limit */
77 0, /* number of sub events */
78 0, /* don't log history */
79 "", "", "",},
80 read_trigger_event, /* readout routine */
81 },
82
83 {"Periodic", /* equipment name */
84 {2, 0, /* event ID, trigger mask */
85 "SYSTEM", /* event buffer */
86 EQ_PERIODIC, /* equipment type */
87 0, /* event source */
88 "MIDAS", /* format */
89 TRUE, /* enabled */
90 RO_RUNNING | RO_TRANSITIONS | /* read when running and on transitions */
91 RO_ODB, /* and update ODB */
92 1000, /* read every sec */
93 0, /* stop run after this event limit */
94 0, /* number of sub events */
95 TRUE, /* log history */
96 "", "", "",},
97 read_periodic_event, /* readout routine */
98 },
99
100 {""}
101};
102
103namespace WD { // put all WD globals into separate namespace
104
105 // WD boards
106 std::vector<WDB *> wdb;
107
108 // waveform processor
110
111 // WD events
112 std::vector<WDEvent *>wde;
113
114}
115
116/*-- Frontend Init -------------------------------------------------*/
117
119{
120 std::string drs_calib_path;
121
122 // set calibration path according to WDBSYS
123 const char *wavedaqpath = getenv("WDBSYS");
124 if (wavedaqpath != nullptr) {
126 drs_calib_path += "/sw/wds/";
127 } else {
128 cm_msg(MINFO, "frontend_init", "Calibration filepath set to current directory. "\
129 "Use WDBSYS environnement variable to point to your wavedaq repository");
130 drs_calib_path = "./";
131 }
132
133 // create WDB object
134 WDB *b = new WDB("wd026");
135 try {
136 b->SetVerbose(true); // change for debugging
137 b->Connect(); // connect to board, throws exception if unsuccessful
138 b->ReceiveControlRegisters();
139
140 // Reset DRS FSM
141 b->ResetDrsControlFsm();
142 b->ResetPackager();
143
144 // Stop DRS
145 b->SetDaqSingle(false);
146 b->SetDaqAuto(false);
147 b->SetDaqNormal(false);
148
149 b->SetSendBlock(true); // update all control registers together
150
151 //---- readout settings
152 b->SetDrsChTxEn(0xFFFF); // enable all DRS readout
153 b->SetAdcChTxEn(0); // disable ADC readout
154 b->SetTdcChTxEn(0); // disable TDC readout
155 b->SetSclTxEn(0); // disable scaler readout
156
157 //---- board settings
158 b->SetDaqClkSrcSel(1); // select on-board clock oscillator
159 b->SetDrsSampleFreq(1000); // Sampling speed 1 GSPS
160 b->SetFeGain(-1, 1); // set FE gain to 1
161 b->SetFePzc(-1, false); // disable pole-zero cancellation
162 b->SetInterPkgDelay(0x753); // minimum inter-packet delay
163 b->SetFeMux(-1, WDB::cFeMuxInput); // set multiplexer to input
164
165 //---- trigger settings
166 b->SetExtAsyncTriggerEn(false); // disable external trigger
167 b->SetTriggerDelay(0); // minimal inter-packet delay
168 b->SetLeadTrailEdgeSel(0); // trigger on leading edge
169 b->SetPatternTriggerEn(true); // enable internal pattern trigger
170 b->SetDacTriggerLevelV(-1, -0.02); // set trigger level to -20 mV for all channels
171
172 b->SetTrgSrcPolarity(0xFFFF); // negative signals
173 b->SetTrgPtrnEn(0xFFFF); // enable 16 trigger patterns
174 // b->SetTrgPtrnEn(0x0001); // enable first trigger pattern
175 for (int i=0 ; i<16 ; i++) {
176 b->SetTrgSrcEnPtrn(i, (1<<i)); // set individual channel as only source for pattern
177 b->SetTrgStatePtrn(i, (1<<i)); // set trigger coincidence for single channel
178 }
179
180 // now send all changes in one packet
181 b->SetSendBlock(false);
182 b->SendControlRegisters();
183
184 // check if PLLs are locked
185 b->ResetAllPll();
186 sleep_ms(100);
187 b->GetPllLock(true);
188 if (!b->GetLmkPllLock() || !b->GetDaqPllLock()) {
189 cm_msg(MERROR, "frontend_init", "PLLs not locked on board %s. Mask = 0x%04X",
190 b->GetName().c_str(), b->GetPllLock(false));
191 return FE_ERR_HW;
192 }
193
194 // read all status registers
195 b->ReceiveStatusRegisters();
196
197 if (b->IsVerbose()) {
198 std::cout << std::endl << "========== Board Info ==========" << std::endl;
199 b->PrintVersion();
200 }
201
202 // load calibration data for this board
203 b->LoadVoltageCalibration(b->GetDrsSampleFreqMhz(), drs_calib_path);
204 b->LoadTimeCalibration(b->GetDrsSampleFreqMhz(), drs_calib_path);
205
206 // create event storage for this board
207 WD::wde.push_back(new WDEvent(b->GetSerialNumber()));
208
209 } catch (std::runtime_error &e) {
210 std::cout << std::endl;
211 cm_msg(MERROR, "frontend_init", "%s", e.what());
212 cm_msg(MERROR, "frontend_init", "Cannot initialize %s, aborting.", b->GetName().c_str());
213 return FE_ERR_HW;
214 }
215
216 WD::wdb.push_back(b);
217
218 // instantiate waveform processor
219 WD::wp = new WP();
220 WD::wp->SetAllCalib(true);
221 WD::wp->SetWDBList(WD::wdb);
222 WD::wp->SetRequestedBoard(WD::wdb);
223
224 // set destination port after waveform processor has been initialized
225 for (auto b: WD::wdb)
226 b->SetDestinationPort(WD::wp->GetServerPort());
227
228 // start DRS for first event
229 for (auto b: WD::wdb)
230 b->SetDaqSingle(true);
231
232 return SUCCESS;
233}
234
235/*-- Frontend Exit -------------------------------------------------*/
236
238{
239 return SUCCESS;
240}
241
242/*-- Begin of Run --------------------------------------------------*/
243
245{
246 // start DRS for first event
247 for (auto b: WD::wdb) {
248 b->ResetDrsControlFsm();
249 b->ResetEventCounter();
250 b->SetDaqSingle(true);
251 }
252
253 return SUCCESS;
254}
255
256/*-- End of Run ----------------------------------------------------*/
257
259{
260 return SUCCESS;
261}
262
263/*-- Pause Run -----------------------------------------------------*/
264
266{
267 return SUCCESS;
268}
269
270/*-- Resuem Run ----------------------------------------------------*/
271
273{
274 return SUCCESS;
275}
276
277/*-- Frontend Loop -------------------------------------------------*/
278
280{
281 /* if frontend_call_loop is true, this routine gets called when
282 the frontend is idle or once between every event */
283 return SUCCESS;
284}
285
286/*------------------------------------------------------------------*/
287
288/********************************************************************\
289
290 Readout routines for different events
291
292\********************************************************************/
293
294/*-- Trigger event routines ----------------------------------------*/
295
297/* Polling routine for events. Returns TRUE if event
298 is available. If test equals TRUE, don't return. The test
299 flag is used to time the polling */
300{
301 int i;
302 bool flag;
303
304 for (i = 0; i < count; i++) {
305 /* poll hardware and set flag to TRUE if new event is available */
306 flag = WD::wp->WaitNewEvent(10);
307
308 if (flag)
309 if (!test)
310 return TRUE;
311 }
312
313 return 0;
314}
315
316/*-- Interrupt configuration ---------------------------------------*/
317
319{
320 switch (cmd) {
322 break;
324 break;
326 break;
328 break;
329 }
330 return SUCCESS;
331}
332
333/*-- Event readout -------------------------------------------------*/
334
336{
337 float *pdata;
338 WDEvent event(WD::wdb[0]->GetSerialNumber());
339
340 // read current event
341 bool bNewEvent = WD::wp->GetLastEvent(WD::wdb[0], 500, event);
342
343 // start DRS for next event
344 WD::wdb[0]->SetDaqSingle(true);
345
346 if (!bNewEvent)
347 return 0;
348
349 // init bank structure
350 bk_init32(pevent);
351
352 // store time arrays for all channels on first event
353 if (SERIAL_NUMBER(pevent) == 0) {
354 bk_create(pevent, "DRST", TID_FLOAT, (void **) &pdata);
355 for (int i = 0; i < 16; i++) {
356 memcpy(pdata, event.mWfTDRS[i], sizeof(float) * 1024);
357 pdata += 1024;
358 }
359 bk_close(pevent, pdata);
360 }
361
362 // create calibrated time array
363 bk_create(pevent, "DRS0", TID_FLOAT, (void **) &pdata);
364
365 // copy over 16 channels
366 for (int i=0 ; i<16 ; i++) {
367 memcpy(pdata, event.mWfUDRS[i], sizeof(float)*1024);
368 pdata += 1024;
369 }
370
371 bk_close(pevent, pdata);
372
373 return bk_size(pevent);
374}
375
376/*-- Periodic event ------------------------------------------------*/
377
379{
380 DWORD *pdata;
381
382 std::vector<unsigned long long> scaler;
383 WD::wdb[0]->GetScalers(scaler, true);
384
385 // init bank structure
386 bk_init(pevent);
387
388 // create SCLR bank
389 bk_create(pevent, "SCLR", TID_DWORD, (void **)&pdata);
390
391 for (int i = 0; i < scaler.size(); i++)
392 *pdata++ = scaler[i];
393
394 bk_close(pevent, pdata);
395
396 return bk_size(pevent);
397}
#define FALSE
Definition cfortran.h:309
INT bk_close(void *event, void *pdata)
Definition midas.cxx:16780
void bk_init(void *event)
Definition midas.cxx:16406
void bk_init32(void *event)
Definition midas.cxx:16469
void bk_create(void *event, const char *name, WORD type, void **pdata)
Definition midas.cxx:16561
INT bk_size(const void *event)
Definition midas.cxx:16495
#define CMD_INTERRUPT_ATTACH
Definition midas.h:822
#define FE_ERR_HW
Definition midas.h:719
#define CMD_INTERRUPT_DISABLE
Definition midas.h:821
#define CMD_INTERRUPT_ENABLE
Definition midas.h:820
#define CMD_INTERRUPT_DETACH
Definition midas.h:823
unsigned int DWORD
Definition mcstd.h:51
#define SUCCESS
Definition mcstd.h:54
#define EQ_POLLED
Definition midas.h:415
#define RO_ODB
Definition midas.h:438
#define EQ_PERIODIC
Definition midas.h:414
#define MINFO
Definition midas.h:560
#define MERROR
Definition midas.h:559
#define RO_TRANSITIONS
Definition midas.h:434
#define TID_FLOAT
Definition midas.h:341
#define RO_RUNNING
Definition midas.h:426
#define TID_DWORD
Definition midas.h:336
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:915
INT run_number[2]
Definition mana.cxx:246
double count
Definition mdump.cxx:33
INT i
Definition mdump.cxx:32
DWORD BOOL
Definition midas.h:105
int INT
Definition midas.h:129
#define TRUE
Definition midas.h:182
#define POINTER_T
Definition midas.h:166
#define SERIAL_NUMBER(e)
Definition midas.h:880
#define resume_run
#define pause_run
program test
Definition miniana.f:6
Definition wdfe.cxx:103
std::vector< WDEvent * > wde
Definition wdfe.cxx:112
WP * wp
Definition wdfe.cxx:109
std::vector< WDB * > wdb
Definition wdfe.cxx:106
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
double scaler[32]
Definition scaler.cxx:47
static double e(void)
Definition tinyexpr.c:136
BOOL frontend_call_loop
frontend_loop is called periodically if this variable is TRUE
Definition wdfe.cxx:30
const char * frontend_file_name
The frontend file name, don't change it.
Definition wdfe.cxx:27
INT max_event_size
maximum event size produced by this frontend
Definition wdfe.cxx:36
INT frontend_exit(void)
Frontend exit.
Definition wdfe.cxx:237
INT event_buffer_size
buffer size to hold events
Definition wdfe.cxx:42
INT max_event_size_frag
maximum event size for fragmented events (EQ_FRAGMENTED)
Definition wdfe.cxx:39
INT interrupt_configure(INT cmd, INT source, POINTER_T adr)
Interrupt configuration (not implemented)
Definition wdfe.cxx:318
BOOL equipment_common_overwrite
Definition wdfe.cxx:63
INT read_periodic_event(char *pevent, INT off)
Definition wdfe.cxx:378
INT frontend_init(void)
Frontend initialization.
Definition wdfe.cxx:118
INT poll_event(INT source, INT count, BOOL test)
Polling routine for events.
Definition wdfe.cxx:296
INT read_trigger_event(char *pevent, INT off)
Definition wdfe.cxx:335
EQUIPMENT equipment[]
Main structure for midas equipment.
Definition wdfe.cxx:65
const char * frontend_name
The frontend name (client name) as seen by other MIDAS clients.
Definition wdfe.cxx:25
INT display_period
a frontend status page is displayed with this frequency in ms
Definition wdfe.cxx:33
INT begin_of_run(INT run_number, char *error)
Begin of Run.
Definition wdfe.cxx:244
INT frontend_loop(void)
Frontend loop.
Definition wdfe.cxx:279
INT end_of_run(INT run_number, char *error)
End of Run.
Definition wdfe.cxx:258