source: drsdaq/HVFeedback.cc@ 202

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