+ // decode GTU track words
+ // this depends on the hardware revision of the SMU
+
+ Int_t sector = fCurrEquipmentId-kDDLOffset;
+
+ if ((sector < 0) || (sector > 17)) {
+ AliError(Form("Invalid sector %i for GTU tracks", sector));
+ return -1;
+ }
+
+ AliDebug(1, DumpRaw(Form("GTU tracks in sector %2i (hw rev %i)", sector, fCurrHwRev),
+ fPayloadCurr + 4, 10, 0xffe0ffff));
+
+ fCurrTrgFlags[sector] = 0;
+
+ if (fCurrHwRev < 1772) {
+ UInt_t fastWord; // fast trigger word
+ ULong64_t trackWord = 0; // extended track word
+ Int_t stack = 0;
+ Int_t idx = 0;
+ for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+ if (fPayloadCurr[iWord] == 0x10000000) { // stack boundary marker
+ stack++;
+ idx = 0;
+ }
+ else {
+ if ((idx == 0) &&
+ ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
+ fastWord = fPayloadCurr[iWord];
+ fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
+ AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
+ continue;
+ }
+ else if ((idx & 0x1) == 0x1) {
+ trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+ AliDebug(1,Form("track debug word: 0x%016llx", trackWord));
+ if (fTracks) {
+ AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+ AliESDTrdTrack();
+
+ trk->SetSector(sector);
+ trk->SetStack((trackWord >> 60) & 0x7);
+ trk->SetA(0);
+ trk->SetB(0);
+ trk->SetPID(0);
+ trk->SetLayerMask((trackWord >> 16) & 0x3f);
+ trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+ trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+ trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+ trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+ trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+ trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+ trk->SetFlags(0);
+ trk->SetReserved(0);
+ trk->SetLabel(-3);
+
+ Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+ if (TMath::Abs(pt) > 0.1) {
+ trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
+ }
+ }
+ }
+ else {
+ trackWord = fPayloadCurr[iWord];
+ }
+ idx++;
+ }
+ }
+ }
+ else if (fCurrHwRev < 1804) {
+ UInt_t fastWord; // fast trigger word
+ ULong64_t trackWord = 0; // extended track word
+ Int_t stack = 0;
+ Int_t idx = 0;
+ for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+ if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
+ stack++;
+ idx = 0;
+ }
+ else {
+ if ((idx == 0) &&
+ ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
+ fastWord = fPayloadCurr[iWord];
+ fCurrTrgFlags[sector] |= 1 << (stack+11); // assume tracking done if fast word sent
+ AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
+ continue;
+ }
+ else if ((idx & 0x1) == 0x1) {
+ trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+ AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
+ if (fTracks) {
+ AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+ AliESDTrdTrack();
+
+ trk->SetSector(fCurrEquipmentId-kDDLOffset);
+ trk->SetStack((trackWord >> 60) & 0x7);
+ trk->SetA(0);
+ trk->SetB(0);
+ trk->SetPID(0);
+ trk->SetLayerMask((trackWord >> 16) & 0x3f);
+ trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+ trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+ trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+ trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+ trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+ trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+ trk->SetFlags(0);
+ trk->SetReserved(0);
+ trk->SetLabel(-3);
+
+ Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+ if (TMath::Abs(pt) > 0.1) {
+ trk->SetA((Int_t) (-0.15*51625./100./pt / 160e-4 * 2));
+ }
+ }
+ }
+ else {
+ trackWord = fPayloadCurr[iWord];
+ }
+ idx++;
+ }
+ }
+ }
+ else if (fCurrHwRev < 1819) {
+ UInt_t fastWord; // fast trigger word
+ ULong64_t trackWord = 0; // extended track word
+ Int_t stack = 0;
+ Int_t idx = 0;
+ for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+ if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
+ stack++;
+ idx = 0;
+ }
+ else {
+ if ((idx == 0) &&
+ ((fPayloadCurr[iWord] & 0xfffff0f0) == 0x13370000)) {
+ fastWord = fPayloadCurr[iWord];
+ if (fastWord & (1 << 13))
+ fCurrTrgFlags[sector] |= 1 << (stack+11);
+ AliDebug(1, Form("stack %i: fast trigger word: 0x%08x", stack, fastWord));
+ continue;
+ }
+ else if ((idx & 0x1) == 0x1) {
+ trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+ AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
+
+ if (fTracks) {
+ AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+ AliESDTrdTrack();
+
+ trk->SetSector(fCurrEquipmentId-kDDLOffset);
+ trk->SetStack((trackWord >> 60) & 0x7);
+ trk->SetA(0);
+ trk->SetB(0);
+ // trk->SetPt(((trackWord & 0xffff) ^ 0x8000) - 0x8000);
+ trk->SetPID(0);
+ trk->SetLayerMask((trackWord >> 16) & 0x3f);
+ trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+ trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+ trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+ trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+ trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+ trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+ trk->SetFlags(0);
+ trk->SetReserved(0);
+ trk->SetLabel(-3);
+
+ Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+ if (TMath::Abs(pt) > 0.1) {
+ trk->SetA((Int_t) (0.15*51625./100./trk->Pt() / 160e-4 * 2));
+ }
+ }
+ }
+ else {
+ trackWord = fPayloadCurr[iWord];
+ }
+ idx++;
+ }
+ }
+ }
+ else if (fCurrHwRev < 1860) {
+ UInt_t fastWord; // fast trigger word
+ ULong64_t trackWord = 0; // extended track word
+ Int_t stack = 0;
+ Int_t idx = 0;
+ Bool_t upperWord = kFALSE;
+ Int_t word = 0;
+ for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+ if (fPayloadCurr[iWord] == 0xffe0ffff) { // stack boundary marker
+ stack++;
+ idx = 0;
+ upperWord = kFALSE;
+ }
+ else {
+ // assemble the 32-bit words out of 16-bit blocks
+ if (upperWord) {
+ word |= (fPayloadCurr[iWord] & 0xffff0000);
+ upperWord = kFALSE;
+ }
+ else {
+ // lower word is read first
+ word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
+ upperWord = kTRUE;
+ continue;
+ }
+
+ if ((word & 0xffff0008) == 0x13370008) {
+ fastWord = word;
+ AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, fastWord));
+ if (fastWord & (1 << 13))
+ fCurrTrgFlags[sector] |= 1 << (stack+11);
+ continue;
+ }
+ else if ((idx & 0x1) == 0x1) {
+ trackWord |= ((ULong64_t) word) << 32;
+ AliDebug(1, Form("track debug word: 0x%016llx", trackWord));
+ if (fTracks) {
+ AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+ AliESDTrdTrack();
+
+ trk->SetSector(fCurrEquipmentId-kDDLOffset);
+ trk->SetStack((trackWord >> 60) & 0x7);
+ trk->SetA(0);
+ trk->SetB(0);
+ trk->SetPID(0);
+ trk->SetLayerMask((trackWord >> 16) & 0x3f);
+ trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+ trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+ trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+ trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+ trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+ trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+ trk->SetFlags(0);
+ trk->SetReserved(0);
+ trk->SetLabel(-3);
+
+ Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+ if (TMath::Abs(pt) > 0.1) {
+ trk->SetA((Int_t) (0.15*51625./100./pt / 160e-4 * 2));
+ }
+ }
+ }
+ else {
+ trackWord = word;
+ }
+ idx++;
+ }
+ }
+
+ }
+ else {
+ ULong64_t trackWord = 0; // this is the debug word
+ Int_t stack = 0;
+ Int_t idx = 0;
+ Bool_t upperWord = kFALSE;
+ Int_t word = 0;
+ for (UInt_t iWord = 4; iWord < fCurrSmHeaderSize; iWord++) {
+ if (fPayloadCurr[iWord] == 0xffe0ffff) {
+ stack++;
+ idx = 0;
+ upperWord = kFALSE;
+ }
+ else {
+ // assemble the 32-bit words out of 16-bit blocks
+ if (upperWord) {
+ word |= (fPayloadCurr[iWord] & 0xffff0000);
+ upperWord = kFALSE;
+ }
+ else {
+ // lower word is read first
+ word = (fPayloadCurr[iWord] & 0xffff0000) >> 16;
+ upperWord = kTRUE;
+ continue;
+ }
+
+ if ((word & 0xffff0008) == 0x13370008) {
+ AliDebug(1, Form("stack %i: fast track word: 0x%08x", stack, word));
+ continue;
+ }
+ else if ((word & 0xffff0010) == 0x13370010) {
+ AliDebug(1, Form("stack %i: tracking done word: 0x%08x", stack, word));
+ fCurrTrgFlags[sector] |= 1 << (stack+11);
+ continue;
+ }
+ else if ((idx & 0x1) == 0x1) {
+ trackWord |= ((ULong64_t) word) << 32;
+ AliDebug(1, Form("track debug word: 0x%16llx", trackWord));
+ if (fTracks) {
+ AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+ AliESDTrdTrack();
+ trk->SetSector(fCurrEquipmentId-kDDLOffset);
+ trk->SetStack((trackWord >> 60) & 0x7);
+ trk->SetA(0);
+ trk->SetB(0);
+ trk->SetPID(0);
+ trk->SetLayerMask((trackWord >> 16) & 0x3f);
+ trk->SetTrackletIndex((trackWord >> 22) & 0x3f, 0);
+ trk->SetTrackletIndex((trackWord >> 28) & 0x3f, 1);
+ trk->SetTrackletIndex((trackWord >> 34) & 0x3f, 2);
+ trk->SetTrackletIndex((trackWord >> 40) & 0x3f, 3);
+ trk->SetTrackletIndex((trackWord >> 46) & 0x3f, 4);
+ trk->SetTrackletIndex((trackWord >> 52) & 0x3f, 5);
+
+ trk->SetFlags(0);
+ trk->SetReserved(0);
+ trk->SetLabel(-3);
+
+ Float_t pt = (((Int_t) (trackWord & 0xffff) ^ 0x8000) - 0x8000)/128.;
+ if (TMath::Abs(pt) > 0.1) {
+ trk->SetA(-(Int_t) (0.15*51625./100./pt / 160e-4 * 2));
+ }
+ }
+ }
+ else {
+ trackWord = word;
+ }
+ idx++;
+ }
+ }
+ }
+ return 0;
+}
+
+Int_t AliTRDrawStream::ReadTrackingHeader(Int_t stack)
+{
+ // read the tracking information and store it for the given stack
+
+ // index word
+
+ fCurrTrkHeaderIndexWord[stack] = *fPayloadCurr;
+ fCurrTrkHeaderSize[stack] = ((*fPayloadCurr) >> 16) & 0x3ff;
+
+ AliDebug(1, Form("tracking header index word: 0x%08x, size: %i (hw rev: %i)",
+ fCurrTrkHeaderIndexWord[stack], fCurrTrkHeaderSize[stack], fCurrHwRev));
+ Int_t trackingTime = *fPayloadCurr & 0x3ff;
+
+ fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= ((fCurrTrkHeaderIndexWord[stack] >> 10) & 0x1) << (22 + stack);
+ fPayloadCurr++;
+
+ // data words
+ ULong64_t trackWord = 0;
+ Int_t idx = 0;
+ Int_t trackIndex = fTracks ? fTracks->GetEntriesFast() : -1;
+
+ for (UInt_t iWord = 0; iWord < fCurrTrkHeaderSize[stack]; iWord++) {
+
+ if (!(idx & 0x1)) {
+ // first part of 64-bit word
+ trackWord = fPayloadCurr[iWord];
+ }
+ else {
+ trackWord |= ((ULong64_t) fPayloadCurr[iWord]) << 32;
+
+ if (trackWord & (1ul << 63)) {
+ if ((trackWord & (0x3ful << 56)) != 0) {
+ // track word
+ AliDebug(2, Form("track word: 0x%016llx", trackWord));
+
+ if (fTracks) {
+ AliESDTrdTrack *trk = new ((*fTracks)[fTracks->GetEntriesFast()])
+ AliESDTrdTrack();
+
+ trk->SetSector(fCurrEquipmentId-kDDLOffset);
+ trk->SetLayerMask((trackWord >> 56) & 0x3f);
+ trk->SetA( (((trackWord >> 38) & 0x3ffff) ^ 0x20000) - 0x20000);
+ trk->SetB( (((trackWord >> 20) & 0x3ffff) ^ 0x20000) - 0x20000);
+ trk->SetC( (((trackWord >> 8) & 0xffff) ^ 0x8000) - 0x8000);
+ trk->SetPID((trackWord >> 0) & 0xff);
+ trk->SetStack(stack);
+ trk->SetLabel(-3);
+
+ // now compare the track word with the one generated from the ESD information
+ if (trackWord != trk->GetTrackWord(0)) {
+ AliError(Form("track word 0x%016llx does not match the read one 0x%016llx",
+ trk->GetTrackWord(0), trackWord));
+ }
+ }
+ }
+ else {
+ // done marker (so far only used to set trigger flag)
+ fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= 1 << (27 + stack);
+ fCurrTrkFlags[(fCurrEquipmentId-kDDLOffset)*fgkNstacks + stack] = trackWord;
+
+ AliDebug(2, Form("tracking done marker: 0x%016llx, trigger flags: 0x%08x",
+ trackWord, fCurrTrgFlags[fCurrEquipmentId-kDDLOffset]));
+ AliDebug(2, Form("seg / stack / first / last / done / index : %i %i %lli %lli %lli %i",
+ fCurrEquipmentId - kDDLOffset, stack,
+ (trackWord >> 20) & 0x3ff,
+ (trackWord >> 10) & 0x3ff,
+ (trackWord >> 0) & 0x3ff,
+ trackingTime));
+ }
+ }
+ else {
+ // extended track word
+ AliDebug(2, Form("extended track word: 0x%016llx", trackWord));
+
+ if (fTracks) {
+ AliESDTrdTrack *trk = (AliESDTrdTrack*) (*fTracks)[trackIndex];
+
+ trk->SetFlags((trackWord >> 52) & 0x7ff);
+ trk->SetFlagsTiming((trackWord >> 51) & 0x1);
+ trk->SetReserved((trackWord >> 49) & 0x3);
+ trk->SetY((trackWord >> 36) & 0x1fff);
+ trk->SetTrackletIndex((trackWord >> 0) & 0x3f, 0);
+ trk->SetTrackletIndex((trackWord >> 6) & 0x3f, 1);
+ trk->SetTrackletIndex((trackWord >> 12) & 0x3f, 2);
+ trk->SetTrackletIndex((trackWord >> 18) & 0x3f, 3);
+ trk->SetTrackletIndex((trackWord >> 24) & 0x3f, 4);
+ trk->SetTrackletIndex((trackWord >> 30) & 0x3f, 5);
+
+ if (trk->GetFlagsTiming() == 0) {
+ AliError(Form("*** track not in time: 0x%016llx", trk->GetExtendedTrackWord(0)));
+ }
+
+ if (trackWord != trk->GetExtendedTrackWord(0)) {
+ AliError(Form("extended track word 0x%016llx does not match the read one 0x%016llx",
+ trk->GetExtendedTrackWord(0), trackWord));
+ }
+
+ trackIndex++;
+ }
+ }
+ }
+ idx++;
+ }
+
+ fPayloadCurr += fCurrTrkHeaderSize[stack];
+
+ return fCurrTrkHeaderSize[stack];
+}
+
+Int_t AliTRDrawStream::ReadTriggerHeaders()
+{
+ // read all trigger headers present
+
+ AliDebug(1, Form("trigger mask: 0x%03x, fired: 0x%03x\n",
+ fCurrTriggerEnable, fCurrTriggerFired));
+ // loop over potential trigger blocks
+ for (Int_t iTrigger = 0; iTrigger < fgkNtriggers; iTrigger++) {
+ // check for trigger enable
+ if (fCurrTriggerEnable & (1 << iTrigger)) {
+ // check for readout mode and trigger fired
+ if ((fCurrTrgHeaderReadout == 0) || (fCurrTriggerFired & (1 << iTrigger))) {
+ // index word
+ AliDebug(1, Form("trigger index word %i: 0x%08x\n", iTrigger, *fPayloadCurr));
+ fCurrTrgHeaderIndexWord[iTrigger] = *fPayloadCurr;
+ fCurrTrgHeaderSize[iTrigger] = ((*fPayloadCurr) >> 16) & 0x3ff;
+ if (iTrigger == 7) {
+ // timeout trigger, use to extract tracking time
+ fCurrTrgFlags[fCurrEquipmentId-kDDLOffset] |= (*fPayloadCurr & 0x3ff) << 12;
+ }
+
+ fPayloadCurr++;
+ // data words
+ fPayloadCurr += fCurrTrgHeaderSize[iTrigger];
+ }
+ }
+ }
+
+ return 0;
+}
+
+Int_t AliTRDrawStream::ReadStackHeader(Int_t stack)
+{
+ // read the stack header