]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDRawReader.cxx
Fix to the raw reader that properly decodes the parameter settings in the
[u/mrichter/AliRoot.git] / FMD / AliFMDRawReader.cxx
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 /* $Id$ */
16 /** @file    AliFMDRawReader.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:45:23 2006
19     @brief   Class to read raw data 
20     @ingroup FMD_rec
21 */
22 //____________________________________________________________________
23 //
24 // Class to read ADC values from a AliRawReader object. 
25 //
26 // This class uses the AliFMDRawStreamer class to read the ALTRO
27 // formatted data. 
28 // 
29 //          +-------+
30 //          | TTask |
31 //          +-------+
32 //              ^
33 //              |
34 //      +-----------------+  <<references>>  +--------------+
35 //      | AliFMDRawReader |<>----------------| AliRawReader |
36 //      +-----------------+                  +--------------+
37 //              |                                  ^
38 //              | <<uses>>                         |
39 //              V                                  |
40 //      +-----------------+      <<uses>>          |
41 //      | AliFMDRawStream |------------------------+
42 //      +-----------------+
43 //              |
44 //              V
45 //      +----------------+
46 //      | AliAltroStream |
47 //      +----------------+
48 //
49 // #include <AliLog.h>          // ALILOG_H
50 #include "AliFMDDebug.h" // Better debug macros
51 #include "AliFMDParameters.h"   // ALIFMDPARAMETERS_H
52 #include "AliFMDDigit.h"        // ALIFMDDIGIT_H
53 #include "AliFMDSDigit.h"       // ALIFMDSDIGIT_H
54 // #include "AliFMDRawStream.h" // ALIFMDRAWSTREAM_H 
55 #include "AliRawReader.h"       // ALIRAWREADER_H 
56 #include "AliFMDRawReader.h"    // ALIFMDRAWREADER_H 
57 #include "AliFMDDebug.h"
58 #include "AliFMDCalibSampleRate.h"
59 #include "AliFMDCalibStripRange.h"
60 #include "AliFMDAltroMapping.h"
61 // #include "AliFMDAltroIO.h"   // ALIFMDALTROIO_H 
62 #include "AliAltroRawStreamV3.h"
63 #include <TArrayS.h>            // ROOT_TArrayS
64 #include <TTree.h>              // ROOT_TTree
65 #include <TClonesArray.h>       // ROOT_TClonesArray
66 #include <TString.h>
67 #include <iostream>
68 #include <climits>
69 // #include <iomanip>
70
71 //____________________________________________________________________
72 ClassImp(AliFMDRawReader)
73 #if 0
74   ; // This is here to keep Emacs for indenting the next line
75 #endif
76
77 //____________________________________________________________________
78 AliFMDRawReader::AliFMDRawReader(AliRawReader* reader, TTree* tree) 
79   : TTask("FMDRawReader", "Reader of Raw ADC values from the FMD"),
80     fTree(tree),
81     fReader(reader), 
82     // fSampleRate(1),
83     fData(0),
84     fNbytes(0), 
85     fMinStrip(0),
86     fMaxStrip(127), 
87     fPreSamp(14+5),
88     fSeen(0)
89 {
90   // Default CTOR
91   for (Int_t i = 0; i < 3; i++) { 
92     fSampleRate[i]   = 0;
93     fZeroSuppress[i] = kFALSE;
94     fNoiseFactor[i]  = 1;
95   }
96 }
97
98 //____________________________________________________________________
99 void
100 AliFMDRawReader::Exec(Option_t*) 
101 {
102   // Read the data 
103   TClonesArray* array = new TClonesArray("AliFMDDigit");
104   if (!fTree) {
105     AliError("No tree");
106     return;
107   }
108   fTree->Branch("FMD", &array);
109   
110   
111   ReadAdcs(array);
112   Int_t nWrite = fTree->Fill();
113   AliFMDDebug(1, ("Got a grand total of %d digits, wrote %d bytes to tree", 
114                    array->GetEntriesFast(), nWrite));
115 }
116
117 //____________________________________________________________________
118 Int_t
119 AliFMDRawReader::NewDDL(AliAltroRawStreamV3& input, UShort_t& det)
120 {
121   // Process a new DDL.  Sets the internal data members fZeroSuppress, 
122   // fSampleRate, and fNoiseFactor based on information in the RCU trailer. 
123   // 
124   // Parameters:
125   //   input Input stream
126   //   det   On return, the detector number
127   // 
128   // Return value:
129   //   negative value in case of problems, the DDL number otherwise
130
131   // Get the DDL number
132   UInt_t ddl = input.GetDDLNumber();
133   AliFMDDebug(2, ("DDL number %d", ddl));
134
135   /* Note, previously, the ALTROCFG1 register was interpreted as 
136    * 
137    * Bits    Value    Description
138    *   0- 3      0/1   1st Baseline filter, mode 
139    *   4- 5   Over-1   2nd baseline filter, # of pre-samples
140    *   6- 9   factor   2nd baseline filter, # of post-samples 
141    *  10-          0   2nd baseline filter, enable
142    *  11-12       00   Zero suppression, glitch filter mode
143    *  13-15      001   Zero suppression, # of post samples
144    *  16-17       01   Zero suppression, # of pre  samples
145    *  18         0/1   Zero suppression, enable
146    *
147    * The interpretation used in AliAltroRawStreamerV3 - which
148    * corresponds directly to ALTRO DPCFG register - is 
149    *
150    * Bits    Value  Description
151    *   0- 3    0/1   1st Baseline filter, mode 
152    *   4         0   Polarity (if '1', then "1's inverse")
153    *   5- 6     01   Zero suppression, # of pre samples
154    *   7-10   0001   Zero suppression, # of post samples
155    *  11         0   2nd baseline filter, enable
156    *  12-13     00   Zero suppression, glitch filter mode
157    *  14-16 factor   2nd baseline filter, # of post-samples
158    *  17-18     01   2nd baseline filter, # of pre-samples 
159    *  19       0/1   Zero suppression, enable
160    *
161    *  Writing 'x' for variable values, that means we have the
162    *  following patterns for the 2 cases 
163    *
164    *    bit #  20   16   12    8    4    0
165    *     old    |0x01|0010|00xx|xxxx|xxxx|
166    *     new    |x01x|xx00|0000|1010|xxxx|
167    *
168    *  That means that we can check if bits 10-13 are '1000' or
169    *  '0000', which will tell us if the value was written with the
170    *  new or the old interpretation.    That is, we can check that 
171    *
172    *    if (((altrocfg1 >> 10) & 0x8) == 0x8) { 
173    *      // old interpretation 
174    *    }
175    *    else { 
176    *      // New interpretation 
177    *    }
178    *
179    * That means, that we should never 
180    *
181    *  - change the # of zero suppression post samples 
182    *  - Turn on 2nd baseline correction 
183    *  - Change the zero-suppression glitch filter mode
184    *
185    * This change as introduced in version 1.2 of Rcu++
186    */
187   UInt_t cfg1 = input.GetAltroCFG1();
188   if (((cfg1 >> 10) & 0x8) == 0x8) {
189     UInt_t cfg2 = input.GetAltroCFG2();
190     fZeroSuppress[ddl] = (cfg1 >> 0) & 0x1;
191     fNoiseFactor[ddl]  = (cfg1 >> 6) & 0xF;
192     fSampleRate[ddl]   = (cfg2 >> 0) & 0xF;
193   }
194   else {
195     fZeroSuppress[ddl] = input.GetZeroSupp();
196     // WARNING: We store the noise factor in the 2nd baseline
197     // filters excluded post samples, since we'll never use that
198     // mode. 
199     fNoiseFactor[ddl]  = input.GetNPostsamples();
200     // WARNING: We store the sample rate in the number of pre-trigger
201     // samples, since we'll never use that mode.
202     fSampleRate[ddl]     = input.GetNPretriggerSamples();
203   }
204   AliFMDDebug(3, ("RCU @ DDL %d zero suppression: %s", 
205                    ddl, (fZeroSuppress[ddl] ? "yes" : "no")));
206   AliFMDDebug(3, ("RCU @ DDL %d noise factor: %d", ddl,fNoiseFactor[ddl]));    
207   AliFMDDebug(3, ("RCU @ DDL %d sample rate: %d", ddl,fSampleRate[ddl]));
208
209
210   // Get Errors seen 
211   Int_t nChAddrMismatch = input.GetNChAddrMismatch();
212   Int_t nChLenMismatch  = input.GetNChLengthMismatch();
213   if (nChAddrMismatch != 0) 
214     AliWarning(Form("Got %d channels with address mis-matches for 0x%03x",
215                     nChAddrMismatch, ddl));
216   if (nChLenMismatch != 0) 
217     AliWarning(Form("Got %d channels with length mis-matches for 0x%03x",
218                     nChLenMismatch, ddl));
219
220   // Map DDL number to the detector number 
221   AliFMDParameters*    pars   = AliFMDParameters::Instance();
222   AliFMDAltroMapping*  map    = pars->GetAltroMap();
223   if (map->DDL2Detector(ddl) < 0) return -1;
224   det = map->DDL2Detector(ddl);
225
226   if (AliLog::GetDebugLevel("FMD", 0) > 5) 
227     input.PrintRCUTrailer();
228   return ddl;
229 }
230
231 //____________________________________________________________________
232 Int_t
233 AliFMDRawReader::NewChannel(AliAltroRawStreamV3& input,  UShort_t det,
234                             Char_t&  ring, UShort_t& sec, Short_t& strbase)
235 {
236   // Processs a new channel.  Sets the internal data members
237   // fMinStrip, fMaxStrip, and fPreSamp. 
238   //
239   // Parameter:
240   //   input   Input stream
241   //   ring    On return, the ring identifier 
242   //   sec     On return, the sector number
243   //   strbase On return, the strip base
244   // 
245   // Return value
246   //   negative value in case of problems, hardware address otherwise
247
248   // Get the hardware address, and map that to detector coordinates 
249   UShort_t board, chip, channel;
250   Int_t    ddl    = input.GetDDLNumber();
251   Int_t    hwaddr = input.GetHWAddress();
252   if (input.IsChannelBad()) { 
253     AliError(Form("Channel 0x%03x is marked as bad!", hwaddr));
254   }
255   
256   AliFMDParameters*    pars   = AliFMDParameters::Instance();
257   AliFMDAltroMapping*  map    = pars->GetAltroMap();
258   // Map to hardware stuff 
259   map->ChannelAddress(hwaddr, board, chip, channel);
260   // Then try to map to detector address
261   if (!map->Channel2StripBase(board, chip, channel, ring, sec, strbase)) {
262     AliError(Form("Failed to get detector id from DDL %d, "
263                   "hardware address 0x%03x", ddl, hwaddr));
264     return -1;
265   }
266   AliFMDDebug(3, ("Board: 0x%02x, Altro: 0x%x, Channel: 0x%x", 
267                   board, chip, channel));
268
269   // Get the 'conditions'
270   fMinStrip = pars->GetMinStrip(det, ring, sec, strbase);
271   fMaxStrip = pars->GetMaxStrip(det, ring, sec, strbase);
272   fPreSamp  = pars->GetPreSamples(det, ring, sec, strbase);
273   if (fSampleRate[ddl] == 0) 
274     fSampleRate[ddl] = pars->GetSampleRate(det, ring, sec, strbase);
275
276   return hwaddr;
277 }
278
279 //____________________________________________________________________
280 Int_t
281 AliFMDRawReader::NewSample(AliAltroRawStreamV3& input, 
282                            Int_t i, UShort_t t, UShort_t sec,
283                            UShort_t  strbase, Short_t&  str, UShort_t& samp)
284 {
285   // Process a new timebin
286   // 
287   // Parameters:
288   //   input   Input stream
289   //   i       Index into bunch data
290   //   t       Time
291   //   strbase Base of strip numbers for this channel
292   //   str     On return, the strip number
293   //   samp    On return, the sample number
294   // 
295   // Return value
296   //   negative value in case of problems, ADC value otherwise
297   if (t < fPreSamp) return -1;
298
299   Int_t           ddl  = input.GetDDLNumber();
300   Int_t           hwa  = input.GetHWAddress();
301   const UShort_t* data = input.GetSignals();
302   Short_t         adc  = data[i];
303   AliFMDDebug(10, ("0x%04x/0x%03x/%04d %4d", ddl, hwa, t, adc));
304
305   AliFMDParameters*    pars   = AliFMDParameters::Instance();
306   AliFMDAltroMapping*  map    = pars->GetAltroMap();
307
308   samp            = 0;
309   Short_t  stroff = 0;
310   map->Timebin2Strip(sec, t, fPreSamp, fSampleRate[ddl], stroff, samp);
311   str             = strbase + stroff;
312       
313   AliFMDDebug(20, ("0x%04x/0x%03x/%04d=%4d maps to strip %3d sample %d " 
314                    "(pre: %d, min: %d, max: %d, rate: %d)",
315                   ddl, hwa, t, adc, str, samp, fPreSamp, 
316                   fMinStrip, fMaxStrip, fSampleRate[ddl]));
317   if (str < 0) { 
318     AliFMDDebug(10, ("Got presamples at timebin %d", i));
319     return -1;
320   }
321           
322   // VA1 Local strip number 
323   Short_t lstrip = (t - fPreSamp) / fSampleRate[ddl] + fMinStrip;
324       
325   AliFMDDebug(15, ("Checking if strip %d (%d) in range [%d,%d]", 
326                    lstrip, str, fMinStrip, fMaxStrip));
327   if (lstrip < fMinStrip || lstrip > fMaxStrip) {
328     AliFMDDebug(10, ("Strip %03d-%d (%d,%d) from t=%d out of range (%3d->%3d)", 
329                     str, samp, lstrip, stroff, t, fMinStrip, fMaxStrip));
330     adc = -1;
331   }
332   // Possibly do pedestal subtraction of signal 
333   if (adc > 1023) 
334     AliWarning(Form("ADC value out of range: %4d", adc));
335   return adc;
336 }
337
338 //____________________________________________________________________
339 Bool_t
340 AliFMDRawReader::NextSample(UShort_t& det, Char_t&   rng, UShort_t& sec, 
341                             UShort_t& str, UShort_t& sam, UShort_t& rat, 
342                             Short_t&  adc, Bool_t&   zs,  UShort_t& fac)
343 {
344   // Scan current event for next signal.   It returns kFALSE when
345   // there's no more data in the event. 
346   static AliAltroRawStreamV3 stream(fReader); //    = 0;
347   static Int_t               ddl      = -1;
348   static UShort_t            tdet     = 0;
349   static Char_t              trng     = '\0';
350   static UShort_t            tsec     = 0;
351   static Short_t             tstr     = 0;   
352   static Short_t             bstr     = -1;
353   static UShort_t            tsam     = 0;   
354   static UInt_t              trate    = 0;
355   static Int_t               hwaddr   = -1;
356   static UShort_t            start    = 0;
357   static UShort_t            length   = 0;
358   static Short_t             t        = -1;
359   static Int_t               i        = 0; 
360   // First entry!
361   if (stream.GetDDLNumber() < 0) { 
362     fReader->Select("FMD");
363
364     // Reset variables
365     ddl    = -1;  
366     trate  = 0;   
367     tdet   = 0;   
368     trng   = '\0';
369     tsec   = 0;   
370     tstr   = 0;  
371     tsam   = -1;
372     hwaddr = -1;
373   }
374
375   do { 
376     if (t < start - length + 1) { 
377       if (!stream.NextBunch()) { 
378         if (!stream.NextChannel()) { 
379           if (!stream.NextDDL()) {
380             stream.Reset();
381             return kFALSE;
382           }
383           ddl = NewDDL(stream, tdet);
384         }
385         hwaddr = NewChannel(stream, tdet, trng, tsec, bstr);
386       }
387       start  = stream.GetStartTimeBin();
388       length = stream.GetBunchLength();
389       t      = start;
390       i      = 0;
391     }
392     Int_t tadc = NewSample(stream, i, t, tsec, bstr, tstr, tsam);
393     if (tadc >= 0) { 
394       det = tdet;
395       rng = trng;
396       sec = tsec;
397       str = tstr;
398       sam = tsam;
399       adc = tadc;
400       rat = fSampleRate[ddl];
401       zs  = fZeroSuppress[ddl];
402       fac = fNoiseFactor[ddl];
403       t--;
404       i++;
405       break;
406     }
407   } while (true);
408
409   return kTRUE;
410 }
411
412
413 //____________________________________________________________________
414 Bool_t
415 AliFMDRawReader::NextSignal(UShort_t& det, Char_t&   rng, 
416                             UShort_t& sec, UShort_t& str, 
417                             Short_t&  adc, Bool_t&   zs, 
418                             UShort_t& fac)
419 {
420   
421   do { 
422     UShort_t samp, rate;
423     if (!NextSample(det, rng, sec, str, samp, rate, adc, zs, fac)) 
424       return kFALSE;
425
426     Bool_t take = kFALSE;
427     switch (rate) { 
428     case 1:                      take = kTRUE; break;
429     case 2:  if (samp == 1)      take = kTRUE; break;
430     case 3:  if (samp == 1)      take = kTRUE; break; 
431     case 4:  if (samp == 2)      take = kTRUE; break;
432     default: if (samp == rate-2) take = kTRUE; break;
433     }
434     if (!take) continue;
435     break;
436   } while (true);
437   return kTRUE;
438 }
439
440 //____________________________________________________________________
441 Bool_t
442 AliFMDRawReader::SelectSample(UShort_t samp, UShort_t rate) 
443 {
444   // Check if the passed sample is the one we need
445   Bool_t take = kFALSE;
446   switch (rate) { 
447   case 1:                      take = kTRUE; break;
448   case 2:  if (samp == 1)      take = kTRUE; break;
449   case 3:  if (samp == 1)      take = kTRUE; break; 
450   case 4:  if (samp == 2)      take = kTRUE; break;
451   default: if (samp == rate-2) take = kTRUE; break;
452   }
453   
454   return take;
455 }
456   
457 //____________________________________________________________________
458 Bool_t
459 AliFMDRawReader::ReadAdcs(TClonesArray* array) 
460 {
461   // Read ADC values from raw input into passed TClonesArray of AliFMDDigit
462   // objects. 
463   AliFMDDebug(2, ("Reading ADC values into a TClonesArray"));
464
465   // Read raw data into the digits array, using AliFMDAltroReader. 
466   if (!array) {
467     AliError("No TClonesArray passed");
468     return kFALSE;
469   }
470   const UShort_t kUShortMax = (1 << 16) - 1;
471   fSeen.Reset(kUShortMax);
472
473   AliAltroRawStreamV3  input(fReader);
474   input.Reset();
475   input.SelectRawData("FMD");
476   
477   // Loop over input RORCs
478   while (input.NextDDL()) { 
479     UShort_t det = 0;
480     Int_t    ddl = NewDDL(input, det);
481     if (ddl < 0) break;
482
483     while (input.NextChannel()) { 
484       // Get the hardware address, and map that to detector coordinates 
485       Char_t   ring;
486       UShort_t sec;
487       Short_t  strbase;
488       Int_t    hwaddr = NewChannel(input, det, ring, sec, strbase);
489       if (hwaddr < 0) break;
490
491       // Loop over bunches 
492       while (input.NextBunch()) { 
493         // Get Lenght of bunch, and pointer to the data 
494         const UShort_t* data   = input.GetSignals();
495         UShort_t        start  = input.GetStartTimeBin();
496         UShort_t        length = input.GetBunchLength();
497       
498         // Loop over the data and store it. 
499         for (Int_t i = 0; i < length; i++) { 
500           // Time 
501           Short_t  str;
502           UShort_t samp;
503           Int_t    t    = start - i;
504           Int_t    adc  = NewSample(input, i, t, sec, strbase, str, samp);
505           if (adc < 0) continue;
506           UShort_t counts = adc;
507       
508           AliFMDDebug(10, ("FMD%d%c[%02d,%03d]-%d: %4d", 
509                            det, ring, sec, str, samp, counts));
510           // Check the cache of indicies
511           Int_t idx = fSeen(det, ring, sec, str);
512           AliFMDDigit* digit = 0;
513           if (idx == kUShortMax) { 
514             // We haven't seen this strip yet. 
515             fSeen(det, ring, sec, str) = idx = array->GetEntriesFast();
516             AliFMDDebug(7,("making digit for FMD%d%c[%2d,%3d]-%d "
517                            "from timebin %4d", 
518                            det, ring, sec, str, samp, t));
519             digit = new ((*array)[idx]) AliFMDDigit(det, ring, sec, str);
520             digit->SetDefaultCounts(fSampleRate[ddl]);
521           }
522           else 
523             digit = static_cast<AliFMDDigit*>(array->At(idx));
524           AliFMDDebug(10, ("Setting FMD%d%c[%2d,%3d]-%d "
525                            "from timebin %4d=%4d (%4d)", 
526                            det, ring, sec, str, samp, t, counts, data[i]));
527           digit->SetCount(samp, counts);
528         } // for (i)
529       } // while (bunch)
530     } // while (channel)
531   } // while (ddl)
532   return kTRUE;
533 }
534
535 //____________________________________________________________________
536 Bool_t AliFMDRawReader::ReadSODevent(AliFMDCalibSampleRate* sampleRate, 
537                                      AliFMDCalibStripRange* stripRange, 
538                                      TArrayS &pulseSize, 
539                                      TArrayS &pulseLength, 
540                                      Bool_t* detectors) 
541 {
542
543   AliFMDDebug(0, ("Start of SOD/EOD"));
544   
545   UInt_t shift_clk[18];
546   UInt_t sample_clk[18];
547   UInt_t strip_low[18];
548   UInt_t strip_high[18];
549   UInt_t pulse_size[18];
550   UInt_t pulse_length[18];  
551   AliFMDParameters*   param = AliFMDParameters::Instance();
552   AliFMDAltroMapping* map   = param->GetAltroMap();
553   
554   AliAltroRawStreamV3  streamer(fReader);
555   streamer.Reset();
556   streamer.SelectRawData("FMD");
557   //fReader->GetDDLID();
558   while (streamer.NextDDL()) {
559     Int_t ddl   = streamer.GetDDLNumber();
560     Int_t detID = fReader->GetDetectorID();
561     if (detectors) detectors[map->DDL2Detector(ddl)-1] = kTRUE;
562     AliFMDDebug(0, (" From reader: DDL number is %d , det ID is %d",ddl,detID));
563
564     ULong_t  nPayloadWords = streamer.GetRCUPayloadSizeInSOD();
565     UChar_t* payloadData   = streamer.GetRCUPayloadInSOD();
566     UInt_t*  payloadWords  = reinterpret_cast<UInt_t*>(payloadData);
567     //UInt_t*   payloadWords  = streamer.GetRCUPayloadInSOD();
568
569     //std::cout<<nPayloadWords<<"    "<<ddl<<std::endl;
570     for (ULong_t i = 1; i <= nPayloadWords ; i++, payloadWords++) {
571       UInt_t payloadWord = *payloadWords; // Get32bitWord(i);
572     
573       //std::cout<<i<<Form("  word: 0x%x",payloadWord)<<std::endl;
574       // address is only 24 bit
575       UInt_t address       = (0xffffff & payloadWord);
576       UInt_t type          = ((address >> 21) & 0xf);
577       UInt_t error         = ((address >> 20) & 0x1);
578       UInt_t bcast         = ((address >> 18) & 0x1);
579       UInt_t bc_not_altro  = ((address >> 17) & 0x1);
580       UInt_t board         = ((address >> 12) & 0x1f);
581       UInt_t instruction   = 0;
582       UInt_t chip          = 0;
583       UInt_t channel       = 0;
584       if(bc_not_altro)
585         instruction        = address & 0xfff;
586       else {
587         chip               = ((address >> 9) & 0x7);
588         channel            = ((address >> 5) & 0x5);
589         instruction        = (address & 0x1f);
590       }
591         
592       Bool_t readDataWord = kFALSE;
593       switch(type) {
594       case 0x0: // Fec read
595         readDataWord = kTRUE;  
596       case 0x1: // Fec cmd
597       case 0x2: // Fec write
598         i++;  
599         payloadWords++;
600         break;
601       case 0x4: // Loop
602       case 0x5: // Wait
603         break;
604       case 0x6: // End sequence
605       case 0x7: // End Mem
606         i = nPayloadWords + 1;
607         break;
608       default:    
609         break;
610       }
611         
612       //Don't read unless we have a FEC_RD
613       if(!readDataWord)  continue;
614
615       UInt_t dataWord      = *payloadWords;//Get32bitWord(i);
616       UInt_t data          = (0xFFFFF & dataWord) ;
617       //UInt_t data          = (0xFFFF & dataWord) ;
618         
619       if(error) {
620         AliWarning(Form("error bit detected at Word 0x%06x; "
621                         "error % d, type %d, bc_not_altro %d, "
622                         "bcast %d, board 0x%02x, chip 0x%x, "
623                         "channel 0x%02x, instruction 0x%03x",
624                         address, error, type, bc_not_altro, 
625                         bcast,board,chip,channel,instruction));
626         //process error
627         continue;
628       }
629         
630         
631       switch(instruction) {
632           
633       case 0x01: break;  // First ADC T           
634       case 0x02: break; // I  3.3 V              
635       case 0x03: break; // I  2.5 V altro digital
636       case 0x04: break; // I  2.5 V altro analog 
637       case 0x05: break; // I  2.5 V VA           
638       case 0x06: break; // First ADC T           
639       case 0x07: break; // I  3.3 V              
640       case 0x08: break; // I  2.5 V altro digital
641       case 0x09: break; // I  2.5 V altro analog 
642       case 0x0A: break; // I  2.5 V VA           
643       case 0x2D: break; // Second ADC T           
644       case 0x2E: break; // I  1.5 V VA            
645       case 0x2F: break; // I -2.0 V               
646       case 0x30: break; // I -2.0 V VA            
647       case 0x31: break; //    2.5 V Digital driver
648       case 0x32: break; // Second ADC T           
649       case 0x33: break; // I  1.5 V VA            
650       case 0x34: break; // I -2.0 V               
651       case 0x35: break; // I -2.0 V VA            
652       case 0x36: break; //    2.5 V Digital driver
653       case 0x37: break; // Third ADC T             
654       case 0x38: break; // Temperature sens. 1     
655       case 0x39: break; // Temperature sens. 2     
656       case 0x3A: break; // U  2.5 altro digital (m)
657       case 0x3B: break; // U  2.5 altro analog (m) 
658       case 0x3C: break; // Third ADC T             
659       case 0x3D: break; // Temperature sens. 1     
660       case 0x3E: break; // Temperature sens. 2     
661       case 0x3F: break; // U  2.5 altro digital (m)
662       case 0x40: break; // U  2.5 altro analog (m) 
663       case 0x41: break; // Forth ADC T  
664       case 0x42: break; // U  2.5 VA (m)
665       case 0x43: break; // U  1.5 VA (m)
666       case 0x44: break; // U -2.0 VA (m)
667       case 0x45: break; // U -2.0 (m)   
668       case 0x46: break; // Forth ADC T  
669       case 0x47: break; // U  2.5 VA (m)
670       case 0x48: break; // U  1.5 VA (m)
671       case 0x49: break; // U -2.0 VA (m)
672       case 0x4A: break;  // U -2.0 (m)   
673         // Counters 
674       case 0x0B: break; // L1 trigger CouNTer
675       case 0x0C: break; // L2 trigger CouNTer
676       case 0x0D: break; // Sampling CLK CouNTer
677       case 0x0E: break; // DSTB CouNTer
678         // Test mode 
679       case 0x0F: break; // Test mode word
680       case 0x10: break; // Undersampling ratio.
681         // Configuration and status 
682       case 0x11: break; // Config/Status Register 0
683       case 0x12: break; // Config/Status Register 1
684       case 0x13: break; // Config/Status Register 2
685       case 0x14: break; // Config/Status Register 3
686       case 0x15: break; // Free
687         // Comands:
688       case 0x16: break; // Latch L1, L2, SCLK Counters
689       case 0x17: break; // Clear counters
690       case 0x18: break; // Clear CSR1
691       case 0x19: break; // rstb ALTROs
692       case 0x1A: break; // rstb BC
693       case 0x1B: break; // Start conversion
694       case 0x1C: break; // Scan event length
695       case 0x1D: break; // Read event length
696       case 0x1E: break; // Start test mode
697       case 0x1F: break; // Read acquisition memory
698         // FMD
699       case 0x20: break; // FMDD status
700       case 0x21: break; // L0 counters
701       case 0x22: break; // FMD: Wait to hold
702       case 0x23: break; // FMD: L1 timeout
703       case 0x24: break; // FMD: L2 timeout
704       case 0x25: // FMD: Shift clk 
705         shift_clk[board] = ((data >> 8 ) & 0xFF); 
706         break; 
707       case 0x26: // FMD: Strips 
708         strip_low[board]  = ((data >> 0 ) & 0xFF); 
709         strip_high[board] = ((data >> 8 ) & 0xFF);  
710         break; 
711       case 0x27: // FMD: Cal pulse 
712         pulse_size[board]  =  ((data >> 8 ) & 0xFF);
713         break; 
714       case 0x28: break; // FMD: Shape bias
715       case 0x29: break; // FMD: Shape ref
716       case 0x2A: break; // FMD: Preamp ref
717       case 0x2B: // FMD: Sample clk 
718         sample_clk[board] = ((data >> 8 ) & 0xFF); 
719         break; 
720       case 0x2C: break; // FMD: Commands
721       case 0x4B: // FMD: Cal events 
722         pulse_length[board] = ((data >> 0 ) & 0xFF);
723         break; 
724       default: break;
725         
726       }
727       AliFMDDebug(50, ("instruction 0x%x, dataword 0x%x",
728                        instruction,dataWord));
729     } // End of loop over Result memory event
730     
731     UShort_t det,sector;
732     Short_t strip;
733     Char_t ring;
734    
735     const UInt_t boards[4] = {0,1,16,17};
736     for(Int_t i=0;i<4;i++) {
737       if(ddl==0 && (i==1 || i==3)) continue;
738
739       UInt_t chip =0, channel=0;
740       det = map->DDL2Detector(ddl);
741       map->Channel2StripBase(boards[i], chip, channel, ring, sector, strip);
742      
743       UInt_t samplerate = 1;
744       if(sample_clk[boards[i]] == 0) {
745         if(ddl == 0) {
746           Int_t sample1 = sample_clk[boards[0]];
747           Int_t sample2 = sample_clk[boards[2]];            
748           if(sample1) sample_clk[boards[i]] = sample1;
749           else sample_clk[boards[i]] = sample2;
750         }
751         else {
752           Int_t sample1 = sample_clk[boards[0]];
753           Int_t sample2 = sample_clk[boards[1]];
754           Int_t sample3 = sample_clk[boards[2]];
755           Int_t sample4 = sample_clk[boards[3]];
756           Int_t agreement = 0;
757           if(sample1 == sample2) agreement++;
758           if(sample1 == sample3) agreement++;
759           if(sample1 == sample4) agreement++;
760           if(sample2 == sample3) agreement++;
761           if(sample2 == sample4) agreement++;
762           if(sample3 == sample4) agreement++;
763             
764           Int_t idx = 0;
765           if(i<3) idx = i+1;
766           else  idx = i-1;
767           if(agreement == 3) {
768             sample_clk[boards[i]] = sample_clk[boards[idx]];
769             shift_clk[boards[i]] = shift_clk[boards[idx]];
770             strip_low[boards[i]] = strip_low[boards[idx]];
771             strip_high[boards[i]] = strip_high[boards[idx]];
772             pulse_length[boards[i]] = pulse_length[boards[idx]];
773             pulse_size[boards[i]] = pulse_size[boards[idx]];
774             AliFMDDebug(0, ("Vote taken for ddl %d, board 0x%x",
775                             ddl,boards[i]));
776           }
777         }
778       } 
779       
780       if(sample_clk[boards[i]])
781         samplerate = shift_clk[boards[i]]/sample_clk[boards[i]];
782       sampleRate->Set(det,ring,sector,0,samplerate);
783       stripRange->Set(det,ring,sector,0,
784                       strip_low[boards[i]],strip_high[boards[i]]);
785       
786       AliFMDDebug(20, ("det %d, ring %c, ",det,ring));
787       pulseLength.AddAt(pulse_length[boards[i]],
788                         GetHalfringIndex(det,ring,boards[i]/16));
789       pulseSize.AddAt(pulse_size[boards[i]],
790                       GetHalfringIndex(det,ring,boards[i]/16));
791       
792       
793       
794       AliFMDDebug(20, (": Board: 0x%02x\n"
795                        "\tstrip_low  %3d, strip_high   %3d\n"
796                        "\tshift_clk  %3d, sample_clk   %3d\n"
797                        "\tpulse_size %3d, pulse_length %3d",
798                        boards[i], 
799                        strip_low[boards[i]], strip_high[boards[i]],
800                        shift_clk[boards[i]], sample_clk[boards[i]],
801                        pulse_size[boards[i]],pulse_length[boards[i]]));
802       }
803     
804     }
805   
806   AliFMDParameters::Instance()->SetSampleRate(sampleRate);
807   AliFMDParameters::Instance()->SetStripRange(stripRange);
808   
809   AliFMDDebug(0, ("End of SOD/EOD"));
810   
811   return kTRUE;
812 }
813 //____________________________________________________________________
814
815 UInt_t AliFMDRawReader::Get32bitWord(Int_t idx)
816 {
817   // This method returns the 32 bit word at a given
818   // position inside the raw data payload.
819   // The 'index' points to the beginning of the next word.
820   // The method is supposed to be endian (platform)
821   // independent.
822   if (!fData) {
823     AliFatal("Raw data paylod buffer is not yet initialized !");
824   }
825
826   Int_t index = 4*idx;
827   
828   if (index < 4) {
829     //  fRawReader->AddFatalErrorLog(k32bitWordReadErr,Form("pos = %d",index));
830     //    PrintDebug();
831     AliWarning(Form("Invalid raw data payload position (%d) !",index));
832   }
833
834   UInt_t word = 0;
835    
836   word  = fData[--index] << 24;
837   word |= fData[--index] << 16;
838   word |= fData[--index] << 8;
839   word |= fData[--index] << 0 ;
840
841   return word;
842 }
843 //_____________________________________________________________________ 
844 Int_t AliFMDRawReader::GetHalfringIndex(UShort_t det, Char_t ring, 
845                                         UShort_t board) {
846
847   UShort_t iring  =  (ring == 'I' ? 1 : 0);
848   
849   Int_t index = (((det-1) << 2) | (iring << 1) | (board << 0));
850   
851   return index-2;
852   
853 }
854
855 //____________________________________________________________________
856 // 
857 // EOF
858 //
859