source: drsdaq/HVFeedback.cc@ 264

Last change on this file since 264 was 254, checked in by ogrimm, 14 years ago
Replaced mutex by Lock()/Unlock() from Evidence class, added feedback state service
File size: 11.9 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 fNumberOfChannels = m->GetBoard(0)->GetNumberOfChannels();
33 fNumberOfChips = m->GetBoard(0)->GetNumberOfChips();
34
35 PixMap = new PixelMap(PIXMAP_LOCATION, false);
36
37 // Initialise with zero content
38 Average = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
39 Sigma = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
40 Response = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
41 Target = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
42 Buffer = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
43
44 DIMAverage = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
45 DIMSigma = new float [m->NumBoards][kNumberOfChipsMax][kNumberOfChannelsMax]();
46
47 // Get configuration data
48 fLedTrigBoard = atoi(m->GetConfig("TrigBoard").c_str());
49 fLedTrigChannel = atoi(m->GetConfig("TrigChannel").c_str());
50 fLedTrigChip = atoi(m->GetConfig("TrigChip").c_str());
51 fLedTrigSample = atoi(m->GetConfig("TrigSample").c_str());
52 fLedTrigThreshold = atoi(m->GetConfig("TrigThreshold").c_str());
53 fLedSignalSample = atoi(m->GetConfig("SignalSample").c_str());
54 fLedBaselineSample = atoi(m->GetConfig("BaselineSample").c_str());
55 fIntHalfWidth = atoi(m->GetConfig("IntHalfWidth").c_str());
56 fDefaultNumAverage = atoi(m->GetConfig("DefaultNumAverage").c_str());
57
58 vector<string> Token = m->Tokenize(m->GetConfig("DefaultResponse"), " \t");
59 unsigned int N = 0;
60 for (int i=0; i<m->NumBoards; i++) {
61 for (int j=0; j<fNumberOfChips; j++) {
62 for (int k=0; k<fNumberOfChannels; k++) {
63 if (N < Token.size()) Response[i][j][k] = (float) atof(Token[N++].c_str());
64 }
65 }
66 }
67
68 Token = m->Tokenize(m->GetConfig("DefaultTarget"), " \t");
69 N = 0;
70 for (int i=0; i<m->NumBoards; i++) {
71 for (int j=0; j<fNumberOfChips; j++) {
72 for (int k=0; k<fNumberOfChannels; k++) {
73 if (N < Token.size()) Target[i][j][k] = (float) atof(Token[N++].c_str());
74 }
75 }
76 }
77
78 // Provide DIM services
79 FeedbackAverage = new DimService ("Feedback/Average", "F", DIMAverage, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
80 FeedbackSigma = new DimService ("Feedback/Sigma", "F", DIMSigma, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
81 FeedbackResponse = new DimService ("Feedback/Response", "F", Response, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
82 FeedbackTarget = new DimService ("Feedback/Target", "F", Target, m->NumBoards*kNumberOfChipsMax*kNumberOfChannelsMax*sizeof(float));
83 CountService = new DimService ("Feedback/Count", Count);
84 FeedbackState = new DimService ("Feedback/State", "I:1;C", NULL, 0);
85
86 // Initial state
87 Gain = atof(m->GetConfig("DefaultGain").c_str());
88 SetFBMode(FB_Off);
89 SetNumAverages(fDefaultNumAverage);
90 LastServiceUpdate = 0;
91}
92
93//
94// Destructor
95//
96HVFeedback::~HVFeedback() {
97
98 delete FeedbackState;
99 delete CountService;
100 delete FeedbackAverage;
101 delete FeedbackSigma;
102 delete FeedbackResponse;
103 delete FeedbackTarget;
104
105 delete[] Average; delete[] Response;
106 delete[] DIMAverage; delete[] DIMSigma;
107 delete[] Sigma;
108 delete[] Target; delete[] Buffer;
109 delete PixMap;
110}
111
112//
113// Check if LED trigger present, if yes accumulate feedback data and
114// calculate new high voltages if the required number of events is reached.
115//
116bool HVFeedback::ProcessEvent() {
117 int i,j,k,q;
118 float Correction, Integral;
119
120 // Check for LED trigger channel on given channel and if feedback running
121 if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][fLedTrigSample] < fLedTrigThreshold) {
122 return false;
123 }
124
125 // Calculate average signal of LED pulse as integral of signal
126 for (i=m->FirstBoard; i<=m->LastBoard; i++) {
127 for (j=0; j<fNumberOfChips; j++) {
128 for (k=0; k<fNumberOfChannels; k++) {
129 for (Integral=0, q=-fIntHalfWidth; q<=(int) fIntHalfWidth; q++) {
130 Integral += (m->WaveForm[i][j][k][fLedSignalSample+q] - m->WaveForm[i][j][k][fLedBaselineSample+q])*m->GetBoard(i)->GetPrecision();
131 }
132 Integral /= 2*fIntHalfWidth+1;
133 Average[i][j][k] += Integral;
134 Sigma[i][j][k] += pow(Integral,2);
135 }
136 }
137 }
138
139 // Update DIM count service regularly
140 if (time(NULL)-LastServiceUpdate > 2) {
141 LastServiceUpdate = time(NULL);
142 CountService->updateService();
143 }
144 // Check if acquired number of event requires action
145 if (++Count<NumAverages) return false;
146
147 // Feedback action
148 std::stringstream Cmd;
149
150 for (i=m->FirstBoard; i<=m->LastBoard; i++) {
151 for (j=0; j<fNumberOfChips; j++) {
152 for (k=0; k<fNumberOfChannels; k++) {
153 // Calculate average
154 Average[i][j][k] /= Count;
155 Sigma[i][j][k] = sqrt(Sigma[i][j][k]/Count-pow(Average[i][j][k],2))/sqrt(Count);
156 DIMAverage[i][j][k] = Average[i][j][k];
157 DIMSigma[i][j][k] = Sigma[i][j][k];
158
159 switch (FBMode) {
160 case FB_Active:
161 // Determine correction from response maxtrix and change voltages
162 Correction = -(Target[i][j][k] - Average[i][j][k])*Response[i][j][k]*Gain;
163 // Limit voltage steps
164 if (fabs(Correction) > 0.1) Correction = fabs(Correction)/Correction*0.1; // Limit changes to 100 mV
165 // Check if voltage change command possible
166 if(Correction==0 || Target[i][j][k]==0 || PixMap->DRS_to_Pixel(i,j,k).empty()) break;
167 // Add voltage change command if not too noisy
168 if(fabs(Average[i][j][k]) > 2*Sigma[i][j][k]) {
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->PrintMessage("%s\n", FBState_Description[FBMode]);
283 else m->PrintMessage("%s (voltage difference %.3f)\n", FBState_Description[FBMode], DiffVoltage);
284 ClearAverages();
285
286 // Update state service
287 State.State = FBMode;
288 strncpy(State.Text, FBState_Description[FBMode], sizeof(State.Text));
289 FeedbackState->updateService(&State, sizeof(State));
290 }
291}
292
293//
294// Get feedback mode
295//
296FBState HVFeedback::GetFBMode() {
297
298 m->PrintMessage("%s.\n", FBState_Description[FBMode]);
299 return FBMode;
300}
301
302//
303// Return current number of events
304//
305unsigned int HVFeedback::GetCurrentCount() {
306 return Count;
307}
308
309//
310// Set target values
311//
312void HVFeedback::SetTarget(int Board, int Chip, int Channel, float TargetVal) {
313
314 if(Board<m->NumBoards && Chip<fNumberOfChips && Channel<fNumberOfChannels) {
315 Target[Board][Chip][Channel] = TargetVal;
316 FeedbackTarget->updateService();
317 }
318 else printf("Invalid board, chip or channel number.\n");
319}
320
321//
322// Print target values
323//
324void HVFeedback::GetTargets() {
325 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
326 for (int j=0; j<fNumberOfChips; j++) {
327 m->PrintMessage("Board %d, chip %d:",i,j);
328 for (int k=0; k<fNumberOfChannels; k++) m->PrintMessage(" %.2f",Target[i][j][k]);
329 m->PrintMessage("\n\r");
330 }
331}
332
333//
334// Measure response matrix
335//
336void HVFeedback::MeasureResponse(float U) {
337
338 std::stringstream Cmd;
339
340 if (U==0) {
341 m->PrintMessage("HV Feedback: Error, voltage difference must not non-zero.\n");
342 return;
343 }
344
345 for (int i=m->FirstBoard; i<=m->LastBoard; i++) {
346 for (int j=0; j<fNumberOfChips; j++) {
347 for (int k=0; k<fNumberOfChannels; k++) {
348 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) {
349 Cmd << PixMap->DRS_to_Pixel(i,j,k) << " " << std::showpos << -U/2 << " ";
350 }
351 }
352 }
353 }
354
355 // Send command
356 if (!Cmd.str().empty()) {
357 DimClient::sendCommand("Bias/Command", ("hv "+Cmd.str()).c_str());
358 }
359
360 DiffVoltage = U;
361 SetFBMode(FB_ResponseFirst, true);
362 m->PrintMessage("HV Feedback: Decreasing voltages by %f for response measurement, acquiring data.\n",DiffVoltage/2);
363}
364
365//
366// Print response values
367//
368void HVFeedback::GetResponse() {
369 for (int i=m->FirstBoard; i<=m->LastBoard; i++) {
370 for (int j=0; j<fNumberOfChips; j++) {
371 m->PrintMessage("Board %d, chip %d:",i,j);
372 for (int k=0; k<fNumberOfChannels; k++) m->PrintMessage(" %.3f",Response[i][j][k]);
373 m->PrintMessage("\n\r");
374 }
375 }
376}
377
378//
379// Print feedback configuration
380//
381void HVFeedback::PrintConfig() {
382
383 m->PrintMessage("LedTrigBoard: %d\t\tLedTrigChip: %d\t\tLedTrigChannel: %d\n"
384 "LedTrigSample: %d\tLedTrigThreshold: %.2f\n"
385 "LedSignalSample: %d\tLedBaselineSample: %d\tDefaultNumAverage: %d\n"
386 "IntHalfWidth:%u\n",
387 fLedTrigBoard, fLedTrigChip, fLedTrigChannel, fLedTrigSample,
388 fLedTrigThreshold, fLedSignalSample, fLedBaselineSample,
389 fDefaultNumAverage, fIntHalfWidth);
390}
Note: See TracBrowser for help on using the repository browser.