source: drsdaq/HVFeedback.cc@ 177

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