source: fact/BIASctrl/Crate.cc@ 10067

Last change on this file since 10067 was 10059, checked in by ogrimm, 14 years ago
Fast ramping for many channels
File size: 7.8 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
48 ClearVoltageArrays();
49
50 // Open device
51 if ((fDescriptor = open(("/dev/"+CrateName).c_str(), O_RDWR|O_NOCTTY|O_NDELAY)) == -1) {
52 if(errno != 2) m->PrintMessage("Error: Could not open device %d/%s (%s)\n", CrateNumber, Name, strerror(errno));
53 return;
54 }
55
56 // Generate FILE pointer
57 if ((File = fdopen(fDescriptor, "rb+")) == NULL) {
58 m->PrintMessage("Error: fdopen() failed on device %d/%s (%s)\n", CrateNumber, Name, strerror(errno));
59 return;
60 }
61
62 // Get current serial port settings
63 if (tcgetattr(fDescriptor, &tio) == -1) {
64 m->PrintMessage("Error: tcgetattr() failed on device %s (%s)\n", Name, strerror(errno));
65 return;
66 }
67
68 // Set baudrate and raw mode
69 if (cfsetspeed(&tio, BAUDRATE) == -1) {
70 m->PrintMessage("Error: Could not set baud rate of device %s (%s)\n", Name, strerror(errno));
71 return;
72 }
73 cfmakeraw(&tio);
74 if (tcsetattr(fDescriptor, TCSANOW, &tio ) == -1) {
75 m->PrintMessage("Error: tcsetattr() failed on device %s (%s)\n", Name, strerror(errno));
76 return;
77 }
78
79 InitOK = true;
80}
81
82//
83// Destructor (Resets board)
84//
85Crate::~Crate() {
86
87 if(fDescriptor != -1) {
88 GlobalSet(0);
89
90 SystemReset();
91 if (File == NULL) {
92 if (close(fDescriptor) == -1) m->PrintMessage("Error closing device %s (%s)\n", Name, strerror(errno));
93 }
94 else if (fclose(File) != 0) m->PrintMessage("Error closing device %s\n", Name);
95 }
96
97 delete NameService;
98 delete BiasVolt;
99 delete[] Name;
100}
101
102
103// Communicate: Write and read from HV Board until time-out has been reached
104//
105// Returns: 0 error, 1 success, -1 time-out exceeded
106vector<char> Crate::Communicate(string Buf) {
107
108 int N;
109 fd_set SelectDescriptor;
110 struct timeval WaitTime = {(long) m->fTimeOut, (long) ((m->fTimeOut-(long) m->fTimeOut)*1e6)};
111 char Buffer[10000];
112 vector<char> Data;
113
114 // === Lock device ===
115 flockfile(File);
116
117 // === Write data ===
118 if ((N = write(fDescriptor, Buf.data(), Buf.size())) < (int) Buf.size()) {
119 if (N == -1) m->Message(m->ERROR, "Could not write data to crate (%s)", strerror(errno));
120 else m->Message(m->ERROR, "Could write only %d of %d bytes to board", N, Buf.size());
121 ErrorCount++;
122 goto ExitCommunicate;
123 }
124
125 // === Try to read back data with time-out ===
126 do {
127 FD_ZERO(&SelectDescriptor); FD_SET(fDescriptor, &SelectDescriptor);
128 if (select(fDescriptor+1, &SelectDescriptor, NULL, NULL, &WaitTime)==-1) {
129 m->Message(m->ERROR, "Error with select() (%s)", strerror(errno));
130 goto ExitCommunicate;
131 }
132
133 // Time-out expired?
134 if (!FD_ISSET(fDescriptor, &SelectDescriptor)) {
135 Data.push_back(-1);
136 goto ExitCommunicate;
137 }
138
139 // Read data
140 if ((N = read(fDescriptor, Buffer, sizeof(Buffer))) == -1) {
141 m->Message(m->ERROR, "Read error (%s)", strerror(errno));
142 ErrorCount++;
143 goto ExitCommunicate;
144 }
145
146 // Add data to buffer
147 for (int i=0; i<N; i++) Data.push_back(Buffer[i]);
148 } while(Data.size() < Buf.size());
149
150 // === Check if multiple of three bytes were returned ===
151 if (Data.size() % 3 != 0) {
152 Data.clear();
153 goto ExitCommunicate;
154 }
155
156 // === Check/update all wrap counter ===
157 for (unsigned int i=0; i<Data.size(); i+=3) {
158 if (WrapCount != -1) {
159 if ((WrapCount+1)%8 == ((Data[i]>>4) & 7)) WrapOK = true;
160 else WrapOK = false;
161 }
162 WrapCount = (Data[i]>>4) & 7;
163 }
164
165 // === UnLock file descriptor ===
166 ExitCommunicate:
167 funlockfile(File);
168
169 if (Data.empty()) Data.push_back(0);
170
171 return Data;
172}
173
174//
175// System reset of bias crate
176//
177int Crate::SystemReset() {
178
179 vector<char> Data = Communicate(string(3, 0));
180
181 if (Data.size() == 3) {
182 ErrorCount = 0;
183 return 1;
184 }
185 return Data[0];
186}
187
188//
189// Read all channels status
190//
191int Crate::ReadAll() {
192
193 string Buf;
194
195 // Prepare command to read all channels
196 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
197 Buf.push_back(1<<5 | i<<1 | (j&16)>>4);
198 Buf.push_back(j<<4);
199 Buf.push_back(0);
200 }
201
202 // Execute command
203 vector<char> Data = Communicate(Buf);
204
205 if (Data.size() != Buf.size()) return Data[0];
206
207 // Evaluate data returned from crate
208 int Count = 0;
209 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
210 Current[i][j] = Data[Count+1] + (Data[Count]&15)*256;
211 OC[i][j] = Data[Count] & 128;
212 Present[i][j] = Data[Count+2] & 0x70 ? false : true;
213 ResetHit = Data[Count+2] & 128;
214 Count += 3;
215 if (i==2 && j==19) OC[i][j] = false;
216 }
217 return 1;
218}
219
220
221// ***** Global set *****
222int Crate::GlobalSet(unsigned int SetPoint) {
223
224 // Check limit
225 if (SetPoint > 0x0FFF) {
226 m->PrintMessage("Error: Voltage DAC value above 0x0FFF\n");
227 return 0;
228 }
229
230 // Execute command
231 string Buf;
232 Buf = (((Buf + char(1<<6)) + char(SetPoint>>8)) + char(SetPoint));
233 vector<char> Data = Communicate(Buf);
234
235 if (Data.size() == 3) {
236 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
237 DAC[i][j] = SetPoint;
238 Volt[i][j] = (double) SetPoint / 0xfff * 90;
239 }
240 return 1;
241 }
242 return Data[0];
243}
244
245
246// ***** Set channel voltages *****
247int Crate::SetChannels(map<unsigned int, unsigned int> V) {
248
249 string Buf;
250
251 if (V.empty()) return 1;
252
253 // Build and execute commands
254 for (map<unsigned int, unsigned int>::const_iterator it = V.begin(); it != V.end(); ++it) {
255 Buf += char(3<<5) | char(it->first/NUM_CHANNELS<<1 & 0x0f) | char((it->first%NUM_CHANNELS&16)>>4 & 1);
256 Buf += char(it->first%NUM_CHANNELS<<4) | ((it->second>>8) & 0x0f);
257 Buf += char(it->second);
258 }
259 vector<char> Data = Communicate(Buf);
260
261 // Store new voltage values of successful
262 if (Data.size() == Buf.size()) {
263 for (map<unsigned int, unsigned int>::const_iterator it = V.begin(); it != V.end(); ++it) {
264 DAC[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = it->second;
265 Volt[it->first/NUM_CHANNELS][it->first%NUM_CHANNELS] = 90.0*it->second/0x0fff;
266 }
267 return 1;
268 }
269 return Data[0];
270}
271
272
273// ***** Synchronize board *****
274bool Crate::Synch() {
275
276 int Trial = 0;
277 vector<char> Data;
278
279 while(++Trial <= 3) {
280 Data = Communicate(string(1, 0));
281 if (Data.size() == 3) return true;
282 if (Data[0] == 0) break;
283 }
284 return false;
285}
286
287
288// ***** Determine offset for current measurement *****
289bool Crate::CurrentCalib(double Voltage) {
290
291 // Set voltage of all channels and wait for current to settle
292 if (GlobalSet((int) (Voltage/90*0xfff)) != 1) return false;
293 sleep(1);
294
295 // Measure current of all channels
296 if (ReadAll() != 1) return false;
297
298 for (int i=0; i<MAX_NUM_BOARDS; i++) for (int j=0; j<NUM_CHANNELS; j++) {
299 CurrentOffset[i][j] = Current[i][j];
300 }
301 return true;
302}
303
304
305// ***** Set all voltages of board to zero *****
306void Crate::ClearVoltageArrays() {
307
308 for (int i=0; i<MAX_NUM_BOARDS; i++) {
309 for (int j=0; j<NUM_CHANNELS; j++){
310 DAC[i][j] = 0;
311 Volt[i][j] = 0.0;
312 }
313 }
314 // Update DIM services
315 BiasVolt->updateService();
316}
Note: See TracBrowser for help on using the repository browser.