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