source: drsdaq/HVFeedback.cc@ 230

Last change on this file since 230 was 229, checked in by ogrimm, 14 years ago
Config requests non-blocking if not made from main thread, adapted all servers to GetConfig() returning std::string, workaround for erroneous SERVICE_LIST
File size: 11.7 KB
Line 
1/********************************************************************\
2
3 HVFeedback.cc
4
5 Class handling the feedback of GAPD high voltage
6
7 Oliver Grimm
8
9\********************************************************************/
10
11#include "HVFeedback.h"
12#include "PixelMap.h"
13
14#define PIXMAP_LOCATION "../config/PixelMap.txt"
15
16static const char* FBState_Description[] = {
17 "Feedback off",
18 "Feedback active",
19 "Feedback acquiring new targets",
20 "Feedback measuring response with first voltage",
21 "Feedback measuring response with second voltage"
22};
23
24using namespace std;
25
26//
27// Constructor: Initialise feedback
28//
29HVFeedback::HVFeedback(DAQReadout* DAQClass){
30
31 m = DAQClass;
32
33 fNumberOfChannels = m->GetBoard(0)->GetNumberOfChannels();
34 fNumberOfChips = m->GetBoard(0)->GetNumberOfChips();
35
36 PixMap = new PixelMap(PIXMAP_LOCATION, false);
37
38 // Initialise with zero content
39 Average = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
40 Sigma = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
41 Response = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
42 Target = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
43 Buffer = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
44
45 DIMAverage = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
46 DIMSigma = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
47
48 // Get configuration data
49 fLedTrigBoard = atoi(m->GetConfig("TrigBoard").c_str());
50 fLedTrigChannel = atoi(m->GetConfig("TrigChannel").c_str());
51 fLedTrigChip = atoi(m->GetConfig("TrigChip").c_str());
52 fLedTrigSample = atoi(m->GetConfig("TrigSample").c_str());
53 fLedTrigThreshold = atoi(m->GetConfig("TrigThreshold").c_str());
54 fLedSignalSample = atoi(m->GetConfig("SignalSample").c_str());
55 fLedBaselineSample = atoi(m->GetConfig("BaselineSample").c_str());
56 fIntHalfWidth = atoi(m->GetConfig("IntHalfWidth").c_str());
57 fDefaultNumAverage = atoi(m->GetConfig("DefaultNumAverage").c_str());
58
59 vector<string> Token = m->Tokenize(m->GetConfig("DefaultResponse"), " \t");
60 unsigned int N = 0;
61 for (int i=0; i<m->NumBoards; i++) {
62 for (int j=0; j<fNumberOfChips; j++) {
63 for (int k=0; k<fNumberOfChannels; k++) {
64 if (N < Token.size()) Response[i][j][k] = (float) atof(Token[N++].c_str());
65 }
66 }
67 }
68
69 Token = m->Tokenize(m->GetConfig("DefaultTarget"), " \t");
70 N = 0;
71 for (int i=0; i<m->NumBoards; i++) {
72 for (int j=0; j<fNumberOfChips; j++) {
73 for (int k=0; k<fNumberOfChannels; k++) {
74 if (N < Token.size()) Target[i][j][k] = (float) atof(Token[N++].c_str());
75 }
76 }
77 }
78
79 PrintConfig(MsgToLog);
80
81 // Provide DIM services
82 FeedbackAverage = new DimService (SERVER_NAME"/Average", "F", DIMAverage, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
83 FeedbackSigma = new DimService (SERVER_NAME"/Sigma", "F", DIMSigma, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
84 FeedbackResponse = new DimService (SERVER_NAME"/Response", "F", Response, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
85 FeedbackTarget = new DimService (SERVER_NAME"/Target", "F", Target, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
86 CountService = new DimService (SERVER_NAME"/Count", Count);
87
88 // Initial state
89 Gain = atof(m->GetConfig("DefaultGain").c_str());
90 SetFBMode(FB_Off);
91 SetNumAverages(fDefaultNumAverage);
92 LastServiceUpdate = 0;
93}
94
95//
96// Destructor
97//
98HVFeedback::~HVFeedback() {
99
100 delete CountService;
101 delete FeedbackAverage;
102 delete FeedbackSigma;
103 delete FeedbackResponse;
104 delete FeedbackTarget;
105
106 delete[] Average; delete[] Response;
107 delete[] DIMAverage; delete[] DIMSigma;
108 delete[] Sigma;
109 delete[] Target; delete[] Buffer;
110 delete PixMap;
111}
112
113//
114// Check if LED trigger present, if yes accumulate feedback data and
115// calculate new high voltages if the required number of events is reached.
116//
117bool HVFeedback::ProcessEvent() {
118 int i,j,k,q;
119 float Correction, Integral;
120
121 // Check for LED trigger channel on given channel and if feedback running
122 if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][fLedTrigSample] < fLedTrigThreshold) {
123 return false;
124 }
125
126 // Calculate average signal of LED pulse as integral of signal
127 for (i=m->FirstBoard; i<=m->LastBoard; i++) {
128 for (j=0; j<fNumberOfChips; j++) {
129 for (k=0; k<fNumberOfChannels; k++) {
130 for (Integral=0, q=-fIntHalfWidth; q<=(int) fIntHalfWidth; q++) {
131 Integral += (m->WaveForm[i][j][k][fLedSignalSample+q] - m->WaveForm[i][j][k][fLedBaselineSample+q])*m->GetBoard(i)->GetPrecision();
132 }
133 Integral /= 2*fIntHalfWidth+1;
134 Average[i][j][k] += Integral;
135 Sigma[i][j][k] += pow(Integral,2);
136 }
137 }
138 }
139
140 // Update DIM count service regularly
141 if (time(NULL)-LastServiceUpdate > 2) {
142 LastServiceUpdate = time(NULL);
143 CountService->updateService();
144 }
145 // Check if acquired number of event requires action
146 if (++Count<NumAverages) return false;
147
148 // Feedback action
149 std::stringstream Cmd;
150
151 for (i=m->FirstBoard; i<=m->LastBoard; i++) {
152 for (j=0; j<fNumberOfChips; j++) {
153 for (k=0; k<fNumberOfChannels; k++) {
154 // Calculate average
155 Average[i][j][k] /= Count;
156 Sigma[i][j][k] = sqrt(Sigma[i][j][k]/Count-pow(Average[i][j][k],2))/sqrt(Count);
157 DIMAverage[i][j][k] = Average[i][j][k];
158 DIMSigma[i][j][k] = Sigma[i][j][k];
159
160 switch (FBMode) {
161 case FB_Active: // Determine correction from response maxtrix and change voltages
162 Correction = -(Target[i][j][k] - Average[i][j][k])*Response[i][j][k]*Gain;
163 if (fabs(Correction) > 0.1) Correction = fabs(Correction)/Correction*0.1; // Limit changes to 100 mV
164 if(Correction==0 || Target[i][j][k]==0 || PixMap->DRS_to_Pixel(i,j,k).empty()) break;
165 printf("Average of board %d, chip %d, channel %d is %.2f +/- %.2f Correction %.3f\n",i,j,k,Average[i][j][k],Sigma[i][j][k],Correction);
166
167 if(fabs(Average[i][j][k]) < 2*Sigma[i][j][k]) printf("Too noisy!\n");
168 else {
169 Cmd << PixMap->DRS_to_Pixel(i,j,k)+" " << std::showpos << Correction << " ";
170 }
171 break;
172
173 case FB_Targets: // Take average as new targets
174 Target[i][j][k] = Average[i][j][k];
175 break;
176
177 case FB_ResponseFirst: // First point of response measurement done
178 Buffer[i][j][k] = Average[i][j][k];
179 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) {
180 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << DiffVoltage << " ";
181 }
182 break;
183
184 case FB_ResponseSecond: // Determine response from signal variation
185 if(Buffer[i][j][k] == Average[i][j][k]) {
186 m->PrintMessage("HV Feedback: Warning, response singular for board %d, chip %d, channel %d.\n",i,j,k);
187 Response[i][j][k] = 0;
188 }
189 else Response[i][j][k] = DiffVoltage/(Buffer[i][j][k]-Average[i][j][k]);
190 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) {
191 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << -DiffVoltage/2 << " ";
192 }
193 break;
194
195 default: break; // to suppress warning abount not handled enumeration value
196 }
197 } // for() channels
198 } // for() chips
199 } // for() boards
200
201 // Update DIM service
202 FeedbackAverage->updateService();
203 FeedbackSigma->updateService();
204
205 // Send command
206 if (!Cmd.str().empty()) {
207 DimClient::sendCommand("Bias/Command", ("hv "+Cmd.str()).c_str());
208 }
209
210 switch (FBMode) {
211 case FB_Targets:
212 FeedbackTarget->updateService();
213 m->PrintMessage("HV Feedback: New targets set, switching off.\n");
214 SetFBMode(FB_Off, true);
215 break;
216 case FB_ResponseFirst:
217 SetFBMode(FB_ResponseSecond, true);
218 m->PrintMessage("HV Feedback: Increasing voltages by %f for response measurement, acquiring data.\n", DiffVoltage);
219 break;
220 case FB_ResponseSecond:
221 FeedbackResponse->updateService();
222 m->PrintMessage("HV Feedback: Response measurements finished, original voltages set, switching off.\n");
223 SetFBMode(FB_Off, true);
224 break;
225 default: break; // to suppress warning abount not handled enumeration value
226 }
227 ClearAverages();
228
229 return true;
230}
231
232//
233// Clear average values and event counter
234//
235void HVFeedback::ClearAverages() {
236 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
237 for (int j=0; j<fNumberOfChips; j++)
238 for (int k=0; k<fNumberOfChannels; k++) {
239 Average[i][j][k] = 0.0;
240 Sigma[i][j][k] = 0.0;
241 }
242 Count = 0;
243 CountService->updateService();
244}
245
246//
247// Number of events to accumulate before correction acts
248//
249void HVFeedback::SetNumAverages(unsigned int Averages) {
250 NumAverages = Averages;
251}
252
253//
254// Get requested number of events
255//
256unsigned int HVFeedback::GetNumAverages() {
257 return NumAverages;
258}
259
260//
261// Set feedback gain
262//
263void HVFeedback::SetGain(float FBGain) {
264 Gain = FBGain;
265}
266
267//
268// Get feedback gain
269//
270float HVFeedback::GetGain() {
271 return Gain;
272}
273
274//
275// Set feedback mode and clear averages
276//
277void HVFeedback::SetFBMode(FBState Mode, bool Internal) {
278 if((Mode==FB_ResponseFirst || Mode==FB_ResponseFirst) && !Internal)
279 m->PrintMessage("Start reponse measurement by calling MeasureResponse().\n");
280 else {
281 FBMode = Mode;
282 if (Mode != FB_ResponseFirst) m->Message(m->INFO, "%s", FBState_Description[FBMode]);
283 else m->Message(m->INFO, "%s (voltage difference %.3f)", FBState_Description[FBMode], DiffVoltage);
284 ClearAverages();
285 }
286}
287
288//
289// Get feedback mode
290//
291FBState HVFeedback::GetFBMode() {
292
293 m->PrintMessage("%s.\n", FBState_Description[FBMode]);
294 return FBMode;
295}
296
297//
298// Return current number of events
299//
300unsigned int HVFeedback::GetCurrentCount() {
301 return Count;
302}
303
304//
305// Set target values
306//
307void HVFeedback::SetTarget(int Board, int Chip, int Channel, float TargetVal) {
308
309 if(Board<m->NumBoards && Chip<fNumberOfChips && Channel<fNumberOfChannels) {
310 Target[Board][Chip][Channel] = TargetVal;
311 FeedbackTarget->updateService();
312 }
313 else printf("Invalid board, chip or channel number.\n");
314}
315
316//
317// Print target values
318//
319void HVFeedback::GetTargets() {
320 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
321 for (int j=0; j<fNumberOfChips; j++) {
322 m->PrintMessage("Board %d, chip %d:",i,j);
323 for (int k=0; k<fNumberOfChannels; k++) m->PrintMessage(" %.2f",Target[i][j][k]);
324 m->PrintMessage("\n\r");
325 }
326}
327
328//
329// Measure response matrix
330//
331void HVFeedback::MeasureResponse(float U) {
332
333 std::stringstream Cmd;
334
335 if (U==0) {
336 m->PrintMessage("HV Feedback: Error, voltage difference must not non-zero.\n");
337 return;
338 }
339
340 for (int i=m->FirstBoard; i<=m->LastBoard; i++) {
341 for (int j=0; j<fNumberOfChips; j++) {
342 for (int k=0; k<fNumberOfChannels; k++) {
343 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) {
344 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << -U/2 << " ";
345 }
346 }
347 }
348 }
349
350 // Send command
351 if (!Cmd.str().empty()) {
352 DimClient::sendCommand("Bias/Command", ("hv "+Cmd.str()).c_str());
353 }
354
355 DiffVoltage = U;
356 SetFBMode(FB_ResponseFirst, true);
357 m->PrintMessage("HV Feedback: Decreasing voltages by %f for response measurement, acquiring data.\n",DiffVoltage/2);
358}
359
360//
361// Print response values
362//
363void HVFeedback::GetResponse() {
364 for (int i=m->FirstBoard; i<=m->LastBoard; i++) {
365 for (int j=0; j<fNumberOfChips; j++) {
366 m->PrintMessage("Board %d, chip %d:",i,j);
367 for (int k=0; k<fNumberOfChannels; k++) m->PrintMessage(" %.3f",Response[i][j][k]);
368 m->PrintMessage("\n\r");
369 }
370 }
371}
372
373//
374// Print feedback configuration
375//
376void HVFeedback::PrintConfig(int Target) {
377
378 m->PrintMessage(Target, "LedTrigBoard: %d\t\tLedTrigChip: %d\t\tLedTrigChannel: %d\n"
379 "LedTrigSample: %d\tLedTrigThreshold: %.2f\n"
380 "LedSignalSample: %d\tLedBaselineSample: %d\tDefaultNumAverage: %d\n"
381 "IntHalfWidth:%u\n",
382 fLedTrigBoard, fLedTrigChip, fLedTrigChannel, fLedTrigSample,
383 fLedTrigThreshold, fLedSignalSample, fLedBaselineSample,
384 fDefaultNumAverage, fIntHalfWidth);
385}
Note: See TracBrowser for help on using the repository browser.