source: fact/BIASctrl/Crate.cc@ 10120

Last change on this file since 10120 was 10118, checked in by ogrimm, 14 years ago
Adapted various programs to new PixelMap class
File size: 9.4 KB
Line 
1/********************************************************************\
2
3 Interface to FACT bias voltage crate
4
5\********************************************************************/
6#include <utility>
7
8#include "Crate.h"
9#include "User.h" // Must not be in header file to avoid problem with declaring class User
10
11using namespace std;
12
13//
14// Constructor
15//
16Crate::Crate(string CrateName, int Number, class User *PIO) {
17
18 struct termios tio;
19
20 // Initialize
21 InitOK = false;
22 File = NULL;
23 m = PIO;
24 Name = new char [CrateName.size()+1];
25 strcpy(Name, CrateName.c_str());
26 CrateNumber = Number;
27 WrapCount = -1;
28
29 for (int i=0; i<MAX_NUM_BOARDS; i++) {
30 for (int j=0; j<NUM_CHANNELS; j++) {
31 OC[i][j] = false;
32 Present[i][j] = false;
33 Current[i][j] = 0;
34 }
35 }
36 ResetHit = false;
37 WrapOK = true;
38 WrapCount = -1;
39 ErrorCount = 0;
40
41 // Create DIM services
42 stringstream ID;
43 ID << setfill('0') << setw(2) << CrateNumber;
44
45 NameService = new DimService ((SERVER_NAME"/NAME/ID"+ID.str()).c_str(), Name);
46 BiasVolt = new DimService ((char *) (SERVER_NAME"/VOLT/ID"+ID.str()).c_str(), (char *) "D", Volt, MAX_NUM_BOARDS*NUM_CHANNELS*sizeof(double));
47 BiasDAC = new DimService ((char *) (SERVER_NAME"/DAC/ID"+ID.str()).c_str(), (char *) "I", DAC, MAX_NUM_BOARDS*NUM_CHANNELS*sizeof(int));
48 BiasCurrent = new DimService ((char *) (SERVER_NAME"/MICROAMP/ID"+ID.str()).c_str(), (char *) "F", Current, MAX_NUM_BOARDS*NUM_CHANNELS*sizeof(float));
49
50 ClearVoltageArrays();
51
52 // Open device
53 if ((fDescriptor = open(("/dev/"+CrateName).c_str(), O_RDWR|O_NOCTTY|O_NDELAY)) == -1) {
54 if(errno != 2) m->PrintMessage("Error: Could not open device %d/%s (%s)\n", CrateNumber, Name, strerror(errno));
55 return;
56 }
57
58 // Generate FILE pointer
59 if ((File = fdopen(fDescriptor, "rb+")) == NULL) {
60 m->PrintMessage("Error: fdopen() failed on device %d/%s (%s)\n", CrateNumber, Name, strerror(errno));
61 return;
62 }
63
64 // Get current serial port settings
65 if (tcgetattr(fDescriptor, &tio) == -1) {
66 m->PrintMessage("Error: tcgetattr() failed on device %s (%s)\n", Name, strerror(errno));
67 return;
68 }
69
70 // Set baudrate and raw mode
71 if (cfsetspeed(&tio, BAUDRATE) == -1) {
72 m->PrintMessage("Error: Could not set baud rate of device %s (%s)\n", Name, strerror(errno));
73 return;
74 }
75 cfmakeraw(&tio);
76 if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) {
77 m->PrintMessage("Error: tcsetattr() failed on device %s (%s)\n", Name, strerror(errno));
78 return;
79 }
80
81 InitOK = true;
82}
83
84//
85// Destructor (Resets board)
86//
87Crate::~Crate() {
88
89 if(fDescriptor != -1) {
90 GlobalSet(0);
91
92 SystemReset();
93 if (File == NULL) {
94 if (close(fDescriptor) == -1) m->PrintMessage("Error closing device %s (%s)\n", Name, strerror(errno));
95 }
96 else if (fclose(File) != 0) m->PrintMessage("Error closing device %s\n", Name);
97 }
98
99 delete NameService;
100 delete BiasVolt;
101 delete BiasDAC;
102 delete BiasCurrent;
103 delete[] Name;
104}
105
106
107// Communicate: Write and read from HV Board until time-out has been reached
108//
109// Returns: 0 error, 1 success, -1 time-out exceeded
110vector<unsigned char> Crate::Communicate(string Buf) {
111
112 int N;
113 fd_set SelectDescriptor;
114 struct timeval WaitTime = {(long) m->fTimeOut, (long) ((m->fTimeOut-(long) m->fTimeOut)*1e6)};
115 char Buffer[10000];
116 vector<unsigned char> Data;
117
118 // === Lock device ===
119 flockfile(File);
120
121 // Do not try to communicate if crate has too many errors
122 if (ErrorCount > MAX_ERR_COUNT) goto ExitCommunicate;
123
124 // === Write data ===
125 if ((N = write(fDescriptor, Buf.data(), Buf.size())) < (int) Buf.size()) {
126 if (N == -1) m->Message(m->ERROR, "Could not write data to crate (%s)", strerror(errno));
127 else m->Message(m->ERROR, "Could write only %d of %d bytes to board", N, Buf.size());
128 ErrorCount++;
129
130 }
131
132 // === Try to read back data with time-out ===
133 do {
134 FD_ZERO(&SelectDescriptor); FD_SET(fDescriptor, &SelectDescriptor);
135 if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
136 m->Message(m->FATAL, "Error with select() (%s)", strerror(errno));
137 }
138
139 // Time-out expired?
140 if (!FD_ISSET(fDescriptor, &SelectDescriptor)) {
141 goto ExitCommunicate;
142 }
143
144 // Read data
145 if ((N = read(fDescriptor, Buffer, sizeof(Buffer))) == -1) {
146 m->Message(m->ERROR, "Read error (%s)", strerror(errno));
147 ErrorCount++;
148 goto ExitCommunicate;
149 }
150
151 // Add data to buffer
152 for (int i=0; i<N; i++) Data.push_back(Buffer[i]);
153 } while(Data.size() < Buf.size());
154
155 // === Check if multiple of three bytes were returned ===
156 if (Data.size() % 3 != 0) {
157 Data.clear();
158 goto ExitCommunicate;
159 }
160
161 // === Check/update all wrap counter ===
162 for (unsigned int i=0; i<Data.size(); i+=3) {
163 if (WrapCount != -1) {
164 if ((WrapCount+1)%8 == ((Data[i]>>4) & 7)) WrapOK = true;
165 else WrapOK = false;
166 }
167 WrapCount = (Data[i]>>4) & 7;
168 }
169
170 // === UnLock file descriptor ===
171 ExitCommunicate:
172 funlockfile(File);
173
174 if (Data.empty()) Data.push_back(0);
175
176 return Data;
177}
178
179//
180// System reset of bias crate
181//
182int Crate::SystemReset() {
183
184 vector<unsigned char> Data = Communicate(string(3, 0));
185
186 if (Data.size() == 3) {
187 ErrorCount = 0;
188 return 1;
189 }
190 return 0;
191}
192
193//
194// Read all channels status
195//
196int Crate::ReadAll() {
197
198 string Buf;
199
200 // Prepare command to read all channels
201 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
202 Buf.push_back(1<<5 | i<<1 | (j&16)>>4);
203 Buf.push_back(j<<4);
204 Buf.push_back(0);
205 }
206
207 // Execute command
208 vector<unsigned char> Data = Communicate(Buf);
209
210 if (Data.size() != Buf.size()) return 0;
211
212 // Evaluate data returned from crate
213 int Count = 0;
214 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
215 Current[i][j] = (Data[Count+1] + (Data[Count] & 0x0f)*256) * 1.22;
216 OC[i][j] = Data[Count] & 128;
217 Present[i][j] = Data[Count+2] & 0x70 ? false : true;
218 ResetHit = Data[Count+2] & 128;
219 Count += 3;
220 if (i==2 && j==19) OC[i][j] = false;
221 }
222 return 1;
223}
224
225
226// ***** Global set *****
227int Crate::GlobalSet(double Voltage) {
228
229 unsigned int SetPoint = (unsigned int) (Voltage/90.0*0x0fff);
230
231 // Execute command
232 string Buf;
233 Buf = (((Buf + char(1<<6)) + char(SetPoint>>8)) + char(SetPoint));
234 vector<unsigned char> Data = Communicate(Buf);
235
236 if (Data.size() == 3) {
237 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
238 DAC[i][j] = SetPoint;
239 Volt[i][j] = Voltage;
240 RefVolt[i][j] = Voltage;
241 }
242 return 1;
243 }
244 return 0;
245}
246
247
248// ***** Set channel voltages *****
249int Crate::SetChannels(map<unsigned int, double> V) {
250
251 string Buf;
252
253 if (V.empty()) return 1;
254
255 // Build and execute commands
256 for (map<unsigned int, double>::const_iterator it = V.begin(); it != V.end(); ++it) {
257 // If DAC value unchanged, do not send command
258 if (DAC[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] == it->second/90.0*0x0fff) continue;
259
260 // Add command to buffer
261 Buf += char(3<<5) | char(it->first/NUM_CHANNELS<<1 & 0x0f) | char((it->first%NUM_CHANNELS&16)>>4 & 1);
262 Buf += char(it->first%NUM_CHANNELS<<4) | ((((unsigned int) (it->second/90.0*0x0fff))>>8) & 0x0f);
263 Buf += char(it->second/90.0*0x0fff);
264 }
265 vector<unsigned char> Data = Communicate(Buf);
266
267 // Store new voltage values of successful
268 if (Data.size() == Buf.size()) {
269 for (map<unsigned int, double>::const_iterator it = V.begin(); it != V.end(); ++it) {
270 DAC[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = (unsigned int) (it->second/90.0*0x0fff);
271 Volt[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = it->second;
272 RefVolt[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = it->second;
273 }
274 return 1;
275 }
276 return 0;
277}
278
279
280// ***** Synchronize board *****
281bool Crate::Synch() {
282
283 int Trial = 0;
284 vector<unsigned char> Data;
285
286 while(++Trial <= 3) {
287 Data = Communicate(string(1, 0));
288 if (Data.size() == 3) return true;
289 }
290 return false;
291}
292
293
294// ***** Set all voltages of board to zero *****
295void Crate::ClearVoltageArrays() {
296
297 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
298 DAC[i][j] = 0;
299 Volt[i][j] = 0;
300 RefVolt[i][j] = 0;
301 }
302
303 UpdateDIM();
304}
305
306
307// ***** Return calibrated voltage of given channel *****
308double Crate::GetVoltage(unsigned int Channel) {
309
310 if (Channel >= MAX_NUM_BOARDS*NUM_CHANNELS) return 0;
311 else return Volt[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS];
312}
313
314
315// ***** Return DAC value of given channel *****
316unsigned int Crate::GetDAC(unsigned int Channel) {
317
318 if (Channel >= MAX_NUM_BOARDS*NUM_CHANNELS) return 0;
319 else return DAC[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS];
320}
321
322
323// ***** Return current of given channel *****
324float Crate::GetCurrent(unsigned int Channel) {
325
326 if (Channel >= MAX_NUM_BOARDS*NUM_CHANNELS) return 0;
327 else return Current[Channel/NUM_CHANNELS][Channel%NUM_CHANNELS];
328}
329
330
331// ***** Update DIM services *****
332void Crate::UpdateDIM() {
333
334 BiasVolt->updateService();
335 BiasDAC->updateService();
336}
337
338
339// ***** Set reference current for dynamic mode *****
340void Crate::SetRefCurrent() {
341
342 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
343 RefCurrent[i][j] = Current[i][j];
344 }
345}
346
347
348// ***** Correct voltages according to current *****
349void Crate::AdaptVoltages() {
350
351 static int LastUpdate = 0;
352
353 map<unsigned int, double> Voltages;
354
355 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
356 if (RefVolt[i][j] == 0) continue;
357 Voltages[i*NUM_CHANNELS+j] = RefVolt[i][j] + (RefCurrent[i][j]-Current[i][j])*RESISTOR/1e6;
358 }
359 SetChannels(Voltages);
360
361 if (time(NULL)-LastUpdate > 5) {
362 LastUpdate = time(NULL);
363 UpdateDIM();
364 }
365}
Note: See TracBrowser for help on using the repository browser.