source: trunk/FACT++/src/ratescan.cc@ 12203

Last change on this file since 12203 was 12203, checked in by tbretz, 13 years ago
Removed some obsolete output in PrintUsage
File size: 14.1 KB
Line 
1#include <valarray>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10#include "Converter.h"
11#include "DimServiceInfoList.h"
12//#include "PixelMap.h"
13
14#include "tools.h"
15
16#include "LocalControl.h"
17
18#include "HeadersFTM.h"
19
20namespace ba = boost::asio;
21namespace bs = boost::system;
22namespace dummy = ba::placeholders;
23
24using namespace std;
25
26// ------------------------------------------------------------------------
27
28#include "DimDescriptionService.h"
29
30// ------------------------------------------------------------------------
31
32class StateMachineRateScan : public StateMachineDim, public DimInfoHandler
33{
34 /*
35 int Wrap(boost::function<void()> f)
36 {
37 f();
38 return T::GetCurrentState();
39 }
40
41 boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
42 {
43 return bind(&StateMachineMCP::Wrap, this, func);
44 }*/
45
46private:
47 enum states_t
48 {
49 kStateDimNetworkNA = 1,
50 kStateDisconnected,
51 kStateConnecting,
52 kStateConnected,
53 kStateInProgress,
54 };
55
56// PixelMap fMap;
57
58 DimServiceInfoList fNetwork;
59
60 pair<Time, int> fStatusDim;
61 pair<Time, int> fStatusFTM;
62
63 DimStampedInfo fDim;
64 DimStampedInfo fFTM;
65 DimStampedInfo fRates;
66
67 int fCounter;
68 int fSeconds;
69
70 int fSecondsMax;
71 int fThresholdMin;
72 int fThresholdMax;
73 int fThresholdStep;
74
75 uint64_t fTriggers;
76 uint64_t fTriggersBoard[40];
77 uint64_t fTriggersPatch[160];
78
79 uint64_t fOnTimeStart;
80
81 float fResolution;
82
83 pair<Time, int> GetNewState(DimStampedInfo &info) const
84 {
85 const bool disconnected = info.getSize()==0;
86
87 // Make sure getTimestamp is called _before_ getTimestampMillisecs
88 const int tsec = info.getTimestamp();
89 const int tms = info.getTimestampMillisecs();
90
91 return make_pair(Time(tsec, tms*1000),
92 disconnected ? -2 : info.getQuality());
93 }
94
95 bool CheckEventSize(size_t has, const char *name, size_t size)
96 {
97 if (has==size)
98 return true;
99
100 ostringstream msg;
101 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
102 Fatal(msg);
103 return false;
104 }
105
106 void infoHandler()
107 {
108 DimInfo *curr = getInfo(); // get current DimInfo address
109 if (!curr)
110 return;
111
112 if (curr==&fFTM)
113 {
114 fStatusFTM = GetNewState(fFTM);
115 return;
116 }
117
118 if (curr==&fDim)
119 {
120 fStatusDim = GetNewState(fDim);
121 fStatusDim.second = curr->getSize()==4 ? curr->getInt() : 0;
122 return;
123 }
124
125 if (curr==&fRates)
126 {
127 if (curr->getSize()!=sizeof(FTM::DimTriggerRates))
128 return;
129
130 if (fCounter<0 || fStatusFTM.second!=FTM::kTakingData)
131 return;
132
133 const FTM::DimTriggerRates &sdata = *static_cast<FTM::DimTriggerRates*>(curr->getData());
134
135 if (fSeconds++<0)
136 return;
137
138 if (fSeconds==0)
139 {
140 fTriggers = 0;
141
142 memset(fTriggersBoard, 0, 40*sizeof(uint64_t));
143 memset(fTriggersPatch, 0, 160*sizeof(uint64_t));
144
145 fOnTimeStart = sdata.fOnTimeCounter;
146 return;
147 }
148
149 fTriggers += sdata.fTriggerRate;
150 for (int i=0; i<40; i++)
151 fTriggersBoard[i] += sdata.fBoardRate[i];
152 for (int i=0; i<40; i++)
153 fTriggersPatch[i] += sdata.fPatchRate[i];
154
155 if (sqrt(fTriggers)>fResolution*fTriggers && fSeconds<fSecondsMax)
156 {
157 cout << "Triggers so far: " << fTriggers << " (" << sqrt(fTriggers)/fTriggers << ")" << endl;
158 return;
159 }
160
161 ostringstream sout1, sout2, sout3;
162
163 sout1 << fThresholdMin+fCounter*fThresholdStep << " ";
164 sout1 << float(fTriggers)/fSeconds << " ";
165 for (int i=0; i<40; i++)
166 sout2 << float(fTriggersBoard[i])/fSeconds << " ";
167 for (int i=0; i<160; i++)
168 sout2 << float(fTriggersPatch[i])/fSeconds << " ";
169 sout3 << fSeconds << " ";
170 sout3 << float(sdata.fOnTimeCounter-fOnTimeStart)/fSeconds;
171
172 cout << sout1.str() << sout3.str() << endl;
173
174
175 ofstream fout("ratescan.txt", ios::app);
176 fout << sout1.str() << sout2.str() << sout3.str() << endl;
177
178
179 fCounter++;
180 fSeconds = -2;
181
182 if (fThresholdMin+fCounter*fThresholdStep>fThresholdMax)
183 {
184 fCounter = -1;
185 DimClient::sendCommandNB("FTM_CONTROL/STOP_RUN", NULL, 0);
186 return;
187 }
188
189 const int32_t data[2] = { -1, fThresholdMin+fCounter*fThresholdStep };
190 DimClient::sendCommandNB("FTM_CONTROL/SET_THRESHOLD", (void*)data, 8);
191 }
192 }
193
194 void PrintState(const pair<Time,int> &state, const char *server)
195 {
196 const State rc = fNetwork.GetState(server, state.second);
197
198 Out() << state.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
199 Out() << kBold << server << ": ";
200 Out() << rc.name << "[" << rc.index << "]";
201 Out() << kReset << " - " << kBlue << rc.comment << endl;
202 }
203
204 int Print()
205 {
206 Out() << fStatusDim.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
207 Out() << kBold << "DIM_DNS: ";
208 if (fStatusDim.second==0)
209 Out() << "Offline" << endl;
210 else
211 Out() << "V" << fStatusDim.second/100 << 'r' << fStatusDim.second%100 << endl;
212
213 PrintState(fStatusFTM, "FTM_CONTROL");
214
215 return GetCurrentState();
216 }
217
218 int StartRateScan()
219 {
220 Dim::SendCommand("FAD_CONTROL/SET_FILE_FORMAT", uint16_t(0));
221
222 const int32_t data[2] = { -1, fThresholdMin };
223
224 Message("Starting Trigger (FTM)");
225 Dim::SendCommand("FTM_CONTROL/SET_PRESCALING", int32_t(0));
226 Dim::SendCommand("FTM_CONTROL/SET_THRESHOLD", data);
227 Dim::SendCommand("FTM_CONTROL/START_RUN");
228
229 fCounter = 0;
230 fSeconds = -2;
231
232 return GetCurrentState();
233 }
234
235 int StopRateScan()
236 {
237 fCounter = -1;
238
239 if (fStatusFTM.second==FTM::kTakingData)
240 {
241 Message("Stopping FTM");
242 Dim::SendCommand("FTM_CONTROL/STOP_RUN");
243 }
244
245 return GetCurrentState();
246 }
247
248 int Execute()
249 {
250 // Dispatch (execute) at most one handler from the queue. In contrary
251 // to run_one(), it doesn't wait until a handler is available
252 // which can be dispatched, so poll_one() might return with 0
253 // handlers dispatched. The handlers are always dispatched/executed
254 // synchronously, i.e. within the call to poll_one()
255 //poll_one();
256
257 if (fStatusDim.second==0)
258 return kStateDimNetworkNA;
259
260 // All subsystems are not connected
261 if (fStatusFTM.second<FTM::kConnected)
262 return kStateDisconnected;
263
264 // At least one subsystem is not connected
265 // if (fStatusFTM.second>=FTM::kConnected)
266 return fCounter<0 ? kStateConnected : kStateInProgress;
267 }
268
269public:
270 StateMachineRateScan(ostream &out=cout) : StateMachineDim(out, "RATE_SCAN"),
271 fStatusDim(make_pair(Time(), -2)),
272 fStatusFTM(make_pair(Time(), -2)),
273 fDim("DIS_DNS/VERSION_NUMBER", (void*)NULL, 0, this),
274 fFTM("FTM_CONTROL/STATE", (void*)NULL, 0, this),
275 fRates("FTM_CONTROL/TRIGGER_RATES", (void*)NULL, 0, this)
276 {
277 // ba::io_service::work is a kind of keep_alive for the loop.
278 // It prevents the io_service to go to stopped state, which
279 // would prevent any consecutive calls to run()
280 // or poll() to do nothing. reset() could also revoke to the
281 // previous state but this might introduce some overhead of
282 // deletion and creation of threads and more.
283
284 // State names
285 AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
286 "The Dim DNS is not reachable.");
287
288 AddStateName(kStateDisconnected, "Disconnected",
289 "The Dim DNS is reachable, but the required subsystems are not available.");
290
291 AddStateName(kStateConnected, "Connected",
292 "All needed subsystems are connected to their hardware, no action is performed.");
293
294 AddStateName(kStateInProgress, "InProgress",
295 "Rate scan in progress.");
296
297 AddEvent("START", kStateConnected)
298 (bind(&StateMachineRateScan::StartRateScan, this))
299 ("");
300
301 AddEvent("START", kStateConnected)
302 (bind(&StateMachineRateScan::StartRateScan, this))
303 ("");
304
305 AddEvent("STOP", kStateInProgress)
306 (bind(&StateMachineRateScan::StopRateScan, this))
307 ("");
308/*
309 AddEvent("ENABLE_OUTPUT", "B:1")//, kStateIdle)
310 (bind(&StateMachineRateScan::EnableOutput, this, placeholders::_1))
311 ("Enable sending of correction values caluclated by the control loop to the biasctrl");
312
313 AddEvent("STORE_REFERENCE")//, kStateIdle)
314 (bind(&StateMachineRateScan::StoreReference, this))
315 ("Store the last (averaged) value as new reference (for debug purpose only)");
316
317 AddEvent("SET_REFERENCE", "F:1")//, kStateIdle)
318 (bind(&StateMachineRateScan::SetReference, this, placeholders::_1))
319 ("Set a new global reference value (for debug purpose only)");
320
321 AddEvent("SET_Ki", "D:1")//, kStateIdle)
322 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 0))
323 ("Set integral constant Ki");
324
325 AddEvent("SET_Kp", "D:1")//, kStateIdle)
326 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 1))
327 ("Set proportional constant Kp");
328
329 AddEvent("SET_Kd", "D:1")//, kStateIdle)
330 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 2))
331 ("Set derivative constant Kd");
332
333 AddEvent("SET_T", "D:1")//, kStateIdle)
334 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 3))
335 ("Set time-constant. (-1 to use the cycle time, i.e. the time for the last average cycle, instead)");
336
337 // Verbosity commands
338// AddEvent("SET_VERBOSE", "B:1")
339// (bind(&StateMachineMCP::SetVerbosity, this, placeholders::_1))
340// ("set verbosity state"
341// "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
342*/
343 AddEvent("PRINT")
344 (bind(&StateMachineRateScan::Print, this))
345 ("");
346 }
347
348 int EvalOptions(Configuration &conf)
349 {
350 /*
351 if (!fMap.Read(conf.Get<string>("pixel-map-file")))
352 {
353 Error("Reading mapping table from "+conf.Get<string>("pixel-map-file")+" failed.");
354 return 1;
355 }*/
356
357 fThresholdMin = 100;
358 fThresholdMax = 1000;
359 fThresholdStep = 25;
360 fSecondsMax = 150;
361 fResolution = 0.05;
362
363 return -1;
364 }
365};
366
367// ------------------------------------------------------------------------
368
369#include "Main.h"
370
371template<class T>
372int RunShell(Configuration &conf)
373{
374 return Main::execute<T, StateMachineRateScan>(conf);
375}
376
377void SetupConfiguration(Configuration &conf)
378{
379 /*
380 po::options_description control("Rate scan options");
381 control.add_options()
382 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage.")
383 ;
384
385 conf.AddOptions(control);
386 */
387}
388
389/*
390 Extract usage clause(s) [if any] for SYNOPSIS.
391 Translators: "Usage" and "or" here are patterns (regular expressions) which
392 are used to match the usage synopsis in program output. An example from cp
393 (GNU coreutils) which contains both strings:
394 Usage: cp [OPTION]... [-T] SOURCE DEST
395 or: cp [OPTION]... SOURCE... DIRECTORY
396 or: cp [OPTION]... -t DIRECTORY SOURCE...
397 */
398void PrintUsage()
399{
400 cout <<
401 /*
402 "The feedback control the BIAS voltages based on the calibration signal.\n"
403 "\n"
404 "The default is that the program is started without user intercation. "
405 "All actions are supposed to arrive as DimCommands. Using the -c "
406 "option, a local shell can be initialized. With h or help a short "
407 "help message about the usuage can be brought to the screen.\n"
408 "\n"*/
409 "Usage: ratescan [-c type] [OPTIONS]\n"
410 " or: ratescan [OPTIONS]\n";
411 cout << endl;
412}
413
414void PrintHelp()
415{
416 /* Additional help text which is printed after the configuration
417 options goes here */
418
419 /*
420 cout << "bla bla bla" << endl << endl;
421 cout << endl;
422 cout << "Environment:" << endl;
423 cout << "environment" << endl;
424 cout << endl;
425 cout << "Examples:" << endl;
426 cout << "test exam" << endl;
427 cout << endl;
428 cout << "Files:" << endl;
429 cout << "files" << endl;
430 cout << endl;
431 */
432}
433
434int main(int argc, const char* argv[])
435{
436 Configuration conf(argv[0]);
437 conf.SetPrintUsage(PrintUsage);
438 Main::SetupConfiguration(conf);
439 SetupConfiguration(conf);
440
441 if (!conf.DoParse(argc, argv, PrintHelp))
442 return -1;
443
444 //try
445 {
446 // No console access at all
447 if (!conf.Has("console"))
448 {
449// if (conf.Get<bool>("no-dim"))
450// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
451// else
452 return RunShell<LocalStream>(conf);
453 }
454 // Cosole access w/ and w/o Dim
455/* if (conf.Get<bool>("no-dim"))
456 {
457 if (conf.Get<int>("console")==0)
458 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
459 else
460 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
461 }
462 else
463*/ {
464 if (conf.Get<int>("console")==0)
465 return RunShell<LocalShell>(conf);
466 else
467 return RunShell<LocalConsole>(conf);
468 }
469 }
470 /*catch (std::exception& e)
471 {
472 cerr << "Exception: " << e.what() << endl;
473 return -1;
474 }*/
475
476 return 0;
477}
Note: See TracBrowser for help on using the repository browser.