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