Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 :
16 : /* $Id$ */
17 :
18 : //-----------------------------------------------------------------------------
19 : /// \class AliMUONRawStreamTrigger
20 : /// This class provides access to MUON digits in raw data.
21 : ///
22 : /// It loops over all MUON digits in the raw data given by the AliRawReader.
23 : /// The Next method goes to the next local response. If there are no local response left
24 : /// it returns kFALSE.
25 : /// It can loop also over DDL and store the decoded rawdata in TClonesArrays
26 : /// in payload class.
27 : ///
28 : /// Version implement for Trigger
29 : /// \author Christian Finck
30 : //-----------------------------------------------------------------------------
31 :
32 : #include <TArrayS.h>
33 :
34 : #include "AliMUONRawStreamTrigger.h"
35 : #include "AliMUONDarcHeader.h"
36 : #include "AliMUONRegHeader.h"
37 : #include "AliMUONLocalStruct.h"
38 : #include "AliMUONDDLTrigger.h"
39 : #include "AliMUONLogger.h"
40 :
41 : #include "AliRawReader.h"
42 : #include "AliRawDataHeader.h"
43 : #include "AliRawDataHeaderV3.h"
44 : #include "AliDAQ.h"
45 : #include "AliLog.h"
46 :
47 : #include <cassert>
48 :
49 : /// \cond CLASSIMP
50 18 : ClassImp(AliMUONRawStreamTrigger)
51 : /// \endcond
52 :
53 : const Int_t AliMUONRawStreamTrigger::fgkMaxDDL = 2;
54 :
55 : //___________________________________________
56 : AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(TRootIOCtor* /*dummy*/)
57 0 : : AliMUONVRawStreamTrigger(),
58 0 : fPayload(0x0),
59 0 : fCurrentDDL(0x0),
60 0 : fCurrentDDLIndex(fgkMaxDDL),
61 0 : fCurrentDarcHeader(0x0),
62 0 : fCurrentRegHeader(0x0),
63 0 : fCurrentRegHeaderIndex(0),
64 0 : fCurrentLocalStruct(0x0),
65 0 : fCurrentLocalStructIndex(0),
66 0 : fLocalStructRead(kFALSE),
67 0 : fDDL(0),
68 0 : fNextDDL(kFALSE)
69 0 : {
70 : ///
71 : /// create an object to read MUON raw digits
72 : /// Default ctor with no mem allocation for I/O
73 : ///
74 0 : }
75 :
76 : //___________________________________________
77 : AliMUONRawStreamTrigger::AliMUONRawStreamTrigger()
78 0 : : AliMUONVRawStreamTrigger(),
79 0 : fPayload(new AliMUONPayloadTrigger()),
80 0 : fCurrentDDL(0x0),
81 0 : fCurrentDDLIndex(fgkMaxDDL),
82 0 : fCurrentDarcHeader(0x0),
83 0 : fCurrentRegHeader(0x0),
84 0 : fCurrentRegHeaderIndex(0),
85 0 : fCurrentLocalStruct(0x0),
86 0 : fCurrentLocalStructIndex(0),
87 0 : fLocalStructRead(kFALSE),
88 0 : fDDL(0),
89 0 : fNextDDL(kFALSE)
90 0 : {
91 : ///
92 : /// create an object to read MUON raw digits
93 : /// Default ctor for monitoring purposes
94 : ///
95 :
96 :
97 0 : }
98 :
99 : //_________________________________________________________________
100 : AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(AliRawReader* rawReader)
101 0 : : AliMUONVRawStreamTrigger(rawReader),
102 0 : fPayload(new AliMUONPayloadTrigger()),
103 0 : fCurrentDDL(0x0),
104 0 : fCurrentDDLIndex(fgkMaxDDL),
105 0 : fCurrentDarcHeader(0x0),
106 0 : fCurrentRegHeader(0x0),
107 0 : fCurrentRegHeaderIndex(0),
108 0 : fCurrentLocalStruct(0x0),
109 0 : fCurrentLocalStructIndex(0),
110 0 : fLocalStructRead(kFALSE),
111 0 : fDDL(0),
112 0 : fNextDDL(kFALSE)
113 0 : {
114 : ///
115 : /// ctor with AliRawReader as argument
116 : /// for reconstruction purpose
117 : ///
118 :
119 0 : }
120 :
121 : //___________________________________
122 : AliMUONRawStreamTrigger::~AliMUONRawStreamTrigger()
123 0 : {
124 : ///
125 : /// clean up
126 : ///
127 0 : delete fPayload;
128 0 : }
129 :
130 : //_____________________________________________________________
131 : Bool_t AliMUONRawStreamTrigger::Next(UChar_t& id, UChar_t& dec, Bool_t& trigY,
132 : UChar_t& yPos, UChar_t& sXDev, UChar_t& xDev,
133 : UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
134 : TArrayS& xPattern, TArrayS& yPattern)
135 : {
136 : ///
137 : /// read the next raw digit (local structure)
138 : /// returns kFALSE if there is no digit left
139 : /// Should call First() before this method to start the iteration.
140 : ///
141 :
142 0 : if ( IsDone() ) return kFALSE;
143 :
144 0 : if ( fLocalStructRead ) {
145 :
146 0 : Bool_t ok = GetNextLocalStruct();
147 0 : if (!ok)
148 : {
149 : // this is the end
150 0 : return kFALSE;
151 : }
152 0 : }
153 :
154 0 : fLocalStructRead = kTRUE;
155 :
156 0 : id = fCurrentLocalStruct->GetId();
157 0 : dec = fCurrentLocalStruct->GetDec();
158 0 : trigY = fCurrentLocalStruct->GetTrigY();
159 0 : yPos = fCurrentLocalStruct->GetYPos();
160 0 : sXDev = fCurrentLocalStruct->GetSXDev();
161 0 : xDev = fCurrentLocalStruct->GetXDev();
162 0 : xPos = fCurrentLocalStruct->GetXPos();
163 :
164 0 : triggerX = fCurrentLocalStruct->GetTriggerX();
165 0 : triggerY = fCurrentLocalStruct->GetTriggerY();
166 :
167 0 : fCurrentLocalStruct->GetXPattern(xPattern);
168 0 : fCurrentLocalStruct->GetYPattern(yPattern);
169 :
170 0 : return kTRUE;
171 0 : }
172 :
173 : //______________________________________________________
174 : Bool_t AliMUONRawStreamTrigger::IsDone() const
175 : {
176 : /// Whether the iteration is finished or not
177 0 : return (fCurrentLocalStruct==0);
178 : }
179 :
180 : //______________________________________________________
181 : void AliMUONRawStreamTrigger::First()
182 : {
183 : /// Initialize the iteration process.
184 :
185 0 : fCurrentDDLIndex = -1;
186 : // Must reset all the pointers because if we return before calling
187 : // GetNextLocalStruct() the user might call CurrentDDL(), CurrentBlockHeader(),
188 : // CurrentRegHeader() or CurrentLocalStruct() which should return reasonable
189 : // results in that case.
190 0 : fCurrentDDL = 0;
191 0 : fCurrentDarcHeader = 0;
192 0 : fCurrentRegHeader = 0;
193 0 : fCurrentLocalStruct = 0;
194 :
195 : // Find the first non-empty structure
196 0 : if (not GetNextDDL()) return;
197 0 : if (not GetNextRegHeader()) return;
198 0 : GetNextLocalStruct();
199 0 : }
200 :
201 : //______________________________________________________
202 : Bool_t AliMUONRawStreamTrigger::GetNextDDL()
203 : {
204 : /// Returns the next DDL present
205 :
206 0 : assert( GetReader() != 0 );
207 :
208 :
209 : Bool_t kFound(kFALSE);
210 :
211 0 : while ( fCurrentDDLIndex < fgkMaxDDL-1 && !kFound )
212 : {
213 0 : ++fCurrentDDLIndex;
214 0 : GetReader()->Reset();
215 0 : GetReader()->Select("MUONTRG",fCurrentDDLIndex,fCurrentDDLIndex);
216 0 : if ( GetReader()->ReadHeader() )
217 : {
218 : kFound = kTRUE;
219 0 : }
220 : }
221 :
222 0 : if ( !kFound )
223 : {
224 : // fCurrentDDLIndex is set to fgkMaxDDL so that we exit the above loop immediately
225 : // for a subsequent call to this method, unless NextEvent is called in between.
226 0 : fCurrentDDLIndex = fgkMaxDDL;
227 : // We have not actually been able to complete the loading of the new DDL so
228 : // we are still on the old one. In this case we do not need to reset fCurrentDDL.
229 : //fCurrentDDL = 0;
230 0 : if (IsErrorLogger()) AddErrorMessage();
231 0 : return kFALSE;
232 : }
233 :
234 0 : Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
235 :
236 0 : AliRawReader * reader = GetReader();
237 0 : if (!reader) return kFALSE;
238 :
239 0 : const AliRawDataHeader * cdh = reader->GetDataHeader();
240 0 : const AliRawDataHeaderV3 * cdh3 = reader->GetDataHeaderV3();
241 :
242 0 : if (!cdh && !cdh3) return kFALSE;
243 :
244 0 : Bool_t scalerEvent = ((cdh ? cdh->GetL1TriggerMessage() : cdh3->GetL1TriggerMessage()) & 0x1) == 0x1;
245 :
246 0 : AliDebug(3, Form("DDL Number %d totalDataWord %d\n", fCurrentDDLIndex,
247 : totalDataWord));
248 :
249 0 : UInt_t *buffer = new UInt_t[totalDataWord/4];
250 :
251 0 : if ( !GetReader()->ReadNext((UChar_t*)buffer, totalDataWord) )
252 : {
253 : // We have not actually been able to complete the loading of the new DDL so
254 : // we are still on the old one. In this case we do not need to reset fCurrentDDL.
255 : //fCurrentDDL = 0;
256 0 : delete [] buffer;
257 0 : return kFALSE;
258 : }
259 :
260 : #ifndef R__BYTESWAP
261 : Swap(buffer, totalDataWord / sizeof(UInt_t)); // swap needed for mac power pc
262 : #endif
263 :
264 0 : fPayload->ResetDDL();
265 :
266 :
267 :
268 0 : Bool_t ok = fPayload->Decode(buffer, scalerEvent);
269 :
270 0 : delete[] buffer;
271 :
272 0 : fCurrentDDL = fPayload->GetDDLTrigger();
273 :
274 0 : fCurrentDarcHeader = fCurrentDDL->GetDarcHeader();
275 :
276 0 : fCurrentRegHeaderIndex = -1;
277 :
278 :
279 0 : return ok;
280 0 : }
281 :
282 :
283 : //______________________________________________________
284 : Bool_t AliMUONRawStreamTrigger::GetNextRegHeader()
285 : {
286 : /// Returns the next Reg Header present
287 :
288 0 : assert( fCurrentDarcHeader != 0 );
289 0 : assert( fCurrentDDL != 0 );
290 :
291 0 : fCurrentRegHeader = 0;
292 :
293 0 : Int_t i = fCurrentRegHeaderIndex;
294 :
295 0 : while ( fCurrentRegHeader == 0 && i < fCurrentDarcHeader->GetRegHeaderEntries()-1 )
296 : {
297 0 : ++i;
298 0 : fCurrentRegHeader = fCurrentDarcHeader->GetRegHeaderEntry(i);
299 : }
300 :
301 0 : if ( !fCurrentRegHeader )
302 : {
303 0 : Bool_t ok = GetNextDDL();
304 0 : if (!ok)
305 : {
306 0 : return kFALSE;
307 : }
308 : else
309 : {
310 0 : return GetNextRegHeader();
311 : }
312 : }
313 :
314 0 : fCurrentRegHeaderIndex = i;
315 :
316 0 : fCurrentLocalStructIndex = -1;
317 :
318 0 : return kTRUE;
319 0 : }
320 :
321 : //______________________________________________________
322 : Bool_t AliMUONRawStreamTrigger::GetNextLocalStruct()
323 : {
324 : /// Find the next non-empty local structure
325 :
326 0 : assert( fCurrentRegHeader != 0 );
327 :
328 0 : fCurrentLocalStruct = 0;
329 :
330 0 : Int_t i = fCurrentLocalStructIndex;
331 :
332 0 : while ( fCurrentLocalStruct == 0 && i < fCurrentRegHeader->GetLocalEntries()-1 )
333 : {
334 0 : ++i;
335 0 : fCurrentLocalStruct = fCurrentRegHeader->GetLocalEntry(i);
336 : }
337 :
338 0 : if ( !fCurrentLocalStruct )
339 : {
340 0 : Bool_t ok = GetNextRegHeader();
341 0 : if (!ok)
342 : {
343 0 : return kFALSE;
344 : }
345 : else
346 : {
347 0 : return GetNextLocalStruct();
348 : }
349 : }
350 :
351 0 : fCurrentLocalStructIndex = i;
352 :
353 0 : fLocalStructRead = kFALSE;
354 :
355 0 : return kTRUE;
356 0 : }
357 :
358 : //______________________________________________________
359 : Bool_t AliMUONRawStreamTrigger::NextDDL()
360 : {
361 : /// reading tracker DDL
362 : /// store local info into Array
363 : /// store only non-empty structures
364 :
365 : // reset TClones
366 0 : fPayload->ResetDDL();
367 :
368 :
369 : // loop over the two ddl's
370 :
371 0 : while ( fDDL < fgkMaxDDL ) {
372 0 : GetReader()->Reset();
373 0 : GetReader()->Select("MUONTRG", fDDL, fDDL); //Select the DDL file to be read
374 0 : if (GetReader()->ReadHeader()) break;
375 0 : AliDebug(3,Form("Skipping DDL %d which does not seem to be there",fDDL));
376 0 : ++fDDL;
377 : }
378 :
379 0 : if (fDDL >= fgkMaxDDL) {
380 0 : fDDL = 0;
381 0 : if (IsErrorLogger()) AddErrorMessage();
382 0 : return kFALSE;
383 : }
384 :
385 0 : AliDebug(3, Form("DDL Number %d\n", fDDL ));
386 :
387 0 : Int_t totalDataWord = GetReader()->GetDataSize(); // in bytes
388 :
389 0 : AliRawReader * reader = GetReader();
390 0 : if (!reader) return kFALSE;
391 :
392 0 : const AliRawDataHeader * cdh = reader->GetDataHeader();
393 0 : const AliRawDataHeaderV3 * cdh3 = reader->GetDataHeaderV3();
394 :
395 0 : if (!cdh && !cdh3) return kFALSE;
396 :
397 0 : Bool_t scalerEvent = ((cdh ? cdh->GetL1TriggerMessage() : cdh3->GetL1TriggerMessage()) & 0x1) == 0x1;
398 :
399 :
400 0 : UInt_t *buffer = new UInt_t[totalDataWord/4];
401 :
402 : // check not necessary yet, but for future developments
403 0 : if (!GetReader()->ReadNext((UChar_t*)buffer, totalDataWord)) return kFALSE;
404 :
405 : #ifndef R__BYTESWAP
406 : Swap(buffer, totalDataWord / sizeof(UInt_t)); // swap needed for mac power pc
407 : #endif
408 :
409 0 : fPayload->Decode(buffer, scalerEvent);
410 :
411 :
412 0 : fDDL++;
413 :
414 0 : delete [] buffer;
415 :
416 :
417 0 : return kTRUE;
418 0 : }
419 :
420 : // //______________________________________________________
421 : // void AliMUONRawStreamTrigger::SetMaxReg(Int_t reg)
422 : // {
423 : // /// set regional card number
424 : // fPayload->SetMaxReg(reg);
425 : // }
426 :
427 : //______________________________________________________
428 : void AliMUONRawStreamTrigger::SetMaxLoc(Int_t loc)
429 : {
430 : /// set local card number
431 0 : fPayload->SetMaxLoc(loc);
432 0 : }
433 :
434 : //______________________________________________________
435 : void AliMUONRawStreamTrigger::AddErrorMessage()
436 : {
437 : /// add message into logger of AliRawReader per event
438 :
439 0 : TString msg;
440 0 : Int_t occurance = 0;
441 0 : AliMUONLogger* log = fPayload->GetErrorLogger();
442 :
443 0 : log->ResetItr();
444 0 : while(log->Next(msg, occurance))
445 : {
446 0 : if (msg.Contains("Darc"))
447 0 : GetReader()->AddMajorErrorLog(kDarcEoWErr, msg.Data());
448 :
449 0 : if (msg.Contains("Global"))
450 0 : GetReader()->AddMajorErrorLog(kGlobalEoWErr, msg.Data());
451 :
452 0 : if (msg.Contains("Regional"))
453 0 : GetReader()->AddMajorErrorLog(kRegEoWErr, msg.Data());
454 :
455 0 : if (msg.Contains("Local"))
456 0 : GetReader()->AddMajorErrorLog(kLocalEoWErr, msg.Data());
457 : }
458 :
459 0 : log->Clear(); // clear after each event
460 0 : }
|