source: drsdaq/HVFeedback.cc@ 24

Last change on this file since 24 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 11.3 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
20// Constructor: Initialise feedback
21HVFeedback::HVFeedback(DAQReadout* DAQClass, char* Configfile) {
22 struct sockaddr_in SocketAddress;
23
24 m = DAQClass;
25 PixMap = new PixelMap("../config/PixelMap.txt", false);
26
27 // Read configuration file
28 FILE *File;
29 if ((File = fopen(Configfile,"r")) == NULL) {
30 printf("Error: Could not open feedback configuration file '%s'\n", Configfile);
31 }
32 else {
33 printf("Reading feedback configuration file %s\n", Configfile);
34 ReadCard("LedTrigBoard", &fLedTrigBoard, 'I', File);
35 ReadCard("LedTrigChannel", &fLedTrigChannel, 'I', File);
36 ReadCard("LedTrigChip", &fLedTrigChip, 'I', File);
37 ReadCard("LedTrigSample", &fLedTrigSample, 'I', File);
38 ReadCard("LedTrigThreshold", &fLedTrigThreshold, 'f', File);
39 ReadCard("LedSignalSample", &fLedSignalSample, 'I', File);
40 ReadCard("LedBaselineSample", &fLedBaselineSample, 'I', File);
41 ReadCard("DefaultNumAverage", &fDefaultNumAverage, 'I', File);
42 ReadCard("HVControlServer", fHVControlServer, 's', File);
43 ReadCard("HVControlPort", &fHVControlPort, 'I', File);
44 ReadCard("MaxCmdAckDelay", &fMaxCmdAckDelay, 'I', File);
45 fclose(File);
46 }
47 PrintConfig();
48
49 // Initialise
50 Average = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
51 Response = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
52 Target = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
53 Buffer = new float [m->NumCMCBoards][kNumberOfChips][kNumberOfChannels];
54
55 Gain = 1;
56 SetFBMode(FB_Off);
57 SetNumAverages(fDefaultNumAverage);
58
59 // Opening socket client to HV control program
60 if ((SocketDescriptor = socket(PF_INET, SOCK_STREAM, 0)) == -1)
61 m->PrintMessage("Could not open client socket, no HV control available.\n");
62
63 // Resolve hostname and try to connect to server
64 struct hostent *hostent = gethostbyname(fHVControlServer);
65 if (hostent==0)
66 m->PrintMessage("Could not resolve HV server host name \"%s\".\n", fHVControlServer);
67 else {
68 SocketAddress.sin_family = PF_INET;
69 SocketAddress.sin_port = htons((unsigned short) fHVControlPort);
70 SocketAddress.sin_addr = *(struct in_addr*) hostent->h_addr;
71
72 if (connect(SocketDescriptor, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress))==-1)
73 m->PrintMessage("Could not connect to HV server %s at port %d (%s)\n", fHVControlServer, fHVControlPort, strerror(errno));
74 else m->PrintMessage("\nFeedback connected to HV server %s (port %d).\n", fHVControlServer, fHVControlPort);
75 signal(SIGPIPE,SIG_IGN); // Do not kill process if writing to closed socket
76 }
77}
78
79// Destructor
80HVFeedback::~HVFeedback() {
81 if (SocketDescriptor!=-1) {
82 close(SocketDescriptor);
83 m->PrintMessage("Feeback socket closed.\n");
84 }
85 delete[] Average; delete[] Response;
86 delete[] Target; delete[] Buffer;
87 delete PixMap;
88}
89
90
91// Check if LED trigger present, if yes accumulate feedback data and
92// calculate new high voltages if the required number of events is reached.
93bool HVFeedback::ProcessEvent() {
94 float Correction;
95
96 // Check for LED trigger channel on given channel and if feedback running
97 if (FBMode==FB_Off || m->WaveForm[fLedTrigBoard][fLedTrigChip][fLedTrigChannel][fLedTrigSample] < fLedTrigThreshold)
98 return false;
99 Count++;
100
101 // Add signal at LED bin for all channels
102 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
103 for (int j=0; j<kNumberOfChips; j++)
104 for (int k=0; k<kNumberOfChannels; k++)
105 Average[i][j][k] += (m->WaveForm[i][j][k][fLedSignalSample] - m->WaveForm[i][j][k][fLedBaselineSample])*m->BStruct[i].ScaleFactor;
106
107 // Acquired number of event requires action
108 if (Count==NumAverages) {
109 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
110 for (int j=0; j<kNumberOfChips; j++)
111 for (int k=0; k<kNumberOfChannels; k++) {
112 Average[i][j][k] /= Count;
113 switch (FBMode) {
114 case FB_Active: // Determine correction from response maxtrix and change voltages
115 Correction = (Target[i][j][k] - Average[i][j][k])*Response[i][j][k]*Gain;
116 if(Target[i][j][k]!=0 && !PixMap->DRS_to_Pixel(i,j,k).empty())
117 WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(),Correction);
118 break;
119 case FB_Targets: // Take average as new targets
120 Target[i][j][k] = Average[i][j][k];
121 break;
122 case FB_ResponseFirst: // First point of response measurement done
123 Buffer[i][j][k] = Average[i][j][k];
124 if(!PixMap->DRS_to_Pixel(i,j,k).empty()) WriteHVCommand("hvdiff %s %f",PixMap->DRS_to_Pixel(i,j,k).c_str(), Voltage2);
125 break;
126 case FB_ResponseSecond: // Determine response from signal variation
127 if(Buffer[i][j][k] == Average[i][j][k]) {
128 m->PrintMessage("HV Feedback: Warning, response singular for board %d, chip %d, channel %d.\n",i,j,k);
129 Response[i][j][k] = 0;
130 }
131 else Response[i][j][k] = Voltage2/(Buffer[i][j][k]-Average[i][j][k]);
132 break;
133 default: break; // to suppress warning abount not handled enumeration value
134 }
135 }
136 switch (FBMode) {
137 case FB_Active:
138 m->PrintMessage("HV Feedback: Acted.\n");
139 break;
140 case FB_Targets:
141 m->PrintMessage("HV Feedback: New targets set, switching off.\n");
142 FBMode = FB_Off;
143 break;
144 case FB_ResponseFirst:
145 FBMode = FB_ResponseSecond;
146 m->PrintMessage("HV Feedback: Setting second voltage %f for response measurement, acquiring data.\n", Voltage2);
147 break;
148 case FB_ResponseSecond:
149 m->PrintMessage("HV Feedback: Response measurements finished, switching off.\n");
150 FBMode = FB_Off;
151 break;
152 default: break; // to suppress warning abount not handled enumeration value
153 }
154 ClearAverages();
155 return true;
156 }
157 else return false;
158}
159
160// Clear average values and event counter
161void HVFeedback::ClearAverages() {
162 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
163 for (int j=0; j<kNumberOfChips; j++)
164 for (int k=0; k<kNumberOfChannels; k++) Average[i][j][k] = 0;
165 Count = 0;
166}
167
168// Number of events to accumulate before correction acts
169void HVFeedback::SetNumAverages(unsigned int Averages) {
170 NumAverages = Averages;
171}
172
173// Get requested number of events
174unsigned int HVFeedback::GetNumAverages() {
175 return NumAverages;
176}
177
178// Set feedback gain
179void HVFeedback::SetGain(float FBGain) {
180 Gain = FBGain;
181}
182
183// Get feedback gain
184float HVFeedback::GetGain() {
185 return Gain;
186}
187
188// Set feedback mode and clear averages
189void HVFeedback::SetFBMode(FBState Mode) {
190 if(Mode==FB_ResponseFirst || Mode==FB_ResponseFirst)
191 m->PrintMessage("Start reponse measurement by calling MeasureResponse().\n");
192 else {
193 FBMode = Mode;
194 ClearAverages();
195 }
196}
197
198// Set feedback mode and clear averages
199FBState HVFeedback::GetFBMode() {
200 switch (FBMode) {
201 case FB_Off: m->PrintMessage("Feedback off.\n"); break;
202 case FB_Active: m->PrintMessage("Feedback active.\n"); break;
203 case FB_Targets: m->PrintMessage("Feedback acquiring new targets.\n"); break;
204 case FB_ResponseFirst: m->PrintMessage("Feedback measuring response with first voltage.\n"); break;
205 case FB_ResponseSecond: m->PrintMessage("Feedback measuring response with second voltage.\n"); break;
206 }
207 return FBMode;
208}
209
210// Return current number of events
211unsigned int HVFeedback::GetCurrentCount() {
212 return Count;
213}
214
215// Set target values
216void HVFeedback::SetTarget(int Board, int Chip, int Channel, float TargetVal) {
217 if(Board<m->NumCMCBoards && Chip<kNumberOfChips && Channel<kNumberOfChannels)
218 Target[Board][Chip][Channel] = TargetVal;
219 else printf("Invalid board, chip or channel number.\n");
220}
221
222// Print target values
223void HVFeedback::GetTargets() {
224 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
225 for (int j=0; j<kNumberOfChips; j++)
226 for (int k=0; k<kNumberOfChannels; k++)
227 m->PrintMessage("Board %d, chip %d, channel %d: %.2f\n",i,j,k,Target[i][j][k]);
228}
229
230// Measure response matrix
231void HVFeedback::MeasureResponse(float U1, float U2) {
232
233 if (U2 == 0)
234 m->PrintMessage("HV Feedback: Error, econd voltage must not be zero.\n");
235 else {
236 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
237 for (int j=0; j<kNumberOfChips; j++)
238 for (int k=0; k<kNumberOfChannels-2; k++) {
239 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);
240 else WriteHVCommand("hvdiff %s %f\n",PixMap->DRS_to_Pixel(i,j,k).c_str(), U1);
241 }
242 Voltage1 = U1; Voltage2 = U2;
243 FBMode = FB_ResponseFirst;
244 ClearAverages();
245 m->PrintMessage("HV Feedback: Setting first voltage %f for response measurement, acquiring data.\n",U1);
246 }
247}
248
249// Print response values
250void HVFeedback::GetResponse() {
251 for (int i=m->FirstBoard; i<=m->LastBoard; i++)
252 for (int j=0; j<kNumberOfChips; j++)
253 for (int k=0; k<kNumberOfChannels; k++)
254 m->PrintMessage("Board %d, chip %d, channel %d: %f\n",i,j,k,Response[i][j][k]);
255}
256
257// Write commmand to socket
258bool HVFeedback::WriteHVCommand(char *Format, ...) {
259 char Textbuffer[MAX_COM_SIZE];
260 fd_set SelectDescriptor;
261 int RetryCount=0;
262
263 do {
264 va_list ArgumentPointer; va_start(ArgumentPointer, Format);
265 vsprintf(Textbuffer, Format, ArgumentPointer);
266
267 printf("%s", Textbuffer);
268 // Write command to socket
269 if(write(SocketDescriptor, Textbuffer, strlen(Textbuffer)+1)!=(int) strlen(Textbuffer)+1) {
270 m->PrintMessage("Error: Could not write (entire) command to HV socket (%s)\n", strerror(errno));
271 return false;
272 }
273
274 // Wait for command acknowledge from hvcontrol program
275 FD_ZERO(&SelectDescriptor); FD_SET(SocketDescriptor, &SelectDescriptor);
276 struct timeval WaitTime = {fMaxCmdAckDelay, 0};
277 if (select(((int) SocketDescriptor)+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
278 m->PrintMessage("Error with select() in command acknowledge (%s)\n", strerror(errno));
279 return false;
280 }
281 if (!FD_ISSET(SocketDescriptor, &SelectDescriptor)) { // Time-out expired
282 m->PrintMessage("Time-out of %d seconds expired before receiving acknowledge from HV socket.\n", fMaxCmdAckDelay);
283 return false;
284 }
285 if (read(SocketDescriptor, Textbuffer, MAX_COM_SIZE) == -1) {
286 m->PrintMessage("Error reading acknowledge from HV socket (%s)\n", strerror(errno));
287 return false;
288 }
289 } while (strstr(Textbuffer,"WC ok")==NULL && ++RetryCount<=MAX_RETRY);
290 if(RetryCount==MAX_RETRY) {
291 m->PrintMessage("Could not set high voltage after %d tries.\n", MAX_RETRY);
292 return false;
293 }
294 return true;
295}
296
297// Print feedback configuration
298void HVFeedback::PrintConfig() {
299 m->PrintMessage("LedTrigBoard: %d\t\tLedTrigChip: %d\t\tLedTrigChannel: %d\n"
300 "LedTrigSample: %d\tLedTrigThreshold: %.2f\n"
301 "LedSignalSample: %d\tLedBaselineSample: %d\tDefaultNumAverage: %d\n"
302 "HVControlServer: %s\tHVControlPort: %d\n"
303 "MaxCmdAckDelay: %d\n",
304 fLedTrigBoard, fLedTrigChip, fLedTrigChannel, fLedTrigSample,
305 fLedTrigThreshold, fLedSignalSample, fLedBaselineSample,
306 fDefaultNumAverage, fHVControlServer, fHVControlPort, fMaxCmdAckDelay);
307}
Note: See TracBrowser for help on using the repository browser.