]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/RCU/AliHLTAltroEncoder.cxx
added ALTRO data encoder and corresponding unit test
[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
29 /** ROOT macro for the implementation of ROOT specific class methods */
30 ClassImp(AliHLTAltroEncoder)
31
32 AliHLTAltroEncoder::AliHLTAltroEncoder()
33   :
34   fpBuffer(NULL),
35   fBufferSize(0),
36   fPrevTimebin(AliHLTUInt16MAX),
37   fBunchLength(0),
38   fChannelStart(0),
39   fChannel(AliHLTUInt16MAX),
40   fChannels(),
41   fOffset(0),
42   f10bitWords(0),
43   fOrder(kUnknownOrder)
44 {
45   // see header file for class documentation
46   // or
47   // refer to README to build package
48   // or
49   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
50 }
51
52 AliHLTAltroEncoder::AliHLTAltroEncoder(AliHLTUInt8_t* pBuffer, int iSize)
53   :
54   fpBuffer(pBuffer),
55   fBufferSize(iSize),
56   fPrevTimebin(AliHLTUInt16MAX),
57   fBunchLength(0),
58   fChannelStart(0),
59   fChannel(AliHLTUInt16MAX),
60   fChannels(),
61   fOffset(0),
62   f10bitWords(0),
63   fOrder(kUnknownOrder)
64 {
65   // see header file for class documentation
66 }
67
68 AliHLTAltroEncoder::~AliHLTAltroEncoder()
69 {
70   // see header file for class documentation
71 }
72
73 int AliHLTAltroEncoder::SetBuffer(AliHLTUInt8_t* pBuffer, int iSize)
74 {
75   // see header file for class documentation
76   fpBuffer=pBuffer;
77   fBufferSize=iSize;
78
79   return 0;
80 }
81
82 int AliHLTAltroEncoder::AddSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin)
83 {
84   // see header file for class documentation
85   int iResult=0;
86   if (fPrevTimebin!=AliHLTUInt16MAX) {
87     assert(fPrevTimebin!=timebin);
88     if (fOrder==kUnknownOrder) {
89       if (fPrevTimebin+1==timebin) fOrder=kAscending;
90       else if (fPrevTimebin==timebin+1) fOrder=kDescending;
91     }
92     if ((fOrder!=kAscending || fPrevTimebin+1!=timebin) &&
93         (fOrder!=kDescending || fPrevTimebin!=timebin+1)) {
94       // Finalize bunch and start new one
95       iResult=SetBunch();
96     }
97   }
98
99   if (iResult>=0 && (iResult=Add10BitValue(signal))>=0) {
100     fBunchLength++;
101   }
102   assert(fOffset*4<=f10bitWords*5);
103   fPrevTimebin=timebin;
104   return iResult;
105 }
106
107 int AliHLTAltroEncoder::SetChannel(AliHLTUInt16_t hwaddress)
108 {
109   // see header file for class documentation
110   int iResult=0;
111   int added10BitWords=0;
112   if (!fpBuffer) return -ENODEV;
113   if (fOffset+5>=fBufferSize) {
114     HLTWarning("buffer too small too finalize channel: %d of %d byte(s) already used", fOffset, fBufferSize);
115     return -ENOSPC;
116   }
117
118   if (iResult>=0 && 
119       (iResult=SetBunch())>=0) {
120     AliHLTUInt16_t length=f10bitWords-fChannelStart;
121     if ((iResult=Pad40Bit())<0) return iResult;
122     // 2 words for the SetBunch (end time and length) and the
123     // padded words to fill 40bit word
124     added10BitWords=iResult+2;
125     assert((length+iResult)%4==0);
126     //HLTInfo("%d %x", hwaddress, hwaddress);
127     fpBuffer[fOffset++]=hwaddress&0xff;
128     fpBuffer[fOffset++]=0xa0 | (hwaddress>>8)&0xf;
129     fpBuffer[fOffset++]=length&0xff;
130     fpBuffer[fOffset++]=0xa8 | (length>>8)&0x3;
131     fpBuffer[fOffset++]=0xaa;
132     f10bitWords+=4;
133     fChannelStart=f10bitWords;
134     fChannels.push_back(hwaddress);
135     fPrevTimebin=AliHLTUInt16MAX;
136   }
137   if (iResult<0) return iResult;
138   return added10BitWords;
139 }
140
141 int AliHLTAltroEncoder::AddChannelSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin, AliHLTUInt16_t hwaddress)
142 {
143   // see header file for class documentation
144   int iResult=0;
145   int added10BitWords=0;
146   if (fChannel==AliHLTUInt16MAX) {
147     fChannel=hwaddress;
148   } else if (fChannel!=hwaddress) {
149     iResult=SetChannel(fChannel);
150     added10BitWords=iResult;
151     fChannel=hwaddress;
152   }
153
154   if (iResult>=0) {
155     if ((iResult=AddSignal(signal, timebin))>=0)
156       added10BitWords++;
157   }
158
159   if (iResult<0) return iResult;
160   return added10BitWords;
161 }
162
163 int AliHLTAltroEncoder::GetTotal40bitWords()
164 {
165   // see header file for class documentation
166   if (fChannelStart!=f10bitWords) {
167     HLTWarning("unterminated channel found, check calling sequence");
168   }
169   assert(fChannelStart%4==0);
170
171   return fChannelStart;
172 }
173
174 int AliHLTAltroEncoder::SetBunch()
175 {
176   // see header file for class documentation
177   int iResult=0;
178
179   // return if the bunch has already been set
180   if (fBunchLength==0) return 0;
181
182   // fill time bin and bunch length
183   if ((iResult=Add10BitValue(fPrevTimebin))>=0) {
184     iResult=Add10BitValue(fBunchLength+2);
185     fBunchLength=0;
186     iResult=2;
187   }
188   return iResult;
189 }
190
191 int AliHLTAltroEncoder::Add10BitValue(AliHLTUInt16_t value)
192 {
193   // see header file for class documentation
194   int iResult=0;
195   if (!fpBuffer) return -ENODEV;
196   if (fOffset+2>=fBufferSize) {
197     HLTWarning("buffer too small too add 10bit word: %d of %d byte(s) already used", fOffset, fBufferSize);
198     return -ENOSPC;
199   }
200
201   int bit=(f10bitWords%4)*10;
202   int shift=bit%8;
203   unsigned short maskLow=~((0xff<<shift)>>8);
204   //unsigned short maskHigh=~((0xff<<((bit+10)%8))>>8);
205   fpBuffer[fOffset++]|=maskLow&(value<<shift);
206   fpBuffer[fOffset]=(value&0x3ff)>>(8-shift);
207   f10bitWords++;
208   if (f10bitWords%4==0) fOffset++;
209
210   return iResult;
211 }
212
213 int AliHLTAltroEncoder::Pad40Bit()
214 {
215   // see header file for class documentation
216   int iResult=0;
217   int added10BitWords=0;
218   while (iResult>=0 && f10bitWords%4!=0) {
219     if ((iResult=Add10BitValue(0x2aa))>=0) {
220       added10BitWords++;
221     }
222   }
223   if (iResult<0) return iResult;
224   return added10BitWords;
225 }