Added documentation of each file.
[u/mrichter/AliRoot.git] / FMD / AliFMDAltroIO.cxx
CommitLineData
1e8f773e 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 **************************************************************************/
1e8f773e 15/* $Id$ */
c2fc1258 16/** @file AliFMDAltroIO.cxx
17 @author Christian Holm Christensen <cholm@nbi.dk>
18 @date Sun Mar 26 18:27:06 2006
19 @brief Altro Input/Output
20*/
1e8f773e 21//____________________________________________________________________
22//
23// Mapping of ALTRO hardware channel to detector coordinates
24//
25#include "AliFMDAltroIO.h"
26#include <AliRawDataHeader.h>
27#include <AliRawReader.h>
28#include "AliLog.h"
29#include <iostream>
30#include <iomanip>
31#define PRETTY_HEX(N,X) \
32 " 0x" << std::setfill('0') << std::setw(N) << std::hex << X \
33 << std::setfill(' ') << std::dec
34
35//====================================================================
36ClassImp(AliFMDAltroIO)
37#if 0
38 ; // This is here to keep Emacs for indenting the next line
39#endif
40
41//____________________________________________________________________
42const AliFMDAltroIO::W40_t AliFMDAltroIO::fgkTrailerMask =
43((AliFMDAltroIO::W40_t(0x2aaa) << 26) + (AliFMDAltroIO::W40_t(0xa) << 12));
44
45//____________________________________________________________________
46AliFMDAltroIO::AliFMDAltroIO()
47 : fBuffer(0), fIBuffer(0)
48{}
49
50//____________________________________________________________________
51const char*
52AliFMDAltroIO::ErrorString(Int_t err) const
53{
54 switch (err) {
55 case kNoError: return "No error"; break;
56 case kBadFile: return "Bad state after open/close file"; break;
57 case kBadBits: return "Bad bit offset specified"; break;
58 case kBadRead: return "Bad state after reading from file"; break;
59 case kBadWrite: return "Bad state after writing to file"; break;
60 case kBadSeek: return "Bad state after seeking in file"; break;
61 case kBadTell: return "Could not tell position in file"; break;
62 case kBadTrailer: return "Bad trailer 40 bit word in file"; break;
63 case kBadFill: return "Bad fill word in file"; break;
64 }
65 return "Unknown";
66}
67
68
69//____________________________________________________________________
70AliFMDAltroIO::W40_t
71AliFMDAltroIO::ConcatW40(size_t n, const W10_t& w) const
72{
73 if (n > 3) return -kBadBits;
74 return W40_t(w & 0x3ff) << (10 * n);
75}
76
77//____________________________________________________________________
78AliFMDAltroIO::W10_t
79AliFMDAltroIO::ExtractW10(size_t n, const W40_t w) const
80{
81 if (n > 3) return -kBadBits;
82 return (w >> (10 * n)) & 0x3ff;
83}
84
85//====================================================================
86ClassImp(AliFMDAltroReader)
87#if 0
88 ; // This is here to keep Emacs for indenting the next line
89#endif
90
91//____________________________________________________________________
92AliFMDAltroReader::AliFMDAltroReader(std::istream& stream)
93 : fInput(stream)
94 // : fBuffer(buffer), fCurrent(n / 10 * sizeof(char))
95{
96 // fInput.open(filename);
97 if (!fInput) throw -kBadFile;
98 fBegin = fInput.tellg();
99 if (fInput.bad()) throw -kBadTell;
100 fInput.seekg(0, std::ios_base::end);
101 if (fInput.bad()) throw -kBadSeek;
102 fCurrent = fInput.tellg();
103 if (fInput.bad()) throw -kBadTell;
104#if 0
105 fInput.seekg(fBegin);
106 size_t i = 0;
107 do {
108 W40_t w = 0;
109 fInput.read((char*)&w, 5);
110 std::cout << std::setw(6) << i << ": " << PRETTY_HEX(10, w) << std::endl;
111 i++;
112 } while (!fInput.eof());
113 fInput.seekg(fCurrent);
114#endif
115}
116
117//____________________________________________________________________
118Int_t
119AliFMDAltroReader::ReadChannel(UShort_t& board, UShort_t& chip,
120 UShort_t& channel, UShort_t& last,
121 UShort_t* data)
122{
123 UShort_t hwaddr;
124 Int_t ret = ReadChannel(hwaddr, last, data);
125 board = (hwaddr >> 7) & 0x1f;
126 chip = (hwaddr >> 4) & 0x3;
127 channel = hwaddr & 0xf;
128 return ret;
129}
130
131//____________________________________________________________________
132Int_t
133AliFMDAltroReader::ReadChannel(UShort_t& hwaddr, UShort_t& last,
134 UShort_t* data)
135{
136 Int_t ret, tmp;
137 AliDebug(15, Form("Reading a channel"));
138 if ((ret = ExtractTrailer(hwaddr, last)) < 0) {
139 AliError(Form("Failed to read trailer: %s", ErrorString(-ret)));
140 return ret;
141 }
142 AliDebug(15, Form("Now extracting bunches from %d 10 bit words", last));
143 tmp = ExtractBunches(last, data);
144 if (tmp < 0) {
145 AliError(Form("Failed to read bunches: %s", ErrorString(-tmp)));
146 return tmp;
147 }
148 ret += tmp;
149 last = (last == 0 ? 0 : last - 2);
150 return ret;
151}
152
153//____________________________________________________________________
154Int_t
155AliFMDAltroReader::ExtractTrailer(UShort_t& hwaddr, UShort_t& last)
156{
157 AliDebug(15, "Extracting trailer");
158 W40_t trailer = GetNextW40();
159 if (trailer < 0) {
160 AliError(Form("Trailer 0x%x is bad: %s", trailer, ErrorString(-trailer)));
161 return trailer;
162 }
163 if (!IsTrailer(trailer)) {
164 AliError(Form("Bad trailer: 0x%08x", trailer));
165 return -kBadTrailer;
166 }
167 last = (trailer >> 16) & 0x3ff;
168 hwaddr = (trailer & 0xfff);
169 return 4;
170}
171
172//____________________________________________________________________
173Int_t
174AliFMDAltroReader::ExtractBunches(UShort_t last, UShort_t* data)
175{
176 Int_t ret;
177 if ((ret = ExtractFillWords(last)) < 0) {
178 AliError(Form("Failed to read fill words: %s", ErrorString(-ret)));
179 return ret;
180 }
181 while (last > 0) {
182 Int_t tmp = ExtractBunch(data);
183 if (tmp <= 0) {
184 AliError(Form("Failed to extract bunch at %d: %s",
185 last, ErrorString(-tmp)));
186 return tmp;
187 }
188 ret += tmp;
189 last -= tmp;
190 }
191 return ret;
192}
193
194//____________________________________________________________________
195Int_t
196AliFMDAltroReader::ExtractFillWords(UShort_t last)
197{
198 // Number of fill words
199 size_t nFill = (last % 4 == 0 ? 0 : 4 - last % 4);
200 // Read the fill words
201 for (size_t i = 3; i >= 4 - nFill; i--) {
202 W10_t f = GetNextW10();
203 if (f != 0x2aa) return -kBadFill;
204 }
205 return nFill;
206}
207
208//____________________________________________________________________
209Int_t
210AliFMDAltroReader::ExtractBunch(UShort_t* data)
211{
212 Int_t ret = 0;
213 W10_t l = GetNextW10();
214 if (l < 0) {
215 AliError(Form("Failed to read bunch length: %s", ErrorString(-l)));
216 return l;
217 }
218 W10_t t = GetNextW10();
219 if (t < 0) {
220 AliError(Form("Failed to read bunch time: %s", ErrorString(-t)));
221 return t;
222 }
223 ret += 2;
224 for (Int_t i = 2; i < l; i++) {
225 W10_t s = GetNextW10();
226 if (s < 0) {
227 AliError(Form("Failed to read bunch data: %s", ErrorString(-s)));
228 return 2;
229 }
230 AliDebug(50,Form("Assigning to data[%d - (%d - 1)] = 0x%X", t, i, s));
231 data[t - (i-1)] = s;
232 ret++;
233 }
234 return ret;
235}
236
237//____________________________________________________________________
238Bool_t
239AliFMDAltroReader::IsTrailer(W40_t x)
240{
241 return ((x & fgkTrailerMask) == fgkTrailerMask);
242}
243
244//____________________________________________________________________
245Bool_t
246AliFMDAltroReader::IsBof()
247{
248 return fCurrent == fBegin;
249}
250
251//____________________________________________________________________
252Int_t
253AliFMDAltroReader::ReadW40()
254{
255 fInput.seekg(fCurrent-std::istream::pos_type(5));
256 if (fInput.bad()) return -kBadSeek;
257 fCurrent = fInput.tellg();
258 if (fInput.bad()) return -kBadTell;
259 fInput.read((char*)&fBuffer, 5 * sizeof(char));
260 if (fInput.bad()) return -kBadRead;
261 fIBuffer = 4;
262 AliDebug(15, Form(" 0x%03x 0x%03x 0x%03x 0x%03x 0x%010x %6d",
263 ExtractW10(3, fBuffer), ExtractW10(2, fBuffer),
264 ExtractW10(1, fBuffer), ExtractW10(0, fBuffer),
265 fBuffer, fCurrent));
266 return fCurrent;
267}
268
269//____________________________________________________________________
270AliFMDAltroIO::W10_t
271AliFMDAltroReader::GetNextW10()
272{
273 if (fIBuffer <= 0) {
274 Int_t ret;
275 if ((ret = ReadW40()) < 0) return ret;
276 }
277 fIBuffer--;
278 W10_t w10 = ExtractW10(fIBuffer, fBuffer);
279 return w10;
280}
281
282//____________________________________________________________________
283AliFMDAltroIO::W40_t
284AliFMDAltroReader::GetNextW40()
285{
286 W40_t w40 = 0;
287 for (Int_t i = 3; i >= 0; i--) {
288 W10_t tmp = GetNextW10();
289 W40_t bits = ConcatW40(i, tmp);
290 if (bits < 0) return bits;
291 w40 += bits;
292 }
293 return w40;
294}
295
296//====================================================================
297ClassImp(AliFMDAltroWriter)
298#if 0
299 ; // This is here to keep Emacs for indenting the next line
300#endif
301
302//____________________________________________________________________
303AliFMDAltroWriter::AliFMDAltroWriter(std::ostream& stream)
304 : fThreshold(0), fTotal(0), fOutput(stream)
305{
306 AliDebug(15, "New AliFMDAltroWriter object");
307 fTime = 0;
308 fLength = 0;
309 fLast = 0;
310 // Write a dummy header
311 fHeader = fOutput.tellp();
312 if (fOutput.bad()) throw -kBadTell;
313 AliRawDataHeader header;
314 fOutput.write((char*)(&header), sizeof(header));
315 if (fOutput.bad()) throw -kBadWrite;
316 fBegin = fOutput.tellp();
317 if (fOutput.bad()) throw -kBadTell;
318}
319
320//____________________________________________________________________
321Int_t
322AliFMDAltroWriter::Flush()
323{
324 if (fIBuffer == 0) return 0;
325 fOutput.write((char*)&fBuffer, 5 * sizeof(char));
326 if (fOutput.bad()) return -kBadWrite;
327 // for (size_t i = 0; i < 4; i++)
328 // std::cout << "\t" << PRETTY_HEX(3, ExtractW10(i, fBuffer));
329 // std::cout << "\t" << PRETTY_HEX(10, fBuffer) << std::endl;
330 fTotal += 5;
331 fIBuffer = 0;
332 fBuffer = 0;
333 return 5;
334}
335
336//____________________________________________________________________
337Int_t
338AliFMDAltroWriter::Close()
339{
340 Flush();
341 std::ostream::pos_type end = fOutput.tellp();
342 if (fOutput.bad()) return -kBadTell;
343 fOutput.seekp(fHeader, std::ios_base::beg);
344 if (fOutput.bad()) return -kBadSeek;
345 AliRawDataHeader header;
346 header.fSize = (size_t(end) - fHeader);
347 AliDebug(15, Form("Size set to %d (%d)", header.fSize, fTotal));
348 header.SetAttribute(0);
349 fOutput.write((char*)(&header), sizeof(header));
350 if (fOutput.bad()) return -kBadWrite;
351 fOutput.seekp(end);
352 if (fOutput.bad()) return -kBadSeek;
353 return sizeof(header);
354}
355
356
357//____________________________________________________________________
358Int_t
359AliFMDAltroWriter::AddSignal(UShort_t adc)
360{
361 Int_t ret = 0;
362 if (adc < fThreshold)
363 ret = AddBunchTrailer();
364 else {
365 ret = AddToBuffer(adc);
366 fLength++;
367 }
368 fTime++;
369 if (ret < 0) AliError(Form("Failed to add signal %x: %s", ErrorString(ret)));
370 return ret;
371}
372
373//____________________________________________________________________
374Int_t
375AliFMDAltroWriter::AddChannelTrailer(UShort_t board, UShort_t chip,
376 UShort_t channel)
377{
378 UInt_t hwaddr = (channel & 0xf)+((chip & 0x3) << 4)+((board & 0x1f) << 7);
379 return AddChannelTrailer(hwaddr);
380}
381
382//____________________________________________________________________
383Int_t
384AliFMDAltroWriter::AddChannelTrailer(UInt_t hwaddr)
385{
386 Int_t ret =0, tmp;
387 if ((tmp = AddBunchTrailer()) < 0) {
388 AliError(Form("Failed to bad bunch trailer: %s", ErrorString(tmp)));
389 return tmp;
390 }
391 ret += tmp;
392 if ((tmp = AddFillWords()) < 0) {
393 AliError(Form("Failed to bad fill words: %s", ErrorString(tmp)));
394 return tmp;
395 }
396 ret += tmp;
397 W40_t trailer = (fgkTrailerMask + hwaddr + ((fLast & 0x3ff) << 16));
398 fBuffer = trailer;
399 fIBuffer = 3;
400 ret += 4;
401 if ((tmp = Flush()) < 0) {
402 AliError(Form("Failed to flush: %s", ErrorString(tmp)));
403 return tmp;
404 }
405 ret += tmp;
406 fTime = 0;
407 fLast = 0;
408 return ret;
409}
410
411//____________________________________________________________________
412Int_t
413AliFMDAltroWriter::AddToBuffer(UShort_t x)
414{
415 W40_t tmp = ConcatW40(fIBuffer, x);
416 if (tmp < 0) return tmp;
417 fBuffer += tmp;
418 fIBuffer++;
419 fLast++;
420 Int_t ret = 0;
421 if (fIBuffer > 3 && (ret = Flush() < 0)) return ret;
422 return 1;
423}
424
425//____________________________________________________________________
426Int_t
427AliFMDAltroWriter::AddBunchTrailer()
428{
429 if (fLength <= 0) return 0;
430 Int_t ret = 0, tmp;
431 if ((tmp = AddToBuffer(fTime)) < 0) return tmp;
432 ret += tmp;
433 if ((tmp = AddToBuffer(fLength+2)) < 0) return tmp;
434 ret += tmp;
435 fLength = 0;
436 return ret;
437}
438
439//____________________________________________________________________
440Int_t
441AliFMDAltroWriter::AddFillWords()
442{
443 Int_t ret = 0, tmp;
444 if (fIBuffer == 0) return ret;
445 for (Int_t i = fIBuffer; i < 4; i++) {
446 if ((tmp = AddToBuffer(0x2aa)) < 0) return tmp;
447 ret += tmp;
448 fLast--;
449 }
450 if ((tmp = Flush() < 0)) return tmp;
451 return ret;
452}
453
454//_____________________________________________________________________________
455//
456// EOF
457//