source: trunk/FACT++/src/feedback.cc@ 17869

Last change on this file since 17869 was 17647, checked in by tbretz, 11 years ago
Added average and rms of Uov for logging; some updates to show how the resistance of the broken patches is calculated; ensure that Udrp does not get negative; Do not allow an overvoltage to be less than -0.44V in real this roubly correponds to the breakdown voltage -- that has to be fixed); in all calculation take into account that the assumed overvoltage of 1.1V is wrong and the real one is about 1.4V; all these changes exist since a long time, but are just comitted now
File size: 44.8 KB
Line 
1#include <valarray>
2#include <algorithm>
3
4#include "Dim.h"
5#include "Event.h"
6#include "Shell.h"
7#include "StateMachineDim.h"
8#include "Connection.h"
9#include "Configuration.h"
10#include "Console.h"
11#include "externals/PixelMap.h"
12
13#include "tools.h"
14
15#include "LocalControl.h"
16
17#include "HeadersFSC.h"
18#include "HeadersBIAS.h"
19#include "HeadersFeedback.h"
20
21#include "DimState.h"
22#include "DimDescriptionService.h"
23
24using namespace std;
25
26// ------------------------------------------------------------------------
27
28class StateMachineFeedback : public StateMachineDim
29{
30private:
31 PixelMap fMap;
32
33 bool fIsVerbose;
34
35 DimVersion fDim;
36
37 DimDescribedState fDimFSC;
38 DimDescribedState fDimBias;
39
40 DimDescribedService fDimCalibration;
41 DimDescribedService fDimCalibration2;
42 DimDescribedService fDimCalibrationR8;
43 DimDescribedService fDimCurrents;
44 DimDescribedService fDimOffsets;
45
46 vector<float> fCalibCurrentMes[6]; // Measured calibration current at six different levels
47 vector<float> fCalibVoltage[6]; // Corresponding voltage as reported by biasctrl
48
49 vector<int64_t> fCurrentsAvg;
50 vector<int64_t> fCurrentsRms;
51
52 vector<float> fVoltGapd; // Nominal breakdown voltage + 1.1V
53 vector<float> fBiasVolt; // Output voltage as reported by bias crate (voltage between R10 and R8)
54 vector<float> fBiasR9; //
55 vector<uint16_t> fBiasDac; // Dac value corresponding to the voltage setting
56
57 vector<float> fCalibration;
58 vector<float> fCalibDeltaI;
59 vector<float> fCalibR8;
60
61 int64_t fCursorCur;
62
63 Time fTimeCalib;
64 Time fTimeTemp;
65
66 double fUserOffset;
67 vector<double> fTempOffset;
68 float fTempOffsetAvg;
69 float fTempOffsetRms;
70 double fTempCoefficient;
71 double fTemp;
72
73 vector<double> fVoltOffset;
74
75 uint16_t fCurrentRequestInterval;
76 uint16_t fNumCalibIgnore;
77 uint16_t fNumCalibRequests;
78 uint16_t fCalibStep;
79
80 // ============================= Handle Services ========================
81
82 int HandleBiasStateChange()
83 {
84 if (fDimBias.state()==BIAS::State::kVoltageOn && GetCurrentState()==Feedback::State::kCalibrating)
85 {
86 Dim::SendCommandNB("BIAS_CONTROL/REQUEST_STATUS");
87 Info("Starting calibration step "+to_string(fCalibStep));
88 }
89
90 if (fDimBias.state()==BIAS::State::kVoltageOff && GetCurrentState()==Feedback::State::kInProgress)
91 return Feedback::State::kCalibrated;
92
93 return GetCurrentState();
94 }
95 // ============================= Handle Services ========================
96
97 bool CheckEventSize(size_t has, const char *name, size_t size)
98 {
99 if (has==size)
100 return true;
101
102 // Disconnected
103 if (has==0)
104 return false;
105
106 ostringstream msg;
107 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
108 Fatal(msg);
109 return false;
110 }
111
112 int HandleBiasNom(const EventImp &evt)
113 {
114 if (evt.GetSize()>=416*sizeof(float))
115 {
116 fVoltGapd.assign(evt.Ptr<float>(), evt.Ptr<float>()+416);
117 fBiasR9.assign(evt.Ptr<float>()+2*416, evt.Ptr<float>()+3*416);
118 Info("Nominal bias voltages and calibration resistor received.");
119 }
120
121 return GetCurrentState();
122 }
123
124 int HandleBiasVoltage(const EventImp &evt)
125 {
126 if (evt.GetSize()>=416*sizeof(float))
127 fBiasVolt.assign(evt.Ptr<float>(), evt.Ptr<float>()+416);
128 return GetCurrentState();
129 }
130
131 int HandleBiasDac(const EventImp &evt)
132 {
133 if (evt.GetSize()>=416*sizeof(uint16_t))
134 fBiasDac.assign(evt.Ptr<uint16_t>(), evt.Ptr<uint16_t>()+416);
135 return GetCurrentState();
136 }
137
138 int HandleCameraTemp(const EventImp &evt)
139 {
140 if (!CheckEventSize(evt.GetSize(), "HandleCameraTemp", 323*sizeof(float)))
141 {
142 fTimeTemp = Time(Time::none);
143 return GetCurrentState();
144 }
145
146 //fTempOffset = (avgt-25)*0.0561765; // [V] From Hamamatsu datasheet
147 //fTempOffset = (avgt-25)*0.05678; // [V] From Hamamatsu datasheet plus our own measurement (gein vs. temperature)
148
149 const float *ptr = evt.Ptr<float>(4);
150
151 fTimeTemp = evt.GetTime();
152 fTemp = evt.Get<float>(321*4);
153
154 fTempOffsetAvg = (fTemp-25)*fTempCoefficient;
155 fTempOffsetRms = evt.Get<float>(322*4)*fTempCoefficient;
156
157 fTempOffset.resize(320);
158 for (int i=0; i<320; i++)
159 fTempOffset[i] = (ptr[i]-25)*fTempCoefficient;
160
161 return GetCurrentState();
162 }
163
164 pair<vector<float>, vector<float>> AverageCurrents(const int16_t *ptr, int n)
165 {
166 if (fCursorCur++>=0)
167 {
168 for (int i=0; i<BIAS::kNumChannels; i++)
169 {
170 fCurrentsAvg[i] += ptr[i];
171 fCurrentsRms[i] += ptr[i]*ptr[i];
172 }
173 }
174
175 if (fCursorCur<n)
176 return make_pair(vector<float>(), vector<float>());
177
178 const double conv = 5e-3/4096;
179
180 vector<float> rms(BIAS::kNumChannels);
181 vector<float> avg(BIAS::kNumChannels);
182 for (int i=0; i<BIAS::kNumChannels; i++)
183 {
184 avg[i] = double(fCurrentsAvg[i])/fCursorCur * conv;
185 rms[i] = double(fCurrentsRms[i])/fCursorCur * conv * conv;
186 rms[i] -= avg[i]*avg[i];
187 rms[i] = rms[i]<0 ? 0 : sqrt(rms[i]);
188 }
189
190 return make_pair(avg, rms);
191 }
192
193 int HandleCalibration(const EventImp &evt)
194 {
195 if (fDimBias.state()!=BIAS::State::kVoltageOn)
196 return GetCurrentState();
197
198 const uint16_t dac = 256+512*fCalibStep; // Command value
199
200 // Only the channels which are no spare channels are ramped
201 if (std::count(fBiasDac.begin(), fBiasDac.end(), dac)!=320)
202 return GetCurrentState();
203
204 const auto rc = AverageCurrents(evt.Ptr<int16_t>(), fNumCalibRequests);
205 if (rc.first.size()==0)
206 {
207 Dim::SendCommandNB("BIAS_CONTROL/REQUEST_STATUS");
208 return GetCurrentState();
209 }
210
211 const vector<float> &avg = rc.first;
212 const vector<float> &rms = rc.second;
213
214 // Current through resistor R8
215 fCalibCurrentMes[fCalibStep] = avg; // [A]
216 fCalibVoltage[fCalibStep] = fBiasVolt; // [V]
217
218 // ------------------------- Update calibration data --------------------
219
220 struct cal_data
221 {
222 uint32_t dac;
223 float U[416];
224 float Iavg[416];
225 float Irms[416];
226
227 cal_data() { memset(this, 0, sizeof(cal_data)); }
228 } __attribute__((__packed__));
229
230 cal_data cal;
231 cal.dac = dac;
232 memcpy(cal.U, fBiasVolt.data(), 416*sizeof(float));
233 memcpy(cal.Iavg, avg.data(), 416*sizeof(float));
234 memcpy(cal.Irms, rms.data(), 416*sizeof(float));
235
236 fDimCalibration2.setData(cal);
237 fDimCalibration2.Update(fTimeCalib);
238
239 // -------------------- Start next calibration steo ---------------------
240
241 if (++fCalibStep<6)
242 {
243 fCursorCur = -fNumCalibIgnore;
244 fCurrentsAvg.assign(BIAS::kNumChannels, 0);
245 fCurrentsRms.assign(BIAS::kNumChannels, 0);
246
247 Dim::SendCommandNB("BIAS_CONTROL/SET_GLOBAL_DAC", uint32_t(256+512*fCalibStep));
248
249 return GetCurrentState();
250 }
251
252 // --------------- Calculate old style calibration ----------------------
253
254 fCalibration.resize(BIAS::kNumChannels*4);
255
256 float *pavg = fCalibration.data();
257 float *prms = fCalibration.data()+BIAS::kNumChannels;
258 float *pres = fCalibration.data()+BIAS::kNumChannels*2;
259 float *pUmes = fCalibration.data()+BIAS::kNumChannels*3;
260
261 for (int i=0; i<BIAS::kNumChannels; i++)
262 {
263 const double I = fCalibCurrentMes[5][i]; // [A]
264 const double U = fBiasVolt[i]; // [V]
265
266 pavg[i] = I*1e6; // [uA]
267 prms[i] = rms[i]*1e6; // [uA]
268 pres[i] = U/I; // [Ohm]
269 pUmes[i] = U; // [V]
270 }
271
272 fDimCalibration.setData(fCalibration);
273 fDimCalibration.Update(fTimeCalib);
274
275 // -------------------- New style calibration --------------------------
276
277 fCalibDeltaI.resize(BIAS::kNumChannels);
278 fCalibR8.resize(BIAS::kNumChannels);
279
280 // Linear regression of the values at 256+512*N for N={ 3, 4, 5 }
281 for (int i=0; i<BIAS::kNumChannels; i++)
282 {
283 // x: Idac
284 // y: Iadc
285
286 double x = 0;
287 double y = 0;
288 double xx = 0;
289 double xy = 0;
290
291 const int beg = 3;
292 const int end = 5;
293 const int len = end-beg+1;
294
295 for (int j=beg; j<=end; j++)
296 {
297 const double Idac = (256+512*j)*1e-3/4096;
298
299 x += Idac;
300 xx += Idac*Idac;
301 y += fCalibCurrentMes[j][i];
302 xy += fCalibCurrentMes[j][i]*Idac;
303 }
304
305 const double m1 = xy - x*y / len;
306 const double m2 = xx - x*x / len;
307
308 const double m = m2==0 ? 0 : m1/m2;
309
310 const double t = (y - m*x) / len;
311
312 fCalibDeltaI[i] = t; // [A]
313 fCalibR8[i] = 100/m; // [Ohm]
314 }
315
316 vector<float> v;
317 v.reserve(BIAS::kNumChannels*2);
318 v.insert(v.end(), fCalibDeltaI.begin(), fCalibDeltaI.end());
319 v.insert(v.end(), fCalibR8.begin(), fCalibR8.end());
320
321 fDimCalibrationR8.setData(v);
322 fDimCalibrationR8.Update(fTimeCalib);
323
324 // ---------------------------------------------------------------------
325
326 Info("Calibration successfully done.");
327 Dim::SendCommandNB("BIAS_CONTROL/SET_ZERO_VOLTAGE");
328
329 return Feedback::State::kCalibrated;
330 }
331
332 int HandleBiasCurrent(const EventImp &evt)
333 {
334 if (!CheckEventSize(evt.GetSize(), "HandleBiasCurrent", BIAS::kNumChannels*sizeof(uint16_t)))
335 return Feedback::State::kConnected;
336
337 if (GetCurrentState()<Feedback::State::kCalibrating)
338 return GetCurrentState();
339
340 // ------------------------------- HandleCalibration -----------------------------------
341 if (GetCurrentState()==Feedback::State::kCalibrating)
342 return HandleCalibration(evt);
343
344 // ---------------------- Calibrated, WaitingForData, InProgress -----------------------
345
346 // We are waiting but no valid temperature yet, go on waiting
347 if (GetCurrentState()==Feedback::State::kWaitingForData &&
348 (!fTimeTemp.IsValid() || Time()-fTimeTemp>boost::posix_time::minutes(5)))
349 return GetCurrentState();
350
351 // We are already in progress but no valid temperature update anymore
352 if (GetCurrentState()==Feedback::State::kInProgress &&
353 (!fTimeTemp.IsValid() || Time()-fTimeTemp>boost::posix_time::minutes(5)))
354 {
355 Warn("Current control in progress, but last received temperature older than 5min... switching voltage off.");
356 Dim::SendCommandNB("BIAS_CONTROL/SET_ZERO_VOLTAGE");
357 return Feedback::State::kCalibrated;
358 }
359
360 // ---------------------- Calibrated, WaitingForData, InProgress -----------------------
361
362 const int Navg = fDimBias.state()!=BIAS::State::kVoltageOn ? 1 : 3;
363
364 const vector<float> &Imes = AverageCurrents(evt.Ptr<int16_t>(), Navg).first;
365 if (Imes.size()==0)
366 return GetCurrentState();
367
368 fCurrentsAvg.assign(416, 0);
369 fCurrentsRms.assign(416, 0);
370 fCursorCur = 0;
371
372 // -------------------------------------------------------------------------------------
373
374 // Nominal overvoltage (w.r.t. the bias setup values)
375 const double overvoltage = GetCurrentState()<Feedback::State::kWaitingForData ? 0 : fUserOffset;
376
377 double avg[2] = { 0, 0 };
378 double min[2] = { 90, 90 };
379 double max[2] = { -90, -90 };
380 int num[3] = { 0, 0, 0 };
381
382 vector<double> med[3];
383 med[0].resize(416);
384 med[1].resize(416);
385 med[2].resize(416);
386
387 struct dim_data
388 {
389 float I[416];
390 float Iavg;
391 float Irms;
392 float Imed;
393 float Idev;
394 uint32_t N;
395 float Tdiff;
396 float Uov[416];
397 float Unom;
398 float dUtemp;
399
400 dim_data() { memset(this, 0, sizeof(dim_data)); }
401 } __attribute__((__packed__));
402
403 int Ndev[3] = { 0, 0, 0 };
404
405 dim_data data;
406
407 data.Unom = overvoltage;
408 data.dUtemp = fTempOffsetAvg;
409
410 vector<float> vec(416);
411
412 /*
413 if (fEnableOldAlgorithm)
414 {
415 // ================================= old =======================
416 // Pixel 583: 5 31 == 191 (5) C2 B3 P3
417 // Pixel 830: 2 2 == 66 (4) C0 B8 P1
418 // Pixel 1401: 6 1 == 193 (5) C2 B4 P0
419
420 // 3900 Ohm/n + 1000 Ohm + 1100 Ohm (with n=4 or n=5)
421 const double R[2] = { 3075, 2870 };
422
423 const float *Iavg = fCalibration.data(); // Offset at U=fCalibrationOffset
424 const float *Ravg = fCalibration.data()+BIAS::kNumChannels*2; // Measured resistance
425
426 for (int i=0; i<320; i++)
427 {
428 const PixelMapEntry &hv = fMap.hv(i);
429 if (!hv)
430 continue;
431
432 // Average measured current
433 const double Im = Imes[i] * 1e6; // [uA]
434
435 // Group index (0 or 1) of the of the pixel (4 or 5 pixel patch)
436 const int g = hv.group();
437
438 // Serial resistors in front of the G-APD
439 double Rg = R[g];
440
441 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
442 if (i==66) // Pixel 830(66)
443 Rg = 2400; // 2400 = (3/3900 + 1/390) + 1000 + 1100
444 if (i==191 || i==193) // Pixel 583(191) / Pixel 1401(193)
445 Rg = 2379; // 2379 = (4/3900 + 1/390) + 1000 + 1100
446
447 const double r = 1./(1./Rg + 1./Ravg[i]); // [Ohm]
448
449 // Offset induced by the voltage above the calibration point
450 const double Ubd = fVoltGapd[i] + fTempOffsets[i];
451 const double U0 = Ubd + overvoltage - fCalibVoltage[5][i]; // appliedOffset-fCalibrationOffset;
452 const double dI = U0/Ravg[i]; // [V/Ohm]
453
454 // Offset at the calibration point (make sure that the calibration is
455 // valid (Im[i]>Iavg[i]) and we operate above the calibration point)
456 const double I = Im>Iavg[i] ? Im - Iavg[i] : 0; // [uA]
457
458 // Make sure that the averaged resistor is valid
459 const double dU = Ravg[i]>10000 ? r*(I*1e-6 - dI) : 0;
460
461 vec[i] = Ubd + overvoltage + dU;
462
463 // Calculate statistics only for channels with a valid calibration
464 if (Iavg[i]>0)
465 {
466 med[g][num[g]] = dU;
467 avg[g] += dU;
468 num[g]++;
469
470 if (dU<min[g])
471 min[g] = dU;
472 if (dU>max[g])
473 max[g] = dU;
474
475 data.I[i] = Imes[i]*1e6 - fBiasVolt[i]/Ravg[i]*1e6;
476 data.I[i] /= hv.count();
477
478 if (i==66)
479 data.I[i] /= 1.3;
480 if (i==191 || i==193)
481 data.I[i] /= 1.4;
482
483 data.Iavg += data.I[i];
484 data.Irms += data.I[i]*data.I[i];
485
486 med[2][num[2]++] = data.I[i];
487 }
488 }
489 }
490 */
491
492 double UdrpAvg = 0;
493 double UdrpRms = 0;
494
495 for (int i=0; i<320/*BIAS::kNumChannels*/; i++)
496 {
497 const PixelMapEntry &hv = fMap.hv(i);
498 if (!hv)
499 continue;
500
501 // Number of G-APDs in this patch
502 const int N = hv.count();
503
504 // Average measured ADC value for this channel
505 const double adc = Imes[i]/* * (5e-3/4096)*/; // [A]
506
507 // Current through ~100 Ohm measurement resistor
508 //const double I8 = (adc-fCalibDeltaI[i])*fCalibR8[i]/100;
509 const double I8 = adc-fCalibDeltaI[i];
510
511 // Current through calibration resistors (R9)
512 // This is uncalibrated, but since the corresponding calibrated
513 // value I8 is subtracted, the difference should yield a correct value
514 const double I9 = fBiasDac[i] * (1e-3/4096);//U9/R9; [A]
515
516 // Current in R4/R5 branch
517 //const double Iout = I8 - I9;//I8>I9 ? I8 - I9 : 0;
518 const double Iout = I8 - I9*100/fCalibR8[i];//I8>I9 ? I8 - I9 : 0;
519
520 // Applied voltage at calibration resistors, according to biasctrl
521 const double U9 = fBiasVolt[i];
522
523 // Serial resistors (one 1kOhm at the output of the bias crate, one 1kOhm in the camera)
524 const double R4 = 2000;
525
526 // Serial resistor of the individual G-APDs
527 double R5 = 3900./N;
528
529 // This is assuming that the broken pixels have a 390 Ohm instead of 3900 Ohm serial resistor
530 if (i==66 || i==193) // Pixel 830(66) / Pixel 583(191)
531 R5 = 1./((N-1)/3900.+1/1000.);
532 if (i==191) // Pixel 1399(193)
533 R5 = 1./((N-1)/3900.+1/390.);
534 if (i==17 || i==206) // dead pixel 923(80) / dead pixel 424(927)
535 R5 = 3900./(N-1); // cannot identify third dead pixel in light-pulser data
536
537 // The measurement resistor
538 const double R8 = 0;
539
540 // Total resistance of branch with diodes (R4+R5)
541 // Assuming that the voltage output of the OpAMP is linear
542 // with the DAC setting and not the voltage at R9, the
543 // additional voltage drop at R8 must be taken into account
544 const double R = R4 + R5 + R8;
545
546 // For the patches with a broken resistor - ignoring the G-APD resistance -
547 // we get:
548 //
549 // I[R=3900] = Iout * 1/(10+(N-1)) = Iout /(N+9)
550 // I[R= 390] = Iout * (1 - 1/(10+(N-1))) = Iout * (N+8)/(N+9)
551 //
552 // I[R=390] / I[R=3900] = N+8
553 //
554 // Udrp = Iout*3900/(N+9) + Iout*1000 + Iout*1000 = Iout * R
555
556 // Voltage drop in R4/R5 branch (for the G-APDs with correct resistor)
557 // The voltage drop should not be <0, otherwise an unphysical value
558 // would be amplified when Uset is calculated.
559 const double Udrp = Iout<0 ? 0 : R*Iout;
560
561 // Nominal breakdown voltage with correction for temperature dependence
562 const double Ubd = fVoltGapd[i] + fVoltOffset[i] + fTempOffset[i];
563
564 // Current overvoltage (at a G-APD with the correct 3900 Ohm resistor)
565 //const double Uov = U9-Udrp-Ubd>0 ? U9-Udrp-Ubd : 0;
566 const double Uov = U9-Udrp-Ubd>-0.44/*-0.34*/ ? U9-Udrp-Ubd : -0.44/*-0.34*/;
567
568 // Iout linear with U9 above Ubd
569 //
570 // Rx = (U9-Ubd)/Iout
571 // I' = (U9'-Ubd) / Rx
572 // Udrp' = R*I'
573 // Uov = U9' - Udrp' - Ubd
574 // Uov = overvoltage
575 //
576 // overvoltage = U9' - Udrp' - Ubd
577 // overvoltage = U9' - R*I' - Ubd
578 // overvoltage = U9' - R*((U9'-Ubd)/Rx) - Ubd
579 // overvoltage = U9' - U9'*R/Rx + Ubd*R/Rx - Ubd
580 // overvoltage = U9'*(1 - R/Rx) + Ubd*R/Rx - Ubd
581 // overvoltage - Ubd*R/Rx +Ubd = U9'*(1 - R/Rx)
582 // U9' = [ overvoltage - Ubd*R/Rx +Ubd ] / (1 - R/Rx)
583 //
584
585 // The current through one G-APD is the sum divided by the number of G-APDs
586 // (assuming identical serial resistors)
587 double Iapd = Iout/N;
588
589 // Rtot = Uapd/Iout
590 // Ich = Uapd/Rch = (Rtot*Iout) / Rch = Rtot/Rch * Iout
591 //
592 // Rtot = 3900/N
593 // Rch = 3900
594 //
595 // Rtot = 1./((N-1)/3900 + 1/X) X=390 or X=1000
596 // Rch = 3900
597 //
598 // Rtot/Rch = 1/((N-1)/3900 + 1/X)/3900
599 // Rtot/Rch = 1/( [ X*(N-1) + 3900 ] / [ 3900 * X ])/3900
600 // Rtot/Rch = X/( [ X*(N-1)/3900 + 1 ] )/3900
601 // Rtot/Rch = X/( [ X*(N-1) + 3900 ] )
602 // Rtot/Rch = 1/( [ (N-1) + 3900/X ] )
603 //
604 // Rtot/Rch[390Ohm] = 1/( [ N + 9.0 ] )
605 // Rtot/Rch[1000Ohm] = 1/( [ N + 2.9 ] )
606 //
607 // In this and the previosu case we neglect the resistance of the G-APDs, but we can make an
608 // assumption: The differential resistance depends more on the NSB than on the PDE,
609 // thus it is at least comparable for all G-APDs in the patch. In addition, although the
610 // G-APD with the 390Ohm serial resistor has the wrong voltage applied, this does not
611 // significantly influences the ohmic resistor or the G-APD because the differential
612 // resistor is large enough that the increase of the overvoltage does not dramatically
613 // increase the current flow as compared to the total current flow.
614 if (i==66 || i==193) // Iout/13 15.8 / Iout/14 16.8
615 Iapd = Iout/(N+2.9);
616 if (i==191) // Iout/7.9 38.3
617 Iapd = Iout/(N+9);
618 if (i==17 || i==206)
619 Iapd = Iout/(N-1);
620
621
622 // 3900 + Rapd = I0 -> Uapd = Utot - 3900*I0
623 // 3900 + Rapd = I0 -> Uapd = Utot - 3900*I0
624 // 3900 + Rapd = I0 -> Uapd = Utot - 3900*I0
625 // 390 + Rx = Ix -> Uapd = Utot - 390*Ix
626
627 // Iout = N*I0 + Ix
628
629 // The differential resistance of the G-APD, i.e. the dependence of the
630 // current above the breakdown voltage, is given by
631 //const double Rapd = Uov/Iapd;
632 // This allows us to estimate the current Iov at the overvoltage we want to apply
633 //const double Iov = overvoltage/Rapd;
634
635 // Estimate set point for over-voltage (voltage drop at the target point)
636 //const double Uset = Ubd + overvoltage + R*Iov*N;
637 //const double Uset = Uov<0.3 ? Ubd + overvoltage + Udrp : Ubd + overvoltage + Udrp*pow(overvoltage/Uov, 1.66);
638 const double Uset =
639
640 // Uov<0 ?
641 // Ubd + overvoltage + Udrp*pow(overvoltage/0.44/*0.34*/+1, 1.85/*1.66*/) :
642 // Ubd + overvoltage + Udrp*pow((overvoltage+0.44/*0.34*/)/(Uov+0.44/*0.34*/), 1.85/*1.66*/);
643
644 // Uov<0 ?
645 // Ubd + overvoltage + Udrp*pow(overvoltage+0.44, 1.3213+0.2475*(overvoltage+0.44)) :
646 // Ubd + overvoltage + Udrp*pow(overvoltage+0.44, 1.3213+0.2475*(overvoltage+0.44))/pow(Uov+0.44, 1.3213+0.2475*(Uov+0.44));
647
648 // This estimation is based on the linear increase of the
649 // gain with voltage and the increase of the crosstalk with
650 // voltage, as measured with the overvoltage-tests (OVTEST)
651
652 Uov+0.44<0.022 ?
653 Ubd + overvoltage + Udrp*
654 exp(0.6*(overvoltage-Uov))*pow((overvoltage+0.44), 0.6) :
655 Ubd + overvoltage + Udrp*
656 exp(0.6*(overvoltage-Uov))*pow((overvoltage+0.44)/(Uov+0.44), 0.6);
657
658
659
660
661 if (fabs(overvoltage-Uov)>0.033)
662 Ndev[0]++;
663 if (fabs(overvoltage-Uov)>0.022)
664 Ndev[1]++;
665 if (fabs(overvoltage-Uov)>0.011)
666 Ndev[2]++;
667
668 // Voltage set point
669 vec[i] = Uset;
670
671 /*
672 if (fDimBias.state()==BIAS::State::kVoltageOn && GetCurrentState()==Feedback::State::kInProgress &&
673 fabs(Uov-overvoltage)>0.033)
674 cout << setprecision(4) << setw(3) << i << ": Uov=" << Uov << " Udrp=" << Udrp << " Iapd=" << Iapd*1e6 << endl;
675 */
676
677 // Calculate statistics only for channels with a valid calibration
678 //if (Uov>0)
679 {
680 const int g = hv.group();
681
682 med[g][num[g]] = Uov;
683 avg[g] += Uov;
684 num[g]++;
685
686 if (Uov<min[g])
687 min[g] = Uov;
688 if (Uov>max[g])
689 max[g] = Uov;
690
691 const double iapd = Iapd*1e6; // A --> uA
692
693 data.I[i] = iapd;
694 data.Iavg += iapd;
695 data.Irms += iapd*iapd;
696
697 data.Uov[i] = Uov;
698
699 med[2][num[2]++] = iapd;
700
701 UdrpAvg += Udrp;
702 UdrpRms += Udrp*Udrp;
703 }
704 }
705
706 // ------------------------------- Update voltages ------------------------------------
707
708 if (GetCurrentState()!=Feedback::State::kCalibrated) // WaitingForData, InProgress
709 {
710 if (fDimBias.state()!=BIAS::State::kRamping)
711 {
712 DimClient::sendCommandNB("BIAS_CONTROL/SET_ALL_CHANNELS_VOLTAGE",
713 vec.data(), BIAS::kNumChannels*sizeof(float));
714
715 UdrpAvg /= 320;
716 UdrpRms /= 320;
717 UdrpRms -= UdrpAvg*UdrpAvg;
718 UdrpRms = UdrpRms<0 ? 0 : sqrt(UdrpRms);
719
720 ostringstream msg;
721 msg << fixed;
722 msg << setprecision(2) << "Sending U: dU(" << fTemp << "degC)="
723 << setprecision(3) << fTempOffsetAvg << "V+-" << fTempOffsetRms << " Udrp="
724 << UdrpAvg << "V+-" << UdrpRms;
725 msg.unsetf(ios_base::floatfield);
726 msg << " Unom=" << overvoltage << "V Uov=" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0) << " [N=" << Ndev[0] << "/" << Ndev[1] << "/" << Ndev[2] << "]";
727 Info(msg);
728 }
729 }
730 else
731 {
732 if (fDimBias.state()==BIAS::State::kVoltageOn)
733 {
734 ostringstream msg;
735 msg << setprecision(4) << "Current status: dU(" << fTemp << "degC)=" << fTempOffsetAvg << "V+-" << fTempOffsetRms << ", Unom=" << overvoltage << "V, Uov=" << (num[0]+num[1]>0?(avg[0]+avg[1])/(num[0]+num[1]):0) << " [N=" << Ndev[0] << "/" << Ndev[1] << "/" << Ndev[2] << "]";
736 Info(msg);
737 }
738
739 }
740
741 if (GetCurrentState()==Feedback::State::kInProgress &&
742 fDimBias.state()==BIAS::State::kRamping)
743 return GetCurrentState();
744
745 // --------------------------------- Console out --------------------------------------
746
747 if (num[0]>0 && num[1]>0 && fIsVerbose && !fDimBias.state()==BIAS::State::kRamping)
748 {
749 sort(med[0].begin(), med[0].begin()+num[0]);
750 sort(med[1].begin(), med[1].begin()+num[1]);
751
752 ostringstream msg;
753 msg << " Avg0=" << setw(7) << avg[0]/num[0] << " | Avg1=" << setw(7) << avg[1]/num[1];
754 Debug(msg);
755
756 msg.str("");
757 msg << " Med0=" << setw(7) << med[0][num[0]/2] << " | Med1=" << setw(7) << med[1][num[1]/2];
758 Debug(msg);
759
760 msg.str("");
761 msg << " Min0=" << setw(7) << min[0] << " | Min1=" << setw(7) << min[1];
762 Debug(msg);
763
764 msg.str("");
765 msg << " Max0=" << setw(7) << max[0] << " | Max1=" << setw(7) << max[1];
766 Debug(msg);
767 }
768
769 // ---------------------------- Calibrated Currents -----------------------------------
770
771 if (num[2]>0)
772 {
773 data.Iavg /= num[2];
774 data.Irms /= num[2];
775 data.Irms -= data.Iavg*data.Iavg;
776
777 data.N = num[2];
778 data.Irms = data.Irms<0 ? 0: sqrt(data.Irms);
779
780 sort(med[2].data(), med[2].data()+num[2]);
781
782 data.Imed = num[2]%2 ? med[2][num[2]/2] : (med[2][num[2]/2-1]+med[2][num[2]/2])/2;
783
784 for (int i=0; i<num[2]; i++)
785 med[2][i] = fabs(med[2][i]-data.Imed);
786
787 sort(med[2].data(), med[2].data()+num[2]);
788
789 data.Idev = med[2][uint32_t(0.682689477208650697*num[2])];
790
791 data.Tdiff = evt.GetTime().UnixTime()-fTimeCalib.UnixTime();
792
793 // FIXME:
794 // + Current overvoltage
795 // + Temp offset
796 // + User offset
797 // + Command overvoltage
798 fDimCurrents.setQuality(GetCurrentState());
799 fDimCurrents.setData(&data, sizeof(dim_data));
800 fDimCurrents.Update(evt.GetTime());
801 }
802
803 return GetCurrentState()==Feedback::State::kCalibrated ? Feedback::State::kCalibrated : Feedback::State::kInProgress;
804 }
805
806 // ======================================================================
807
808 int Print() const
809 {
810 Out() << fDim << endl;
811 Out() << fDimFSC << endl;
812 Out() << fDimBias << endl;
813
814 return GetCurrentState();
815 }
816
817 int PrintCalibration()
818 {
819 /*
820 if (fCalibration.size()==0)
821 {
822 Out() << "No calibration performed so far." << endl;
823 return GetCurrentState();
824 }
825
826 const float *avg = fCalibration.data();
827 const float *rms = fCalibration.data()+BIAS::kNumChannels;
828 const float *res = fCalibration.data()+BIAS::kNumChannels*2;
829
830 Out() << "Average current at " << fCalibrationOffset << "V below G-APD operation voltage:\n";
831
832 for (int k=0; k<13; k++)
833 for (int j=0; j<8; j++)
834 {
835 Out() << setw(2) << k << "|" << setw(2) << j*4 << "|";
836 for (int i=0; i<4; i++)
837 Out() << Tools::Form(" %6.1f+-%4.1f", avg[k*32+j*4+i], rms[k*32+j*4+i]);
838 Out() << '\n';
839 }
840 Out() << '\n';
841
842 Out() << "Measured calibration resistor:\n";
843 for (int k=0; k<13; k++)
844 for (int j=0; j<4; j++)
845 {
846 Out() << setw(2) << k << "|" << setw(2) << j*8 << "|";
847 for (int i=0; i<8; i++)
848 Out() << Tools::Form(" %5.0f", res[k*32+j*8+i]);
849 Out() << '\n';
850 }
851
852 Out() << flush;
853 */
854 return GetCurrentState();
855 }
856
857 int SetVerbosity(const EventImp &evt)
858 {
859 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
860 return kSM_FatalError;
861
862 fIsVerbose = evt.GetBool();
863
864 return GetCurrentState();
865 }
866
867 int SetCurrentRequestInterval(const EventImp &evt)
868 {
869 if (!CheckEventSize(evt.GetSize(), "SetCurrentRequestInterval", 2))
870 return kSM_FatalError;
871
872 fCurrentRequestInterval = evt.GetUShort();
873
874 Info("New current request interval: "+to_string(fCurrentRequestInterval)+"ms");
875
876 return GetCurrentState();
877 }
878
879 int Calibrate()
880 {
881 if (fDimBias.state()!=BIAS::State::kVoltageOff)
882 {
883 Warn("Calibration can only be started when biasctrl is in state VoltageOff.");
884 return GetCurrentState();
885 }
886
887 Message("Starting calibration (ignore="+to_string(fNumCalibIgnore)+", N="+to_string(fNumCalibRequests)+")");
888
889 fCursorCur = -fNumCalibIgnore;
890 fCurrentsAvg.assign(BIAS::kNumChannels, 0);
891 fCurrentsRms.assign(BIAS::kNumChannels, 0);
892
893 fBiasDac.assign(BIAS::kNumChannels, 0);
894
895 fCalibStep = 3;
896 fTimeCalib = Time();
897
898 Dim::SendCommandNB("BIAS_CONTROL/SET_GLOBAL_DAC", uint32_t(256+512*fCalibStep));
899
900 return Feedback::State::kCalibrating;
901 }
902
903 int Start(const EventImp &evt)
904 {
905 if (!CheckEventSize(evt.GetSize(), "Start", 4))
906 return kSM_FatalError;
907
908 if (fDimBias.state()==BIAS::State::kRamping)
909 {
910 Warn("Feedback can not be started when biasctrl is in state Ramping.");
911 return GetCurrentState();
912 }
913
914 fUserOffset = evt.GetFloat();
915
916 fCursorCur = 0;
917
918 fCurrentsAvg.assign(BIAS::kNumChannels, 0);
919 fCurrentsRms.assign(BIAS::kNumChannels, 0);
920
921 ostringstream out;
922 out << "Starting feedback with an offset of " << fUserOffset << "V";
923 Message(out);
924
925 return Feedback::State::kWaitingForData;
926 }
927
928 int StopFeedback()
929 {
930 if (GetCurrentState()==Feedback::State::kCalibrating)
931 return Feedback::State::kConnected;
932
933 if (GetCurrentState()>Feedback::State::kCalibrated)
934 return Feedback::State::kCalibrated;
935
936 return GetCurrentState();
937 }
938
939 bool LoadOffsets(const string &file)
940 {
941 vector<double> data(416);
942
943 ifstream fin(file);
944
945 int cnt = 0;
946 while (fin && cnt<320)
947 fin >> data[cnt++];
948
949 if (cnt!=320)
950 {
951 Error("Reading offsets from "+file+" failed [N="+to_string(cnt-1)+"]");
952 return false;
953 }
954
955 fVoltOffset = data;
956
957 fDimOffsets.Update(fVoltOffset);
958
959 Info("New voltage offsets loaded from "+file);
960 return true;
961
962 }
963
964 int LoadOffset(const EventImp &evt)
965 {
966 LoadOffsets(evt.GetText());
967 return GetCurrentState();
968 }
969
970 int ResetOffset()
971 {
972 fVoltOffset.assign(416, 0);
973
974 fDimOffsets.Update(fVoltOffset);
975
976 Info("Voltage offsets resetted.");
977 return GetCurrentState();
978 }
979
980
981 int Execute()
982 {
983 if (!fDim.online())
984 return Feedback::State::kDimNetworkNA;
985
986 const bool bias = fDimBias.state() >= BIAS::State::kConnecting;
987 const bool fsc = fDimFSC.state() >= FSC::State::kConnected;
988
989 // All subsystems are not connected
990 if (!bias && !fsc)
991 return Feedback::State::kDisconnected;
992
993 // Not all subsystems are yet connected
994 if (!bias || !fsc)
995 return Feedback::State::kConnecting;
996
997 if (GetCurrentState()<Feedback::State::kCalibrating)
998 return Feedback::State::kConnected;
999
1000 if (GetCurrentState()==Feedback::State::kConnected)
1001 return GetCurrentState();
1002 if (GetCurrentState()==Feedback::State::kCalibrating)
1003 return GetCurrentState();
1004
1005 // kCalibrated, kWaitingForData, kInProgress
1006
1007 if (fDimBias.state()==BIAS::State::kVoltageOn || (fDimBias.state()==BIAS::State::kVoltageOff && GetCurrentState()==Feedback::State::kWaitingForData))
1008 {
1009 static Time past;
1010 if (fCurrentRequestInterval>0 && Time()-past>boost::posix_time::milliseconds(fCurrentRequestInterval))
1011 {
1012 Dim::SendCommandNB("BIAS_CONTROL/REQUEST_STATUS");
1013 past = Time();
1014 }
1015 }
1016
1017 return GetCurrentState();
1018 }
1019
1020public:
1021 StateMachineFeedback(ostream &out=cout) : StateMachineDim(out, "FEEDBACK"),
1022 fIsVerbose(false),
1023 //---
1024 fDimFSC("FSC_CONTROL"),
1025 fDimBias("BIAS_CONTROL"),
1026 //---
1027 fDimCalibration("FEEDBACK/CALIBRATION", "F:416;F:416;F:416;F:416",
1028 "Current offsets"
1029 "|Avg[uA]:Average offset at dac=256+5*512"
1030 "|Rms[uA]:Rms of Avg"
1031 "|R[Ohm]:Measured calibration resistor"
1032 "|U[V]:Corresponding voltage reported by biasctrl"),
1033 fDimCalibration2("FEEDBACK/CALIBRATION_STEPS", "I:1;F:416;F:416;F:416",
1034 "Calibration of the R8 resistor"
1035 "|DAC[dac]:DAC setting"
1036 "|U[V]:Corresponding voltages reported by biasctrl"
1037 "|Iavg[uA]:Averaged measured current"
1038 "|Irms[uA]:Rms measured current"),
1039 fDimCalibrationR8("FEEDBACK/CALIBRATION_R8", "F:416;F:416",
1040 "Calibration of R8"
1041 "|DeltaI[uA]:Average offset"
1042 "|R8[uA]:Measured effective resistor R8"),
1043 fDimCurrents("FEEDBACK/CALIBRATED_CURRENTS", "F:416;F:1;F:1;F:1;F:1;I:1;F:1;F:416;F:1;F:1",
1044 "Calibrated currents"
1045 "|I[uA]:Calibrated currents per pixel"
1046 "|I_avg[uA]:Average calibrated current (N channels)"
1047 "|I_rms[uA]:Rms of calibrated current (N channels)"
1048 "|I_med[uA]:Median calibrated current (N channels)"
1049 "|I_dev[uA]:Deviation of calibrated current (N channels)"
1050 "|N[uint16]:Number of valid values"
1051 "|T_diff[s]:Time difference to calibration"
1052 "|U_ov[V]:Calculated overvoltage"
1053 "|U_nom[V]:Nominal overvoltage"
1054 "|dU_temp[V]:Correction calculated from temperature"
1055 ),
1056 fDimOffsets("FEEDBACK/OFFSETS", "F:416",
1057 "Offsets operation voltages"
1058 "|U[V]:Offset per bias channels"),
1059 fVoltOffset(416),
1060 fCurrentRequestInterval(0),
1061 fNumCalibIgnore(30),
1062 fNumCalibRequests(300)
1063 {
1064 fDim.Subscribe(*this);
1065 fDimFSC.Subscribe(*this);
1066 fDimBias.Subscribe(*this);
1067
1068 fDimBias.SetCallback(bind(&StateMachineFeedback::HandleBiasStateChange, this));
1069
1070 Subscribe("BIAS_CONTROL/CURRENT")
1071 (bind(&StateMachineFeedback::HandleBiasCurrent, this, placeholders::_1));
1072 Subscribe("BIAS_CONTROL/VOLTAGE")
1073 (bind(&StateMachineFeedback::HandleBiasVoltage, this, placeholders::_1));
1074 Subscribe("BIAS_CONTROL/DAC")
1075 (bind(&StateMachineFeedback::HandleBiasDac, this, placeholders::_1));
1076 Subscribe("BIAS_CONTROL/NOMINAL")
1077 (bind(&StateMachineFeedback::HandleBiasNom, this, placeholders::_1));
1078 Subscribe("FSC_CONTROL/BIAS_TEMP")
1079 (bind(&StateMachineFeedback::HandleCameraTemp, this, placeholders::_1));
1080
1081 // State names
1082 AddStateName(Feedback::State::kDimNetworkNA, "DimNetworkNotAvailable",
1083 "The Dim DNS is not reachable.");
1084
1085 AddStateName(Feedback::State::kDisconnected, "Disconnected",
1086 "The Dim DNS is reachable, but the required subsystems are not available.");
1087 AddStateName(Feedback::State::kConnecting, "Connecting",
1088 "Either biasctrl or fscctrl not connected.");
1089 AddStateName(Feedback::State::kConnected, "Connected",
1090 "biasctrl and fscctrl are available and connected with their hardware.");
1091
1092 AddStateName(Feedback::State::kCalibrating, "Calibrating",
1093 "Bias crate calibrating in progress.");
1094 AddStateName(Feedback::State::kCalibrated, "Calibrated",
1095 "Bias crate calibrated.");
1096
1097 AddStateName(Feedback::State::kWaitingForData, "WaitingForData",
1098 "Current control started, waiting for valid temperature and current data.");
1099 AddStateName(Feedback::State::kInProgress, "InProgress",
1100 "Current control in progress.");
1101
1102
1103 /*
1104 AddEvent("SET_CURRENT_REQUEST_INTERVAL")
1105 (bind(&StateMachineFeedback::SetCurrentRequestInterval, this, placeholders::_1))
1106 ("|interval[ms]:Interval between two current requests in modes which need that.");
1107 */
1108
1109 AddEvent("CALIBRATE", Feedback::State::kConnected, Feedback::State::kCalibrated)
1110 (bind(&StateMachineFeedback::Calibrate, this))
1111 ("");
1112
1113 AddEvent("START", "F:1", Feedback::State::kCalibrated)
1114 (bind(&StateMachineFeedback::Start, this, placeholders::_1))
1115 ("Start the current/temperature control loop"
1116 "|Uov[V]:Overvoltage to be applied (standard value is 1.1V)");
1117
1118 AddEvent("STOP")
1119 (bind(&StateMachineFeedback::StopFeedback, this))
1120 ("Stop any control loop");
1121
1122 AddEvent("LOAD_OFFSETS", "C", Feedback::State::kConnected, Feedback::State::kCalibrated)
1123 (bind(&StateMachineFeedback::LoadOffset, this, placeholders::_1))
1124 ("");
1125 AddEvent("RESET_OFFSETS", Feedback::State::kConnected, Feedback::State::kCalibrated)
1126 (bind(&StateMachineFeedback::ResetOffset, this))
1127 ("");
1128
1129
1130 AddEvent("PRINT")
1131 (bind(&StateMachineFeedback::Print, this))
1132 ("");
1133 AddEvent("PRINT_CALIBRATION")
1134 (bind(&StateMachineFeedback::PrintCalibration, this))
1135 ("");
1136
1137 // Verbosity commands
1138 AddEvent("SET_VERBOSE", "B:1")
1139 (bind(&StateMachineFeedback::SetVerbosity, this, placeholders::_1))
1140 ("set verbosity state"
1141 "|verbosity[bool]:disable or enable verbosity when calculating overvoltage");
1142 }
1143
1144 int EvalOptions(Configuration &conf)
1145 {
1146 fIsVerbose = !conf.Get<bool>("quiet");
1147
1148 if (!fMap.Read(conf.Get<string>("pixel-map-file")))
1149 {
1150 Error("Reading mapping table from "+conf.Get<string>("pixel-map-file")+" failed.");
1151 return 1;
1152 }
1153
1154 fCurrentRequestInterval = conf.Get<uint16_t>("current-request-interval");
1155 fNumCalibIgnore = conf.Get<uint16_t>("num-calib-ignore");
1156 fNumCalibRequests = conf.Get<uint16_t>("num-calib-average");
1157 fTempCoefficient = conf.Get<double>("temp-coefficient");
1158
1159 if (conf.Has("offset-file"))
1160 LoadOffsets(conf.Get<string>("offset-file"));
1161
1162 return -1;
1163 }
1164};
1165
1166// ------------------------------------------------------------------------
1167
1168#include "Main.h"
1169
1170template<class T>
1171int RunShell(Configuration &conf)
1172{
1173 return Main::execute<T, StateMachineFeedback>(conf);
1174}
1175
1176void SetupConfiguration(Configuration &conf)
1177{
1178 po::options_description control("Feedback options");
1179 control.add_options()
1180 ("quiet,q", po_bool(true), "Disable printing more information on average overvoltagecontents of all received messages (except dynamic data) in clear text.")
1181 ("pixel-map-file", var<string>()->required(), "Pixel mapping file. Used here to get the default reference voltage.")
1182 ("current-request-interval", var<uint16_t>(1000), "Interval between two current requests.")
1183 ("num-calib-ignore", var<uint16_t>(30), "Number of current requests to be ignored before averaging")
1184 ("num-calib-average", var<uint16_t>(300), "Number of current requests to be averaged")
1185 ("temp-coefficient", var<double>()->required(), "Temp. coefficient [V/K]")
1186 ("offset-file", var<string>(), "File with operation voltage offsets")
1187 ;
1188
1189 conf.AddOptions(control);
1190}
1191
1192/*
1193 Extract usage clause(s) [if any] for SYNOPSIS.
1194 Translators: "Usage" and "or" here are patterns (regular expressions) which
1195 are used to match the usage synopsis in program output. An example from cp
1196 (GNU coreutils) which contains both strings:
1197 Usage: cp [OPTION]... [-T] SOURCE DEST
1198 or: cp [OPTION]... SOURCE... DIRECTORY
1199 or: cp [OPTION]... -t DIRECTORY SOURCE...
1200 */
1201void PrintUsage()
1202{
1203 cout <<
1204 "The feedback control the BIAS voltages based on the calibration signal.\n"
1205 "\n"
1206 "The default is that the program is started without user intercation. "
1207 "All actions are supposed to arrive as DimCommands. Using the -c "
1208 "option, a local shell can be initialized. With h or help a short "
1209 "help message about the usuage can be brought to the screen.\n"
1210 "\n"
1211 "Usage: feedback [-c type] [OPTIONS]\n"
1212 " or: feedback [OPTIONS]\n";
1213 cout << endl;
1214}
1215
1216void PrintHelp()
1217{
1218 Main::PrintHelp<StateMachineFeedback>();
1219
1220 /* Additional help text which is printed after the configuration
1221 options goes here */
1222
1223 /*
1224 cout << "bla bla bla" << endl << endl;
1225 cout << endl;
1226 cout << "Environment:" << endl;
1227 cout << "environment" << endl;
1228 cout << endl;
1229 cout << "Examples:" << endl;
1230 cout << "test exam" << endl;
1231 cout << endl;
1232 cout << "Files:" << endl;
1233 cout << "files" << endl;
1234 cout << endl;
1235 */
1236}
1237
1238int main(int argc, const char* argv[])
1239{
1240 Configuration conf(argv[0]);
1241 conf.SetPrintUsage(PrintUsage);
1242 Main::SetupConfiguration(conf);
1243 SetupConfiguration(conf);
1244
1245 if (!conf.DoParse(argc, argv, PrintHelp))
1246 return 127;
1247
1248 //try
1249 {
1250 // No console access at all
1251 if (!conf.Has("console"))
1252 {
1253// if (conf.Get<bool>("no-dim"))
1254// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
1255// else
1256 return RunShell<LocalStream>(conf);
1257 }
1258 // Cosole access w/ and w/o Dim
1259/* if (conf.Get<bool>("no-dim"))
1260 {
1261 if (conf.Get<int>("console")==0)
1262 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
1263 else
1264 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
1265 }
1266 else
1267*/ {
1268 if (conf.Get<int>("console")==0)
1269 return RunShell<LocalShell>(conf);
1270 else
1271 return RunShell<LocalConsole>(conf);
1272 }
1273 }
1274 /*catch (std::exception& e)
1275 {
1276 cerr << "Exception: " << e.what() << endl;
1277 return -1;
1278 }*/
1279
1280 return 0;
1281}
Note: See TracBrowser for help on using the repository browser.