]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - FMD/AliFMDAltroIO.cxx
New RAW I/O. I rolled my own, because I wasn't happy with the old
[u/mrichter/AliRoot.git] / FMD / AliFMDAltroIO.cxx
diff --git a/FMD/AliFMDAltroIO.cxx b/FMD/AliFMDAltroIO.cxx
new file mode 100644 (file)
index 0000000..3d7b68a
--- /dev/null
@@ -0,0 +1,454 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//____________________________________________________________________
+//                                                                          
+// Mapping of ALTRO hardware channel to detector coordinates 
+//
+#include "AliFMDAltroIO.h"
+#include <AliRawDataHeader.h>
+#include <AliRawReader.h>
+#include "AliLog.h"
+#include <iostream>
+#include <iomanip>
+#define PRETTY_HEX(N,X) \
+  "  0x" << std::setfill('0') << std::setw(N) << std::hex << X \
+         << std::setfill(' ') << std::dec
+
+//====================================================================
+ClassImp(AliFMDAltroIO)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+const AliFMDAltroIO::W40_t AliFMDAltroIO::fgkTrailerMask = 
+((AliFMDAltroIO::W40_t(0x2aaa) << 26) + (AliFMDAltroIO::W40_t(0xa) << 12));
+
+//____________________________________________________________________
+AliFMDAltroIO::AliFMDAltroIO() 
+  : fBuffer(0), fIBuffer(0)
+{}
+
+//____________________________________________________________________
+const char*
+AliFMDAltroIO::ErrorString(Int_t err)  const
+{
+  switch (err) {
+  case kNoError:    return "No error";                          break;
+  case kBadFile:    return "Bad state after open/close file";   break;
+  case kBadBits:    return "Bad bit offset specified";          break;
+  case kBadRead:    return "Bad state after reading from file"; break;
+  case kBadWrite:   return "Bad state after writing to file";   break;
+  case kBadSeek:    return "Bad state after seeking in file";   break;
+  case kBadTell:    return "Could not tell position in file";   break;
+  case kBadTrailer: return "Bad trailer 40 bit word in file";   break;
+  case kBadFill:    return "Bad fill word in file";             break;
+  }
+  return "Unknown";
+}
+
+
+//____________________________________________________________________
+AliFMDAltroIO::W40_t
+AliFMDAltroIO::ConcatW40(size_t n, const W10_t& w) const
+{
+  if (n > 3) return -kBadBits;
+  return W40_t(w & 0x3ff) << (10 * n);
+}
+
+//____________________________________________________________________
+AliFMDAltroIO::W10_t
+AliFMDAltroIO::ExtractW10(size_t n, const W40_t w) const
+{
+  if (n > 3) return -kBadBits;
+  return (w >> (10 * n)) & 0x3ff;
+}
+
+//====================================================================
+ClassImp(AliFMDAltroReader)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDAltroReader::AliFMDAltroReader(std::istream& stream)
+  : fInput(stream)
+  // : fBuffer(buffer), fCurrent(n / 10 * sizeof(char))
+{
+  // fInput.open(filename);
+  if (!fInput)      throw -kBadFile;
+  fBegin   = fInput.tellg();
+  if (fInput.bad()) throw -kBadTell;
+  fInput.seekg(0, std::ios_base::end);
+  if (fInput.bad()) throw -kBadSeek;
+  fCurrent = fInput.tellg();
+  if (fInput.bad()) throw -kBadTell;
+#if 0
+  fInput.seekg(fBegin);
+  size_t i = 0;
+  do {
+    W40_t w = 0;
+    fInput.read((char*)&w, 5);
+    std::cout << std::setw(6) << i << ": " << PRETTY_HEX(10, w) << std::endl;
+    i++;
+  } while (!fInput.eof());
+  fInput.seekg(fCurrent);
+#endif
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ReadChannel(UShort_t& board, UShort_t& chip, 
+                              UShort_t& channel, UShort_t& last, 
+                              UShort_t* data) 
+{
+  UShort_t hwaddr;
+  Int_t    ret = ReadChannel(hwaddr, last, data);
+  board        = (hwaddr >>  7) & 0x1f;
+  chip         = (hwaddr >>  4) & 0x3;
+  channel      = hwaddr & 0xf;
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ReadChannel(UShort_t& hwaddr, UShort_t& last, 
+                              UShort_t* data) 
+{
+  Int_t ret, tmp;
+  AliDebug(15, Form("Reading a channel"));
+  if ((ret = ExtractTrailer(hwaddr, last)) < 0) { 
+    AliError(Form("Failed to read trailer: %s", ErrorString(-ret)));
+    return ret;
+  }
+  AliDebug(15, Form("Now extracting bunches from %d 10 bit words", last));
+  tmp     =  ExtractBunches(last, data); 
+  if (tmp < 0) {
+    AliError(Form("Failed to read bunches: %s", ErrorString(-tmp)));
+    return tmp;
+  }
+  ret     += tmp;
+  last    =  (last == 0 ? 0 : last - 2); 
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractTrailer(UShort_t& hwaddr, UShort_t& last)
+{
+  AliDebug(15, "Extracting trailer");
+  W40_t trailer = GetNextW40();
+  if (trailer < 0) {
+    AliError(Form("Trailer 0x%x is bad: %s", trailer, ErrorString(-trailer)));
+    return trailer;
+  }
+  if (!IsTrailer(trailer)) { 
+    AliError(Form("Bad trailer: 0x%08x", trailer));
+    return -kBadTrailer;
+  }
+  last    = (trailer >> 16) & 0x3ff;
+  hwaddr  = (trailer & 0xfff);
+  return 4;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractBunches(UShort_t last, UShort_t* data) 
+{
+  Int_t ret;
+  if ((ret = ExtractFillWords(last)) < 0) { 
+    AliError(Form("Failed to read fill words: %s", ErrorString(-ret)));
+    return ret;
+  }
+  while (last > 0) { 
+    Int_t tmp = ExtractBunch(data);
+    if (tmp <= 0) { 
+      AliError(Form("Failed to extract bunch at %d: %s", 
+                   last, ErrorString(-tmp)));
+      return tmp;
+    }
+    ret  += tmp;
+    last -= tmp;
+  }
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractFillWords(UShort_t last) 
+{
+  // Number of fill words 
+  size_t nFill = (last % 4 == 0 ? 0 : 4 - last % 4);
+  // Read the fill words 
+  for (size_t i = 3; i >= 4 - nFill; i--) {
+    W10_t f = GetNextW10();
+    if (f != 0x2aa) return -kBadFill;
+  }
+  return nFill;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractBunch(UShort_t* data)
+{
+  Int_t ret =  0;
+  W10_t l =  GetNextW10(); 
+  if (l < 0) { 
+    AliError(Form("Failed to read bunch length: %s", ErrorString(-l)));
+    return l;
+  }
+  W10_t t =  GetNextW10(); 
+  if (t < 0) { 
+    AliError(Form("Failed to read bunch time: %s", ErrorString(-t)));
+    return t;
+  }
+  ret     += 2;
+  for (Int_t i = 2; i < l; i++) {
+    W10_t s = GetNextW10();
+    if (s < 0) { 
+      AliError(Form("Failed to read bunch data: %s", ErrorString(-s)));
+      return 2;
+    }
+    AliDebug(50,Form("Assigning to data[%d - (%d - 1)] = 0x%X", t, i, s));
+    data[t - (i-1)] = s;
+    ret++;
+  }
+  return ret;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDAltroReader::IsTrailer(W40_t x) 
+{
+  return ((x & fgkTrailerMask) == fgkTrailerMask);
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDAltroReader::IsBof() 
+{
+  return fCurrent == fBegin;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ReadW40() 
+{
+  fInput.seekg(fCurrent-std::istream::pos_type(5));
+  if (fInput.bad()) return -kBadSeek;
+  fCurrent = fInput.tellg();
+  if (fInput.bad()) return -kBadTell;
+  fInput.read((char*)&fBuffer, 5 * sizeof(char));
+  if (fInput.bad()) return -kBadRead;
+  fIBuffer = 4;
+  AliDebug(15, Form("  0x%03x  0x%03x  0x%03x  0x%03x    0x%010x  %6d", 
+                   ExtractW10(3, fBuffer), ExtractW10(2, fBuffer), 
+                   ExtractW10(1, fBuffer), ExtractW10(0, fBuffer), 
+                   fBuffer, fCurrent));
+  return fCurrent;
+}
+
+//____________________________________________________________________
+AliFMDAltroIO::W10_t
+AliFMDAltroReader::GetNextW10()
+{
+  if (fIBuffer <= 0) {
+    Int_t ret;
+    if ((ret = ReadW40()) < 0) return ret;
+  }
+  fIBuffer--;
+  W10_t w10 = ExtractW10(fIBuffer, fBuffer); 
+  return w10;
+}
+
+//____________________________________________________________________
+AliFMDAltroIO::W40_t
+AliFMDAltroReader::GetNextW40() 
+{
+  W40_t w40 = 0;
+  for (Int_t i = 3; i >= 0; i--) {
+    W10_t tmp  =  GetNextW10();
+    W40_t bits =  ConcatW40(i, tmp);
+    if (bits < 0) return bits;
+    w40        += bits;
+  }
+  return w40;
+}
+
+//====================================================================
+ClassImp(AliFMDAltroWriter)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDAltroWriter::AliFMDAltroWriter(std::ostream& stream) 
+  : fThreshold(0), fTotal(0), fOutput(stream)
+{
+  AliDebug(15, "New AliFMDAltroWriter object");
+  fTime   = 0;
+  fLength = 0;
+  fLast   = 0;
+  // Write a dummy header
+  fHeader = fOutput.tellp();
+  if (fOutput.bad()) throw -kBadTell;
+  AliRawDataHeader header;
+  fOutput.write((char*)(&header), sizeof(header));
+  if (fOutput.bad()) throw -kBadWrite;
+  fBegin = fOutput.tellp();
+  if (fOutput.bad()) throw -kBadTell;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::Flush() 
+{
+  if (fIBuffer == 0) return 0;
+  fOutput.write((char*)&fBuffer, 5 * sizeof(char));
+  if (fOutput.bad()) return -kBadWrite;
+  // for (size_t i = 0; i < 4; i++) 
+  //   std::cout << "\t" << PRETTY_HEX(3, ExtractW10(i, fBuffer));
+  // std::cout << "\t" << PRETTY_HEX(10, fBuffer) << std::endl;
+  fTotal   += 5;
+  fIBuffer =  0;
+  fBuffer  =  0;
+  return 5;
+}
+
+//____________________________________________________________________
+Int_t 
+AliFMDAltroWriter::Close() 
+{
+  Flush();
+  std::ostream::pos_type end = fOutput.tellp();
+  if (fOutput.bad()) return -kBadTell;
+  fOutput.seekp(fHeader, std::ios_base::beg);
+  if (fOutput.bad()) return -kBadSeek;
+  AliRawDataHeader header;
+  header.fSize = (size_t(end) - fHeader);
+  AliDebug(15, Form("Size set to %d (%d)", header.fSize, fTotal));
+  header.SetAttribute(0);
+  fOutput.write((char*)(&header), sizeof(header));
+  if (fOutput.bad()) return -kBadWrite;
+  fOutput.seekp(end);
+  if (fOutput.bad()) return -kBadSeek;
+  return sizeof(header);
+}
+
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddSignal(UShort_t adc) 
+{
+  Int_t ret = 0;
+  if (adc < fThreshold) 
+    ret = AddBunchTrailer();
+  else {
+    ret = AddToBuffer(adc);
+    fLength++;
+  }
+  fTime++;
+  if (ret < 0) AliError(Form("Failed to add signal %x: %s", ErrorString(ret)));
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddChannelTrailer(UShort_t board, UShort_t chip, 
+                                    UShort_t channel)
+{
+  UInt_t hwaddr = (channel & 0xf)+((chip & 0x3) << 4)+((board & 0x1f) << 7);
+  return AddChannelTrailer(hwaddr);
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddChannelTrailer(UInt_t hwaddr)
+{
+  Int_t ret =0, tmp;
+  if ((tmp = AddBunchTrailer()) < 0) { 
+    AliError(Form("Failed to bad bunch trailer: %s", ErrorString(tmp)));
+    return tmp;
+  }
+  ret += tmp;
+  if ((tmp = AddFillWords())    < 0) { 
+    AliError(Form("Failed to bad fill words: %s", ErrorString(tmp)));
+    return tmp;
+  }
+  ret += tmp;
+  W40_t trailer = (fgkTrailerMask + hwaddr + ((fLast & 0x3ff) << 16));
+  fBuffer = trailer;
+  fIBuffer = 3;
+  ret     += 4;
+  if ((tmp = Flush()) < 0) {
+    AliError(Form("Failed to flush: %s", ErrorString(tmp)));
+    return tmp;
+  }
+  ret     += tmp;
+  fTime   =  0;
+  fLast   =  0;
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddToBuffer(UShort_t x) 
+{
+  W40_t tmp = ConcatW40(fIBuffer, x);
+  if (tmp < 0) return tmp;
+  fBuffer += tmp;
+  fIBuffer++;
+  fLast++;
+  Int_t ret = 0;
+  if (fIBuffer > 3 && (ret = Flush() < 0)) return ret;
+  return 1;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddBunchTrailer()
+{
+  if (fLength <= 0) return 0;    
+  Int_t ret = 0, tmp;
+  if ((tmp = AddToBuffer(fTime))     < 0) return tmp;
+  ret += tmp;
+  if ((tmp = AddToBuffer(fLength+2)) < 0) return tmp;
+  ret += tmp;
+  fLength = 0;
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddFillWords() 
+{
+  Int_t ret = 0, tmp;
+  if (fIBuffer == 0) return ret;
+  for (Int_t i = fIBuffer; i < 4; i++) { 
+    if ((tmp = AddToBuffer(0x2aa)) < 0) return tmp;
+    ret += tmp;
+    fLast--; 
+  }
+  if ((tmp = Flush() < 0)) return tmp;
+  return ret;
+}
+
+//_____________________________________________________________________________
+//
+// EOF
+//