Line data Source code
1 : /*******************************************************************\
2 :
3 : Name: tmfe_example_frontend.cxx
4 : Created by: K.Olchanski
5 :
6 : Contents: Example of converting examples/experiment/frontend.cxx to TMFE framework
7 :
8 : \********************************************************************/
9 :
10 : #undef NDEBUG // midas required assert() to be always enabled
11 :
12 : #include <stdio.h>
13 : #include <math.h> // M_PI
14 :
15 : #include "tmfe.h"
16 :
17 : /********************************************************************\
18 :
19 : Name: frontend.c
20 : Created by: Stefan Ritt
21 :
22 : Contents: Experiment specific readout code (user part) of
23 : Midas frontend. This example simulates a "trigger
24 : event" and a "periodic event" which are filled with
25 : random data.
26 :
27 : The trigger event is filled with two banks (ADC0 and TDC0),
28 : both with values with a gaussian distribution between
29 : 0 and 4096. About 100 event are produced per second.
30 :
31 : The periodic event contains one bank (PRDC) with four
32 : sine-wave values with a period of one minute. The
33 : periodic event is produced once per second and can
34 : be viewed in the history system.
35 :
36 : \********************************************************************/
37 :
38 : #undef NDEBUG // midas required assert() to be always enabled
39 :
40 : //#include "midas.h"
41 : //#include "experim.h"
42 :
43 : #if 0
44 : const char *frontend_name = "Sample Frontend";
45 : const char *frontend_file_name = __FILE__;
46 : BOOL frontend_call_loop = FALSE;
47 : INT display_period = 3000;
48 : INT max_event_size = 10000;
49 : INT max_event_size_frag = 5 * 1024 * 1024;
50 : INT event_buffer_size = 100 * 10000;
51 : BOOL equipment_common_overwrite = TRUE;
52 :
53 : EQUIPMENT equipment[] = {
54 :
55 : {"Trigger", /* equipment name */
56 : {1, 0, /* event ID, trigger mask */
57 : "SYSTEM", /* event buffer */
58 : EQ_POLLED, /* equipment type */
59 : 0, /* event source */
60 : "MIDAS", /* format */
61 : TRUE, /* enabled */
62 : RO_RUNNING | /* read only when running */
63 : RO_ODB, /* and update ODB */
64 : 100, /* poll for 100ms */
65 : 0, /* stop run after this event limit */
66 : 0, /* number of sub events */
67 : 0, /* don't log history */
68 : "", "", "",},
69 : read_trigger_event, /* readout routine */
70 : },
71 :
72 : {"Periodic", /* equipment name */
73 : {2, 0, /* event ID, trigger mask */
74 : "SYSTEM", /* event buffer */
75 : EQ_PERIODIC, /* equipment type */
76 : 0, /* event source */
77 : "MIDAS", /* format */
78 : TRUE, /* enabled */
79 : RO_RUNNING | RO_TRANSITIONS | /* read when running and on transitions */
80 : RO_ODB, /* and update ODB */
81 : 1000, /* read every sec */
82 : 0, /* stop run after this event limit */
83 : 0, /* number of sub events */
84 : TRUE, /* log history */
85 : "", "", "",},
86 : read_periodic_event, /* readout routine */
87 : },
88 :
89 : {""}
90 : };
91 : #endif
92 :
93 : class EqTrigger :
94 : public TMFeEquipment
95 : {
96 : public:
97 0 : EqTrigger(const char* eqname, const char* eqfilename) // ctor
98 0 : : TMFeEquipment(eqname, eqfilename)
99 : {
100 : /* configure your equipment here */
101 :
102 0 : fEqConfReadConfigFromOdb = false;
103 0 : fEqConfEventID = 1;
104 0 : fEqConfBuffer = "SYSTEM";
105 0 : fEqConfPeriodMilliSec = 0; // in milliseconds
106 0 : fEqConfLogHistory = 0;
107 0 : fEqConfReadOnlyWhenRunning = true;
108 : //fEqConfWriteEventsToOdb = true;
109 0 : fEqConfEnablePoll = true; // enable polled equipment
110 : //fEqConfPollSleepSec = 0; // to create a "100% CPU busy" polling loop, set poll sleep time to zero
111 0 : fEqConfPollSleepSec = 0.010; // limit event rate to 100 Hz. In a real experiment remove this line
112 0 : }
113 :
114 0 : ~EqTrigger() // dtor
115 0 : {
116 0 : }
117 :
118 0 : void HandleUsage()
119 : {
120 0 : printf("EqTrigger::Usage!\n");
121 0 : }
122 :
123 0 : TMFeResult HandleInit(const std::vector<std::string>& args)
124 : {
125 : /* put any hardware initialization here */
126 :
127 :
128 : /* start poll thread here */
129 :
130 : //EqStartPollThread();
131 :
132 : /* return TMFeErrorMessage("my error message") if frontend should not be started */
133 0 : return TMFeOk();
134 : }
135 :
136 0 : TMFeResult HandleRpc(const char* cmd, const char* args, std::string& response)
137 : {
138 : /* handler for JRPC into the frontend, see tmfe_example_everything.cxx */
139 0 : return TMFeOk();
140 : }
141 :
142 0 : TMFeResult HandleBeginRun(int run_number)
143 : {
144 : /* put here clear scalers etc. */
145 0 : return TMFeOk();
146 : }
147 :
148 0 : TMFeResult HandleEndRun(int run_number)
149 : {
150 0 : return TMFeOk();
151 : }
152 :
153 0 : bool HandlePoll()
154 : {
155 : /* Polling routine for events. Returns TRUE if event is available */
156 0 : return true;
157 : }
158 :
159 0 : void HandlePollRead()
160 : {
161 : char buf[1024];
162 0 : ComposeEvent(buf, sizeof(buf));
163 0 : BkInit(buf, sizeof(buf));
164 :
165 : /* create structured ADC0 bank */
166 0 : uint32_t* pdata = (uint32_t*)BkOpen(buf, "ADC0", TID_UINT32);
167 :
168 : /* following code to "simulates" some ADC data */
169 0 : for (int a = 0; a < 4; a++)
170 0 : *pdata++ = rand()%1024 + rand()%1024 + rand()%1024 + rand()%1024;
171 :
172 0 : BkClose(buf, pdata);
173 :
174 : /* create variable length TDC bank */
175 0 : pdata = (uint32_t*)BkOpen(buf, "TDC0", TID_UINT32);
176 :
177 : /* following code to "simulates" some TDC data */
178 0 : for (int a = 0; a < 4; a++)
179 0 : *pdata++ = rand()%1024 + rand()%1024 + rand()%1024 + rand()%1024;
180 :
181 0 : BkClose(buf, pdata);
182 :
183 0 : EqSendEvent(buf);
184 0 : }
185 : };
186 :
187 : class EqPeriodic :
188 : public TMFeEquipment
189 : {
190 : public:
191 0 : EqPeriodic(const char* eqname, const char* eqfilename) // ctor
192 0 : : TMFeEquipment(eqname, eqfilename)
193 : {
194 : /* configure your equipment here */
195 :
196 0 : fEqConfReadConfigFromOdb = false;
197 0 : fEqConfEventID = 2;
198 0 : fEqConfBuffer = "SYSTEM";
199 0 : fEqConfPeriodMilliSec = 1000; // in milliseconds
200 0 : fEqConfLogHistory = 1;
201 0 : fEqConfReadOnlyWhenRunning = true;
202 0 : fEqConfWriteEventsToOdb = true;
203 0 : }
204 :
205 0 : void HandlePeriodic()
206 : {
207 : char buf[1024];
208 :
209 0 : ComposeEvent(buf, sizeof(buf));
210 0 : BkInit(buf, sizeof(buf));
211 :
212 : /* create SCLR bank */
213 0 : uint32_t* pdata = (uint32_t*)BkOpen(buf, "PRDC", TID_UINT32);
214 :
215 : /* following code "simulates" some values in sine wave form */
216 0 : for (int a = 0; a < 16; a++)
217 0 : *pdata++ = 100*sin(M_PI*time(NULL)/60+a/2.0)+100;
218 :
219 0 : BkClose(buf, pdata);
220 :
221 0 : EqSendEvent(buf);
222 0 : }
223 : };
224 :
225 : class FeExample: public TMFrontend
226 : {
227 : public:
228 0 : FeExample() // ctor
229 0 : {
230 : /* register with the framework */
231 0 : FeSetName("Sample Frontend");
232 0 : FeAddEquipment(new EqTrigger("Trigger", __FILE__));
233 0 : FeAddEquipment(new EqPeriodic("Periodic", __FILE__));
234 0 : }
235 :
236 0 : TMFeResult HandleFrontendInit(const std::vector<std::string>& args)
237 : {
238 : /* called before equipment HandleInit(), do all hardware initialization here */
239 :
240 0 : printf("frontend init!\n");
241 :
242 0 : return TMFeOk();
243 : };
244 :
245 0 : TMFeResult HandleFrontendReady(const std::vector<std::string>& args)
246 : {
247 : /* called after equipment HandleInit(), anything that needs to be done
248 : * before starting the main loop goes here */
249 :
250 0 : printf("frontend ready!\n");
251 :
252 : /* start periodic and rpc threads here */
253 :
254 : //fMfe->StartPeriodicThread();
255 : //fMfe->StartRpcThread();
256 :
257 0 : return TMFeOk();
258 : };
259 :
260 0 : void HandleFrontendExit()
261 : {
262 : /* hardware shutdown goes here */
263 :
264 0 : printf("frontend exit!\n");
265 0 : };
266 : };
267 :
268 0 : int main(int argc, char* argv[])
269 : {
270 0 : FeExample fe_example;
271 0 : return fe_example.FeMain(argc, argv);
272 0 : }
273 :
274 : /* emacs
275 : * Local Variables:
276 : * tab-width: 8
277 : * c-basic-offset: 3
278 : * indent-tabs-mode: nil
279 : * End:
280 : */
|