source: drsdaq/HVFeedback.cc@ 212

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