]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONRawWriter.cxx
AliHMPIDDigitN no longer needed
[u/mrichter/AliRoot.git] / MUON / AliMUONRawWriter.cxx
CommitLineData
a19e2543 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
da8d4b6d 16/* $Id$ */
17
9265505b 18/// \class AliMUONRawWriter
19/// MUON Raw Data generaton in ALICE-MUON
20/// This class version 3 (further details could be found in Alice-note)
21///
22/// Implemented non-constant buspatch numbers for tracking
23/// with correct DDL id (first guess)
24/// (Ch. Finck, dec 2005)
25///
26/// Digits2Raw:
27/// Generates raw data for MUON tracker and finally for trigger
28/// Using real mapping (inverse) for tracker
29/// For trigger there is no mapping (mapping could be found in AliMUONTriggerCircuit)
30/// Ch. Finck, July 04
31/// Use memcpy instead of assignment elt by elt
32/// Introducing variable DSP numbers, real manu numbers per buspatch for st12
33/// Implemented scaler event for Trigger
34/// Ch. Finck, Jan. 06
35/// Using bus itr in DDL instead of simple incrementation
36/// treat correctly the DDL & buspatch for station 3.
37/// Using informations from AliMUONTriggerCrateStore for
38/// empty slots and non-notified cards in trigger crates.
39/// Ch. Finck, August 06.
a19e2543 40
2cbb173f 41#include "AliMUONRawWriter.h"
a19e2543 42
344ef20f 43#include "AliMUONBlockHeader.h"
44#include "AliMUONBusStruct.h"
a19e2543 45#include "AliMUONConstants.h"
2cf44ef3 46#include "AliMUONDarcHeader.h"
2cbb173f 47#include "AliMUONData.h"
48#include "AliMUONDigit.h"
344ef20f 49#include "AliMUONDspHeader.h"
2cbb173f 50#include "AliMUONGlobalTrigger.h"
344ef20f 51#include "AliMUONLocalStruct.h"
2cbb173f 52#include "AliMUONLocalTrigger.h"
a844d67f 53#include "AliMUONLocalTriggerBoard.h"
4798d385 54#include "AliMUONRegionalTrigger.h"
344ef20f 55#include "AliMUONRegHeader.h"
56#include "AliMUONTriggerCrate.h"
57#include "AliMUONTriggerCrateStore.h"
9265505b 58
344ef20f 59#include "AliMpBusPatch.h"
2cbb173f 60#include "AliMpDEManager.h"
344ef20f 61#include "AliMpExMap.h"
1c80232e 62#include "AliMpConstants.h"
a19e2543 63#include "AliMpPlaneType.h"
9265505b 64#include "AliMpSegmentation.h"
2cbb173f 65#include "AliMpStationType.h"
a19e2543 66#include "AliMpVSegmentation.h"
9265505b 67
344ef20f 68#include "AliRawReader.h"
9265505b 69#include "AliBitPacking.h"
70#include "AliDAQ.h"
71#include "AliLog.h"
72
73#include "TList.h"
a844d67f 74#include "TObjArray.h"
1c80232e 75#include "TStopwatch.h"
2cf44ef3 76
9265505b 77/// \cond CLASSIMP
a19e2543 78ClassImp(AliMUONRawWriter) // Class implementation in ROOT context
9265505b 79/// \endcond
ced309a5 80
81Int_t AliMUONRawWriter::fgManuPerBusSwp1B[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 224, 232};
82Int_t AliMUONRawWriter::fgManuPerBusSwp1NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 225, 233};
83
84Int_t AliMUONRawWriter::fgManuPerBusSwp2B[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 226, 246};
85Int_t AliMUONRawWriter::fgManuPerBusSwp2NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 227, 245};
86
344ef20f 87namespace
88{
89 enum ETimer { kWriteTracker, kWriteTrigger, kDigitLoop, kGetBusPatch, kTest, kLast };
90}
ced309a5 91
a19e2543 92//__________________________________________________________________________
2cbb173f 93AliMUONRawWriter::AliMUONRawWriter(AliMUONData* data)
9f5dcca3 94 : TObject(),
95 fMUONData(data),
9f5dcca3 96 fBlockHeader(new AliMUONBlockHeader()),
97 fDspHeader(new AliMUONDspHeader()),
9f5dcca3 98 fDarcHeader(new AliMUONDarcHeader()),
99 fRegHeader(new AliMUONRegHeader()),
100 fLocalStruct(new AliMUONLocalStruct()),
101 fBusPatchManager(new AliMpBusPatch()),
102 fCrateManager(new AliMUONTriggerCrateStore()),
103 fScalerEvent(kFALSE),
104 fHeader(),
9265505b 105 fTimers(new TStopwatch[kLast])
344ef20f 106
a19e2543 107{
9265505b 108 /// Standard Constructor
109
2cbb173f 110 AliDebug(1,"Standard ctor");
9f5dcca3 111 fFile[0] = fFile[1] = 0x0;
112 fFile[2] = fFile[3] = 0x0;
a19e2543 113
84ceeb06 114 // setting data key to default value (only for writting)
115 fBlockHeader->SetDataKey(fBlockHeader->GetDefaultDataKey());
116 fDspHeader->SetDataKey(fDspHeader->GetDefaultDataKey());
84ceeb06 117
a844d67f 118 // bus patch managers
a19e2543 119 fBusPatchManager->ReadBusPatchFile();
2cbb173f 120
a844d67f 121 // Crate manager
a844d67f 122 fCrateManager->ReadFromFile();
123
84ceeb06 124 // timers
344ef20f 125 for ( Int_t i = 0; i < kLast; ++i )
126 {
127 fTimers[i].Start(kTRUE);
128 fTimers[i].Stop();
129 }
2cbb173f 130
a19e2543 131}
132
133//__________________________________________________________________________
134AliMUONRawWriter::AliMUONRawWriter()
135 : TObject(),
136 fMUONData(0),
2cf44ef3 137 fBlockHeader(0),
138 fDspHeader(0),
2cf44ef3 139 fDarcHeader(0),
140 fRegHeader(0),
141 fLocalStruct(0),
ced309a5 142 fBusPatchManager(0),
a844d67f 143 fCrateManager(0x0),
2cbb173f 144 fScalerEvent(kFALSE),
9f5dcca3 145 fHeader(),
9265505b 146 fTimers(0)
a19e2543 147{
9265505b 148 /// Default Constructor
149
2cbb173f 150 AliDebug(1,"Default ctor");
151 fFile[0] = fFile[1] = 0x0;
1d81a83f 152 fFile[2] = fFile[3] = 0x0;
153
a19e2543 154}
155
a19e2543 156//__________________________________________________________________________
157AliMUONRawWriter::~AliMUONRawWriter(void)
158{
9265505b 159 /// Destructor
160
2cbb173f 161 AliDebug(1,"dtor");
162
2cf44ef3 163 delete fBlockHeader;
164 delete fDspHeader;
2cf44ef3 165 delete fDarcHeader;
166 delete fRegHeader;
167 delete fLocalStruct;
a19e2543 168
2cbb173f 169 delete fBusPatchManager;
a844d67f 170 delete fCrateManager;
171
344ef20f 172 for ( Int_t i = 0; i < kLast; ++i )
173 {
a7b01aa5 174 AliDebug(1, Form("Execution time (timer %d) : R:%7.2fs C:%7.2fs",i,
344ef20f 175 fTimers[i].RealTime(),fTimers[i].CpuTime()));
176 }
177
178 delete[] fTimers;
a19e2543 179}
2cbb173f 180
344ef20f 181//______________________________________________________________________________
182//void
183//AliMUONRawWriter::CheckDigits()
184//{
185// std::map<int,std::map<int,int> > m;
186//
187// for (Int_t iSt = 0; iSt < AliMUONConstants::NTrackingCh()/2; ++iSt)
188// {
189// for (Int_t iCh = iSt*2; iCh <= iSt*2 + 1; ++iCh)
190// {
191// TClonesArray* muonDigits = fMUONData->Digits(iCh);
192// for (Int_t idig = 0; idig < muonDigits->GetEntriesFast(); idig++)
193// {
194// AliMUONDigit* digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
195// Int_t busPatchId = GetBusPatch(*digit);
196// m[busPatchId][digit->ManuId()]++;
197// }
198// }
199// }
200//
201// std::map<int,std::map<int,int> >::const_iterator it;
202//
203// Int_t nManuMax(0);
204//
205// for ( it = m.begin(); it != m.end(); ++it )
206// {
207// AliDebug(1,Form("BusPatch %3d has %3d manus",it->first,it->second.size()));
208// nManuMax = std::max((Int_t)it->second.size(),nManuMax);
209// std::map<int,int>::const_iterator it2;
210// for ( it2 = it->second.begin(); it2 != it->second.end(); ++it2 )
211// {
212// AliDebug(1,Form(" BusPatch %3d Manu %4d Nch %3d",it->first,it2->first,it2->second));
213// }
214// }
215// AliDebug(1,Form("Max manus per busPatch : %3d",nManuMax));
216//}
217
a19e2543 218//____________________________________________________________________
219Int_t AliMUONRawWriter::Digits2Raw()
220{
9265505b 221 /// convert digits of the current event to raw data
222
a19e2543 223 Int_t idDDL;
1d81a83f 224 Char_t name[255];
a19e2543 225
2cbb173f 226 fMUONData->GetLoader()->LoadDigits("READ");
a19e2543 227
228 fMUONData->SetTreeAddress("D,GLT");
229
2cbb173f 230 fMUONData->ResetDigits();
231 fMUONData->ResetTrigger();
232
233 // This will get both tracker and trigger digits.
234 fMUONData->GetDigits();
235
344ef20f 236// CheckDigits();
a19e2543 237
344ef20f 238 // tracking chambers
239
240 for (Int_t iSt = 0; iSt < AliMUONConstants::NTrackingCh()/2; ++iSt) {
1d81a83f 241
242 // open files for one station
243 // cos station 3, 1/4 of DE's from 2 chambers has same DDL number
244 idDDL = iSt * 4;
362c9d61 245 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
a19e2543 246 fFile[0] = fopen(name,"w");
247
1d81a83f 248 idDDL = (iSt * 4) + 1;
362c9d61 249 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
a19e2543 250 fFile[1] = fopen(name,"w");
1d81a83f 251
252 idDDL = (iSt * 4) + 2;;
253 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
254 fFile[2] = fopen(name,"w");
255
256 idDDL = (iSt * 4) + 3;
257 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
258 fFile[3] = fopen(name,"w");
259
260 WriteTrackerDDL(iSt);
a19e2543 261
1d81a83f 262 // reset and close when station has been processed
a19e2543 263 fclose(fFile[0]);
264 fclose(fFile[1]);
1d81a83f 265 fclose(fFile[2]);
266 fclose(fFile[3]);
267
a19e2543 268 }
269
344ef20f 270 AliDebug(1,"Tracker written");
271
a19e2543 272 // trigger chambers
273
274 // open files
362c9d61 275 idDDL = 0;// MUTR
276 strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
a19e2543 277 fFile[0] = fopen(name,"w");
278
362c9d61 279 idDDL = 1;// MUTR
280 strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
a19e2543 281 fFile[1] = fopen(name,"w");
282
283 WriteTriggerDDL();
284
285 // reset and close
286 fclose(fFile[0]);
287 fclose(fFile[1]);
2cbb173f 288
344ef20f 289 AliDebug(1,"Trigger written");
290
2cbb173f 291 fMUONData->ResetDigits();
292 fMUONData->ResetTrigger();
293 fMUONData->GetLoader()->UnloadDigits();
a19e2543 294
344ef20f 295 AliDebug(1,"muondata reset");
296
a19e2543 297 return kTRUE;
298}
2cbb173f 299
a19e2543 300//____________________________________________________________________
1d81a83f 301Int_t AliMUONRawWriter::WriteTrackerDDL(Int_t iSt)
a19e2543 302{
9265505b 303 /// writing DDL for tracker
304 /// used inverse mapping
305
344ef20f 306 fTimers[kWriteTracker].Start(kFALSE);
2cbb173f 307
84aac932 308 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
2cf44ef3 309
a19e2543 310 // resets
311 TClonesArray* muonDigits = 0;
2cf44ef3 312
a19e2543 313 // DDL header
2cf44ef3 314 Int_t headerSize = sizeof(fHeader)/4;
315
316 // DDL event one per half chamber
a19e2543 317
2cf44ef3 318 // raw data
a19e2543 319 Char_t parity = 0x4;
320 UShort_t manuId = 0;
321 UChar_t channelId = 0;
322 UShort_t charge = 0;
323 Int_t busPatchId = 0;
a19e2543 324 UInt_t word;
2cf44ef3 325
84ceeb06 326
327 // Dsp length
328 Int_t totalDspLength;
329 Int_t dspLength;
330
2cf44ef3 331 // block length
332 Int_t totalBlkLength;
333 Int_t blkLength;
334
335 // total DDL length
336 Int_t totalDDLLength;
337
338 // indexes
a19e2543 339 Int_t index;
340 Int_t indexDsp;
341 Int_t indexBlk;
2cf44ef3 342
344ef20f 343 // buffer size (max'ed out)
344 // (((43 manus max per bus patch *64 channels + 4 bus patch words) * 5 bus patch
345 // + 10 dsp words)*5 dsps + 8 block words)*2 blocks
346 static const Int_t kBufferSize = (((43*64 + 4)*5 + 10)*5 + 8)*2;
347
a19e2543 348 Int_t nDigits;
349
344ef20f 350 AliMpExMap busPatchMap(kTRUE);
351
352 fTimers[kDigitLoop].Start(kFALSE);
353
354 for (Int_t iCh = iSt*2; iCh <= iSt*2 + 1; ++iCh) {
a19e2543 355
1d81a83f 356 muonDigits = fMUONData->Digits(iCh);
344ef20f 357
1d81a83f 358 nDigits = muonDigits->GetEntriesFast();
344ef20f 359
1d81a83f 360 // loop over digit
344ef20f 361 for (Int_t idig = 0; idig < nDigits; ++idig) {
362
363 AliMUONDigit* digit = static_cast<AliMUONDigit*>(muonDigits->UncheckedAt(idig));
364
1d81a83f 365 charge = digit->ADC();
366 if ( charge > kMAXADC )
344ef20f 367 {
368 // This is most probably an error in the digitizer (which should insure
369 // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
370 AliError(Form("adc value %d above %x for ch %d . Setting to %x. Digit is:",iCh,
371 charge,kMAXADC,kMAXADC));
372 StdoutToAliError(digit->Print());
373 charge = kMAXADC;
374 }
375
1d81a83f 376 // inverse mapping
344ef20f 377 fTimers[kGetBusPatch].Start(kFALSE);
1d81a83f 378 busPatchId = GetBusPatch(*digit);
344ef20f 379 fTimers[kGetBusPatch].Stop();
1d81a83f 380 if (busPatchId<0) continue;
344ef20f 381
1d81a83f 382 if ( digit->ManuId() > 0x7FF || digit->ManuId() < 0 ||
344ef20f 383 digit->ManuChannel() > 0x3F || digit->ManuChannel() < 0 )
384 {
385 StdoutToAliError(digit->Print(););
386 AliFatal("ManuId,ManuChannel are invalid for the digit above.");
387 }
388
1d81a83f 389 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
390 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
344ef20f 391
1d81a83f 392 //packing word
393 word = 0;
394 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
395 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
396 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
344ef20f 397
1d81a83f 398 // parity word
399 parity = word & 0x1;
344ef20f 400 for (Int_t i = 1; i <= 30; ++i)
401 parity ^= ((word >> i) & 0x1);
1d81a83f 402 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
344ef20f 403
404 AliMUONBusStruct* busStruct =
405 static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
406
407 if (!busStruct)
408 {
409 busStruct = new AliMUONBusStruct;
410 busStruct->SetDataKey(busStruct->GetDefaultDataKey());
411 busStruct->SetBusPatchId(busPatchId);
412 busStruct->SetLength(0);
413 busPatchMap.Add(busPatchId,busStruct);
f5439c77 414 }
a19e2543 415
344ef20f 416 // set sub Event
417 busStruct->AddData(word);
418
419 } // idig
420 } // loop over chamber in station
421
422 fTimers[kDigitLoop].Stop();
a19e2543 423
424 // getting info for the number of buspatches
425 Int_t iBusPatch;
426 Int_t length;
427 Int_t iBusPerDSP[5];//number of bus patches per DSP
428 Int_t iDspMax; //number max of DSP per block
a19e2543 429 Int_t iFile = 0;
a19e2543 430
344ef20f 431 AliMUONBusStruct* busStructPtr(0x0);
a19e2543 432
1d81a83f 433 // open DDL files, 4 per station
344ef20f 434 for (Int_t iDDL = iSt*4; iDDL < 4 + iSt*4; ++iDDL) {
a19e2543 435
1d81a83f 436 fBusPatchManager->ResetBusItr(iDDL);
437 fBusPatchManager->GetDspInfo(iDDL, iDspMax, iBusPerDSP);
84ceeb06 438
344ef20f 439 Int_t buffer[kBufferSize];
440
2cf44ef3 441 totalDDLLength = 0;
442
a19e2543 443 indexBlk = 0;
444 indexDsp = 0;
445 index = 0;
2cf44ef3 446
a19e2543 447 // two blocks A and B per DDL
344ef20f 448 for (Int_t iBlock = 0; iBlock < 2; ++iBlock) {
449
a19e2543 450 // block header
2cf44ef3 451 length = fBlockHeader->GetHeaderLength();
452 memcpy(&buffer[index],fBlockHeader->GetHeader(),length*4);
a19e2543 453 indexBlk = index;
454 index += length;
344ef20f 455
a19e2543 456 // 5 DSP's max per block
344ef20f 457 for (Int_t iDsp = 0; iDsp < iDspMax; ++iDsp) {
458
459 // DSP header
460 length = fDspHeader->GetHeaderLength();
461 memcpy(&buffer[index],fDspHeader->GetHeader(),length*4);
462 indexDsp = index;
463 index += length;
464
465 // 5 buspatches max per DSP
466 for (Int_t i = 0; i < iBusPerDSP[iDsp]; i++) {
467
468 iBusPatch = fBusPatchManager->NextBusInDDL(iDDL);
469
470 // iteration over bus patch in DDL
471 if (iBusPatch == -1) {
472 AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
473 continue;
474 }
475
476 // 4 DDL's per station, condition needed for station 3
477 iFile = iDDL - iSt*4; // works only if DDL begins at zero (as it should be) !!!
478
479 busStructPtr = static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(iBusPatch));
480
481 // check if buspatchid has digit
482 if (busStructPtr) {
483 // add bus patch structure header
484 length = busStructPtr->GetHeaderLength();
485 memcpy(&buffer[index],busStructPtr->GetHeader(),length*4);
486 index += length;
487
488 // add bus patch data
489 length = busStructPtr->GetLength();
490 memcpy(&buffer[index],busStructPtr->GetData(),length*4);
491 index += length;
492
493 if (AliLog::GetGlobalDebugLevel() == 3) {
494 for (Int_t j = 0; j < busStructPtr->GetLength(); j++) {
495 printf("busPatchId %d, manuId %d channelId %d\n", busStructPtr->GetBusPatchId(),
496 busStructPtr->GetManuId(j), busStructPtr->GetChannelId(j));
497 }
498 }
499 } else {
500 // writting anyhow buspatch structure (empty ones)
501 buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
502 buffer[index++] = busStructPtr->GetHeaderLength(); // header length
503 buffer[index++] = 0; // raw data length
504 buffer[index++] = iBusPatch; // bus patch
505 }
506 } // bus patch
507
508 // check if totalLength even
509 // set padding word in case
510 // Add one word 0xBEEFFACE at the end of DSP structure
511 totalDspLength = index - indexDsp;
512 if ((totalDspLength % 2) == 1) {
513 buffer[indexDsp + fDspHeader->GetHeaderLength() - 2] = 1;
514 buffer[index++] = fDspHeader->GetDefaultPaddingWord();
515 totalDspLength++;
516 }
517
518 dspLength = totalDspLength - fDspHeader->GetHeaderLength();
519
520 buffer[indexDsp+1] = totalDspLength; // dsp total length
521 buffer[indexDsp+2] = dspLength; // data length
522
a19e2543 523 } // dsp
344ef20f 524
2cf44ef3 525 totalBlkLength = index - indexBlk;
526 blkLength = totalBlkLength - fBlockHeader->GetHeaderLength();
527 totalDDLLength += totalBlkLength;
344ef20f 528
84ceeb06 529 buffer[indexBlk+1] = totalBlkLength; // total block length
530 buffer[indexBlk+2] = blkLength;
344ef20f 531
2cf44ef3 532 } // block
a19e2543 533
534 //writting onto disk
1d81a83f 535 // write DDL 1 - 4
344ef20f 536 // total length in bytes
537 fHeader.fSize = (totalDDLLength + headerSize) * 4;
538
2cf44ef3 539 fwrite((char*)(&fHeader),headerSize*4,1,fFile[iFile]);
a19e2543 540 fwrite(buffer,sizeof(int),index,fFile[iFile]);
a19e2543 541 }
344ef20f 542
543 fTimers[kWriteTracker].Stop();
a19e2543 544 return kTRUE;
545}
ced309a5 546
547//____________________________________________________________________
344ef20f 548Int_t AliMUONRawWriter::GetBusPatch(Int_t detElemId, Int_t manuId) const
ced309a5 549{
9265505b 550 /// Determine the BusPatch this digit belongs to.
2cbb173f 551
ced309a5 552 Int_t* ptr = 0;
344ef20f 553
554 AliMpPlaneType plane =
555 (manuId & AliMpConstants::ManuMask(kNonBendingPlane)) ?
556 kNonBendingPlane : kBendingPlane;
2cbb173f 557
2cbb173f 558 AliMpStationType stationType = AliMpDEManager::GetStationType(detElemId);
344ef20f 559
f6512e3a 560 if ( stationType == kStation1)
2cbb173f 561 {
562 if (plane == kBendingPlane)
563 {
564 ptr = &fgManuPerBusSwp1B[0];
565 }
566 else
567 {
568 ptr = &fgManuPerBusSwp1NB[0];
ced309a5 569 }
570 }
f6512e3a 571 else if ( stationType == kStation2)
2cbb173f 572 {
573 if (plane == kBendingPlane)
574 {
575 ptr = &fgManuPerBusSwp2B[0];
576 }
577 else
578 {
579 ptr = &fgManuPerBusSwp2NB[0];
580 }
ced309a5 581 }
344ef20f 582
ced309a5 583 // Getting buspatch id
2cbb173f 584 TArrayI* vec = fBusPatchManager->GetBusfromDE(detElemId);
ced309a5 585 Int_t pos = 0;
344ef20f 586
587 Int_t m = ( manuId & 0x3FF ); // remove bit 10
588 //FIXME : how can we remove that condition
589 // on the 10-th bit ? All the rest need not any knowledge about it,
590 // can't we find a way to get manu<->buspatch transparent to this too ?
2cbb173f 591
592 if ( stationType == kStation1 || stationType == kStation2 )
593 {
344ef20f 594 for (pos = 11; pos >=0 ; --pos)
2cbb173f 595 {
344ef20f 596 if (m >= ptr[pos]) break;
2cbb173f 597 }
598 }
599 else
600 {
ced309a5 601 // offset of 100 in manuId for following bus patch
2cbb173f 602 pos = m/100;
ced309a5 603 }
344ef20f 604
605
ced309a5 606 if (pos >(Int_t) vec->GetSize())
2cbb173f 607 {
608 AliError(Form("pos greater %d than size %d manuId %d detElemId %d \n",
344ef20f 609 pos, (Int_t)vec->GetSize(), manuId, detElemId));
2cbb173f 610 AliError(Form("Chamber %s Plane %s manuId %d m %d",
344ef20f 611 StationTypeName(stationType).Data(),
612 PlaneTypeName(plane).Data(),
613 manuId,
614 m));
2cbb173f 615 return -1;
616 }
ced309a5 617
2cbb173f 618 Int_t busPatchId = vec->At(pos);
344ef20f 619
620 if ( ( stationType == kStation1 || stationType == kStation2 ) &&
621 ( plane == kNonBendingPlane ) )
622 {
623 busPatchId += 12;
624 }
2cbb173f 625
626 return busPatchId;
ced309a5 627}
628
344ef20f 629//____________________________________________________________________
630Int_t AliMUONRawWriter::GetBusPatch(const AliMUONDigit& digit) const
631{
9265505b 632 /// Determine the BusPatch this digit belongs to.
633
344ef20f 634 return GetBusPatch(digit.DetElemId(),digit.ManuId());
635}
636
a19e2543 637//____________________________________________________________________
638Int_t AliMUONRawWriter::WriteTriggerDDL()
639{
9265505b 640 /// Write trigger DDL
641
344ef20f 642 fTimers[kWriteTrigger].Start(kFALSE);
2cbb173f 643
a19e2543 644 // DDL event one per half chamber
a19e2543 645
a19e2543 646 // stored local id number
647 TArrayI isFired(256);
648 isFired.Reset();
649
650
2cf44ef3 651 // DDL header size
652 Int_t headerSize = sizeof(AliRawDataHeader)/4;
ced309a5 653
a19e2543 654 TClonesArray* localTrigger;
655 TClonesArray* globalTrigger;
4798d385 656 TClonesArray* regionalTrigger;
657
a19e2543 658 AliMUONGlobalTrigger* gloTrg;
659 AliMUONLocalTrigger* locTrg = 0x0;
4798d385 660 AliMUONRegionalTrigger* regTrg = 0x0;
a19e2543 661
a19e2543 662 // global trigger for trigger pattern
663 globalTrigger = fMUONData->GlobalTrigger();
664 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
344ef20f 665 if (!gloTrg)
666 {
667 fTimers[kWriteTrigger].Stop();
668 return 0;
669 }
670
073695a9 671 Int_t gloTrigResp = gloTrg->GetGlobalResponse();
a19e2543 672
673 // local trigger
4798d385 674 localTrigger = fMUONData->LocalTrigger();
675
676
677 // regional trigger
678 regionalTrigger = fMUONData->RegionalTrigger();
679
a19e2543 680
681 UInt_t word;
682 Int_t* buffer = 0;
683 Int_t index;
684 Int_t iEntries = 0;
685 Int_t iLocCard, locCard;
bebe0279 686 Char_t locDec, trigY, posY, posX, regOut;
687 UInt_t regInpLpt;
688 UInt_t regInpHpt;
689
a19e2543 690 Int_t devX;
691 Int_t version = 1; // software version
d622a0ec 692 Int_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
a19e2543 693 Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
d622a0ec 694 Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
695
696 // size of headers
697 static const Int_t kDarcHeaderLength = fDarcHeader->GetDarcHeaderLength();
698 static const Int_t kGlobalHeaderLength = fDarcHeader->GetGlobalHeaderLength();
699 static const Int_t kDarcScalerLength = fDarcHeader->GetDarcScalerLength();
700 static const Int_t kGlobalScalerLength = fDarcHeader->GetGlobalScalerLength();
701 static const Int_t kRegHeaderLength = fRegHeader->GetHeaderLength();
702 static const Int_t kRegScalerLength = fRegHeader->GetScalerLength();
703 static const Int_t kLocHeaderLength = fLocalStruct->GetLength();
704 static const Int_t kLocScalerLength = fLocalStruct->GetScalerLength();
705
706 // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824
707 static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) + (kRegHeaderLength+1))* 8
708 + kDarcHeaderLength + kGlobalHeaderLength + 2;
709
710 // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
711 static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength + kLocScalerLength +1) +
712 (kRegHeaderLength + kRegScalerLength +1))* 8 +
713 (kDarcHeaderLength + kDarcScalerLength +
714 kGlobalHeaderLength + kGlobalScalerLength + 2);
ced309a5 715 if(fScalerEvent)
d622a0ec 716 eventPhys = 0; //set to generate scaler events
ced309a5 717
a19e2543 718 Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
719 // stored the local card id that's fired
720 for (Int_t i = 0; i < nEntries; i++) {
721 locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
722 isFired[locTrg->LoCircuit()] = 1; // storing local boards with informations
723 }
724
725 if (!nEntries)
a7b01aa5 726 AliDebug(1, "No Trigger information available");
a19e2543 727
ced309a5 728 if(fScalerEvent)
d622a0ec 729 buffer = new Int_t [kScalerBufferSize];
ced309a5 730 else
d622a0ec 731 buffer = new Int_t [kBufferSize];
ced309a5 732
a844d67f 733 // reset crate
a19e2543 734
735 // open DDL file, on per 1/2 chamber
736 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
a844d67f 737
a19e2543 738 index = 0;
739
a19e2543 740 if (iDDL == 0) // suppose global info in DDL one
a19e2543 741 globalFlag = 1;
d622a0ec 742 else
743 globalFlag = 0;
ced309a5 744
d622a0ec 745 word = 0;
746 // set darc status word
747 // see AliMUONDarcHeader.h for details
748 AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
749 AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
750 AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
751 AliBitPacking::PackWord((UInt_t)version,word,12,19);
2cf44ef3 752 fDarcHeader->SetWord(word);
18d3ded7 753
d622a0ec 754 memcpy(&buffer[index], fDarcHeader->GetHeader(), (kDarcHeaderLength)*4);
bebe0279 755 index += kDarcHeaderLength;
a19e2543 756
073695a9 757 // no global input for the moment....
a19e2543 758 if (iDDL == 0)
073695a9 759 fDarcHeader->SetGlobalOutput(gloTrigResp);
a19e2543 760 else
2cf44ef3 761 fDarcHeader->SetGlobalOutput(0);
ced309a5 762
763 if (fScalerEvent) {
764 // 6 DARC scaler words
d622a0ec 765 memcpy(&buffer[index], fDarcHeader->GetDarcScalers(),kDarcScalerLength*4);
bebe0279 766 index += kDarcScalerLength;
ced309a5 767 }
2cf44ef3 768 // end of darc word
769 buffer[index++] = fDarcHeader->GetEndOfDarc();
ced309a5 770
771 // 4 words of global board input + Global board output
d622a0ec 772 memcpy(&buffer[index], fDarcHeader->GetGlobalInput(), (kGlobalHeaderLength)*4);
bebe0279 773 index += kGlobalHeaderLength;
ced309a5 774
775 if (fScalerEvent) {
776 // 10 Global scaler words
d622a0ec 777 memcpy(fDarcHeader->GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
bebe0279 778 index += kGlobalScalerLength;
ced309a5 779 }
a19e2543 780
2cf44ef3 781 // end of global word
782 buffer[index++] = fDarcHeader->GetEndOfGlobal();
783
a19e2543 784 // 8 regional cards per DDL
785 for (Int_t iReg = 0; iReg < 8; iReg++) {
786
a844d67f 787 // crate info
aa6ecf89 788 AliMUONTriggerCrate* crate = fCrateManager->Crate(iDDL, iReg);
a844d67f 789
790 if (!crate)
791 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
792
4798d385 793 // regional info tree, make sure that no reg card missing
794 for (Int_t i = 0; i < 16; ++i) {
795 regTrg = (AliMUONRegionalTrigger*)regionalTrigger->At(i);
796 if (regTrg)
797 if (regTrg->GetId() == (iReg + iDDL*8)) break;
798 }
799
a19e2543 800 // Regional card header
801 word = 0;
00f56161 802
803 // set darc status word
804 fRegHeader->SetDarcWord(word);
805
4798d385 806 regOut = regTrg->GetOutput();
807 regInpHpt = regTrg->GetLocalOutput(0);
808 regInpLpt = regTrg->GetLocalOutput(1);
809
d622a0ec 810 // fill darc word, not darc status for the moment (empty)
811 //see AliMUONRegHeader.h for details
812 AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31);
813 AliBitPacking::PackWord((UInt_t)serialNb,word,19,24);
a19e2543 814 AliBitPacking::PackWord((UInt_t)version,word,16,23);
d622a0ec 815 AliBitPacking::PackWord((UInt_t)iReg,word,15,18);
4798d385 816 AliBitPacking::PackWord((UInt_t)regOut,word,0,7);
2cf44ef3 817 fRegHeader->SetWord(word);
d622a0ec 818
bebe0279 819
820 // fill header later, need local response
821 Int_t indexReg = index;
822 index += kRegHeaderLength;
a19e2543 823
ced309a5 824 // 11 regional scaler word
825 if (fScalerEvent) {
bebe0279 826 memcpy(&buffer[index], fRegHeader->GetScalers(), kRegScalerLength*4);
827 index += kRegScalerLength;
ced309a5 828 }
a19e2543 829
2cf44ef3 830 // end of regional word
831 buffer[index++] = fRegHeader->GetEndOfReg();
a844d67f 832
833 TObjArray *boards = crate->Boards();
834
2cf44ef3 835
a19e2543 836 // 16 local card per regional board
4798d385 837 // UShort_t localMask = 0x0;
8f4d1d7f 838
a19e2543 839 for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
840
a844d67f 841 // slot zero for Regional card
842 AliMUONLocalTriggerBoard* localBoard = (AliMUONLocalTriggerBoard*)boards->At(iLoc+1);
843
844 if (localBoard) { // if not empty slot
845
846 if ((iLocCard = localBoard->GetNumber()) != 0) {// if notified board
847
848 if (isFired[iLocCard]) { // if card has triggered
6a6a56b4 849 locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries++);
a844d67f 850 locCard = locTrg->LoCircuit();
851 locDec = locTrg->GetLoDecision();
852 trigY = 0;
bebe0279 853 posY = locTrg->LoStripY();
854 posX = locTrg->LoStripX();
855 devX = locTrg->LoDev();
856
a844d67f 857 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
858 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
859 } else { //no trigger (see PRR chpt 3.4)
a844d67f 860 locDec = 0;
861 trigY = 1;
862 posY = 15;
863 posX = 0;
864 devX = 0x8;
bebe0279 865 // set local card id to -1
866 locCard = -1;
a844d67f 867 }
8f4d1d7f 868
a844d67f 869 //packing word
870 word = 0;
871 AliBitPacking::PackWord((UInt_t)iLoc,word,19,22); //card id number in crate
872 AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
873 AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
874 AliBitPacking::PackWord((UInt_t)posY,word,10,13);
875 AliBitPacking::PackWord((UInt_t)devX,word,5,9);
876 AliBitPacking::PackWord((UInt_t)posX,word,0,4);
877
878 if (locCard == iLocCard) {
879 // add local cards structure
880 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
881 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
882 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
883 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
884 buffer[index++] = (Int_t)word; // data word
6a6a56b4 885
a844d67f 886 } else {
887 buffer[index++] = 0; // 4 words for x1, x2, y1, y2
888 buffer[index++] = 0;
889 buffer[index++] = 0;
890 buffer[index++] = 0;
891 buffer[index++] = (Int_t)word; // data word
892
893 }
894 } else {// number!=0
895 // fill with 10CDEAD word for 'non-notified' slots
896 for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
897 buffer[index++] = fLocalStruct->GetDisableWord();
898 }
899 } else {
900 // fill with 10CDEAD word for empty slots
901 for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
902 buffer[index++] = fLocalStruct->GetDisableWord();
903 }// condition localBoard
a19e2543 904
ced309a5 905 // 45 regional scaler word
906 if (fScalerEvent) {
bebe0279 907 memcpy(&buffer[index], fLocalStruct->GetScalers(), kLocScalerLength*4);
908 index += kLocScalerLength;
ced309a5 909 }
910
2cf44ef3 911 // end of local structure words
912 buffer[index++] = fLocalStruct->GetEndOfLocal();
a19e2543 913
2cf44ef3 914 } // local card
bebe0279 915 // fill regional header with local output
4798d385 916 fRegHeader->SetInput(regInpHpt, 0);
bebe0279 917 fRegHeader->SetInput(regInpHpt, 1);
bebe0279 918 memcpy(&buffer[indexReg],fRegHeader->GetHeader(),kRegHeaderLength*4);
a19e2543 919
920 } // Regional card
921
a19e2543 922
923 // writting onto disk
a844d67f 924 // write DDL's
2cf44ef3 925 fHeader.fSize = (index + headerSize) * 4;// total length in bytes
926 fwrite((char*)(&fHeader),headerSize*4,1,fFile[iDDL]);
a19e2543 927 fwrite(buffer,sizeof(int),index,fFile[iDDL]);
928
929 }
930 delete[] buffer;
931
344ef20f 932 fTimers[kWriteTrigger].Stop();
2cbb173f 933
ced309a5 934 return kTRUE;
a19e2543 935}
84ceeb06 936//____________________________________________________________________
937void AliMUONRawWriter::SetScalersNumbers()
938{
9265505b 939 /// set numbers for scaler events for trigger headers
940 /// since this is provided by the experiment
941 /// put dummy numbers to check the monitoring
84ceeb06 942
943 fDarcHeader->SetScalersNumbers();
944 fRegHeader->SetScalersNumbers();
945 fLocalStruct->SetScalersNumbers();
946
947 fScalerEvent = kTRUE;
948}
a844d67f 949