source: fact/BIASctrl/Crate.cc@ 10057

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