Adding comment lines to class description needed for Root documentation,
[u/mrichter/AliRoot.git] / MUON / AliMUONPayloadTracker.cxx
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 AliMUONPayloadTracker
20 /// Decodes rawdata from buffer and stores in TClonesArray.
21 /// First version implement for Tracker
22 ///
23 /// \author Christian Finck
24 //-----------------------------------------------------------------------------
25
26 #include "AliMUONPayloadTracker.h"
27
28 #include "AliMUONDspHeader.h"
29 #include "AliMUONBlockHeader.h"
30 #include "AliMUONBusStruct.h"
31 #include "AliMUONDDLTracker.h"
32
33 #include "AliLog.h"
34
35 /// \cond CLASSIMP
36 ClassImp(AliMUONPayloadTracker)
37 /// \endcond
38
39 AliMUONPayloadTracker::AliMUONPayloadTracker()
40   : TObject(),
41     fBusPatchId(0),
42     fDspId(0),
43     fBlkId(0),
44     fMaxDDL(20),
45     fMaxBlock(2),
46     fMaxDsp(5),
47     fMaxBus(5),
48     fDDLTracker(new AliMUONDDLTracker()),
49     fBusStruct(new AliMUONBusStruct()),
50     fBlockHeader(new AliMUONBlockHeader()),
51     fDspHeader(new AliMUONDspHeader()),
52     fParityErrBus(),
53     fGlitchErrors(0),
54     fPaddingErrors(0)
55 {
56   ///
57   /// create an object to decode MUON payload
58   ///
59
60 }
61
62 //___________________________________
63 AliMUONPayloadTracker::~AliMUONPayloadTracker()
64 {
65   ///
66   /// clean up
67   ///
68   delete fDDLTracker;
69   delete fBusStruct;
70   delete fBlockHeader;
71   delete fDspHeader;
72 }
73
74 //______________________________________________________
75 Bool_t AliMUONPayloadTracker::Decode(UInt_t* buffer, Int_t totalDDLSize)
76 {
77
78   /// Each DDL is made with 2 Blocks each of which consists of 5 DSP's at most 
79   /// and each of DSP has at most 5 buspatches.
80   /// The different structures, Block (CRT), DSP (FRT) and Buspatch,
81   /// are identified by a key word 0xFC0000FC, 0xF000000F and 0xB000000B respectively.
82   /// (fBusPatchManager no more needed !)
83
84
85   //Read Header Size of DDL,Block,DSP and BusPatch
86   static Int_t kBlockHeaderSize    = fBlockHeader->GetHeaderLength();
87   static Int_t kDspHeaderSize      = fDspHeader->GetHeaderLength();
88   static Int_t kBusPatchHeaderSize = fBusStruct->GetHeaderLength();
89
90   // size structures
91   Int_t totalBlockSize;
92   Int_t totalDspSize;
93   Int_t totalBusPatchSize;
94   Int_t dataSize; 
95   Int_t bufSize;
96
97   // indexes
98   Int_t indexBlk;
99   Int_t indexDsp;
100   Int_t indexBusPatch;
101   Int_t index = 0;
102   Int_t iBlock = 0;
103
104   // CROCUS CRT
105   while (buffer[index] == fBlockHeader->GetDefaultDataKey()) {
106
107     if (iBlock > fMaxBlock) break;
108      
109     // copy within padding words
110     memcpy(fBlockHeader->GetHeader(),&buffer[index], (kBlockHeaderSize)*4);
111
112     totalBlockSize = fBlockHeader->GetTotalLength();
113
114     indexBlk = index;
115     index += kBlockHeaderSize;
116
117     // copy in TClonesArray
118     fDDLTracker->AddBlkHeader(*fBlockHeader);
119
120     // Crocus FRT
121     Int_t iDsp = 0;
122     while (buffer[index] == fDspHeader->GetDefaultDataKey()) {
123
124       if (iDsp > fMaxDsp) break; // if ever...
125                 
126       memcpy(fDspHeader->GetHeader(),&buffer[index], kDspHeaderSize*4);
127
128       totalDspSize = fDspHeader->GetTotalLength();
129
130       if (fDspHeader->GetErrorWord()) {
131         fDspHeader->Print("");
132         if ( fDspHeader->GetErrorWord() == (0x000000B1 |  fBlockHeader->GetDspId())
133              ||  fDspHeader->GetErrorWord() == (0x00000091 |  fBlockHeader->GetDspId()) ){
134           // an event with a glitch in the readout  has been detected
135           // it means that somewhere a 1 byte word has been randomly inserted
136           // all the readout sequence is shifted  untill the next event 
137
138           AliWarning(Form("Glitch in data detected, skipping event ")); 
139
140           fGlitchErrors++;
141           return kFALSE ; 
142         }       
143       }
144       
145       indexDsp = index;
146       index += kDspHeaderSize;
147
148       // copy in TClonesArray
149       fDDLTracker->AddDspHeader(*fDspHeader, iBlock);
150
151       // buspatch structure
152       Int_t iBusPatch = 0;
153       while (buffer[index] == fBusStruct->GetDefaultDataKey()) {
154
155         if (iBusPatch > fMaxBus) break; // if ever
156         
157         //copy buffer into header structure
158         memcpy(fBusStruct->GetHeader(), &buffer[index], kBusPatchHeaderSize*4);
159
160         totalBusPatchSize = fBusStruct->GetTotalLength();
161         indexBusPatch     = index;
162                 
163         //Check Buspatch header, not empty events
164         if(totalBusPatchSize > kBusPatchHeaderSize) {    
165
166           index   += kBusPatchHeaderSize;
167           dataSize = fBusStruct->GetLength();
168           bufSize  = fBusStruct->GetBufSize();
169
170           if(dataSize > 0) { // check data present
171             if (dataSize > bufSize) // check buffer size
172               fBusStruct->SetAlloc(dataSize);
173          
174             //copy buffer into data structure
175             memcpy(fBusStruct->GetData(), &buffer[index], dataSize*4);
176             fBusStruct->SetBlockId(iBlock); // could be usefull in future applications ?
177             fBusStruct->SetDspId(iDsp);
178
179             // check parity
180             if(!CheckDataParity())
181                 AddParityErrBus(fBusStruct->GetBusPatchId());
182
183             // copy in TClonesArray
184             fDDLTracker->AddBusPatch(*fBusStruct, iBlock, iDsp);
185
186           } // dataSize test
187
188         } // testing buspatch
189
190         index = indexBusPatch + totalBusPatchSize;
191         if (index >= totalDDLSize) {// check the end of DDL
192           index = totalDDLSize - 1; // point to the last element of buffer
193           break;
194         }
195         iBusPatch++;
196       }  // buspatch loop
197
198       // skipping additionnal word if padding
199       if (fDspHeader->GetPaddingWord() == 1) {
200         if (buffer[index++] != fDspHeader->GetDefaultPaddingWord())
201
202             AliWarning(Form("Error in padding word for iBlock %d, iDsp %d, iBus %d\n", 
203                           iBlock, iDsp, iBusPatch));
204
205         fPaddingErrors++;
206       }
207
208       index = indexDsp + totalDspSize;
209       if (index >= totalDDLSize) {
210         index = totalDDLSize - 1;
211         break;
212       }
213       iDsp++;
214     }  // dsp loop
215
216     index = indexBlk + totalBlockSize;
217     if (index >= totalDDLSize) {
218       index = totalDDLSize - 1;
219       break;
220     }
221     iBlock++;
222   }  // block loop
223
224   return kTRUE;
225 }
226
227 //______________________________________________________
228 void AliMUONPayloadTracker::ResetDDL()
229 {
230   /// reseting TClonesArray
231   /// after each DDL
232   ///
233   fDDLTracker->GetBlkHeaderArray()->Delete();
234   fGlitchErrors = 0;
235   fPaddingErrors = 0;
236   fParityErrBus.Reset();
237
238 }
239
240 //______________________________________________________
241 void AliMUONPayloadTracker::SetMaxBlock(Int_t blk) 
242 {
243   /// set regional card number
244   if (blk > 2) blk = 2;
245   fMaxBlock = blk;
246 }
247
248 //______________________________________________________
249 Bool_t AliMUONPayloadTracker::CheckDataParity()
250 {
251   /// parity check
252   /// taken from MuTrkBusPatch.cxx (sotfware test for CROCUS)
253   /// A. Baldisseri
254
255   Int_t  parity;
256   UInt_t data;
257   
258   Int_t dataSize = fBusStruct->GetLength();
259   for (int idata = 0; idata < dataSize; idata++) {
260
261     data  = fBusStruct->GetData(idata);
262
263     // Compute the parity for each data word
264     parity  = data & 0x1;
265     for (Int_t i = 1; i <= 30; i++) 
266       parity ^= ((data >> i) & 0x1);
267
268     // Check
269     if (parity != fBusStruct->GetParity(idata)) {
270
271       AliWarning(Form("Parity error in word %d for manuId %d and channel %d\n", 
272                       idata, fBusStruct->GetManuId(idata), fBusStruct->GetChannelId(idata)));
273
274       return kFALSE;
275                      
276     }
277   }
278   return kTRUE;
279 }
280
281 //______________________________________________________
282 void AliMUONPayloadTracker::AddParityErrBus(Int_t buspatch)
283 {
284 /// adding bus with at least on parity error
285     fParityErrBus.Set(fParityErrBus.GetSize() + 1);
286     fParityErrBus.AddAt(buspatch, fParityErrBus.GetSize() - 1);
287 }