]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PMD/AliPMDDDLRawData.cxx
Setting the area in the AOD Jet
[u/mrichter/AliRoot.git] / PMD / AliPMDDDLRawData.cxx
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 #include <Riostream.h>
17 #include <TClonesArray.h>
18 #include <TTree.h>
19 #include <TBranch.h>
20 #include <TMath.h>
21 #include <TString.h>
22 #include <TSystem.h>
23
24 #include "AliLog.h"
25 #include "AliRawDataHeaderSim.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"
33 #include "AliDAQ.h"
34 #include "AliFstream.h"
35
36 ClassImp(AliPMDDDLRawData)
37
38 AliPMDDDLRawData::AliPMDDDLRawData():
39   fDigits(new TClonesArray("AliPMDdigit", 1000))
40 {
41   // Default Constructor
42   //
43
44 }
45 //____________________________________________________________________________
46 AliPMDDDLRawData::AliPMDDDLRawData(const AliPMDDDLRawData& ddlraw):
47   TObject(ddlraw),
48   fDigits(ddlraw.fDigits)
49 {
50   //Copy Constructor 
51 }
52 //____________________________________________________________________________
53 AliPMDDDLRawData & AliPMDDDLRawData::operator=(const AliPMDDDLRawData& ddlraw)
54 {
55   //Assignment operator 
56   if(this != &ddlraw)
57     {
58       fDigits = ddlraw.fDigits;
59     }
60   return *this;
61 }
62 //____________________________________________________________________________
63
64 AliPMDDDLRawData::~AliPMDDDLRawData()
65 {
66   // Default Destructor
67   //
68
69 }
70
71 //____________________________________________________________________________
72 void AliPMDDDLRawData::WritePMDRawData(TTree *treeD)
73 {
74   // write digits into raw data format
75
76   AliFstream *outfile;
77
78   TBranch *branch = treeD->GetBranch("PMDDigit");
79   if (!branch)
80     {
81       AliError("PMD Digit branch not found");
82       return;
83     }
84   branch->SetAddress(&fDigits);  
85   
86   Int_t   nmodules = (Int_t) treeD->GetEntries();
87   AliDebug(1,Form("Number of modules inside treeD = %d",nmodules));
88
89   const Int_t kDDL          = AliDAQ::NumberOfDdls("PMD");
90   Int_t modulePerDDL        = 0;
91
92
93   AliRawDataHeaderSim header;
94   UInt_t sizeRawData = 0;
95   
96   const Int_t kbusSize = 51;
97   const Int_t kSize = 1536;
98   UInt_t buffer[kSize];
99
100   UInt_t busPatch[kbusSize][1536];
101
102   Int_t contentsBus[kbusSize];
103
104   Char_t filename[80];
105
106   // open the ddl file info to know the modules per DDL
107   TString ddlinfofileName(gSystem->Getenv("ALICE_ROOT"));
108   ddlinfofileName += "/PMD/PMD_ddl_info.dat";
109
110   ifstream infileddl;
111   infileddl.open(ddlinfofileName.Data(), ios::in); // ascii file
112   if(!infileddl) AliError("Could not read the ddl info file");
113
114
115
116   Int_t mmodule = 0;
117   Int_t ddlno;
118   Int_t modno;
119   Int_t *modulenoddl = 0x0;
120
121   for(Int_t iddl = 0; iddl < kDDL; iddl++)
122     {
123       if (infileddl.eof()) break;
124       infileddl >> ddlno >> modulePerDDL;
125
126       if (modulePerDDL == 0) continue;
127
128       modulenoddl = new Int_t [modulePerDDL];
129       for (Int_t im = 0; im < modulePerDDL; im++)
130         {
131           infileddl >> modno;
132           modulenoddl[im] = modno;
133         }
134
135       strcpy(filename,AliDAQ::DdlFileName("PMD",iddl));
136       
137       outfile = new AliFstream(filename);
138       
139       // Write the Dummy Data Header into the file
140       Int_t bHPosition = outfile->Tellp();
141       outfile->WriteBuffer((char*)(&header),sizeof(header));
142
143       for (Int_t ibus = 0; ibus < kbusSize; ibus++)
144         {
145           contentsBus[ibus] = 0;
146           for (Int_t ich = 0; ich < kSize; ich++)
147             {
148               busPatch[ibus][ich] = 0;
149             }
150         }
151
152       for(Int_t ium = 0; ium < modulePerDDL; ium++)
153         {
154           //if (iddl == 4 && ium == 6) mmodule = 42;
155
156           // Extract energy deposition per cell and pack it
157           // in a 32-bit word and returns all the total words
158           // per one unit-module
159           
160           mmodule = modulenoddl[ium];
161           GetUMDigitsData(treeD, mmodule, iddl, modulePerDDL, contentsBus, busPatch);
162         }
163
164       Int_t ij = 0;
165       Int_t dsp[10];
166       Int_t dspBus[10];
167       for (Int_t i = 0; i < 10; i++)
168         {
169           dsp[i] = 0;
170           dspBus[i] = 0;
171           for (Int_t ibus=0; ibus < 5; ibus++)
172             {
173               ij++;
174               if (contentsBus[ij] > 0)
175                 {
176                   dsp[i] += contentsBus[ij];
177                 }
178               dspBus[i]++;
179             }
180           // Add the patch Bus header to the DSP contents
181           dsp[i] += 4*dspBus[i];
182         }
183
184       Int_t dspBlockARDL    = 0;
185       Int_t dspBlockBRDL    = 0;
186       Int_t remainder       = 0;
187
188
189       for (Int_t i = 0; i < 5; i++)
190         {
191           Int_t ieven = 2*i;
192           Int_t iodd  = 2*i + 1;
193           if (dsp[ieven] > 0)
194             {
195               dspBlockARDL += dsp[ieven];
196               remainder = dsp[ieven]%2;
197               if (remainder == 1)
198                 {
199                   dspBlockARDL++;
200                 }
201             }
202           if (dsp[iodd] > 0)
203             {
204               dspBlockBRDL += dsp[iodd];
205               remainder = dsp[iodd]%2;
206               if (remainder == 1)
207                 {
208                   dspBlockBRDL++;
209                 }
210             }
211         }
212
213       dspBlockARDL += 50;
214       dspBlockBRDL += 50;
215
216       // Start writing the DDL file
217
218       AliPMDBlockHeader blHeader;
219       AliPMDDspHeader   dspHeader;
220       AliPMDPatchBusHeader pbusHeader;
221
222       const Int_t kblHLen   = blHeader.GetHeaderLength();
223       const Int_t kdspHLen  = dspHeader.GetHeaderLength();
224       const Int_t kpbusHLen = pbusHeader.GetHeaderLength();
225
226       UInt_t dspRDL = 0;
227       UInt_t dspBlockHeaderWord[8];
228       UInt_t dspHeaderWord[10];
229       UInt_t patchBusHeaderWord[4];
230       Int_t  iskip[5];
231       UInt_t ddlEndWord[2] = {0xDEADFACE, 0xDEADFACE};
232
233       Int_t bknJunk = 0;
234
235
236       for (Int_t iblock = 0; iblock < 2; iblock++)
237         {
238           // DSP Block Header
239           
240           for (Int_t i=0; i<kblHLen; i++)
241             {
242               dspBlockHeaderWord[i] = 0;
243             }
244           if (iblock == 0)
245             {
246               dspBlockHeaderWord[1] = (UInt_t) (dspBlockARDL + kblHLen);
247               dspBlockHeaderWord[2] = (UInt_t) dspBlockARDL;
248             }
249           else if (iblock == 1)
250             {
251               dspBlockHeaderWord[1] = (UInt_t) (dspBlockBRDL + kblHLen);
252               dspBlockHeaderWord[2] = (UInt_t) dspBlockBRDL;
253             }
254
255           outfile->WriteBuffer((char*)dspBlockHeaderWord,kblHLen*sizeof(UInt_t));
256
257           if (iblock == 0)
258             {
259               iskip[0] = 0;
260               iskip[1] = 10;
261               iskip[2] = 20;
262               iskip[3] = 30;
263               iskip[4] = 40;
264             }
265           else if (iblock == 1)
266             {
267               iskip[0] = 5;
268               iskip[1] = 15;
269               iskip[2] = 25;
270               iskip[3] = 35;
271               iskip[4] = 45;
272             }
273
274           for (Int_t idsp = 0; idsp < 5; idsp++)
275             {
276               // DSP Header
277               Int_t dspno = 0;
278               if (iblock == 0)
279                 {
280                   dspno = 2*idsp;
281                   dspRDL = (UInt_t) dsp[dspno];
282                 }
283               else if (iblock == 1)
284                 {
285                   dspno = 2*idsp + 1;
286                   dspRDL = (UInt_t) dsp[dspno];
287                 }
288
289               for (Int_t i=0; i<kdspHLen; i++)
290                 {
291                   dspHeaderWord[i] = 0;
292                 }
293               remainder = dspRDL%2;
294               if (remainder == 1) dspRDL++;
295
296               dspHeaderWord[1] = dspRDL + kdspHLen;
297               dspHeaderWord[2] = dspRDL;
298               dspHeaderWord[3] = dspno;
299               if (remainder == 1) dspHeaderWord[8] = 1; // setting the padding word
300
301
302               outfile->WriteBuffer((char*)dspHeaderWord,kdspHLen*sizeof(UInt_t));
303
304               for (Int_t ibus = 0; ibus < 5; ibus++)
305                 {
306                   // Patch Bus Header
307
308                   Int_t busno = iskip[idsp] + ibus + 1;
309                   Int_t patchbusRDL = contentsBus[busno];
310
311                   if (patchbusRDL > 0)
312                     {
313                       patchBusHeaderWord[0] = 0;
314                       patchBusHeaderWord[1] = (UInt_t) (patchbusRDL + kpbusHLen);
315                       patchBusHeaderWord[2] = (UInt_t) patchbusRDL;
316                       patchBusHeaderWord[3] = (UInt_t) busno;
317                     }
318                   else if (patchbusRDL == 0)
319                     {
320                       patchBusHeaderWord[0] = 0;
321                       patchBusHeaderWord[1] = (UInt_t) kpbusHLen;
322                       patchBusHeaderWord[2] = (UInt_t) 0;
323                       patchBusHeaderWord[3] = (UInt_t) busno;
324                     }
325
326
327                   outfile->WriteBuffer((char*)patchBusHeaderWord,4*sizeof(UInt_t));
328
329                   bknJunk += patchbusRDL;
330
331                   for (Int_t iword = 0; iword < patchbusRDL; iword++)
332                     {
333                       buffer[iword] = busPatch[busno][iword];
334                     }
335                   
336                   outfile->WriteBuffer((char*)buffer,patchbusRDL*sizeof(UInt_t));
337
338                 } // End of patch bus loop
339
340
341               // Adding a padding word if the total words odd
342               if (remainder == 1)
343                 {
344                   UInt_t paddingWord = dspHeader.GetDefaultPaddingWord();
345                   outfile->WriteBuffer((char*)(&paddingWord),sizeof(UInt_t));
346                 }
347             }
348         }
349
350       // Write two extra word at the end of each DDL file
351       outfile->WriteBuffer((char*)ddlEndWord,2*sizeof(UInt_t));
352
353       // Write real data header
354       // take the pointer to the beginning of the data header
355       // write the total number of words per ddl and bring the
356       // pointer to the current file position and close it
357       UInt_t cFPosition = outfile->Tellp();
358       sizeRawData = cFPosition - bHPosition - sizeof(header);
359
360       header.fSize = cFPosition - bHPosition;
361       header.SetAttribute(0);  // valid data
362       outfile->Seekp(bHPosition);
363       outfile->WriteBuffer((char*)(&header),sizeof(header));
364       outfile->Seekp(cFPosition);
365
366       delete outfile;
367     } // DDL Loop over
368
369   delete [] modulenoddl;
370   infileddl.close();
371 }
372 //____________________________________________________________________________
373 void AliPMDDDLRawData::GetUMDigitsData(TTree *treeD, Int_t imodule,
374                                        Int_t ddlno, Int_t modulePerDDL,
375                                        Int_t *contentsBus,
376                                        UInt_t busPatch[][1536])
377 {
378   // Retrieves digits data UnitModule by UnitModule
379
380   const Int_t kMaxBus = 51;
381
382   UInt_t baseword = 0;
383   UInt_t mcmno = 0, chno = 0;
384   UInt_t adc = 0;
385   Int_t  det = 0, smn = 0, irow = 0, icol = 0;
386   Int_t  parity = 0;
387   
388   Int_t totPatchBus = 0, bPatchBus = 0, ePatchBus = 0;
389   Int_t ibus = 0, totmcm = 0, rows = 0, cols = 0, rowe = 0, cole = 0;
390   Int_t moduleno = 0;
391   Int_t busno = 0;
392   Int_t patchBusNo[kMaxBus], mcmperBus[kMaxBus];
393   Int_t startRowBus[kMaxBus], startColBus[kMaxBus];
394   Int_t endRowBus[kMaxBus], endColBus[kMaxBus];
395
396   Int_t beginPatchBus = -1;
397   Int_t endPatchBus   = -1;
398   for(Int_t i = 0; i < kMaxBus; i++)
399     {
400       patchBusNo[i]  = -1;
401       mcmperBus[i]   = -1;
402       startRowBus[i] = -1;
403       startColBus[i] = -1;
404       endRowBus[i]   = -1;
405       endColBus[i]   = -1;
406     }
407
408
409   TString fileName(gSystem->Getenv("ALICE_ROOT"));
410
411   if(ddlno == 0)
412     {
413       fileName += "/PMD/PMD_Mapping_ddl0.dat";
414     }
415   else if(ddlno == 1)
416     {
417       fileName += "/PMD/PMD_Mapping_ddl1.dat";
418     }
419   else if(ddlno == 2)
420     {
421       fileName += "/PMD/PMD_Mapping_ddl2.dat";
422     }
423   else if(ddlno == 3)
424     {
425       fileName += "/PMD/PMD_Mapping_ddl3.dat";
426     }
427   else if(ddlno == 4)
428     {
429       fileName += "/PMD/PMD_Mapping_ddl4.dat";
430     }
431   else if(ddlno == 5)
432     {
433       fileName += "/PMD/PMD_Mapping_ddl5.dat";
434     }
435
436   ifstream infile;
437   infile.open(fileName.Data(), ios::in); // ascii file
438   if(!infile)
439     AliError(Form("Could not read the mapping file for DDL No = %d",ddlno));
440
441   for (Int_t im = 0; im < modulePerDDL; im++)
442     {
443       infile >> moduleno;
444       infile >> totPatchBus >> bPatchBus >> ePatchBus;
445       
446       if (totPatchBus == 0) continue;    // BKN
447
448       if (moduleno == imodule)
449         {
450           beginPatchBus = bPatchBus;
451           endPatchBus   = ePatchBus;
452         }
453       
454       for(Int_t i=0; i<totPatchBus; i++)
455         {
456           infile >> ibus >> totmcm >> rows >> rowe >> cols >> cole;
457
458           if (moduleno == imodule)
459             {
460               patchBusNo[ibus]   = ibus;
461               mcmperBus[ibus]    = totmcm;
462               startRowBus[ibus]  = rows;
463               startColBus[ibus]  = cols;
464               endRowBus[ibus]    = rowe;
465               endColBus[ibus]    = cole;
466             }
467         }
468
469     }
470
471   infile.close();
472
473   // Read if some chains are off
474   TString rchainName(gSystem->Getenv("ALICE_ROOT"));
475   rchainName += "/PMD/PMD_removed_chains.dat";
476
477   ifstream rchainfile;
478   rchainfile.open(rchainName.Data(), ios::in); // ascii file
479   if(!rchainfile)AliError("Could not read the removed cahins file");
480
481   Int_t srowoff1[2][24], erowoff1[2][24];
482   Int_t scoloff1[2][24], ecoloff1[2][24];
483   Int_t srowoff2[2][24], erowoff2[2][24];
484   Int_t scoloff2[2][24], ecoloff2[2][24];
485
486   Int_t rows1 = 0, rowe1 = 0, cols1 = 0, cole1 = 0;
487   Int_t rows2 = 0, rowe2 = 0, cols2 = 0, cole2 = 0;
488
489   for (Int_t im = 0; im < 48; im++)
490     {
491       rchainfile >> det >> smn >> rows1 >> rowe1 >> cols1 >> cole1
492                  >> rows2 >> rowe2 >> cols2 >> cole2;
493       
494       srowoff1[det][smn] = rows1;
495       erowoff1[det][smn] = rowe1;
496       scoloff1[det][smn] = cols1;
497       ecoloff1[det][smn] = cole1;
498       srowoff2[det][smn] = rows2;
499       erowoff2[det][smn] = rowe2;
500       scoloff2[det][smn] = cols2;
501       ecoloff2[det][smn] = cole2;
502     }
503
504   rchainfile.close();
505
506   treeD->GetEntry(imodule); 
507   Int_t nentries = fDigits->GetLast();
508   Int_t totword = nentries+1;
509
510   AliPMDdigit *pmddigit = 0x0;
511
512   for (Int_t ient = 0; ient < totword; ient++)
513     {
514       pmddigit = (AliPMDdigit*)fDigits->UncheckedAt(ient);
515       
516       det    = pmddigit->GetDetector();
517       smn    = pmddigit->GetSMNumber();
518       irow   = pmddigit->GetRow();
519       icol   = pmddigit->GetColumn();
520       adc    = (UInt_t) pmddigit->GetADC();
521
522       TransformS2H(smn,irow,icol);
523       
524       // remove the non-existence channels
525
526       //printf("%d %d %d %d\n",det,smn,irow,icol);
527       //printf("--- %d   %d   %d   %d\n",srowoff[det][smn],erowoff[det][smn],
528       //     scoloff[det][smn],ecoloff[det][smn]);
529
530       if (irow >= srowoff1[det][smn] && irow <= erowoff1[det][smn])
531         {
532           if (icol >= scoloff1[det][smn] && icol <= ecoloff1[det][smn])
533             {
534               continue;
535             }
536         }
537       if (irow >= srowoff2[det][smn] && irow <= erowoff2[det][smn])
538         {
539           if (icol >= scoloff2[det][smn] && icol <= ecoloff2[det][smn])
540             {
541               continue;
542             }
543         }
544
545
546       GetMCMCh(imodule, irow, icol, beginPatchBus, endPatchBus,
547                mcmperBus, startRowBus, startColBus,
548                endRowBus, endColBus, busno, mcmno, chno);
549
550       baseword = 0;
551       AliBitPacking::PackWord(adc,baseword,0,11);
552       AliBitPacking::PackWord(chno,baseword,12,17);
553       AliBitPacking::PackWord(mcmno,baseword,18,28);
554       AliBitPacking::PackWord(0,baseword,29,30);
555       parity = ComputeParity(baseword);      // generate the parity bit
556       AliBitPacking::PackWord(parity,baseword,31,31);
557
558       Int_t jj = contentsBus[busno];
559       busPatch[busno][jj] = baseword;
560
561       contentsBus[busno]++;
562     }
563
564 }
565
566 //____________________________________________________________________________
567 void AliPMDDDLRawData::TransformS2H(Int_t smn, Int_t &irow, Int_t &icol)
568 {
569   // Does the Software to Hardware coordinate transformation
570   //
571
572   Int_t  irownew = 0;
573   Int_t  icolnew = 0;
574
575   // First in digits we have all dimension 48x96
576   // Transform into the realistic one, i.e, For SM 0&1 96(row)x48(col)
577   // and for SM 2&3 48(row)x96(col)
578   // 
579   if(smn < 12)
580     {
581       irownew = icol;
582       icolnew = irow;
583     }
584   else if( smn >= 12 && smn < 24)
585     {
586       irownew = irow;
587       icolnew = icol;
588     }
589
590   irow = irownew;
591   icol = icolnew;
592
593 }
594
595
596 //____________________________________________________________________________
597
598 void AliPMDDDLRawData::GetMCMCh(Int_t imodule, Int_t row, Int_t col,
599                                 Int_t beginPatchBus, Int_t endPatchBus,
600                                 Int_t *mcmperBus,
601                                 Int_t *startRowBus, Int_t *startColBus,
602                                 Int_t *endRowBus, Int_t *endColBus,
603                                 Int_t & busno, UInt_t &mcmno, UInt_t &chno)
604 {
605   // This converts row col to hardware channel number
606   // This is the final version of mapping supplied by Mriganka
607
608     UInt_t iCh[16][4];
609
610     static const UInt_t kChDdl01[16][4] = { {6, 4, 5, 7},
611                                            {10, 2, 1, 9},
612                                            {12, 0, 3, 11},
613                                            {14, 8, 13, 15},
614                                            {16, 18, 23, 17},
615                                            {20, 28, 31, 19},
616                                            {22, 30, 29, 21},
617                                            {24, 26, 27, 25},
618                                            {38, 36, 37, 39},
619                                            {42, 34, 33, 41},
620                                            {44, 32, 35, 43},
621                                            {46, 40, 45, 47},
622                                            {48, 50, 55, 49},
623                                            {52, 60, 63, 51},
624                                            {54, 62, 61, 53},
625                                            {56, 58, 59, 57} };
626
627
628     static const UInt_t kChDdl23[16][4] = { {57, 59, 58, 56},
629                                             {53, 61, 62, 54},
630                                             {51, 63, 60, 52},
631                                             {49, 55, 50, 48},
632                                             {47, 45, 40, 46},
633                                             {43, 35, 32, 44},
634                                             {41, 33, 34, 42},
635                                             {39, 37, 36, 38},
636                                             {25, 27, 26, 24},
637                                             {21, 29, 30, 22},
638                                             {19, 31, 28, 20},
639                                             {17, 23, 18, 16},
640                                             {15, 13, 8, 14},
641                                             {11, 3, 0, 12},
642                                             {9, 1, 2, 10},
643                                             {7, 5, 4, 6} };
644     
645     
646     static const UInt_t kChDdl41[16][4] = { {56, 58, 59, 57},
647                                            {54, 62, 61, 53},
648                                            {52, 60, 63, 51},
649                                            {48, 50, 55, 49},
650                                            {46, 40, 45, 47},
651                                            {44, 32, 35, 43},
652                                            {42, 34, 33, 41},
653                                            {38, 36, 37, 39},
654                                            {24, 26, 27, 25},
655                                            {22, 30, 29, 21},
656                                            {20, 28, 31, 19},
657                                            {16, 18, 23, 17},
658                                            {14, 8, 13, 15},
659                                            {12, 0, 3, 11},
660                                            {10, 2, 1, 9},
661                                            {6, 4, 5, 7} };
662
663
664     static const UInt_t kChDdl42[16][4] = { {7, 5, 4, 6},
665                                             {9, 1, 2, 10},
666                                             {11, 3, 0, 12},
667                                             {15, 13, 8, 14},
668                                             {17, 23, 18, 16},
669                                             {19, 31, 28, 20},
670                                             {21, 29, 30, 22},
671                                             {25, 27, 26, 24},
672                                             {39, 37, 36, 38},
673                                             {41, 33, 34, 42},
674                                             {43, 35, 32, 44},
675                                             {47, 45, 40, 46},
676                                             {49, 55, 50, 48},
677                                             {51, 63, 60, 52},
678                                             {53, 61, 62, 54},
679                                             {57, 59, 58, 56} };
680
681
682     static const UInt_t kChDdl51[16][4] = { {7, 5, 4, 6},
683                                             {9, 1, 2, 10},
684                                             {11, 3, 0, 12},
685                                             {15, 13, 8, 14},
686                                             {17, 23, 18, 16},
687                                             {19, 31, 28, 20},
688                                             {21, 29, 30, 22},
689                                             {25, 27, 26, 24},
690                                             {39, 37, 36, 38},
691                                             {41, 33, 34, 42},
692                                             {43, 35, 32, 44},
693                                             {47, 45, 40, 46},
694                                             {49, 55, 50, 48},
695                                             {51, 63, 60, 52},
696                                             {53, 61, 62, 54},
697                                             {57, 59, 58, 56} };
698     
699
700
701     static const UInt_t kChDdl52[16][4] = { {56, 58, 59, 57},
702                                             {54, 62, 61, 53},
703                                             {52, 60, 63, 51},
704                                             {48, 50, 55, 49},
705                                             {46, 40, 45, 47},
706                                             {44, 32, 35, 43},
707                                             {42, 34, 33, 41},
708                                             {38, 36, 37, 39},
709                                             {24, 26, 27, 25},
710                                             {22, 30, 29, 21},
711                                             {20, 28, 31, 19},
712                                             {16, 18, 23, 17},
713                                             {14, 8, 13, 15},
714                                             {12, 0, 3, 11},
715                                             {10, 2, 1, 9},
716                                             {6, 4, 5, 7} };
717     
718     
719     for (Int_t i = 0; i < 16; i++)
720       {
721         for (Int_t j = 0; j < 4; j++)
722           {
723             
724             if(imodule < 6)                    iCh[i][j] = kChDdl01[i][j];
725             if(imodule >= 6 && imodule <= 11)  iCh[i][j] = kChDdl01[i][j];
726             if(imodule >= 12 && imodule <= 17) iCh[i][j] = kChDdl23[i][j];
727             if(imodule >= 18 && imodule <= 23) iCh[i][j] = kChDdl23[i][j];
728
729             if(imodule >= 24 && imodule <= 29) iCh[i][j] = kChDdl41[i][j];
730             if(imodule >= 42 && imodule <= 47) iCh[i][j] = kChDdl42[i][j];
731             if(imodule >= 36 && imodule <= 41) iCh[i][j] = kChDdl51[i][j];
732             if(imodule >= 30 && imodule <= 35) iCh[i][j] = kChDdl52[i][j];
733             
734           }
735       }
736
737
738   Int_t irownew = row%16;
739   Int_t icolnew = col%4;
740   
741   chno  = iCh[irownew][icolnew];
742   
743   
744   for (Int_t ibus = beginPatchBus; ibus <= endPatchBus; ibus++)
745     {
746       Int_t srow = startRowBus[ibus];
747       Int_t erow = endRowBus[ibus];
748       Int_t scol = startColBus[ibus];
749       Int_t ecol = endColBus[ibus];
750       Int_t tmcm = mcmperBus[ibus];
751
752       if ((row >= srow && row <= erow) && (col >= scol && col <= ecol))
753         {
754           busno = ibus;
755           
756           // Find out the MCM Number
757           //
758
759           if (imodule < 6)                  mcmno = (col-scol)/4 + 1;
760           if (imodule >= 6 && imodule < 12) mcmno = (col-scol)/4 + 1;
761
762           if (imodule >= 12 && imodule < 18)
763             {
764               icolnew = (col - scol)/4;
765               mcmno = tmcm - icolnew;
766             }         
767           if (imodule >= 18 && imodule < 24)
768             {
769               icolnew = (col - scol)/4;
770               mcmno = tmcm - icolnew;
771             }         
772
773           // DDL = 4
774           if (imodule >= 24 && imodule < 30)
775             {
776
777               //if (tmcm == 24)
778               Int_t rowdiff = endRowBus[ibus] - startRowBus[ibus];
779               if(rowdiff > 16)
780                 {
781                   Int_t midrow = srow + 16;
782                   if(row >= srow && row < midrow)
783                     {
784                       mcmno = 12 + (col-scol)/4 + 1;
785                     }
786                   else if(row >= midrow && row <= erow)
787                     
788                     {
789                       mcmno = (col-scol)/4 + 1;
790                     }
791                 }
792               else if (rowdiff < 16)
793                 {
794                   mcmno = (col-scol)/4 + 1;
795                 }
796             
797             }         
798           if (imodule >= 42 && imodule < 48)
799             {
800               Int_t rowdiff = endRowBus[ibus] - startRowBus[ibus];
801               if(rowdiff > 16)
802                 {
803                   Int_t midrow = srow + 16;
804                   if (row >= midrow && row <= erow)
805                     {
806                       mcmno = 12 + (ecol -col)/4 + 1;
807                     }
808                   else if (row >= srow && row < midrow)
809                     {
810                       mcmno = (ecol - col)/4 + 1;
811                     }
812                 }
813               else if (rowdiff < 16)
814                 {
815                   mcmno = (ecol - col)/4 + 1;
816                 }
817             }         
818
819           // DDL = 5
820           if (imodule >= 30 && imodule < 36)
821             {
822               // CPV plane,  SU Mod = 1, 2 : ddl = 5
823               
824               //if(tmcm == 24)
825               Int_t rowdiff = endRowBus[ibus] - startRowBus[ibus];
826               if(rowdiff > 16)
827                 {
828                   Int_t midrow = srow + 16;
829                   if(row >= srow && row < midrow)
830                     {
831                       mcmno = 12 + (col-scol)/4 + 1;
832                     }
833                   else if(row >= midrow && row <= erow)
834                     {
835                       mcmno = (col-scol)/4 + 1;
836                     }
837                 }
838               else if(rowdiff < 16)
839                 {
840                   mcmno = (col-scol)/4 + 1;
841                 }
842               
843             }
844           if (imodule >= 36 && imodule < 42)
845             {
846               Int_t rowdiff = endRowBus[ibus] - startRowBus[ibus];
847               if(rowdiff > 16)
848                 {
849                   Int_t midrow = srow + 16;
850                   if (row >= midrow && row <= erow)
851                     {
852                       mcmno = 12 + (ecol - col)/4 + 1;
853                     }
854                   else if (row >= srow && row < midrow)
855                     {
856                       mcmno = (ecol - col)/4 + 1;
857                     }
858                 }
859               else if (rowdiff < 16)
860                 {
861                   mcmno = (ecol - col)/4 + 1;
862                 }
863             }
864
865         }
866     }
867
868
869 //____________________________________________________________________________
870
871 Int_t AliPMDDDLRawData::ComputeParity(UInt_t baseword)
872 {
873   // Generate the parity bit
874
875   Int_t count = 0;
876   for(Int_t j=0; j<29; j++)
877     {
878       if (baseword & 0x01 ) count++;
879       baseword >>= 1;
880     }
881   Int_t parity = count%2;
882   return parity;
883 }
884
885 //____________________________________________________________________________