source: fact/FADctrl/FADBoard.cc@ 10067

Last change on this file since 10067 was 10036, checked in by ogrimm, 14 years ago
First version of FADctrl
File size: 9.4 KB
Line 
1/********************************************************************\
2
3 Class interfacing to FAD board
4
5\********************************************************************/
6
7#include "FADBoard.h"
8using namespace std;
9
10//
11// Constructor
12//
13FADBoard::FADBoard(string Server, unsigned short Port, class FAD *Parent, unsigned int Num) {
14
15 int Ret;
16
17 // Initialization
18 m = Parent;
19 InitOK = false;
20 Active = true;
21 CommError = false;
22 ACalibTime = -1;
23 Status.Update.tv_sec = -1;
24 Thread = pthread_self(); // For checking in destructor
25
26 Name = new char [Server.size()+1]; // Name in permanent memory for DIM service
27 strcpy(Name, Server.c_str());
28
29 // Resolve hostname
30 struct hostent *Host = gethostbyname(Server.c_str());
31 if (Host == 0) {
32 m->PrintMessage("Could not resolve host name for %s\n", Server.c_str());
33 return;
34 }
35
36 // Open socket descriptor
37 if ((Socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
38 m->PrintMessage("Could not open socket for %s (%s)\n", Server.c_str(), strerror(errno));
39 return;
40 }
41
42 // Connect to server
43 struct sockaddr_in SocketAddress;
44 SocketAddress.sin_family = PF_INET;
45 SocketAddress.sin_port = htons(Port);
46 SocketAddress.sin_addr = *(struct in_addr*) Host->h_addr;
47
48 if (connect(Socket, (struct sockaddr *) &SocketAddress, sizeof(SocketAddress)) == -1) {
49 m->PrintMessage("Could not connect to %s at port %d (%s)\n", Server.c_str(), Port, strerror(errno));
50 return;
51 }
52
53 // Construct DIM service name prefix
54 stringstream ID;
55 ID << SERVER_NAME"/Board" << setfill('0') << setw(2) << Num << "/";
56
57 NameService = new DimService((ID.str()+"Server").c_str(), Name);
58 IDService = new DimService((ID.str()+"BoardID").c_str(), (char *) "S", NULL, 0);
59 TempService = new DimService((ID.str()+"Temperature").c_str(), (char *) "F", NULL, 0);
60 DACService = new DimService((ID.str()+"DAC").c_str(), (char *) "S", NULL, 0);
61 ROIService = new DimService((ID.str()+"ROI").c_str(), (char *) "S", NULL, 0);
62
63 // Initialise mutex for synchronization
64 pthread_mutexattr_t Attr;
65
66 if ((Ret = pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_ERRORCHECK)) != 0) {
67 m->Message(m->ERROR, "pthread_mutex_settype() failed (%s)", strerror(Ret));
68 }
69 if ((Ret = pthread_mutex_init(&Mutex, &Attr)) != 0) {
70 m->Message(m->ERROR, "pthread_mutex_init() failed (%s)", strerror(Ret));
71 return;
72 }
73
74 // Create thread that receives data
75 if ((Ret = pthread_create(&Thread, NULL, (void * (*)(void *)) LaunchThread,(void *) this)) != 0) {
76 m->PrintMessage("pthread_create() failed (%s)\n", strerror(Ret));
77 Thread = pthread_self();
78 return;
79 }
80
81 InitOK = true;
82}
83
84//
85// Destructor
86//
87FADBoard::~FADBoard() {
88
89 int Ret;
90
91 // Cancel thread and wait for it to quit
92 if (pthread_equal(Thread, pthread_self()) == 0) {
93 if ((Ret = pthread_cancel(Thread)) != 0) m->PrintMessage("Error: Could not request thread cancellation (%s)\n", strerror(Ret));
94 if ((Ret = pthread_join(Thread, NULL)) != 0) m->PrintMessage("pthread_join() failed (%s)\n", strerror(Ret));
95 }
96
97 // Delete mutex
98 if (InitOK && ((Ret = pthread_mutex_destroy(&Mutex)) != 0)) {
99 m->PrintMessage("pthread_mutex_destroy() failed (%s)", strerror(Ret));
100 }
101
102 delete NameService;
103 delete IDService;
104 delete TempService;
105 delete DACService;
106 delete ROIService;
107 delete[] Name;
108
109 // Close socket descriptor
110 if ((Socket != -1) && (close(Socket) == -1)) {
111 m->PrintMessage("Could not close socket descriptor (%s)", strerror(errno));
112 }
113}
114
115
116//
117// Send data to board
118//
119void FADBoard::Send(const void *Data, size_t Bytes) {
120
121 // Do not send if not active
122 if (!Active) return;
123
124 // Write data
125 ssize_t Result = write(Socket, Data, Bytes);
126
127 // Check result
128 if (Result == -1) m->PrintMessage("Error: Could not write to socket (%s)\n", strerror(errno));
129 else if ((size_t) Result < Bytes) m->PrintMessage("Error: Could only write %d bytes out of %d to socket\n", Result, Bytes);
130}
131
132void FADBoard::Send(unsigned short Data) {
133
134 unsigned short Buffer = htons(Data);
135
136 Send(&Buffer, sizeof(unsigned short));
137}
138
139
140//
141// Get board status (mutex protected to avoid concurrent access in ReadLoop)
142//
143struct FADBoard::BoardStatus FADBoard::GetStatus() {
144
145 int Ret;
146 struct BoardStatus S;
147
148 // Lock
149 if ((Ret = pthread_mutex_lock(&Mutex)) != 0) {
150 m->Message(m->FATAL, "pthread_mutex_lock() failed in ReadLoop() (%s)", strerror(Ret));
151 }
152
153 S = Status;
154
155 // Unlock
156 if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) {
157 m->Message(m->FATAL, "pthread_mutex_unlock() failed in Unlock() (%s)", strerror(Ret));
158 }
159
160 return S;
161}
162
163//
164// Initiate average
165//
166void FADBoard::AccumulateSum(unsigned int n) {
167
168 if (!Active) return;
169
170 Lock();
171 memset(Sum, 0, sizeof(Sum));
172 NumForSum = n;
173 DoSum = true;
174 Unlock();
175}
176
177
178//
179// Read data from board
180//
181void FADBoard::ReadLoop() {
182
183 static char Buffer[READ_BUFFER_SIZE];
184 static unsigned int Pos = 0;
185 const PEVNT_HEADER *Header = (PEVNT_HEADER *) Buffer;
186 ssize_t Result;
187 struct BoardStatus PrevStatus;
188
189 memset(&PrevStatus, 0, sizeof(PrevStatus));
190
191 while (!m->ExitRequest) {
192 // Read data from socket
193 Result = read(Socket, Buffer + Pos, sizeof(Buffer)-Pos);
194
195 // Check result of read
196 if (Result == -1) {
197 m->PrintMessage("Error: Could not read from socket, exiting read loop (%s)\n", strerror(errno));
198 CommError = true;
199 break;
200 }
201 else if (Result == 0) {
202 m->PrintMessage("Server not existing anymore, exiting read loop\n");
203 CommError = true;
204 break;
205 }
206
207 // If not active, discard incoming data
208 if (!Active) continue;
209
210 // Advance write pointer
211 Pos += Result;
212
213 // Check if internal buffer full
214 if (Pos == sizeof(Buffer)) {
215 m->PrintMessage("Internal buffer full, deleting all data in buffer\n");
216 Pos = 0;
217 continue;
218 }
219
220 // Check if full event available in buffer
221 if (Pos < sizeof(PEVNT_HEADER) || ntohs(Header->start_package_flag) != 0xfb01) continue;
222
223 unsigned int Length = ntohs(Header->package_length)*2*sizeof(char);
224 if (Pos < Length) continue;
225
226 // Extract data if event end package flag correct
227 if (ntohs(*(unsigned short *) (Buffer+Length-sizeof(unsigned short))) == 0x04FE) {
228
229 // Prepare pointers to channel data (channels stored in order 0,9,18,27 - 1,10,19,28 - ... - 8,17,26,35)
230 PCHANNEL *Channel[NChips*NChannels], *Pnt=(PCHANNEL *) (Header+1);
231 for(unsigned int i=0; i<NChips*NChannels; i++) {
232 Channel[i] = Pnt;
233 Pnt = (PCHANNEL *) ((short *) (Channel[i] + 1) + ntohs(Channel[i]->roi));
234 }
235
236 PrevStatus = Status;
237
238 // Lock to avoid concurrent access in GetStatus()
239 Lock();
240
241 gettimeofday(&Status.Update, NULL);
242
243 // Extract ID and type information
244 Status.BoardID = ntohl(Header->board_id);
245 Status.TriggerID = ntohl(Header->local_trigger_id);
246 Status.TriggerType = ntohs(Header->local_trigger_type);
247
248 // Extract temperatures (MSB indicates if temperature is positive or negative)
249 for (unsigned int i=0; i<NTemp; i++) {
250 if ((ntohs(Header->drs_temperature[i]) & 0x8000) == 0) Status.Temp[i] = float(ntohs(Header->drs_temperature[i]) >> 3)/16;
251 else Status.Temp[i] = float(0xE000 | (ntohs(Header->drs_temperature[i])) >> 3)/16;
252 }
253
254 // Extract DAC channels
255 for (unsigned int i=0; i<NDAC; i++) Status.DAC[i] = ntohs(Header->dac[i]);
256
257 short Buf;
258 for (unsigned int Chip=0; Chip<NChips; Chip++) {
259 // Extract trigger cells
260 Status.TriggerCell[Chip] = (int) ntohs(Channel[Chip]->start_cell);
261
262 for (unsigned int Chan=0; Chan<NChannels; Chan++) {
263 // Extract ROI
264 Status.ROI[Chip][Chan] = ntohs(Channel[Chip+NChips*Chan]->roi);
265
266 // Extract ADC data (stored in 12 bit signed twis complement with out-of-range-bit and leading zeroes)
267 for (int i=0; i<Status.ROI[Chip][Chan]; i++) {
268 Buf = ntohs(Channel[Chip+NChips*Chan]->adc_data[i]);
269 (Buf <<= 4) >>= 4; //delete the sign-bit by shifting left and shift back
270 Data[Chip][Chan][i] = Buf;
271 }
272 }
273 }
274
275 // If requested for calibration, add rotated data for later averaging
276 if (DoSum && NumForSum>0) {
277 for (unsigned int Chip=0; Chip<NChips; Chip++) for (unsigned int Chan=0; Chan<NChannels; Chan++) {
278 for (int i=0; i<Status.ROI[Chip][Chan]; i++) {
279 Sum[Chip][Chan][(i+ntohs(Channel[Chip+NChips*Chan]->start_cell)) % NBins] = Data[Chip][Chan][i];
280 }
281 }
282 NumForSum--;
283 if (NumForSum == 0) DoSum = false;
284 }
285
286 Unlock();
287
288 // Update DIM services if necessary
289 if (memcmp(PrevStatus.Temp, Status.Temp, sizeof(Status.Temp)) != 0) {
290 TempService->updateService(Status.Temp, sizeof(Status.Temp));
291 }
292 if (memcmp(PrevStatus.DAC, Status.DAC, sizeof(Status.DAC)) != 0) {
293 DACService->updateService(Status.DAC, sizeof(Status.DAC));
294 }
295 if (memcmp(PrevStatus.ROI, Status.ROI, sizeof(Status.ROI)) != 0) {
296 ROIService->updateService(Status.ROI, sizeof(Status.ROI));
297 }
298 if (PrevStatus.BoardID != Status.BoardID) {
299 IDService->updateService(&Status.BoardID, sizeof(Status.BoardID));
300 }
301 }
302 else printf("End package flag incorrect, removing corrupt event\n");
303
304 // Remove event data from internal buffer
305 memmove(Buffer, Buffer+Length, Pos-Length);
306 Pos = Pos-Length;
307 } // while()
308}
309
310
311//
312// Launch read thread inside class
313//
314void FADBoard::LaunchThread(class FADBoard *m) {
315
316 m->ReadLoop();
317}
318
319
320//
321// Lock and unlock mutex
322//
323void FADBoard::Lock() {
324
325 int Ret;
326
327 if ((Ret = pthread_mutex_lock(&Mutex)) != 0) {
328 m->Message(m->FATAL, "pthread_mutex_lock() failed in class FADBoard (%s)", strerror(Ret));
329 }
330}
331
332void FADBoard::Unlock() {
333
334 int Ret;
335
336 if ((Ret = pthread_mutex_unlock(&Mutex)) != 0) {
337 m->Message(m->FATAL, "pthread_mutex_unlock() failed in class FADBoard (%s)", strerror(Ret));
338 }
339}
Note: See TracBrowser for help on using the repository browser.