]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/RCU/AliHLTAltroEncoder.cxx
58d2c1ff44d60bf1bdbfa34c642710760ae5899a
[u/mrichter/AliRoot.git] / HLT / RCU / AliHLTAltroEncoder.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /** @file   AliHLTAltroEncoder.cxx
20     @author Matthias Richter
21     @date   
22     @brief  Encoder class for 10/40bit Altro Data format
23 */
24
25 #include <cassert>
26 #include <cerrno>
27 #include "AliHLTAltroEncoder.h"
28 #include "TArrayC.h"
29
30 /** ROOT macro for the implementation of ROOT specific class methods */
31 ClassImp(AliHLTAltroEncoder)
32
33 AliHLTAltroEncoder::AliHLTAltroEncoder()
34   :
35   fpBuffer(NULL),
36   fBufferSize(0),
37   fPrevTimebin(AliHLTUInt16MAX),
38   fBunchLength(0),
39   fChannelStart(0),
40   fChannel(AliHLTUInt16MAX),
41   fChannels(),
42   fOffset(0),
43   f10bitWords(0),
44   fOrder(kUnknownOrder),
45   fpCDH(NULL),
46   fpRCUTrailer(NULL)
47 {
48   // see header file for class documentation
49   // or
50   // refer to README to build package
51   // or
52   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
53 }
54
55 AliHLTAltroEncoder::AliHLTAltroEncoder(AliHLTUInt8_t* pBuffer, int iSize)
56   :
57   fpBuffer(pBuffer),
58   fBufferSize(iSize),
59   fPrevTimebin(AliHLTUInt16MAX),
60   fBunchLength(0),
61   fChannelStart(0),
62   fChannel(AliHLTUInt16MAX),
63   fChannels(),
64   fOffset(0),
65   f10bitWords(0),
66   fOrder(kUnknownOrder),
67   fpCDH(NULL),
68   fpRCUTrailer(NULL)
69 {
70   // see header file for class documentation
71 }
72
73 AliHLTAltroEncoder::~AliHLTAltroEncoder()
74 {
75   // see header file for class documentation
76   if (fpCDH) delete fpCDH;
77   fpCDH=NULL;
78
79   if (fpRCUTrailer) delete fpRCUTrailer;
80   fpRCUTrailer=NULL;
81 }
82
83 int AliHLTAltroEncoder::SetBuffer(AliHLTUInt8_t* pBuffer, int iSize)
84 {
85   // see header file for class documentation
86   fpBuffer=pBuffer;
87   fBufferSize=iSize;
88
89   return 0;
90 }
91
92 int AliHLTAltroEncoder::AddSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin)
93 {
94   // see header file for class documentation
95   int iResult=0;
96   if (fPrevTimebin!=AliHLTUInt16MAX) {
97     if (fPrevTimebin==timebin){
98       HLTWarning("timebin missmatch, two subsequent signals with identical time added, ignoring signal %d at time %d", signal, timebin);
99       return -EINVAL;
100     }
101     //assert(fPrevTimebin!=timebin);
102     if (fOrder==kUnknownOrder) {
103       if (fPrevTimebin+1==timebin) fOrder=kAscending;
104       else if (fPrevTimebin==timebin+1) fOrder=kDescending;
105     }
106     if ((fOrder!=kAscending || fPrevTimebin+1!=timebin) &&
107         (fOrder!=kDescending || fPrevTimebin!=timebin+1)) {
108       // Finalize bunch and start new one
109       iResult=SetBunch();
110     }
111   }
112
113   if (iResult>=0 && (iResult=Add10BitValue(signal))>=0) {
114     fBunchLength++;
115   }
116   //  HLTDebug("fOffset: %d  (fOffset-32)*4: %d  f10bitWords*5 %d", fOffset,(fOffset-32)*4,f10bitWords*5);
117   assert((fOffset-(fpCDH?fpCDH->GetSize():0)*4)<=f10bitWords*5);//32 is here size of CDH 8 32bit words
118   fPrevTimebin=timebin;
119   return iResult;
120 }
121
122 int AliHLTAltroEncoder::SetChannel(AliHLTUInt16_t hwaddress)
123 {
124   // see header file for class documentation
125   int iResult=0;
126   int added10BitWords=0;
127   if (!fpBuffer) return -ENODEV;
128   if (fOffset+5>=fBufferSize-(fpRCUTrailer?fpRCUTrailer->GetSize():0)) {
129     HLTWarning("buffer too small too finalize channel: %d of %d byte(s) already used", fOffset, fBufferSize);
130     return -ENOSPC;
131   }
132
133   if (iResult>=0 && 
134       (iResult=SetBunch())>=0) {
135     AliHLTUInt16_t length=f10bitWords-fChannelStart;
136     if ((iResult=Pad40Bit())<0) return iResult;
137     // 2 words for the SetBunch (end time and length) and the
138     // padded words to fill 40bit word
139     added10BitWords=iResult+2;
140     assert((length+iResult)%4==0);
141     //HLTInfo("%d %x", hwaddress, hwaddress);
142     fpBuffer[fOffset++]=hwaddress&0xff;
143     fpBuffer[fOffset++]=0xa0 | ((hwaddress>>8)&0xf);
144     fpBuffer[fOffset++]=length&0xff;
145     fpBuffer[fOffset++]=0xa8 | ((length>>8)&0x3);
146     fpBuffer[fOffset++]=0xaa;
147     f10bitWords+=4;
148     fChannelStart=f10bitWords;
149     fChannels.push_back(hwaddress);
150     fPrevTimebin=AliHLTUInt16MAX;
151   }
152   if (iResult<0) return iResult;
153   return added10BitWords;
154 }
155
156 int AliHLTAltroEncoder::AddChannelSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin, AliHLTUInt16_t hwaddress)
157 {
158   // see header file for class documentation
159   int iResult=0;
160   int added10BitWords=0;
161   if (fChannel==AliHLTUInt16MAX) {
162     fChannel=hwaddress;
163   } else if (fChannel!=hwaddress) {
164     iResult=SetChannel(fChannel);
165     added10BitWords=iResult;
166     fChannel=hwaddress;
167   }
168
169   if (iResult>=0) {
170     if ((iResult=AddSignal(signal, timebin))>=0)
171       added10BitWords++;
172   }
173
174   if (iResult<0) return iResult;
175   return added10BitWords;
176 }
177
178 int AliHLTAltroEncoder::GetTotal40bitWords()
179 {
180   // see header file for class documentation
181   if (fChannelStart!=f10bitWords) {
182     HLTWarning("unterminated channel found, check calling sequence");
183   }
184   assert(fChannelStart%4==0);
185
186   return fChannelStart;
187 }
188
189 int AliHLTAltroEncoder::SetBunch()
190 {
191   // see header file for class documentation
192   int iResult=0;
193
194   // return if the bunch has already been set
195   if (fBunchLength==0) return 0;
196
197   // fill time bin and bunch length
198   if ((iResult=Add10BitValue(fPrevTimebin))>=0) {
199     iResult=Add10BitValue(fBunchLength+2);
200     fBunchLength=0;
201     iResult=2;
202   }
203   return iResult;
204 }
205
206 int AliHLTAltroEncoder::Add10BitValue(AliHLTUInt16_t value)
207 {
208   // see header file for class documentation
209   int iResult=0;
210   if (!fpBuffer) return -ENODEV;
211   if (fOffset+2>=fBufferSize-(fpRCUTrailer?fpRCUTrailer->GetSize():0)) {
212     HLTWarning("buffer too small too add 10bit word: %d of %d byte(s) already used", fOffset, fBufferSize);
213     return -ENOSPC;
214   }
215
216   int bit=(f10bitWords%4)*10;
217   int shift=bit%8;
218   unsigned short maskLow=~((0xff<<shift)>>8);
219   //unsigned short maskHigh=~((0xff<<((bit+10)%8))>>8);
220   if (bit==0) fpBuffer[fOffset]=0;
221   fpBuffer[fOffset++]|=maskLow&(value<<shift);
222   fpBuffer[fOffset]=(value&0x3ff)>>(8-shift);
223   f10bitWords++;
224   if (f10bitWords%4==0) fOffset++;
225
226   return iResult;
227 }
228
229 int AliHLTAltroEncoder::Pad40Bit()
230 {
231   // see header file for class documentation
232   int iResult=0;
233   int added10BitWords=0;
234   while (iResult>=0 && f10bitWords%4!=0) {
235     if ((iResult=Add10BitValue(0x2aa))>=0) {
236       added10BitWords++;
237     }
238   }
239   if (iResult<0) return iResult;
240   return added10BitWords;
241 }
242
243 int AliHLTAltroEncoder::SetCDH(AliHLTUInt8_t* pCDH,int size)
244 {
245   // see header file for class documentation
246   int iResult=0;
247   if (fOffset>0) {
248     HLTError("CDH can only be set prior to data");
249     iResult=-EFAULT;
250   }
251   if (size>0 && pCDH){
252     if (fpCDH == NULL){
253       fpCDH = new TArrayC(0);
254     }
255     if (fpCDH){
256       fpCDH->Set(0);
257       fpCDH->Set(size, (const char*)pCDH);
258       fOffset=size;
259     } else {
260       iResult=-ENOMEM;
261     }
262   } else {
263     iResult=-EINVAL;
264   }
265   return iResult;
266 }
267
268 int AliHLTAltroEncoder::SetRCUTrailer(AliHLTUInt8_t* pRCUTrailer,int size)
269 {
270   // see header file for class documentation
271   int iResult=0;
272   if (size>0 && pRCUTrailer){
273     if (fpRCUTrailer == NULL){
274       fpRCUTrailer = new TArrayC(0);
275     }
276     if (fpRCUTrailer){
277       fpRCUTrailer->Set(0);
278       fpRCUTrailer->Set(size, (const char*)pRCUTrailer);
279     } else {
280       iResult=-ENOMEM;
281     }
282   } else {
283     iResult=-EINVAL;
284   }
285   return iResult;
286 }
287
288 int AliHLTAltroEncoder::SetLength()
289 {
290   // see header file for class documentation
291   int iResult=0;
292   if (fChannel!=AliHLTUInt16MAX && (iResult=SetChannel(fChannel))<0) {
293     HLTError("error finalizing channel");
294     return iResult;
295   }
296
297   if (fpRCUTrailer && fOffset+fpRCUTrailer->GetSize()<fBufferSize) {
298     // copy the trailer
299     AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer+fOffset);
300     memcpy(pTgt, fpRCUTrailer->GetArray(), fpRCUTrailer->GetSize());
301     // set number of 10bit words
302     *pTgt=GetTotal40bitWords();
303     fOffset+=fpRCUTrailer->GetSize();
304   }
305   if (fpCDH && fOffset>fpCDH->GetSize()) {
306     memcpy(fpBuffer, fpCDH->GetArray(), fpCDH->GetSize());
307     AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer);
308     *pCdhSize=fOffset;//set the first word in the header to be the fOffset(number of bytes added)  
309     HLTDebug("Size set in the header: %d",*pCdhSize);
310   }
311   return fOffset;
312 }