source: drsdaq/HVFeedback.cc@ 91

Last change on this file since 91 was 89, checked in by ogrimm, 15 years ago
Corrected writing of wrong board structure is first chosen board is not also the first physical board
File size: 13.8 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#include <sys/socket.h>
15#include <netdb.h>
16#include <signal.h>
17
18#define MAX_RETRY 5
19#define PIXMAP_LOCATION "../config/PixelMap.txt"
20
21//
22// Constructor: Initialise feedback
23//
24HVFeedback::HVFeedback(DAQReadout* DAQClass, char* Configfile) {
25 struct sockaddr_in SocketAddress;
26 char Filename[MAX_PATH];
27
28 m = DAQClass;
29 PixMap = new PixelMap(PIXMAP_LOCATION, false);
30
31 // Create instance of slow data class for feedback
32 snprintf(Filename,sizeof(Filename),"%s/SlowData/", m->fRawDataPath);
33 SlowDataClass = new SlowData("HVFB", Filename);
34 if (SlowDataClass->ErrorCode != 0) {
35 m->PrintMessage("Warning: Could not open feedback slowdata file (%s)\n", strerror(SlowDataClass->ErrorCode));
36 }
37
38 // Initialise with zero content
39 Average = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
40 Sigma = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
41 Response = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
42 Target = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
43 Buffer = new float [m->NumBoards][kNumberOfChips][kNumberOfChannels]();
44
45 // Read configuration file
46 FILE *File;
47 if ((File = fopen(Configfile,"r")) == NULL) {
48 printf("Error: Could not open feedback configuration file '%s'\n", Configfile);
49 }
50 else {
51 printf("Reading feedback configuration file %s\n", Configfile);
52 ReadCard("TrigBoard", &fLedTrigBoard, 'I', File);
53 ReadCard("TrigChannel", &fLedTrigChannel, 'I', File);
54 ReadCard("TrigChip", &fLedTrigChip, 'I', File);
55 ReadCard("TrigSample", &fLedTrigSample, 'I', File);
56 ReadCard("TrigThreshold", &fLedTrigThreshold, 'f', File);
57 ReadCard("SignalSample", &fLedSignalSample, 'I', File);
58 ReadCard("BaselineSample", &fLedBaselineSample, 'I', File);
59 ReadCard("IntHalfWidth", &fIntHalfWidth, 'U', File);
60 ReadCard("DefaultNumAverage", &fDefaultNumAverage, 'I', File);
61 ReadCard("HVControlServer", fHVControlServer, 's', File);
62 ReadCard("HVControlPort", &fHVControlPort, 'I', File);
63 ReadCard("MaxCmdAckDelay", &fMaxCmdAckDelay, 'I', File);
64 ReadCard("DefaultResponse", Response, 'f', File, m->NumBoards*kNumberOfChips*kNumberOfChannels);
65 fclose(File);
66 }
67 PrintConfig();
68
69 // Initial state
70 Gain = 1;
71 SetFBMode(FB_Off);
72 SetNumAverages(fDefaultNumAverage);
73
74 // Opening socket client to HV control program
75 if ((SocketDescriptor = socket(PF_INET, SOCK_STREAM, 0)) == -1)
76 m->PrintMessage("Could not open client socket, no HV control available.\n");
77
78 // Resolve hostname and try to connect to server
79 struct hostent *hostent = gethostbyname(fHVControlServer);
80 if (hostent==0)
81 m->PrintMessage("Could not resolve HV server host name \"%s\".\n", fHVControlServer);
82 else {
83 SocketAddress.sin_family = PF_INET;
84 SocketAddress.sin_port = htons((unsigned short) fHVControlPort);
85 SocketAddress.sin_addr = *(struct in_addr*) hostent->h_addr;
86
87 if (connect(SocketDescriptor, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress))==-1)
88 m->PrintMessage("Could not connect to HV server %s at port %d (%s)\n", fHVControlServer, fHVControlPort, strerror(errno));
89 else m->PrintMessage("\nFeedback connected to HV server %s (port %d).\n", fHVControlServer, fHVControlPort);
90 signal(SIGPIPE,SIG_IGN); // Do not kill process if writing to closed socket
91 }
92}
93
94//
95// Destructor
96//
97HVFeedback::~HVFeedback() {
98 if (SocketDescriptor!=-1) {
99 close(SocketDescriptor);
100 m->PrintMessage("Feeback socket closed.\n");
101 }
102 delete[] Average; delete[] Response;
103 delete[] Target; delete[] Buffer;
104 delete SlowDataClass; delete PixMap;
105}
106
107//
108// Check if LED trigger present, if yes accumulate feedback data and
109// calculate new high voltages if the required number of events is reached.
110//
111bool HVFeedback::ProcessEvent() {
112 int i,j,k,q;
113 float Correction, Integral, Difference, EffectiveGain;
114
115 // Check for LED trigger channel on given channel and if feedback running
116 if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][fLedTrigSample] < fLedTrigThreshold)
117 return false;
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<kNumberOfChips; j++)
122 for (k=0; k<kNumberOfChannels; 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->BStruct[i].ScaleFactor;
125 Integral /= 2*fIntHalfWidth+1;
126 Average[i][j][k] += Integral;
127 Sigma[i][j][k] += pow(Integral,2);
128 }
129
130 if (++Count<NumAverages) return false;
131
132 // Acquired number of event requires action
133 switch (FBMode) {
134 case FB_Active: SlowDataClass->NewEntry("Average");
135 break;
136 case FB_Targets: SlowDataClass->NewEntry("Target");
137 break;
138 case FB_ResponseSecond: SlowDataClass->NewEntry("Response");
139 SlowDataClass->AddToEntry("%.3f ",DiffVoltage);
140 break;
141 default: break; // to suppress warning abount not handled enumeration value
142 }
143
144 for (i=m->FirstBoard; i<=m->LastBoard; i++) {
145 for (j=0; j<kNumberOfChips; j++) {
146 for (k=0; k<kNumberOfChannels; k++) {
147 Average[i][j][k] /= Count;
148 Sigma[i][j][k] = sqrt(Sigma[i][j][k]/Count-pow(Average[i][j][k],2))/sqrt(Count);
149 switch (FBMode) {
150 case FB_Active: // Determine correction from response maxtrix and change voltages
151 Difference = Target[i][j][k] - Average[i][j][k];
152 EffectiveGain = Gain*pow(0.5*(1+(Difference/Sigma[i][j][k]-1)/(Difference/Sigma[i][j][k]+1)),2);
153 Correction = -Difference*Response[i][j][k]*EffectiveGain;
154 if(Correction!=0 && Target[i][j][k]!=0 && !PixMap->DRS_to_Pixel(i,j,k).empty()) {
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 SlowDataClass->AddToEntry("%d %d %d %.3f %.3f %.3f ", i,j,k,Average[i][j][k],Sigma[i][j][k],Correction);
157 if(fabs(Average[i][j][k]) < 2*Sigma[i][j][k]) printf("Too noisy!\n");
158 else WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(),Correction);
159 }
160 break;
161 case FB_Targets: // Take average as new targets
162 Target[i][j][k] = Average[i][j][k];
163 SlowDataClass->AddToEntry("%d %d %d %.3f %.3f ", i,j,k,Average[i][j][k],Sigma[i][j][k]);
164 break;
165 case FB_ResponseFirst: // First point of response measurement done
166 Buffer[i][j][k] = Average[i][j][k];
167 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hvdiff %s %f",PixMap->DRS_to_Pixel(i,j,k).c_str(), DiffVoltage);
168 break;
169 case FB_ResponseSecond: // Determine response from signal variation
170 if(Buffer[i][j][k] == Average[i][j][k]) {
171 m->PrintMessage("HV Feedback: Warning, response singular for board %d, chip %d, channel %d.\n",i,j,k);
172 Response[i][j][k] = 0;
173 }
174 else Response[i][j][k] = DiffVoltage/(Buffer[i][j][k]-Average[i][j][k]);
175 SlowDataClass->AddToEntry("%d %d %d %.3f ", i,j,k,Response[i][j][k]);
176 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hvdiff %s %f",PixMap->DRS_to_Pixel(i,j,k).c_str(), -DiffVoltage/2);
177 break;
178 default: break; // to suppress warning abount not handled enumeration value
179 }
180 }
181 }
182 }
183
184 switch (FBMode) {
185 case FB_Targets:
186 m->PrintMessage("HV Feedback: New targets set, switching off.\n");
187 FBMode = FB_Off;
188 break;
189 case FB_ResponseFirst:
190 FBMode = FB_ResponseSecond;
191 m->PrintMessage("HV Feedback: Increasing voltages by %f for response measurement, acquiring data.\n", DiffVoltage);
192 break;
193 case FB_ResponseSecond:
194 m->PrintMessage("HV Feedback: Response measurements finished, original voltages set, switching off.\n");
195 FBMode = FB_Off;
196 break;
197 default: break; // to suppress warning abount not handled enumeration value
198 }
199
200 if(m->SlowDataClass->ErrorCode != 0) {
201 m->PrintMessage("Error, could not write feedback slow data to file (%s), file closed.\n", strerror(m->SlowDataClass->ErrorCode));
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<kNumberOfChips; j++)
214 for (int k=0; k<kNumberOfChannels; k++) {
215 Average[i][j][k] = 0.0;
216 Sigma[i][j][k] = 0.0;
217 }
218 Count = 0;
219}
220
221//
222// Number of events to accumulate before correction acts
223//
224void HVFeedback::SetNumAverages(unsigned int Averages) {
225 NumAverages = Averages;
226}
227
228//
229// Get requested number of events
230//
231unsigned int HVFeedback::GetNumAverages() {
232 return NumAverages;
233}
234
235//
236// Set feedback gain
237//
238void HVFeedback::SetGain(float FBGain) {
239 Gain = FBGain;
240}
241
242//
243// Get feedback gain
244//
245float HVFeedback::GetGain() {
246 return Gain;
247}
248
249//
250// Set feedback mode and clear averages
251//
252void HVFeedback::SetFBMode(FBState Mode) {
253 if(Mode==FB_ResponseFirst || Mode==FB_ResponseFirst)
254 m->PrintMessage("Start reponse measurement by calling MeasureResponse().\n");
255 else {
256 FBMode = Mode;
257 ClearAverages();
258 }
259}
260
261//
262// Set feedback mode and clear averages
263//
264FBState HVFeedback::GetFBMode() {
265 switch (FBMode) {
266 case FB_Off: m->PrintMessage("Feedback off.\n"); break;
267 case FB_Active: m->PrintMessage("Feedback active.\n"); break;
268 case FB_Targets: m->PrintMessage("Feedback acquiring new targets.\n"); break;
269 case FB_ResponseFirst: m->PrintMessage("Feedback measuring response with first voltage.\n"); break;
270 case FB_ResponseSecond: m->PrintMessage("Feedback measuring response with second voltage.\n"); break;
271 }
272 return FBMode;
273}
274
275//
276// Return current number of events
277//
278unsigned int HVFeedback::GetCurrentCount() {
279 return Count;
280}
281
282//
283// Set target values
284//
285void HVFeedback::SetTarget(int Board, int Chip, int Channel, float TargetVal) {
286 if(Board<m->NumBoards && Chip<kNumberOfChips && Channel<kNumberOfChannels)
287 Target[Board][Chip][Channel] = TargetVal;
288 else printf("Invalid board, chip or channel number.\n");
289}
290
291//
292// Print target values
293//
294void HVFeedback::GetTargets() {
295 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
296 for (int j=0; j<kNumberOfChips; j++)
297 for (int k=0; k<kNumberOfChannels; k++)
298 m->PrintMessage("Board %d, chip %d, channel %d: %.2f\n",i,j,k,Target[i][j][k]);
299}
300
301//
302// Measure response matrix
303//
304void HVFeedback::MeasureResponse(float U) {
305
306 if (U==0) m->PrintMessage("HV Feedback: Error, voltage difference must not non-zero.\n");
307 else {
308 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
309 for (int j=0; j<kNumberOfChips; j++)
310 for (int k=0; k<kNumberOfChannels-2; k++) {
311 if(PixMap->DRS_to_Pixel(i,j,k).empty()) m->PrintMessage("Could not find pixel ID of board %d, chip %d, channel %d\n",i,j,k);
312 else WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), -U/2);
313 }
314 DiffVoltage = U;
315 FBMode = FB_ResponseFirst;
316 ClearAverages();
317 m->PrintMessage("HV Feedback: Decreasing voltages by %f for response measurement, acquiring data.\n",DiffVoltage/2);
318 }
319}
320
321//
322// Print response values
323//
324void HVFeedback::GetResponse() {
325 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
326 for (int j=0; j<kNumberOfChips; j++)
327 for (int k=0; k<kNumberOfChannels; k++)
328 m->PrintMessage("Board %d, chip %d, channel %d: %.3f\n",i,j,k,Response[i][j][k]);
329}
330
331//
332// Write commmand to socket
333//
334bool HVFeedback::WriteHVCommand(const char *Format, ...) {
335 char Textbuffer[MAX_COM_SIZE];
336 fd_set SelectDescriptor;
337 int RetryCount=0;
338
339 do {
340 va_list ArgumentPointer; va_start(ArgumentPointer, Format);
341 vsnprintf(Textbuffer, sizeof(Textbuffer), Format, ArgumentPointer);
342
343 // Write command to socket
344 if(write(SocketDescriptor, Textbuffer, strlen(Textbuffer)+1)!=(int) strlen(Textbuffer)+1) {
345 m->PrintMessage("Error: Could not write (entire) command to HV socket (%s)\n", strerror(errno));
346 return false;
347 }
348
349 // Wait for command acknowledge from hvcontrol program
350 FD_ZERO(&SelectDescriptor); FD_SET(SocketDescriptor, &SelectDescriptor);
351 struct timeval WaitTime = {fMaxCmdAckDelay, 0};
352 if (select(((int) SocketDescriptor)+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
353 m->PrintMessage("Error with select() in command acknowledge (%s)\n", strerror(errno));
354 return false;
355 }
356 if (!FD_ISSET(SocketDescriptor, &SelectDescriptor)) { // Time-out expired
357 m->PrintMessage("Time-out of %d seconds expired before receiving acknowledge from HV socket.\n", fMaxCmdAckDelay);
358 return false;
359 }
360 if (read(SocketDescriptor, Textbuffer, MAX_COM_SIZE) == -1) {
361 m->PrintMessage("Error reading acknowledge from HV socket (%s)\n", strerror(errno));
362 return false;
363 }
364 } while (strstr(Textbuffer,"WC ok")==NULL && ++RetryCount<=MAX_RETRY);
365 if(RetryCount==MAX_RETRY) {
366 m->PrintMessage("Could not set high voltage after %d tries.\n", MAX_RETRY);
367 return false;
368 }
369 return true;
370}
371
372//
373// Print feedback configuration
374//
375void HVFeedback::PrintConfig() {
376 m->PrintMessage("LedTrigBoard: %d\t\tLedTrigChip: %d\t\tLedTrigChannel: %d\n"
377 "LedTrigSample: %d\tLedTrigThreshold: %.2f\n"
378 "LedSignalSample: %d\tLedBaselineSample: %d\tDefaultNumAverage: %d\n"
379 "IntHalfWidth:%u\tHVControlServer: %s\tHVControlPort: %d\n"
380 "MaxCmdAckDelay: %d\n",
381 fLedTrigBoard, fLedTrigChip, fLedTrigChannel, fLedTrigSample,
382 fLedTrigThreshold, fLedSignalSample, fLedBaselineSample,
383 fDefaultNumAverage, fIntHalfWidth, fHVControlServer, fHVControlPort, fMaxCmdAckDelay);
384}
Note: See TracBrowser for help on using the repository browser.