#include <cassert>
#include <cerrno>
#include "AliHLTAltroEncoder.h"
+#include "TArrayC.h"
/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTAltroEncoder)
fChannels(),
fOffset(0),
f10bitWords(0),
- fOrder(kUnknownOrder)
+ fOrder(kUnknownOrder),
+ fpCDH(NULL),
+ fpRCUTrailer(NULL)
{
// see header file for class documentation
// or
fChannels(),
fOffset(0),
f10bitWords(0),
- fOrder(kUnknownOrder)
+ fOrder(kUnknownOrder),
+ fpCDH(NULL),
+ fpRCUTrailer(NULL)
{
// see header file for class documentation
}
AliHLTAltroEncoder::~AliHLTAltroEncoder()
{
// see header file for class documentation
+ if (fpCDH) delete fpCDH;
+ fpCDH=NULL;
+
+ if (fpRCUTrailer) delete fpRCUTrailer;
+ fpRCUTrailer=NULL;
}
int AliHLTAltroEncoder::SetBuffer(AliHLTUInt8_t* pBuffer, int iSize)
if (iResult>=0 && (iResult=Add10BitValue(signal))>=0) {
fBunchLength++;
}
- assert(fOffset*4<=f10bitWords*5);
+ // HLTDebug("fOffset: %d (fOffset-32)*4: %d f10bitWords*5 %d", fOffset,(fOffset-32)*4,f10bitWords*5);
+ assert((fOffset-(fpCDH?fpCDH->GetSize():0)*4)<=f10bitWords*5);//32 is here size of CDH 8 32bit words
fPrevTimebin=timebin;
return iResult;
}
int iResult=0;
int added10BitWords=0;
if (!fpBuffer) return -ENODEV;
- if (fOffset+5>=fBufferSize) {
+ if (fOffset+5>=fBufferSize-(fpRCUTrailer?fpRCUTrailer->GetSize():0)) {
HLTWarning("buffer too small too finalize channel: %d of %d byte(s) already used", fOffset, fBufferSize);
return -ENOSPC;
}
// see header file for class documentation
int iResult=0;
if (!fpBuffer) return -ENODEV;
- if (fOffset+2>=fBufferSize) {
+ if (fOffset+2>=fBufferSize-(fpRCUTrailer?fpRCUTrailer->GetSize():0)) {
HLTWarning("buffer too small too add 10bit word: %d of %d byte(s) already used", fOffset, fBufferSize);
return -ENOSPC;
}
if (iResult<0) return iResult;
return added10BitWords;
}
+
+int AliHLTAltroEncoder::SetCDH(AliHLTUInt8_t* pCDH,int size)
+{
+ // see header file for class documentation
+ int iResult=0;
+ if (fOffset>0) {
+ HLTError("CDH can only be set prior to data");
+ iResult=-EFAULT;
+ }
+ if (size>0 && pCDH){
+ if (fpCDH == NULL){
+ fpCDH = new TArrayC(0);
+ }
+ if (fpCDH){
+ fpCDH->Set(0);
+ fpCDH->Set(size, (const char*)pCDH);
+ fOffset=size;
+ } else {
+ iResult=-ENOMEM;
+ }
+ } else {
+ iResult=-EINVAL;
+ }
+ return iResult;
+}
+
+int AliHLTAltroEncoder::SetRCUTrailer(AliHLTUInt8_t* pRCUTrailer,int size)
+{
+ // see header file for class documentation
+ int iResult=0;
+ if (size>0 && pRCUTrailer){
+ if (fpRCUTrailer == NULL){
+ fpRCUTrailer = new TArrayC(0);
+ }
+ if (fpRCUTrailer){
+ fpRCUTrailer->Set(0);
+ fpRCUTrailer->Set(size, (const char*)pRCUTrailer);
+ } else {
+ iResult=-ENOMEM;
+ }
+ } else {
+ iResult=-EINVAL;
+ }
+ return iResult;
+}
+
+int AliHLTAltroEncoder::SetLength()
+{
+ // see header file for class documentation
+ int iResult=0;
+ if (fChannel!=AliHLTUInt16MAX && (iResult=SetChannel(fChannel))<0) {
+ HLTError("error finalizing channel");
+ return iResult;
+ }
+
+ if (fpRCUTrailer && fOffset+fpRCUTrailer->GetSize()<fBufferSize) {
+ // copy the trailer
+ AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer+fOffset);
+ memcpy(pTgt, fpRCUTrailer->GetArray(), fpRCUTrailer->GetSize());
+ // set number of 10bit words
+ *pTgt=GetTotal40bitWords();
+ fOffset+=fpRCUTrailer->GetSize();
+ }
+ if (fpCDH && fOffset>fpCDH->GetSize()) {
+ memcpy(fpBuffer, fpCDH->GetArray(), fpCDH->GetSize());
+ AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer);
+ *pCdhSize=fOffset;//set the first word in the header to be the fOffset(number of bytes added)
+ HLTDebug("Size set in the header: %d",*pCdhSize);
+ }
+ return fOffset;
+}
#define AliHLTUInt16MAX 0xffff
+class TArrayC;
+
/**
* @class AliHLTAltroEncoder
* Encoder of the RCU/Altro data format.
* encoder.SetChannel(channelAddress);
* }
* </pre>
- *
+ *
+ * By default, the encoder provides only the ALTRO data, but not the common
+ * data header (in AliRoot language AliRawDataHeader) nor the RCU trailer.
+ * The CDH is 32 bytes long, the first 4 byte contain the data length excluding
+ * the CDH itsself. The CDH can be set by SetCDH(AliHLTUInt8_t*, int).
+ *
+ * The RCU trailer has varying formats, actually the last 4 byte are supposed
+ * to contain the length of the trailer itsself. The first 4 byte contain the
+ * number of 40bit ALTRO words. Currently, the RCU firmware adds only one 4 byte
+ * word, the number of 40bit wirds. The trailer can be set using
+ * SetRCUTrailer(AliHLTUInt8_t*, int);
+ *
+ * When using CDH and Trailer the Finalize() function must be called at the end
+ * in order to copy the trailer and update the size members correctly.
+ *
* @ingroup alihlt_rcu
*/
class AliHLTAltroEncoder : AliHLTLogging {
*/
int GetTotal40bitWords();
+ /**
+ * Sets the common data header at the beginning of the buffer
+ */
+ int SetCDH(AliHLTUInt8_t* pCDH, int size);
+
+ /**
+ * Sets the RCU trailer at the end of the buffer
+ */
+ int SetRCUTrailer(AliHLTUInt8_t* pTrailer, int size);
+
+ /**
+ * Finalize the encoded data.
+ * Finish the last channel if open, copy RCU trailer if available and update
+ * ALTRO word count in the trailer. Update the data length in the CDH if
+ * available.
+ */
+ int SetLength();
+
+ int GetOffset(){return fOffset;}
+
enum {
kUnknownOrder = 0,
kAscending,
/// time bin order
int fOrder; //!transient
+
+ /// common data header
+ TArrayC* fpCDH; //!transient
+
+ /// RCU trailer
+ TArrayC* fpRCUTrailer; //!transient
- ClassDef(AliHLTAltroEncoder, 0);
+ ClassDef(AliHLTAltroEncoder, 1);
};
#endif
#endif
AliHLTAltroEncoder encoder;
- Char_t* pTgt=encData.GetArray();
- pTgt+=sizeofAliRawDataHeader;
- encoder.SetBuffer((AliHLTUInt8_t*)pTgt, maxAltroDataSize);
+ encoder.SetBuffer((AliHLTUInt8_t*)encData.GetArray(), encData.GetSize());
+
+ // set the common data header
+ TArrayC dummyCdh(sizeofAliRawDataHeader);
+ encoder.SetCDH((AliHLTUInt8_t*)dummyCdh.GetArray(), dummyCdh.GetSize());
+
+ // set a trailer like in the real data format of the v1 RCU format (1 trailer word)
+ Int_t trailer=0;
+ encoder.SetRCUTrailer((AliHLTUInt8_t*)&trailer, 4);
if (bVerbose) cout << "number of channels: " << nofChannels << endl;
int channelAddress=-1;
if (bVerbose) cout << " channel " << channelAddress << ": number of bunches " << totalBunches << endl;
}
- if (bUseAddChannelSignal && lastChannel>=0) encoder.SetChannel(lastChannel);
+ int dataSize=encoder.SetLength();
+ if (dataSize<0) {
+ cerr << "error finalizing encoded buffer" << endl;
+ return -1;
+ }
int nof40bitWords=encoder.GetTotal40bitWords();
- pTgt+=nof40bitWords*5/4;
- *((Int_t*)pTgt)=nof40bitWords;
- int encDataSize=sizeofAliRawDataHeader+nof40bitWords*5/4+sizeof(Int_t);
- encData.Set(encDataSize);
+ encData.Set(dataSize);
if (bVerbose) cout << "simulated data array:" << simData.GetSize() << " , ALTRO block length: " << nof40bitWords << " ALTRO words -> encoded data: " << encData.GetSize() << endl;
return 0;
}
-int main(int argc, const char** argv)
+int main(int /*argc*/, const char** /*argv*/)
{
// CompareDumpFiles();
// return 0;