#include <formatio.h>
 
#include "H1D.h"
 
#include "H2D.h"
 
#include <utility.h>
 
#include <ansi_c.h>
 
#include <cvirte.h>             
 
#include <userint.h>
 
#include "vmusb_ctrl.h"
 
#include "daq_cvi.h"
 
static int p1, p2, p3;
 
 
 
 
 
static int daq_on;
 
static int plothandle[4]= {0,0,0, 0};
 
static int tfID;
 
static int controlID;
 
static int verbose;
 
static int timeout;
 
extern int ctrlcflag;
 
 
 
#define MAX_THREADS 10
 
 
 
static CmtThreadPoolHandle poolHandle = 0;
 
 
 
#define MAXCH 72
 
  float gSum[6];
 
  float gRawSum[6];
 
  float gMax[6];
 
  float gSumCluster[6];
 
  float gNtdata[MAXCH*3];
 
  int   gNabove[5];
 
  double gData[MAXCH]; // korigirani ADC ji
 
  double gAdc[MAXCH];  // raw ADC ji
 
 
 
  double gPedestals[MAXCH]; 
 
    double gPeak[MAXCH]; 
 
   
 
    double gPeakScaling;    
 
    double gThreshold;    
 
   
 
  
 
typedef struct Channel {
 
  int ix;
 
  int iy;
 
  int idx;
 
 
 
};
 
 
 
struct Channel m_geo_ch[16];
 
  
 
  
 
char strbuf[0xFF];
 
 
 
int gLog=0;
 
int printf(const char *format
, ...
) {  
  va_list aptr;
 
  int ret;
 
  FILE *flog;
 
 
 
  SetCtrlVal(p1,P1_IO,strbuf);
 
 
 
  if (gLog) {
 
    flog 
= fopen ("stdio.log", "a"); 
  }
 
  return(ret);
 
}
 
 
 
 
 
 
 
int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
 
                       LPSTR lpszCmdLine, int nCmdShow) {
 
  if (InitCVIRTE (hInstance, 0, 0) == 0)
 
    return -1;  /* out of memory */
 
  if ((p1 = LoadPanel (0, "vmusb_ctrl.uir", P1)) < 0)
 
    return -1;
 
  if ((p2 = LoadPanel (0, "vmusb_ctrl.uir", P2)) < 0)
 
    return -1;
 
  if ((p3 = LoadPanel (0, "vmusb_ctrl.uir", P3)) < 0)
 
    return -1;
 
  SetStdioPort (CVI_STDIO_WINDOW);
 
  SetSleepPolicy(VAL_SLEEP_MORE);
 
  CmtNewThreadPool (MAX_THREADS,  &poolHandle);
 
  DisplayPanel (p1);
 
  
 
  RunUserInterface ();
 
  DiscardPanel (p1);
 
  DiscardPanel (p2);  
 
  DiscardPanel (p3);  
 
  return 0;
 
}
 
 
 
static void start_timer (double tout) {
 
        timeout = 0;
 
  SetCtrlAttribute (p1, P1_TIMER, ATTR_INTERVAL, tout);
 
  SetCtrlAttribute (p1, P1_TIMER, ATTR_ENABLED, 1);
 
}
 
 
 
static void stop_timer ( void ) {
 
  SetCtrlAttribute (p1, P1_TIMER, ATTR_ENABLED, 0);
 
  //DRSSetTimeout();
 
}
 
 
 
 
 
 
 
 
 
 
 
int georead(){
 
int i;
 
for (i=0; i<64; i++) {
 
  int row=i+1;
 
  double val;
 
  unsigned short sval;
 
  GetTableCellVal (p3, P3_CGEO, MakePoint (3,row), &sval);
 
  fThreshold[i]=sval;
 
  GetTableCellVal (p3, P3_CGEO, MakePoint (4,row), &val);
 
  gPeak[i]=val;
 
  GetTableCellVal (p3, P3_CGEO, MakePoint (5,row), &val);
 
  gPedestals[i]=val;
 
}
 
  
 
GetCtrlVal(p3, P3_PEAKSCALING, &gPeakScaling );
 
GetCtrlVal(p3, P3_GTHRESHOLD, &gThreshold );
 
 
 
for (i=0; i<16; i++) {
 
  int row=i+1;
 
  double val;
 
  unsigned short sval, id;
 
  GetTableCellVal (p3, P3_CGEO, MakePoint (1,row), &id);
 
  GetTableCellVal (p3, P3_CGEO, MakePoint (2,row), &sval);
 
  m_geo_ch[id].ix=sval;
 
  GetTableCellVal (p3, P3_CGEO, MakePoint (3,row), &sval);
 
  m_geo_ch[id].iy=sval;     
 
  m_geo_ch[id].idx=id;     
 
}
 
 
 
return 0;
 
}
 
 
 
void CVICALLBACK EndOfThread ( CmtThreadPoolHandle poolhandle,
 
                               CmtThreadFunctionID functionID, unsigned int event,
 
                               int value, void *callbackData  ) {
 
 
 
  daq_on=0;
 
  //SetDimming(0);
 
  return ;
 
 
 
}
 
 
 
 
 
int CVICALLBACK RefreshGraphs (int panel, int control, int event,
 
                               void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_TIMER_TICK:
 
//      if (!daq_on ) return 0;
 
    case EVENT_COMMIT: {
 
                        
 
      int ch=0;
 
      int logy=0;
 
      int pmt =0;
 
      int updateplots=0;
 
      GetCtrlVal(p1,P1_RECO, &updateplots);
 
      if (!updateplots) return 0;
 
      GetCtrlVal(p2,P2_PMT, &pmt);
 
      GetCtrlVal(p2,P2_ADC, &ch);
 
      
 
      
 
      H1D_Draw(10,p2,P2_GRAPHADC,&plothandle[1]);
 
      H2D_Draw(0,p2,P2_GRAPH2D,&plothandle[2]);
 
                        
 
 
 
    }
 
 
 
    
 
    break;
 
 
 
  }
 
  return 0;
 
}
 
 
 
 
 
 
 
int vmusb_init(){
 
 
 
  int range = 2056;
 
  for (int i=0; i<MAXCH; i++) {
 
    char name[0xFF];
 
                
 
    H1D_Init(i, name,name, range, 0 , range);
 
    H1D_SetTitleX(0,"ADC");
 
    H1D_SetTitleY(0,"N");
 
                
 
    H1D_Init(100+i, name,name, range, 0 , range);
 
    H1D_SetTitleX(0,"Energy");
 
    H1D_SetTitleY(0,"N");
 
  }
 
  
 
 
 
  H2D_Init(0, "cog","Center of grg_peakscalingavity", 256, 0 ,1, 256, 0 ,1);
 
  H2D_SetTitleX(0,"x");
 
  H2D_SetTitleY(0,"y");
 
  
 
  return 0;
 
}
 
 
 
double GetEnergy(int ch, int adc){
 
   return (adc-gPedestals[ch])/(gPeak[ch]-gPedestals[ch])*gPeakScaling;
 
}
 
 
 
int FillHistograms() {
 
 
 
  int npmts = 4;
 
  for (int ipmt=0; ipmt<npmts; ipmt++) { // zanka preko pmtjev
 
    int j2= (ipmt/2)*2+1-ipmt%2;  // sosednja fotopomnozevalka
 
 
 
    float posx[2]= {0,0};
 
    float posy[2]= {0,0};
 
    float sum[2]= {0,0};
 
    float m_threshold =100;
 
    for (int ich=0; ich<16; ich++) { // zanka preko elektronskih kanalov na fotopomnozevalki
 
      int ch= ich+ipmt*16;
 
      if (gMax[ipmt]>m_threshold) {
 
        posx[0]+= gData[ch]*m_geo_ch[ich].ix;
 
        posy[0]+= gData[ch]*m_geo_ch[ich].iy;
 
        sum[0] += gData[ch];
 
 
 
        if (gData[ch]> 0.2*gMax[ipmt]) { // pri racunanju pozicije upostevaj le kanale, ki imajo vrednost vecjo od ratio*maksimalna na tisti fotopomnozevalki
 
          posx[1]+= gData[ch]*m_geo_ch[ich].ix;
 
          posy[1]+= gData[ch]*m_geo_ch[ich].iy;
 
          sum[1] += gData[ch];
 
        }
 
      }
 
    }
 
 
 
    if ( sum[0] > 0  ) {
 
      float px=posx[0]/sum[0];
 
      float py=posy[0]/sum[0];
 
      H2D_Fill(0, px,py,1);
 
    }
 
  }
 
 
 
 
 
  return 0;
 
};
 
 
 
 
 
int DecodeData(int n, unsigned int *buf){
 
  
 
        int idx=1;
 
      int neve=buf[0]/2;
 
      //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
      for (int nev=0;nev<neve;nev++){
 
        int len=buf[idx];
 
        int sb =buf[idx+1];
 
        unsigned int *pbuf=&buf[idx+2];
 
        if (sb!=0xffab) { 
 
          printf("0x%04x!0xffab len=%d\n",sb
,len
);  
          break;
 
        }
 
        // postavi na nic
 
#define InitArrayWithAValue(arr,n,x) {for (int i=0;i<n;i++) arr[i]=x;}      
 
        InitArrayWithAValue( gSum       , 4    , 0);
 
        InitArrayWithAValue( gRawSum    , 4    , 0);
 
        InitArrayWithAValue( gMax       , 4    , 0);
 
        InitArrayWithAValue( gSumCluster, 4    , 0);
 
        InitArrayWithAValue( gNabove    , 4    , 0);
 
        InitArrayWithAValue( gData      , MAXCH, 0);
 
        InitArrayWithAValue( gAdc       , MAXCH, 0);    
 
        //------------------------------------------------------------
 
        for (int i0=0;i0<len-2;i0+=2) {
 
          
 
          int data0  = pbuf[i0];
 
          int data1  = pbuf[i0+1];
 
          int geo    = (data1 >> 11) & 0x1f;
 
          int ch     = (data1&0x1f)  | (geo<<5);
 
          int dtype  = (data1>>9)&0x3;
 
          int adc    =  data0&0xfff;
 
         
 
          switch (dtype) {
 
          case 0x0:
 
            if (ch<MAXCH) {              
 
              H1D_Fill(ch,adc,1);
 
              
 
              int ipmt = ch/16;
 
              
 
              gAdc[ch]=adc;
 
              gRawSum[ipmt]+=adc;
 
              
 
              if (ch<64) gData[ch]= GetEnergy(ch,adc); else gData[ch]=adc;
 
              H1D_Fill(1+ch,gData[ch],1); 
 
              gSum[ipmt]+=gData[ch];
 
              if (gData[ch]   >gMax[ipmt] )     gMax[ipmt]= gData[ch];
 
              if (gData[ch]   >gThreshold )    gNabove[ipmt]++;
 
            } 
 
            break;
 
          case 0x10:
 
          case 0x11:
 
          case 0x01:
 
            break;
 
          }
 
 
 
        };// for (int i0=0;i0<len-2;i0+=2) 
 
        //------------------------------------------------------------
 
        
 
        idx+=len+1;
 
        FillHistograms();
 
      } // for (int nev=0;nev<neve;nev++)
 
      //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  
 
  
 
  return 0;
 
}
 
int vmusb_daq(){
 
 
 
  
 
  vmusb_init();
 
  
 
  
 
  
 
 
 
   // print welcome message
 
  time_t t,told=0, tstart, tstop;
 
  printf("#############################################\n");  
  printf("Program vmusb version\n");  
  printf("Compiled on %s %s\n",__DATE__
, __TIME__
);  
  printf("#############################################\n");  
 
 
 
 
  int neve=-1;
 
  char cfname[100]="test.dat";
 
  char fname[0xff];
 
  char fpedname[0xff];
 
 
 
#define BSIZE 10000
 
  uint32_t data[10000];
 
  int oldValue;
 
  //oldValue = SetBreakOnLibraryErrors (0);
 
  daq_init(); /* Function calls that may legitimately return errors. */
 
  //SetBreakOnLibraryErrors (oldValue);
 
 
 
  int output=0;
 
  GetCtrlVal(p1,P1_OUTPUT, &output);
 
 
 
  GetCtrlVal(p1,P1_FMASK, fpedname);
 
  int fsize=0;
 
  georead();
 
 
 
  GetCtrlVal(p1,P1_NEVE, &neve);
 
  // negative argument time ( in s )limited event loop
 
  GetCtrlVal(p1,P1_FNAME, fname);
 
 
 
  if (GetFileInfo(fname,&fsize)==1) {
 
    printf( "File %s already exist. Appending ....\n",fname
);  
    //fprintf(stdout,"Remove the file and restart !!!\n");
 
    //exit(0);
 
  }
 
 
 
 
 
  FILE *fp=NULL;
 
  if (output
) fp 
= fopen(fname
,"a");  
  //gzFile fp=gzopen(fname,"a");
 
  
 
  init();
 
  clear();
 
  
 
  int hdr[4]={2}; // recid od run 11 naprej
 
  int i=0;
 
  int ntotal=0;
 
  int counters[30]={0,0,0,0,0, 0,0,0,0,0,0,0};
 
  char names[10][20]={"TRG","CAEN V965"};
 
  tstart=t;
 
  tstop=tstart+360000;
 
  int evetype=0;
 
  GetCtrlVal(p1,P1_EVE, &evetype);    
 
  if (evetype) {
 
    double ntime=0;
 
    GetCtrlVal(p1,P1_NTIME, &ntime); 
 
    tstop=tstart+ntime;
 
    neve=-1;
 
  }
 
  int reco=0;
 
  GetCtrlVal(p1,P1_RECO, &reco);
 
  for (i=0;i!=neve && !ctrlcflag && t<tstop;i++){ 
 
     if (t!=told ) {
 
       printf("%d in %2.2f min daq::event() %s\n",i
, (double)(t
-tstart
)/60.
, ctime(&t
));  
       GetCtrlVal(p1,P1_RECO, &reco); 
 
       RefreshGraphs(p2,P2_PMT,EVENT_COMMIT,NULL,0,0);
 
     }  
 
     int nb=event(data,BSIZE, counters,t!=told);
 
     SetCtrlVal(p1,P1_CEVE,i);
 
     if (nb>0){
 
       
 
      if (reco) DecodeData(nb, data); 
 
      // zapis v datoteko   
 
      hdr[1]=nb+4*sizeof(int);
 
      hdr[3]=i;
 
      if (fp
) fwrite(hdr
,   sizeof(int),4 , fp
);   
      if (fp
) ntotal 
+= fwrite(data
, 1,nb
, fp
);  
      
 
     } else i--;
 
     told=t;
 
  } 
 
 
 
  end();
 
  
 
  printf("Number of Events: %d\n",i
);  
  if (ctrlcflag
) printf("User Program termination CTRL-C\n");  
  if (t
>tstop  
) printf("Timeout termination tstart# t>tstop: %d# %d >%d\n",(int)t
, (int)tstart
, (int) tstop
);  
  
 
 
 
  //gzclose(fp);  
 
  printf("%d bytes written to %s\nCounts:\n", (int) (ntotal
*sizeof(int)),fname
);  
  for (i
=0;i
<2;i
++) printf("%s\t%d\t%d\n",names
[i
],counters
[2*i
],counters
[2*i
+1]) ;  
 
 
 
 
  
 
  printf("Usage: vmusb [filename] [number of events] [thresholdfile]\n negative number of events = acq time in seconds\n");  
  
 
  disconnect();
 
  
 
  return 0;
 
}
 
 
 
int CVICALLBACK StartCB (int panel, int control, int event,
 
                         void *callbackData, int eventData1, int eventData2) {
 
  ThreadFunctionPtr mythread = NULL;
 
  switch (event) {
 
 
 
    case EVENT_COMMIT:
 
 
 
      controlID= control;
 
      if (panel == p1 && control == P1_START) {
 
        mythread = vmusb_daq;
 
        
 
      }
 
      //if (panel == xyscan && control == SCAN_SCAN)   mythread = scan;  
 
      if (mythread!=NULL) {
 
        printf("New Thread panel=%d button=%d\n", panel
, control
);  
 
 
        // SetDimming(1);
 
 
 
       
 
        CmtScheduleThreadPoolFunctionAdv (poolHandle, mythread, &controlID,
 
                                          DEFAULT_THREAD_PRIORITY,
 
                                          EndOfThread,
 
                                          EVENT_TP_THREAD_FUNCTION_END,
 
                                          NULL, RUN_IN_SCHEDULED_THREAD,
 
                                          &tfID);
 
      }
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
int CVICALLBACK StopCB (int panel, int control, int event,
 
                        void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_COMMIT:
 
      ctrlcflag=1;
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
int CVICALLBACK ExitCB (int panel, int control, int event,
 
                        void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_COMMIT:
 
      QuitUserInterface (0);
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
int CVICALLBACK ShowHistoCB (int panel, int control, int event,
 
                             void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_COMMIT:
 
      DisplayPanel (p2);
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
int CVICALLBACK SetLogZCB (int panel, int control, int event,
 
                           void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_COMMIT:
 
      GetCtrlVal
(panel
,control
, &log); 
 
 
        SetCtrlAttribute (p2, P2_GRAPH2D, ATTR_YMAP_MODE, VAL_LOG);
 
 
 
      } else {
 
        SetCtrlAttribute (p2, P2_GRAPH2D, ATTR_YMAP_MODE, VAL_LINEAR);
 
      }
 
 
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
int CVICALLBACK SetLogYCB (int panel, int control, int event,
 
                           void *callbackData, int eventData1, int eventData2) {
 
  
 
  switch (event) {
 
    case EVENT_COMMIT:{
 
      GetCtrlVal
(panel
,control
, &log); 
 
 
        SetCtrlAttribute (p2, P2_GRAPHADC, ATTR_YMAP_MODE, VAL_LOG);
 
 
 
      } else {
 
        SetCtrlAttribute (p2, P2_GRAPHADC, ATTR_YMAP_MODE, VAL_LINEAR);
 
      }
 
 
 
    }
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
 
 
int CVICALLBACK ShowMainCB (int panel, int control, int event,
 
                            void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_COMMIT:
 
      DisplayPanel (p1);
 
      break;
 
  }
 
  return 0;
 
}
 
 
 
int CVICALLBACK ShowSettingsCB (int panel, int control, int event,
 
                                void *callbackData, int eventData1, int eventData2) {
 
  switch (event) {
 
    case EVENT_COMMIT:
 
      DisplayPanel (p3);   
 
      break;
 
  }
 
  return 0;
 
}