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

Last change on this file since 12210 was 12210, checked in by tbretz, 13 years ago
Debuged to make it work.
File size: 14.3 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/1000000;
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
181 if (fSeconds>=fSecondsMax || fThresholdMin+fCounter*fThresholdStep>fThresholdMax)
182 {
183 fCounter = -1;
184 cout << "The END" << endl;
185 //DimClient::sendCommandNB("FTM_CONTROL/STOP_RUN", NULL, 0);
186 return;
187 }
188
189 fSeconds = -2; // FIXME: In principle one missed report is enough
190
191 const int32_t data[2] = { -1, fThresholdMin+fCounter*fThresholdStep };
192 DimClient::sendCommandNB("FTM_CONTROL/SET_THRESHOLD", (void*)data, 8);
193 }
194 }
195
196 void PrintState(const pair<Time,int> &state, const char *server)
197 {
198 const State rc = fNetwork.GetState(server, state.second);
199
200 Out() << state.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
201 Out() << kBold << server << ": ";
202 Out() << rc.name << "[" << rc.index << "]";
203 Out() << kReset << " - " << kBlue << rc.comment << endl;
204 }
205
206 int Print()
207 {
208 Out() << fStatusDim.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
209 Out() << kBold << "DIM_DNS: ";
210 if (fStatusDim.second==0)
211 Out() << "Offline" << endl;
212 else
213 Out() << "V" << fStatusDim.second/100 << 'r' << fStatusDim.second%100 << endl;
214
215 PrintState(fStatusFTM, "FTM_CONTROL");
216
217 return GetCurrentState();
218 }
219
220 int StartRateScan()
221 {
222 Dim::SendCommand("FAD_CONTROL/SET_FILE_FORMAT", uint16_t(0));
223
224 const int32_t data[2] = { -1, fThresholdMin };
225
226 Message("Starting Trigger (FTM)");
227 Dim::SendCommand("FTM_CONTROL/SET_PRESCALING", int32_t(20));
228 Dim::SendCommand("FTM_CONTROL/SET_THRESHOLD", data);
229 //Dim::SendCommand("FTM_CONTROL/STOP_RUN");
230
231 fCounter = 0;
232 fSeconds = -2;
233
234 return GetCurrentState();
235 }
236
237 int StopRateScan()
238 {
239 fCounter = -1;
240
241 //if (fStatusFTM.second==FTM::kTakingData)
242 {
243 Message("Stopping FTM");
244 //Dim::SendCommand("FTM_CONTROL/STOP_RUN");
245 }
246
247 return GetCurrentState();
248 }
249
250 int Execute()
251 {
252 // Dispatch (execute) at most one handler from the queue. In contrary
253 // to run_one(), it doesn't wait until a handler is available
254 // which can be dispatched, so poll_one() might return with 0
255 // handlers dispatched. The handlers are always dispatched/executed
256 // synchronously, i.e. within the call to poll_one()
257 //poll_one();
258
259 if (fStatusDim.second==0)
260 return kStateDimNetworkNA;
261
262 // All subsystems are not connected
263 if (fStatusFTM.second<FTM::kConnected)
264 return kStateDisconnected;
265
266 // At least one subsystem is not connected
267 // if (fStatusFTM.second>=FTM::kConnected)
268 return fCounter<0 ? kStateConnected : kStateInProgress;
269 }
270
271public:
272 StateMachineRateScan(ostream &out=cout) : StateMachineDim(out, "RATE_SCAN"),
273 fStatusDim(make_pair(Time(), -2)),
274 fStatusFTM(make_pair(Time(), -2)),
275 fDim("DIS_DNS/VERSION_NUMBER", (void*)NULL, 0, this),
276 fFTM("FTM_CONTROL/STATE", (void*)NULL, 0, this),
277 fRates("FTM_CONTROL/TRIGGER_RATES", (void*)NULL, 0, this),
278 fCounter(-1)
279 {
280 // ba::io_service::work is a kind of keep_alive for the loop.
281 // It prevents the io_service to go to stopped state, which
282 // would prevent any consecutive calls to run()
283 // or poll() to do nothing. reset() could also revoke to the
284 // previous state but this might introduce some overhead of
285 // deletion and creation of threads and more.
286
287 // State names
288 AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
289 "The Dim DNS is not reachable.");
290
291 AddStateName(kStateDisconnected, "Disconnected",
292 "The Dim DNS is reachable, but the required subsystems are not available.");
293
294 AddStateName(kStateConnected, "Connected",
295 "All needed subsystems are connected to their hardware, no action is performed.");
296
297 AddStateName(kStateInProgress, "InProgress",
298 "Rate scan in progress.");
299
300 AddEvent("START", kStateConnected)
301 (bind(&StateMachineRateScan::StartRateScan, this))
302 ("");
303
304 AddEvent("START", kStateConnected)
305 (bind(&StateMachineRateScan::StartRateScan, this))
306 ("");
307
308 AddEvent("STOP", kStateInProgress)
309 (bind(&StateMachineRateScan::StopRateScan, this))
310 ("");
311/*
312 AddEvent("ENABLE_OUTPUT", "B:1")//, kStateIdle)
313 (bind(&StateMachineRateScan::EnableOutput, this, placeholders::_1))
314 ("Enable sending of correction values caluclated by the control loop to the biasctrl");
315
316 AddEvent("STORE_REFERENCE")//, kStateIdle)
317 (bind(&StateMachineRateScan::StoreReference, this))
318 ("Store the last (averaged) value as new reference (for debug purpose only)");
319
320 AddEvent("SET_REFERENCE", "F:1")//, kStateIdle)
321 (bind(&StateMachineRateScan::SetReference, this, placeholders::_1))
322 ("Set a new global reference value (for debug purpose only)");
323
324 AddEvent("SET_Ki", "D:1")//, kStateIdle)
325 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 0))
326 ("Set integral constant Ki");
327
328 AddEvent("SET_Kp", "D:1")//, kStateIdle)
329 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 1))
330 ("Set proportional constant Kp");
331
332 AddEvent("SET_Kd", "D:1")//, kStateIdle)
333 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 2))
334 ("Set derivative constant Kd");
335
336 AddEvent("SET_T", "D:1")//, kStateIdle)
337 (bind(&StateMachineRateScan::SetConstant, this, placeholders::_1, 3))
338 ("Set time-constant. (-1 to use the cycle time, i.e. the time for the last average cycle, instead)");
339
340 // Verbosity commands
341// AddEvent("SET_VERBOSE", "B:1")
342// (bind(&StateMachineMCP::SetVerbosity, this, placeholders::_1))
343// ("set verbosity state"
344// "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
345*/
346 AddEvent("PRINT")
347 (bind(&StateMachineRateScan::Print, this))
348 ("");
349 }
350
351 int EvalOptions(Configuration &conf)
352 {
353 /*
354 if (!fMap.Read(conf.Get<string>("pixel-map-file")))
355 {
356 Error("Reading mapping table from "+conf.Get<string>("pixel-map-file")+" failed.");
357 return 1;
358 }*/
359
360 fThresholdMin = 0;
361 fThresholdMax = 100;
362 fThresholdStep = 1;
363
364 fSecondsMax = 150;
365 fResolution = 0.05;
366
367 return -1;
368 }
369};
370
371// ------------------------------------------------------------------------
372
373#include "Main.h"
374
375template<class T>
376int RunShell(Configuration &conf)
377{
378 return Main::execute<T, StateMachineRateScan>(conf);
379}
380
381void SetupConfiguration(Configuration &conf)
382{
383 /*
384 po::options_description control("Rate scan options");
385 control.add_options()
386 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage.")
387 ;
388
389 conf.AddOptions(control);
390 */
391}
392
393/*
394 Extract usage clause(s) [if any] for SYNOPSIS.
395 Translators: "Usage" and "or" here are patterns (regular expressions) which
396 are used to match the usage synopsis in program output. An example from cp
397 (GNU coreutils) which contains both strings:
398 Usage: cp [OPTION]... [-T] SOURCE DEST
399 or: cp [OPTION]... SOURCE... DIRECTORY
400 or: cp [OPTION]... -t DIRECTORY SOURCE...
401 */
402void PrintUsage()
403{
404 cout <<
405 /*
406 "The feedback control the BIAS voltages based on the calibration signal.\n"
407 "\n"
408 "The default is that the program is started without user intercation. "
409 "All actions are supposed to arrive as DimCommands. Using the -c "
410 "option, a local shell can be initialized. With h or help a short "
411 "help message about the usuage can be brought to the screen.\n"
412 "\n"*/
413 "Usage: ratescan [-c type] [OPTIONS]\n"
414 " or: ratescan [OPTIONS]\n";
415 cout << endl;
416}
417
418void PrintHelp()
419{
420 /* Additional help text which is printed after the configuration
421 options goes here */
422
423 /*
424 cout << "bla bla bla" << endl << endl;
425 cout << endl;
426 cout << "Environment:" << endl;
427 cout << "environment" << endl;
428 cout << endl;
429 cout << "Examples:" << endl;
430 cout << "test exam" << endl;
431 cout << endl;
432 cout << "Files:" << endl;
433 cout << "files" << endl;
434 cout << endl;
435 */
436}
437
438int main(int argc, const char* argv[])
439{
440 Configuration conf(argv[0]);
441 conf.SetPrintUsage(PrintUsage);
442 Main::SetupConfiguration(conf);
443 SetupConfiguration(conf);
444
445 if (!conf.DoParse(argc, argv, PrintHelp))
446 return -1;
447
448 //try
449 {
450 // No console access at all
451 if (!conf.Has("console"))
452 {
453// if (conf.Get<bool>("no-dim"))
454// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
455// else
456 return RunShell<LocalStream>(conf);
457 }
458 // Cosole access w/ and w/o Dim
459/* if (conf.Get<bool>("no-dim"))
460 {
461 if (conf.Get<int>("console")==0)
462 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
463 else
464 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
465 }
466 else
467*/ {
468 if (conf.Get<int>("console")==0)
469 return RunShell<LocalShell>(conf);
470 else
471 return RunShell<LocalConsole>(conf);
472 }
473 }
474 /*catch (std::exception& e)
475 {
476 cerr << "Exception: " << e.what() << endl;
477 return -1;
478 }*/
479
480 return 0;
481}
Note: See TracBrowser for help on using the repository browser.