source: drsdaq/HVFeedback.cc@ 193

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