#include "Digitizer.h"

void Digitizer::DigitizeDummy() {

//   fhBookTree->SetBranchStatus("Enestrip",1);//modified by E.Vannuccini 03/08

  // dumy header
  fDataDummy[0] = 0xCAAA;

  for (Int_t i=1; i<fDummybuffer; i++){
    fDataDummy[i] = 0xFFFF;
    //   printf("%0x  ",fDataDummy[i]);   
    //if ((i+1)%8 ==0) cout << endl;
  }
};


void Digitizer::DigitizeTrack() {
//std:: cout << "Entering DigitizeTrack " << endl;
Float_t  AdcTrack[fNviews][fNstrips_view];  //  Vector of strips to be compressed

Int_t Iview;
Int_t Nstrip;

  for (Int_t j=0; j<fNviews;j++) {

    for (Int_t i=0; i<fNladder;i++) {

      Float_t commonN1=gRandom->Gaus(0.,fSigmaCommon);
      Float_t commonN2=gRandom->Gaus(0.,fSigmaCommon);
      for (Int_t k=0; k<fNstrips_ladder;k++) {
      Nstrip=i*fNstrips_ladder+k;
      Float_t Sigma=fabs(fSigmaTrack[j][Nstrip]);
      AdcTrack[j][Nstrip]=gRandom->Gaus(fPedeTrack[j][Nstrip],Sigma );
      if(k<4*128) {AdcTrack[j][Nstrip] += commonN1;}  // full correlation of 4 VA1 Com. Noise
      else {AdcTrack[j][Nstrip] += commonN2;}   // full correlation of 4 VA1 Com. Noise
      if(AdcTrack[j][Nstrip] < 0. ) AdcTrack[j][Nstrip]=0.;
      if(AdcTrack[j][Nstrip] > 4095.) AdcTrack[j][Nstrip]=4095.;
//      if(AdcTrack[j][Nstrip] < 10. ) cout << "j= " << j << "Nstrip= " << Nstrip <<"AdcTrack[j][Nstrip] " <<  AdcTrack[j][Nstrip]  << endl;
      };
      
        
    };


  }; 


//   fhBookTree->SetBranchStatus("Nstrpx",1);//modified by E.Vannuccini 03/08
//   fhBookTree->SetBranchStatus("Npstripx",1);
//   fhBookTree->SetBranchStatus("Ntstripx",1);
//   fhBookTree->SetBranchStatus("Istripx",1);
//   fhBookTree->SetBranchStatus("Qstripx",1);
//   fhBookTree->SetBranchStatus("Xstripx",1);
//   fhBookTree->SetBranchStatus("Nstrpy",1);
//   fhBookTree->SetBranchStatus("Npstripy",1);
//   fhBookTree->SetBranchStatus("Ntstripy",1);
//   fhBookTree->SetBranchStatus("Istripy",1);
//   fhBookTree->SetBranchStatus("Qstripy",1);
//   fhBookTree->SetBranchStatus("Ystripy",1);


  Float_t ADCfull;
  Int_t iladd=0;
  for (Int_t ix=0; ix<Nstrpx;ix++) {
  Iview=Npstripx[ix]*2-1;
  Nstrip=(Int_t)Istripx[ix]-1;
  if(Nstrip<fNstrips_ladder) iladd=0;
  if((Nstrip>=fNstrips_ladder)&&(Nstrip<2*fNstrips_ladder)) iladd=1;
  if((Nstrip>=2*fNstrips_ladder)&&(Nstrip<3*fNstrips_ladder)) iladd=2;
  ADCfull=AdcTrack[Iview][Nstrip] += Qstripx[ix]*fMipCor[iladd][Iview];
  AdcTrack[Iview][Nstrip] *= SaturationTrackx(ADCfull);

  };


  for (Int_t iy=0; iy<Nstrpy;iy++) {
  Iview=Npstripy[iy]*2-2;
  Nstrip=(Int_t)Istripy[iy]-1;
  if(Nstrip<fNstrips_ladder) iladd=0;
  if((Nstrip>=fNstrips_ladder)&&(Nstrip<2*fNstrips_ladder)) iladd=1;
  if((Nstrip>=2*fNstrips_ladder)&&(Nstrip<3*fNstrips_ladder)) iladd=2;
  ADCfull=AdcTrack[Iview][Nstrip] -= Qstripy[iy]*fMipCor[iladd][Iview];
  AdcTrack[Iview][Nstrip] *= SaturationTracky(ADCfull);

  };  
      
CompressTrackData(AdcTrack);  // Compress and Digitize data of one Ladder  in turn for all ladders

};



void Digitizer::DigitizeTrackCalib(Int_t ii) {

std:: cout << "Entering DigitizeTrackCalib " << ii << endl;
if( (ii!=1)&&(ii!=2) ) {
 std:: cout << "error wrong DigitizeTrackCalib argument" << endl;
 return;
}; 

memset(fDataTrack,0,sizeof(UShort_t)*fTRACKbuffer);
fTracklength=0;

UShort_t Dato;

Float_t dato1;
Float_t dato2;
Float_t dato3;
Float_t dato4;

UShort_t DatoDec;
UShort_t DatoDec1;
UShort_t DatoDec2;
UShort_t DatoDec3;
UShort_t DatoDec4;

UShort_t EVENT_CAL;
UShort_t PED_L1;
UShort_t ReLength;
UShort_t OveCheckCode;
//UShort_t PED_L2;
//UShort_t PED_L3HI;
//UShort_t PED_L3LO;
//UShort_t SIG_L1HI;
//UShort_t SIG_L1LO;
//UShort_t SIG_L2HI;
//UShort_t SIG_L2LO;
//UShort_t SIG_L3;
//UShort_t BAD_L1;
//UShort_t BAD_L2LO;
//UShort_t BAD_L3HI;
//UShort_t BAD_L3LO;
//UShort_t FLAG;


  Int_t DSPpos;
  for (Int_t j=ii-1; j<fNviews;j+=2) {
  UShort_t CkSum=0;
  // here skip the dsp header and his trailer , to be written later
  DSPpos=fTracklength;
  fTracklength=fTracklength+13+3;


    for (Int_t i=0; i<fNladder;i++) {
      for (Int_t k=0; k<fNstrips_ladder;k++) {
      // write in buffer the current LADDER
      Dato=(UShort_t)fPedeTrack[j][i*fNstrips_ladder+k];
      dato1=fPedeTrack[j][i*fNstrips_ladder+k]-Dato; 

      DatoDec1=(UShort_t)(dato1*2);
      dato2=dato1*2-DatoDec1;

      DatoDec2=(UShort_t)(dato2*2);
      dato3=dato2*2-DatoDec2;
      
      DatoDec3=(UShort_t)(dato3*2);
      dato4=dato3*2-DatoDec3;
      
      DatoDec4=(UShort_t)(dato4*2);
      
      DatoDec=DatoDec1*0x0008+DatoDec2*0x0004+DatoDec3*0x0002+DatoDec4*0x0001;
      fDataTrack[fTracklength]=( (Dato << 4) | (DatoDec & 0x000F) );
      CkSum=CkSum^fDataTrack[fTracklength];
      fTracklength++;
      };

      for (Int_t k=0; k<fNstrips_ladder;k++) {
      // write in buffer the current LADDER
      
      Dato=(UShort_t)fabs(fSigmaTrack[j][i*fNstrips_ladder+k]); 
      dato1=fabs(fSigmaTrack[j][i*fNstrips_ladder+k])-Dato; 

      DatoDec1=(UShort_t)(dato1*2);
      dato2=dato1*2-DatoDec1;

      DatoDec2=(UShort_t)(dato2*2);
      dato3=dato2*2-DatoDec2;
      
      DatoDec3=(UShort_t)(dato3*2);
      dato4=dato3*2-DatoDec3;
      
      DatoDec4=(UShort_t)(dato4*2);
      
      DatoDec=DatoDec1*0x0008+DatoDec2*0x0004+DatoDec3*0x0002+DatoDec4*0x0001;
      
      fDataTrack[fTracklength]=( (Dato << 4) | (DatoDec & 0x000F) );
      CkSum=CkSum^fDataTrack[fTracklength];
      fTracklength++;
      };
      
      for (Int_t k=0; k<64;k++) {
        UShort_t DatoBad=0x0000;
        for (Int_t nb=0; nb<16;nb++) {
	  if( fSigmaTrack[j][i*fNstrips_ladder+k*16+nb]<0. ) DatoBad=( DatoBad | (0x8000 >> nb) ); 	

	};
      fDataTrack[fTracklength]=DatoBad;
      CkSum=CkSum^fDataTrack[fTracklength];
      fTracklength++;

      };
      // end ladder

    // write in buffer the end ladder word
    if(i==0) fDataTrack[fTracklength]=0x1807;
    if(i==1) fDataTrack[fTracklength]=0x1808;
    if(i==2) fDataTrack[fTracklength]=0x1809;
    CkSum=CkSum^fDataTrack[fTracklength];
    fTracklength++;

    // write in buffer the TRAILER
    ReLength=(UShort_t)((fNstrips_ladder*2+64+1)*2+3);
    OveCheckCode=0x0000;

    fDataTrack[fTracklength]=0x0000;
    fTracklength++;
  
    fDataTrack[fTracklength]=(ReLength >> 8);
    fTracklength++;
  
    fDataTrack[fTracklength]=( (ReLength << 8) | (OveCheckCode & 0x00FF) );
    fTracklength++;

    // end TRAILER        
    };

  // write in buffer the DSP header

  fDataTrack[DSPpos]=(0xE800 | ( ((j+1) << 3) | 0x0005) );
  
  fDataTrack[DSPpos+1]=0x01A9;

  fDataTrack[DSPpos+2]=0x8740;
   
  EVENT_CAL=0;
  fDataTrack[DSPpos+3]=(0x1A00 | ( (0x03FF & EVENT_CAL)>> 1) );
   
  PED_L1=0;
  fDataTrack[DSPpos+4]=( ((EVENT_CAL << 15) | 0x5002 ) | ((0x03FF & PED_L1) << 2) );
  
  // FROM HERE WE WRITE AS ALL VARIABLE apart CkSum are =0   

  fDataTrack[DSPpos+5]=0x8014;
  
  fDataTrack[DSPpos+6]=0x00A0;
  
  fDataTrack[DSPpos+7]=0x0500;
  
  fDataTrack[DSPpos+8]=0x2801;
  
  fDataTrack[DSPpos+9]=0x400A;
   
  fDataTrack[DSPpos+10]=0x0050;
  
  CkSum=(CkSum >> 8)^(CkSum&0x00FF);
  fDataTrack[DSPpos+11]=(0x0280 | (CkSum >> 3));
  
  fDataTrack[DSPpos+12]=(0x1FFF | (CkSum << 13) );

  // end dsp header

  // write in buffer the TRAILER
  
  ReLength=(UShort_t)((13*2)+3);
  OveCheckCode=0x0000;
  fDataTrack[DSPpos+13]=0x0000;

  fDataTrack[DSPpos+14]=(ReLength >> 8);
   
  fDataTrack[DSPpos+15]=( (ReLength << 8) | (OveCheckCode & 0x00FF) );
  
  // end TRAILER



   
  // end DSP    
  };    



};

void Digitizer::WriteTrackCalib() {


std:: cout << " Entering WriteTrackCalib " << endl;

fOutputfile.write(reinterpret_cast<char*>(fDataPSCU),sizeof(UShort_t)*fPSCUbuffer);

UShort_t temp[1000000];
memset(temp,0,sizeof(UShort_t)*1000000);
swab(fDataTrack,temp,sizeof(UShort_t)*fTracklength);  // WE MUST SWAP THE BYTES!!!
fOutputfile.write(reinterpret_cast<char*>(temp),sizeof(UShort_t)*fTracklength); 
fTracklength=0; 
if ( fPadding ){
      fOutputfile.write(reinterpret_cast<char*>(fDataPadding),sizeof(UChar_t)*fPadding);
};

};


void Digitizer::ClearTrackCalib() {

std:: cout << "Entering ClearTrackCalib " << endl;
     
  
};


void Digitizer::LoadTrackCalib() {
std:: cout << "Entering LoadTrackCalib " << endl;


// prepare correction factors
Float_t sigmacorr[12];
sigmacorr[0]=1.;
sigmacorr[1]=1.;
sigmacorr[2]=1.;
sigmacorr[3]=1.;
sigmacorr[4]=1.;
sigmacorr[5]=1.;
sigmacorr[6]=1.;
sigmacorr[7]=1.;
sigmacorr[8]=1.;
sigmacorr[9]=1.;
sigmacorr[10]=1.;
sigmacorr[11]=1.;

stringstream calibfile;
Int_t error = 0;
TFile *FileCalib= NULL;

GL_PARAM *glparam = new GL_PARAM();
error = 0;
error = glparam->Query_GL_PARAM(0,8,fDbc);

if(error<0) {
 FileCalib = new TFile("CalibTrk_00110_000_000.root"); 
 printf("\n No entry in Database. Use file tracker GP calibration From Main Directory\n");
} else {
 //
 calibfile.str("");
 calibfile << glparam->PATH.Data() << "/";
 calibfile << glparam->NAME.Data();
 //
 printf("\n Using GP calibration file for tracker : \n %s \n",calibfile.str().c_str());
 FileCalib = new TFile( calibfile.str().c_str() );


 if ( FileCalib==NULL ) {
  FileCalib = new TFile("CalibTrk_00110_000_000.root");
  printf("\n No file in Database.Use file tracker GP calibration From Main Directory\n");
 } else {
  if ( FileCalib->IsZombie() ) {
  FileCalib = new TFile("CalibTrk_00110_000_000.root");
  printf("\n No file in Database. Use file tracker GP calibration From Main Directory\n");
  };


 };
};

TTree *tr1 = (TTree*)FileCalib->Get("CalibTrk1");
CalibTrk1Event *calibdata1 = 0;
tr1->SetBranchAddress("CalibTrk1",&calibdata1);
tr1->GetEntry(1);


Int_t ixbr=0;
Int_t iybr=0;
Int_t iva1=0;
Int_t Kview=0;
Int_t jj=0;
for (Int_t i=0; i<6;i++) {

for (Int_t j=0; j<3072;j++) {

jj=j;

// broken va1 replaced
ixbr=0;
iva1=4;
if(i==ixbr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));

ixbr=5;
iva1=12;
if(i==ixbr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));
//

//Kview=11-(i*2);
Kview=calibdata1->DSPnumber[i]-1;
fPedeTrack[Kview][j]=calibdata1->DSPped_par[i][jj];
fSigmaTrack[Kview][j]=sigmacorr[Kview]*calibdata1->DSPsig_par[i][jj];
if(calibdata1->DSPbad_par[i][jj]==1) fSigmaTrack[Kview][j]=-fSigmaTrack[Kview][j];

 };
};

TTree *tr2 = (TTree*)FileCalib->Get("CalibTrk2");
CalibTrk2Event *calibdata2 = 0;
tr2->SetBranchAddress("CalibTrk2",&calibdata2);
tr2->GetEntry(1);
for (Int_t i=0; i<6;i++) {

for (Int_t j=0; j<3072;j++) {
jj=j;

// broken va1 replaced
iybr=2;
iva1=3;
if(i==iybr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));

iybr=2;
iva1=5;
if(i==iybr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));

iybr=2;
iva1=6;
if(i==iybr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));


iybr=2;
iva1=7;
if(i==iybr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));   


iybr=2;
iva1=11;
if(i==iybr && j>=(256*(iva1-1)) && j<(256*iva1)) jj=j-(256*(iva1-1));   
//

//Kview=11-(i*2+1);
Kview=calibdata2->DSPnumber[i]-1;
fPedeTrack[Kview][j]=calibdata2->DSPped_par[i][jj];
fSigmaTrack[Kview][j]=sigmacorr[Kview]*calibdata2->DSPsig_par[i][jj];
if(calibdata2->DSPbad_par[i][jj]==1) fSigmaTrack[Kview][j]=-fSigmaTrack[Kview][j];

 };
};



FileCalib->Close();
delete glparam;
// Generate the pedestals and sigmas according to parametrization
//  for (Int_t j=0; j<fNviews;j++) {
//    for (Int_t i=0; i<fNstrips_view;i++) {
    
//    if((j+1)%2==0) {
//    fPedeTrack[j][i]=gRandom->Gaus(fAvePedex,fSigmaPedex);
//    fSigmaTrack[j][i]=gRandom->Gaus(fAveSigmax,fSigmaSigmax);
//    std:: cout << "j= " << j+1 << "i= " << i+1 <<"X ! fPedeTrack[j][i] " << fPedeTrack[j][i] << endl;
//    std:: cout << "j= " << j+1 << "i= " << i+1 <<"X ! fSigmaTrack[j][i] " << fSigmaTrack[j][i] << endl;
//    if (fSigmaTrack[j][i]<0.1) { fSigmaTrack[j][i]=0.1 ; };
    
//    };
//    if((j+1)%2==1) {
//    fPedeTrack[j][i]=gRandom->Gaus(fAvePedey,fSigmaPedey);
//    fSigmaTrack[j][i]=gRandom->Gaus(fAveSigmay,fSigmaSigmay);
//    std:: cout << "j= " << j+1 << "i= " << i+1 <<"Y ! fPedeTrack[j][i] " << fPedeTrack[j][i] << endl;
//    std:: cout << "j= " << j+1 << "i= " << i+1 <<"Y ! fSigmaTrack[j][i] " << fSigmaTrack[j][i] << endl;
//    };
//    
//    };
//  };    

   
  
};

void Digitizer::LoadMipCor() {
std:: cout << "Entering LoadMipCor" << endl;
  Float_t xfactor=1./151.6*1.04;
  Float_t yfactor=1./152.1;

  fMipCor[0][0]=140.02*yfactor;
  fMipCor[0][1]=140.99*xfactor;
  fMipCor[0][2]=134.48*yfactor;
  fMipCor[0][3]=144.41*xfactor;
  fMipCor[0][4]=140.74*yfactor;
  fMipCor[0][5]=142.28*xfactor;
  fMipCor[0][6]=134.53*yfactor;
  fMipCor[0][7]=140.63*xfactor;
  fMipCor[0][8]=135.55*yfactor;
  fMipCor[0][9]=138.00*xfactor;
  fMipCor[0][10]=154.95*yfactor;
  fMipCor[0][11]=158.44*xfactor;
  
  
  fMipCor[1][0]=136.07*yfactor;
  fMipCor[1][1]=135.59*xfactor;
  fMipCor[1][2]=142.69*yfactor;
  fMipCor[1][3]=138.19*xfactor;
  fMipCor[1][4]=137.35*yfactor;
  fMipCor[1][5]=140.23*xfactor;
  fMipCor[1][6]=153.15*yfactor;
  fMipCor[1][7]=151.42*xfactor;
  fMipCor[1][8]=129.76*yfactor;
  fMipCor[1][9]=140.63*xfactor;
  fMipCor[1][10]=157.87*yfactor;
  fMipCor[1][11]=153.64*xfactor;

  fMipCor[2][0]=134.98*yfactor;
  fMipCor[2][1]=143.95*xfactor;
  fMipCor[2][2]=140.23*yfactor;
  fMipCor[2][3]=138.88*xfactor;
  fMipCor[2][4]=137.95*yfactor;
  fMipCor[2][5]=134.87*xfactor;
  fMipCor[2][6]=157.56*yfactor;
  fMipCor[2][7]=157.31*xfactor;
  fMipCor[2][8]=141.37*yfactor;
  fMipCor[2][9]=143.39*xfactor;
  fMipCor[2][10]=156.15*yfactor;
  fMipCor[2][11]=158.79*xfactor;

/*
  for (Int_t j=0; j<fNviews;j++) {
    for (Int_t i=0; i<fNstrips_view;i++) {
    fMipCor[j][i]=1.;
    };
  };    

     
*/  
};

void Digitizer::CompressTrackData(Float_t AdcTrack[fNviews][fNstrips_view]) {
// copy of the corresponding compression fortran routine + new digitization
// std:: cout << "Entering CompressTrackData " << endl;
Int_t oldval=0;
Int_t newval=0;
Int_t trasmesso=0;
Int_t ntrastot=0;
Float_t real;
Float_t inte;
Int_t cercacluster=0;
Int_t kt=0;
static const int DSPbufferSize = 4000; // 13 bit buffer to be rearranged in 16 bit Track buffer
UShort_t DataDSP[DSPbufferSize];  // 13 bit  buffer to be rearranged in 16 bit Track buffer
UShort_t DSPlength;  // 13 bit buffer to be rearranged in 16 bit Track buffer

memset(fDataTrack,0,sizeof(UShort_t)*fTRACKbuffer); // probably not necessary becouse already done ?
fTracklength=0;

  for (Int_t iv=0; iv<fNviews;iv++) {
  memset(DataDSP,0,sizeof(UShort_t)*DSPbufferSize);
  DSPlength=16; // skip the header, to be written later
  UShort_t CheckSum=0;
// write dsp header on buffer

//    fDataTrack[fTracklength]=0xE805;
//    fTracklength++;

//    fDataTrack[fTracklength]=0x01A9;
//    fTracklength++;

// end dsp header

   //
   // INIZIO VISTA IV - TAKE PROPER ACTION
   //



    for (Int_t ladder=0; ladder<fNladder;ladder++) {
      Int_t k=0;
      while (k<fNstrips_ladder) {
        // compress write in buffer the current LADDER
        if ( k == 0)  {
	  real=modff(AdcTrack[iv][ladder*fNstrips_ladder+k],&inte);
          if (real > 0.5) inte=inte+1;
          newval=(Int_t)inte -(Int_t)fPedeTrack[iv][ladder*fNstrips_ladder+k];
          // first strip of ladder is transmitted
          // DC_TOT first " << AdcTrack[iv][ladder*fNstrips_ladder+k] << endl;
	  DataDSP[DSPlength]=( ((UShort_t)inte) & 0x0FFF);
	  DSPlength++;  
          ntrastot++;
          trasmesso=1;
          oldval=newval;
	  kt=k;
	  k++;
	  continue; 
        };
	real=modff(AdcTrack[iv][ladder*fNstrips_ladder+k],&inte);
        if (real > 0.5) inte=inte+1;
        newval=(Int_t)inte -(Int_t)(fPedeTrack[iv][ladder*fNstrips_ladder+k]);
        cercacluster=1; // ????????? 
        if (cercacluster==1) {
	
 // controlla l'ordine di tutti queste strip ladder e DSP !!!!!!!	
          Int_t diff=0;

	  
	  switch ((iv+1)%2) {
	  case 0: diff=newval-oldval;
	  break;
	  case 1: diff=oldval-newval;	  
          break;
	  };

	  if (diff>fCutclu*(Int_t)fabs(fSigmaTrack[iv][ladder*fNstrips_ladder+k]) ) {
            Int_t clval=newval;
            Int_t klp=k;	// go on to search for maximum 
            klp++;

            while(klp<fNstrips_ladder) {
	      real=modff(AdcTrack[iv][ladder*fNstrips_ladder+klp],&inte);
              if (real > 0.5) inte=inte+1;
              Int_t clvalp=(Int_t)inte -(Int_t)fPedeTrack[iv][ladder*fNstrips_ladder+klp];
	      if((iv+1)%2==0) {

 	        if(clvalp>clval) {
	           clval=clvalp;
	  	   k=klp;}
		else break; // max of cluster found

	      }	else {  

	        if(clvalp<clval) {
	           clval=clvalp;
		   k=klp;}
		else break; // max of cluster found

	      };
	      
	      klp++;
	    };

            Int_t kl1=k-fNclst; // max of cluster (or end of ladder ?)
	    trasmesso=0;
	    if(kl1<0)  kl1=0;

	    if(kt>=kl1) kl1=kt+1;
            if( (kt+1)==kl1 ) trasmesso=1;


	    
	    Int_t kl2=k+fNclst;
	    if(kl2>=fNstrips_ladder) kl2=fNstrips_ladder-1;

	    for(Int_t klt=kl1 ; klt<=kl2 ; klt++) {
              if(trasmesso==0) { 
	      //  std:: cout << "STRIP " << klt << endl;
              //  std:: cout << "ADC_TOT " <<AdcTrack[iv][ladder*fNstrips_ladder+klt] << endl;

	        DataDSP[DSPlength]=( ((UShort_t)klt) | 0x1000);
	        DSPlength++;  
                ntrastot++;
	     

	        real=modff(AdcTrack[iv][ladder*fNstrips_ladder+klt],&inte);
                if (real > 0.5) inte=inte+1;
	        DataDSP[DSPlength]=( ((UShort_t)inte) & 0x0FFF);
	        DSPlength++; 
	        ntrastot++;
	     
               }
	       else { 
               //   std:: cout << "ADC_TOT " <<AdcTrack[iv][ladder*fNstrips_ladder+klt] << endl;
 	        real=modff(AdcTrack[iv][ladder*fNstrips_ladder+klt],&inte);
                if (real > 0.5) inte=inte+1;
	        DataDSP[DSPlength]=( ((UShort_t)inte) & 0x0FFF);
	        DSPlength++;               
		ntrastot++;
                };
                trasmesso=1;	      	   	    
	    };  // end trasmission
	    kt=kl2;
	    k=kl2;
	    real=modff(AdcTrack[iv][ladder*fNstrips_ladder+kt],&inte);
            if (real > 0.5) inte=inte+1;
 	    oldval=(Int_t)inte -(Int_t)fPedeTrack[iv][ladder*fNstrips_ladder+kt];
            k++;
	    continue;


	  }; // end cercacluster
	}; // end cercacluster
      
// start ZOP check for strips no
      
      if(abs(newval-oldval)>=fCutzop*(Int_t)fabs(fSigmaTrack[iv][ladder*fNstrips_ladder+k]) ) { 

       if(trasmesso==0) {
       // std:: cout << "STRIP " << k << endl;
       // std:: cout << "ADC_TOT " << AdcTrack[iv][ladder*fNstrips_ladder+k] << endl;

	 DataDSP[DSPlength]=( ((UShort_t)k) | 0x1000);
	 DSPlength++;  
         ntrastot++;
	     

	 real=modff(AdcTrack[iv][ladder*fNstrips_ladder+k],&inte);
         if (real > 0.5) inte=inte+1;
	 DataDSP[DSPlength]=( ((UShort_t)inte) & 0x0FFF);
	 DSPlength++; 
	 ntrastot++;

       }
       else {
       //  std:: cout << "ADC_TOT " << AdcTrack[iv][ladder*fNstrips_ladder+k] << endl;
	 real=modff(AdcTrack[iv][ladder*fNstrips_ladder+k],&inte);
         if (real > 0.5) inte=inte+1;
	 DataDSP[DSPlength]=(  ((UShort_t)inte) & 0x0FFF);
	 DSPlength++; 
	 ntrastot++;      
       };
       trasmesso=1;
       oldval=newval;
       kt=k;

      }  
      else trasmesso=0;
      // end zop 
      
      k++;      
      };  // end cycle inside ladder
// write here the end ladder bytes
//            std:: cout << "FINE LADDER " << ladder+1 << endl; 

      DataDSP[DSPlength]=( ((UShort_t)(ladder+1))  | 0x1800);
      DSPlength++; 
      ntrastot++; 
      trasmesso=0;

    };  //end cycle inside dsp
//  std:: cout << "FINE DSP " << iv+1 << endl;
// here put DSP header
    DataDSP[0]=(0x1CA0 | ((UShort_t)(iv+1)) );
    UShort_t Nword=(DSPlength*13)/16; 
    if( ((DSPlength*13)%16)!=0) Nword++;
    DataDSP[1]=(0x1400 | ( Nword >> 10));
    DataDSP[2]=(0x1400 | ( Nword & 0x03FF) );
    DataDSP[3]=(0x1400 | (( (UShort_t)(fCounter >> 10) ) & 0x03FF) ); 
    DataDSP[4]=(0x1400 | (( (UShort_t)(fCounter) )  & 0x03FF) );
    DataDSP[5]=(0x1400 | ( (UShort_t)(fNclst << 7) ) | ( (UShort_t)(fCutzop << 4) )
     | ( (UShort_t)fCutzop  ) ); 
    DataDSP[6]=0x1400;
    DataDSP[7]=0x1400;
    DataDSP[8]=0x1400;
    DataDSP[9]=0x1400;
    DataDSP[10]=0x1400;
    DataDSP[11]=0x1400;
    DataDSP[12]=0x1400;
    DataDSP[13]=0x1400;
    DataDSP[14]=(0x1400 | (CheckSum & 0x00FF) ); 
    DataDSP[15]=0x1C00;
// end DSP header    


// write 13 bit DataDSP bufer inside 16 bit fDataTrack buffer
    Int_t Bit16free=16;
    UShort_t Dato;
    for (Int_t NDSP=0; NDSP<DSPlength;NDSP++) {
      Int_t Bit13ToWrite=13;
      while(Bit13ToWrite>0) { 
        if(Bit13ToWrite<=Bit16free) {
          Dato=((DataDSP[NDSP]&(0xFFFF >> (16-Bit13ToWrite)))<<(Bit16free-Bit13ToWrite));
	  fDataTrack[fTracklength]=fDataTrack[fTracklength] | Dato ;
	  Bit16free=Bit16free-Bit13ToWrite;
	  Bit13ToWrite=0;
	  if(Bit16free==0) {
	    if(NDSP>15) CheckSum=CheckSum^fDataTrack[fTracklength];
	    fTracklength++;
	    Bit16free=16;
	  };          
        }
	else if(Bit13ToWrite>Bit16free) {
	  Dato=( (DataDSP[NDSP]&(0xFFFF >> (16-Bit13ToWrite) ) ) >> (Bit13ToWrite-Bit16free) );
	  fDataTrack[fTracklength]=fDataTrack[fTracklength] | Dato ;
	  if(NDSP>15) CheckSum=CheckSum^fDataTrack[fTracklength];
	  fTracklength++;
	  Bit13ToWrite=Bit13ToWrite-Bit16free;
	  Bit16free=16;	 
	};
	
      }; // end cycle while(Bit13ToWrite>0)
          
    }; // end cycle DataDSP
    if(Bit16free!=16) { fTracklength++; CheckSum=CheckSum^fDataTrack[fTracklength]; }; 
    CheckSum=(CheckSum >> 8)^(CheckSum&0x00FF);
    fDataTrack[fTracklength-Nword+11]=(0x0280 | (CheckSum >> 3));
    fDataTrack[fTracklength-Nword+12]=(0x1C00 | (CheckSum << 13) );

// end write 13 bit DataDSP bufer inside 16 bit fDataTrack buffer

//write trailer on buffer
    UShort_t ReLength=(UShort_t)((Nword+13)*2+3);
    UShort_t OveCheckCode=0x0000;

    fDataTrack[fTracklength]=0x0000;
    fTracklength++;
  
    fDataTrack[fTracklength]=(ReLength >> 8);
    fTracklength++;
  
    fDataTrack[fTracklength]=( (ReLength << 8) | (OveCheckCode & 0x00FF) );
    fTracklength++;  
// end trailer 
//    std:: cout  << "DSPlength  " <<DSPlength << endl;
//    std:: cout << "Nword " << Nword  << endl;
//    std:: cout <<  "ReLength " << ReLength << endl;
  };    
//    std:: cout << "ntrastot " << ntrastot << endl;    

};


Float_t Digitizer::SaturationTrackx(Float_t ADC) {
  Float_t SatFact=1.;
  if(ADC<1.) { SatFact=1./ADC; }; 
  if(ADC>3000.) { SatFact=3000./ADC; }; 
  return SatFact;
};




Float_t Digitizer::SaturationTracky(Float_t ADC) {
  Float_t SatFact=1.;
  if(ADC<70.) { SatFact=70./ADC; }; 
  if(ADC>4095.) { SatFact=4095./ADC; }; 
  return SatFact;
};
