]>
Commit | Line | Data |
---|---|---|
3ea47630 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
16 | /* $Id$ */ | |
17 | ||
18 | // Interface to the Altro format | |
19 | // to read and write digits | |
20 | // To be used in Alice Data Challenges | |
21 | // and in the compression of the RAW data | |
3ea47630 | 22 | |
23 | #include "AliAltroBuffer.h" | |
5802cf2d | 24 | #include "AliAltroMapping.h" |
74b154bd | 25 | #include "AliRawDataHeaderSim.h" |
5802cf2d | 26 | #include "AliLog.h" |
4c846604 | 27 | #include "AliFstream.h" |
28 | //#include <stdlib.h> | |
3ea47630 | 29 | |
30 | ||
31 | ClassImp(AliAltroBuffer) | |
32 | ||
3ea47630 | 33 | //_____________________________________________________________________________ |
573322da | 34 | AliAltroBuffer::AliAltroBuffer(const char* fileName, AliAltroMapping *mapping): |
3ea47630 | 35 | fShift(0), |
36 | fCurrentCell(0), | |
5e6235b5 | 37 | fFreeCellBuffer(16), |
3ea47630 | 38 | fVerbose(0), |
39 | fFile(NULL), | |
3ea47630 | 40 | fDataHeaderPos(0), |
5802cf2d | 41 | fMapping(mapping) |
3ea47630 | 42 | { |
3ea47630 | 43 | //the buffer is cleaned |
44 | for (Int_t i = 0; i < 5; i++) fBuffer[i] = 0; | |
45 | ||
4c846604 | 46 | //open the output file |
47 | fFile = new AliFstream(fileName); | |
5802cf2d | 48 | |
3ea47630 | 49 | } |
50 | ||
51 | //_____________________________________________________________________________ | |
52 | AliAltroBuffer::~AliAltroBuffer() | |
53 | { | |
54 | // destructor | |
55 | ||
4c846604 | 56 | //Flush out the Buffer content at the end only if Buffer wasn't completely filled |
57 | Flush(); | |
58 | if (fVerbose) Info("~AliAltroBuffer", "File Created"); | |
59 | ||
3ea47630 | 60 | delete fFile; |
5802cf2d | 61 | |
3ea47630 | 62 | } |
63 | ||
64 | //_____________________________________________________________________________ | |
65 | AliAltroBuffer::AliAltroBuffer(const AliAltroBuffer& source): | |
66 | TObject(source), | |
67 | fShift(source.fShift), | |
68 | fCurrentCell(source.fCurrentCell), | |
69 | fFreeCellBuffer(source.fFreeCellBuffer), | |
3ea47630 | 70 | fVerbose(source.fVerbose), |
71 | fFile(NULL), | |
3ea47630 | 72 | fDataHeaderPos(source.fDataHeaderPos), |
5802cf2d | 73 | fMapping(source.fMapping) |
3ea47630 | 74 | { |
75 | // Copy Constructor | |
76 | ||
77 | Fatal("AliAltroBuffer", "copy constructor not implemented"); | |
78 | } | |
79 | ||
80 | //_____________________________________________________________________________ | |
81 | AliAltroBuffer& AliAltroBuffer::operator = (const AliAltroBuffer& /*source*/) | |
82 | { | |
83 | //Assigment operator | |
84 | ||
85 | Fatal("operator =", "assignment operator not implemented"); | |
86 | return *this; | |
87 | } | |
88 | ||
3ea47630 | 89 | //_____________________________________________________________________________ |
90 | void AliAltroBuffer::Flush() | |
91 | { | |
92 | // Flushes the Buffer content | |
93 | if (fFreeCellBuffer != 16) { | |
94 | Int_t temp = fFreeCellBuffer; | |
95 | for (Int_t i = 0; i < temp; i++){ | |
96 | FillBuffer(0x2AA); | |
97 | }//end for | |
98 | }//end if | |
99 | } | |
100 | ||
101 | //_____________________________________________________________________________ | |
102 | void AliAltroBuffer::FillBuffer(Int_t val) | |
103 | { | |
104 | //Fills the Buffer with 16 ten bits words and write into a file | |
105 | ||
23b19451 | 106 | if ((val > 0x3FF) || (val < 0)) { |
107 | Error("FillBuffer", "Value out of range (10 bits): %d", val); | |
108 | val = 0x3FF; | |
109 | } | |
3ea47630 | 110 | fFreeCellBuffer--; |
5e6235b5 | 111 | |
112 | fBuffer[fCurrentCell] |= (val << fShift); | |
113 | fShift += 10; | |
114 | ||
115 | if (fShift > 32) { | |
3ea47630 | 116 | fCurrentCell++; |
5e6235b5 | 117 | fShift -= 32; |
118 | fBuffer[fCurrentCell] |= (val >> (10 - fShift)); | |
3ea47630 | 119 | } |
5e6235b5 | 120 | |
121 | if (fShift == 32) { | |
3ea47630 | 122 | //Buffer is written into a file |
4c846604 | 123 | fFile->WriteBuffer((char*)fBuffer, sizeof(UInt_t)*5); |
3ea47630 | 124 | //Buffer is empty |
125 | for (Int_t j = 0; j < 5; j++) fBuffer[j] = 0; | |
5e6235b5 | 126 | fShift = 0; |
3ea47630 | 127 | fCurrentCell = 0; |
128 | fFreeCellBuffer = 16; | |
129 | } | |
130 | } | |
131 | ||
3ea47630 | 132 | //_____________________________________________________________________________ |
133 | void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Int_t padNumber, | |
134 | Int_t rowNumber, Int_t secNumber) | |
135 | { | |
136 | //Writes a trailer of 40 bits | |
137 | ||
5802cf2d | 138 | if (!fMapping) { |
94b2b783 | 139 | AliFatal("No ALTRO mapping information is loaded!"); |
5802cf2d | 140 | } |
141 | ||
cc934096 | 142 | Short_t hwAddress = fMapping->GetHWAddress(rowNumber,padNumber,secNumber); |
143 | if (hwAddress == -1) | |
20daa34d | 144 | AliFatal(Form("No hardware (ALTRO) adress found for these pad-row (%d) and pad (%d) indeces !",rowNumber,padNumber)); |
cc934096 | 145 | WriteTrailer(wordsNumber,hwAddress); |
20daa34d | 146 | } |
147 | ||
148 | //_____________________________________________________________________________ | |
cc934096 | 149 | void AliAltroBuffer::WriteTrailer(Int_t wordsNumber, Short_t hwAddress) |
20daa34d | 150 | { |
151 | //Writes a trailer of 40 bits using | |
152 | //a given hardware adress | |
3ea47630 | 153 | Int_t num = fFreeCellBuffer % 4; |
154 | for(Int_t i = 0; i < num; i++) { | |
155 | FillBuffer(0x2AA); | |
156 | }//end for | |
5802cf2d | 157 | Int_t temp; |
cc934096 | 158 | temp = hwAddress & 0x3FF; |
5802cf2d | 159 | FillBuffer(temp); |
cc934096 | 160 | |
5802cf2d | 161 | temp = (wordsNumber << 6) & 0x3FF; |
162 | temp |= (0xA << 2); | |
cc934096 | 163 | temp |= ((hwAddress >> 10) & 0x3); |
164 | FillBuffer(temp); | |
5802cf2d | 165 | |
cc934096 | 166 | temp = 0xA << 6; |
167 | temp |= ((wordsNumber & 0x3FF) >> 4); | |
5802cf2d | 168 | FillBuffer(temp); |
cc934096 | 169 | |
170 | temp = 0x2AA; | |
5802cf2d | 171 | FillBuffer(temp); |
3ea47630 | 172 | } |
173 | ||
3ea47630 | 174 | //_____________________________________________________________________________ |
175 | void AliAltroBuffer::WriteChannel(Int_t padNumber, Int_t rowNumber, | |
176 | Int_t secNumber, | |
177 | Int_t nTimeBins, const Int_t* adcValues, | |
178 | Int_t threshold) | |
179 | { | |
cc934096 | 180 | //Write all ADC values and the trailer of a channel |
181 | Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold); | |
182 | // write the trailer | |
bd2e5cec | 183 | if (nWords) WriteTrailer(nWords, padNumber, rowNumber, secNumber); |
cc934096 | 184 | } |
185 | ||
186 | //_____________________________________________________________________________ | |
187 | void AliAltroBuffer::WriteChannel(Short_t hwAddress, | |
188 | Int_t nTimeBins, const Int_t* adcValues, | |
189 | Int_t threshold) | |
190 | { | |
191 | //Write all ADC values and the trailer of a channel | |
192 | Int_t nWords = WriteBunch(nTimeBins,adcValues,threshold); | |
193 | // write the trailer | |
bd2e5cec | 194 | if (nWords) WriteTrailer(nWords, hwAddress); |
cc934096 | 195 | } |
196 | ||
197 | //_____________________________________________________________________________ | |
198 | Int_t AliAltroBuffer::WriteBunch(Int_t nTimeBins, const Int_t* adcValues, | |
199 | Int_t threshold) | |
200 | { | |
201 | //Write all ADC values | |
202 | //Return number of words written | |
3ea47630 | 203 | |
204 | Int_t nWords = 0; | |
205 | Int_t timeBin = -1; | |
206 | Int_t bunchLength = 0; | |
207 | ||
208 | // loop over time bins | |
209 | for (Int_t iTime = 0; iTime < nTimeBins; iTime++) { | |
210 | if (adcValues[iTime] >= threshold) { // ADC value above threshold | |
211 | FillBuffer(adcValues[iTime]); | |
212 | nWords++; | |
213 | timeBin = iTime; | |
214 | bunchLength++; | |
215 | ||
216 | } else if (timeBin >= 0) { // end of bunch | |
217 | FillBuffer(timeBin); | |
218 | FillBuffer(bunchLength + 2); | |
219 | nWords += 2; | |
220 | timeBin = -1; | |
221 | bunchLength = 0; | |
222 | } | |
223 | } | |
224 | ||
225 | if (timeBin >= 0) { // end of bunch | |
226 | FillBuffer(timeBin); | |
227 | FillBuffer(bunchLength + 2); | |
228 | nWords += 2; | |
229 | } | |
230 | ||
cc934096 | 231 | return nWords; |
3ea47630 | 232 | } |
233 | ||
3ea47630 | 234 | //_____________________________________________________________________________ |
b73dbf18 | 235 | void AliAltroBuffer::WriteDataHeader(Bool_t dummy, Bool_t /*compressed*/) |
3ea47630 | 236 | { |
237 | //Write a (dummy or real) DDL data header, | |
b73dbf18 | 238 | //set the attributes according to the RCU version |
3ea47630 | 239 | |
74b154bd | 240 | AliRawDataHeaderSim header; |
3ea47630 | 241 | if (dummy) { |
242 | //if size=0 it means that this data header is a dummy data header | |
4c846604 | 243 | fDataHeaderPos = fFile->Tellp(); |
244 | fFile->WriteBuffer((char*)(&header), sizeof(header)); | |
3ea47630 | 245 | } else { |
b73dbf18 | 246 | UChar_t rcuVer = WriteRCUTrailer(0); |
4c846604 | 247 | UInt_t currentFilePos = fFile->Tellp(); |
248 | fFile->Seekp(fDataHeaderPos); | |
2c7410c2 | 249 | header.fSize = 0xFFFFFFFF; // RCU can't write raw-data size so we always get an 'invalid' size field |
b73dbf18 | 250 | header.fAttributesSubDetectors |= (rcuVer << 24); |
4c846604 | 251 | fFile->WriteBuffer((char*)(&header), sizeof(header)); |
252 | fFile->Seekp(currentFilePos); | |
3ea47630 | 253 | } |
254 | } | |
5e6235b5 | 255 | |
256 | //_____________________________________________________________________________ | |
b73dbf18 | 257 | UChar_t AliAltroBuffer::WriteRCUTrailer(Int_t rcuId) |
5e6235b5 | 258 | { |
259 | // Writes the RCU trailer | |
260 | // rcuId the is serial number of the corresponding | |
261 | // RCU. The basic format of the trailer can be | |
262 | // found in the RCU manual. | |
263 | // This method should be called at the end of | |
264 | // raw data writing. | |
265 | ||
266 | UInt_t currentFilePos = fFile->Tellp(); | |
267 | UInt_t size = currentFilePos-fDataHeaderPos; | |
480f0332 | 268 | size -= sizeof(AliRawDataHeaderV3); |
5e6235b5 | 269 | |
270 | if ((size % 5) != 0) { | |
271 | AliFatal(Form("The current raw data payload is not a mutiple of 5 (%d) ! Can not write the RCU trailer !",size)); | |
b73dbf18 | 272 | return 0; |
5e6235b5 | 273 | } |
274 | ||
275 | // Now put the size in unit of number of 40bit words | |
276 | size /= 5; | |
277 | fFile->WriteBuffer((char *)(&size),sizeof(UInt_t)); | |
278 | ||
279 | // Now several not yet full defined fields | |
280 | // In principle they are supposed to contain | |
281 | // information about the sampling frequency, | |
282 | // L1 phase, list of 'dead' FECs, etc. | |
283 | // UInt_t buffer[n]; | |
284 | // fFile->WriteBuffer((char *)(buffer),sizeof(UInt_t)*n); | |
285 | ||
286 | // Now the RCU identifier and size of the trailer | |
287 | // FOr the moment the triler size is 2 32-bit words | |
9a090ccd | 288 | UInt_t buffer = (2 & 0x7F); |
289 | buffer |= ((rcuId & 0x1FF) << 7); | |
aea0bb6b | 290 | buffer |= 0xAAAAU << 16; |
5e6235b5 | 291 | fFile->WriteBuffer((char *)(&buffer),sizeof(UInt_t)); |
292 | ||
b73dbf18 | 293 | return 0; |
5e6235b5 | 294 | } |