source: drsdaq/HVFeedback.cc@ 183

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