3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
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 //**************************************************************************
19 /** @file AliHLTAltroEncoder.cxx
20 @author Matthias Richter
22 @brief Encoder class for 10/40bit Altro Data format
27 #include "AliHLTAltroEncoder.h"
30 /** ROOT macro for the implementation of ROOT specific class methods */
31 ClassImp(AliHLTAltroEncoder)
33 AliHLTAltroEncoder::AliHLTAltroEncoder()
37 fPrevTimebin(AliHLTUInt16MAX),
40 fChannel(AliHLTUInt16MAX),
44 fOrder(kUnknownOrder),
48 // see header file for class documentation
50 // refer to README to build package
52 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
55 AliHLTAltroEncoder::AliHLTAltroEncoder(AliHLTUInt8_t* pBuffer, int iSize)
59 fPrevTimebin(AliHLTUInt16MAX),
62 fChannel(AliHLTUInt16MAX),
66 fOrder(kUnknownOrder),
70 // see header file for class documentation
73 AliHLTAltroEncoder::~AliHLTAltroEncoder()
75 // see header file for class documentation
76 if (fpCDH) delete fpCDH;
79 if (fpRCUTrailer) delete fpRCUTrailer;
83 int AliHLTAltroEncoder::SetBuffer(AliHLTUInt8_t* pBuffer, int iSize)
85 // see header file for class documentation
92 int AliHLTAltroEncoder::AddSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin)
94 // see header file for class documentation
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);
101 //assert(fPrevTimebin!=timebin);
102 if (fOrder==kUnknownOrder) {
103 if (fPrevTimebin+1==timebin) fOrder=kAscending;
104 else if (fPrevTimebin==timebin+1) fOrder=kDescending;
106 if ((fOrder!=kAscending || fPrevTimebin+1!=timebin) &&
107 (fOrder!=kDescending || fPrevTimebin!=timebin+1)) {
108 // Finalize bunch and start new one
113 if (iResult>=0 && (iResult=Add10BitValue(signal))>=0) {
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;
122 int AliHLTAltroEncoder::SetChannel(AliHLTUInt16_t hwaddress)
124 // see header file for class documentation
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);
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;
148 fChannelStart=f10bitWords;
149 fChannels.push_back(hwaddress);
150 fPrevTimebin=AliHLTUInt16MAX;
152 if (iResult<0) return iResult;
153 return added10BitWords;
156 int AliHLTAltroEncoder::AddChannelSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin, AliHLTUInt16_t hwaddress)
158 // see header file for class documentation
160 int added10BitWords=0;
161 if (fChannel==AliHLTUInt16MAX) {
163 } else if (fChannel!=hwaddress) {
164 iResult=SetChannel(fChannel);
165 added10BitWords=iResult;
170 if ((iResult=AddSignal(signal, timebin))>=0)
174 if (iResult<0) return iResult;
175 return added10BitWords;
178 int AliHLTAltroEncoder::GetTotal40bitWords()
180 // see header file for class documentation
181 if (fChannelStart!=f10bitWords) {
182 HLTWarning("unterminated channel found, check calling sequence");
184 assert(fChannelStart%4==0);
186 return fChannelStart;
189 int AliHLTAltroEncoder::SetBunch()
191 // see header file for class documentation
194 // return if the bunch has already been set
195 if (fBunchLength==0) return 0;
197 // fill time bin and bunch length
198 if ((iResult=Add10BitValue(fPrevTimebin))>=0) {
199 iResult=Add10BitValue(fBunchLength+2);
206 int AliHLTAltroEncoder::Add10BitValue(AliHLTUInt16_t value)
208 // see header file for class documentation
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);
216 int bit=(f10bitWords%4)*10;
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);
224 if (f10bitWords%4==0) fOffset++;
229 int AliHLTAltroEncoder::Pad40Bit()
231 // see header file for class documentation
233 int added10BitWords=0;
234 while (iResult>=0 && f10bitWords%4!=0) {
235 if ((iResult=Add10BitValue(0x2aa))>=0) {
239 if (iResult<0) return iResult;
240 return added10BitWords;
243 int AliHLTAltroEncoder::SetCDH(AliHLTUInt8_t* pCDH,int size)
245 // see header file for class documentation
248 HLTError("CDH can only be set prior to data");
253 fpCDH = new TArrayC(0);
257 fpCDH->Set(size, (const char*)pCDH);
268 int AliHLTAltroEncoder::SetRCUTrailer(AliHLTUInt8_t* pRCUTrailer,int size)
270 // see header file for class documentation
272 if (size>0 && pRCUTrailer){
273 if (fpRCUTrailer == NULL){
274 fpRCUTrailer = new TArrayC(0);
277 fpRCUTrailer->Set(0);
278 fpRCUTrailer->Set(size, (const char*)pRCUTrailer);
288 int AliHLTAltroEncoder::SetLength()
290 // see header file for class documentation
292 if (fChannel!=AliHLTUInt16MAX && (iResult=SetChannel(fChannel))<0) {
293 HLTError("error finalizing channel");
297 if (fpRCUTrailer && fOffset+fpRCUTrailer->GetSize()<fBufferSize) {
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();
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);