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