5e2aa1fed76155c4befc6ec4083d68dd08a71c89
[u/mrichter/AliRoot.git] / TPC / AliTPCBuffer160.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 // 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
22 // Author: D.Favretto
23
24 #include "TObjArray.h"
25 #include "Riostream.h"
26 #include <stdlib.h>
27 #include "AliTPCBuffer160.h"
28 #include "TMath.h"
29
30 ClassImp(AliTPCBuffer160)
31
32 AliTPCBuffer160::AliTPCBuffer160(const char* fileName,Int_t flag){
33   //if flag = 1 the actual object is used in the write mode
34   //if flag = 0 the actual object is used in the read mode
35   fFlag=flag;
36   fCurrentCell=0;
37   fMiniHeaderPos=0;
38   fMaskBackward=0xFF;
39   fVerbose=0;
40   if (flag){
41     fFreeCellBuffer=16;
42     fShift=32; 
43     //the buffer is cleaned 
44     for (Int_t i=0;i<5;i++)fBuffer[i]=0;
45     //open the output file
46     f.open(fileName,ios::binary|ios::out);
47   }
48   else{
49     //open the input file
50     f.open(fileName,ios::binary|ios::in);
51     if(!f){cout<<"File doesn't exist\n";exit(-1);}
52     fShift=0;
53     //To get the file dimension (position of the last element in term of bytes)
54     f.seekg(0, ios::end);
55     fFilePosition= f.tellg();
56     fFileEnd=fFilePosition;
57     f.seekg(0);
58   }
59 }
60
61 AliTPCBuffer160::~AliTPCBuffer160(){
62   // destructor
63   if (fFlag){
64     //Flush out the Buffer content at the end only if Buffer wasn't completely filled
65     Flush();
66     if(fVerbose)
67       cout<<"File Created\n";
68   }//end if
69   f.close();
70 }
71
72
73 AliTPCBuffer160::AliTPCBuffer160(const AliTPCBuffer160 &source){
74   // Copy Constructor
75   if(&source==this)return;
76   this->fShift=source.fShift;
77   this->fCurrentCell=source.fCurrentCell;
78   this->fFreeCellBuffer=source.fFreeCellBuffer;
79   this->fFlag=source.fFlag;
80   this->fMaskBackward=source.fMaskBackward;
81   this->fFilePosition=source.fFilePosition;
82   this->fMiniHeaderPos=source.fMiniHeaderPos;
83   this->fVerbose=source.fVerbose;
84   for (Int_t i=0;i<5;i++)this->fBuffer[i]=source.fBuffer[i];
85   return;
86 }
87
88 AliTPCBuffer160& AliTPCBuffer160::operator=(const AliTPCBuffer160 &source){
89   //Assigment operator
90   if(&source==this)return *this;
91   this->fShift=source.fShift;
92   this->fCurrentCell=source.fCurrentCell;
93   this->fFreeCellBuffer=source.fFreeCellBuffer;
94   this->fFlag=source.fFlag;
95   this->fMaskBackward=source.fMaskBackward;
96   this->fFilePosition=source.fFilePosition;
97   this->fMiniHeaderPos=source.fMiniHeaderPos;
98   this->fVerbose=source.fVerbose;
99   for (Int_t i=0;i<5;i++)this->fBuffer[i]=source.fBuffer[i];
100   return *this;
101 }
102
103 Int_t AliTPCBuffer160::GetNext(){
104   //It reads a 10 bits word in forward dicection from the Buffer.
105   //A new Buffer is read from the file only when Buffer is empty.
106   //If there aren't elements anymore -1 is returned otherwise 
107   //the next element is returned
108   ULong_t mask=0xFFC00000;
109   ULong_t temp;
110   ULong_t value;
111   if (!fShift){
112     if ( f.read((char*)fBuffer,sizeof(ULong_t)*5) ){
113       fCurrentCell=0;
114       fShift=22;
115       value=fBuffer[fCurrentCell]&mask;
116       value=value>>22;
117       fBuffer[fCurrentCell]=fBuffer[fCurrentCell]<<10;
118       return value;      
119     }
120     else return -1;
121   }//end if
122   else{
123     if (fShift>=10){
124       value=fBuffer[fCurrentCell]&mask;
125       value=value>>22;
126       fShift-=10;
127       fBuffer[fCurrentCell]=fBuffer[fCurrentCell]<<10;
128     }
129     else{
130       value=fBuffer[fCurrentCell]&mask;
131       fCurrentCell++;
132       temp=fBuffer[fCurrentCell];
133       temp=temp>>fShift;
134       temp=temp&mask;
135       value=value|temp;
136       value=value>>22;
137       fBuffer[fCurrentCell]=fBuffer[fCurrentCell]<<(10-fShift);
138       fShift=22+fShift;
139     }
140     return value;
141   }//end else
142 }
143
144 Int_t AliTPCBuffer160::GetNextBackWord(){
145   //It reads a 10 bits word in backward dicection from the Buffer.
146   //A new Buffer is read from the file only when Buffer is empty.
147   //If there aren't elements anymore -1 is returned otherwise 
148   //the next element is returned
149   ULong_t mask=0x3FF;
150   ULong_t temp;
151   ULong_t value;
152   if (!fShift){
153     if (fFilePosition){
154       fFilePosition-=sizeof(ULong_t)*5;
155       f.seekg(fFilePosition);
156       f.read((char*)fBuffer,sizeof(ULong_t)*5);
157       fCurrentCell=4;
158       fShift=22;
159       fMaskBackward=0xFF;
160       value=fBuffer[fCurrentCell]&mask;
161       fBuffer[fCurrentCell]=fBuffer[fCurrentCell]>>10;
162       return value;      
163     }
164     else return -1;
165   }//end if
166   else{
167     if (fShift>=10){
168       value=fBuffer[fCurrentCell]&mask;
169       fShift-=10;
170       fBuffer[fCurrentCell]=fBuffer[fCurrentCell]>>10;
171     }
172     else{
173       value=fBuffer[fCurrentCell];
174       fCurrentCell--;
175       temp=fBuffer[fCurrentCell]&mask;
176       temp=temp&fMaskBackward;
177       fMaskBackward=fMaskBackward>>2;
178       temp=temp<<fShift;
179       value=value|temp;
180       fBuffer[fCurrentCell]=fBuffer[fCurrentCell]>>(10-fShift);
181       fShift=22+fShift;
182     }
183     return value;
184   }//end else
185 }
186
187 void AliTPCBuffer160::Flush(){
188   // Flushes the Buffer content 
189   if(fFreeCellBuffer!=16){
190     Int_t temp=fFreeCellBuffer;
191     for(Int_t i=0;i<temp;i++){
192       FillBuffer(0x2AA);
193     }//end for
194   }//end if
195 }
196
197 void AliTPCBuffer160::FillBuffer(Int_t Val){
198   //Fills the Buffer with 16 ten bits words and write into a file 
199   fFreeCellBuffer--;
200   if (fShift<10){
201     Int_t temp=Val;
202     Val=Val>>(10-fShift);
203     fBuffer[fCurrentCell]|=Val;
204     fCurrentCell++;
205     fShift+=32;
206     Val=temp;
207   }
208   fShift-=10;
209   Val=Val<<fShift;
210   fBuffer[fCurrentCell]|=Val;
211   if(!fShift){
212     //Buffer is written into a file
213     f.write((char*)fBuffer,sizeof(ULong_t)*5);
214    //Buffer is empty
215     for(Int_t j=0;j<5;j++)fBuffer[j]=0;
216     fShift=32;
217     fCurrentCell=0;
218     fFreeCellBuffer=16;
219   }
220   /*
221     for(Int_t jj=0;jj<5;jj++){
222     cout.flags(ios::hex);
223     cout<<fBuffer[jj]<<endl;
224     cout.flags(ios::dec);
225     }
226     
227   */
228   return;
229 }
230
231 void   AliTPCBuffer160::WriteTrailer(Int_t WordsNumber,Int_t PadNumber,Int_t RowNumber,Int_t SecNumber){
232   //Writes a trailer of 40 bits
233   Int_t num=fFreeCellBuffer%4;
234   for(Int_t i=0;i<num;i++){
235     FillBuffer(0x2AA);
236   }//end for
237   FillBuffer(WordsNumber);
238   FillBuffer(PadNumber);
239   FillBuffer(RowNumber);
240   FillBuffer(SecNumber);
241 }
242
243 void AliTPCBuffer160::ReadTrailer(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber){
244   //Read a trailer of 40 bits in the forward reading mode
245   WordsNumber=GetNext();
246   PadNumber=GetNext();
247   RowNumber=GetNext();
248   SecNumber=GetNext();
249 }
250
251
252 Int_t AliTPCBuffer160::ReadTrailerBackward(Int_t &WordsNumber,Int_t &PadNumber,Int_t &RowNumber,Int_t &SecNumber){
253   //Read a trailer of 40 bits in the backward reading mode
254   Int_t temp;
255   fEndingFillWords=0;
256   do{
257     temp=GetNextBackWord();
258     fEndingFillWords++;
259     if (temp==-1)return -1;
260   }while (temp==0x2AA);  
261   fEndingFillWords--;
262   SecNumber=temp;
263   RowNumber=GetNextBackWord();
264   PadNumber=GetNextBackWord();
265   WordsNumber=GetNextBackWord();
266   return 0;
267
268
269 void AliTPCBuffer160::WriteMiniHeader(ULong_t Size,Int_t SecNumber,Int_t SubSector,Int_t Detector,Int_t Flag ){
270   //Size msg errore sector number sub-sector number 0 for TPC 0 for uncompressed
271   Int_t ddlNumber;
272   ULong_t miniHeader[3];
273   Int_t version=1;
274   if(SecNumber<36)
275     ddlNumber=SecNumber*2+SubSector;
276   else
277     ddlNumber=72+(SecNumber-36)*4+SubSector;
278   //  cout<<"DDL number "<<ddlNumber<<endl;
279   for(Int_t i=0;i<3;i++)miniHeader[i]=0;
280   Int_t miniHeaderSize=(sizeof(ULong_t))*3;
281   PackWord(miniHeader[1],Detector,0,7);
282   PackWord(miniHeader[1],0x123456,8,31);
283   PackWord(miniHeader[2],version,0,7);
284   PackWord(miniHeader[2],Flag,8,15);
285   PackWord(miniHeader[2],ddlNumber,16,31);
286   if (!Size){
287     //if size=0 it means that this mini header is a dummi mini header
288     fMiniHeaderPos=f.tellp();
289     //cout<<" Position of the DUMMY MH:"<<fMiniHeaderPos<<" Size:"<<Size<<endl;
290     miniHeader[0]=Size;
291     f.write((char*)(miniHeader),miniHeaderSize);
292   }//end if
293   else{
294     ULong_t currentFilePos=f.tellp();
295     f.seekp(fMiniHeaderPos);
296     Size=currentFilePos-fMiniHeaderPos-miniHeaderSize;
297     //cout<<"Current Position (Next MH) "<<currentFilePos<<" Position of the MH:"<<fMiniHeaderPos<<" Size:"<<Size<<endl;
298     miniHeader[0]=Size;
299     //cout<<"Mini Header Size:"<<miniHeader[0]<<endl;
300     f.write((char*)(miniHeader),miniHeaderSize);
301     f.seekp(currentFilePos);
302   }
303   return;
304 }
305
306
307 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
308
309 void AliTPCBuffer160::PackWord(ULong_t &BaseWord, ULong_t Word, Int_t StartBit, Int_t StopBit){
310   //Packs a word into the BaseWord buffer from StartBit bit up to StopBit bit
311   ULong_t dummyWord,offSet;
312   Int_t   length;
313   ULong_t sum;
314   //The BaseWord is being filled with 1 from StartBit to StopBit
315   length=StopBit-StartBit+1;
316   sum=(ULong_t)TMath::Power(2,length)-1;
317   if(Word > sum){
318     cout<<"WARNING::Word to be filled is not within desired length"<<endl;
319     exit(-1);
320   }
321   offSet=sum;
322   offSet<<=StartBit;
323   BaseWord=BaseWord|offSet;
324   //The Word to be filled is shifted to the position StartBit
325   //and the remaining  Left and Right bits are filled with 1
326   sum=(ULong_t)TMath::Power(2,StartBit)-1;
327   dummyWord=0xFFFFFFFF<<length;
328   dummyWord +=Word;
329   dummyWord<<=StartBit;
330   dummyWord+=sum;
331   BaseWord=BaseWord&dummyWord;
332   return;
333 }
334
335 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
336
337 void AliTPCBuffer160::UnpackWord(ULong_t PackedWord, Int_t StartBit, Int_t StopBit, ULong_t &Word){     
338   //Unpacks a word of StopBit-StartBit+1 bits from PackedWord buffer starting from the position 
339   //indicated by StartBit
340   ULong_t offSet;
341   Int_t length;
342   length=StopBit-StartBit+1;
343   offSet=(ULong_t)TMath::Power(2,length)-1;
344   offSet<<=StartBit;
345   Word=PackedWord&offSet;
346   Word>>=StartBit;
347   return;
348 }
349
350 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////