Export AliDAQ header file into include
[u/mrichter/AliRoot.git] / RAW / AliAltroRawStream.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 ///
20 /// This class provides access to Altro digits in raw data.
21 ///
22 /// It loops over all Altro digits in the raw data given by the AliRawReader.
23 /// The Next method goes to the next digit. If there are no digits left
24 /// it returns kFALSE.
25 /// Several getters provide information about the current digit.
26 ///
27 ///////////////////////////////////////////////////////////////////////////////
28
29 #include "AliAltroRawStream.h"
30 #include "AliRawReader.h"
31 #include "AliLog.h"
32
33 ClassImp(AliAltroRawStream)
34
35
36 //_____________________________________________________________________________
37 AliAltroRawStream::AliAltroRawStream(AliRawReader* rawReader) :
38   fNoAltroMapping(kTRUE),
39   fIsOldRCUFormat(kFALSE),
40   fIsShortDataHeader(kFALSE),
41   fDDLNumber(-1),
42   fPrevDDLNumber(-1),
43   fRCUId(-1),
44   fPrevRCUId(-1),
45   fHWAddress(-1),
46   fPrevHWAddress(-1),
47   fTime(-1),
48   fPrevTime(-1),
49   fSignal(-1),
50   fTimeBunch(-1),
51   fRawReader(rawReader),
52   fData(NULL),
53   fPosition(0),
54   fCount(0),
55   fBunchLength(0),
56   fRCUTrailerData(NULL),
57   fRCUTrailerSize(0)
58 {
59 // create an object to read Altro raw digits
60   fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
61 }
62
63 //_____________________________________________________________________________
64 AliAltroRawStream::AliAltroRawStream(const AliAltroRawStream& stream) :
65   TObject(stream),
66   fNoAltroMapping(kTRUE),
67   fIsOldRCUFormat(kFALSE),
68   fIsShortDataHeader(kFALSE),
69   fDDLNumber(-1),
70   fPrevDDLNumber(-1),
71   fRCUId(-1),
72   fPrevRCUId(-1),
73   fHWAddress(-1),
74   fPrevHWAddress(-1),
75   fTime(-1),
76   fPrevTime(-1),
77   fSignal(-1),
78   fTimeBunch(-1),
79   fRawReader(NULL),
80   fData(NULL),
81   fPosition(0),
82   fCount(0),
83   fBunchLength(0),
84   fRCUTrailerData(NULL),
85   fRCUTrailerSize(0)
86 {
87   Fatal("AliAltroRawStream", "copy constructor not implemented");
88 }
89
90 //_____________________________________________________________________________
91 AliAltroRawStream& AliAltroRawStream::operator = (const AliAltroRawStream& 
92                                               /* stream */)
93 {
94   Fatal("operator =", "assignment operator not implemented");
95   return *this;
96 }
97
98 //_____________________________________________________________________________
99 AliAltroRawStream::~AliAltroRawStream()
100 {
101 // clean up
102
103 }
104
105 //_____________________________________________________________________________
106 void AliAltroRawStream::Reset()
107 {
108 // reset altro raw stream params
109
110   fPosition = fCount = fBunchLength = 0;
111
112   fRCUTrailerData = NULL;
113   fRCUTrailerSize = 0;
114
115   fDDLNumber = fPrevDDLNumber = fRCUId = fPrevRCUId = fHWAddress = fPrevHWAddress = fTime = fPrevTime = fSignal = fTimeBunch = -1;
116
117   if (fRawReader) fRawReader->Reset();
118
119   fSegmentation[0] = fSegmentation[1] = fSegmentation[2] = -1;
120 }
121
122 //_____________________________________________________________________________
123 Bool_t AliAltroRawStream::Next()
124 {
125 // read the next raw digit
126 // returns kFALSE if there is no digit left
127
128   fPrevDDLNumber = fDDLNumber;
129   fPrevRCUId = fRCUId;
130   fPrevHWAddress = fHWAddress;
131   fPrevTime = fTime;
132
133   while (fCount == 0) {  // next trailer
134     if (fPosition <= 0) {  // next payload
135       do {
136         if (!fRawReader->ReadNextData(fData)) return kFALSE;
137       } while (fRawReader->GetDataSize() == 0);
138
139       fDDLNumber = fRawReader->GetDDLID();
140
141       fPosition = GetPosition();
142     }
143
144     if (!ReadTrailer())
145       AliFatal("Incorrect trailer information !");
146
147     fBunchLength = 0;
148   }
149
150   if (fBunchLength == 0) ReadBunch();
151   else fTime--;
152
153   ReadAmplitude();
154
155   return kTRUE;
156 }
157
158 //_____________________________________________________________________________
159 void AliAltroRawStream::SelectRawData(Int_t detId)
160 {
161   // Select the raw data for specific
162   // detector id
163   AliDebug(1,Form("Selecting raw data for detector %d",detId));
164   fRawReader->Select(detId);
165 }
166
167 //_____________________________________________________________________________
168 UShort_t AliAltroRawStream::GetNextWord()
169 {
170   // Read the next 10 bit word in backward direction
171   // The input stream access is given by fData and fPosition
172
173   fPosition--;
174
175   Int_t iBit = fPosition * 10;
176   Int_t iByte = iBit / 8;
177   Int_t shift = iBit % 8;
178
179   // the raw data is written as integers where the low bits are filled first
180   // -> little endian is assumed here !
181   Int_t iByteLow = iByte;
182   iByte++;
183   Int_t iByteHigh  = iByte;
184   return ((fData[iByteHigh] * 256 + fData[iByteLow]) >> shift) & 0x03FF;
185 }
186
187 //_____________________________________________________________________________
188 Bool_t AliAltroRawStream::ReadTrailer()
189 {
190   //Read a trailer of 40 bits in the backward reading mode
191   //In case of no mapping is provided, read a dummy trailer
192   if (fNoAltroMapping) {
193     AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
194     return ReadDummyTrailer();
195   }
196
197   //First reading filling words
198   UShort_t temp;
199   Int_t nFillWords = 0;
200   while ((temp = GetNextWord()) == 0x2AA) nFillWords++;
201   if (nFillWords == 0)
202     AliFatal("Incorrect trailer found ! Expected 0x2AA not found !");
203
204   //Then read the trailer
205   if (fPosition <= 4)
206     AliFatal(Form("Incorrect raw data size ! Expected at lest 4 words but found %d !",fPosition));
207
208   fCount = (temp << 4) & 0x3FF;
209   if ((temp >> 6) != 0xA)
210     AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
211
212   temp = GetNextWord();
213   fHWAddress = (temp & 0x3) << 10;
214   if (((temp >> 2) & 0xF) != 0xA)
215     AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",(temp >> 2) & 0xF));
216   fCount |= ((temp & 0x3FF) >> 6);
217   if (fCount == 0) return kFALSE;
218
219   temp = GetNextWord();
220   fHWAddress |= temp;
221
222   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
223
224   return kTRUE;
225 }
226
227 //_____________________________________________________________________________
228 Bool_t AliAltroRawStream::ReadDummyTrailer()
229 {
230   //Read a trailer of 40 bits in the backward reading mode
231   //In case of no mapping is provided, read a dummy trailer
232   UShort_t temp;
233   while ((temp = GetNextWord()) == 0x2AA);
234
235   fSegmentation[0] = temp;
236   fSegmentation[1] = GetNextWord();
237   fSegmentation[2] = GetNextWord();
238   fCount = GetNextWord();
239   if (fCount == 0) return kFALSE;
240   fHWAddress = -1;
241
242   fPosition -= (4 - (fCount % 4)) % 4;  // skip fill words
243
244   return kTRUE;
245 }
246
247 //_____________________________________________________________________________
248 void AliAltroRawStream::ReadBunch()
249 {
250   // Read altro payload in 
251   // backward direction
252   if (fPosition <= 0)
253     AliFatal("Could not read bunch length !");
254
255   fBunchLength = GetNextWord() - 2;
256   fTimeBunch = fBunchLength;
257   fCount--;
258
259   if (fPosition <= 0)
260     AliFatal("Could not read time bin !");
261
262   fTime = GetNextWord();
263   fCount--;
264
265   return;
266 }
267
268 //_____________________________________________________________________________
269 void AliAltroRawStream::ReadAmplitude()
270 {
271   // Read next time bin amplitude
272   if (fPosition <= 0)
273     AliFatal("Could not read sample amplitude !");
274
275   fSignal = GetNextWord();
276   fCount--;
277   fBunchLength--;
278
279   return;
280 }
281
282 //_____________________________________________________________________________
283 Int_t AliAltroRawStream::GetPosition()
284 {
285   // Sets the position in the
286   // input stream
287   // Read the RCU trailer
288   // This includes the trailer size,
289   // RCU identifier and raw data payload.
290   // The RCU trailer format is described
291   // in details in the RCU manual.
292
293   if (!fIsOldRCUFormat) {
294     // First read 32-bit word with the
295     // trailer size (22 bits) and RCU ID (the rest)
296     Int_t index = fRawReader->GetDataSize();
297     UInt_t word = Get32bitWord(index);
298     fRCUId = (Int_t)(word >> 22);
299     Int_t trailerSize = (word & 0x3FFFFF);
300
301     // Now read the beginning of the trailer
302     // where the payload size is written
303     if (trailerSize < 2)
304       AliFatal(Form("Invalid trailer size found (%d bytes) !",trailerSize*4));
305     fRCUTrailerSize = (trailerSize-2)*4;
306     index -= fRCUTrailerSize;
307     if (index < 4)
308       AliFatal(Form("Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%d bytes)!",
309                     trailerSize*4,
310                     fRawReader->GetDataSize()));
311     fRCUTrailerData = fData + index;
312     Int_t position = Get32bitWord(index);
313     // The size is specified in a number of 40bits
314     // Therefore we need to transform it to number of bytes
315     position *= 5;
316
317     // Check the consistency of the header and trailer
318     if ((fRawReader->GetDataSize() - trailerSize*4) != position)
319       AliFatal(Form("Inconsistent raw data size ! Raw data size - %d bytes (from the header), RCU trailer - %d bytes, raw data paylod - %d bytes !",
320                     fRawReader->GetDataSize(),
321                     trailerSize*4,
322                     position));
323
324     return position * 8 / 10;
325   }
326   else {
327     // In case of the Old RCU trailer format
328     // we have to read just the size of altro payload
329     // in units of 40-bit words
330     Int_t index = fRawReader->GetDataSize();
331     Int_t position = Get32bitWord(index);
332
333     fRCUId = -1;
334     fRCUTrailerSize = 0;
335     fRCUTrailerData = NULL;
336
337     // The size is specified in a number of 40bits
338     // Therefore we need to transform it to number of bytes
339     position *= 5;
340
341     if (!fIsShortDataHeader) {
342
343       // Check the consistency of the header and trailer
344       if ((fRawReader->GetDataSize() - 4) != position)
345         AliFatal(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
346                       fRawReader->GetDataSize()-4,
347                       position));
348     }
349     else {
350       // Check the consistency of the header and trailer
351       // In this case the header is shorter by 4 bytes
352       if (fRawReader->GetDataSize() != position)
353         AliFatal(Form("Inconsistent raw data size ! Expected %d bytes (from the header), found %d bytes (in the RCU trailer)!",
354                       fRawReader->GetDataSize(),
355                       position));
356
357       // 7 32-bit words Common Data Header
358       // therefore we have to shift back by 4 bytes
359       // the pointer to the raw data payload
360       fData -= 4;
361     }
362      
363     // Return the position in units of 10-bit words
364     return position*8/10;
365   }
366 }
367
368 //_____________________________________________________________________________
369 UInt_t AliAltroRawStream::Get32bitWord(Int_t &index)
370 {
371   // This method returns the 32 bit word at a given
372   // position inside the raw data payload.
373   // The 'index' points to the beginning of the next word.
374   // The method is supposed to be endian (platform)
375   // independent.
376   if (!fData)
377     AliFatal("Raw data paylod buffer is not yet initialized !");
378   if (index < 4)
379     AliFatal(Form("Invalid raw data payload index (%d) !",index));
380
381   UInt_t word = 0;
382   word  = fData[--index] << 24;
383   word |= fData[--index] << 16;
384   word |= fData[--index] << 8;
385   word |= fData[--index];
386
387   return word;
388 }
389
390 //_____________________________________________________________________________
391 Bool_t AliAltroRawStream::GetRCUTrailerData(UChar_t*& data) const
392 {
393   // Return a pointer to the RCU trailer
394   // data. Should be called always after
395   // the RCU trailer was already processed
396   // in the GetPosition() method
397   if (!fRCUTrailerSize || !fRCUTrailerData) {
398     AliError("No valid RCU trailer data is found !");
399     data = NULL;
400     return kFALSE;
401   }
402
403   data = fRCUTrailerData;
404
405   return kTRUE;
406 }