Line data Source code
1 : /********************************************************************\
2 :
3 : Name: frontend.c
4 : Created by: Stefan Ritt
5 :
6 : Contents: Experiment specific readout code (user part) of
7 : Midas frontend. This example simulates a "trigger
8 : event" and a "periodic event" which are filled with
9 : random data.
10 :
11 : The trigger event is filled with two banks (ADC0 and TDC0),
12 : both with values with a gaussian distribution between
13 : 0 and 4096. About 100 event are produced per second.
14 :
15 : The periodic event contains one bank (PRDC) with four
16 : sine-wave values with a period of one minute. The
17 : periodic event is produced once per second and can
18 : be viewed in the history system.
19 :
20 : \********************************************************************/
21 :
22 : #undef NDEBUG // midas required assert() to be always enabled
23 :
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <math.h>
27 : #include <assert.h> // assert()
28 :
29 : #include "midas.h"
30 : #include "experim.h"
31 :
32 : #include "mfe.h"
33 :
34 : /*-- Globals -------------------------------------------------------*/
35 :
36 : /* The frontend name (client name) as seen by other MIDAS clients */
37 : const char *frontend_name = "Sample Frontend";
38 : /* The frontend file name, don't change it */
39 : const char *frontend_file_name = __FILE__;
40 :
41 : /*-- Function declarations -----------------------------------------*/
42 :
43 : INT read_trigger_event(char *pevent, INT off);
44 : INT read_periodic_event(char *pevent, INT off);
45 :
46 : INT poll_trigger_event(INT source, INT count, BOOL test);
47 :
48 : /*-- Equipment list ------------------------------------------------*/
49 :
50 : BOOL equipment_common_overwrite = TRUE;
51 :
52 : EQUIPMENT equipment[] = {
53 :
54 : {"Trigger", /* equipment name */
55 : {1, 0, /* event ID, trigger mask */
56 : "SYSTEM", /* event buffer */
57 : EQ_POLLED, /* equipment type */
58 : 0, /* event source */
59 : "MIDAS", /* format */
60 : TRUE, /* enabled */
61 : RO_RUNNING | /* read only when running */
62 : RO_ODB, /* and update ODB */
63 : 100, /* poll for 100ms */
64 : 0, /* stop run after this event limit */
65 : 0, /* number of sub events */
66 : 0, /* don't log history */
67 : "", "", "", "", "", 0},
68 : read_trigger_event, /* readout routine */
69 : },
70 :
71 : {"Periodic", /* equipment name */
72 : {2, 0, /* event ID, trigger mask */
73 : "SYSTEM", /* event buffer */
74 : EQ_PERIODIC, /* equipment type */
75 : 0, /* event source */
76 : "MIDAS", /* format */
77 : TRUE, /* enabled */
78 : RO_RUNNING | RO_TRANSITIONS | /* read when running and on transitions */
79 : RO_ODB, /* and update ODB */
80 : 1000, /* read every 1000 msec (1 sec) */
81 : 0, /* stop run after this event limit */
82 : 0, /* number of sub events */
83 : 10, /* log history every ten seconds*/
84 : "", "", "", "", "", 0},
85 : read_periodic_event, /* readout routine */
86 : },
87 :
88 : {""}
89 : };
90 :
91 : /********************************************************************\
92 : Frontend callback routines
93 :
94 : The function frontend_init gets called when the frontend program
95 : is started. This routine should initialize the hardware, and can
96 : optionally install several callback functions:
97 :
98 : install_poll_event:
99 : Install a function which gets called to check if a new event is
100 : available for equipment of type EQ_POLLED.
101 :
102 : install_frontend_exit:
103 : Install a function which gets called when the frontend program
104 : finishes.
105 :
106 : install_begin_of_run:
107 : Install a function which gets called when a new run gets started.
108 :
109 : install_end_of_run:
110 : Install a function which gets called when a new run gets stopped.
111 :
112 : install_pause_run:
113 : Install a function which gets called when a new run gets paused.
114 :
115 : install_resume_run:
116 : Install a function which gets called when a new run gets resumed.
117 :
118 : install_frontend_loop:
119 : Install a function which gets called inside the main event loop
120 : as often as possible. This function gets all available CPU cycles,
121 : so in order not to take 100% CPU, this function can use the
122 : ss_sleep(10) function to give up some CPU cycles.
123 :
124 : \********************************************************************/
125 :
126 : /*-- Frontend Init -------------------------------------------------*/
127 :
128 0 : INT frontend_init()
129 : {
130 : /* install polling routine */
131 0 : install_poll_event(poll_trigger_event);
132 :
133 : /* set cache size */
134 0 : set_write_cache_size("SYSTEM", 10000000);
135 :
136 : /* put any hardware initialization here */
137 :
138 : /* print message and return FE_ERR_HW if frontend should not be started */
139 0 : return SUCCESS;
140 : }
141 :
142 : /*------------------------------------------------------------------*/
143 :
144 : /********************************************************************\
145 :
146 : Readout routines for different events
147 :
148 : \********************************************************************/
149 :
150 : /*-- Trigger event routines ----------------------------------------*/
151 :
152 0 : INT poll_trigger_event(INT source, INT count, BOOL test)
153 : /* Polling routine for events. Returns TRUE if event
154 : is available. If test equals TRUE, don't return. The test
155 : flag is used to time the polling */
156 : {
157 : int i;
158 : DWORD flag;
159 :
160 0 : for (i = 0; i < count; i++) {
161 : /* poll hardware and set flag to TRUE if new event is available */
162 0 : flag = TRUE;
163 :
164 0 : if (flag)
165 0 : if (!test)
166 0 : return TRUE;
167 : }
168 :
169 0 : return 0;
170 : }
171 :
172 : /*-- Event readout -------------------------------------------------*/
173 : // This function gets called whenever poll_event() returns TRUE (the
174 : // MFE framework calls poll_event() regularly).
175 :
176 0 : INT read_trigger_event(char *pevent, INT off)
177 : {
178 : UINT32 *pdata;
179 :
180 : /* init bank structure */
181 0 : bk_init(pevent);
182 :
183 : /* create a bank called ADC0 */
184 0 : bk_create(pevent, "ADC0", TID_UINT32, (void **)&pdata);
185 :
186 : /* following code "simulates" some ADC data */
187 0 : for (int i = 0; i < 4; i++)
188 0 : *pdata++ = rand()%1024 + rand()%1024 + rand()%1024 + rand()%1024;
189 :
190 0 : bk_close(pevent, pdata);
191 :
192 : /* create another bank called TDC0 */
193 0 : bk_create(pevent, "TDC0", TID_UINT32, (void **)&pdata);
194 :
195 : /* following code "simulates" some TDC data */
196 0 : for (int i = 0; i < 4; i++)
197 0 : *pdata++ = rand()%1024 + rand()%1024 + rand()%1024 + rand()%1024;
198 :
199 0 : bk_close(pevent, pdata);
200 :
201 : /* limit event rate to 100 Hz. In a real experiment remove this line */
202 0 : ss_sleep(10);
203 :
204 0 : return bk_size(pevent);
205 : }
206 :
207 : /*-- Periodic event ------------------------------------------------*/
208 : // This function gets called periodically by the MFE framework (the
209 : // period is set in the EQUIPMENT structs at the top of the file).
210 :
211 0 : INT read_periodic_event(char *pevent, INT off)
212 : {
213 : UINT32 *pdata;
214 :
215 : /* init bank structure */
216 0 : bk_init(pevent);
217 :
218 : /* create a bank called PRDC */
219 0 : bk_create(pevent, "PRDC", TID_UINT32, (void **)&pdata);
220 :
221 : /* following code "simulates" some values in sine wave form */
222 0 : for (int i = 0; i < 16; i++)
223 0 : *pdata++ = 100*sin(M_PI*time(NULL)/60+i/2.0)+100;
224 :
225 0 : bk_close(pevent, pdata);
226 :
227 0 : return bk_size(pevent);
228 : }
|