Adding a missing include file
[u/mrichter/AliRoot.git] / RAW / AliAltroBuffer.cxx
CommitLineData
3ea47630 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// Interface to the Altro format
19// to read and write digits
20// To be used in Alice Data Challenges
21// and in the compression of the RAW data
3ea47630 22
23#include "AliAltroBuffer.h"
5802cf2d 24#include "AliAltroMapping.h"
3ea47630 25#include "AliRawDataHeader.h"
5802cf2d 26#include "AliLog.h"
3ea47630 27#include <Riostream.h>
28#include <stdlib.h>
29
30
31ClassImp(AliAltroBuffer)
32
3ea47630 33//_____________________________________________________________________________
5802cf2d 34AliAltroBuffer::AliAltroBuffer(const char* fileName, Int_t flag, const AliAltroMapping *mapping):
3ea47630 35 fShift(0),
36 fCurrentCell(0),
37 fFreeCellBuffer(0),
38 fFlag(flag),
39 fVerbose(0),
40 fFile(NULL),
41 fMaskBackward(0xFF),
42 fFilePosition(0),
43 fFileEnd(0),
44 fDataHeaderPos(0),
5802cf2d 45 fEndingFillWords(0),
46 fMapping(mapping)
3ea47630 47{
48//if flag = 1 the actual object is used in the write mode
49//if flag = 0 the actual object is used in the read mode
50
51 //the buffer is cleaned
52 for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0;
53
54 if (flag) {
55 fFreeCellBuffer = 16;
56 fShift = 32;
57 //open the output file
58#ifndef __DECCXX
59 fFile = new fstream(fileName, ios::binary|ios::out);
60#else
61 fFile = new fstream(fileName, ios::out);
62#endif
63 } else {
64 //open the input file
65#ifndef __DECCXX
66 fFile = new fstream(fileName, ios::binary|ios::in);
67#else
68 fFile = new fstream(fileName, ios::in);
69#endif
70 if (!fFile) {
71 Error("AliAltroBuffer", "File doesn't exist: %s", fileName);
72 return;
73 }
74 fShift = 0;
75 //To get the file dimension (position of the last element in term of bytes)
76 fFile->seekg(0, ios::end);
77 fFilePosition = fFile->tellg();
78 fFileEnd = fFilePosition;
79 fFile->seekg(0);
80 }
5802cf2d 81
3ea47630 82}
83
84//_____________________________________________________________________________
85AliAltroBuffer::~AliAltroBuffer()
86{
87// destructor
88
89 if (fFlag) {
90 //Flush out the Buffer content at the end only if Buffer wasn't completely filled
91 Flush();
92 if (fVerbose) Info("~AliAltroBuffer", "File Created");
93 }//end if
94 fFile->close();
95 delete fFile;
5802cf2d 96
3ea47630 97}
98
99//_____________________________________________________________________________
100AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source):
101 TObject(source),
102 fShift(source.fShift),
103 fCurrentCell(source.fCurrentCell),
104 fFreeCellBuffer(source.fFreeCellBuffer),
105 fFlag(source.fFlag),
106 fVerbose(source.fVerbose),
107 fFile(NULL),
108 fMaskBackward(source.fMaskBackward),
109 fFilePosition(source.fFilePosition),
110 fFileEnd(source.fFileEnd),
111 fDataHeaderPos(source.fDataHeaderPos),
5802cf2d 112 fEndingFillWords(source.fEndingFillWords),
113 fMapping(source.fMapping)
3ea47630 114{
115// Copy Constructor
116
117 Fatal("AliAltroBuffer", "copy constructor not implemented");
118}
119
120//_____________________________________________________________________________
121AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/)
122{
123//Assigment operator
124
125 Fatal("operator =", "assignment operator not implemented");
126 return *this;
127}
128
129
130//_____________________________________________________________________________
131Int_t AliAltroBuffer::GetNext()
132{
133//It reads a 10 bits word in forward dicection from the Buffer.
134//A new Buffer is read from the file only when Buffer is empty.
135//If there aren't elements anymore -1 is returned otherwise
136//the next element is returned
137
138 UInt_t mask = 0xFFC00000;
139 UInt_t temp;
140 UInt_t value;
141 if (!fShift) {
142 if (fFile->tellg() >= (Int_t)fFileEnd) return -1;
143 if (fFile->read((char*)fBuffer, sizeof(UInt_t)*5)) {
144 fCurrentCell = 0;
145 fShift = 22;
146 value = fBuffer[fCurrentCell] & mask;
147 value = value >> 22;
148 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
149 return value;
150 } else {
151 return -1;
152 }
153 } else {
154 if (fShift >= 10) {
155 value = fBuffer[fCurrentCell] & mask;
156 value = value >> 22;
157 fShift -= 10;
158 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << 10;
159 } else {
160 value = fBuffer[fCurrentCell] & mask;
161 fCurrentCell++;
162 temp = fBuffer[fCurrentCell];
163 temp = temp >> fShift;
164 temp = temp & mask;
165 value = value | temp;
166 value = value >> 22;
167 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] << (10-fShift);
168 fShift += 22;
169 }
170 return value;
171 }//end else
172}
173
174//_____________________________________________________________________________
175Int_t AliAltroBuffer::GetNextBackWord()
176{
177//It reads a 10 bits word in backward dicection from the Buffer.
178//A new Buffer is read from the file only when Buffer is empty.
179//If there aren't elements anymore -1 is returned otherwise
180//the next element is returned
181
182 UInt_t mask = 0x3FF;
183 UInt_t temp;
184 UInt_t value;
185 if (!fShift) {
186 if (fFilePosition > fDataHeaderPos){
187 fFilePosition -= sizeof(UInt_t)*5;
188 fFile->seekg(fFilePosition);
189 fFile->read((char*)fBuffer, sizeof(UInt_t)*5);
190
191 fCurrentCell = 4;
192 fShift = 22;
193 fMaskBackward = 0xFF;
194 value = fBuffer[fCurrentCell] & mask;
195 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
196 return value;
197 } else {
198 fFile->seekg(fDataHeaderPos);
199 return -1;
200 }
201 } else {
202 if (fShift >= 10) {
203 value = fBuffer[fCurrentCell] & mask;
204 fShift -= 10;
205 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> 10;
206 } else {
207 value = fBuffer[fCurrentCell];
208 fCurrentCell--;
209 temp = fBuffer[fCurrentCell] & mask;
210 temp = temp & fMaskBackward;
211 fMaskBackward = fMaskBackward >> 2;
212 temp = temp << fShift;
213 value = value | temp;
214 fBuffer[fCurrentCell] = fBuffer[fCurrentCell] >> (10-fShift);
215 fShift = 22 + fShift;
216 }
217 return value;
218 }//end else
219}
220
221//_____________________________________________________________________________
222void AliAltroBuffer::Flush()
223{
224// Flushes the Buffer content
225 if (fFreeCellBuffer != 16) {
226 Int_t temp = fFreeCellBuffer;
227 for (Int_t i = 0; i < temp; i++){
228 FillBuffer(0x2AA);
229 }//end for
230 }//end if
231}
232
233//_____________________________________________________________________________
234void AliAltroBuffer::FillBuffer(Int_t val)
235{
236//Fills the Buffer with 16 ten bits words and write into a file
237
23b19451 238 if ((val > 0x3FF) || (val < 0)) {
239 Error("FillBuffer", "Value out of range (10 bits): %d", val);
240 val = 0x3FF;
241 }
3ea47630 242 fFreeCellBuffer--;
243 if (fShift < 10) {
244 Int_t temp = val;
245 val = val >> (10-fShift);
246 fBuffer[fCurrentCell] |= val;
247 fCurrentCell++;
248 fShift += 32;
249 val = temp;
250 }
251 fShift -= 10;
252 val = val << fShift;
253 fBuffer[fCurrentCell] |= val;
254 if (!fShift) {
255 //Buffer is written into a file
256 fFile->write((char*)fBuffer, sizeof(UInt_t)*5);
257 //Buffer is empty
258 for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0;
259 fShift = 32;
260 fCurrentCell = 0;
261 fFreeCellBuffer = 16;
262 }
263}
264
265
266//_____________________________________________________________________________
5802cf2d 267void AliAltroBuffer::WriteDummyTrailer(Int_t wordsNumber, Int_t padNumber,
268 Int_t rowNumber, Int_t secNumber)
269{
270//Writes a trailer of 40 bits
271
272 Int_t num = fFreeCellBuffer % 4;
273 for(Int_t i = 0; i < num; i++) {
274 FillBuffer(0x2AA);
275 }//end for
276 FillBuffer(wordsNumber);
277 FillBuffer(padNumber);
278 FillBuffer(rowNumber);
279 FillBuffer(secNumber);
280}
281
282//_____________________________________________________________________________
3ea47630 283void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber,
284 Int_t rowNumber, Int_t secNumber)
285{
286//Writes a trailer of 40 bits
287
5802cf2d 288 if (!fMapping) {
289 AliError("No ALTRO mapping information is loaded! Filling a dummy trailer!");
290 return WriteDummyTrailer(wordsNumber,padNumber,
291 rowNumber,secNumber);
292 }
293
cc934096 294 Short_t hwAddress = fMapping->GetHWAddress(rowNumber,padNumber,secNumber);
295 if (hwAddress == -1)
20daa34d 296 AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber));
cc934096 297 WriteTrailer(wordsNumber,hwAddress);
20daa34d 298}
299
300//_____________________________________________________________________________
cc934096 301void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Short_t hwAddress)
20daa34d 302{
303//Writes a trailer of 40 bits using
304//a given hardware adress
3ea47630 305 Int_t num = fFreeCellBuffer % 4;
306 for(Int_t i = 0; i < num; i++) {
307 FillBuffer(0x2AA);
308 }//end for
5802cf2d 309 Int_t temp;
cc934096 310 temp = hwAddress & 0x3FF;
5802cf2d 311 FillBuffer(temp);
cc934096 312
5802cf2d 313 temp = (wordsNumber << 6) & 0x3FF;
314 temp |= (0xA << 2);
cc934096 315 temp |= ((hwAddress >> 10) & 0x3);
316 FillBuffer(temp);
5802cf2d 317
cc934096 318 temp = 0xA << 6;
319 temp |= ((wordsNumber & 0x3FF) >> 4);
5802cf2d 320 FillBuffer(temp);
cc934096 321
322 temp = 0x2AA;
5802cf2d 323 FillBuffer(temp);
3ea47630 324}
325
326//_____________________________________________________________________________
16e29964 327Bool_t AliAltroBuffer::ReadDummyTrailer(Int_t& wordsNumber, Int_t& padNumber,
328 Int_t& rowNumber, Int_t& secNumber)
3ea47630 329{
16e29964 330//Read a dummy trailer of 40 bits in the forward reading mode
3ea47630 331
332 wordsNumber = GetNext();
333 if (wordsNumber == -1) return kFALSE;
334 padNumber = GetNext();
335 if (padNumber == -1) return kFALSE;
336 rowNumber = GetNext();
337 if (rowNumber == -1) return kFALSE;
338 secNumber = GetNext();
339 if (secNumber == -1) return kFALSE;
340 return kTRUE;
341}
342
343//_____________________________________________________________________________
16e29964 344Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Int_t& padNumber,
345 Int_t& rowNumber, Int_t& secNumber)
346{
347//Read a trailer of 40 bits in the forward reading mode
348 if (!fMapping) {
349 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
350 return ReadDummyTrailer(wordsNumber,padNumber,
351 rowNumber,secNumber);
352 }
353
cc934096 354 Short_t hwAddress;
355 if (!ReadTrailer(wordsNumber,hwAddress)) return kFALSE;
356 rowNumber = fMapping->GetPadRow(hwAddress);
357 padNumber = fMapping->GetPad(hwAddress);
358 secNumber = fMapping->GetSector(hwAddress);
20daa34d 359
360 return kTRUE;
361}
362
363//_____________________________________________________________________________
cc934096 364Bool_t AliAltroBuffer::ReadTrailer(Int_t& wordsNumber, Short_t& hwAddress)
20daa34d 365{
366//Read a trailer of 40 bits in the forward reading mode
367
16e29964 368 Int_t temp = GetNext();
cc934096 369 hwAddress = temp;
16e29964 370
371 temp = GetNext();
cc934096 372 wordsNumber = ((temp & 0x3FF) >> 6);
20daa34d 373 if (((temp >> 2) & 0xF) != 0xA)
16e29964 374 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",temp >> 6));
cc934096 375 hwAddress |= (temp & 0x3) << 10;
376
377 temp = GetNext();
378 if ((temp >> 6) != 0xA)
379 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
380 wordsNumber |= (temp << 4) & 0x3FF;
16e29964 381
382 temp = GetNext();
cc934096 383 if (temp != 0x2AA)
384 AliFatal(Form("Incorrect trailer found ! Expecting 0x2AA but found %x !",temp));
16e29964 385
16e29964 386 return kTRUE;
387}
388
389//_____________________________________________________________________________
20daa34d 390Bool_t AliAltroBuffer::ReadDummyTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
391 Int_t& rowNumber, Int_t& secNumber)
3ea47630 392{
393//Read a trailer of 40 bits in the backward reading mode
394
395 Int_t temp;
396 fEndingFillWords = 0;
397 do {
398 temp = GetNextBackWord();
399 fEndingFillWords++;
400 if (temp == -1) return kFALSE;
401 } while (temp == 0x2AA);
402 fEndingFillWords--;
403 secNumber = temp;
404 rowNumber = GetNextBackWord();
405 if (rowNumber == -1) return kFALSE;
406 padNumber = GetNextBackWord();
407 if (padNumber == -1) return kFALSE;
408 wordsNumber = GetNextBackWord();
409 if (wordsNumber == -1) return kFALSE;
410 return kTRUE;
411}
412
20daa34d 413//_____________________________________________________________________________
414Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Int_t& padNumber,
415 Int_t& rowNumber, Int_t& secNumber)
416{
417//Read a trailer of 40 bits in the backward reading mode
418 if (!fMapping) {
419 AliError("No ALTRO mapping information is loaded! Reading a dummy trailer!");
420 return ReadDummyTrailerBackward(wordsNumber,padNumber,
421 rowNumber,secNumber);
422 }
423
cc934096 424 Short_t hwAddress;
425 if (!ReadTrailerBackward(wordsNumber,hwAddress)) return kFALSE;
426 rowNumber = fMapping->GetPadRow(hwAddress);
427 padNumber = fMapping->GetPad(hwAddress);
428 secNumber = fMapping->GetSector(hwAddress);
20daa34d 429
430 return kTRUE;
431}
432
433//_____________________________________________________________________________
cc934096 434Bool_t AliAltroBuffer::ReadTrailerBackward(Int_t& wordsNumber, Short_t& hwAddress)
20daa34d 435{
436//Read a trailer of 40 bits in the backward reading mode
437
438 Int_t temp;
439 fEndingFillWords = 0;
cc934096 440 while ((temp = GetNextBackWord()) == 0x2AA) {
20daa34d 441 fEndingFillWords++;
442 if (temp == -1) return kFALSE;
cc934096 443 };
444 if (fEndingFillWords == 0)
445 AliFatal("Incorrect trailer found ! Expected 0x2AA not found !");
20daa34d 446 fEndingFillWords--;
447
cc934096 448 wordsNumber = (temp << 4) & 0x3FF;
449 if ((temp >> 6) != 0xA)
450 AliFatal(Form("Incorrect trailer found ! Expecting 0xA but found %x !",temp >> 6));
20daa34d 451
452 temp = GetNextBackWord();
cc934096 453 hwAddress = (temp & 0x3) << 10;
20daa34d 454 if (((temp >> 2) & 0xF) != 0xA)
cc934096 455 AliFatal(Form("Incorrect trailer found ! Expecting second 0xA but found %x !",(temp >> 2) & 0xF));
456 wordsNumber |= ((temp & 0x3FF) >> 6);
20daa34d 457
458 temp = GetNextBackWord();
cc934096 459 hwAddress |= temp;
20daa34d 460
461 return kTRUE;
462}
3ea47630 463
464//_____________________________________________________________________________
465void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber,
466 Int_t secNumber,
467 Int_t nTimeBins, const Int_t* adcValues,
468 Int_t threshold)
469{
cc934096 470 //Write all ADC values and the trailer of a channel
471 Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
472 // write the trailer
473 WriteTrailer(nWords, padNumber, rowNumber, secNumber);
474}
475
476//_____________________________________________________________________________
477void AliAltroBuffer::WriteChannel(Short_t hwAddress,
478 Int_t nTimeBins, const Int_t* adcValues,
479 Int_t threshold)
480{
481 //Write all ADC values and the trailer of a channel
482 Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold);
483 // write the trailer
484 WriteTrailer(nWords, hwAddress);
485}
486
487//_____________________________________________________________________________
488Int_t AliAltroBuffer::WriteBunch(Int_t nTimeBins, const Int_t* adcValues,
489 Int_t threshold)
490{
491 //Write all ADC values
492 //Return number of words written
3ea47630 493
494 Int_t nWords = 0;
495 Int_t timeBin = -1;
496 Int_t bunchLength = 0;
497
498 // loop over time bins
499 for (Int_t iTime = 0; iTime < nTimeBins; iTime++) {
500 if (adcValues[iTime] >= threshold) { // ADC value above threshold
501 FillBuffer(adcValues[iTime]);
502 nWords++;
503 timeBin = iTime;
504 bunchLength++;
505
506 } else if (timeBin >= 0) { // end of bunch
507 FillBuffer(timeBin);
508 FillBuffer(bunchLength + 2);
509 nWords += 2;
510 timeBin = -1;
511 bunchLength = 0;
512 }
513 }
514
515 if (timeBin >= 0) { // end of bunch
516 FillBuffer(timeBin);
517 FillBuffer(bunchLength + 2);
518 nWords += 2;
519 }
520
cc934096 521 return nWords;
3ea47630 522}
523
20daa34d 524//_____________________________________________________________________________
cc934096 525void AliAltroBuffer::ReadChannelBackward(Int_t& padNumber, Int_t& rowNumber,
526 Int_t& secNumber,
527 Int_t& nTimeBins, Int_t* adcValues)
20daa34d 528{
cc934096 529//Read all ADC values and the trailer of a channel (in backward order)
20daa34d 530
531 Int_t wordsNumber;
cc934096 532 if (!ReadTrailerBackward(wordsNumber,padNumber,
533 rowNumber,secNumber)) return;
534 return ReadBunchBackward(wordsNumber,nTimeBins,adcValues);
535}
20daa34d 536
cc934096 537//_____________________________________________________________________________
538void AliAltroBuffer::ReadChannelBackward(Short_t& hwAddress,
539 Int_t& nTimeBins, Int_t* adcValues)
540{
541//Read all ADC values and the trailer of a channel (in backward order)
542
543 Int_t wordsNumber;
544 if (!ReadTrailerBackward(wordsNumber,
545 hwAddress)) return;
546 return ReadBunchBackward(wordsNumber,nTimeBins,adcValues);
547}
548
549//_____________________________________________________________________________
550void AliAltroBuffer::ReadBunchBackward(Int_t wordsNumber,
551 Int_t& nTimeBins, Int_t* adcValues)
552{
20daa34d 553 if (wordsNumber < 0) return;
554 // Number of fill words
555 Int_t nFillWords;
556 if ((wordsNumber % 4) == 0)
557 nFillWords = 0;
558 else
559 nFillWords = 4 - wordsNumber % 4;
560 // Read the fill words
561 for (Int_t i = 0; i < nFillWords; i++) {
cc934096 562 Int_t temp = GetNextBackWord();
20daa34d 563 if (temp != 0x2AA)
564 AliFatal(Form("Invalid fill word, expected 0x2AA, but got %X", temp));
565 }
566
567 // Decoding
568 Int_t lastWord = wordsNumber;
569 nTimeBins = -1;
570 while (lastWord > 0) {
cc934096 571 Int_t l = GetNextBackWord();
20daa34d 572 if (l < 0) AliFatal(Form("Bad bunch length (%d) !", l));
cc934096 573 Int_t t = GetNextBackWord();
20daa34d 574 if (t < 0) AliFatal(Form("Bad bunch time (%d) !", t));
575 lastWord -= 2;
576 if (nTimeBins == -1) nTimeBins = t + 1;
577 for (Int_t i = 2; i < l; i++) {
cc934096 578 Int_t amp = GetNextBackWord();
20daa34d 579 if (amp < 0) AliFatal(Form("Bad adc value (%X) !", amp));
580 adcValues[t - (i-2)] = amp;
581 lastWord--;
582 }
583 }
584
585}
3ea47630 586
587//_____________________________________________________________________________
588void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t compressed)
589{
590//Write a (dummy or real) DDL data header,
591//set the compression bit if compressed
592
593 AliRawDataHeader header;
594 if (dummy) {
595 //if size=0 it means that this data header is a dummy data header
596 fDataHeaderPos = fFile->tellp();
597 fFile->write((char*)(&header), sizeof(header));
598 } else {
599 UInt_t currentFilePos = fFile->tellp();
600 fFile->seekp(fDataHeaderPos);
601 header.fSize = currentFilePos-fDataHeaderPos;
602 header.SetAttribute(0); // valid data
603 if (compressed) header.SetAttribute(1);
604 fFile->write((char*)(&header), sizeof(header));
605 fFile->seekp(currentFilePos);
606 }
607}
b0aef454 608
609//_____________________________________________________________________________
610Bool_t AliAltroBuffer::ReadDataHeader()
611{
612//Read the DDL data header at the beginning of the file,
613//returns true in case of valid data
614
615 AliRawDataHeader header;
616 UInt_t currentPos = fFile->tellp();
617 fFile->seekp(0);
618 if (!fFile->read((char*)(&header), sizeof(header))) return kFALSE;
619 fDataHeaderPos = fFile->tellp();
620 fFile->seekp(currentPos);
621 return header.TestAttribute(0);
622}
5802cf2d 623