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