1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ////////////////////////////////////
20 // MUON Raw Data generaton in ALICE-MUON
21 // This class version 3 (further details could be found in Alice-note)
23 // Implemented non-constant buspatch numbers for tracking
24 // with correct DDL id (first guess)
25 // (Ch. Finck, dec 2005)
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)
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
36 // Using bus itr in DDL instead of simple incrementation
37 // treat correctly the DDL & buspatch for station 3.
38 // Using informations from AliMUONTriggerCrateStore for
39 // empty slots and non-notified cards in trigger crates.
40 // Ch. Finck, August 06.
42 ////////////////////////////////////
44 #include "AliMUONRawWriter.h"
46 #include "AliBitPacking.h"
47 #include "AliRawReader.h"
51 #include "AliMUONConstants.h"
53 #include "AliMUONDarcHeader.h"
54 #include "AliMUONRegHeader.h"
55 #include "AliMUONLocalStruct.h"
56 #include "AliMUONDspHeader.h"
57 #include "AliMUONBlockHeader.h"
59 #include "AliMUONData.h"
60 #include "AliMUONDigit.h"
61 #include "AliMUONGlobalTrigger.h"
62 #include "AliMUONLocalTrigger.h"
64 #include "AliMpBusPatch.h"
65 #include "AliMUONTriggerCrateStore.h"
66 #include "AliMUONTriggerCrate.h"
67 #include "AliMUONLocalTriggerBoard.h"
69 #include "AliMpDEManager.h"
71 #include "AliMpPlaneType.h"
72 #include "AliMpSegFactory.h"
73 #include "AliMpStationType.h"
74 #include "AliMpVSegmentation.h"
76 #include "TClonesArray.h"
77 #include "TObjArray.h"
79 ClassImp(AliMUONRawWriter) // Class implementation in ROOT context
81 Int_t AliMUONRawWriter::fgManuPerBusSwp1B[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 224, 232};
82 Int_t AliMUONRawWriter::fgManuPerBusSwp1NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 225, 233};
84 Int_t AliMUONRawWriter::fgManuPerBusSwp2B[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 226, 246};
85 Int_t AliMUONRawWriter::fgManuPerBusSwp2NB[12] = {1, 27, 53, 79, 105, 131, 157, 183, 201, 214, 227, 245};
88 //__________________________________________________________________________
89 AliMUONRawWriter::AliMUONRawWriter(AliMUONData* data)
92 fBusArray(new TClonesArray("AliMUONBusStruct",1000)),
93 fBlockHeader(new AliMUONBlockHeader()),
94 fDspHeader(new AliMUONDspHeader()),
95 fBusStruct(new AliMUONBusStruct()),
96 fDarcHeader(new AliMUONDarcHeader()),
97 fRegHeader(new AliMUONRegHeader()),
98 fLocalStruct(new AliMUONLocalStruct()),
99 fBusPatchManager(new AliMpBusPatch()),
100 fCrateManager(new AliMUONTriggerCrateStore()),
101 fScalerEvent(kFALSE),
106 fSegFactory(new AliMpSegFactory())
110 // Standard Constructor
112 AliDebug(1,"Standard ctor");
113 fFile[0] = fFile[1] = 0x0;
114 fFile[2] = fFile[3] = 0x0;
117 fBusArray->SetOwner(kTRUE);
119 // setting data key to default value (only for writting)
120 fBlockHeader->SetDataKey(fBlockHeader->GetDefaultDataKey());
121 fDspHeader->SetDataKey(fDspHeader->GetDefaultDataKey());
122 fBusStruct->SetDataKey(fBusStruct->GetDefaultDataKey());
124 // bus patch managers
125 fBusPatchManager->ReadBusPatchFile();
128 fCrateManager->ReadFromFile();
131 fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
132 fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
133 fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
137 //__________________________________________________________________________
138 AliMUONRawWriter::AliMUONRawWriter()
150 fScalerEvent(kFALSE),
158 // Default Constructor
160 AliDebug(1,"Default ctor");
161 fFile[0] = fFile[1] = 0x0;
162 fFile[2] = fFile[3] = 0x0;
164 fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
165 fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
166 fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
169 //__________________________________________________________________________
170 AliMUONRawWriter::~AliMUONRawWriter(void)
186 delete fBusPatchManager;
187 delete fCrateManager;
191 AliInfo(Form("Execution time for MUON tracker : R:%.2fs C:%.2fs",
192 fTrackerTimer.RealTime(),fTrackerTimer.CpuTime()));
193 AliInfo(Form(" Execution time for MUON tracker (mapping calls part) "
195 fMappingTimer.RealTime(),fMappingTimer.CpuTime()));
196 AliInfo(Form("Execution time for MUON trigger : R:%.2fs C:%.2fs",
197 fTriggerTimer.RealTime(),fTriggerTimer.CpuTime()));
200 //____________________________________________________________________
201 Int_t AliMUONRawWriter::Digits2Raw()
204 // convert digits of the current event to raw data
209 fMUONData->GetLoader()->LoadDigits("READ");
211 fMUONData->SetTreeAddress("D,GLT");
213 fMUONData->ResetDigits();
214 fMUONData->ResetTrigger();
216 // This will get both tracker and trigger digits.
217 fMUONData->GetDigits();
221 for (Int_t iSt = 0; iSt < AliMUONConstants::NTrackingCh()/2; iSt++) {
223 // open files for one station
224 // cos station 3, 1/4 of DE's from 2 chambers has same DDL number
226 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
227 fFile[0] = fopen(name,"w");
229 idDDL = (iSt * 4) + 1;
230 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
231 fFile[1] = fopen(name,"w");
233 idDDL = (iSt * 4) + 2;;
234 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
235 fFile[2] = fopen(name,"w");
237 idDDL = (iSt * 4) + 3;
238 strcpy(name,AliDAQ::DdlFileName("MUONTRK",idDDL));
239 fFile[3] = fopen(name,"w");
241 WriteTrackerDDL(iSt);
243 // reset and close when station has been processed
255 strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
256 fFile[0] = fopen(name,"w");
259 strcpy(name,AliDAQ::DdlFileName("MUONTRG",idDDL));
260 fFile[1] = fopen(name,"w");
268 fMUONData->ResetDigits();
269 fMUONData->ResetTrigger();
270 fMUONData->GetLoader()->UnloadDigits();
275 //____________________________________________________________________
276 Int_t AliMUONRawWriter::WriteTrackerDDL(Int_t iSt)
278 // writing DDL for tracker
279 // used inverse mapping
281 fTrackerTimer.Start(kFALSE);
284 static const Int_t kMAXADC = (1<<12)-1; // We code the charge on a 12 bits ADC.
287 TClonesArray* muonDigits = 0;
300 Int_t headerSize = sizeof(fHeader)/4;
302 // DDL event one per half chamber
307 UChar_t channelId = 0;
309 Int_t busPatchId = 0;
314 Int_t totalDspLength;
318 Int_t totalBlkLength;
322 Int_t totalDDLLength;
338 const AliMUONDigit* digit;
340 for (Int_t iCh = iSt*2; iCh <= iSt*2 + 1; iCh++) {
342 muonDigits = fMUONData->Digits(iCh);
344 nDigits = muonDigits->GetEntriesFast();
345 AliDebug(3,Form("ndigits = %d\n",nDigits));
348 for (Int_t idig = 0; idig < nDigits; idig++) {
350 digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
352 padX = digit->PadX();
353 padY = digit->PadY();
354 charge = digit->ADC();
355 if ( charge > kMAXADC )
357 // This is most probably an error in the digitizer (which should insure
358 // the adc is below kMAXADC), so make it a (non-fatal) error indeed.
359 AliError(Form("adc value %d above %x. Setting to %x",
360 charge,kMAXADC,kMAXADC));
363 cathode = digit->Cathode();
364 detElemId = digit->DetElemId();
367 busPatchId = GetBusPatch(*digit);
368 if (busPatchId<0) continue;
370 if ( digit->ManuId() > 0x7FF || digit->ManuId() < 0 ||
371 digit->ManuChannel() > 0x3F || digit->ManuChannel() < 0 )
373 StdoutToAliError(digit->Print(););
374 AliFatal("ManuId,ManuChannel are invalid for the digit above.");
377 manuId = ( digit->ManuId() & 0x7FF ); // 11 bits
378 channelId = ( digit->ManuChannel() & 0x3F ); // 6 bits
380 AliDebug(3,Form("input IdDE %d busPatchId %d PadX %d PadY %d iCath %d \n",
381 detElemId, busPatchId, padX, padY, cathode));
383 AliDebug(3,Form("busPatchId %d, manuId %d channelId %d\n", busPatchId, manuId,
388 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
389 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
390 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
394 for (Int_t i = 1; i <= 30; i++)
395 parity ^= ((word >> i) & 0x1);
396 AliBitPacking::PackWord((UInt_t)parity,word,31,31);
399 fBusStruct->SetLength(0);
400 fBusStruct->AddData(word);
401 fBusStruct->SetBusPatchId(busPatchId);
403 // storing the number of identical buspatches
404 nbInBus[busPatchId]++;
405 AddData(*fBusStruct);
408 } // loop over chamber in station
410 // sorting by buspatch
413 // gather datas from same bus patch
414 nEntries = fBusArray->GetEntriesFast();
416 for (Int_t i = 0; i < nEntries; i++) {
417 AliMUONBusStruct* temp = (AliMUONBusStruct*)fBusArray->At(i);
418 busPatchId = temp->GetBusPatchId();
420 // add bus patch header, length and total length managed by subevent class
421 for (Int_t j = 0; j < nbInBus[busPatchId]-1; j++) {
422 AliMUONBusStruct* temp1 = (AliMUONBusStruct*)fBusArray->At(++i);
423 temp->AddData(temp1->GetData(0));
424 fBusArray->RemoveAt(i) ;
427 fBusArray->Compress();
429 if (AliLog::GetGlobalDebugLevel() == 3) {
430 nEntries = fBusArray->GetEntriesFast();
431 for (Int_t i = 0; i < nEntries; i++) {
432 AliMUONBusStruct* temp = (AliMUONBusStruct*)fBusArray->At(i);
433 printf("busPatchid back %d\n",temp->GetBusPatchId());
434 for (Int_t j = 0; j < temp->GetLength(); j++) {
435 printf("manuId back %d, ",temp->GetManuId(j));
436 printf("channelId back %d, ",temp->GetChannelId(j));
437 printf("charge back %d\n",temp->GetCharge(j));
442 // end of TreeD reading and storing in TClonesArray
444 // getting info for the number of buspatches
447 Int_t iBusPerDSP[5];//number of bus patches per DSP
448 Int_t iDspMax; //number max of DSP per block
452 AliMUONBusStruct* busStructPtr = 0x0;
454 // open DDL files, 4 per station
455 for (Int_t iDDL = iSt*4; iDDL < 4 + iSt*4; iDDL++) {
457 fBusPatchManager->ResetBusItr(iDDL);
458 fBusPatchManager->GetDspInfo(iDDL, iDspMax, iBusPerDSP);
463 // ((43 manus max*64 ch + 4 bus word) * 5 DSPs + 10 DSP word) * 2 blocks + 8 block words = 27588
464 static const Int_t kBufferSize = ((43*64 + 4)*5 + 10)*2 + 8;
467 buffer = new Int_t [kBufferSize];
473 // two blocks A and B per DDL
474 for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
477 length = fBlockHeader->GetHeaderLength();
478 memcpy(&buffer[index],fBlockHeader->GetHeader(),length*4);
482 // 5 DSP's max per block
483 for (Int_t iDsp = 0; iDsp < iDspMax; iDsp++) {
486 length = fDspHeader->GetHeaderLength();
487 memcpy(&buffer[index],fDspHeader->GetHeader(),length*4);
491 //Â 5 buspatches max per DSP
492 for (Int_t i = 0; i < iBusPerDSP[iDsp]; i++) {
494 // iteration over bus patch in DDL
495 if ((iBusPatch = fBusPatchManager->NextBusInDDL(iDDL)) == -1) {
496 AliWarning(Form("Error in bus itr in DDL %d\n", iDDL));
500 // 4 DDL's per station, condition needed for station 3
501 iFile = iDDL - iSt*4; // works only if DDL begins at zero (as it should be) !!!
503 AliDebug(3,Form("iSt %d iDDL %d iBlock %d iDsp %d busPatchId %d", iSt, iDDL, iBlock,
506 nEntries = fBusArray->GetEntriesFast();
509 // checking buspatch structure not empty
510 for (Int_t iEntry = 0; iEntry < nEntries; iEntry++) { // method "bourrique"...
511 busStructPtr = (AliMUONBusStruct*)fBusArray->At(iEntry);
512 busPatchId = busStructPtr->GetBusPatchId();
513 if (busPatchId == iBusPatch) {
518 AliDebug(3,Form("busPatchId %d", busStructPtr->GetBusPatchId()));
521 // check if buspatchid has digit
522 if (busPatchId != -1) {
523 // add bus patch structure header
524 length = busStructPtr->GetHeaderLength();
525 memcpy(&buffer[index],busStructPtr->GetHeader(),length*4);
528 // add bus patch data
529 length = busStructPtr->GetLength();
530 memcpy(&buffer[index],busStructPtr->GetData(),length*4);
533 if (AliLog::GetGlobalDebugLevel() == 3) {
534 for (Int_t j = 0; j < busStructPtr->GetLength(); j++) {
535 printf("busPatchId %d, manuId %d channelId %d\n", busStructPtr->GetBusPatchId(),
536 busStructPtr->GetManuId(j), busStructPtr->GetChannelId(j));
540 fBusArray->RemoveAt(rEntry);
541 fBusArray->Compress();
543 // writting anyhow buspatch structure (empty ones)
544 buffer[index++] = busStructPtr->GetDefaultDataKey(); // fill it also for empty data size
545 buffer[index++] = busStructPtr->GetHeaderLength(); // header length
546 buffer[index++] = 0; // raw data length
547 buffer[index++] = iBusPatch; // bus patch
551 // check if totalLength even
552 // set padding word in case
553 // Add one word 0xBEEFFACE at the end of DSP structure
554 totalDspLength = index - indexDsp;
555 if ((totalDspLength % 2) == 1) {
556 buffer[indexDsp + fDspHeader->GetHeaderLength() - 2] = 1;
557 buffer[index++] = fDspHeader->GetDefaultPaddingWord();
561 dspLength = totalDspLength - fDspHeader->GetHeaderLength();
563 buffer[indexDsp+1] = totalDspLength; // dsp total length
564 buffer[indexDsp+2] = dspLength; // data length
568 totalBlkLength = index - indexBlk;
569 blkLength = totalBlkLength - fBlockHeader->GetHeaderLength();
570 totalDDLLength += totalBlkLength;
572 buffer[indexBlk+1] = totalBlkLength; // total block length
573 buffer[indexBlk+2] = blkLength;
579 fHeader.fSize = (totalDDLLength + headerSize) * 4;// total length in bytes
580 fwrite((char*)(&fHeader),headerSize*4,1,fFile[iFile]);
581 fwrite(buffer,sizeof(int),index,fFile[iFile]);
586 fTrackerTimer.Stop();
590 //____________________________________________________________________
591 Int_t AliMUONRawWriter::GetBusPatch(const AliMUONDigit& digit)
594 // Determine the BusPatch this digit belongs to.
596 fMappingTimer.Start(kFALSE);
600 // information from digits
601 Int_t detElemId = digit.DetElemId();
603 AliMpVSegmentation* seg =
604 fSegFactory->CreateMpSegmentationByElectronics(detElemId, digit.ManuId());
606 AliMpPlaneType plane = seg->PlaneType();
608 AliMpStationType stationType = AliMpDEManager::GetStationType(detElemId);
610 if ( stationType == kStation1 || stationType == kStation2 )
612 if (plane == kBendingPlane)
614 ptr = &fgManuPerBusSwp1B[0];
618 ptr = &fgManuPerBusSwp1NB[0];
623 if (plane == kBendingPlane)
625 ptr = &fgManuPerBusSwp2B[0];
629 ptr = &fgManuPerBusSwp2NB[0];
633 // Getting buspatch id
634 TArrayI* vec = fBusPatchManager->GetBusfromDE(detElemId);
637 Int_t m = ( digit.ManuId() & 0x3FF ); // remove bit 10
638 //FIXME : how can we remove that condition
639 // on the 10-th bit ? All the rest need not any knowledge about it,
640 // can't we find a way to get manu<->buspatch transparent to this too ?
642 if ( stationType == kStation1 || stationType == kStation2 )
644 for (Int_t i = 0; i < 12; i++)
646 if (m >= *(ptr + pos++)) break;
651 // offset of 100 in manuId for following bus patch
655 if (pos >(Int_t) vec->GetSize())
657 AliError(Form("pos greater %d than size %d manuId %d detElemId %d \n",
658 pos, (Int_t)vec->GetSize(), digit.ManuId(), detElemId));
659 AliError(Form("Chamber %s Plane %s manuId %d m %d",
660 StationTypeName(stationType).Data(),
661 PlaneTypeName(plane).Data(),
667 Int_t busPatchId = vec->At(pos);
669 fMappingTimer.Stop();
674 //____________________________________________________________________
675 Int_t AliMUONRawWriter::WriteTriggerDDL()
680 fTriggerTimer.Start(kFALSE);
682 // DDL event one per half chamber
684 // stored local id number
685 TArrayI isFired(256);
690 Int_t headerSize = sizeof(AliRawDataHeader)/4;
692 TClonesArray* localTrigger;
693 TClonesArray* globalTrigger;
694 AliMUONGlobalTrigger* gloTrg;
695 AliMUONLocalTrigger* locTrg = 0x0;
697 // global trigger for trigger pattern
698 globalTrigger = fMUONData->GlobalTrigger();
699 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
700 Int_t gloTrigPat = gloTrg->GetGlobalPattern();
703 localTrigger = fMUONData->LocalTrigger();
709 Int_t iLocCard, locCard;
710 Char_t locDec, trigY, posY, posX, regOut;
715 Int_t version = 1; // software version
716 Int_t eventPhys = 1; // trigger type: 1 for physics, 0 for software
717 Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
718 Int_t globalFlag = 0; // set to 1 if global info present in DDL else set to 0
721 static const Int_t kDarcHeaderLength = fDarcHeader->GetDarcHeaderLength();
722 static const Int_t kGlobalHeaderLength = fDarcHeader->GetGlobalHeaderLength();
723 static const Int_t kDarcScalerLength = fDarcHeader->GetDarcScalerLength();
724 static const Int_t kGlobalScalerLength = fDarcHeader->GetGlobalScalerLength();
725 static const Int_t kRegHeaderLength = fRegHeader->GetHeaderLength();
726 static const Int_t kRegScalerLength = fRegHeader->GetScalerLength();
727 static const Int_t kLocHeaderLength = fLocalStruct->GetLength();
728 static const Int_t kLocScalerLength = fLocalStruct->GetScalerLength();
730 // [16(local)*6 words + 6 words]*8(reg) + 8 words = 824
731 static const Int_t kBufferSize = (16 * (kLocHeaderLength+1) + (kRegHeaderLength+1))* 8
732 + kDarcHeaderLength + kGlobalHeaderLength + 2;
734 // [16(local)*51 words + 16 words]*8(reg) + 8 + 10 + 8 words scaler event 6682 words
735 static const Int_t kScalerBufferSize = (16 * (kLocHeaderLength + kLocScalerLength +1) +
736 (kRegHeaderLength + kRegScalerLength +1))* 8 +
737 (kDarcHeaderLength + kDarcScalerLength +
738 kGlobalHeaderLength + kGlobalScalerLength + 2);
740 eventPhys = 0; //set to generate scaler events
742 Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
743 // stored the local card id that's fired
744 for (Int_t i = 0; i < nEntries; i++) {
745 locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
746 isFired[locTrg->LoCircuit()] = 1; // storing local boards with informations
750 AliInfo("No Trigger information available");
753 buffer = new Int_t [kScalerBufferSize];
755 buffer = new Int_t [kBufferSize];
759 // open DDL file, on per 1/2 chamber
760 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
764 if (iDDL == 0) // suppose global info in DDL one
770 // set darc status word
771 // see AliMUONDarcHeader.h for details
772 AliBitPacking::PackWord((UInt_t)eventPhys,word,30,30);
773 AliBitPacking::PackWord((UInt_t)serialNb,word,20,23);
774 AliBitPacking::PackWord((UInt_t)globalFlag,word,10,10);
775 AliBitPacking::PackWord((UInt_t)version,word,12,19);
776 fDarcHeader->SetWord(word);
778 memcpy(&buffer[index], fDarcHeader->GetHeader(), (kDarcHeaderLength)*4);
779 index += kDarcHeaderLength;
782 fDarcHeader->SetGlobalOutput(gloTrigPat);// no global input for the moment....
784 fDarcHeader->SetGlobalOutput(0);
787 // 6 DARC scaler words
788 memcpy(&buffer[index], fDarcHeader->GetDarcScalers(),kDarcScalerLength*4);
789 index += kDarcScalerLength;
792 buffer[index++] = fDarcHeader->GetEndOfDarc();
794 // 4 words of global board input + Global board output
795 memcpy(&buffer[index], fDarcHeader->GetGlobalInput(), (kGlobalHeaderLength)*4);
796 index += kGlobalHeaderLength;
799 // 10 Global scaler words
800 memcpy(fDarcHeader->GetGlobalScalers(), &buffer[index], kGlobalScalerLength*4);
801 index += kGlobalScalerLength;
804 // end of global word
805 buffer[index++] = fDarcHeader->GetEndOfGlobal();
807 // 8 regional cards per DDL
808 for (Int_t iReg = 0; iReg < 8; iReg++) {
811 Char_t crateName[10];
812 GetCrateName(crateName, iDDL, iReg);
813 AliMUONTriggerCrate* crate = fCrateManager->Crate(crateName);
816 AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, iDDL));
818 // Regional card header
821 // set darc status word
822 fRegHeader->SetDarcWord(word);
825 regInpHpt = regInpLpt = 0;
826 // fill darc word, not darc status for the moment (empty)
827 //see AliMUONRegHeader.h for details
828 AliBitPacking::PackWord((UInt_t)eventPhys,word,31,31);
829 AliBitPacking::PackWord((UInt_t)serialNb,word,19,24);
830 AliBitPacking::PackWord((UInt_t)version,word,16,23);
831 AliBitPacking::PackWord((UInt_t)iReg,word,15,18);
832 AliBitPacking::PackWord((UInt_t)regOut,word,0,7); // waiting realistic output of AliMUONGlobalTrigger (oct 06 ?)
833 fRegHeader->SetWord(word);
836 // fill header later, need local response
837 Int_t indexReg = index;
838 index += kRegHeaderLength;
840 // 11 regional scaler word
842 memcpy(&buffer[index], fRegHeader->GetScalers(), kRegScalerLength*4);
843 index += kRegScalerLength;
846 // end of regional word
847 buffer[index++] = fRegHeader->GetEndOfReg();
849 TObjArray *boards = crate->Boards();
852 // 16 local card per regional board
853 UShort_t localMask = 0x0;
855 for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
857 // slot zero for Regional card
858 AliMUONLocalTriggerBoard* localBoard = (AliMUONLocalTriggerBoard*)boards->At(iLoc+1);
860 if (localBoard) { // if not empty slot
862 if ((iLocCard = localBoard->GetNumber()) != 0) {// if notified board
864 localMask |= (0x1 << iLoc); // local mask
865 if (isFired[iLocCard]) { // if card has triggered
866 locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries);
867 locCard = locTrg->LoCircuit();
868 locDec = locTrg->GetLoDecision();
870 posY = locTrg->LoStripY();
871 posX = locTrg->LoStripX();
872 devX = locTrg->LoDev();
874 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
875 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
876 } else { //no trigger (see PRR chpt 3.4)
882 // set local card id to -1
885 // calculate regional input High and low Pt
886 UInt_t tmp1 = (locDec >> 2) & 0x3;
887 UInt_t tmp2 = locDec & 0x3;
889 regInpHpt |= tmp1 << (30 - iLoc*2);
890 regInpLpt |= tmp2 << (30 - iLoc*2);
894 AliBitPacking::PackWord((UInt_t)iLoc,word,19,22); //card id number in crate
895 AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
896 AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
897 AliBitPacking::PackWord((UInt_t)posY,word,10,13);
898 AliBitPacking::PackWord((UInt_t)devX,word,5,9);
899 AliBitPacking::PackWord((UInt_t)posX,word,0,4);
901 if (locCard == iLocCard) {
902 // add local cards structure
903 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
904 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
905 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
906 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
907 buffer[index++] = (Int_t)word; // data word
908 if (iEntries < nEntries-1)
911 buffer[index++] = 0; // 4 words for x1, x2, y1, y2
915 buffer[index++] = (Int_t)word; // data word
919 // fill with 10CDEAD word for 'non-notified' slots
920 for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
921 buffer[index++] = fLocalStruct->GetDisableWord();
924 // fill with 10CDEAD word for empty slots
925 for (Int_t i = 0; i < fLocalStruct->GetLength(); i++)
926 buffer[index++] = fLocalStruct->GetDisableWord();
927 }// condition localBoard
929 // 45 regional scaler word
931 memcpy(&buffer[index], fLocalStruct->GetScalers(), kLocScalerLength*4);
932 index += kLocScalerLength;
935 // end of local structure words
936 buffer[index++] = fLocalStruct->GetEndOfLocal();
939 // fill regional header with local output
940 fRegHeader->SetInput(regInpLpt, 0);
941 fRegHeader->SetInput(regInpHpt, 1);
942 fRegHeader->SetMask(localMask);
943 memcpy(&buffer[indexReg],fRegHeader->GetHeader(),kRegHeaderLength*4);
948 // writting onto disk
950 fHeader.fSize = (index + headerSize) * 4;// total length in bytes
951 fwrite((char*)(&fHeader),headerSize*4,1,fFile[iDDL]);
952 fwrite(buffer,sizeof(int),index,fFile[iDDL]);
957 fTriggerTimer.Stop();
961 //____________________________________________________________________
962 void AliMUONRawWriter::SetScalersNumbers()
964 // set numbers for scaler events for trigger headers
965 // since this is provided by the experiment
966 // put dummy numbers to check the monitoring
968 fDarcHeader->SetScalersNumbers();
969 fRegHeader->SetScalersNumbers();
970 fLocalStruct->SetScalersNumbers();
972 fScalerEvent = kTRUE;
974 //____________________________________________________________________
975 void AliMUONRawWriter::GetCrateName(Char_t* name, Int_t iDDL, Int_t iReg)
977 // set crate name from DDL & reg number
982 sprintf(name,"%d", iReg+1);
992 sprintf(name,"%d", iReg);
996 // crate Right for first DDL