1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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
21 //____________________________________________________________________
23 // Mapping of ALTRO hardware channel to detector coordinates
25 #include "AliFMDAltroIO.h"
26 #include <AliRawDataHeader.h>
27 #include <AliRawReader.h>
31 #define PRETTY_HEX(N,X) \
32 " 0x" << std::setfill('0') << std::setw(N) << std::hex << X \
33 << std::setfill(' ') << std::dec
35 //====================================================================
36 ClassImp(AliFMDAltroIO)
38 ; // This is here to keep Emacs for indenting the next line
41 //____________________________________________________________________
42 const AliFMDAltroIO::W40_t AliFMDAltroIO::fgkTrailerMask =
43 ((AliFMDAltroIO::W40_t(0x2aaa) << 26) + (AliFMDAltroIO::W40_t(0xa) << 12));
45 //____________________________________________________________________
46 AliFMDAltroIO::AliFMDAltroIO()
47 : fBuffer(0), fIBuffer(0)
50 //____________________________________________________________________
52 AliFMDAltroIO::ErrorString(Int_t err) const
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;
69 //____________________________________________________________________
71 AliFMDAltroIO::ConcatW40(UShort_t n, const W10_t& w) const
73 if (n > 3) return -kBadBits;
74 return W40_t(w & 0x3ff) << (10 * n);
77 //____________________________________________________________________
79 AliFMDAltroIO::ExtractW10(UShort_t n, const W40_t w) const
81 if (n > 3) return -kBadBits;
82 return (w >> (10 * n)) & 0x3ff;
85 //====================================================================
86 ClassImp(AliFMDAltroReader)
88 ; // This is here to keep Emacs for indenting the next line
91 //____________________________________________________________________
92 AliFMDAltroReader::AliFMDAltroReader(std::istream& stream)
94 // : fBuffer(buffer), fCurrent(n / 10 * sizeof(char))
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;
105 fInput.seekg(fBegin);
109 fInput.read((char*)&w, 5);
110 std::cout << std::setw(6) << i << ": " << PRETTY_HEX(10, w) << std::endl;
112 } while (!fInput.eof());
113 fInput.seekg(fCurrent);
117 //____________________________________________________________________
119 AliFMDAltroReader::ReadChannel(UShort_t& board, UShort_t& chip,
120 UShort_t& channel, UShort_t& last,
124 Int_t ret = ReadChannel(hwaddr, last, data);
125 board = (hwaddr >> 7) & 0x1f;
126 chip = (hwaddr >> 4) & 0x3;
127 channel = hwaddr & 0xf;
131 //____________________________________________________________________
133 AliFMDAltroReader::ReadChannel(UShort_t& hwaddr, UShort_t& last,
137 AliFMDDebug(15, ("Reading a channel"));
138 if ((ret = ExtractTrailer(hwaddr, last)) < 0) {
139 AliError(Form("Failed to read trailer: %s", ErrorString(-ret)));
142 AliFMDDebug(15, ("Now extracting bunches from %d 10 bit words", last));
143 tmp = ExtractBunches(last, data);
145 AliError(Form("Failed to read bunches: %s", ErrorString(-tmp)));
149 last = (last == 0 ? 0 : last - 2);
153 //____________________________________________________________________
155 AliFMDAltroReader::ExtractTrailer(UShort_t& hwaddr, UShort_t& last)
157 AliFMDDebug(15, ("Extracting trailer"));
158 W40_t trailer = GetNextW40();
160 AliError(Form("Trailer 0x%x is bad: %s", trailer, ErrorString(-trailer)));
163 if (!IsTrailer(trailer)) {
164 AliError(Form("Bad trailer: 0x%08x", trailer));
167 last = (trailer >> 16) & 0x3ff;
168 hwaddr = (trailer & 0xfff);
172 //____________________________________________________________________
174 AliFMDAltroReader::ExtractBunches(UShort_t last, UShort_t* data)
177 if ((ret = ExtractFillWords(last)) < 0) {
178 AliError(Form("Failed to read fill words: %s", ErrorString(-ret)));
182 Int_t tmp = ExtractBunch(data);
184 AliError(Form("Failed to extract bunch at %d: %s",
185 last, ErrorString(-tmp)));
194 //____________________________________________________________________
196 AliFMDAltroReader::ExtractFillWords(UShort_t last)
198 // Number of fill words
199 UShort_t nFill = (last % 4 == 0 ? 0 : 4 - last % 4);
200 // Read the fill words
201 for (UShort_t i = 3; i >= 4 - nFill; i--) {
202 W10_t f = GetNextW10();
203 if (f != 0x2aa) return -kBadFill;
208 //____________________________________________________________________
210 AliFMDAltroReader::ExtractBunch(UShort_t* data)
213 W10_t l = GetNextW10();
215 AliError(Form("Failed to read bunch length: %s", ErrorString(-l)));
218 W10_t t = GetNextW10();
220 AliError(Form("Failed to read bunch time: %s", ErrorString(-t)));
224 for (Int_t i = 2; i < l; i++) {
225 W10_t s = GetNextW10();
227 AliError(Form("Failed to read bunch data: %s", ErrorString(-s)));
230 AliFMDDebug(50, ("Assigning to data[%d - (%d - 1)] = 0x%X", t, i, s));
237 //____________________________________________________________________
239 AliFMDAltroReader::IsTrailer(W40_t x)
241 return ((x & fgkTrailerMask) == fgkTrailerMask);
244 //____________________________________________________________________
246 AliFMDAltroReader::IsBof()
248 return fCurrent == fBegin;
251 //____________________________________________________________________
253 AliFMDAltroReader::ReadW40()
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;
262 AliFMDDebug(15, (" 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),
269 //____________________________________________________________________
271 AliFMDAltroReader::GetNextW10()
275 if ((ret = ReadW40()) < 0) return ret;
278 W10_t w10 = ExtractW10(fIBuffer, fBuffer);
282 //____________________________________________________________________
284 AliFMDAltroReader::GetNextW40()
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;
296 //====================================================================
297 ClassImp(AliFMDAltroWriter)
299 ; // This is here to keep Emacs for indenting the next line
302 //____________________________________________________________________
303 AliFMDAltroWriter::AliFMDAltroWriter(std::ostream& stream)
304 : fThreshold(0), fTotal(0), fOutput(stream)
306 AliFMDDebug(15, ("New AliFMDAltroWriter object"));
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;
320 //____________________________________________________________________
322 AliFMDAltroWriter::Flush()
324 if (fIBuffer == 0) return 0;
325 fOutput.write((char*)&fBuffer, 5 * sizeof(char));
326 if (fOutput.bad()) return -kBadWrite;
327 // for (UShort_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;
336 //____________________________________________________________________
338 AliFMDAltroWriter::Close()
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 = (UShort_t(end) - fHeader);
347 AliFMDDebug(15, ("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;
352 if (fOutput.bad()) return -kBadSeek;
353 return sizeof(header);
357 //____________________________________________________________________
359 AliFMDAltroWriter::AddSignal(UShort_t adc)
362 if (adc < fThreshold)
363 ret = AddBunchTrailer();
365 ret = AddToBuffer(adc);
369 if (ret < 0) AliError(Form("Failed to add signal %x: %s", ErrorString(ret)));
373 //____________________________________________________________________
375 AliFMDAltroWriter::AddChannelTrailer(UShort_t board, UShort_t chip,
378 UInt_t hwaddr = (channel & 0xf)+((chip & 0x3) << 4)+((board & 0x1f) << 7);
379 return AddChannelTrailer(hwaddr);
382 //____________________________________________________________________
384 AliFMDAltroWriter::AddChannelTrailer(UInt_t hwaddr)
387 if ((tmp = AddBunchTrailer()) < 0) {
388 AliError(Form("Failed to bad bunch trailer: %s", ErrorString(tmp)));
392 if ((tmp = AddFillWords()) < 0) {
393 AliError(Form("Failed to bad fill words: %s", ErrorString(tmp)));
397 W40_t trailer = (fgkTrailerMask + hwaddr + ((fLast & 0x3ff) << 16));
401 if ((tmp = Flush()) < 0) {
402 AliError(Form("Failed to flush: %s", ErrorString(tmp)));
411 //____________________________________________________________________
413 AliFMDAltroWriter::AddToBuffer(UShort_t x)
415 W40_t tmp = ConcatW40(fIBuffer, x);
416 if (tmp < 0) return tmp;
421 if (fIBuffer > 3 && (ret = Flush() < 0)) return ret;
425 //____________________________________________________________________
427 AliFMDAltroWriter::AddBunchTrailer()
429 if (fLength <= 0) return 0;
431 if ((tmp = AddToBuffer(fTime)) < 0) return tmp;
433 if ((tmp = AddToBuffer(fLength+2)) < 0) return tmp;
439 //____________________________________________________________________
441 AliFMDAltroWriter::AddFillWords()
444 if (fIBuffer == 0) return ret;
445 for (Int_t i = fIBuffer; i < 4; i++) {
446 if ((tmp = AddToBuffer(0x2aa)) < 0) return tmp;
450 if ((tmp = Flush() < 0)) return tmp;
454 //_____________________________________________________________________________