]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONRawWriter.cxx
- Use new AliMpDDLStore instead of previous BusPatch manager.
[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
e5ced899 59#include "AliMpDDLStore.h"
60#include "AliMpDDL.h"
61#include "AliMpDetElement.h"
2cbb173f 62#include "AliMpDEManager.h"
344ef20f 63#include "AliMpExMap.h"
1c80232e 64#include "AliMpConstants.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()),
e5ced899 103 fBusPatchManager(AliMpDDLStore::Instance()),
9f5dcca3 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 // Crate manager
a844d67f 121 fCrateManager->ReadFromFile();
122
84ceeb06 123 // timers
344ef20f 124 for ( Int_t i = 0; i < kLast; ++i )
125 {
126 fTimers[i].Start(kTRUE);
127 fTimers[i].Stop();
128 }
2cbb173f 129
a19e2543 130}
131
132//__________________________________________________________________________
133AliMUONRawWriter::AliMUONRawWriter()
134 : TObject(),
135 fMUONData(0),
2cf44ef3 136 fBlockHeader(0),
137 fDspHeader(0),
2cf44ef3 138 fDarcHeader(0),
139 fRegHeader(0),
140 fLocalStruct(0),
ced309a5 141 fBusPatchManager(0),
a844d67f 142 fCrateManager(0x0),
2cbb173f 143 fScalerEvent(kFALSE),
9f5dcca3 144 fHeader(),
9265505b 145 fTimers(0)
a19e2543 146{
9265505b 147 /// Default Constructor
148
2cbb173f 149 AliDebug(1,"Default ctor");
150 fFile[0] = fFile[1] = 0x0;
1d81a83f 151 fFile[2] = fFile[3] = 0x0;
152
a19e2543 153}
154
a19e2543 155//__________________________________________________________________________
156AliMUONRawWriter::~AliMUONRawWriter(void)
157{
9265505b 158 /// Destructor
159
2cbb173f 160 AliDebug(1,"dtor");
161
2cf44ef3 162 delete fBlockHeader;
163 delete fDspHeader;
2cf44ef3 164 delete fDarcHeader;
165 delete fRegHeader;
166 delete fLocalStruct;
a19e2543 167
a844d67f 168 delete fCrateManager;
169
344ef20f 170 for ( Int_t i = 0; i < kLast; ++i )
171 {
a7b01aa5 172 AliDebug(1, Form("Execution time (timer %d) : R:%7.2fs C:%7.2fs",i,
344ef20f 173 fTimers[i].RealTime(),fTimers[i].CpuTime()));
174 }
175
176 delete[] fTimers;
a19e2543 177}
2cbb173f 178
344ef20f 179//______________________________________________________________________________
180//void
181//AliMUONRawWriter::CheckDigits()
182//{
183// std::map<int,std::map<int,int> > m;
184//
185// for (Int_t iSt = 0; iSt < AliMUONConstants::NTrackingCh()/2; ++iSt)
186// {
187// for (Int_t iCh = iSt*2; iCh <= iSt*2 + 1; ++iCh)
188// {
189// TClonesArray* muonDigits = fMUONData->Digits(iCh);
190// for (Int_t idig = 0; idig < muonDigits->GetEntriesFast(); idig++)
191// {
192// AliMUONDigit* digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
193// Int_t busPatchId = GetBusPatch(*digit);
194// m[busPatchId][digit->ManuId()]++;
195// }
196// }
197// }
198//
199// std::map<int,std::map<int,int> >::const_iterator it;
200//
201// Int_t nManuMax(0);
202//
203// for ( it = m.begin(); it != m.end(); ++it )
204// {
205// AliDebug(1,Form("BusPatch %3d has %3d manus",it->first,it->second.size()));
206// nManuMax = std::max((Int_t)it->second.size(),nManuMax);
207// std::map<int,int>::const_iterator it2;
208// for ( it2 = it->second.begin(); it2 != it->second.end(); ++it2 )
209// {
210// AliDebug(1,Form(" BusPatch %3d Manu %4d Nch %3d",it->first,it2->first,it2->second));
211// }
212// }
213// AliDebug(1,Form("Max manus per busPatch : %3d",nManuMax));
214//}
215
a19e2543 216//____________________________________________________________________
217Int_t AliMUONRawWriter::Digits2Raw()
218{
9265505b 219 /// convert digits of the current event to raw data
220
a19e2543 221 Int_t idDDL;
1d81a83f 222 Char_t name[255];
a19e2543 223
2cbb173f 224 fMUONData->GetLoader()->LoadDigits("READ");
a19e2543 225
226 fMUONData->SetTreeAddress("D,GLT");
227
2cbb173f 228 fMUONData->ResetDigits();
229 fMUONData->ResetTrigger();
230
231 // This will get both tracker and trigger digits.
232 fMUONData->GetDigits();
233
344ef20f 234// CheckDigits();
a19e2543 235
344ef20f 236 // tracking chambers
237
238 for (Int_t iSt = 0; iSt < AliMUONConstants::NTrackingCh()/2; ++iSt) {
1d81a83f 239
240 // open files for one station
241 // cos station 3, 1/4 of DE's from 2 chambers has same DDL number
242 idDDL = iSt * 4;
362c9d61 243 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
a19e2543 244 fFile[0] = fopen(name,"w");
245
1d81a83f 246 idDDL = (iSt * 4) + 1;
362c9d61 247 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
a19e2543 248 fFile[1] = fopen(name,"w");
1d81a83f 249
250 idDDL = (iSt * 4) + 2;;
251 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
252 fFile[2] = fopen(name,"w");
253
254 idDDL = (iSt * 4) + 3;
255 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
256 fFile[3] = fopen(name,"w");
257
258 WriteTrackerDDL(iSt);
a19e2543 259
1d81a83f 260 // reset and close when station has been processed
a19e2543 261 fclose(fFile[0]);
262 fclose(fFile[1]);
1d81a83f 263 fclose(fFile[2]);
264 fclose(fFile[3]);
265
a19e2543 266 }
267
344ef20f 268 AliDebug(1,"Tracker written");
269
a19e2543 270 // trigger chambers
271
272 // open files
362c9d61 273 idDDL = 0;// MUTR
274 strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
a19e2543 275 fFile[0] = fopen(name,"w");
276
362c9d61 277 idDDL = 1;// MUTR
278 strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
a19e2543 279 fFile[1] = fopen(name,"w");
280
1afc1008 281 WriteTriggerDDL();
a19e2543 282
283 // reset and close
284 fclose(fFile[0]);
285 fclose(fFile[1]);
2cbb173f 286
344ef20f 287 AliDebug(1,"Trigger written");
288
2cbb173f 289 fMUONData->ResetDigits();
290 fMUONData->ResetTrigger();
291 fMUONData->GetLoader()->UnloadDigits();
a19e2543 292
344ef20f 293 AliDebug(1,"muondata reset");
294
a19e2543 295 return kTRUE;
296}
2cbb173f 297
a19e2543 298//____________________________________________________________________
1d81a83f 299Int_t AliMUONRawWriter::WriteTrackerDDL(Int_t iSt)
a19e2543 300{
9265505b 301 /// writing DDL for tracker
302 /// used inverse mapping
303
344ef20f 304 fTimers[kWriteTracker].Start(kFALSE);
2cbb173f 305
84aac932 306 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
2cf44ef3 307
a19e2543 308 // resets
309 TClonesArray* muonDigits = 0;
2cf44ef3 310
a19e2543 311 // DDL header
2cf44ef3 312 Int_t headerSize = sizeof(fHeader)/4;
313
314 // DDL event one per half chamber
a19e2543 315
2cf44ef3 316 // raw data
a19e2543 317 Char_t parity = 0x4;
318 UShort_t manuId = 0;
319 UChar_t channelId = 0;
320 UShort_t charge = 0;
321 Int_t busPatchId = 0;
a19e2543 322 UInt_t word;
2cf44ef3 323
84ceeb06 324
325 // Dsp length
326 Int_t totalDspLength;
327 Int_t dspLength;
328
2cf44ef3 329 // block length
330 Int_t totalBlkLength;
331 Int_t blkLength;
332
333 // total DDL length
334 Int_t totalDDLLength;
335
336 // indexes
a19e2543 337 Int_t index;
338 Int_t indexDsp;
339 Int_t indexBlk;
2cf44ef3 340
344ef20f 341 // buffer size (max'ed out)
342 // (((43 manus max per bus patch *64 channels + 4 bus patch words) * 5 bus patch
343 // + 10 dsp words)*5 dsps + 8 block words)*2 blocks
344 static const Int_t kBufferSize = (((43*64 + 4)*5 + 10)*5 + 8)*2;
345
a19e2543 346 Int_t nDigits;
347
344ef20f 348 AliMpExMap busPatchMap(kTRUE);
349
350 fTimers[kDigitLoop].Start(kFALSE);
351
352 for (Int_t iCh = iSt*2; iCh <= iSt*2 + 1; ++iCh) {
a19e2543 353
1d81a83f 354 muonDigits = fMUONData->Digits(iCh);
344ef20f 355
1d81a83f 356 nDigits = muonDigits->GetEntriesFast();
344ef20f 357
1d81a83f 358 // loop over digit
344ef20f 359 for (Int_t idig = 0; idig < nDigits; ++idig) {
360
361 AliMUONDigit* digit = static_cast<AliMUONDigit*>(muonDigits->UncheckedAt(idig));
362
1d81a83f 363 charge = digit->ADC();
364 if ( charge > kMAXADC )
344ef20f 365 {
366 // This is most probably an error in the digitizer (which should insure
367 // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
368 AliError(Form("adc value %d above %x for ch %d . Setting to %x. Digit is:",iCh,
369 charge,kMAXADC,kMAXADC));
370 StdoutToAliError(digit->Print());
371 charge = kMAXADC;
372 }
373
1d81a83f 374 // inverse mapping
344ef20f 375 fTimers[kGetBusPatch].Start(kFALSE);
1d81a83f 376 busPatchId = GetBusPatch(*digit);
344ef20f 377 fTimers[kGetBusPatch].Stop();
1d81a83f 378 if (busPatchId<0) continue;
344ef20f 379
1d81a83f 380 if ( digit->ManuId() > 0x7FF || digit->ManuId() < 0 ||
344ef20f 381 digit->ManuChannel() > 0x3F || digit->ManuChannel() < 0 )
382 {
383 StdoutToAliError(digit->Print(););
384 AliFatal("ManuId,ManuChannel are invalid for the digit above.");
385 }
386
1d81a83f 387 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
388 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
344ef20f 389
1d81a83f 390 //packing word
391 word = 0;
392 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
393 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
394 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
344ef20f 395
1d81a83f 396 // parity word
397 parity = word & 0x1;
344ef20f 398 for (Int_t i = 1; i <= 30; ++i)
399 parity ^= ((word >> i) & 0x1);
1d81a83f 400 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
344ef20f 401
402 AliMUONBusStruct* busStruct =
403 static_cast<AliMUONBusStruct*>(busPatchMap.GetValue(busPatchId));
404
405 if (!busStruct)
406 {
407 busStruct = new AliMUONBusStruct;
408 busStruct->SetDataKey(busStruct->GetDefaultDataKey());
409 busStruct->SetBusPatchId(busPatchId);
410 busStruct->SetLength(0);
411 busPatchMap.Add(busPatchId,busStruct);
f5439c77 412 }
a19e2543 413
344ef20f 414 // set sub Event
415 busStruct->AddData(word);
416
417 } // idig
418 } // loop over chamber in station
419
420 fTimers[kDigitLoop].Stop();
a19e2543 421
422 // getting info for the number of buspatches
423 Int_t iBusPatch;
424 Int_t length;
425 Int_t iBusPerDSP[5];//number of bus patches per DSP
426 Int_t iDspMax; //number max of DSP per block
a19e2543 427 Int_t iFile = 0;
a19e2543 428
344ef20f 429 AliMUONBusStruct* busStructPtr(0x0);
a19e2543 430
1d81a83f 431 // open DDL files, 4 per station
344ef20f 432 for (Int_t iDDL = iSt*4; iDDL < 4 + iSt*4; ++iDDL) {
a19e2543 433
e5ced899 434 AliMpDDL* ddl = fBusPatchManager->GetDDL(iDDL);
435 iDspMax = ddl->GetMaxDsp();
436 ddl->GetBusPerDsp(iBusPerDSP);
437 Int_t busIter = 0;
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
e5ced899 468 iBusPatch = ddl->GetBusPatchId(busIter++);
344ef20f 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
e5ced899 554 AliMp::PlaneType plane =
555 (manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane)) ?
556 AliMp::kNonBendingPlane : AliMp::kBendingPlane;
2cbb173f 557
e5ced899 558 AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
344ef20f 559
e5ced899 560 if ( stationType == AliMp::kStation1)
2cbb173f 561 {
e5ced899 562 if (plane == AliMp::kBendingPlane)
2cbb173f 563 {
564 ptr = &fgManuPerBusSwp1B[0];
565 }
566 else
567 {
568 ptr = &fgManuPerBusSwp1NB[0];
ced309a5 569 }
570 }
e5ced899 571 else if ( stationType == AliMp::kStation2)
2cbb173f 572 {
e5ced899 573 if (plane == AliMp::kBendingPlane)
2cbb173f 574 {
575 ptr = &fgManuPerBusSwp2B[0];
576 }
577 else
578 {
579 ptr = &fgManuPerBusSwp2NB[0];
580 }
ced309a5 581 }
344ef20f 582
ced309a5 583 // Getting buspatch id
e5ced899 584 AliMpDetElement* detElement = fBusPatchManager->GetDetElement(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
e5ced899 592 if ( stationType == AliMp::kStation1 || stationType == AliMp::kStation2 )
2cbb173f 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
e5ced899 606 if (pos > detElement->GetNofBusPatches())
2cbb173f 607 {
608 AliError(Form("pos greater %d than size %d manuId %d detElemId %d \n",
e5ced899 609 // pos, (Int_t)vec->GetSize(), manuId, detElemId));
610 pos, detElement->GetNofBusPatches(), manuId, detElemId));
2cbb173f 611 AliError(Form("Chamber %s Plane %s manuId %d m %d",
e5ced899 612 AliMp::StationTypeName(stationType).Data(),
613 AliMp::PlaneTypeName(plane).Data(),
344ef20f 614 manuId,
615 m));
2cbb173f 616 return -1;
617 }
ced309a5 618
e5ced899 619 Int_t busPatchId = detElement->GetBusPatchId(pos); // ???? CHECK
344ef20f 620
e5ced899 621 if ( ( stationType == AliMp::kStation1 || stationType == AliMp::kStation2 ) &&
622 ( plane == AliMp::kNonBendingPlane ) )
344ef20f 623 {
624 busPatchId += 12;
625 }
2cbb173f 626
627 return busPatchId;
ced309a5 628}
629
344ef20f 630//____________________________________________________________________
631Int_t AliMUONRawWriter::GetBusPatch(const AliMUONDigit& digit) const
632{
9265505b 633 /// Determine the BusPatch this digit belongs to.
634
344ef20f 635 return GetBusPatch(digit.DetElemId(),digit.ManuId());
636}
637
a19e2543 638//____________________________________________________________________
639Int_t AliMUONRawWriter::WriteTriggerDDL()
640{
9265505b 641 /// Write trigger DDL
642
344ef20f 643 fTimers[kWriteTrigger].Start(kFALSE);
2cbb173f 644
a19e2543 645 // DDL event one per half chamber
a19e2543 646
a19e2543 647 // stored local id number
648 TArrayI isFired(256);
649 isFired.Reset();
650
651
2cf44ef3 652 // DDL header size
653 Int_t headerSize = sizeof(AliRawDataHeader)/4;
ced309a5 654
a19e2543 655 TClonesArray* localTrigger;
656 TClonesArray* globalTrigger;
4798d385 657 TClonesArray* regionalTrigger;
658
a19e2543 659 AliMUONGlobalTrigger* gloTrg;
660 AliMUONLocalTrigger* locTrg = 0x0;
4798d385 661 AliMUONRegionalTrigger* regTrg = 0x0;
a19e2543 662
a19e2543 663 // global trigger for trigger pattern
664 globalTrigger = fMUONData->GlobalTrigger();
665 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
344ef20f 666 if (!gloTrg)
667 {
668 fTimers[kWriteTrigger].Stop();
669 return 0;
670 }
671
073695a9 672 Int_t gloTrigResp = gloTrg->GetGlobalResponse();
a19e2543 673
674 // local trigger
4798d385 675 localTrigger = fMUONData->LocalTrigger();
676
677
678 // regional trigger
679 regionalTrigger = fMUONData->RegionalTrigger();
680
a19e2543 681
682 UInt_t word;
683 Int_t* buffer = 0;
684 Int_t index;
685 Int_t iEntries = 0;
686 Int_t iLocCard, locCard;
1afc1008 687 UChar_t locDec, trigY, posY, posX, regOut;
bebe0279 688 UInt_t regInpLpt;
689 UInt_t regInpHpt;
690
1afc1008 691 UInt_t devX;
692 UInt_t version = 1; // software version
693 UInt_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
694 UInt_t serialNb = 0xF; // serial nb of card: all bits on for the moment
d622a0ec 695 Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
696
697 // size of headers
698 static const Int_t kDarcHeaderLength = fDarcHeader->GetDarcHeaderLength();
699 static const Int_t kGlobalHeaderLength = fDarcHeader->GetGlobalHeaderLength();
700 static const Int_t kDarcScalerLength = fDarcHeader->GetDarcScalerLength();
701 static const Int_t kGlobalScalerLength = fDarcHeader->GetGlobalScalerLength();
702 static const Int_t kRegHeaderLength = fRegHeader->GetHeaderLength();
703 static const Int_t kRegScalerLength = fRegHeader->GetScalerLength();
704 static const Int_t kLocHeaderLength = fLocalStruct->GetLength();
705 static const Int_t kLocScalerLength = fLocalStruct->GetScalerLength();
706
707 // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824
708 static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) + (kRegHeaderLength+1))* 8
709 + kDarcHeaderLength + kGlobalHeaderLength + 2;
710
711 // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
712 static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength + kLocScalerLength +1) +
713 (kRegHeaderLength + kRegScalerLength +1))* 8 +
714 (kDarcHeaderLength + kDarcScalerLength +
715 kGlobalHeaderLength + kGlobalScalerLength + 2);
ced309a5 716 if(fScalerEvent)
d622a0ec 717 eventPhys = 0; //set to generate scaler events
ced309a5 718
a19e2543 719 Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
720 // stored the local card id that's fired
721 for (Int_t i = 0; i < nEntries; i++) {
722 locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
723 isFired[locTrg->LoCircuit()] = 1; // storing local boards with informations
724 }
725
726 if (!nEntries)
a7b01aa5 727 AliDebug(1, "No Trigger information available");
a19e2543 728
ced309a5 729 if(fScalerEvent)
d622a0ec 730 buffer = new Int_t [kScalerBufferSize];
ced309a5 731 else
d622a0ec 732 buffer = new Int_t [kBufferSize];
ced309a5 733
a844d67f 734 // reset crate
a19e2543 735
736 // open DDL file, on per 1/2 chamber
737 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
a844d67f 738
a19e2543 739 index = 0;
740
a19e2543 741 if (iDDL == 0) // suppose global info in DDL one
a19e2543 742 globalFlag = 1;
d622a0ec 743 else
744 globalFlag = 0;
ced309a5 745
d622a0ec 746 word = 0;
747 // set darc status word
748 // see AliMUONDarcHeader.h for details
749 AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
750 AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
751 AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
752 AliBitPacking::PackWord((UInt_t)version,word,12,19);
2cf44ef3 753 fDarcHeader->SetWord(word);
18d3ded7 754
d622a0ec 755 memcpy(&buffer[index], fDarcHeader->GetHeader(), (kDarcHeaderLength)*4);
bebe0279 756 index += kDarcHeaderLength;
a19e2543 757
073695a9 758 // no global input for the moment....
a19e2543 759 if (iDDL == 0)
073695a9 760 fDarcHeader->SetGlobalOutput(gloTrigResp);
a19e2543 761 else
2cf44ef3 762 fDarcHeader->SetGlobalOutput(0);
ced309a5 763
764 if (fScalerEvent) {
765 // 6 DARC scaler words
d622a0ec 766 memcpy(&buffer[index], fDarcHeader->GetDarcScalers(),kDarcScalerLength*4);
bebe0279 767 index += kDarcScalerLength;
ced309a5 768 }
2cf44ef3 769 // end of darc word
770 buffer[index++] = fDarcHeader->GetEndOfDarc();
ced309a5 771
772 // 4 words of global board input + Global board output
d622a0ec 773 memcpy(&buffer[index], fDarcHeader->GetGlobalInput(), (kGlobalHeaderLength)*4);
bebe0279 774 index += kGlobalHeaderLength;
ced309a5 775
776 if (fScalerEvent) {
777 // 10 Global scaler words
d622a0ec 778 memcpy(fDarcHeader->GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
bebe0279 779 index += kGlobalScalerLength;
ced309a5 780 }
a19e2543 781
2cf44ef3 782 // end of global word
783 buffer[index++] = fDarcHeader->GetEndOfGlobal();
784
a19e2543 785 // 8 regional cards per DDL
786 for (Int_t iReg = 0; iReg < 8; iReg++) {
787
a844d67f 788 // crate info
aa6ecf89 789 AliMUONTriggerCrate* crate = fCrateManager->Crate(iDDL, iReg);
a844d67f 790
791 if (!crate)
792 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
793
4798d385 794 // regional info tree, make sure that no reg card missing
795 for (Int_t i = 0; i < 16; ++i) {
796 regTrg = (AliMUONRegionalTrigger*)regionalTrigger->At(i);
797 if (regTrg)
798 if (regTrg->GetId() == (iReg + iDDL*8)) break;
799 }
800
a19e2543 801 // Regional card header
802 word = 0;
00f56161 803
804 // set darc status word
805 fRegHeader->SetDarcWord(word);
806
4798d385 807 regOut = regTrg->GetOutput();
808 regInpHpt = regTrg->GetLocalOutput(0);
809 regInpLpt = regTrg->GetLocalOutput(1);
810
d622a0ec 811 // fill darc word, not darc status for the moment (empty)
812 //see AliMUONRegHeader.h for details
813 AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31);
814 AliBitPacking::PackWord((UInt_t)serialNb,word,19,24);
a19e2543 815 AliBitPacking::PackWord((UInt_t)version,word,16,23);
d622a0ec 816 AliBitPacking::PackWord((UInt_t)iReg,word,15,18);
4798d385 817 AliBitPacking::PackWord((UInt_t)regOut,word,0,7);
2cf44ef3 818 fRegHeader->SetWord(word);
d622a0ec 819
bebe0279 820
821 // fill header later, need local response
822 Int_t indexReg = index;
823 index += kRegHeaderLength;
a19e2543 824
ced309a5 825 // 11 regional scaler word
826 if (fScalerEvent) {
bebe0279 827 memcpy(&buffer[index], fRegHeader->GetScalers(), kRegScalerLength*4);
828 index += kRegScalerLength;
ced309a5 829 }
a19e2543 830
2cf44ef3 831 // end of regional word
832 buffer[index++] = fRegHeader->GetEndOfReg();
a844d67f 833
834 TObjArray *boards = crate->Boards();
835
2cf44ef3 836
a19e2543 837 // 16 local card per regional board
4798d385 838 // UShort_t localMask = 0x0;
8f4d1d7f 839
a19e2543 840 for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
841
a844d67f 842 // slot zero for Regional card
843 AliMUONLocalTriggerBoard* localBoard = (AliMUONLocalTriggerBoard*)boards->At(iLoc+1);
844
845 if (localBoard) { // if not empty slot
846
847 if ((iLocCard = localBoard->GetNumber()) != 0) {// if notified board
848
849 if (isFired[iLocCard]) { // if card has triggered
6a6a56b4 850 locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries++);
a844d67f 851 locCard = locTrg->LoCircuit();
852 locDec = locTrg->GetLoDecision();
853 trigY = 0;
bebe0279 854 posY = locTrg->LoStripY();
855 posX = locTrg->LoStripX();
856 devX = locTrg->LoDev();
857
a844d67f 858 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
859 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
860 } else { //no trigger (see PRR chpt 3.4)
a844d67f 861 locDec = 0;
862 trigY = 1;
863 posY = 15;
864 posX = 0;
865 devX = 0x8;
bebe0279 866 // set local card id to -1
867 locCard = -1;
a844d67f 868 }
8f4d1d7f 869
a844d67f 870 //packing word
871 word = 0;
872 AliBitPacking::PackWord((UInt_t)iLoc,word,19,22); //card id number in crate
873 AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
874 AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
875 AliBitPacking::PackWord((UInt_t)posY,word,10,13);
876 AliBitPacking::PackWord((UInt_t)devX,word,5,9);
877 AliBitPacking::PackWord((UInt_t)posX,word,0,4);
878
879 if (locCard == iLocCard) {
880 // add local cards structure
881 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
882 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
883 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
884 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
885 buffer[index++] = (Int_t)word; // data word
6a6a56b4 886
a844d67f 887 } else {
888 buffer[index++] = 0; // 4 words for x1, x2, y1, y2
889 buffer[index++] = 0;
890 buffer[index++] = 0;
891 buffer[index++] = 0;
892 buffer[index++] = (Int_t)word; // data word
893
894 }
895 } else {// number!=0
896 // fill with 10CDEAD word for 'non-notified' slots
897 for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
898 buffer[index++] = fLocalStruct->GetDisableWord();
899 }
900 } else {
901 // fill with 10CDEAD word for empty slots
902 for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
903 buffer[index++] = fLocalStruct->GetDisableWord();
904 }// condition localBoard
a19e2543 905
ced309a5 906 // 45 regional scaler word
907 if (fScalerEvent) {
bebe0279 908 memcpy(&buffer[index], fLocalStruct->GetScalers(), kLocScalerLength*4);
909 index += kLocScalerLength;
ced309a5 910 }
911
2cf44ef3 912 // end of local structure words
913 buffer[index++] = fLocalStruct->GetEndOfLocal();
a19e2543 914
2cf44ef3 915 } // local card
bebe0279 916 // fill regional header with local output
4798d385 917 fRegHeader->SetInput(regInpHpt, 0);
bebe0279 918 fRegHeader->SetInput(regInpHpt, 1);
bebe0279 919 memcpy(&buffer[indexReg],fRegHeader->GetHeader(),kRegHeaderLength*4);
a19e2543 920
921 } // Regional card
922
a19e2543 923
924 // writting onto disk
a844d67f 925 // write DDL's
2cf44ef3 926 fHeader.fSize = (index + headerSize) * 4;// total length in bytes
927 fwrite((char*)(&fHeader),headerSize*4,1,fFile[iDDL]);
a19e2543 928 fwrite(buffer,sizeof(int),index,fFile[iDDL]);
929
930 }
931 delete[] buffer;
932
344ef20f 933 fTimers[kWriteTrigger].Stop();
2cbb173f 934
ced309a5 935 return kTRUE;
a19e2543 936}
84ceeb06 937//____________________________________________________________________
938void AliMUONRawWriter::SetScalersNumbers()
939{
9265505b 940 /// set numbers for scaler events for trigger headers
941 /// since this is provided by the experiment
942 /// put dummy numbers to check the monitoring
84ceeb06 943
944 fDarcHeader->SetScalersNumbers();
945 fRegHeader->SetScalersNumbers();
946 fLocalStruct->SetScalersNumbers();
947
948 fScalerEvent = kTRUE;
949}
a844d67f 950