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 #include <Riostream.h>
17 #include <TClonesArray.h>
25 #include "AliRawDataHeader.h"
26 #include "AliBitPacking.h"
27 #include "AliPMDdigit.h"
28 #include "AliPMDBlockHeader.h"
29 #include "AliPMDDspHeader.h"
30 #include "AliPMDPatchBusHeader.h"
31 #include "AliPMDRawStream.h"
32 #include "AliPMDDDLRawData.h"
34 #include "AliFstream.h"
36 ClassImp(AliPMDDDLRawData)
38 AliPMDDDLRawData::AliPMDDDLRawData():
39 fDigits(new TClonesArray("AliPMDdigit", 1000))
41 // Default Constructor
45 //____________________________________________________________________________
46 AliPMDDDLRawData::AliPMDDDLRawData(const AliPMDDDLRawData& ddlraw):
48 fDigits(ddlraw.fDigits)
52 //____________________________________________________________________________
53 AliPMDDDLRawData & AliPMDDDLRawData::operator=(const AliPMDDDLRawData& ddlraw)
58 fDigits = ddlraw.fDigits;
62 //____________________________________________________________________________
64 AliPMDDDLRawData::~AliPMDDDLRawData()
71 //____________________________________________________________________________
72 void AliPMDDDLRawData::WritePMDRawData(TTree *treeD)
74 // write digits into raw data format
78 TBranch *branch = treeD->GetBranch("PMDDigit");
81 AliError("PMD Digit branch not found");
84 branch->SetAddress(&fDigits);
86 Int_t nmodules = (Int_t) treeD->GetEntries();
87 AliDebug(1,Form("Number of modules inside treeD = %d",nmodules));
89 const Int_t kDDL = AliDAQ::NumberOfDdls("PMD");
90 Int_t modulePerDDL = 0;
93 AliRawDataHeader header;
94 UInt_t sizeRawData = 0;
96 const Int_t kSize = 1536;
99 UInt_t busPatch[50][1536];
101 Int_t contentsBus[50];
107 for(Int_t iddl = 0; iddl < kDDL; iddl++)
109 strcpy(filename,AliDAQ::DdlFileName("PMD",iddl));
111 outfile = new AliFstream(filename);
131 // Write the Dummy Data Header into the file
132 Int_t bHPosition = outfile->Tellp();
133 outfile->WriteBuffer((char*)(&header),sizeof(header));
135 for (Int_t ibus = 0; ibus < 50; ibus++)
137 contentsBus[ibus] = 0;
138 for (Int_t ich = 0; ich < 1536; ich++)
140 busPatch[ibus][ich] = 0;
144 for(Int_t ium = 0; ium < modulePerDDL; ium++)
146 if (iddl == 4 && ium == 6) mmodule = 42;
148 // Extract energy deposition per cell and pack it
149 // in a 32-bit word and returns all the total words
150 // per one unit-module
152 GetUMDigitsData(treeD, mmodule, iddl, contentsBus, busPatch);
161 for (Int_t i = 0; i < 10; i++)
165 for (Int_t ibus=0; ibus < 5; ibus++)
167 if (contentsBus[ij] > 0)
169 dsp[i] += contentsBus[ij];
174 // Add the patch Bus header to the DSP contents
175 dsp[i] += 4*dspBus[i];
178 Int_t dspBlockARDL = 0;
179 Int_t dspBlockBRDL = 0;
181 for (Int_t i = 0; i < 5; i++)
184 Int_t iodd = 2*i + 1;
187 dspBlockARDL += dsp[ieven];
188 Int_t remainder = dsp[ieven]%2;
196 dspBlockBRDL += dsp[iodd];
197 Int_t remainder = dsp[ieven]%2;
205 // Start writing the DDL file
207 AliPMDBlockHeader blHeader;
208 AliPMDDspHeader dspHeader;
209 AliPMDPatchBusHeader pbusHeader;
211 const Int_t kblHLen = blHeader.GetHeaderLength();
212 const Int_t kdspHLen = dspHeader.GetHeaderLength();
213 const Int_t kpbusHLen = pbusHeader.GetHeaderLength();
216 UInt_t dspBlockHeaderWord[8];
217 UInt_t dspHeaderWord[10];
218 UInt_t patchBusHeaderWord[4];
222 for (Int_t iblock = 0; iblock < 2; iblock++)
226 for (Int_t i=0; i<kblHLen; i++)
228 dspBlockHeaderWord[i] = 0;
232 dspBlockHeaderWord[1] = (UInt_t) (dspBlockARDL + kblHLen);
233 dspBlockHeaderWord[2] = (UInt_t) dspBlockARDL;
235 else if (iblock == 1)
237 dspBlockHeaderWord[1] = (UInt_t) (dspBlockBRDL + kblHLen);
238 dspBlockHeaderWord[2] = (UInt_t) dspBlockBRDL;
241 outfile->WriteBuffer((char*)dspBlockHeaderWord,kblHLen*sizeof(UInt_t));
251 else if (iblock == 1)
260 for (Int_t idsp = 0; idsp < 5; idsp++)
267 dspRDL = (UInt_t) dsp[dspno];
269 else if (iblock == 1)
272 dspRDL = (UInt_t) dsp[dspno];
275 for (Int_t i=0; i<kdspHLen; i++)
277 dspHeaderWord[i] = 0;
279 Int_t remainder = dspRDL%2;
280 if (remainder == 1) dspRDL++;
282 dspHeaderWord[1] = dspRDL + kdspHLen;
283 dspHeaderWord[2] = dspRDL;
284 dspHeaderWord[3] = dspno;
285 if (remainder == 1) dspHeaderWord[8] = 1; // setting the padding word
286 outfile->WriteBuffer((char*)dspHeaderWord,kdspHLen*sizeof(UInt_t));
288 for (Int_t ibus = 0; ibus < 5; ibus++)
291 Int_t busno = iskip[idsp] + ibus;
292 Int_t patchbusRDL = contentsBus[busno];
296 patchBusHeaderWord[0] = 0;
297 patchBusHeaderWord[1] = (UInt_t) (patchbusRDL + kpbusHLen);
298 patchBusHeaderWord[2] = (UInt_t) patchbusRDL;
299 patchBusHeaderWord[3] = (UInt_t) busno;
301 else if (patchbusRDL == 0)
303 patchBusHeaderWord[0] = 0;
304 patchBusHeaderWord[1] = (UInt_t) kpbusHLen;
305 patchBusHeaderWord[2] = (UInt_t) 0;
306 patchBusHeaderWord[3] = (UInt_t) busno;
310 outfile->WriteBuffer((char*)patchBusHeaderWord,4*sizeof(UInt_t));
313 for (Int_t iword = 0; iword < patchbusRDL; iword++)
315 buffer[iword] = busPatch[busno][iword];
318 outfile->WriteBuffer((char*)buffer,patchbusRDL*sizeof(UInt_t));
320 } // End of patch bus loop
323 // Adding a padding word if the total words odd
326 UInt_t paddingWord = dspHeader.GetDefaultPaddingWord();
327 outfile->WriteBuffer((char*)(&paddingWord),sizeof(UInt_t));
332 // Write real data header
333 // take the pointer to the beginning of the data header
334 // write the total number of words per ddl and bring the
335 // pointer to the current file position and close it
336 UInt_t cFPosition = outfile->Tellp();
337 sizeRawData = cFPosition - bHPosition - sizeof(header);
339 header.fSize = cFPosition - bHPosition;
340 header.SetAttribute(0); // valid data
341 outfile->Seekp(bHPosition);
342 outfile->WriteBuffer((char*)(&header),sizeof(header));
343 outfile->Seekp(cFPosition);
350 //____________________________________________________________________________
351 void AliPMDDDLRawData::GetUMDigitsData(TTree *treeD, Int_t imodule,
352 Int_t ddlno, Int_t *contentsBus,
353 UInt_t busPatch[][1536])
355 // Retrives digits data UnitModule by UnitModule
360 Int_t det, smn, irow, icol;
363 const Int_t kMaxBus = 50;
364 Int_t totPatchBus, bPatchBus, ePatchBus;
365 Int_t ibus, totmcm, rows, cols, rowe, cole;
368 Int_t patchBusNo[kMaxBus], mcmperBus[kMaxBus];
369 Int_t startRowBus[kMaxBus], startColBus[kMaxBus];
370 Int_t endRowBus[kMaxBus], endColBus[kMaxBus];
372 Int_t beginPatchBus = -1;
373 Int_t endPatchBus = -1;
374 for(Int_t i = 0; i < kMaxBus; i++)
383 Int_t modulePerDDL = 0;
388 else if (ddlno == 4 || ddlno == 5)
393 TString fileName(gSystem->Getenv("ALICE_ROOT"));
397 fileName += "/PMD/PMD_Mapping_ddl0.dat";
401 fileName += "/PMD/PMD_Mapping_ddl1.dat";
405 fileName += "/PMD/PMD_Mapping_ddl2.dat";
409 fileName += "/PMD/PMD_Mapping_ddl3.dat";
413 fileName += "/PMD/PMD_Mapping_ddl4.dat";
417 fileName += "/PMD/PMD_Mapping_ddl5.dat";
421 infile.open(fileName.Data(), ios::in); // ascii file
423 AliError(Form("Could not read the mapping file for DDL No = %d",ddlno));
425 for (Int_t im = 0; im < modulePerDDL; im++)
428 infile >> totPatchBus >> bPatchBus >> ePatchBus;
430 if (moduleno == imodule)
432 beginPatchBus = bPatchBus;
433 endPatchBus = ePatchBus;
436 for(Int_t i=0; i<totPatchBus; i++)
438 infile >> ibus >> totmcm >> rows >> rowe >> cols >> cole;
440 if (moduleno == imodule)
442 patchBusNo[ibus] = ibus;
443 mcmperBus[ibus] = totmcm;
444 startRowBus[ibus] = rows;
445 startColBus[ibus] = cols;
446 endRowBus[ibus] = rowe;
447 endColBus[ibus] = cole;
455 treeD->GetEntry(imodule);
456 Int_t nentries = fDigits->GetLast();
457 Int_t totword = nentries+1;
459 AliPMDdigit *pmddigit;
461 for (Int_t ient = 0; ient < totword; ient++)
463 pmddigit = (AliPMDdigit*)fDigits->UncheckedAt(ient);
465 det = pmddigit->GetDetector();
466 smn = pmddigit->GetSMNumber();
467 irow = pmddigit->GetRow();
468 icol = pmddigit->GetColumn();
469 adc = (UInt_t) pmddigit->GetADC();
471 TransformS2H(smn,irow,icol);
473 GetMCMCh(ddlno, irow, icol, beginPatchBus, endPatchBus,
474 mcmperBus, startRowBus, startColBus,
475 endRowBus, endColBus, busno, mcmno, chno);
478 AliBitPacking::PackWord(adc,baseword,0,11);
479 AliBitPacking::PackWord(chno,baseword,12,17);
480 AliBitPacking::PackWord(mcmno,baseword,18,28);
481 AliBitPacking::PackWord(0,baseword,29,30);
482 parity = ComputeParity(baseword); // generate the parity bit
483 AliBitPacking::PackWord(parity,baseword,31,31);
485 Int_t jj = contentsBus[busno];
486 busPatch[busno][jj] = baseword;
488 contentsBus[busno]++;
493 //____________________________________________________________________________
494 void AliPMDDDLRawData::TransformS2H(Int_t smn, Int_t &irow, Int_t &icol)
496 // Does the Software to Hardware coordinate transformation
502 // First in digits we have all dimension 48x96
503 // Transform into the realistic one, i.e, For SM 0&1 96(row)x48(col)
504 // and for SM 2&3 48(row)x96(col)
511 else if( smn >= 12 && smn < 24)
523 //____________________________________________________________________________
525 void AliPMDDDLRawData::GetMCMCh(Int_t ddlno, Int_t row, Int_t col,
526 Int_t beginPatchBus, Int_t endPatchBus,
528 Int_t *startRowBus, Int_t *startColBus,
529 Int_t *endRowBus, Int_t *endColBus,
530 Int_t & busno, UInt_t &mcmno, UInt_t &chno)
532 // This converts row col to hardware channel number
533 // This is the final version of mapping supplied by Mriganka
535 static const UInt_t kCh[16][4] = { {56, 58, 59, 57},
552 Int_t irownew = row%16;
553 Int_t icolnew = col%4;
555 chno = kCh[irownew][icolnew];
558 for (Int_t ibus = beginPatchBus; ibus <= endPatchBus; ibus++)
560 Int_t srow = startRowBus[ibus];
561 Int_t erow = endRowBus[ibus];
562 Int_t scol = startColBus[ibus];
563 Int_t ecol = endColBus[ibus];
564 Int_t tmcm = mcmperBus[ibus];
565 if ((row >= srow && row <= erow) && (col >= scol && col <= ecol))
569 // Find out the MCM Number
572 if (ddlno == 0 || ddlno == 1)
574 // PRE plane, SU Mod = 0, 1
575 mcmno = (col-scol)/4;
578 else if (ddlno == 2 || ddlno == 3)
580 // PRE plane, SU Mod = 2, 3
581 Int_t icolnew = (col - scol)/4;
582 mcmno = tmcm - 1 - icolnew;
584 else if (ddlno == 4 )
586 // CPV plane, SU Mod = 0, 3 : ddl = 4
590 Int_t midrow = srow + 16;
591 if(row >= srow && row < midrow)
593 mcmno = 12 + (col-scol)/4;
595 else if(row >= midrow && row <= erow)
598 mcmno = (col-scol)/4;
604 Int_t rowdiff = endRowBus[ibus] - startRowBus[ibus];
607 Int_t midrow = srow + 16;
608 if (row >= midrow && row <= erow)
610 mcmno = 12 + (ecol -col)/4;
612 else if (row >= srow && row < midrow)
614 mcmno = (ecol - col)/4;
617 else if (rowdiff < 16)
619 mcmno = (ecol - col)/4;
623 else if ( ddlno == 5)
625 // CPV plane, SU Mod = 0, 3 : ddl = 4
629 Int_t midrow = srow + 16;
630 if(row >= srow && row < midrow)
632 mcmno = 12 + (col-scol)/4;
634 else if(row >= midrow && row <= erow)
636 mcmno = (col-scol)/4;
642 Int_t rowdiff = endRowBus[ibus] - startRowBus[ibus];
645 Int_t midrow = srow + 16;
646 if (row >= midrow && row <= erow)
648 mcmno = 12 + (ecol -col)/4;
650 else if (row >= srow && row < midrow)
652 mcmno = (ecol - col)/4;
655 else if (rowdiff < 16)
657 mcmno = (ecol - col)/4;
665 //____________________________________________________________________________
667 Int_t AliPMDDDLRawData::ComputeParity(UInt_t baseword)
669 // Generate the parity bit
672 for(Int_t j=0; j<29; j++)
674 if (baseword & 0x01 ) count++;
677 Int_t parity = count%2;
681 //____________________________________________________________________________