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),
49 fPointerToCurrentAltroHeader(NULL),
50 fPointerToCurrentBunchWord(NULL),
51 fWordLocationOfBunchCount(0),
52 fNumberOfAltroHeadersInPayload(0),
58 // see header file for class documentation
60 // refer to README to build package
62 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
65 AliHLTAltroEncoder::AliHLTAltroEncoder(AliHLTUInt8_t* pBuffer, int iSize)
69 fPrevTimebin(AliHLTUInt16MAX),
72 fChannel(AliHLTUInt16MAX),
76 fOrder(kUnknownOrder),
81 fPointerToCurrentAltroHeader(NULL),
82 fPointerToCurrentBunchWord(NULL),
83 fWordLocationOfBunchCount(0),
84 fNumberOfAltroHeadersInPayload(0),
90 // see header file for class documentation
93 AliHLTAltroEncoder::~AliHLTAltroEncoder()
95 // see header file for class documentation
96 if (fpCDH) delete fpCDH;
99 if (fpRCUTrailer) delete fpRCUTrailer;
103 int AliHLTAltroEncoder::SetBuffer(AliHLTUInt8_t* pBuffer, int iSize)
105 // see header file for class documentation
112 int AliHLTAltroEncoder::AddSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin)
114 // see header file for class documentation
116 if (fPrevTimebin!=AliHLTUInt16MAX) {
117 if (fPrevTimebin==timebin){
118 HLTWarning("timebin missmatch, two subsequent signals with identical time added, ignoring signal %d at time %d", signal, timebin);
121 //assert(fPrevTimebin!=timebin);
122 if (fOrder==kUnknownOrder) {
123 if (fPrevTimebin+1==timebin) fOrder=kAscending;
124 else if (fPrevTimebin==timebin+1) fOrder=kDescending;
126 if ((fOrder!=kAscending || fPrevTimebin+1!=timebin) &&
127 (fOrder!=kDescending || fPrevTimebin!=timebin+1)) {
128 // Finalize bunch and start new one
133 if (iResult>=0 && (iResult=Add10BitValue(signal))>=0) {
136 // HLTDebug("fOffset: %d (fOffset-32)*4: %d f10bitWords*5 %d", fOffset,(fOffset-32)*4,f10bitWords*5);
137 assert((fOffset-(fpCDH?fpCDH->GetSize():0)*4)<=f10bitWords*5);//32 is here size of CDH 8 32bit words
138 fPrevTimebin=timebin;
142 int AliHLTAltroEncoder::SetChannel(AliHLTUInt16_t hwaddress)
144 // see header file for class documentation
146 if(f32BitFormat == kTRUE){
147 if(fPointerToCurrentAltroHeader==NULL){
148 return -1; //Add correct error
152 SetBunch();//finalize the last bunch
154 f10bitWords-=2;//remove the two words that was reserved for the next bunch
156 // set all bits in the altro header to 0
157 for(Int_t i=0;i<4;i++){
158 fPointerToCurrentAltroHeader[i]=0;
160 //set the HW address to bit 0-15
161 fPointerToCurrentAltroHeader[0]=hwaddress&0xff; // copy the first 8 bits
162 fPointerToCurrentAltroHeader[1]=(hwaddress>>8)&0xff; // copy the last 8 bits
164 // set number of 10 bit words to bit 16-28
165 AliHLTUInt16_t length= f10bitWords - fChannelStart;
166 fPointerToCurrentAltroHeader[2]= length&0xff; // copy the first 8 bits
167 fPointerToCurrentAltroHeader[3]= (length>>8)&0xf; // copy the last 4 bits
170 //fill up with fillwords
171 while((f10bitWords%3) != 0){
177 // Set the error bit to 0 (bit 29) and the bit 30 and 31 to 10(mark that this is the altro header)
178 // These three bits are already zero, so in effect it is only bit 31 which is set to 1
179 fPointerToCurrentAltroHeader[3] |= 0x40; // (0x80 = 1 0 0 0 0 0 0 0)
180 fChannelStart=f10bitWords;
181 fNumberOfAltroHeadersInPayload++;
184 int added10BitWords=0;
185 if (!fpBuffer) return -ENODEV;
186 if (fOffset+5>=fBufferSize-(fpRCUTrailer?fpRCUTrailer->GetSize():0)) {
187 HLTWarning("buffer too small too finalize channel: %d of %d byte(s) already used", fOffset, fBufferSize);
192 (iResult=SetBunch())>=0) {
193 AliHLTUInt16_t length=f10bitWords-fChannelStart;
194 if ((iResult=Pad40Bit())<0) return iResult;
195 // 2 words for the SetBunch (end time and length) and the
196 // padded words to fill 40bit word
197 added10BitWords=iResult+2;
198 assert((length+iResult)%4==0);
199 //HLTInfo("%d %x", hwaddress, hwaddress);
200 fpBuffer[fOffset++]=hwaddress&0xff;
201 fpBuffer[fOffset++]=0xa0 | ((hwaddress>>8)&0xf);
202 fpBuffer[fOffset++]=length&0xff;
203 fpBuffer[fOffset++]=0xa8 | ((length>>8)&0x3);
204 fpBuffer[fOffset++]=0xaa;
206 fChannelStart=f10bitWords;
207 fChannels.push_back(hwaddress);
208 fPrevTimebin=AliHLTUInt16MAX;
210 if (iResult<0) return iResult;
212 return added10BitWords;
217 int AliHLTAltroEncoder::AddChannelSignal(AliHLTUInt16_t signal, AliHLTUInt16_t timebin, AliHLTUInt16_t hwaddress)
219 // see header file for class documentation
221 int added10BitWords=0;
222 if (fChannel==AliHLTUInt16MAX) {
224 } else if (fChannel!=hwaddress) {
225 iResult=SetChannel(fChannel);
226 added10BitWords=iResult;
231 if ((iResult=AddSignal(signal, timebin))>=0)
235 if (iResult<0) return iResult;
236 return added10BitWords;
239 int AliHLTAltroEncoder::GetTotal40bitWords()
241 // see header file for class documentation
242 if (fChannelStart!=f10bitWords) {
243 HLTWarning("unterminated channel found, check calling sequence");
245 assert(fChannelStart%4==0);
247 return fChannelStart;
250 int AliHLTAltroEncoder::SetBunch()
252 // see header file for class documentation
255 // return if the bunch has already been set
256 if (fBunchLength==0) return 0;
258 // fill time bin and bunch length
259 if(f32BitFormat == kTRUE){
260 if(fWordLocationOfBunchCount==3){
261 //means we have to put the n10bitWords into word 3
262 //of the 32 bit word and the timebin value into word 2
263 fBunchLength+=2;//takes the n10bitwords and the timebin value into account
265 //insert the first 4 bits of the 10 bit word into the end of 8bit word 3.
266 fPointerToCurrentBunchWord[2] |= (fBunchLength<<4)&0xf0;
268 //insert the last 6 bits of the 10 bit word into the beginning of 8bitword 4
269 fPointerToCurrentBunchWord[3] |= (fBunchLength>>4)&0x3f;
271 //set the timebin value
272 //insert the first 6 bits of the 10bitword into the end of 8bit word 2
273 fPointerToCurrentBunchWord[1] |= ((fPrevTimebin+fBunchLength-3)<<2)&0xfc;
274 //insert the last 4 bits of the 10bitWord into the beginning of 8bit word 3
275 fPointerToCurrentBunchWord[2] |= ((fPrevTimebin+fBunchLength-3)>>6)&0xf;
276 // set the bunch word pointer and which word the n10bitwords are in
277 fPointerToCurrentBunchWord = &fpBuffer[fOffset];
278 fWordLocationOfBunchCount = 3-f10bitWords%3;
279 if(fWordLocationOfBunchCount<3){
282 fpBuffer[fOffset+1]=0;
283 fpBuffer[fOffset+2]=0;
284 fpBuffer[fOffset+3]=0;
286 f10bitWords+=2;// makes room for the n10bitwords and the timebin
289 else if(fWordLocationOfBunchCount==2){
290 //means we have to put the n10bitWords into word 2 of the 32 bit word
291 //and the timebin value into word 1
293 fBunchLength+=2;//takes the n10bitwords and the timebin value into account
295 //insert the first 6 bits of the 10 bit word into the end of 8bit word 2.
296 fPointerToCurrentBunchWord[1] |= (fBunchLength<<2)&0xfc;
298 //insert the last 4 bits of the 10 bit word into the beginning of 8bitword 3
299 fPointerToCurrentBunchWord[2] |= (fBunchLength>>6)&0xf;
301 //set the timebin value
302 //insert the first 8 bits of the 10bitword into the end of 8bit word 1
303 fPointerToCurrentBunchWord[0] |= (fPrevTimebin+fBunchLength-3)&0xff;
304 //insert the last 2 bits of the 10bitWord into the beginning of 8bit word 2
305 fPointerToCurrentBunchWord[1] |= ((fPrevTimebin+fBunchLength-3)>>8)&0x3;
306 // set the bunch word pointer and which word the n10bitwords are in
307 fPointerToCurrentBunchWord = &fpBuffer[fOffset];
308 fWordLocationOfBunchCount = 3-f10bitWords%3;
309 if(fWordLocationOfBunchCount<3){
312 fpBuffer[fOffset+1]=0;
313 fpBuffer[fOffset+2]=0;
314 fpBuffer[fOffset+3]=0;
316 f10bitWords+=2;// makes room for the n10bitwords and the timebin
319 else if(fWordLocationOfBunchCount==1){
320 //means we have to put the n10bitWords into word 1 of the 32 bit word
321 //and the timebin value into word 3 of the next 32 bit word
323 fBunchLength+=2;//takes the n10bitwords and the timebin value into account
325 //insert the first 8 bits of the 10 bit word into the beginning of 8bit word 1.
326 fPointerToCurrentBunchWord[0] |= fBunchLength&0xff;
328 //insert the last 2 bits of the 10 bit word into the beginning of 8bitword 2
329 fPointerToCurrentBunchWord[1] |= (fBunchLength>>8)&0x3;
331 //set the timebin value
332 //insert the first 4 bits of the 10bitword into the end of 8bit word 7
333 fPointerToCurrentBunchWord[6] |= ((fPrevTimebin+fBunchLength-3)<<4)&0xf0;
334 //insert the last 6 bits of the 10bitWord into the beginning of 8bit word 8
335 fPointerToCurrentBunchWord[7] |= ((fPrevTimebin+fBunchLength-3)>>4)&0x3f;
336 // set the bunch word pointer and which word the n10bitwords are in
337 fPointerToCurrentBunchWord = &fpBuffer[fOffset];
338 fWordLocationOfBunchCount = 3-f10bitWords%3;
339 if(fWordLocationOfBunchCount<3){
342 fpBuffer[fOffset+1]=0;
343 fpBuffer[fOffset+2]=0;
344 fpBuffer[fOffset+3]=0;
346 f10bitWords+=2;// makes room for the n10bitwords and the timebin
352 if ((iResult=Add10BitValue(fPrevTimebin))>=0) {
353 iResult=Add10BitValue(fBunchLength+2);
358 // fPrevTimebin=AliHLTUInt16MAX;// resets the timebin number
362 int AliHLTAltroEncoder::Add10BitValue(AliHLTUInt16_t value)
364 // see header file for class documentation
366 if (!fpBuffer) return -ENODEV;
367 if (fOffset+2>=fBufferSize-(fpRCUTrailer?fpRCUTrailer->GetSize():0)) {
368 HLTWarning("buffer too small too add 10bit word: %d of %d byte(s) already used", fOffset, fBufferSize);
373 HLTError("10 bit value cannot be larger than 1023, something is wrong.");
374 return -1; //TODO find better error
377 if(f32BitFormat == kFALSE){
378 int bit=(f10bitWords%4)*10;
380 unsigned short maskLow=~((0xff<<shift)>>8);
381 //unsigned short maskHigh=~((0xff<<((bit+10)%8))>>8);
382 if (bit==0) fpBuffer[fOffset]=0;
383 fpBuffer[fOffset++]|=maskLow&(value<<shift);
384 fpBuffer[fOffset]=(value&0x3ff)>>(8-shift);
386 if (f10bitWords%4==0) fOffset++;
390 if(f10bitWords == fChannelStart){ //means that there is a new channel(or the first)
391 fPointerToCurrentAltroHeader = &fpBuffer[fOffset]; // set a pointer to the beginning of the altro header
393 fOffset+=4; //Makes space for the altro header in front of the altrodata (1 32 bit word)
396 fpBuffer[fOffset+1]=0;
397 fpBuffer[fOffset+2]=0;
398 fpBuffer[fOffset+3]=0;
400 //set the pointer to the bunch currently being filled
401 //it is always in the 3d 10 bit word when a new channel has started.
402 fPointerToCurrentBunchWord = &fpBuffer[fOffset];
403 fWordLocationOfBunchCount=3;
404 //make room for the n10BitWords, and the timebin value
409 int bit=20-(f10bitWords%3)*10;
411 if(bit ==20){//means we should fill the third word
412 //set bits 25-32 to 0, this also takes care of setting the marker (00) at the end.
413 fpBuffer[fOffset+3] = 0;
414 //copy the last 6 bits of the signal into the first 6 bits of 8BitWord 3
415 fpBuffer[fOffset+3] |= (value>>4)&0x3f;
416 //set bits 17-24 to 0
417 fpBuffer[fOffset+2]=0;
418 //copy the first 4 bits of the signal into the last 4 bits of 8BitWord 2
419 fpBuffer[fOffset+2] |= (value<<4)&0xf0;
422 else if(bit == 10){//means we should fill the middle (2nd) word
423 //copy the last 4 bits of the signal into the first 4 bits of 8BitWord 2
424 fpBuffer[fOffset+2] |= (value>>6)&0xf;
426 fpBuffer[fOffset+1]=0;
427 //copy the first 6 bits of the signal into the last 6 bits of 8BitWord 1
428 fpBuffer[fOffset+1] |= (value<<2)&0xfc;
434 //copy the last 2 bits of the signal into the first 2 bits of 8BitWord 1
435 fpBuffer[fOffset+1] |= (value>>8)&0x3;
436 //copy the first 8 bits of the signal into the first 8 bits of 8BitWord 0
437 fpBuffer[fOffset] |= value&0xff;
439 if(fFillWord == kFALSE){
440 fOffset += 4; // only increase when the last word is added
442 fpBuffer[fOffset+1]=0;
443 fpBuffer[fOffset+2]=0;
444 fpBuffer[fOffset+3]=0;
451 int AliHLTAltroEncoder::Pad40Bit()
453 // see header file for class documentation
455 int added10BitWords=0;
456 while (iResult>=0 && f10bitWords%4!=0) {
457 if ((iResult=Add10BitValue(0x2aa))>=0) {
461 if (iResult<0) return iResult;
462 return added10BitWords;
465 int AliHLTAltroEncoder::SetCDH(AliHLTUInt8_t* pCDH,int size)
467 // see header file for class documentation
470 HLTError("CDH can only be set prior to data");
475 fpCDH = new TArrayC(0);
479 fpCDH->Set(size, (const char*)pCDH);
491 int AliHLTAltroEncoder::SetRCUTrailer(AliHLTUInt8_t* pRCUTrailer,int size)
493 // see header file for class documentation
495 if (size>0 && pRCUTrailer){
496 if (fpRCUTrailer == NULL){
497 fpRCUTrailer = new TArrayC(0);
500 fpRCUTrailer->Set(0);
501 fpRCUTrailer->Set(size, (const char*)pRCUTrailer);
511 int AliHLTAltroEncoder::SetLength()
513 // see header file for class documentation
515 if (fChannel!=AliHLTUInt16MAX && (iResult=SetChannel(fChannel))<0) {
516 HLTError("error finalizing channel");
520 if (fpRCUTrailer && fOffset+fpRCUTrailer->GetSize()<fBufferSize) {
522 AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer+fOffset);
523 memcpy(pTgt, fpRCUTrailer->GetArray(), fpRCUTrailer->GetSize());
524 // set number of 10bit words
525 *pTgt=GetTotal40bitWords();
526 fOffset+=fpRCUTrailer->GetSize();
528 if (fpCDH && fOffset>fpCDH->GetSize()) {
529 memcpy(fpBuffer, fpCDH->GetArray(), fpCDH->GetSize());
530 AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer);
531 *pCdhSize=fOffset;//set the first word in the header to be the fOffset(number of bytes added)
532 HLTDebug("Size set in the header: %d",*pCdhSize);
534 if(f32BitFormat == kTRUE){
535 //set all bits to 1 in the first 32 bit of the cdh
551 void AliHLTAltroEncoder::Revert40BitWords(Int_t /*CDHSize*/, Int_t /*trailerSize*/)
553 // see headerfile for class documentation
554 HLTWarning("Revert40BitWords function no longer has any function, please remove this function call from your analysis");
557 void AliHLTAltroEncoder::PrintDebug()
559 int n32bitWords = fOffset/4;
560 int word8Counter = 0;
561 Bool_t isAnAltroHeader=kFALSE;
562 Bool_t isData=kFALSE;
564 Bool_t isTrailer=kFALSE;
566 for(Int_t n32bit=0;n32bit<n32bitWords;n32bit++){
567 isAnAltroHeader=kFALSE;
571 for(Int_t w=0;w<4;w++){
572 Int_t wordPosition = 4-word8Counter%4;
573 AliHLTUInt8_t word = fpBuffer[n32bit*4+wordPosition-1];
575 if(n32bit < fCDHSize/4){
578 else if(wordPosition==4 && (word & 0x80)==0 && (word & 0x40)!=0){//means we have a altroheader
579 isAnAltroHeader=kTRUE;
581 else if(wordPosition==4 && (word & 0x80)==0 && (word & 0x40)==0){//means we have data
584 else if(wordPosition==4 && (word & 0x80) !=0 && (word & 0x40)==0){//means we have trailer
587 else if(wordPosition==4 && (word & 0x80) !=0 && (word & 0x40) !=0){//means we have trailer (last trailer word)
590 for(int n=7; n>=0; n--){
591 if(isAnAltroHeader == kTRUE){
592 if((wordPosition == 4 && n==5) || (wordPosition == 4 && n==4) /*|| wordPosition == 4 && n==0*/){
595 if(wordPosition == 2 && n==7){
599 else if(isData == kTRUE){
600 if(wordPosition == 4 && n==5){
603 if(wordPosition == 3 && n==3){
606 if(wordPosition == 2 && n==1){
610 else if(isTrailer == kTRUE){
611 if(wordPosition == 4 && n==5){
615 //print the byte values
616 if((((word>>n)<<7)&0x80) != 0){
626 printf("\t CDH %d\n",n32bit);
628 else if(isAnAltroHeader == kTRUE){
629 printf("\t AltroHeader \n");
631 else if(isData == kTRUE){
632 printf("\t Data \n");
634 else if(isTrailer == kTRUE){
635 printf("\t Trailer \n");