Subversion Repositories f9daq

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

//#include "tabela.h"
//#include "proba.h"


#include "vme.h"

//#define PTS_ADDR 0x025F0000
//#define PTS_ADDR 0x26000000

#include "PtsModule.h"
#define PTS_ADDR 0x61000000
#include <windows.h>
#include <formatio.h>
#include <analysis.h>
#include "toolbox.h"
#include <cvirte.h>
#include <stdlib.h>
#include <stdio.h>

#include <string.h>
#include <ctype.h>
#include <stdint.h>

#include <signal.h>
#include <utility.h>
#include <ansi_c.h>
#include <userint.h>
#include "toolbox.h"

#include "sa02lib.h"
#include "CAEN_V729.h"
#include "CAEN_V729_CVI.h"
#include "icfa.h"

#include "MIKRO.h"
const int dsize = 144*4;

#include "H1D.h"
#include "H2D.h"
#include "H3D.h"
#include "HDraw.h"
#include "dataio.h"
#include "sa02lib.h"
#include "sa02_CVI.h"

int ProcessUserEvent(int pID, int rID,int mode);

const char  palaser[0xFF]="\"C:\\home\\software\\daq\\LaserDriver-Ver2.0\\Particulars LASER control.exe\"";

#define MAX_THREADS 10
const char slowcname[20][20]= {"TMON0","TMON1","VDD","V2P","V2N","VSS","VTH1","VTH2", "VCC12", "VCC15" ,"VCC25", "V38P" };
const int chart_control[4]= {P1_CHART_1,P1_CHART_2,P1_CHART_3,P1_CHART_4};
const int hapd_serials [4]= { P1_SERIAL_1, P1_SERIAL_2, P1_SERIAL_3, P1_SERIAL_4 };
const int fpga_serials [4]= { P1_SERIAL_FPGA_1, P1_SERIAL_FPGA_2, P1_SERIAL_FPGA_3, P1_SERIAL_FPGA_4 };
const int hapd_onoff   [4]= { P1_ONOFF_1, P1_ONOFF_2, P1_ONOFF_3, P1_ONOFF_4 };
const int p2graph   [4]= { P2_GRAPH_1, P2_GRAPH_2, P2_GRAPH_3, P2_GRAPH_4 };

#define PTS_ADDR 0x61000000

#define MIKRO_COM 4
#define MIKRO_X 1
#define MIKRO_Y 2
#define MIKRO_Z 3

#define TRUE 1
#define FALSE 0
#define TIMEOUT 3

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
uint32_t gVME_CONTROLLER=WIENER_VMEMM;
uint32_t gCAEN_V288=0;
uint32_t gBELLEPTS=PTS_ADDR;
uint32_t gMIKRO_PORT=MIKRO_COM;
uint32_t gMIKRO_X=MIKRO_X, gMIKRO_Y=MIKRO_Y, gMIKRO_Z=MIKRO_Y;
uint32_t gCENTER_X=176000, gCENTER_Y=170000;
double gCENTER_KX=6./300, gCENTER_KY=3./300;
uint32_t gCAEN_V729=0;
uint32_t gCAEN_V1495=0;
uint32_t gFEBParamRead=0;
uint32_t gFEBMask=0xF;
uint32_t gTriggerType=2;
char gFEBParam[0xFF]="";

uint32_t uInterf = 0;

RUNINFO runinfo;
RUNREC runrec;
ENDREC endrec;
POSREC posrec;
EVTREC evtrec;
EVTREC evtrec1;
DATREC datrec;
MONREC monrec;
ITERATORREC iteratorrec;


typedef struct {
  int chip;
  int ch;
  int chx;
  int chy;
} EID2HAPDY;

EID2HAPDY eid2hapdxy[144];

// Variables
static int p1h, pID, rID, tfID;
static int p2h;
static int p3h;
static int p4h;
static int p5h;
static int pm1;
static int daq_on,loop_on;
static CmtThreadPoolHandle poolHandle = 0;
static CmtTSQHandle  pTSQ = 0;
static int pTSQData[2];

double datay[10000];
double datax[10000];
double datayfit[10000];

//const int mux_map[4]={ 1,3,0,2};

int ctrl_c=0;
int integer_val=0;
FILE *gFp=NULL;

//***********************VARIABLE ZA BRANJE NAPETOSTI***********************//

#include "CAENV288.h"

#define ReadOperationalParam  0x02 //N470
#define TurnChanelOn          0x0a //N470  
#define TurnChanelOff         0x0b //N470  
#define ReadStatus            0x01 //SYS403
#define ReadParameters        0x02 //SYS403

int hvmon=0;
int hvmonFirst=0;
int32_t vset[24], iset[24];


// reads the run number from the first line in the file
int GetRunNumberFromFile(char *fname) {
  char line[MAX_PATHNAME_LEN];
  int ndim= MAX_PATHNAME_LEN;
  int current_run = -1;
  FILE *fp = NULL;
  ssize_t size;

  if ( GetFileInfo(fname,&size) ) fp = fopen(fname,"r");

  if (fp) {
    if (fgets(line,ndim,fp)!= NULL) current_run = atoi(line);
    fclose(fp);
  }
  return current_run;

}

int IncreaseRunNumberInFile(char *fname) {

  int current_run = GetRunNumberFromFile(fname);
  FILE *fp = fopen(fname,"w");

  if (fp) {
    fprintf(fp,"%d", current_run+1 );
    fclose(fp);
  }
  return current_run+1;
}


//**************************** get station parameters from ini file
int readIni(char *fname) {

  FILE *fp = NULL;
  char cmd[0xFF],val[0xFF];
  int ndim=400;
  char line[ndim];
  ssize_t size;

  if ( GetFileInfo(fname,&size) ) fp = fopen(fname,"r");
  if (!fp) {
    sprintf(line, "%s not found. Using default values.\n",fname);
    MessagePopup ("Info", line);
    return -1;
  }
  while (fgets(line,ndim,fp)!=NULL) {
    sscanf(line,"%s%s",cmd, val);
    if (cmd[0]=='#') continue;
    if ( strstr(cmd,"VME_CONTROLLER")!= NULL ) {
      if ( strstr(val,"WIENER_VMUSB")!= NULL ) gVME_CONTROLLER=WIENER_VMUSB;
      if ( strstr(val,"WIENER_VMEMM")!= NULL ) gVME_CONTROLLER=WIENER_VMEMM;
      if ( strstr(val,"CAEN_V1718")  != NULL ) gVME_CONTROLLER=CAEN_V1718;
      if ( strstr(val,"SIS3153_USB")  != NULL ) gVME_CONTROLLER=SIS3153_USB;
    }
    if ( strstr(cmd,"CAEN_V288" )!= NULL ) gCAEN_V288 =strtoul(val,NULL,0);
    if ( strstr(cmd,"BELLEPTS")  != NULL ) gBELLEPTS  =strtoul(val,NULL,0);
    if ( strstr(cmd,"CAEN_V1495")  != NULL ) gCAEN_V1495  =strtoul(val,NULL,0);
    if ( strstr(cmd,"MIKRO_PORT")!= NULL ) gMIKRO_PORT=strtoul(val,NULL,0);
    if ( strstr(cmd,"MIKRO_X")   != NULL ) gMIKRO_X   =strtoul(val,NULL,0);
    if ( strstr(cmd,"MIKRO_Y")   != NULL ) gMIKRO_Y   =strtoul(val,NULL,0);
    if ( strstr(cmd,"MIKRO_Z")   != NULL ) gMIKRO_Z   =strtoul(val,NULL,0);
    if ( strstr(cmd,"CENTER_X")   != NULL ) gCENTER_X   =strtoul(val,NULL,0);
    if ( strstr(cmd,"CENTER_Y")   != NULL ) gCENTER_Y   =strtoul(val,NULL,0);
    if ( strstr(cmd,"CENTER_KX")   != NULL ) gCENTER_KX   =strtod(val,NULL);
    if ( strstr(cmd,"CENTER_KY")   != NULL ) gCENTER_KY   =strtod(val,NULL);
    if ( strstr(cmd,"CAEN_V729") != NULL ) gCAEN_V729 =strtoul(val,NULL,0);
    if ( strstr(cmd,"FEBParam") != NULL ) sprintf(gFEBParam,"%s", val);
    if ( strstr(cmd,"UI") != NULL ) uInterf =strtoul(val,NULL,0);
    if ( strstr(cmd,"FEBMask") != NULL ) gFEBMask =strtoul(val,NULL,0);
    if ( strstr(cmd,"TriggerType") != NULL ) gTriggerType =strtoul(val,NULL,0);
  }
  fclose(fp);
  return 0;
}
//**************************** missing declarations in the library
char strbuf[0xFF];

int gLog=0;
int sa02Printf(const char *format, ...) {
  va_list aptr;
  int ret;
  FILE *flog;

  va_start(aptr, format);
  ret = vsprintf(strbuf, format, aptr);
  va_end(aptr);
  SetCtrlVal(p1h,P1_STDIO,strbuf);

  if (gLog) {
    flog = fopen ("stdio.log", "a");
    fprintf (flog, "%s", strbuf);
    fclose (flog);
  }
  return(ret);
}


int CVICALLBACK sa02timeout (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_TIMER_TICK:
      sa02TimerOut = TRUE;
      sa02Printf("sa02timeout\n");
      //sa02Printf("TIMEOUT %s in line %d\n", __FILE__ , __LINE__);
      break;
  }
  return 0;
}
void sa02Timerast (int signumber) {
  sa02TimerOut = TRUE;
  sa02Printf("TIMEOUT !!!\n");
  SetCtrlAttribute (p1h, P1_DAQ_TIMEOUT, ATTR_ENABLED, 0);
}

void sa02Tmlnk (int tout) {
  sa02TimerOut = FALSE;
  SetCtrlAttribute (p1h, P1_DAQ_TIMEOUT, ATTR_INTERVAL,
                    (float)tout/100.);
  SetCtrlAttribute (p1h, P1_DAQ_TIMEOUT, ATTR_ENABLED, 1);
  //  ResetTimer (p1h, P1_DAQ_TIMEOUT);
}

void sa02Tmulk ( void ) {
  SetCtrlAttribute (p1h, P1_DAQ_TIMEOUT, ATTR_ENABLED, 0);
}
//****************************


int EscapeString(const char *i, char *o) {
  unsigned int iptr=0, optr = 0;
  // walk though the input string
  for (iptr = 0; iptr < strlen(i); iptr++, optr++) {
    // search for
    if ( (i[iptr]=='\\') ) {
      sa02Printf("Escape String %d %d \n",i[iptr] , i[iptr]==92 ) ;
      //sa02Printf("Escape String %d %d \n",i[iptr] , ( (i[iptr] == 92) || (i[iptr] == 42) )) ;
      o[optr] = i[iptr];
      optr++;
    }

    o[optr] = i[iptr];
  }

  o[optr] = '\0';


  return 0;
}



int p1plothandle=0;
int p2plothandle[4]= {0,0,0,0};
int p3plothandle=0;

int plothandle=0;

int phandle[4]= {0,0,0,0};


int plothandle2dfit=0;
int plothandleslix=0;
int plothandlesliy=0;
int plothandlefit=0;

void SigInt (int sig) {
  ctrl_c = 1;
  sa02TimerOut=1;
}

//int sa02Verbose=0;
int module_header(int recid,uint32_t *data,int len) {
  data[0] = recid;
  data[1] = (len >0)? len : 0 ;
  return data[1]+2;
}

int PrintData(uint32_t *rdata, int count) {
  int j;
  uint32_t i;
  for (j=0; j<count; j++) {
    uint32_t recid   = rdata[j++];
    uint32_t len     = rdata[j++];
    sa02Printf(" recid=0x%0x len=%d pos=%d(maxpos %d) val=",recid, len, j, count);
    if (len>2) {
      sa02Printf("\n");
    }
    for (i=0; i<len; i++) {
      if (j< count) {
        sa02Printf("0x%0x\t", rdata[j]);
      }
      if (i%4==3) {
        sa02Printf("\n");
      }
      j++;
    }
    sa02Printf("\n");
    if (len) {
      j--;
    }
  }
  return 0;
}

//-------------------------------------------------------------------------
int CVICALLBACK PlotSliceY (int panel, int control, int event,
                            void *callbackData, int eventData1, int eventData2) {
  int nslice,i;
  int h2=(int) callbackData;

  switch (event) {
    case EVENT_COMMIT: {
      int ny       =  H2DGetNbinsY(h2);
      double miny  =  H2DGetMinY(h2);
      double stepy =  H2DGetStepY(h2);
      GetCtrlVal(panel,P1_NSLIX,&nslice);

      for (i=0; i < ny; i++ ) {
        datax[i]=H2DGetBinContent(h2,nslice,i);
      }
      if (ny>0) {
        if (plothandleslix) {
          DeleteGraphPlot (p1h, P1_GRAPHY, plothandleslix, VAL_IMMEDIATE_DRAW);
        }

        plothandleslix = PlotWaveform (p1h, P1_GRAPHY, datax, ny,
                                       VAL_DOUBLE, 1.0, 0.0, miny,
                                       stepy, VAL_FAT_LINE,
                                       VAL_EMPTY_SQUARE, VAL_SOLID, 1,
                                       VAL_BLUE);
      }

    }
    break;
  }
  return 0;
}


int CVICALLBACK PlotSliceX (int panel, int control, int event,
                            void *callbackData, int eventData1, int eventData2) {
  int nslice,i;
  int h2=(int) callbackData;

  switch (event) {
    case EVENT_COMMIT: {
      int nx       =  H2DGetNbinsX(h2);
      double minx  =  H2DGetMinX(h2);
      double stepx =  H2DGetStepX(h2);
      GetCtrlVal(panel,P1_NSLIY,&nslice);
      for (i=0; i < nx; i++ ) {
        datax[i]=H2DGetBinContent(h2,i,nslice);
      }
      if (nx>0) {
        if (plothandlesliy) {
          DeleteGraphPlot (p1h, P1_GRAPHX, plothandlesliy, VAL_IMMEDIATE_DRAW);
        }

        plothandlesliy = PlotWaveform (p1h, P1_GRAPHX, datax, nx,
                                       VAL_DOUBLE, 1.0, 0.0, minx,
                                       stepx, VAL_FAT_LINE,
                                       VAL_EMPTY_SQUARE, VAL_SOLID, 1,
                                       VAL_BLUE);
      }

    }
    break;
  }
  return 0;
}



void plot1d(int npoints, double x0, double dx) {
  sa02Printf("TEST %d\n", npoints);
  if (npoints>0) {
    if (plothandle) {
      DeleteGraphPlot (p1h, P1_GRAPH, plothandle, VAL_IMMEDIATE_DRAW);
    }
    plothandle = PlotWaveform (p1h, P1_GRAPH, datay, npoints, VAL_DOUBLE,
                               1.0, 0.0, x0, dx, VAL_CONNECTED_POINTS,
                               VAL_EMPTY_SQUARE, VAL_SOLID, 1, VAL_BLUE);
  }
}

/*
void plotxy(int h2d){
  if (plothandlexy > 0 ) DeleteGraphPlot (p2h, P2_GRAPHXY, plothandlexy, VAL_IMMEDIATE_DRAW);
  RangeColors(H2DGetMin(h2d),H2DGetMax(h2d));
  plothandlexy = PlotScaledIntensity (p2h, P2_GRAPHXY, H2DGetData(h2d),
                   H2DGetNbinsX(h2d), H2DGetNbinsY(h2d), VAL_DOUBLE,
                   H2DGetStepY(h2d),H2DGetMinY(h2d),H2DGetStepX(h2d),H2DGetMinX(h2d),
                   colormap->array,
                   colormap->HiColor,
                   colormap->numberofColors, 1, 0);
  ProcessSystemEvents ();
}
*/


int CVICALLBACK ZoomToFebCB (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  int feb=-1;
  float xmin=0, xmax=0;
  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal(panel,control,&feb);
      switch (feb) {
        case -1:
          xmin=0;
          xmax=144*4-1;
          break;
        default:
          xmin =  feb *144;
          xmax =xmin+144 -1;
          break;
      }
      SetAxisRange (p1h, P1_GRAPH2D, VAL_MANUAL, xmin, xmax, VAL_NO_CHANGE, 0.0, 1.0);
      break;
  }
  return 0;
}




void plot2d(int h2d, int nslice) {
  if  (nslice < 0 ) {
    nslice=0;
  }
  if (plothandle2dfit > 0 ) {
    DeleteGraphPlot (p1h, P1_GRAPH2D, plothandle2dfit, VAL_IMMEDIATE_DRAW);
    plothandle2dfit=0;
  }
  H2DDraw(h2d,p1h, P1_GRAPH2D, &p1plothandle);

  if (sa02Verbose > 2) {
    sa02Printf("min %f max %f  x:min %f step%f y:min %f step%f\n",
               H2DGetMin(h2d),H2DGetMax(h2d), H2DGetMinX(h2d),
               H2DGetStepX(h2d),H2DGetMinY(h2d), H2DGetStepY(h2d));
  }
  SetCtrlVal(p1h, P1_NSLIY, nslice);
  PlotSliceX(p1h,P1_GRAPHY,EVENT_COMMIT, NULL,0,0);
  PlotSliceY(p1h,P1_GRAPHY,EVENT_COMMIT, NULL,0,0);
  ProcessSystemEvents ();
}

void SetDimming(int state) {
  SetCtrlAttribute (p1h, P1_MULTIFPGAWRITE, ATTR_DIMMED, state);
  SetCtrlAttribute (p1h, P1_DAQ, ATTR_DIMMED, state);
  SetCtrlAttribute (p1h, P1_READOUT, ATTR_DIMMED, state);
  SetCtrlAttribute (p1h, P1_FPGAWRITE, ATTR_DIMMED, state);
  SetCtrlVal (p1h, P1_LED, state);
  SetCtrlAttribute (p2h, P2_DAQ, ATTR_DIMMED, state);
  SetCtrlAttribute (p2h, P2_RUNSCRIPT, ATTR_DIMMED, state);
  SetCtrlAttribute (p3h, P3_DAQ, ATTR_DIMMED, state);
  SetCtrlAttribute (p4h, P4_DAQ, ATTR_DIMMED, state);
  SetCtrlAttribute (p1h, P1_STOP, ATTR_DIMMED, !state);
  SetCtrlAttribute (p2h, P2_STOP, ATTR_DIMMED, !state);
  SetCtrlAttribute (p3h, P3_STOP, ATTR_DIMMED, !state);
  SetCtrlAttribute (p4h, P4_STOP, ATTR_DIMMED, !state);
}


uint16_t GetConnectedFebMask(void) {

  uint16_t mask=0;
  int ison;
  for (int i=0; i<4; i++) {
    GetCtrlVal(p1h,hapd_onoff[i], &ison);
    mask |= (ison << i);
  }
  sa02Printf("Connected FEBs mask, 0x%0x\n",mask);
  return mask;
}

int CVICALLBACK daq(void *functionData) {

  char title[256], serial[64];
  int daqmode=1;
#define MAXSIZE 10000
  int h2=0;
  int maxsize = MAXSIZE;
  uint32_t *rdata;
  uint32_t response[2]= {0,0};

  uint32_t fixeddata =0;
  int testfixeddata =0;
  uint32_t data    =0;
  uint32_t data0    =0;
  uint32_t dataoff =0;
  uint32_t dataon =0;

  uint32_t cmd     =0;
  uint32_t chip    =0;
  uint32_t asicpar =0;
  uint32_t asicshft=0;
  uint32_t dstep   =0;
  uint32_t sendswtrg  =0;
  uint32_t tpenb   =0;

  uint32_t trglen;
  uint16_t mask;
  //uint32_t boardnumber_current=0;
  // uint32_t hdr[10];

  unsigned int aborttimeout =0;
  int append   =0;
  int remap    =0;
  int neve     =0;
  int towrite  =0;
  int toread   =0;
  int ch       =0;
  int output   =0;
  int externalcmd   =0;
  int i=0,j=0, ir;
  int ich;
  //int ison;

  char sfixeddata[0xFF]="";
  char scmd[0xFF]="";

  char filename[0xFF]="";

  char externalcommand[0xFF]="";

  FILE *fp=NULL;
  int nbtotal=0;
  time_t t,told, tstart;
  int ncount=0;
  int nerrors=0;
  int readerror=0;
  //int writeevents=0;
  double fraction=0;
  int board;
  double t0;

  rdata = malloc(sizeof(uint32_t)*maxsize);

  // intercept routine
  if (signal (SIGINT, SigInt) == SIG_ERR) {
    perror ("sigignore");
  }


  mask=GetConnectedFebMask();
  GetCtrlVal(p1h,P1_OUTPUTFILE, filename);
  GetCtrlVal(p1h,P1_APPEND,&append);    // append the data to the file filename
  GetCtrlVal(p1h,P1_FRACTION, &fraction);

  GetCtrlVal(p1h,P1_ABORTTOUT, &aborttimeout);

  GetCtrlVal( p1h,P1_EXTERNALCMD, externalcommand);
  GetCtrlVal( p1h,P1_EXTCMD, &externalcmd);

  GetCtrlVal(p1h,P1_FIXEDDATA, sfixeddata);
  fixeddata =  strtoul (sfixeddata,NULL,0);
  GetCtrlVal(p1h,P1_TESTFIXEDDATA, &testfixeddata);


  GetCtrlVal(p1h,P1_TOREAD, &toread);


  GetCtrlVal(p1h,P1_NEVE, &neve);
  GetCtrlVal(p1h,P1_DSTEP, &dstep );


  GetCtrlVal(p1h,P1_SENDSWTRIG,&sendswtrg);
  GetCtrlVal(p1h,P1_INTTRGLEN, &trglen);
  GetCtrlVal(p1h,P1_DAQMODE, &daqmode);
  Sa02DaqMode (daqmode);
  Sa02SelectTriggerWithMaskAndLength (sendswtrg, mask, trglen);


  GetCtrlVal(p1h,P1_CHIP,&chip);
  GetCtrlVal(p1h,P1_CHANNEL,&ch);
  GetCtrlVal(p1h,P1_DATA,&data);
  data0=data;
  GetCtrlVal(p1h,P1_SCANTYPE,&towrite);
  switch (towrite) {
    case 1:
      GetCtrlVal(p1h,P1_WRITECMD,scmd);
      if (strcmp(scmd,"MUXASIC")==0) {
        remap=1;
      }
      cmd =sa02GetCmdCode(scmd);
      break;
    case 3:
      GetCtrlVal(p1h,P1_CHANNELOFF,scmd);
      dataoff  = strtoul (scmd,NULL,0);
      GetCtrlVal(p1h,P1_CHANNELON,scmd);
      dataon  = strtoul (scmd,NULL,0);
      chip    =data/36;
      ch      =data%36;
      sprintf(scmd,"channel");
    case 2:
      GetCtrlVal(p1h,P1_ASICPAR,scmd);
      if (strlen(scmd))  cmd = sa02GetAsicCode(scmd,&asicpar, &asicshft);

      break;
  }


  if (remap) {
    data = sa02MuxMap(data);
    sa02Printf("MUX %d\n",data);
  }

  GetCtrlVal(p1h,P1_TPENB,&tpenb);
  //ReplaceAxisItem (p1h, P1_GRAPH2D, VAL_LEFT_YAXIS, 0, scmd, data0);

  if (strlen(filename)>0) {
    if (sa02Verbose) {
      sa02Printf("Data in the file:%s\n", filename);
    }
    if (gFp) {
      fp=gFp;
    } else {
      if (append) {
        fp=fopen(filename,"ab");
      } else {
        fp=fopen(filename,"wb");
      }
    }
    output=1;
    // run header
    runinfo.id= RUNINFO_ID; // run record ID
    runinfo.len= sizeof(runinfo);
    runinfo.cmd= cmd;
    runinfo.x0 = data;
    runinfo.dx = dstep;
    runinfo.nx = neve;
    runinfo.chip= chip;
    runinfo.ch  = ch;
    runinfo.neve= toread;
    runinfo.writemode= towrite;
    sa02Printf("RUNINFO x0=%d nx=%d dx=%d\n", runinfo.x0,runinfo.dx,runinfo.nx);
    nbtotal+=fwrite(&runinfo, 1,sizeof(runinfo),fp); //gzip
  } else {
    if (sa02Verbose) {
      sa02Printf("Data are not written to the file!\n");
    }
  }

  if (!neve & (towrite || toread) ) {
    neve=1;
  }


  time(&t);
  tstart=t;
  told=t;
  t0 = Timer();


  title[0] = 0;
  for (i=0; i<4; i++) {
    int febon=0;
    Sa02TestPulseEnable(i, tpenb); // Enable/disable test pulse
    sa02GetSerial(i, serial);
    GetCtrlVal(p1h,hapd_onoff[i], &febon);
    if (strstr(serial,"0x00000000000000")!=NULL && febon) {
      char txt[0xFF];
      sprintf(txt, "FEB %d not connected or firmware not loaded? Serial number error! Switch Off FEB!",i);
      MessagePopup ("Error", txt);
      return -1;
    }
    sprintf(title,"%s FEB%d=%s", title, i, serial);
  }

  ///////////////////////////////////////////////////////////////
  int icfa_visible=0;
  int icfa_add=0;
  GetPanelAttribute (p6h, ATTR_VISIBLE, &icfa_visible);
  GetCtrlVal (p6h, MINIRICH_ADD, &icfa_add);
  if (icfa_visible) {
    icfa_Init();
    icfa_Histo();
  }  
  ///////////////////////////////////////////////////////////////
  SetCtrlAttribute  (p1h, P1_GRAPH2D, ATTR_LABEL_TEXT , title);
  H2DInit(h2, "h2d",title, 144*4, 0,1,neve,data0, dstep);
  H2DSetTitleY(h2,scmd);

  sa02Printf("H2D nx=%d ny=%d  i=%d neve=%d\n", H2DGetNbinsX(h2),H2DGetNbinsY(h2), i, neve);


  plot2d(h2,1);
  for (i=0; i<neve; i++) {
    int nb = sizeof(uint32_t);
    int count=0;


    for (board=0; board<4; board++) {

      switch (towrite) {
        case 1: {
          rdata[count+2]= data;
          rdata[count+3]= sa02Cmd(board, cmd, data, chip, ch,1,response);
          count+=module_header(cmd,&rdata[count],2 );
          break;
        }
        case 2: {
          uint32_t datal = asicpar & (data << asicshft);
          rdata[count+2] =  data;
          rdata[count+3] =  sa02AsicWrite(board, cmd, datal, chip, ch, asicpar,asicshft);
          count+=module_header(cmd ,&rdata[count],2); // recid cmd
          break;
        }
        case 3: {
          rdata[count+2] =  chip*36+ch;
          rdata[count+3] =  sa02AsicWrite(board, cmd, dataon, chip, ch, asicpar,asicshft);  // switch on the channel
          count+=module_header(cmd ,&rdata[count],2); // recid cmd
          break;
        }
      }
      if (towrite==3) {
        SetCtrlVal(p1h,P1_SETVALUE, chip*36+ch );
      } else {
        SetCtrlVal(p1h,P1_SETVALUE, data);
      }



    }

    Sa02SetNeve(toread);
    sa02Reset();

//    for ( j=0; j< toread; j++)
    {
      int eventerror =  0;

      if ( (count +2 +dsize)  >= maxsize) {

        maxsize*=2;
        sa02Printf("Increasing data buffer to %d elements\n", maxsize);
        rdata=realloc(rdata ,sizeof(uint32_t)*maxsize);
      }

      do {
        if (sendswtrg == 1) Sa02SoftwareTrigger();
        nb  = sa02Read(mask, &rdata[count+2] );
      } while  ( nb==0 && !ctrl_c);
      if (nb==0)  sa02Printf("nb==0 LINE=%d\n",__LINE__);

      if (testfixeddata && nb>0) {
        int len = nb / sizeof(uint32_t);
        for (ir=0; ir<len; ir++) {
          if ( rdata[count+2+ir]!=fixeddata ) {
            time(&t);
            sa02Printf("INSERT INTO fixederror VALUES ( '%d', '%d','%d','%d','0x%08x','0x%08x' ) \n", t, t-tstart, i*toread+j, ir, rdata[count+2+ir], fixeddata );
            eventerror++;
          }
        }
      }
      if (eventerror) {
        readerror++;
        if (readerror==3) {
          ctrl_c = 1;
          system("date >> firmware.lock");
        }
      } else {
        readerror= 0;
      }

      for (ich=0; ich<144*4; ich++) {
        int xch = (143 - ich%144) + ich/144*144;
        H2DFillBin(h2, xch,i,rdata[count+2+ich]);
      }
     
      if (icfa_visible) icfa_Event(&rdata[count+2], icfa_add );
       
      /*
      for (ich=0; ich<144; ich++) {
      //        id=(35-ich/4)+gBoardNumber*36;
      //        shft=(ich%4)*8;
        id=(17-ich/8)+sa02BoardNumber*18;
        shft=(ich%8)*4;

      //        if ( rdata[count+2+id]  & (0xFF <<shft)  ) {
        if ( rdata[count+2+id]  & (0xF <<shft)  ) {
          H2DFillBin(h2, ich,i,1);
        }
        if (sa02Verbose>2) {
          sa02Printf("%02X ",(rdata[count+2+id]>> shft)& 0xF );
      //        sa02Printf("%02X ",(rdata[count+2+id]>> shft)& 0xFF );
        }
      }
      */


      if (sa02Verbose>2) sa02Printf("\n" );
      if (nb>=0) count+=module_header(0x3,&rdata[count],nb/sizeof(uint32_t));  // recid 0x3

      if (ctrl_c) {
        sa02Printf("ctrl_c detected ....\n");
        break;
      }

      time(&t);
      if (t!=told ) {
        double done= (double) (i)/neve;
        EstimatedFinish(p1h, P1_PROGRESS, P1_ETA, tstart, done);
        plot2d(h2,i-1);
        GetPanelAttribute (p6h, ATTR_VISIBLE, &icfa_visible);
        if (icfa_visible) icfa_Draw();
        SetCtrlVal(p1h,P1_CUREVE, j);
        sa02Printf("%d events in %2.2f min (%d s)  TIMEOUTS=%d %s",ncount, (double)(t-tstart)/60.,t-tstart,  nerrors, ctime(&t));
      }
      if (aborttimeout && (t-tstart)>aborttimeout) {
        sa02Printf("Abort timeout reached ....\n");
        ctrl_c=1;
        break;
      }
      told=t;
      if (nb==0) {
        nerrors++;
        //j--;    /// kako potem pride cez zeljeno stevil ozadetkov?
      } else {
        ncount++;
      }
    }
    if (externalcmd) {
      char ecmd[256];
      sprintf(ecmd,"%s %u %u %u %u",externalcommand,(unsigned int)  tstart,data, rdata[2], rdata[3]);
      if (sa02Verbose) {
        sa02Printf("Executing external command %s\n",ecmd);
      }
      system(ecmd);
    }

    if (output && Random(0,1)<fraction) {
      evtrec.id = EVTREC_ID;
      evtrec.len=count*sizeof(uint32_t)+ sizeof(evtrec);
      evtrec.time= (uint32_t) time(NULL);
      evtrec.nev=i;
      nb = (int) fwrite( &evtrec,  1,  sizeof(evtrec),fp); //gzip
      if (count) {
        nb+= (int) fwrite(&rdata[0],1,count*sizeof(uint32_t),fp);  //gzip
      }
      if (nb!= (int) evtrec.len) {
        sa02Printf("Error writing! %d!=%d\n",nb,evtrec.len);
      }
      nbtotal+= nb;
    }

    if (sa02Verbose==1)  {
      sa02Printf("[%d/%d] %u \t", i,count, (unsigned int) time(NULL));
      PrintData(rdata,count);
    }
    if (towrite ==3) {
      sa02AsicWrite(board, cmd, dataoff, chip, ch, asicpar, asicshft);
      ch += dstep;
      if (ch>35) {
        ch-=36;
        chip++;
      }
    } else {
      data += dstep;
    }
    if (ctrl_c ) {
      if (!testfixeddata) {
        sa02Printf("Ctrl+C Program interrupted ....\n");
      }
      break;
    }
  }
  plot2d(h2, i-1);
  if (icfa_visible) icfa_Draw();

  if (output) {
    sprintf(scmd,"channel;daqtime=%f", Timer()-t0 );
    H2DSetTitleX(h2,scmd);
    H2DWrite2File(h2,fp);
    if (!gFp) {
      fclose(fp);
    }
  }
  if (sa02Verbose>1) sa02Printf("%d bytes written to file %s\n", nbtotal, filename);
  time(&t);
  if (toread && !testfixeddata) sa02Printf("%d events in %2.2f min  (%f s)  TIMEOUTS=%d  %s",ncount, (double)(Timer()-t0)/60.,Timer()-t0, nerrors, ctime(&t));
  free(rdata);

  return 0;
}

int CVICALLBACK quit (int panel, int event, void *callbackData,
                      int eventData1, int eventData2) {
  switch (event) {
    case EVENT_CLOSE:
      // Stop timer callbacks
      SuspendTimerCallbacks();
      QuitUserInterface (0);
      break;
  }
  return 0;
}

int CVICALLBACK Exit (int panel, int control, int event,
                      void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      quit(0,0,NULL,0,0);
      exit(0);
  }
  return 0;
}

int SetParametersFromFile( const char *fname) {
  uint32_t gdata;
  uint32_t cdata;

  sa02AsicGlobalRegister  *greg = (sa02AsicGlobalRegister *) &gdata ;
  sa02AsicChannelRegister *creg = (sa02AsicChannelRegister *) &cdata ;
  unsigned short cregdata[8*144*4];
  unsigned short gregdata[7*4*4];
#define NDIM 400
  int ndim=NDIM;
  char line[NDIM];
  char cmd[NDIM];
  char sasic[NDIM];
  char v0[NDIM];
  char v1[NDIM];
  int asic=0, ch=0;
  int gval=0, cval=0;
  int board=0;
  int row=0;
  uint32_t sa02code;
  int i;
  ssize_t size;
  FILE *fp = NULL;
  if ( GetFileInfo(fname,&size) ) fp = fopen(fname,"r");
  if (!fp) {
    sa02Printf("Error! Cannot open file %s\n",fname);
    return -1;
  }
  for (i=0; i<8*144*4; i++) {
    cregdata[i]=0;
  }
  for (i=0; i<7*4*4; i++) {
    gregdata[i]=0;
  }
  gdata=0;
  cdata=0;
  ResetTextBox(p3h,P3_FPGAPAR,"");
  while (fgets(line,ndim,fp)!=NULL) {
    int nb = sscanf(line,"%s%s%s%s",cmd,sasic,v0,v1);
    if (nb<1 || cmd[0]=='#') {
      continue;
    }
    asic =   strtoul (sasic,NULL,0);
    ch   =   strtoul (v0,NULL,0);
    gval =   strtoul (v0,NULL,0);
    cval =   strtoul (v1,NULL,0);
    if (sa02Verbose>2) {
      sa02Printf("%d %s",nb,line);
    }
    sa02code = sa02GetCmdCode(cmd);
    if (strcmp(cmd,"MUXASIC")==0) {
      asic = sa02MuxMap(asic);
    }
    switch (nb) {
      case 1: {
        if ( sa02code ) {
          SetCtrlVal(p3h,P3_FPGAPAR,line);

          break;
        }
        break;
      }
      case 2: {
        if ( sa02code ) {
          SetCtrlVal(p3h,P3_FPGAPAR,line);

          break;
        }
        if (strcmp(cmd,"param_board")==0) {
          board= asic;
        }
        if (strcmp(cmd,"load_global")==0) {
          row= asic+1;
          greg->id=13;
          /*
          SetTableCellVal (p3h, P3_GREG, MakePoint (1,row), greg->phasecmps);
          SetTableCellVal (p3h, P3_GREG, MakePoint (2,row), greg->gain);
          SetTableCellVal (p3h, P3_GREG, MakePoint (3,row), greg->shapingtime);
          SetTableCellVal (p3h, P3_GREG, MakePoint (4,row), greg->comparator);
          SetTableCellVal (p3h, P3_GREG, MakePoint (5,row), greg->vrdrive);
          SetTableCellVal (p3h, P3_GREG, MakePoint (6,row), greg->monitor);
          SetTableCellVal (p3h, P3_GREG, MakePoint (7,row), greg->id);
          */

          gregdata[(board*4+asic)*7]   = greg->phasecmps;
          gregdata[(board*4+asic)*7+1] = greg->gain;
          gregdata[(board*4+asic)*7+2] = greg->shapingtime;
          gregdata[(board*4+asic)*7+3] = greg->comparator;
          gregdata[(board*4+asic)*7+4] = greg->vrdrive;
          gregdata[(board*4+asic)*7+5] = greg->monitor;
          gregdata[(board*4+asic)*7+6] = greg->id;

          break;
        }
        break;
      }
      case 3: {
        if ( sa02code) {
          SetCtrlVal(p3h,P3_FPGAPAR,line);
          break;
        }
        if (strcmp(cmd,"param_global")==0)    {
          gdata = 0;
          break;
        }
        if (strcmp(cmd,"phasecmps")==0)   {
          greg->phasecmps = gval;
          break;
        }
        if (strcmp(cmd,"gain")     ==0)   {
          greg->gain = gval;
          break;
        }
        if (strcmp(cmd,"shapingtime")==0) {
          greg->shapingtime = gval;
          break;
        }
        if (strcmp(cmd,"comparator")==0)  {
          greg->comparator = gval;
          break;
        }
        if (strcmp(cmd,"vrdrive")==0)     {
          greg->vrdrive = gval;
          break;
        }
        if (strcmp(cmd,"monitor")==0)     {
          greg->monitor = gval;
          break;
        }
        if (strcmp(cmd,"load_ch")==0)   {
          row = board*144+asic*36+ch+1;
          /*
          SetTableCellVal (p3h, P3_CREG, MakePoint (1,row), asic);
          SetTableCellVal (p3h, P3_CREG, MakePoint (2,row), ch);
          SetTableCellVal (p3h, P3_CREG, MakePoint (3,row), creg->decaytime);
          SetTableCellVal (p3h, P3_CREG, MakePoint (4,row), creg->offset);
          SetTableCellVal (p3h, P3_CREG, MakePoint (5,row), creg->fineadj_unipol);
          SetTableCellVal (p3h, P3_CREG, MakePoint (6,row), creg->fineadj_diff);
          SetTableCellVal (p3h, P3_CREG, MakePoint (7,row), creg->tpenb);
          SetTableCellVal (p3h, P3_CREG, MakePoint (8,row), creg->kill);
          */


          cregdata[(row -1)*8]   = (unsigned short) asic;
          cregdata[(row -1)*8+1] = (unsigned short) ch;
          cregdata[(row -1)*8+2] = creg->decaytime;
          cregdata[(row -1)*8+3] = creg->offset;
          cregdata[(row -1)*8+4] = creg->fineadj_unipol;
          cregdata[(row -1)*8+5] = creg->fineadj_diff;
          cregdata[(row -1)*8+6] = creg->tpenb;
          cregdata[(row -1)*8+7] = creg->kill;
          cdata=0;
          break;
        }
        if (strcmp(cmd,"select")==0)    {
          sa02Printf ("%s not implemeted yet\n", cmd);
          break;
        }
        break;
      }
      case 4: {
        if (strcmp(cmd,"param_ch")==0)    {
          cdata = 0;
          break;
        }
        if (strcmp(cmd,"decaytime")==0)  {
          creg->decaytime = cval;
          break;
        }
        if (strcmp(cmd,"offset")==0)     {
          creg->offset = cval;
          break;
        }
        if (strcmp(cmd,"fineadj_unipol")==0) {
          creg->fineadj_unipol = cval;
          break;
        }
        if (strcmp(cmd,"fineadj_diff")==0) {
          creg->fineadj_diff   = cval;
          break;
        }
        if (strcmp(cmd,"tpenb")==0)      {
          creg->tpenb = cval;
          break;
        }
        if (strcmp(cmd,"kill")==0)       {
          creg->kill  = cval;
          break;
        }
        break;
      }
    }

  }
  fclose(fp);
  SetTableCellRangeVals (p3h, P3_CREG, MakeRect (1, 1, 144*4, 8), cregdata, VAL_ROW_MAJOR);
  SetTableCellRangeVals (p3h, P3_GREG, MakeRect (1, 1, 4*4, 7)  , gregdata, VAL_ROW_MAJOR);

  sa02Printf("Parameters loaded from file %s to Parameter Panel \n", fname);
  return 0;
}

void CVICALLBACK MenuCB(int menubar, int menuItem, void *callbackData, int panel) {
  switch (menuItem) {
    case MENU_OPERATIO_CAEN_V729:
      DisplayPanel(p4h);
      break;
    case MENU_OPERATIO_SA02CFG :
      DisplayPanel(p3h);
      break;
    case MENU_OPERATIO_2DSCAN:
      DisplayPanel(p2h);
      break;
    case MENU_OPERATIO_LASER:
      DisplayPanel(p5h);
      break;
    case MENU_MINIRICH:
      DisplayPanel(p6h);
      break;  
    case MENU_OPERATIO_EXIT :
      quit(0,0,NULL,0,0);
      exit(0);
      //loop_on=0;
      break;
    case MENU_HELP :
      sa02Help();
      break;
  }
}

int CVICALLBACK daq_readonly(void *functionData) {
  int h2=0;
  uint32_t trglen;
  uint32_t data[10000];
  uint16_t mask;
  //int ison;
  //int *fdata= (int *) functionData;
  int nbit,neve,nb,ch,i,j,sendswtrg;

  time_t t,told, tstart;
  //int gBoardNumber=0;
  int ploteachevent =0;

  GetCtrlVal(p1h,P1_PLOTEACHEVENT, &ploteachevent);
  GetCtrlVal(p1h,P1_TOREAD , &neve);
  GetCtrlVal(p1h,P1_NSLIX , &nbit);
  if (nbit>7) {
    nbit=7;
  }
  GetCtrlVal(p1h,P1_SENDSWTRIG,&sendswtrg);
  GetCtrlVal(p1h,P1_INTTRGLEN, &trglen);

  mask=GetConnectedFebMask();
  Sa02SelectTriggerWithMaskAndLength (sendswtrg, mask, trglen);
  Sa02SetNeve(2);

  H2DInit(h2,"hbit","Bit Occupancy", 144*4, 0,1,8,0, 1);
  H2DSetTitleX(h2,"channel");
  H2DSetTitleY(h2,"Data bit");
  time(&t);
  tstart=t;
  told=t;
  for ( j=0; j< neve; j++) {
    do {
      if (sendswtrg==1) Sa02SoftwareTrigger();
      nb  = sa02Read(mask, data );
    } while  ( nb==0 && !ctrl_c);
    if (nb==0)  sa02Printf("nb==0 LINE=%d\n",__LINE__);

    if (ctrl_c==1) break;

    for (ch=0; ch<144*4; ch++) {
      int board = ch/144;
      int xch   = (143 - ch%144) + board *144;
      for (i=0; i<8; i++) if (data[ch] & (1<<i) ) H2DFillBin(h2,xch,i,1);
    }
    /*
    for (ch=0; ch<144*4; ch++)
    {
      id=(35-ch/4)+gBoardNumber*36;
      shft=(ch%4)*8;
      for (i=0; i<8; i++)
      {
        if (data[id] & (1<<(i+shft)) )
        {
          H2DFillBin(h2,ch,i,1);
        }
      }
      if (sa02Verbose>2)
      {
        sa02Printf("%02X ",(data[id]>> shft)& 0xFF );
      }
    }
    */


    if (sa02Verbose>2) {
      sa02Printf("\n" );
    }

    time(&t);
    if (t!=told || ploteachevent) {
      sa02Printf("%d events in %2.2f min (%d s) %s",j, (double)(t-tstart)/60.,t-tstart, ctime(&t));
      GetCtrlVal(p1h,P1_NSLIY,&nbit);
      plot2d(h2, nbit);
      GetCtrlVal(p1h,P1_PLOTEACHEVENT, &ploteachevent);
      SetCtrlVal(p1h,P1_CUREVE, j);
      ProcessSystemEvents ();
      ProcessSystemEvents ();
    }

    told=t;

  }

  plot2d(h2, nbit);
  SetCtrlVal(p1h,P1_CUREVE, j);

  return 0;
}

int CVICALLBACK LoadParameters (int panel, int control, int event,
                                void *callbackData, int eventData1, int eventData2) {
  char fname[0xFF];
  uint16_t mask;
  switch (event) {
    case EVENT_COMMIT:
      mask=GetConnectedFebMask();
      sa02Printf("LoadParameters 0x%0x\n", mask);
      GetCtrlVal(p3h, P3_INPUTFILE, fname);
      GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 1);
      sa02LoadParametersFromFile(fname, mask);
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 0);

      break;
  }
  return 0;
}

int SlowControl(uint32_t board, FILE *fp) {
  uint32_t data;//,step,cmd;//,response[2]= {0,0};
  int chip,channel,i;
  //double doubleval;
  char saddress[0xFF];
  double sdata[20];

  chip=0;
  channel=0;
  data=0;

  GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);
  sa02Status(board,saddress,sdata);
  SetCtrlVal(p1h,fpga_serials[board],saddress);
  if (fp) {
    fprintf(fp,"<slowc>\n<id>%d</id>\n", board );
    fprintf(fp,"<dna>%s</dna>\n",saddress );
    for (i=0; i<12; i++) fprintf(fp,"<%s>%f</%s>\n",slowcname[i],sdata[i],slowcname[i] );
    fprintf(fp,"</slowc>\n" );
  }
  PlotStripChart (p1h, chart_control[board], sdata, 12, 0, 0, VAL_DOUBLE);
  return 0;
}


int WriteChannelParameters ( int offset, int fine_offset, int tpenb) {

  uint32_t response[2]= {0,0};
  uint32_t cdata;

  sa02AsicChannelRegister *creg = (sa02AsicChannelRegister *) &cdata ;
  unsigned int i=0, j=0;
  int row=0;
  unsigned short val,asic,ch, board;
  uint16_t mask=GetConnectedFebMask();
  for (j=0; j<144*4; j++) {
    i = j%144;
    board = (unsigned short) j/144;
    asic=(unsigned short )(i/36);
    ch=(unsigned short )(i%36);
    row=j+1;
    GetTableCellVal (p3h, P3_CREG, MakePoint (1,row), &asic);
    GetTableCellVal (p3h, P3_CREG, MakePoint (2,row), &ch);
    GetTableCellVal (p3h, P3_CREG, MakePoint (3,row), &val);
    creg->decaytime=val;
    creg->offset = offset;
    creg->fineadj_unipol = fine_offset;
    GetTableCellVal (p3h, P3_CREG, MakePoint (6,row), &val);
    creg->fineadj_diff = val;
    creg->tpenb = tpenb;
    //sa02Printf("===%d   %d\n",i, tpenb);
    GetTableCellVal (p3h, P3_CREG, MakePoint (8,row), &val);
    creg->kill = val;
    creg->unused=0;
    if ( mask &(1<<board)) sa02Cmd(board,SA0x_ASIC0_CREG, cdata, asic, ch,1,response);

    if (ctrl_c) {
      break;
    }
  }
  return 0;
}

int FebTestAna(void) {
  int current_run;
  char cmdCommand[0xFF];
  current_run = GetRunNumberFromFile("current_run.txt");
  sprintf(cmdCommand ,"C:/root/bin/root.exe \"../macros/febreport.cxx(\\\"data\\\", %d )\"", current_run);
  sa02Printf("%s\n",cmdCommand);
  LaunchExecutable(cmdCommand);
  return 0;
}

int FebTest(void) {
  int board=0, j=0, value, step;

  FILE *fp;
  int ndim=400;
  char line[ndim];
  int current_run=1;
  time_t t;
  int start;
  int addheader=1;
  char filename[0xFF];
  char cmdCommand[0xFF];

  uint32_t mask=GetConnectedFebMask();

  LoadParameters(p3h, P3_LOADPAR,EVENT_COMMIT,NULL,0,0);


  fp = fopen ("current_run.txt","r");
  if (fp) {
    if (fgets(line,ndim,fp)!=NULL) current_run=atoi(line)+1;
    fclose(fp);
    fp= NULL;
  }

  sprintf(line,"data\\febtest_%04d.dat",current_run );
  SetCtrlVal(p1h,P1_OUTPUTFILE, line);

  SetCtrlVal(p1h,P1_SENDSWTRIG,3 ); // set internal trigger
  SendTriggerTypeCB(p1h,P1_TEST, EVENT_COMMIT,NULL, 0,0);

  ThresholdLinearityCB (p1h, P1_THRVSADC, EVENT_COMMIT, NULL, 0, 0 );

  GetCtrlVal(p1h,P1_OUTPUTFILE, filename);
  fp = fopen(line, "ab");
  if(fp) {
    for (board=0; board<4; board++) if ( mask &(1<<board))  H1DWrite2File(board,fp);
    fclose(fp);
  }


  sprintf(line,"data/febslowc_%04d.xml",current_run );
//  SetCtrlVal(p1h, P1_RUNID, current_run);
  fp = fopen (line,"w");
  fprintf(fp,"<febtest>\n");
  time(&t);
  fprintf(fp,"<time>%s</time>\n", ctime(&t));



  if (!ctrl_c)  for (board=0; board<4; board++) {
      if ( mask &(1<<board)) {
        for (j=0; j<10; j++) {
          SlowControl(board,fp);
          ProcessSystemEvents ();
          if (ctrl_c) break;
        }
      }
      if (ctrl_c) break;
    }


  fprintf(fp,"</febtest>\n");
  fclose(fp);


  fp = fopen ("current_run.txt","w");
  fprintf(fp,"%d\n", current_run);
  fclose(fp);





  WriteChannelParameters ( 0,0,0);   // Test pulse on all channels
  for (board=0; board<4; board++) if ( mask &(1<<board)) SlowControl(board,fp);
  SetCtrlVal(p1h,P1_TPENB,1);    // enable test pulse

  SetCtrlVal(p1h,P1_DATA, 350);
  SetCtrlVal(p1h,P1_NEVE, 150);

  GetCtrlVal(p1h,P1_DATA, &start);

  daq(NULL);
  SetCtrlVal(p1h,P1_TPENB,0);    // disable test pulse


  // coarse offset
  step=1;
  if (!ctrl_c)  for (value=0; value<16; value+=step) {
      if (addheader) {
        iteratorrec.id = ITERATORREC_ID;
        iteratorrec.len = sizeof(iteratorrec);
        iteratorrec.value = value;
        iteratorrec.n     = 16;
        iteratorrec.step  = step;
        iteratorrec.level = 1;
        GetCtrlVal(p1h,P1_OUTPUTFILE, filename);
        fp = fopen(filename, "ab");
        if(fp) {
          fwrite (&iteratorrec, 1, iteratorrec.len, fp);
          fclose(fp);
        }
      }

      WriteChannelParameters ( value,0,1);

      SetCtrlVal(p1h,P1_DATA,start - (value%8) * 13 + (value/8)*13*8 );
      sa02Printf("offset=>%d\n", value);
      daq(NULL);
      if (ctrl_c) break;
    }

  // fine offset
  if (!ctrl_c)  for (value=0; value<16; value+=step) {
      if (addheader) {
        iteratorrec.id = ITERATORREC_ID;
        iteratorrec.len = sizeof(iteratorrec);
        iteratorrec.value = value;
        iteratorrec.n     = 16;
        iteratorrec.step  = step;
        iteratorrec.level = 1;
        GetCtrlVal(p1h,P1_OUTPUTFILE, filename);
        fp = fopen(filename, "ab");
        if(fp) {
          fwrite (&iteratorrec, 1, iteratorrec.len, fp);
          fclose(fp);
        }
      }


      WriteChannelParameters (0, value,1);

      SetCtrlVal(p1h,P1_DATA, start - (value%8)  + (value/8)*8 );
      sa02Printf("offset=>%d\n", value);
      daq(NULL);
      if (ctrl_c) break;
    }

  SetCtrlVal(p1h,P1_DATA, start);

  GetCtrlVal(p1h,P1_OUTPUTFILE, filename);

  sprintf(cmdCommand,"..\\sa02read -i %s -o data\\febtest_%04d.root", filename, current_run);
  sa02Printf("%s\n",cmdCommand);
  LaunchExecutable(cmdCommand);

  //sprintf(cmdCommand ,"C:/root/bin/root.exe ../macros/febreport.cxx(\\\"data/febtest_%04d.root\\\")", current_run);
  sprintf(cmdCommand ,"C:/root/bin/root.exe \"../macros/febreport.cxx(\\\"data\\\", %d )\"", current_run);
  sa02Printf("%s\n",cmdCommand);
  LaunchExecutable(cmdCommand);

  sprintf(line,"%s", "test.dat");
  SetCtrlVal(p1h,P1_OUTPUTFILE, line);
  //daq(NULL);
  return 0;
}


int CVICALLBACK ThresholdLinearityCB (int panel, int control, int event,
                                      void *callbackData, int eventData1, int eventData2) {
  const int kmax= 1024;
  const int boardmax= 4;

  switch (event) {
    case EVENT_COMMIT: {
      uint32_t val,retval, board,data,response[2]= {0,0};
      int k;
      int chip,channel;
      double doubleval;
      time_t t,told;
      char title[0xFF];
      char name[0xFF];
      int h1=0;
      uint16_t mask=GetConnectedFebMask();
      chip=0;
      channel=0;
      GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);

      for (board=0; board<boardmax; board++) if ( mask &(1<<board)) {
          char serial[0xFF];
          GetCtrlVal(p1h,hapd_serials[board],serial );
          sprintf(title,"VTH1 linearity, position  %d sn=%s", board, serial);
          sprintf(name,"vth1_%d", board);
          H1DInit(h1+board, name,title, kmax, 0 ,1);
          H1DSetTitleX(h1+board,"VTH1");
          H1DSetTitleY(h1+board,"ADC(VTH1)");
          SetCtrlAttribute  (p1h, P1_GRAPH, ATTR_XNAME, H1DGetTitleX(h1+board) );
          SetCtrlAttribute  (p1h, P1_GRAPH, ATTR_YNAME, H1DGetTitleY(h1+board) );
          //SetCtrlAttribute  (p1h, P1_GRAPH, ATTR_LABEL_TEXT , H1DGetTitle(h1+board) );
          if (phandle[board]> 0 ) DeleteGraphPlot (p1h, P1_GRAPH, phandle[board], VAL_IMMEDIATE_DRAW);
          phandle[board] = 0;
        }
      for (board=0; board<boardmax; board++) if ( mask &(1<<board)) {
          val=sa02Cmd(board, FEB_MUX, data=0x20, chip, channel ,1,response);  // set mux to  VTH1
          time(&t);
          told=t;
          if (ctrl_c) break;
          for (k=0; k<kmax; k++) {
            if (ctrl_c) break;
            SetCtrlVal(p1h,P1_SETSINGLEVALUE,k);
            SetCtrlVal(p1h,P1_CUREVE,k);
            retval=sa02Cmd(board, FEB_VTH1 , k  , chip, channel ,1, response);
            val=sa02Cmd(board, FEB_ADC_READ, data, chip, channel ,1,response);
            if (sa02BoardType>2)
              doubleval = (2*((val & 0xFFF) + 0.5)/0x1000 - 1.) * 3.3;
            else
              doubleval = ((val & 0xFFF) + 0.5)/0x1000 * 3.3;


            H1DFillBin(h1+board, k, doubleval);
            if (t!=told || k==kmax-1 ||k==0 ) {
              H1DDraw(h1+board,p1h, P1_GRAPH, &phandle[board]);
              sa02Printf("[%d] set VTH1=%d  ADC(VTH1)= %6.3f V\n",board, k,  doubleval);
              SetCtrlVal(p1h,P1_CUREVE, k);
              ProcessSystemEvents ();
            }
            told=t;
            time(&t);
          }
        }
      break;
    }
  }
  return 0;
}


int CVICALLBACK MultiFpgaWrite (void *functionData) {
  uint32_t val, board,data,step,cmd,response[2]= {0,0};
  char  scmd[0xFF],sdata[0xFF];
  int chip, channel;
  char filename[0xFF];
  double delay, doubleval=0, x0, dx;
  int neve,i,daqexe,addheader;
  time_t t,told, tstart;
  FILE *fp;
  //int h2=0;
  int *fdata= (int *) functionData;

  datrec.id = DATREC_ID;
  datrec.len = sizeof(datrec);
  GetCtrlVal(p1h,P1_MULTINEVE , &neve);
  GetCtrlVal(p1h,P1_WAIT , &delay);
  GetCtrlVal(p1h, P1_SINGLEWRITECMD, scmd);
  cmd=sa02GetCmdCode(scmd);
  GetCtrlVal(p1h,P1_BOARDNUMBER, &board);
  GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);
  GetCtrlVal(p1h, P1_SINGLEDATA, sdata);
  data =  strtoul (sdata,NULL,0);
//        if (strcmp(scmd,"MUXASIC")==0) {
//               data = sa02MuxMap(data);
//               sa02Printf("MUX %d\n",data);
//        }
  GetCtrlVal(p1h, P1_SINGLEDATA, sdata);
  data =  strtoul (sdata,NULL,0);
  x0=(double)data;
  GetCtrlVal(p1h, P1_DSTEP0, &step);
  dx=(double)step;
  GetCtrlVal(p1h,P1_SINGLECHIP,&chip);
  GetCtrlVal(p1h,P1_SINGLECHANNEL,&channel);
  if (fdata[0]==P1_FPGAWRITE) {
    neve=1;
  }
  GetCtrlVal(p1h,P1_DAQEXE,&daqexe);
  GetCtrlVal(p1h,P1_ADDHEADER,&addheader);
  time(&t);
  tstart=t;
  told=t;
  if (addheader) {
    iteratorrec.id = ITERATORREC_ID;
    iteratorrec.len = sizeof(iteratorrec);
    iteratorrec.value = data;
    iteratorrec.n     = neve;
    iteratorrec.step  = step;
    iteratorrec.level = 2;
    GetCtrlVal(p1h,P1_OUTPUTFILE, filename);
    fp = fopen(filename, "ab");
    if(fp) {
      fwrite (&iteratorrec, 1, iteratorrec.len, fp);
      fclose(fp);
    }
  }
  for (i=0; i<neve; i++) {
    SetCtrlVal(p1h,P1_SETSINGLEVALUE,data);
    SetCtrlVal(p1h,P1_CUREVE,i);
    val=sa02Cmd(board, cmd, data, chip, channel ,1, response);
    if (addheader) {
      datrec.cmd    =cmd;
      datrec.data   =data;
      datrec.chip   =chip;
      datrec.channel=channel;
      datrec.retval =val;
      GetCtrlVal(p1h,P1_OUTPUTFILE, filename);
      fp = fopen(filename, "ab");
      if(fp) {
        fwrite (&datrec, 1, datrec.len, fp);
        fclose(fp);
      }
    }
    switch (cmd & (~ FEB_RO)) {
      case FEB_ADC_READ:
      case FEB_ADC_RESET:
        doubleval = ((val & 0xFFF) + 0.5)/0x1000 * 3.3;
        sa02Printf("ADC %f, 0x%08x\n", doubleval, val ) ;
        break;
      case FEB_TMON1:
      case FEB_TMON0:
        doubleval = ( (val >>2 ) & 0xFFF ) * 0.0625;
        if (val&0x4000) {
          doubleval=-doubleval;
        }
        sa02Printf("TMON %f 0x%x\n",doubleval, val ) ;
        break;
      case FEB_VTH1:
      case FEB_VTH2:
        doubleval = (val & 0xFFFF );
        if (cmd & 1)
          val=0x20;
        else
          val=0x30;
        val=sa02Cmd(board, FEB_MUX, val, 0, 0 ,1,response);
        val=sa02Cmd(board, FEB_ADC_READ, 0, 0, 0, 1,response);
        if (sa02BoardType>2)
          doubleval = (2*((val & 0xFFF) + 0.5)/0x1000 - 1.) * 3.3;
        else
          doubleval = ((val & 0xFFF) + 0.5)/0x1000 * 3.3;
        sa02Printf("%5d %6.3f\n",data, doubleval);
        break;
      case SA0x_ASIC0_GREG:
        if (cmd & FEB_RO) {
          sa02PrintGREG(&val,"Returned GREG data->");
        }
        break;
      case SA0x_ASIC0_CREG:
        if (cmd & FEB_RO) {
          sa02PrintCREG(&val,"Returned CREG data->");
        }
        break;
      default:
        sa02Printf("0x%08X\n",val);
//        break;
    }
    datay[i]=doubleval;
    if (delay>0 && fdata[0]==P1_MULTIFPGAWRITE) {
      Delay(delay);
    }
    if  (daqexe) {
      daq(NULL);
    }
    if (ctrl_c) {
      break;
    }
    if (t!=told  ) {
      plot1d(i,x0,dx);
      SetCtrlVal(p1h,P1_CUREVE, i);
      ProcessSystemEvents ();
    }
    data+=step;
    told=t;
    time(&t);
  }
  plot1d(i,x0,dx);
  SetCtrlVal(p1h,P1_CUREVE, i);
  return 0;
}

int CVICALLBACK SendSEUTRigger (int panel, int control, int event,
                                void *callbackData, int eventData1, int eventData2) {

  switch (event) {
    case EVENT_COMMIT:
      Sa02SEUTrigger();
      break;
  }
  return 0;
}

int CVICALLBACK FSelect (int panel, int control, int event,
                         void *callbackData, int eventData1, int eventData2) {
  int status,fcontrol = 0;
  char pathName[MAX_PATHNAME_LEN];
  char defName[MAX_PATHNAME_LEN];
  char fileMessage[100] = "";
  switch (event) {
    case EVENT_COMMIT:
      switch (control) {
        case P3_FSELECT:
          fcontrol=P3_INPUTFILE;
          strcpy(fileMessage,"Select Parameter file");
          break;
        case P3_PTSFSELECT:
          fcontrol=P3_PTSFIRMWARE;
          strcpy(fileMessage,"Select PTS Firmware file");
          break;
      }
      sa02Printf("MAX_PATHNAME_LEN %d\n",MAX_PATHNAME_LEN);
      GetCtrlVal(panel,fcontrol,defName);
      status = FileSelectPopup ("",defName,"",
                                fileMessage, VAL_LOAD_BUTTON, 0,
                                0, 1, 0, pathName);
      if (status>0)
        SetCtrlVal(panel,fcontrol,pathName);
      break;
  }
  return 0;
}

int CVICALLBACK Verbose (int panel, int control, int event,
                         void *callbackData, int eventData1, int eventData2) {
  //int * data;
  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal(panel,control,&sa02Verbose);
      break;
  }
  return 0;
}

int CVICALLBACK Print (int panel, int control, int event,
                       void *callbackData, int eventData1, int eventData2) {
  char dfile[MAX_PATHNAME_LEN];
  char name[MAX_PATHNAME_LEN];
  int h2=0;
  switch (event) {
    case EVENT_COMMIT: {
      int hours, minutes, seconds;
      int month, day, year;
      int   id=-1;
      //int   bitmap = 0;
      if (panel == p1h) {
        switch (control) {
          case P1_PRINT:
            id= P1_GRAPH;
            sprintf(name,"G");
            break;
          case P1_PRINT2D:
            id= P1_GRAPH2D;
            sprintf(name,"2D");
            break;
          case P1_PRINTX:
            id= P1_GRAPHX;
            sprintf(name,"X");
            break;
          case P1_PRINTY:
            id= P1_GRAPHY;
            sprintf(name,"Y");
            break;
        }
        h2=0;
      } else {
        switch (control) {
          case P2_PRINTXY:
            id= P2_GRAPH_1;
            sprintf(name,"XY");
            break;
        }
        h2=1;
      }
      GetSystemDate (&month,&day ,&year );
      GetSystemTime(&hours, &minutes, &seconds);
      if (id>=0) {
        if( ( (panel == p1h)&&(control ==  P1_PRINT2D) ) || ((panel == p2h)&&(control ==  P2_GRAPH_1))) {
          sprintf(dfile ,"data/%d_%d_%d_%d_%d_%s.th2d",year,month,day,hours,minutes, name );
          H2DWrite(h2,dfile,"wb");
          sa02Printf("sizeof H2D %d \n",sizeof(H2D));
          sa02Printf("H2D image saved as %s\n", dfile);
          sprintf(name ,"C:\\root\\bin\\root.exe ..\\macros\\H2Dload.cxx(\\\"%s\\\")", dfile);
          LaunchExecutable(name);
        } else {
          sprintf(dfile ,"data/%d_%d_%d_%d_%d_%s.bmp",year,month,day,hours,minutes, name );
          SaveCtrlDisplayToFile (panel,id, 0, -1, -1, dfile);
          sa02Printf("bmp image saved as %s\n", dfile);
        }
      }
      //PrintCtrl (p1h, P1_GRAPH2D, "sa02_CVI", 1, 1);
    }
    break;
  }
  return 0;
}

int CVICALLBACK CursorCB (int panel, int control, int event,
                          void *callbackData, int eventData1, int eventData2) {
  double x=0,y=0;
  int ix=0,iy=0;
  int h2=(int) callbackData;

  switch (event) {
    case EVENT_COMMIT:
      GetGraphCursor (p1h, P1_GRAPH2D, 1, &x, &y);
      if(H2DGetStepX(h2)>0) {
        ix=(int)((x-H2DGetMinX(h2))/H2DGetStepX(h2));
      }
      if(H2DGetStepY(h2)>0) {
        iy=(int)((y-H2DGetMinY(h2))/H2DGetStepY(h2));
      }
      SetCtrlVal(panel,P1_NSLIX,ix);
      SetCtrlVal(panel,P1_NSLIY,iy);
      sa02Printf("Cursor %f %f h2=%d val=%f min=%f max=%f\n",
                 x,y,h2,H2DGetBinContent(h2,ix,iy),H2DGetMin(h2),
                 H2DGetMax(h2) );
      break;
  }
  return 0;
}


int CVICALLBACK HistoInfoCB (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  double x=0,y=0;
  int ix=0,iy=0;
  int h2=(int) callbackData;
  int b=0;
  switch (event) {
    case EVENT_COMMIT:

      GetGraphCursor (panel, control, 1, &x, &y);
      if (panel == p2h ) {
        for (b=0; b<4; b++) {
          if (control==p2graph[b]) break;
        }
        h2=100+b;
        if(H2DGetStepX(h2)>0) {
          ix=(int)((x-H2DGetMinX(h2))/H2DGetStepX(h2));
        }
        if(H2DGetStepY(h2)>0) {
          iy=(int)((y-H2DGetMinY(h2))/H2DGetStepY(h2));
        }

        sa02Printf("Cursor %f %f h2=%d val=%f min=%f max=%f\n",
                   x,y,h2,H2DGetBinContent(h2,ix,iy),H2DGetMin(h2),
                   H2DGetMax(h2) );
      }
      break;
  }
  return 0;
}


int GetElectronicChannel(int x, int y, int *chip, int *ch) {
  int i=0;
  for (i=0; i<144; i++) {
    if (eid2hapdxy[i].chx == x && eid2hapdxy[i].chy == y) {
      *chip = eid2hapdxy[i].chip;
      *ch   = eid2hapdxy[i].ch  ;
      return 0;
    }
  }
  return -1;
}

int SetCMon(int chx,int chy) {
  int chip,ch,asic;
  uint32_t response[2]= {0,0};
  uint32_t board;
  uint16_t mask=GetConnectedFebMask();

//  GetCtrlVal(p1h,P1_BOARDNUMBER, &board);
  GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);
  GetElectronicChannel(chx,chy,&chip,&ch);
  asic = sa02MuxMap(chip);
  sa02Printf("CHX %d CHY %d ",chx, chy);
  sa02Printf("MUX %d ",asic);
  sa02Printf("CMON ASIC: %d  ch: %d\n",chip, ch);
  for (board=0; board<4; board++) {
    if (mask & (1<<board)) {
      sa02Cmd(board,FEB_MUX , asic, 0, 0 ,2,response);
      sa02Cmd(board,SA0x_ASIC0_CMON,0,chip,ch,2,response);
    }
  }

  return 0;
}

int CVICALLBACK HDraw2DCB (int panel, int control, int event,
                           void *callbackData, int eventData1, int eventData2) {
  int ch=0;
  int ctrlID=0;
  int *plot=0;
  int graph=0;
  int board=0;
  switch (event) {

    case EVENT_COMMIT:
      for (board=0; board<4; board++) {
//        if (panel == p1h){ rID = P1_CH; graph = P1_GRAPH; plot =&p1plothandle;}
        if (panel == p2h) {
          ctrlID = P2_CH;
          graph = p2graph[board];
          plot =&p2plothandle[board];
        }
//        if (panel == p3h){ rID = P3_CH; graph = P3_GRAPH; plot =&p3plothandle;}
//        if (panel == p4h){ rID = P4_CH; graph = P4_GRAPH; plot =&p4plothandle;}


        GetCtrlVal(panel,ctrlID, &ch);
        if (ch) {
          H3DDrawSliceXY(100+board,ch-1,panel,graph, plot);
        } else {
          H2DDraw(100+board,panel,graph, plot);
        }
      }
      break;
  }
  return 0;
}

int GetHvMonitor( void ) {
  int N470mid   = 4;
  int SYS403mid = 2;
  unsigned short buf[256]= {0};
  int retval;
  int ii;
//                 G0,A0,B0,C0,D0,H0,G1,A1,B1,C1,D1,H1,G2,A2,B2,C2,D2,H2,G3,A3,B3,C3,D3,H3
  int channels[]= {24, 0, 1, 2, 3, 0,25, 4, 5, 6, 7, 1,26, 8, 9,10,11, 2,27,12,13,14,15, 3}; //channel for  SYS403 , then for  N470
//  int channels[]= {0,1,2,3,4,0,5,6,7,8,9,1,10,11,12,13,14,2,15,16,17,18,19,3}; //channel for  SYS403 , then for  N470

  for (ii=0; ii<256; ii++) buf[ii]=0;
  monrec.time = (uint32_t) time(NULL);
  for (ii=0; ii<=23; ii++) {
    if ((ii+1)%6==0 && ii!=0) {
      buf[0]=(unsigned short) (channels[ii]<<8) | ReadOperationalParam;
      if (gCAEN_V288) {
        V288_Send(0,N470mid,1,buf);
        retval=V288_Receive(0,255, buf);
      }
      monrec.status[ii] = buf[0];   //status
      monrec.vmon[ii] = buf[1]*1000;//zapisano v mV
      monrec.imon[ii] = buf[2]*1000;//zapisano v nA
      monrec.vset[ii] = buf[3]*1000;//zapisano v mV
      monrec.iset[ii] = buf[4]*1000;//zapisano v nA
    } else {
      buf[0]=(unsigned short) (channels[ii]<<8) | ReadStatus;
      if (gCAEN_V288) {
        V288_Send(0,SYS403mid,1,buf);
        retval=V288_Receive(0,255,buf);
      }
      monrec.vmon[ii] = buf[1]*10;//zapisano v mV
      monrec.imon[ii] = buf[2]*10;//zapisano v nA
      monrec.status[ii] = buf[3]; //status

      if (!hvmonFirst) {
        buf[0]=(unsigned short) (channels[ii]<<8) | ReadParameters;
        if (gCAEN_V288) {
          V288_Send(0,SYS403mid,1,buf);
          retval=V288_Receive(0,255,buf);
        }
        vset[ii] = monrec.vset[ii] = buf[7]*10;//zapisano v mV
        iset[ii] = monrec.iset[ii] = buf[10]*10;//zapisano v nA
      }
      monrec.vset[ii] = vset[ii];//zapisano v mV
      monrec.iset[ii] = iset[ii];//zapisano v nA
    }
    //sa02Printf("%04x \t %d \t %d \t %d \t %d *\n",monrec.status[ii],monrec.vmon[ii],monrec.vset[ii],monrec.imon[ii],monrec.iset[ii]);
  }
  hvmonFirst=1;
  return 0;
}

int CVICALLBACK daq_scan(void *functionData) {
  int ich,count=0, xyval[4]= {0,0,0,0};
  //int c[4]= {0,0,0,0};
  //int e[4]= {0,0,0,0};
  uint32_t daqmode=1;
  uint32_t trglen;
  int nb,dsave,fcount=0,fmax=0,status,ch;
  unsigned int i;
  int hxy=100;
  //int h2=0;
  time_t t,told, tstart, t0;

  uint32_t board;
  uint32_t tpenb   =0;
  uint32_t response[2]= {0,0};
  char title[0xFF];
  char dfile[MAX_PATHNAME_LEN],dfile0[MAX_PATHNAME_LEN];
#define MAXSIZE 10000
  int maxsize = MAXSIZE;
  uint32_t sendswtrg=0;
  int ncount=0;
  uint32_t *rdata;
  float dx,dy,gapx,gapy,addgap;
  int ix,iy,nx,ny;
  int scanunitsx=0,scanunitsy=0;
  int x0,y0;
  const float fx= (float)(1000 / 0.3595); // 4M scaling factor steps/mm
  int daqexe;
  int writeevents=0;
  double fraction=0;
  uint32_t *data;
  char serial[4][0xFF];
  char hname[0xFF];
  time_t cas;

  uint16_t mask=GetConnectedFebMask();
  runrec.id = RUNREC_ID;
  runrec.len = sizeof(runrec);
  endrec.id = ENDREC_ID;
  endrec.len = sizeof(endrec);
  posrec.id = POSREC_ID;
  posrec.len = sizeof(posrec);
  evtrec.id = EVTREC_ID;
  evtrec.len = sizeof(evtrec);
  datrec.id = DATREC_ID;
  datrec.len = sizeof(datrec);
  monrec.id = MONREC_ID;
  monrec.len = sizeof(monrec);

  SetCtrlAttribute (p2h, P2_DAQ, ATTR_DIMMED, 1);
  ctrl_c=0;

  GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);

  GetCtrlVal (p1h, P1_SERIAL_1, serial[0]);
  GetCtrlVal (p1h, P1_SERIAL_2, serial[1]);
  GetCtrlVal (p1h, P1_SERIAL_3, serial[2]);
  GetCtrlVal (p1h, P1_SERIAL_4, serial[3]);

  sprintf(runrec.serial,"HAPD=%s,%s,%s,%s", serial[0],serial[1],serial[2],serial[3]);

  GetCtrlVal (p2h, P2_NEVE, &runrec.nev);
  GetCtrlVal (p2h, P2_PEDESTAL, &runrec.ped);
  GetCtrlVal (p2h, P2_NX, &runrec.nx);
  GetCtrlVal (p2h, P2_XSTEP, &runrec.dx);
  GetCtrlVal (p2h, P2_XMIN, &runrec.x0);
  GetCtrlVal (p2h, P2_NY, &runrec.ny);
  GetCtrlVal (p2h, P2_YSTEP, &runrec.dy);
  GetCtrlVal (p2h, P2_YMIN, &runrec.y0);
  GetCtrlVal ( p1h, P2_TPENB,&tpenb);
  GetCtrlVal ( p2h,P2_DAQEXE,&daqexe);
  GetCtrlVal(p2h,P2_FRACTION, &fraction);
  GetCtrlVal (p2h, P2_SCANUNITSX,  &scanunitsx);
  GetCtrlVal (p2h, P2_SCANUNITSY,  &scanunitsy);
  GetCtrlVal (p2h, P2_GAPX,  &gapx);
  GetCtrlVal (p2h, P2_GAPX,  &gapy);
  GetCtrlVal (p2h, P2_DX, &dx);
  GetCtrlVal (p2h, P2_DX, &dy);

  GetCtrlVal (p2h, P2_XC,  &x0);
  GetCtrlVal (p2h, P2_YC,  &y0);

  GetCtrlVal (p2h, P2_DIRECTION,  &runrec.direction);


  SetCtrlAttribute(p1h,P1_TRGHVMON,ATTR_ENABLED,1);
  hvmonFirst = 0;


  GetCtrlVal(p1h,P1_SENDSWTRIG,&sendswtrg);
  GetCtrlVal(p1h,P1_INTTRGLEN, &trglen);
  GetCtrlVal(p1h,P1_DAQMODE, &daqmode);




  runrec.fver = scanunitsx + scanunitsy*2 ;
  if (scanunitsx) {
    x0 = (int)(x0 - 5.5 * fx * dx  - gapx * fx * 0.5);
  }
  if (scanunitsy) {
    y0 = (int)(y0 - 5.5 * fx * dy  - gapy * fx * 0.5);
  }

  GetCtrlVal(p2h, P2_DSAVE, &dsave);
  if (dsave) {
    GetCtrlVal (p2h, P2_DFILE, dfile0);
    fcount=1;
    GetCtrlVal (p2h, P2_NEWF, &fmax);
    fmax*=1000000;//fmax in Mega Bytes
  }
  time (&t0);
  sa02Printf("---->daq_scan\n");
 
  if (dsave) {
    sprintf(dfile,"%s_file%02d.dat",dfile0,fcount);
    //gFp = fopen (dfile, "ab");
    gFp = fopen (dfile, "ab");
    if (gFp==NULL) sa02Printf("----> !!! gFp==NULL !!!\n");
    if (ferror (gFp)) sa02Printf("----> !!! ferror (gFp) after fopen !!!\n");    
    //time ((time_t *) &runrec.time);
    time (&cas);
    runrec.time = (uint32_t) cas;
    status = (int) fwrite (&runrec, 1, runrec.len, gFp);
    if(status != runrec.len) sa02Printf("----> !!! status != runrec.len (= %d) !!!\n", status);    
    if (ferror (gFp)) sa02Printf("----> !!! ferror (gFp) = %d !!!\n", ferror (gFp));  
   
  }


  for (i=0; i<4; i++) {
    sprintf(title,"HAPD%d Surface Scan single channels", i);
    sprintf(hname,"hxy%d", i);
    H3DInit(hxy+i,hname,title, runrec.nx,runrec.x0, runrec.dx,runrec.ny,runrec.y0, runrec.dy, 144, -0.5, 1);
    H3DSetTitleZ(hxy+i,"channel");
    sprintf(hname,"hxy%d_sum", i);
    H2DInit(hxy+i,hname,runrec.serial, runrec.nx,runrec.x0, runrec.dx,runrec.ny,runrec.y0, runrec.dy);
    if (scanunitsx) {
      H2DSetTitleX(hxy+i,"x (channels)");
      H3DSetTitleX(hxy+i,"x (channels)");
    } else {
      H2DSetTitleX(hxy+i,"x (stage steps)");
      H3DSetTitleX(hxy+i,"x (stage steps)");
    }
    if (scanunitsy) {
      H2DSetTitleY(hxy+i,"y (channels)");
      H3DSetTitleY(hxy+i,"y (channels)");
    } else {
      H2DSetTitleY(hxy+i,"y (stage steps)");
      H3DSetTitleY(hxy+i,"y (stage steps)");
    }

  }
  if (runrec.direction) {
    ny = runrec.ny;
    nx = runrec.nx;
  } else {
    ny = runrec.nx;
    nx = runrec.ny;
  }
  rdata = malloc(sizeof(uint32_t)*maxsize);

  time(&t);
  tstart=t;
  told=t-1;

  for (iy=0; iy<ny; iy++) {

    if (ctrl_c) break;

    if (runrec.direction) {
      posrec.iy = iy;
      posrec.yset=runrec.y0+posrec.iy*runrec.dy;
      if (scanunitsy) {
        if (posrec.yset>5) {
          addgap=gapy * fx;
        } else {
          addgap=0;
        }
        posrec.yset = (int32_t)(y0+dy *fx * posrec.yset + addgap);
      }
      if (gMIKRO_Y) {
        //sa02Printf("MIKRO_MoveTo (2, y);%d\n",y);
        MIKRO_MoveTo (MIKRO_Y, posrec.yset);
        sa02Printf("->MIKRO_MoveTo (2, y);%d\n",posrec.yset);
      }

      SetCtrlVal (p2h, P2_Y, posrec.yset);
      SetCtrlVal (p2h, P2_IY, posrec.iy);
    } else {
      posrec.ix = iy;
      posrec.xset=runrec.x0+posrec.ix*runrec.dx;
      if (scanunitsx) {
        if (posrec.xset>5) {
          addgap=gapx * fx;
        } else {
          addgap=0;
        }
        posrec.xset =  (int32_t)(x0+dx *fx * posrec.xset + addgap);
      }
      if (gMIKRO_Y) {
        //sa02Printf("MIKRO_MoveTo (2, y);%d\n",y);
        MIKRO_MoveTo (MIKRO_X, posrec.xset);
        sa02Printf("->MIKRO_MoveTo (1, x);%d\n",posrec.xset);
      }
      SetCtrlVal (p2h, P2_X, posrec.xset);
      SetCtrlVal (p2h, P2_IX, posrec.ix);
    }
    for (ix=0; ix<nx; ix++) {
      if (ctrl_c) break;

      if (runrec.direction) {
        posrec.ix = ix;
        posrec.xset=runrec.x0+posrec.ix*runrec.dx;
        if (scanunitsx) {
          if (posrec.xset>5) {
            addgap=gapx * fx;
          } else {
            addgap=0;
          }
          posrec.xset =  (int32_t)(x0+dx *fx * posrec.xset + addgap);
        }
        if (gMIKRO_X) {
          //sa02Printf("MIKRO_MoveTo (1, x);%d\n",posrec.x);
          MIKRO_MoveTo (MIKRO_X, posrec.xset);
          sa02Printf("->MIKRO_MoveTo (1, x);%d\n",posrec.xset);
        }
        SetCtrlVal (p2h, P2_X, posrec.xset);
        SetCtrlVal (p2h, P2_IX, posrec.ix);
      } else {
        posrec.iy = ix;
        posrec.yset=runrec.y0+posrec.iy*runrec.dy;
        if (scanunitsy) {
          if (posrec.yset>5) {
            addgap=gapy * fx;
          } else {
            addgap=0;
          }
          posrec.yset =  (int32_t)(y0+dy *fx * posrec.yset + addgap);
        }
        if (gMIKRO_X) {
          //sa02Printf("MIKRO_MoveTo (1, x);%d\n",posrec.y);
          MIKRO_MoveTo (MIKRO_Y, posrec.yset);
          sa02Printf("->MIKRO_MoveTo (2, y);%d\n",posrec.yset);
        }
        SetCtrlVal (p2h, P2_Y, posrec.yset);
        SetCtrlVal (p2h, P2_IY, posrec.iy);
      }
      if (scanunitsx && scanunitsy) {
        SetCMon(runrec.x0+posrec.ix*runrec.dx,runrec.y0+posrec.iy*runrec.dy);
      }
      if (dsave) {
        if (fmax && (ftell(gFp) > fmax)) {
          fcount+=1;
          sprintf(dfile,"%s_file%02d.dat",dfile0,fcount);
          fclose(gFp);
          gFp = fopen (dfile, "ab");
        }
        time (&cas);
        posrec.time = (uint32_t) cas;
        status = (int) fwrite (&posrec, 1, posrec.len, gFp);
      }

      Sa02DaqMode (daqmode);
      Sa02SelectTriggerWithMaskAndLength (sendswtrg, mask, trglen);

      for (board=0; board<4; board++) {
        if (mask & (1<<board)) {
          sa02Cmd( board, FEB_VTH1, runrec.ped, 0,0,1,response);
          Sa02TestPulseEnable(board,tpenb); // Enable/disable test pulse
        }
      }

      Sa02SetNeve(runrec.nev);

      evtrec.nev=1;


      sa02Reset();

      if (ctrl_c) break;

      if ( (count+2+dsize)  >= maxsize) {
        maxsize*=2;
        sa02Printf("Increasing data buffer to %d elements\n", maxsize);
        rdata=realloc(rdata ,sizeof(uint32_t)*maxsize);
      }

      data = &rdata[count+2];
      do {
        //int k;
        //uint32_t inputtriggers;
        if (sendswtrg == 1) Sa02SoftwareTrigger();
        nb  = sa02Read(mask, &rdata[count+2] );
        /*
        for (k=0; k<4; k++)  c[k] = Sa02GetCounter ( k ,&e[k]);
        for (k=0; k<4; k++)  sa02Printf(" CNTR%d=%d (ERR=%d)\t",k,c[k],e[k]);
        sa02Printf("\nsa02Read bytes =  %d mask=%d neve=%d (%d # %d)\n", nb, mask, runrec.nev, Sa02GetNeve( &inputtriggers ) , inputtriggers);
        */

      } while  ( nb==0 && !ctrl_c);



      if (sa02TimerOut || nb==0) sa02Printf("sa02TimerOut || nb==0\n");

      for (ich=0; ich<144*4; ich++) {
        int brd = ich/144;
        int xch   = 143 - ich%144;
        //sa02Printf("[%d] = %d \n", ich, data[ich]);
        if (data[ich]> xyval[brd])   xyval[brd] = data[ich];
        if (mask & (1<<brd)) {
          H3DFillBin(hxy+ brd, posrec.ix,posrec.iy,xch,data[ich]);
          H2DFillBin(hxy+ brd, posrec.ix,posrec.iy,data[ich]);
        }
      }
      sa02Printf("max couts = %d %d %d %d\n", xyval[0],xyval[1],xyval[2],xyval[3]);
      if (nb>=0) {
        count+=module_header(0x3,&rdata[count],nb/sizeof(uint32_t));
      }


      /*
      for (ich=0; ich<144; ich++) {

      //          uint32_t mask=0xFF;
      //          id=(35-ich/4);
      //          shft=(ich%4)*8;
        uint32_t mask=0xF;
            id=(17-ich/8)+board*18;
        shft=(ich%8)*4;
        if ( data[id]  & (mask <<shft)  )  {
          H3DFillBin(hxy, posrec.ix,posrec.iy,ich,1);
          H2DFillBin(hxy, posrec.ix,posrec.iy,1);
        }
      }
      */

      if (dsave) {
        if (Random(0,1)<fraction) {
          writeevents=1;
        } else {
          writeevents=0;
        }
        if (writeevents) {
          evtrec.id = EVTREC_ID;
          evtrec.len=count*sizeof(uint32_t)+ sizeof(evtrec);

          evtrec.time= (uint32_t) time(NULL);
          evtrec.nev=i;
          status = (int) fwrite( &evtrec,  1,  sizeof(evtrec),gFp);
          if (count) {
            status = (int) fwrite(rdata,1,count*sizeof(uint32_t),gFp);  //gzip
          }
        }
        if (hvmon) {
          time_t thv0,thv1;
          time(&thv0);
          GetHvMonitor();
          time(&thv1);
          status = (int) fwrite( &monrec,  1,  sizeof(monrec),gFp);
          sa02Printf("HvMonitor dt= %d s\n", thv1-thv0 );
          hvmon =0;
        }

        ncount++;
      }

      time(&t);
      if (t!=told ) {
        double done= (double) (posrec.ix+posrec.iy*runrec.nx)/(runrec.nx*runrec.ny);
        EstimatedFinish(p2h, P2_PROGRESS, P2_ETA, t0, done);
        GetCtrlVal(p2h,P2_CH, &ch);
        for (board=0; board<4; board++) {
          if (ch) {
            H3DDrawSliceXY(hxy+board,ch,p2h, p2graph[board], &p2plothandle[board]);
          } else {
            H2DDraw(hxy+board,p2h, p2graph[board], &p2plothandle[board]);
          }
        }
        ProcessSystemEvents ();
        SetCtrlVal(p2h,P2_CEVE, i);
        sa02Printf("%d events in %2.2f min (%d s) %s",ncount, (double)(t-tstart)/60.,t-tstart, ctime(&t));

      }
      told=t;



      if (ctrl_c) break;

      if (daqexe &0x1) {
        daq(NULL);
        sa02Cmd( board, FEB_VTH1, runrec.ped, 0,0,1,response);
      }
      if (daqexe &0x2) {
        V729_SetFilePointer(gFp);
        V729_daq(NULL);
      }

    }
  }

  if (gFp) {
    int ii=0, ison=0;
    for (ii=0; ii<4; ii++) {
      GetCtrlVal(p1h,hapd_onoff[ii], &ison);
      if (ison ) {
        H3DWrite2File(hxy+ii, gFp);
        H2DWrite2File(hxy+ii, gFp);
      }
    }
    fclose(gFp);
  }
  gFp=NULL;
  free(rdata);

  SetCtrlAttribute(p1h,P1_TRGHVMON,ATTR_ENABLED,0);

  return 0;
}

int CVICALLBACK Testing(void *functionData) {
  int i;
  int N470mid   = 4;
  int SYS403mid = 2;
  unsigned short buf[256]= {0};
  int odg;
  int channels[]= {0,1,2,3,4,0,5,6,7,8,9,1,10,11,12,13,14,2,15,16,17,18,19,3}; //channel for  SYS403 , then for  N470
  time_t t0,t1;
  time(&t0);

  hvmonFirst=0;

  for (i=0; i<256; i++) buf[i]=0;
  for (i=0; i<=23; i++) {
    if (((i+1)%6)==0&&i!=0) {
      buf[0]=(unsigned short) (channels[i]<<8) | ReadOperationalParam;
      if (gCAEN_V288) {
        V288_Send(0,N470mid,1,buf);
        odg=V288_Receive(0,255,buf);
      }
      monrec.status[i] = buf[0];   //status
      monrec.vmon[i] = buf[1]*1000;//zapisano v mV
      monrec.imon[i] = buf[2]*1000;//zapisano v nA
      monrec.vset[i] = buf[3]*1000;//zapisano v mV
      monrec.iset[i] = buf[4]*1000;//zapisano v nA
    } else {
      buf[0]=(unsigned short) (channels[i]<<8) | ReadStatus;
      if (gCAEN_V288) {
        V288_Send(0,SYS403mid,1,buf);
        odg=V288_Receive(0,255,buf);
      }
      monrec.vmon[i] = buf[1]*10;//zapisano v mV
      monrec.imon[i] = buf[2]*10;//zapisano v nA
      monrec.status[i] = buf[3]; //status
      if(!hvmonFirst) {
        buf[0]=(unsigned short) (channels[i]<<8) | ReadParameters;
        if (gCAEN_V288) {
          V288_Send(0,SYS403mid,1,buf);
          odg=V288_Receive(0,255,buf);
        }
        vset[i] = monrec.vset[i] = buf[7]*10;//zapisano v mV
        iset[i] = monrec.iset[i] = buf[10]*10;//zapisano v nA
      }
      monrec.vset[i] = vset[i];//zapisano v mV
      monrec.iset[i] = iset[i];//zapisano v nA
    }
    sa02Printf("%04x \t %.02f V \t %d V \t\t %.02f muA \t %d muA *\n",monrec.status[i],(float)monrec.vmon[i]/1000,monrec.vset[i]/1000,(float)monrec.imon[i]/1000,monrec.iset[i]/1000);
  }
  time (&t1);
  sa02Printf("Cas izvedbe:%g s.\n",difftime(t1,t0));

  return 0;
}

int CVICALLBACK set_dac(int OnOff) {
  int val;
  char name[MAX_PATHNAME_LEN];
  if (OnOff) {
    GetCtrlVal (p5h, P5_DAC_ON, &val);
    sprintf(name ,"%s -p %d",palaser, val);
    sa02Printf("%s\n", name);
    system(name);
    GetCtrlVal (p5h, P5_FREQUENCY_ON, &val);
    sprintf(name ,"%s -f %d",palaser, val);
    sa02Printf("%s\n", name);
    system(name);
  } else {
    GetCtrlVal (p5h, P5_DAC_OFF, &val);
    sprintf(name ,"%s -p %d",palaser, val);
    sa02Printf("%s\n", name);
    system(name);
    GetCtrlVal (p5h, P5_FREQUENCY_OFF, &val);
    sprintf(name ,"%s -f %d",palaser, val);
    sa02Printf("%s\n", name);
    system(name);
  }
  return 0;
}

int CVICALLBACK set_hv(int OnOff) {
  int N470mid = 4;
  int channel = 0;
  int ret;

  unsigned short buf[256];

  buf[0]=(unsigned short) (channel<<8) | TurnChanelOff;
  if (OnOff) buf[0]=(unsigned short) (channel<<8) | TurnChanelOn;
  V288_Send(0,N470mid,1,buf);
  ret=V288_Receive(0,255,buf);

  buf[0]=(unsigned short) (channel<<8) | ReadOperationalParam;
  V288_Send(0,N470mid,1,buf);
  ret=V288_Receive(0,255,buf);

  while (((buf[0]&0x20)&&(buf[0]&0x1))||(buf[0]&0x40)) {
    if((buf[0]&0x20)&&(buf[0]&0x20)) sa02Printf("Channel is ramping up \t Vmon: %d V \t Vset: %d \t status: 0x%x\n",buf[1],buf[3],buf[0]);
    else if(buf[0]&0x40) sa02Printf("Channel is ramping down \t Vmon: %d V \t Vset: %d \t status: 0x%x\n",buf[1],buf[3],buf[0]);
    else if(buf[0]&0x1E) {
      sa02Printf("status: 0x%x\n",buf[0]);
      return -1;
    } else  sa02Printf("status: 0x%x\n",buf[0]);
    Delay(2);
    buf[0]=(unsigned short) (channel<<8) | ReadOperationalParam;
    V288_Send(0,N470mid,1,buf);
    ret=V288_Receive(0,255,buf);
  }

  buf[0]=(unsigned short) (channel<<8) | ReadOperationalParam;
  V288_Send(0,N470mid,1,buf);
  ret=V288_Receive(0,255,buf);
  if(buf[0]&0x1) sa02Printf("HV is ON \t status: 0x%x\n",buf[0]);
  else sa02Printf("HV is OFF \t status: 0x%x\n",buf[0]);

  return 0;
}

int CVICALLBACK changeGlobalParam(int paramID, int paramValue) {
  int state;
  int cid = P3_GREG;
  int scanpar = paramID; //ID of the parameter you are about to change
  int nch = 4; //4 ASIC chips
  int spar = scanpar-10;
  Rect save_range,trange;
  const int maxrange[20]= {0,0,8,16,16,16,2,2,2,0,4,4,4,2,256,4,512};

  trange.top=0;
  trange.left=0;

  state = GetTableSelection (p3h, cid, &save_range);
  trange = MakeRect (1, spar, nch, 1);
  state = SetTableSelection (p3h, cid, trange);
  if ((trange.top!=0)&&(trange.left!=0)) {
    if (scanpar!=1) {
      state = FillTableCellRange (p3h, cid, MakeRect (1, spar, nch, 1), paramValue%maxrange[scanpar-1]);
      if (maxrange[scanpar-1] && paramValue/maxrange[scanpar-1]) {
        state = FillTableCellRange (p3h, cid, MakeRect (1, spar-1, nch, 1), paramValue/maxrange[scanpar-1]);
      }
    }
    UploadGlobalParameters (p3h,cid,EVENT_COMMIT,NULL,0,0);
  }
  state = SetTableSelection (p3h, cid, save_range);

  return 0;
}

int CreateParamFile(char *filename) {
  int n,i,row,asic,ch;
  unsigned short val;
  time_t t;
  char buf[MAX_PATHNAME_LEN];
  FILE   *fp;

  sprintf(buf,"..//parameters//%s",filename);
  fp = fopen(buf, "w");
  if (fp) {
    //--------------------------------------------------- Parameters header
    time(&t);
    fprintf(fp, "#Parameter exported from CVI %s\n",ctime(&t) );
    //--------------------------------------------------- FPGA parameters
    GetNumTextBoxLines(p3h, P3_FPGAPAR,&n);
    for (i=0; i<n; i++) {
      GetTextBoxLine(p3h, P3_FPGAPAR, i, buf);
      fprintf(fp, "%s\n",buf);
    }
    //--------------------------------------------------- Global parameters
    for (row=1; row<1+16; row++) {
      int irow = (row-1)%4;
      int iboard = (row-1)/4;
      fprintf(fp, "param_board %d\n",iboard);
      fprintf(fp, "## global parameter for chip %d\n",(row-1)%4);
      fprintf(fp, "param_global %d 0x1ffff\n",irow);
      GetTableCellVal (p3h, P3_GREG, MakePoint (1,row), &val);
      fprintf(fp, "phasecmps %d 0x%x\n",irow,val);
      GetTableCellVal (p3h, P3_GREG, MakePoint (2,row), &val);
      fprintf(fp, "gain %d 0x%x\n",irow,val);
      GetTableCellVal (p3h, P3_GREG, MakePoint (3,row), &val);
      fprintf(fp, "shapingtime %d 0x%x\n",irow,val);
      GetTableCellVal (p3h, P3_GREG, MakePoint (4,row), &val);
      fprintf(fp, "comparator %d 0x%x\n",irow,val);
      GetTableCellVal (p3h, P3_GREG, MakePoint (5,row), &val);
      fprintf(fp, "vrdrive %d 0x%x\n",irow,val);
      GetTableCellVal (p3h, P3_GREG, MakePoint (6,row), &val);
      fprintf(fp, "monitor %d 0x%x\n",irow,val);
      GetTableCellVal (p3h, P3_GREG, MakePoint (7,row), &val);
      fprintf(fp, "id %d 0x%x\n",irow,val);

      fprintf(fp, "load_global  %d\n\n\n",irow);
    }

    //--------------------------------------------------- Channel parameters
    for (i=0; i<144*4; i++) {
      int board = i/144;
      int j= i%144;
      asic=(j/36);
      ch=j%36;
      row=(i+1);
      if (i%36==0) {
        fprintf(fp, "# channel parameter for chip %d\n\n",asic);
      }

      fprintf(fp, "param_board %d\n",board);
      fprintf(fp, "param_ch       %d %d 0x0000\n",asic,ch);

      GetTableCellVal (p3h, P3_CREG, MakePoint (3,row), &val);
      fprintf(fp, "decaytime %d %d 0x%x\n",asic,ch,val);
      GetTableCellVal (p3h, P3_CREG, MakePoint (4,row), &val);
      fprintf(fp, "offset %d %d 0x%x\n",asic,ch,val);
      GetTableCellVal (p3h, P3_CREG, MakePoint (5,row), &val);
      fprintf(fp, "fineadj_unipol %d %d 0x%x\n",asic,ch,val);
      GetTableCellVal (p3h, P3_CREG, MakePoint (6,row), &val);
      fprintf(fp, "fineadj_diff %d %d 0x%x\n",asic,ch,val);
      GetTableCellVal (p3h, P3_CREG, MakePoint (7,row), &val);
      fprintf(fp, "tpenb %d %d 0x%x\n",asic,ch,val);
      GetTableCellVal (p3h, P3_CREG, MakePoint (8,row), &val);
      fprintf(fp, "kill %d %d 0x%x\n",asic,ch,val);
      fprintf(fp, "load_ch  %d %d\n\n\n",asic,ch);
    }
    fclose(fp);
  }
  sprintf(buf,"Created file '..//parameters//%s'\n",filename);
  sa02Printf("%s",buf);
  return 0;
}


int StepOne(void) {
  char defaulParamFile[0xFF] = "..\\parameters\\default.param";            // path to default.param file

  char HAPDnum[0xFF];
  int HAPDnumberOnOff;
  int ActiveHAPDNo=0;
  int HAPDid[]= {P1_SERIAL_1,P1_SERIAL_2,P1_SERIAL_3,P1_SERIAL_4};
  int HAPDstatus[]= {P1_ONOFF_1,P1_ONOFF_2,P1_ONOFF_3,P1_ONOFF_4};
  char HAPDnumber[4][0xFF];

  FILE *fp;
  int ndim=400;
  char line[ndim];
  time_t t;
  uint32_t mask = GetConnectedFebMask();
  int current_run=1;

  char cmdCommand[ndim];

  int numberOfIterations = 1;  //change this when everything will be working...

  /****** Check if Serial numbers are filled in ******/
  for (int i=0; i<4; i++) {
    GetCtrlVal(p1h, HAPDid[i], HAPDnum);
    GetCtrlVal(p1h, HAPDstatus[i], &HAPDnumberOnOff);
    if(!strcmp(HAPDnum, "noserial") && HAPDnumberOnOff) {
      printf("Fill in 'HAPD%d number' or disable 'HAPD%d'\n",i,i);
      return -1;
    }
    strcpy(HAPDnumber[i],HAPDnum);
    ActiveHAPDNo+=HAPDnumberOnOff;
  }
  if(!ActiveHAPDNo) {
    sa02Printf("Turn on at least 1 HAPD.");
    return -1;
  }
  sa02Printf("HAPD0 serial: %s \nHAPD1 serial: %s \nHAPD2 serial: %s \nHAPD3 serial: %s \n",HAPDnumber[0],HAPDnumber[1],HAPDnumber[2],HAPDnumber[3]);

  /****** Loads param file and uploads it to FEB ******/
  SetCtrlVal(p3h, P3_INPUTFILE, defaulParamFile);               // write path to P3_INPUTFILE
  SetParametersFromFile(defaulParamFile);                       // write default.param to P3_CREG table

  LoadParameters(p3h, P3_LOADPAR, EVENT_COMMIT, NULL, 0, 0);    // load parameters from defaul.param to FEB
  ProcessSystemEvents ();
  LoadParameters(p3h, P3_LOADPAR, EVENT_COMMIT, NULL, 0, 0);    // load parameters from defaul.param to FEB
  ProcessSystemEvents ();
  LoadParameters(p3h, P3_LOADPAR, EVENT_COMMIT, NULL, 0, 0);    // load parameters from defaul.param to FEB
  ProcessSystemEvents ();

  /****** MicroMini calibration ******/
  sa02Printf("Calibration *\n\n");
  SetHome(p2h, P2_HO,EVENT_COMMIT,NULL, 0, 0);
  SetCtrlVal(p2h,P2_XC,gCENTER_X);
  SetCtrlVal(p2h,P2_YC,gCENTER_Y);

  /****** Reads run number ******/
  fp = fopen ("CompleteScan_RunNumber.txt","r");
  if (fp) {
    if (fgets(line,ndim,fp)!= NULL) current_run = atoi(line)+1;
    fclose(fp);
    fp = NULL;
  }
  ProcessSystemEvents ();

  /****** Slow Control ******/
  sprintf(line,"%04d_SlowControl.xml",current_run);
  fp = fopen (line,"w");
  fprintf(fp,"<febtest>\n");
  time(&t);
  fprintf(fp,"<time>%s</time>\n", ctime(&t));

  for (int board=0; board<4; board++) {
    if (mask &(1<<board)) {
      for (int k=0; k<10; k++) {
        Delay(0.1);
        SlowControl(board,fp);
        ProcessSystemEvents ();
        if (ctrl_c) break;
      }
    }
    if (ctrl_c) break;
  }

  fprintf(fp,"</febtest>\n");
  fclose(fp);
  fp = NULL;

  /****** Treshold scan, Calibration & Channel Param Upload (iterations) ******/
  for(int j=0; j<=numberOfIterations; j++) {
    if(!j) {
      //Treshold settings
      SetCtrlVal(p1h,P1_DATA, 400);
      SetCtrlVal(p1h,P1_DSTEP, 1);
      SetCtrlVal(p1h,P1_NEVE, 300);
      SetCtrlVal(p1h,P1_TOREAD, 1000);
      //Calibration settings
      SetCtrlVal (p3h, P3_FITMODE, 2);
      SetCtrlVal (p3h, P3_TARGETOFFSET, 550.);
      SetCtrlVal (p3h, P3_TARGETRMS, 3.);
    }
    sprintf(line,"%04d_0_Treshold_%d.dat", current_run, j);
    SetCtrlVal(p1h,P1_OUTPUTFILE, line);
    if(j==numberOfIterations) continue; //when everything will be working remove this one and uncoment the next one

    daq(NULL);

    sprintf(cmdCommand,"cmd.exe /c ..\\sa02read -i .\\%s -o .\\%04d_0_Treshold_%d.root", line, current_run, j);
    LaunchExecutable(cmdCommand);


    ProcessSystemEvents ();

    //if(j==numberOfIterations) continue;

    sprintf(line,"Coarse fit parameters, iteration %d *\n\n", j);
    sa02Printf(line);

    FitH2DCoarse(p3h, P3_CALIBRATION_2,EVENT_COMMIT,NULL,0,0);
    ProcessSystemEvents ();

    sprintf(line,"%04d_Iteration_%d.param", current_run, j);
    CreateParamFile(line);

    sa02Printf("Loading channel parameters *\n\n");

    sprintf(defaulParamFile,"..\\parameters\\%s",line);
    SetCtrlVal(p3h, P3_INPUTFILE, defaulParamFile);                    // write path to P3_INPUTFILE
    SetParametersFromFile(defaulParamFile);                            // write default.param to P3_CREG table

    LoadParameters(p3h, P3_LOADPAR, EVENT_COMMIT, NULL, 0, 0);         // load parameters to FEB
    ProcessSystemEvents ();
    LoadParameters(p3h, P3_LOADPAR, EVENT_COMMIT, NULL, 0, 0);         // load parameters to FEB
    ProcessSystemEvents ();
    LoadParameters(p3h, P3_LOADPAR, EVENT_COMMIT, NULL, 0, 0);         // load parameters to FEB
    ProcessSystemEvents ();


  }

  /****** Increases run number in file for 1 ******/
  /*  fp = fopen ("CompleteScan_RunNumber.txt","w");
    fprintf(fp,"%d\n", current_run);
    fclose(fp);
  */


  return 0;
}

int ModuleTest(void) {
  int HAPDnumberOnOff;
  int ActiveHAPDNo=0;
  int HAPDid[]= {P1_SERIAL_1,P1_SERIAL_2,P1_SERIAL_3,P1_SERIAL_4};
  int HAPDstatus[]= {P1_ONOFF_1,P1_ONOFF_2,P1_ONOFF_3,P1_ONOFF_4};
  int ndim=400;
  int current_run=1;
  int ithr;
  double targetoffset;
  char line[ndim];
  char buf[0xFF];
  char cmdCommand[ndim];
  char HAPDnumber[4][0xFF];
  char HAPDnum[0xFF];

  FILE *fp;


  /****** Check if Serial numbers are filled in ******/
  for (int i=0; i<4; i++) {
    GetCtrlVal(p1h, HAPDid[i], HAPDnum);
    GetCtrlVal(p1h, HAPDstatus[i], &HAPDnumberOnOff);
    if(!strcmp(HAPDnum, "noserial") && HAPDnumberOnOff) {
      printf("Fill in 'HAPD%d number' or disable 'HAPD%d'\n",i,i);
      return -1;
    }
    strcpy(HAPDnumber[i],HAPDnum);
    ActiveHAPDNo+=HAPDnumberOnOff;
  }
  if(!ActiveHAPDNo) {
    sa02Printf("Turn on at least 1 HAPD.");
    return -1;
  }
  sa02Printf("HAPD0 serial: %s \nHAPD1 serial: %s \nHAPD2 serial: %s \nHAPD3 serial: %s \n",HAPDnumber[0],HAPDnumber[1],HAPDnumber[2],HAPDnumber[3]);

  /****** MicroMini calibration ******/
  sa02Printf("Calibration *\n\n");
  SetHome(p2h, P2_HO,EVENT_COMMIT,NULL, 0, 0);
  SetCtrlVal(p2h,P2_XC,gCENTER_X);
  SetCtrlVal(p2h,P2_YC,gCENTER_Y);

  /****** Reads run number ******/
  fp = fopen ("CompleteScan_RunNumber.txt","r");
  if (fp) {
    if (fgets(line,ndim,fp)!= NULL) current_run = atoi(line)+1;
    fclose(fp);
    fp = NULL;
  }
  ProcessSystemEvents ();

  fp = fopen ("CompleteScan_RunNumber.txt","w");
  fprintf(fp,"%d\n", current_run);
  fclose(fp);

  GetCtrlVal (p3h, P3_TARGETOFFSET, &targetoffset);   // Treshold
  ithr=(int)targetoffset+20;
  /****** Treshold + Waveform scan over 144x center ******/
  SetCtrlVal (p2h, P2_ZSET, 0);
  SetCtrlVal (p2h, P2_XC, (uint32_t)(gCENTER_KX*0+gCENTER_X));
  SetCtrlVal (p2h, P2_YC, (uint32_t)(gCENTER_KY*0+gCENTER_Y));
  Zset(p2h,P2_ZSET,EVENT_COMMIT,NULL,0,0);
  // Panel 1 setting
  SetCtrlVal (p1h, P1_TPENB, 0);                                    // disable test pulz
  SetCtrlVal (p1h, P1_SENDSWTRIG, 2);                               // set external trigger
  SendTriggerTypeCB (p1h, P1_SENDSWTRIG, EVENT_COMMIT,NULL,0,0);    // commit external trigger

  SetCtrlVal(p1h,P1_DATA, 500);    // Inital value
  SetCtrlVal(p1h,P1_DSTEP, 2);     // Step size
  SetCtrlVal(p1h,P1_NEVE, 101);    // Number of steps
  SetCtrlVal(p1h,P1_TOREAD, 1000);  // Number of events

  // Panel 4 setting
  //SetCtrlVal(p4h,P4_FRACTION, 0.);  // Fraction of waveforms to store (If you want to create charge accumulation graphs with sa02read set to 1.)
  SetCtrlVal(p4h,P4_NEVE, 4000);  // Number of events

  // Panel 2 settings
  SetCtrlVal (p2h, P2_SCANUNITSX, 1);   // Only over the channel centers   (1 Ch, 0 Step)
  SetCtrlVal (p2h, P2_NX, 12);          // Noumber of steps = 12
  SetCtrlVal (p2h, P2_XSTEP, 1);        // Step size = 1
  SetCtrlVal (p2h, P2_XMIN, 0);         // Start position = 0
  SetCtrlVal (p2h, P2_SCANUNITSY, 1);   // Only over the channel centers   (1 Ch, 0 Step)
  SetCtrlVal (p2h, P2_NY, 12);          // Noumber of steps = 12
  SetCtrlVal (p2h, P2_YSTEP, 1);        // Step size = 1
  SetCtrlVal (p2h, P2_YMIN, 0);         // Start position = 0
  SetCtrlVal (p2h, P2_DIRECTION, 1);    // Set Y then scan X = 1 (0 = Set X then scan X)

  SetCtrlVal (p2h, P2_NEVE, 100);        // Number of events for position scan (keep low so the scan is faster ... this is not the point of interest for this scan)
  SetCtrlVal (p2h, P2_PEDESTAL, ithr);   // Treshold

  SetCtrlVal (p2h, P2_DAQEXE, 3);       // Execute at each position: SA02 scan and CAEN V729a

  sprintf(buf,"%04d_1_Treshold_Waveform",current_run);
  sprintf(line,"..\\modules\\%s",buf);
  SetCtrlVal (p2h, P2_DFILE, line);


  daq_scan(NULL);

  sprintf(cmdCommand,"cmd.exe /c mkdir ..\\modules\\%04d & ..\\sa02read -i %s_file01.dat -o ..\\modules\\%04d\\%s.root",
          current_run, line, current_run, buf);
  LaunchExecutable(cmdCommand);


 
  /****** 2D v X ******/
  // Panel 2 settings
  SetCtrlVal (p2h, P2_SCANUNITSX, 0);   // Continuous scan over X  (1 Ch, 0 Step)
  SetCtrlVal (p2h, P2_NX, 380/2);         // Noumber of steps = 380
  SetCtrlVal (p2h, P2_XSTEP, 2*500);      // Step size = 500
  SetCtrlVal (p2h, P2_XMIN, 83000);     // Start position = 8500
  SetCtrlVal (p2h, P2_SCANUNITSY, 1);   // Only over the channel centers   (1 Ch, 0 Step)
  SetCtrlVal (p2h, P2_NY, 12);          // Noumber of steps = 12
  SetCtrlVal (p2h, P2_YSTEP, 1);        // Step size = 1
  SetCtrlVal (p2h, P2_YMIN, 0);         // Start position = 0
  SetCtrlVal (p2h, P2_DIRECTION, 1);    // Set Y then scan X = 1

  SetCtrlVal (p2h, P2_NEVE, 1000);       // Number of events for position scan
  SetCtrlVal (p2h, P2_PEDESTAL, ithr);   // Treshold

  SetCtrlVal (p2h, P2_DAQEXE, 0);       // Execute at each position: nothing

  sprintf(buf,"%04d_2_2DX",current_run);
  sprintf(line,"..\\modules\\%s", buf);
  SetCtrlVal (p2h, P2_DFILE, line);


  daq_scan(NULL);

  sprintf(cmdCommand,"cmd.exe /c mkdir ..\\modules\\%04d & ..\\sa02read -i %s_file01.dat -o ..\\modules\\%04d\\%s.root ", current_run, line, current_run, buf);
  LaunchExecutable(cmdCommand);


  /****** 2D v Y ******/
  // Panel 2 settings
  SetCtrlVal (p2h, P2_SCANUNITSX, 1);   // Only over the channel centers   (1 Ch, 0 Step)
  SetCtrlVal (p2h, P2_NX, 12);          // Noumber of steps = 12
  SetCtrlVal (p2h, P2_XSTEP, 1);        // Step size = 1
  SetCtrlVal (p2h, P2_XMIN, 0);         // Start position = 0
  SetCtrlVal (p2h, P2_SCANUNITSY, 0);   // Continuous scan over Y  (1 Ch, 0 Step)
  SetCtrlVal (p2h, P2_NY, 380/2);          // Noumber of steps = 380
  SetCtrlVal (p2h, P2_YSTEP, 2*500);        // Step size = 500
  SetCtrlVal (p2h, P2_YMIN, 75000);         // Start position = 7500
  SetCtrlVal (p2h, P2_DIRECTION, 0);    // Set X then scan Y = 0

  SetCtrlVal (p2h, P2_NEVE, 1000);        // Number of events for position scan
  SetCtrlVal (p2h, P2_PEDESTAL, ithr);   // Treshold

  SetCtrlVal (p2h, P2_DAQEXE, 0);       // Execute at each position: nothing

  sprintf(buf,"%04d_3_2DY",current_run);
  sprintf(line,"..\\modules\\%s", buf);
  SetCtrlVal (p2h, P2_DFILE, line);


  daq_scan(NULL);

  sprintf(cmdCommand,"cmd.exe /c mkdir ..\\modules\\%04d & ..\\sa02read -i %s_file01.dat -o ..\\modules\\%04d\\%s.root ", current_run, line, current_run, buf);
  system(cmdCommand); // wait here to finish to proceed to next step    
 
  sprintf(cmdCommand,"cmd.exe /c ..\\thisroot.bat & cd analysis & root script.c(%d)",current_run);
  LaunchExecutable(cmdCommand);

  SetCtrlVal (p2h, P2_ZSET, 300000);
  SetCtrlVal (p2h, P2_XC, (uint32_t)(gCENTER_KX*0+gCENTER_X));
  SetCtrlVal (p2h, P2_YC, (uint32_t)(gCENTER_KY*0+gCENTER_Y));
  Zset(p2h,P2_ZSET,EVENT_COMMIT,NULL,0,0);

  return 0;
}

int StepThree(void) {
  //char cmdCommand[0xFF];
  //char line[0xFF];
  //char buf[0xFF];
  //int current_run = 11;

  return 0;
}


// map uir controls ....
#define MAX_UIRCTRLMAP_SIZE 1000
typedef struct {
  char name[32];
  int id;
  int handle;
} UirCtrlMap;
UirCtrlMap gUirCtrlMap[MAX_UIRCTRLMAP_SIZE];
int gNUirCtrlMap=0;

int GetControlID(const char *ctrl) {
  for (int i=0; i<gNUirCtrlMap; i++) {
    if (strcmp(ctrl,gUirCtrlMap[i].name)==0) return ctrl,gUirCtrlMap[i].id;
  }
  return -1;
}
int GetPanelHandle(const char *ctrl) {

  if ( strstr(ctrl, "P1_")!= NULL ) return p1h;
  if ( strstr(ctrl, "P2_")!= NULL ) return p2h;
  if ( strstr(ctrl, "P3_")!= NULL ) return p3h;
  if ( strstr(ctrl, "P4_")!= NULL ) return p4h;
  if ( strstr(ctrl, "P5_")!= NULL ) return p5h;

  return -1;
}

int LoadUirHeader(const char *fname) {
  int ndim=MAX_PATHNAME_LEN;
  char line[MAX_PATHNAME_LEN];
  char cmd[MAX_PATHNAME_LEN];
  FILE *fp = NULL;
  ssize_t size;
  int n0= gNUirCtrlMap;
  if ( GetFileInfo(fname,&size) ) fp = fopen(fname,"r");
  if (!fp) {
    sa02Printf("Error! Cannot open header file %s\n",fname);
    return -1;
  }

  while (fgets(line,ndim,fp)!=NULL ) {
    char ctrl[32];
    int ctrlid;
    int nb = sscanf(line,"%s%s%d",cmd, ctrl, &ctrlid);
    if (strstr(cmd,"#define")!=NULL && nb==3) {
      strcpy(gUirCtrlMap[gNUirCtrlMap].name, ctrl );
      if (gNUirCtrlMap<MAX_UIRCTRLMAP_SIZE) {
        gUirCtrlMap[gNUirCtrlMap].id     = ctrlid;
        gUirCtrlMap[gNUirCtrlMap].handle = GetPanelHandle(ctrl);
        gNUirCtrlMap++;
      } else {
        sa02Printf("ERROR: Increase gNUirCtrlMap\n");
      }
    }
  }
  fclose(fp);
  sa02Printf("Number of Controls loaded from File %s = %d \n", fname,gNUirCtrlMap-n0);
  return 0;
}


char *str_replace(const char *str, const char *old, const char *new) {

  /* Adjust each of the below values to suit your needs. */

  /* Increment positions cache size initially by this number. */
  size_t cache_sz_inc = 16;
  /* Thereafter, each time capacity needs to be increased,
   * multiply the increment by this factor. */

  const size_t cache_sz_inc_factor = 3;
  /* But never increment capacity by more than this number. */
  const size_t cache_sz_inc_max = 1048576;

  char *pret, *ret = NULL;
  const char *pstr2, *pstr = str;
  size_t i, count = 0;
  ptrdiff_t *pos_cache = NULL;
  size_t cache_sz = 0;
  size_t cpylen, orglen, retlen, newlen =0, oldlen = strlen(old);

  /* Find all matches and cache their positions. */
  while ((pstr2 = strstr(pstr, old)) != NULL) {
    count++;

    /* Increase the cache size when necessary. */
    if (cache_sz < count) {
      cache_sz += cache_sz_inc;
      pos_cache = realloc(pos_cache, sizeof(*pos_cache) * cache_sz);
      if (pos_cache == NULL) {
        goto end_repl_str;
      }
      cache_sz_inc *= cache_sz_inc_factor;
      if (cache_sz_inc > cache_sz_inc_max) {
        cache_sz_inc = cache_sz_inc_max;
      }
    }

    pos_cache[count-1] = pstr2 - str;
    pstr = pstr2 + oldlen;
  }

  orglen = pstr - str + strlen(pstr);

  /* Allocate memory for the post-replacement string. */
  if (count > 0) {
    newlen = strlen(new);
    retlen = orglen + (newlen - oldlen) * count;
  } else  retlen = orglen;
  ret = malloc(retlen + 1);
  if (ret == NULL) {
    goto end_repl_str;
  }

  if (count == 0) {
    /* If no matches, then just duplicate the string. */
    strcpy(ret, str);
  } else {
    /* Otherwise, duplicate the string whilst performing
     * the replacements using the position cache. */

    pret = ret;
    memcpy(pret, str, pos_cache[0]);
    pret += pos_cache[0];
    for (i = 0; i < count; i++) {
      memcpy(pret, new, newlen);
      pret += newlen;
      pstr = str + pos_cache[i] + oldlen;
      cpylen = (i == count-1 ? orglen : (size_t)pos_cache[i+1]) - pos_cache[i] - oldlen;
      memcpy(pret, pstr, cpylen);
      pret += cpylen;
    }
    ret[retlen] = '\0';
  }

end_repl_str:
  /* Free the cache and return the post-replacement string,
   * which will be NULL in the event of an error. */

  free(pos_cache);
  return ret;
}


int CVICALLBACK run_script(void *functionData) {
  FILE *fp = NULL;
  FILE *fpout =NULL;

 
  char *line;
  char buf[MAX_PATHNAME_LEN];
  int status;
  char type[MAX_PATHNAME_LEN];
  char param[MAX_PATHNAME_LEN];
  char paramValue[MAX_PATHNAME_LEN];
  int scx,nx,xstep,xmin,scy,ny,ystep,ymin,direction,nevents,tresh;
  char test[256];
  char outputFileSuffix[128];
  char outputFile[MAX_PATHNAME_LEN];
  char HAPDserialNumber[128];
  ssize_t size;
  int data[2];
  int runno=0;

  char scriptname[MAX_PATHNAME_LEN];
  GetCtrlVal(p1h,P1_SCRIPTNAME, scriptname);


  if ( GetFileInfo(scriptname,&size) ) fp = fopen(scriptname,"r");
  if (!fp) {
    sa02Printf("Error! Cannot open script file %s\n",scriptname);
    return -1;
  }
  while (fgets(buf,MAX_PATHNAME_LEN,fp)!=NULL ) {
   
    if (buf[0]!='#' && strlen(buf)>2) {
      if (strstr(buf, "%RUN%")!=NULL) {
          char srun[16];
          sprintf(srun,"%04d",runno);
          line = str_replace(buf,"%RUN%", srun);
      } else {
          line = buf;
      }
      sa02Printf("#[%d] %s",strlen(buf),buf);  
     
      sscanf(line,"%s",type);
     
      if (strstr(type,"SetCtrlVal")!=NULL) {
        int pID;  
        int rID;
        int datatype;
        sscanf(line,"%*s%s%s",param,paramValue);
   
        pID= GetPanelHandle(param);  
        rID= GetControlID(param);
        if (rID>0 && pID>0) {
          GetCtrlAttribute (pID, rID, ATTR_DATA_TYPE, &datatype);
       
          switch (datatype){
            case VAL_INTEGER: SetCtrlVal (pID, rID, atoi(paramValue)); break;
            case VAL_UNSIGNED_INTEGER: SetCtrlVal (pID, rID, strtoul(paramValue,NULL,0)); break;
            case VAL_SHORT_INTEGER: SetCtrlVal (pID, rID, atoi(paramValue)); break;
            case VAL_UNSIGNED_SHORT_INTEGER: SetCtrlVal (pID, rID, strtoul(paramValue,NULL,0)); break;
            case VAL_DOUBLE : SetCtrlVal (pID, rID, atof(paramValue)); break;
            case VAL_STRING : SetCtrlVal (pID, rID, paramValue      ); break;
            default: sa02Printf("[%s] ATTR_DATA_TYPE of the %s not supported datatype %d p4h=%d\n\n", type, param, datatype, p4h);
          }
          //sa02Printf("[%s] SetCtrlVal %s %s panel=%d control=%d\n",type,param, paramValue,pID,rID);  
        } else {
           sa02Printf("[%s] Invalid Ctrl %s %s panel=%d control=%d\n",type,param, paramValue,pID,rID);
        }  
       
      } else if (strstr(type,"2D")!=NULL) {
        sscanf(line,"%*s%d%d%d%d%d%d%d%d%d%d%d%s",&scx,&nx,&xstep,&xmin,&scy,&ny,&ystep,&ymin,&direction,&nevents,&tresh,outputFileSuffix);
        sprintf(test,"%d %d %d %d %d %d %d %d %d %d %d %s *\n",scx,nx,xstep,xmin,scy,ny,ystep,ymin,direction,nevents,tresh,outputFileSuffix);
        sa02Printf("%s *\n\n",test);
        SetCtrlVal (p2h, P2_SCANUNITSX, scx);
        SetCtrlVal (p2h, P2_NX, nx);
        SetCtrlVal (p2h, P2_XSTEP, xstep);
        SetCtrlVal (p2h, P2_XMIN, xmin);
        SetCtrlVal (p2h, P2_SCANUNITSY, scy);
        SetCtrlVal (p2h, P2_NY, ny);
        SetCtrlVal (p2h, P2_YSTEP, ystep);
        SetCtrlVal (p2h, P2_YMIN, ymin);
        SetCtrlVal (p2h, P2_DIRECTION, direction);

        SetCtrlVal (p2h, P2_NEVE, nevents);
        SetCtrlVal (p2h, P2_PEDESTAL, tresh);

        GetCtrlVal (p1h, P1_SERIAL_1, HAPDserialNumber);
        sprintf(outputFile,"%s_%s", HAPDserialNumber, outputFileSuffix);
        SetCtrlVal (p2h, P2_DFILE, outputFile);


        daq_scan(NULL);

      } else if (strstr(type,"Delay")!=NULL) {
        int idelay=0;
        sscanf(line,"%*s%s",paramValue);
        for (idelay=atoi(paramValue) ; idelay>0; idelay--) {
          Delay(1);
          SetCtrlVal(p1h, P1_DELAY, idelay);
          ProcessSystemEvents();
          if (ctrl_c) break;
        }
      }  else if (strstr(type,"ThresholdLinearity")!=NULL) {
        char *fname;
        uint16_t mask = GetConnectedFebMask();

        sscanf(line,"%*s%s",paramValue);
        fname = paramValue;
       

        ThresholdLinearityCB (p1h, P1_THRVSADC, EVENT_COMMIT, NULL, 0, 0 );
        fpout = fopen(fname,"ab");
        if(fpout) {
          for (int board=0; board<4; board++) if ( mask &(1<<board))  H1DWrite2File(board,fpout);
          fclose(fpout);
        }

      }  else if (strstr(type,"LaunchExecutable")!=NULL) {
        int index = FindPattern (line, 0, -1, "LaunchExecutable", 0, 0) + 17;
       
        char *cmd = &line[index];
        sa02Printf("cmd %d=%s\n",index, cmd);
        if (strlen(cmd)>0) LaunchExecutable( cmd );
      }  else if (strstr(type,"CAEN_V729")!=NULL) {  
        char *fname;
        //FILE *fpmon=NULL;
       
        sscanf(line,"%*s%s",paramValue);
        fname=paramValue;
       
        fpout = fopen(fname,"ab");
        if (fpout) {
         
          V729_SetFilePointer(fpout);
          V729_daq(NULL);
          fclose(fpout);
        }
      } else if (strstr(type,"HvMonitor")!=NULL) {
        int nrepetitions;
        int delaytime;
        int k=0;
        FILE *fpmon=NULL;
        sscanf(line,"%*s%s%d%d",paramValue, &delaytime, &nrepetitions );
        fpmon = fopen(paramValue,"ab");
       
        if ( fpmon ) {
          hvmonFirst = 0;
          for (k=0; k<nrepetitions; k++) {
            double thv0,thv1;
            thv0 = Timer();
            GetHvMonitor();
            for (int board=0;board<4;board++){
              double sdata[12];
              for (int k=0;k<6;k++){
                 sdata[k] = monrec.imon[k+4*board];
                 sdata[k+6] = 0;
              }
             
              SetAxisScalingMode (p1h, chart_control[board], VAL_LEFT_YAXIS, VAL_AUTOSCALE, 0, 1);
              SetAxisScalingMode (p1h, chart_control[board], VAL_RIGHT_YAXIS, VAL_AUTOSCALE, 0, 1);
              PlotStripChart (p1h, chart_control[board], sdata, 12, 0, 0, VAL_DOUBLE);
            }  
            monrec.id = MONREC_ID;
            monrec.len = sizeof(monrec);
            thv1=Timer();
            status = (int) fwrite( &monrec,  1,  sizeof(monrec),fpmon);
            sa02Printf("[%04d] HvMonitor dt= %f s status=%d\n", runno, thv1-thv0, status );
            for (int idelay=delaytime ; idelay>0; idelay--) {
              Delay(1);
              SetCtrlVal(p1h, P1_DELAY, idelay);
              ProcessSystemEvents();
              if (ctrl_c) break;
            }
            if (ctrl_c) break;
          }
          fclose(fpmon);
        } else {
          sa02Printf("%s cannot open file %s\n",param, paramValue );
        }

      } else if (strstr(type,"GetRunNumberFromFile")!=NULL) {
        sscanf(line,"%*s%s",paramValue);
        runno = GetRunNumberFromFile(paramValue);
        SetCtrlVal(p1h, P1_RUNNO, runno);
        sa02Printf("%s %s run=>%d\n",type, paramValue, runno );
      } else if (strstr(type,"IncreaseNumberInFile")!=NULL) {
        sscanf(line,"%*s%s",paramValue);
        runno = IncreaseRunNumberInFile(paramValue);
        sa02Printf("%s %s run=>%d\n",type, paramValue, runno );
        SetCtrlVal(p1h, P1_RUNNO, runno);
      } else if (strstr(type,"LoadParameters")!=NULL) {
        LoadParameters(p3h, P3_LOADPAR,EVENT_COMMIT,NULL,0,0);
        sa02Printf("Loading parameters *\n\n");
      } else if (strstr(type,"QueueUserEvent")!=NULL || strstr(type,"ProcessUserEvent")!=NULL) {
        char scontrol[0xFF];
        int panelHandle=0;
        int controlID;
        sscanf(line,"%*s%s",scontrol);
        panelHandle = GetPanelHandle(scontrol);
        controlID   = GetControlID(scontrol);
        sa02Printf("UserEvent %s panelHandle %d controlID %d\n",scontrol, panelHandle, controlID );
        if (panelHandle>=0 && controlID >=0 ) {
          if (strstr(type,"ProcessUserEvent")!=NULL) {
            ProcessUserEvent(panelHandle, controlID,0);
          } else {
            data[1] = controlID;
            data[0] = panelHandle;
       
            status = CmtWriteTSQData (pTSQ, data, 1, TSQ_INFINITE_TIMEOUT, NULL);
          }  
        }

      }  else if (strstr(type,"SetPositionAndMux")!=NULL) {
        int ix,iy;
        sscanf(line,"%*s%d%d",&ix,&iy);
        sa02Printf("SetPositionAndMux %d %d \n", ix,iy);

        SetCtrlVal (p2h, P2_CHX,  ix);
        SetCtrlVal (p2h, P2_CHY,  iy);
        SetPositionAndMux(  p2h,0, EVENT_COMMIT , NULL,0,0);

      }  else if (strstr(type,"Treshold")!=NULL) {
        sscanf(line,"%*s%s",outputFileSuffix);

        GetCtrlVal (p1h, P1_SERIAL_1, HAPDserialNumber);
        sprintf(outputFile,"%s_%s.dat", HAPDserialNumber, outputFileSuffix);
        SetCtrlVal (p1h, P1_OUTPUTFILE, outputFile);

        sprintf(test,"Treshold scan to file %s",outputFile);
        sa02Printf("%s *\n\n", test);

        daq(NULL);
      } else if (strstr(type,"Fitanje")!=NULL) {
        FitH2DCoarse(p3h, P3_CALIBRATION_2,EVENT_COMMIT,NULL,0,0);
        sa02Printf("Coarse fit parameters *\n\n");
      } else if (strstr(type,"UploadChannelParameters")!=NULL) {
        UploadChannelParameters(p3h, P3_CPARLOAD,EVENT_COMMIT,NULL,0,0);
        sa02Printf("Loading channel parameters *\n\n");
      } else if (strstr(type,"KalibracijaMizice")!=NULL) {
        SetHome(p2h, P2_HO,EVENT_COMMIT,NULL,0,0);
        SetCtrlVal(p2h,P2_XC,gCENTER_X);
        SetCtrlVal(p2h,P2_YC,gCENTER_Y);
        sa02Printf("Calibration *\n\n");
      } else if (strstr(type,"LaserHVOn")!=NULL) {
        set_dac(1);
        sa02Printf("Low intensity laser *\n\n");
      } else if (strstr(type,"LaserHVOff")!=NULL) {
        set_dac(0);
        sa02Printf("High intensity laser *\n\n");
      } else if (strstr(type,"Gain")!=NULL) {
        sscanf(line,"%*s%d",paramValue);
        sprintf(test,"    %d", atoi(paramValue));
        sa02Printf("%s *\n\n", test);
        changeGlobalParam(12, atoi(paramValue)); // Global parameter Gain has ID 12
      } else if (strstr(type,"ShapingTime")!=NULL) {
        sscanf(line,"%*s%s",paramValue);
        sprintf(test,"    %d", atoi(paramValue));
        sa02Printf("%s *\n\n", test);
        changeGlobalParam(13, atoi(paramValue)); // Global parameter ShapingTime has ID 13
      }
    }
    if (ctrl_c) {
      break;
    }
  }
  fclose(fp);
  return 0;
}

/*
int CVICALLBACK StartPositionScan (int panel, int control, int event,
    void *callbackData, int eventData1, int eventData2)
{
  switch (event)
    {
    case EVENT_COMMIT:
        daq_scan(NULL);
      break;
    }
  return 0;
}
*/


int CVICALLBACK SetHome (int panel, int control, int event,
                         void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      SetWaitCursor (1);
      if (gMIKRO_X)  MIKRO_ReferenceMove (MIKRO_X);
      if (gMIKRO_Y)  MIKRO_ReferenceMove (MIKRO_Y);
      if (gMIKRO_Z)  MIKRO_ReferenceMove (MIKRO_Z);
      SetWaitCursor (0);
      break;
  }
  return 0;
}

int CVICALLBACK CBTimer (int panel, int control, int event,
                         void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_TIMER_TICK:
//      ProcessSystemEvents();
      break;
  }
  return 0;
}

int CVICALLBACK GetPosition (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  int xpos=0,ypos=0,zpos=0;
  switch (event) {

    case EVENT_COMMIT:

      if (gMIKRO_X) {
        MIKRO_GetPosition(MIKRO_X,&xpos);
        Delay(0.01);
        SetCtrlVal (p2h, P2_X, xpos);
      }

      if (gMIKRO_Y) {
        MIKRO_GetPosition(MIKRO_Y,&ypos);
        Delay(0.01);
        SetCtrlVal (p2h, P2_Y, ypos);
      }
      if (gMIKRO_X) {
        MIKRO_GetPosition(MIKRO_Z,&zpos);
        Delay(0.01);
        SetCtrlVal (p2h, P2_Z, zpos);
        sa02Printf("x=%d y=%d z=%d\n",xpos,ypos,zpos);
      }


      break;
  }
  return 0;
}

int CVICALLBACK ReRead (int panel, int control, int event,
                        void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT: {
      int status;
      char dfile[MAX_PATHNAME_LEN];
      FILE *fp;

      status = FileSelectPopup ("", "*.dat", ".dat",
                                "Izberi datoteko s podatki",
                                VAL_LOAD_BUTTON, 0, 0, 1, 0, dfile);
      if (status==1) {
        fp = fopen (dfile, "rb");
        status = (int) fread (&runrec, 1, sizeof(runrec), fp);
        fclose(fp);
        if (runrec.id==RUNREC_ID) {
          SetCtrlVal (p2h, P2_NX, runrec.nx);
          SetCtrlVal (p2h, P2_XSTEP, runrec.dx);
          SetCtrlVal (p2h, P2_XMIN, runrec.x0);
          SetCtrlVal (p2h, P2_NY, runrec.ny);
          SetCtrlVal (p2h, P2_YSTEP, runrec.dy);
          SetCtrlVal (p2h, P2_YMIN, runrec.y0);
          SetCtrlVal (p2h, P2_NEVE, runrec.nev);
          SetCtrlVal (p2h, P2_SCANUNITSX, runrec.fver%2);
          SetCtrlVal (p2h, P2_SCANUNITSY, runrec.fver/2);
          SetCtrlVal (p2h, P2_DIRECTION, runrec.direction);
        }
      }
    }
    break;
  }
  return 0;
}

int CVICALLBACK Zset (int panel, int control, int event,
                      void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT: {
      int zpos;
      GetCtrlVal (p2h, P2_ZSET, &zpos);
      if (gMIKRO_Z) MIKRO_MoveTo (MIKRO_Z, zpos);

    }
    break;
  }
  return 0;
}

int CVICALLBACK HidePanelCB (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      HidePanel (panel);
      break;
  }
  return 0;
}

int GetChannelPosition(int chip, int ch, int *chx, int *chy) {

  int i=0;

  for (i=0; i<144; i++) {

    if (eid2hapdxy[i].chip == chip && eid2hapdxy[i].ch == ch) {
      *chx   = eid2hapdxy[i].chx;
      *chy   = eid2hapdxy[i].chy  ;
      return 0;
    }
  }
  return -1;

}

int LoadElectronicMap(const char *fname) {

  FILE *fp = fopen(fname,"r");
  int chip,ch,chx,chy,chxr,chyr;
  int nread=0;
  int ndim=400;
  char line[400];
  int  nr=0;

  while (fgets(line,ndim,fp)!=NULL) {

    nr = sscanf(line,"%d%d%d%d",&chip,&ch,&chxr,&chyr);
    if (nr) {
// Orientation of HAPD in xy system - position of APD A:LR,UR,UL,LL and view:B,F
//LRB
//      chx=11-chxr;
//      chy=11-chyr;
//URB
      chx=chyr;
      chy=11-chxr;
//ULB
//      chx=chxr;
//      chy=chyr;
//LLB
//      chx=11-chyr;
//      chy=chxr;
      eid2hapdxy[nread].chip = chip;
      eid2hapdxy[nread].ch   = ch  ;
      eid2hapdxy[nread].chx  = chx ;
      eid2hapdxy[nread].chy  = chy ;
    }
    nread++;
  }
  sa02Printf("eid2hapdxy %d records read.\n",nread);
  fclose(fp);
  return 0;

}

int CVICALLBACK SetParameters (int panel, int control, int event,
                               void *callbackData, int eventData1, int eventData2) {
  //uint32_t address;
  //char saddress[0xFF],
  char fname[0xFF];

  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal(p3h, P3_INPUTFILE, fname);
      SetParametersFromFile(fname);

      break;
  }
  return 0;
}

int CVICALLBACK UploadGlobalParameters (int panel, int control, int event,
                                        void *callbackData, int eventData1, int eventData2) {
  uint32_t response[2]= {0,0};
  switch (event) {
    case EVENT_COMMIT:
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 1);
      {
        uint32_t gdata;

        int board,asic;
        int i=0,imin=0,imax=0;
        Rect trange;
        Point cell;
        int row=0;
        unsigned short val;
        sa02AsicGlobalRegister  *greg = (sa02AsicGlobalRegister *) &gdata ;
        uint16_t mask=GetConnectedFebMask();
//        GetCtrlVal(p1h,P1_BOARDNUMBER,&board);
        GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);

        if (control== P3_SELGPARLOAD) {
          GetTableSelection (p3h, P3_GREG, &trange);
          if ((trange.top!=0)&&(trange.left!=0)) {
            imin= trange.top - 1;
            imax= imin + trange.height;

          } else {
            if (!GetActiveTableCell(p3h, P3_GREG, &cell)) {
              imin = cell.y-1;
              imax = imin;
            } else return 0;
          }
        } else {
          imin=0;
          imax=4*4;
        }

        for (i=imin; i<imax; i++) {
          row=i+1;
          GetTableCellVal (p3h, P3_GREG, MakePoint (1,row), &val);
          greg->phasecmps = val;
          GetTableCellVal (p3h, P3_GREG, MakePoint (2,row), &val);
          greg->gain = val;
          GetTableCellVal (p3h, P3_GREG, MakePoint (3,row), &val);
          greg->shapingtime = val;
          GetTableCellVal (p3h, P3_GREG, MakePoint (4,row), &val);
          greg->comparator = val;
          GetTableCellVal (p3h, P3_GREG, MakePoint (5,row), &val);
          greg->vrdrive = val;
          GetTableCellVal (p3h, P3_GREG, MakePoint (6,row), &val);
          greg->monitor = val;
          //GetTableCellVal (p3h, P3_GREG, MakePoint (7,row), &val); greg->id = val;
          greg->id = 0;
          greg->unused=0;
          board=i/4;
          asic=i%4;

          if (mask & (1<<board) ) sa02Cmd(board,SA0x_ASIC0_GREG, gdata, asic, 0,1,response);
          if (ctrl_c) {
            break;
          }
        }
      }
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 0);
      sa02Printf("Global Parameters Uploaded to the ASICs\n");
      break;
  }
  return 0;
}

int CVICALLBACK UploadChannelParameters (int panel, int control, int event,
    void *callbackData, int eventData1, int eventData2) {
  uint32_t response[2]= {0,0};
  switch (event) {
    case EVENT_COMMIT:
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 1);
      {
        uint32_t cdata;
        int state;
        Rect trange;
        Point cell;

        sa02AsicChannelRegister *creg = (sa02AsicChannelRegister *) &cdata ;

        unsigned int i=0,imin=0,imax=0;
        int row=0;
        uint32_t board;
        uint16_t mask=GetConnectedFebMask();

        unsigned short val,asic,ch;

//        GetCtrlVal(p1h,P1_BOARDNUMBER, &board);
        GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);

        if ((panel==p3h)&&(control==P3_SELCPARLOAD)) {
          state = GetTableSelection (p3h, P3_CREG, &trange);
          if ((trange.top!=0)&&(trange.left!=0)) {
            imin= trange.top-1;
            imax= imin + trange.height;

          } else {
            if (!GetActiveTableCell(p3h, P3_CREG, &cell)) {
              imin = cell.y-1;
              imax = imin+1;
            } else return 0;
          }
        } else if ((panel==p1h)&&(control==P1_CHPARLOAD)) {
          GetCtrlVal(p1h,P1_NSLIX,&imin);
          imax=imin+1;
        } else {
          imin=0;
          imax=144*4;
        }

        for (i=imin; i<imax; i++) {
//          asic=(unsigned short )(i/36);
//          ch=(unsigned short )(i%36);
          int err = 0;
          row=i+1;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (1,row), &asic)) err=1;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (2,row), &ch)) err=1;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (3,row), &val)) err=1;
          creg->decaytime=val;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (4,row), &val)) err=1;
          creg->offset = val;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (5,row), &val)) err=1;
          creg->fineadj_unipol = val;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (6,row), &val)) err=1;
          creg->fineadj_diff = val;
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (7,row), &val)) err=1;
          creg->tpenb = val;
          //sa02Printf("===%d   %d\n",i, val);
          if (GetTableCellVal (p3h, P3_CREG, MakePoint (8,row), &val)) err=1;
          creg->kill = val;
          creg->unused=0;
          board=i/144;
          if (mask & (1<<board) ) sa02Cmd(board,SA0x_ASIC0_CREG, cdata, asic, ch,1,response);
          if (sa02Verbose >0) {
            sa02Printf("===%d\n",i);
          }
          if (err) sa02Printf("*** Table read error at row %d ***\n",row);
          if (ctrl_c) {
            break;
          }
        }
        sa02Printf("Channel Parameters Uploaded to the ASICs\n");

      }
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 0);
      break;
  }
  return 0;
}

int CVICALLBACK UploadFPGAParameters (int panel, int control, int event,
                                      void *callbackData, int eventData1, int eventData2) {

  int n=0;
  int i=0;
  int nb=0;
#define NDIM 400
  int asic=0;
  char buf[NDIM];
  char cmd[NDIM];
  char sasic[NDIM];
  uint32_t sa02code;
  uint32_t board;
  uint32_t response[2]= {0,0};

  switch (event) {
    case EVENT_COMMIT: {
      uint16_t mask=GetConnectedFebMask();
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 1);

      GetNumTextBoxLines(p3h, P3_FPGAPAR,&n);
      for (i=0; i<n; i++) {
        GetTextBoxLine(p3h, P3_FPGAPAR, i, buf);
        nb = sscanf(buf,"%s%s",cmd,sasic);
        asic =   strtoul (sasic,NULL,0);
        sa02code = sa02GetCmdCode(cmd);
        if (strcmp(cmd,"MUXASIC")==0) {
          asic = sa02MuxMap(asic);
        }
        for (board = 0; board < 4; board ++) if ( mask & (1 << board) ) sa02Cmd(board,sa02code, asic, 0, 0, 2,response);
        sa02Printf("%s\n",buf);
      }
      sa02Printf("FPGA Parameters Uploaded to FEBS\n");
      SetCtrlAttribute (panel, control, ATTR_DIMMED, 0);
      break;
    }
  }
  return 0;
}

int CVICALLBACK SetSelectionToVal (int panel, int control, int event,
                                   void *callbackData, int eventData1, int eventData2) {
  int state, input_cid=-1,output_cid=-1;
  Rect trange;
  unsigned short value;
  switch (event) {
    case EVENT_COMMIT:
      switch (control) {
        case P3_SETSELCPAR:
          input_cid=P3_SETCPAR;
          output_cid=P3_CREG;
          break;
        case P3_SETSELGPAR:
          input_cid=P3_SETGPAR;
          output_cid=P3_GREG;
          break;

      }
      state = GetTableSelection (p3h, output_cid, &trange);
      if ((trange.top!=0)&&(trange.left!=0)) {
        GetCtrlVal(p3h,input_cid, &value);
        state = FillTableCellRange (p3h, output_cid, trange, value);
      }
      break;
  }
  return 0;
}

int CVICALLBACK SelectMux (int panel, int control, int event,
                           void *callbackData, int eventData1, int eventData2) {
  int cid[4]= {P3_MUX0,P3_MUX1,P3_MUX2,P3_MUX3};
  int id=0,i;
  uint32_t sa02code;
  uint32_t board;
  uint32_t response[2]= {0,0};

  switch (event) {
    case EVENT_COMMIT:

      switch (control) {
        case P3_MUX0:
          id=0;
          break;
        case P3_MUX1:
          id=1;
          break;
        case P3_MUX2:
          id=2;
          break;
        case P3_MUX3:
          id=3;
          break;
        default:
          id=0;
      }
      SetCtrlVal(panel,control,1);
      sa02code = sa02GetCmdCode("MUX");
      GetCtrlVal(p1h,P1_BOARDNUMBER,&board);
      sa02Cmd(board,sa02code, id, 0, 0, 2,response);


      for (i=0; i<4; i++) {
        if (id!= i) {
          SetCtrlVal(panel,cid[i],0);
        }
      }
      sa02Printf("MUX %d\n",id);
      break;
  }
  return 0;
}

int CVICALLBACK UploadFromPanels (int panel, int control, int event,
                                  void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      UploadFPGAParameters(panel,control,event,callbackData,eventData1,eventData2);
      UploadChannelParameters(panel,control,event,callbackData,eventData1,eventData2);
      UploadGlobalParameters(panel,control,event,callbackData,eventData1,eventData2);
      break;
  }
  return 0;
}

double erf(double x, double par[], int npar) {
  double y=0;
  double x0= (x-par[0])*par[1];
  Erf(x0,&y);
  return (y);
}

int CVICALLBACK FitH2D (int panel, int control, int event,
                        void *callbackData, int eventData1, int eventData2) {
  char name[MAX_PATHNAME_LEN];

  switch (event) {
    case EVENT_COMMIT: {
      //sprintf(name ,"C:\\root\\bin\\root.exe");
      int status;
      char dfile[MAX_PATHNAME_LEN];
      char efile[MAX_PATHNAME_LEN];

      status = FileSelectPopup ("data", "*.th2d", ".th2d",
                                "Izberi datoteko s histogramom",
                                VAL_LOAD_BUTTON, 0, 0, 1, 0, efile);
      EscapeString(efile,dfile);
      sprintf(name ,"C:/root/bin/root.exe ../macros/sa02fit.cxx(\\\"%s\\\")", dfile);



      sa02Printf("%s\n",name);

      LaunchExecutable(name);


    }
    break;
  }
  return 0;
}

double Round(double x) {

  int ix= (int)x;
  if (x>0) {
    if (x - ix > 0.5 ) {
      return ix+1;
    } else {
      return ix;
    }
  } else {
    if (x - ix < -0.5 ) {
      return ix-1;
    } else {
      return ix;
    }
  }


}

//const double ffine    = -1.45; //  dac steps/offset unit  (fine)
const double foffset  = -13.;  // dac steps/offset unit (coarse)
const double ffine    = foffset/16.; //  dac steps/offset unit  (fine)

double sa02getshift(int offset, int fineadj_unipol ) {

  int c=offset;
  int f=fineadj_unipol;
  if (c>7) {
    c-=16;
  }
  if (f>7) {
    f-=16;
  }
  return foffset*c+ffine*f;
}

double sa02getoffset(double x, double fx, int *dx) {

  *dx = (int) Round(x/ fx) ;
  if (*dx>7) {
    *dx=7;
  }
  if (*dx<-8) {
    *dx=-8;
  }
  x=x-(*dx)*fx;
  if (*dx<0) {
    *dx+=16;
  }
  return x;
}

//______________________________________________________________________________
double GetMean(int fNpoints, double *fX, double *fY) {
// Return mean value of X
  int i;
  double sumw  = 0;
  double sumwx = 0;
  if (fNpoints <= 0) {
    return 0;
  }

  for (i=0; i<fNpoints; i++) {
    sumw += fY[i];
    sumwx += fX[i]* fY[i];
  }
  return sumwx/sumw;
}

//______________________________________________________________________________
double GetRMS(int fNpoints, double *fX, double *fY) {
// Return RMS of X

  int i;
  double sumw = 0, sumwx = 0,mean,rms2;
  double sumwx2 = 0;
  if (fNpoints <= 0) {
    return 0;
  }

  for (i=0; i<fNpoints; i++) {
    sumwx += fX[i]* fY[i];
    sumw += fY[i];
    sumwx2 += fX[i]* fX[i]* fY[i];

  }
  if (sumw <= 0) {
    return 0;
  }
  mean = sumwx/sumw;
  rms2 = fabs(sumwx2/sumw -mean*mean);
  return sqrt(rms2);
}


int FitGraph(int mode, int n, double *x, double *y, double *par) {
  const double threshold=0.5;
  ssize_t i,imax,imin;
  double dmax,dmin;
//  double rms=0;
//  double sum=0;

  MaxMin1D(y,n,&dmax,&imax,&dmin,&imin);
  switch (mode) {
    case 0:
      par[0]=x[imax];
      par[1]=0;
      break;
    case 1:
      for (i=0; i<n; i++)
        if (y[i]>threshold) {
          par[0]=x[i];
        }
      par[1]=0;
      break;
    case 2:
      par[0]=GetMean(n,x,y);
      par[1]=GetRMS(n,x,y);
      break;
    case 3:
      break;
    case 4: {
      int npar=2;
      double fitpar[2];
      double rms;
      NonLinearFit (y, x, datayfit,n, erf, fitpar, npar, &rms);
      par[0]=0;
      par[1]=0;
      break;
    }
    default:
      break;
  }
  return 0;
}

int CVICALLBACK FitH2DCoarse (int panel, int control, int event,
                              void *callbackData, int eventData1, int eventData2) {
  double mean[144*2*4];
  double rms[144*2*4];
  int ix,iy;

  double fpar[3]= {0,0,0};
  int h2=0;
  switch (event) {
    case EVENT_COMMIT: {
      unsigned short offsets[144*2*4];
      double x;
      int offset=0, fineadj_unipol=0;
      //unsigned short val;
      double mean0,rms0;
      uint16_t mask=GetConnectedFebMask();
      int nch = H2DGetNbinsX(h2);
      int npt = H2DGetNbinsY(h2);
      int fitmode  =0;
      double minx  =  H2DGetMinX(h2);
      double stepx =  H2DGetStepX(h2);
      GetCtrlVal(p3h,P3_FITMODE,&fitmode);
      GetCtrlVal(p3h,P3_TARGETOFFSET,&mean0);
      GetCtrlVal(p3h,P3_TARGETRMS,&rms0);
      for (iy=0; iy < npt; iy++ ) {
        datax[iy] = H2DGetYBinCenter(h2,iy);
      }
      GetTableCellRangeVals (p3h, P3_CREG, MakeRect (1, 4, 144*4, 2), offsets, VAL_ROW_MAJOR);
      for (ix=0; ix < nch; ix++ ) {
        if (!(mask & (1<<(ix/144)) )) {
          mean[ix] = datax[0];
          rms[ix]  = 0;
          continue;
        }
        for (iy=0; iy < npt; iy++ ) {
          datay[iy] = H2DGetBinContent(h2,ix,iy); // /H2DGetMax(h2);
        }
        FitGraph(fitmode, npt, datax , datay, fpar);
        mean[ix]=fpar[0];
        rms[ix] =fpar[1];
        offset         = offsets[ix*2];
        fineadj_unipol = offsets[ix*2+1];

        x =  sa02getshift(offset, fineadj_unipol);
        x += (mean0-(mean[ix]+rms0*rms[ix]));
        /*if (x<0) {
          sa02Printf(" ch. %d mean+%f*sigma %g above threshold %f \n",ix, rms0,mean[ix]+rms0*rms[ix],mean0);
        }*/

        x = sa02getoffset(x, foffset, &offset);
        x = sa02getoffset(x, ffine  , &fineadj_unipol);
        //sa02Printf("offsets ch. %d mean=%f rms %f  shift=%f calcshift=%f offset %d fineadj %d\n",ix, mean[ix],rms[ix], x, sa02getshift(offset, fineadj_unipol),offset, fineadj_unipol);
        offsets[ix*2]=(unsigned short) offset;
        offsets[ix*2+1]=(unsigned short) fineadj_unipol;
        ProcessSystemEvents();
      }

      SetTableCellRangeVals (p3h, P3_CREG, MakeRect (1, 4, 144*4, 2), offsets, VAL_ROW_MAJOR);


      if (nch>0) {
        if (plothandle2dfit) {
          DeleteGraphPlot (p1h, P1_GRAPH2D, plothandle2dfit, VAL_IMMEDIATE_DRAW);
        }
        plothandle2dfit = PlotWaveform (p1h, P1_GRAPH2D, mean, nch,
                                        VAL_DOUBLE, 1.0, 0.0, minx,
                                        stepx, VAL_FAT_LINE,
                                        VAL_EMPTY_SQUARE, VAL_SOLID, 1,
                                        VAL_YELLOW);
        if (plothandleslix) {
          DeleteGraphPlot (p1h, P1_GRAPHY, plothandleslix, VAL_IMMEDIATE_DRAW);
        }

        plothandleslix = PlotWaveform (p1h, P1_GRAPHY, rms, nch,
                                       VAL_DOUBLE, 1.0, 0.0, minx,
                                       stepx, VAL_FAT_LINE,
                                       VAL_EMPTY_SQUARE, VAL_SOLID, 1,
                                       VAL_BLUE);
        sa02Printf("offset calculated:\n");
      }
    }
    break;
  }
  return 0;
}

int CVICALLBACK LedCB (int panel, int control, int event,
                       void *callbackData, int eventData1, int eventData2) {

  if (!gBELLEPTS)return 0;

  switch (event) {

    case EVENT_COMMIT: {
      char saddress[0xFF];
      uint32_t address;
      uint32_t value=0;
      GetCtrlVal(p3h,P3_ADDRESS, saddress);
      address =  strtoul (saddress,NULL,0);
      VME_A32D32_R(address+FEB_DEADBEEF, &value);
      sa02Printf("READ at FEB_DEADBEEF 0x%08x\n",  value);


      GetCtrlVal(p1h,P1_PTSLED,&value);
      value++;
      sa02Printf("LedCB ADDR 0x%08x VAL %d\n",address,  value);
      //VME_A24D32_W(address,&value);

      VME_A32D32_W(address,value);
      /*
      NIM standard level ports.

            You should write 0x7600 to address : baseaddress + 4 .

            0x7600 means the connection
            CLKOUT1 -> 7 -> CLK_VOUT1 (VOUT1 pin of FPGA)
            CLKOUT0 -> 6 -> CLK_VOUT0 (VOUT1 pin of FPGA)
            SCLK    -> 0 -> CLK_IN    (internal clock)
            PCLK    -> 0 -> CLK_IN    (internal clock)
      */


      if (value==2) {
        value=0x7600;
      } else {
        value=0;
      }
      VME_A32D32_W(address+4,value); // enable outputs
    }
    sa02Printf("SizeOf(Double)=%d\n",sizeof(double));
    break;
  }
  return 0;
}

int CVICALLBACK SetPositionAndMux (int panel, int control, int event,
                                   void *callbackData, int eventData1, int eventData2) {
  const float fx= (float)(1000./0.3595); // 4M scaling factor steps/mm
  int chx,x0,chy,y0;
  float gapx,gapy, dx , dy;

  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal (p2h, P2_CHX,  &chx);
      GetCtrlVal (p2h, P2_CHY,  &chy);
      GetCtrlVal (p2h, P2_GAPX,  &gapx);
      GetCtrlVal (p2h, P2_GAPX,  &gapy);
      GetCtrlVal (p2h, P2_DX, &dx);
      GetCtrlVal (p2h, P2_DX, &dy);
      GetCtrlVal (p2h, P2_XC,  &x0);
      GetCtrlVal (p2h, P2_YC,  &y0);
      y0 = (int)(y0 - 5.5* fx * dy  - gapy * fx * 0.5);
      x0 = (int)(x0 - 5.5* fx * dx  - gapx * fx * 0.5);
      if (gMIKRO_Y) {
        posrec.yset =  (int32_t)(y0+dy *fx * chy);
        if (chy>5) {
          posrec.yset +=gapy * fx;
        }
        MIKRO_MoveTo (MIKRO_Y, posrec.yset);
        sa02Printf("->MIKRO_MoveTo (2, y);%d\n",posrec.yset);
      }
      if (gMIKRO_X) {
        posrec.xset=(int32_t)(x0+dx*fx*chx);
        if (chx>5) {
          posrec.xset +=gapx * fx;
        }
        MIKRO_MoveTo (MIKRO_X, posrec.xset);
        sa02Printf("->MIKRO_MoveTo (1, x);%d\n",posrec.xset);
      }
//      GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);
      SetCMon(chx,chy);
      break;
  }
  return 0;
}

int CVICALLBACK SetCenter (int panel, int control, int event,
                           void *callbackData, int eventData1, int eventData2) {
  int x0,y0;
  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal (p2h, P2_XC,  &x0);
      GetCtrlVal (p2h, P2_YC,  &y0);
      if (gMIKRO_X)  MIKRO_MoveTo (MIKRO_X, x0);
      if (gMIKRO_Y)  MIKRO_MoveTo (MIKRO_Y, y0);
      break;
  }
  return 0;
}

void CVICALLBACK EndOfThread ( CmtThreadPoolHandle poolhandle,
                               CmtThreadFunctionID functionID, unsigned int event,
                               int value, void *callbackData  ) {

  daq_on=0;
  SetDimming(0);
  sa02Printf("End of Thread \n");
  return ;

}

int Asic_TENB_Shift( void ) {

  int i,stanje;
  unsigned short inmask[144], outmask[144], tmp;
  for (int board = 0; board<4; board++) {
    stanje = GetTableCellRangeVals (p3h, P3_CREG, MakeRect (1+board*144, 7, 144, 1),
                                    inmask, VAL_COLUMN_MAJOR);
    tmp = inmask[143];
    for (i=0; i<143; i++) {
      outmask[i+1]=inmask[i];
    }
    outmask[0]=tmp;

    stanje = SetTableCellRangeVals (p3h, P3_CREG, MakeRect (1+board*144, 7, 144, 1),
                                    outmask, VAL_COLUMN_MAJOR);

  }
  return 0;
}

int CVICALLBACK daq_scanpar (void *functionData) {


  char filename[0xFF];
  int scanpar=0;
  int ix, x0,dx,nx;
  int value,state;
  Rect save_range,trange;
  int cid=0;
  int daqexe;
  time_t t,told=0, tstart;
  FILE *fp;
  int spar;
  int nch;
  const int maxrange[20]= {0,0,8,16,16,16,2,2,2,0, 4,4,4,2,256,4,512};

  trange.top=0;
  trange.left=0;

  GetCtrlVal(p3h,P3_SCANPAR, &scanpar);
  sa02Printf("%d\n",scanpar);
  GetCtrlVal(p3h,P3_X0, &x0);
  GetCtrlVal(p3h,P3_DX, &dx);
  GetCtrlVal(p3h,P3_NX, &nx);
  GetCtrlVal(p3h,P3_DAQEXE,&daqexe);
  GetCtrlVal(p1h,P1_OUTPUTFILE, filename);


  if (!scanpar) {
    return 0;
  }
  if (scanpar>10) {
    cid=P3_GREG;
    spar=scanpar-10;
    nch=4*4;

  } else {
    cid=P3_CREG;
    spar=scanpar;
    nch=144*4;

  }
  if (spar==1) {
    spar=7;
  }
  sa02Printf("Range:%d\n",maxrange[scanpar-1]);
  state = GetTableSelection (p3h, cid, &save_range);

  trange = MakeRect (1, spar, nch, 1);
  state = SetTableSelection (p3h, cid, trange);
  if ((trange.top!=0)&&(trange.left!=0)) {



    time(&t);
    tstart=t;
    if (daqexe) {
      iteratorrec.id = ITERATORREC_ID;
      iteratorrec.len = sizeof(iteratorrec);
      iteratorrec.value = x0;
      iteratorrec.n     = nx;
      iteratorrec.step  = dx;
      iteratorrec.level = 2;
      fp = fopen(filename, "ab");
      if(fp) {
        fwrite (&datrec, 1, datrec.len, fp);
        fclose(fp);
      }
      sa02Printf("new ITERATORREC recid=0x%x\n", iteratorrec.id);
    }


    for (ix=0; ix<nx; ix++) {
      value = ix*dx + x0;
      if (scanpar!=1) {
        state = FillTableCellRange (p3h, cid, MakeRect (1, spar, nch, 1), value%maxrange[scanpar-1]);
        if (maxrange[scanpar-1] && value/maxrange[scanpar-1]) {
          state = FillTableCellRange (p3h, cid, MakeRect (1, spar-1, nch, 1), value/maxrange[scanpar-1]);
        }
      }
      switch (cid) {
        case P3_CREG:
          UploadChannelParameters(p3h,cid,EVENT_COMMIT,functionData,0,0);
          break;
        case P3_GREG:
          UploadGlobalParameters (p3h,cid,EVENT_COMMIT,functionData,0,0);
          break;
      }
      if (scanpar==1) {
        Asic_TENB_Shift();
      }
      if (t!=told  ) {
        ProcessSystemEvents ();
      }
      if (ctrl_c) {
        break;
      }

      if (daqexe) {
        datrec.id = DATREC_ID;
        datrec.len = sizeof(datrec);
        datrec.cmd    =0xBEEF0000+ scanpar;
        datrec.data   =value;
        datrec.chip   =-1;
        datrec.channel=-1;
        datrec.retval =value;

        fp = fopen(filename, "ab");
        if(fp) {
          fwrite (&datrec, 1, datrec.len, fp);
          fclose(fp);
        }
        sa02Printf("new DATREC recid=0x%x  datrec->cmd=0x%x\n", datrec.id , datrec.cmd);
        daq(NULL);
        sa02Printf("H2D image saved as %s\n", filename);

      }
      if (ctrl_c) {
        break;
      }

      if (t!=told  ) {
        ProcessSystemEvents ();
      }
      told=t;
      time(&t);

    }
  }
  state = SetTableSelection (p3h, cid, save_range);





  return 0;
}


int CVICALLBACK ExportParameters (int panel, int control, int event,
                                  void *callbackData, int eventData1, int eventData2) {
  int status;
  char filename[MAX_PATHNAME_LEN];
  switch (event) {
    case EVENT_COMMIT:

      status = FileSelectPopup ("./parameters/", "*.param", "*.param",
                                "Export Parameters to file", VAL_SAVE_BUTTON, 0,
                                0, 1, 1, filename);
      sa02Printf("ExportParameters to %d\n",MAX_PATHNAME_LEN);
      switch (status) {
        case 1:
          MessagePopup ("Warning", "File exist. Remove it first or choose another file");
          break;
        case 2: {
          int n,i,row,asic,ch;
          unsigned short val;
          time_t t;
          char buf[MAX_PATHNAME_LEN];
          FILE   *fp = fopen(filename, "w");
          if (fp) {
            //--------------------------------------------------- Parameters header
            time(&t);
            fprintf(fp, "#Parameter exported from CVI %s\n",ctime(&t) );
            //--------------------------------------------------- FPGA parameters
            GetNumTextBoxLines(p3h, P3_FPGAPAR,&n);
            for (i=0; i<n; i++) {
              GetTextBoxLine(p3h, P3_FPGAPAR, i, buf);
              fprintf(fp, "%s\n",buf);
            }
            //--------------------------------------------------- Global parameters
            for (row=1; row<1+16; row++) {
              int irow = (row-1)%4;
              int iboard = (row-1)/4;
              if ( (row-1)%4 == 0 ) fprintf(fp, "param_board %d\n",iboard);
              fprintf(fp, "## global parameter for chip %d\n",(row-1)%4);
              fprintf(fp, "param_global %d 0x1ffff\n",irow);
              GetTableCellVal (p3h, P3_GREG, MakePoint (1,row), &val);
              fprintf(fp, "phasecmps %d 0x%x\n",irow,val);
              GetTableCellVal (p3h, P3_GREG, MakePoint (2,row), &val);
              fprintf(fp, "gain %d 0x%x\n",irow,val);
              GetTableCellVal (p3h, P3_GREG, MakePoint (3,row), &val);
              fprintf(fp, "shapingtime %d 0x%x\n",irow,val);
              GetTableCellVal (p3h, P3_GREG, MakePoint (4,row), &val);
              fprintf(fp, "comparator %d 0x%x\n",irow,val);
              GetTableCellVal (p3h, P3_GREG, MakePoint (5,row), &val);
              fprintf(fp, "vrdrive %d 0x%x\n",irow,val);
              GetTableCellVal (p3h, P3_GREG, MakePoint (6,row), &val);
              fprintf(fp, "monitor %d 0x%x\n",irow,val);
              GetTableCellVal (p3h, P3_GREG, MakePoint (7,row), &val);
              fprintf(fp, "id %d 0x%x\n",irow,val);

              fprintf(fp, "load_global  %d\n\n\n",irow);
            }

            //--------------------------------------------------- Channel parameters
            for (i=0; i<144*4; i++) {
              int board = i/144;
              int j= i%144;
              asic=(j/36);
              ch=j%36;
              row=(i+1);
              if (i%36==0) {
                fprintf(fp, "# channel parameter for chip %d\n\n",asic);
              }

              if (i%144 == 0) fprintf(fp, "param_board %d\n",board);
              fprintf(fp, "param_ch       %d %d 0x0000\n",asic,ch);

              GetTableCellVal (p3h, P3_CREG, MakePoint (3,row), &val);
              fprintf(fp, "decaytime %d %d 0x%x\n",asic,ch,val);
              GetTableCellVal (p3h, P3_CREG, MakePoint (4,row), &val);
              fprintf(fp, "offset %d %d 0x%x\n",asic,ch,val);
              GetTableCellVal (p3h, P3_CREG, MakePoint (5,row), &val);
              fprintf(fp, "fineadj_unipol %d %d 0x%x\n",asic,ch,val);
              GetTableCellVal (p3h, P3_CREG, MakePoint (6,row), &val);
              fprintf(fp, "fineadj_diff %d %d 0x%x\n",asic,ch,val);
              GetTableCellVal (p3h, P3_CREG, MakePoint (7,row), &val);
              fprintf(fp, "tpenb %d %d 0x%x\n",asic,ch,val);
              GetTableCellVal (p3h, P3_CREG, MakePoint (8,row), &val);
              fprintf(fp, "kill %d %d 0x%x\n",asic,ch,val);
              fprintf(fp, "load_ch  %d %d\n\n\n",asic,ch);
            }

            fclose(fp);

          }
          break;
        }
      }

      break;
  }
  return 0;
}



int ProcessUserEvent(int pID, int rID,int mode){    
    ThreadFunctionPtr mythread = NULL;
    if (pID ==p1h && rID == P1_DAQ            ) mythread=daq;
    if (pID ==p1h && rID == P1_READOUT        ) mythread=daq_readonly;
    if (pID ==p1h && rID == P1_FPGAWRITE      ) mythread=MultiFpgaWrite;
    if (pID ==p1h && rID == P1_MULTIFPGAWRITE ) mythread=MultiFpgaWrite;
    if (pID ==p1h && rID == P1_TESTING        ) mythread=Testing;
    if (pID ==p2h && rID == P2_DAQ            ) mythread=daq_scan;
    if (pID ==p6h && rID == MINIRICH_START    ) mythread=daq;
    if (pID ==p2h && rID == P2_RUNSCRIPT      ) {
      char scriptname[MAX_PATHNAME_LEN] ;

      int status = FileSelectPopup ("./scripts/", "*.txt", "*.txt",
                                    "Select Script file", VAL_LOAD_BUTTON, 0, 0,
                                    1, 0, scriptname);
      if (status) {
        SetCtrlVal(p1h, P1_SCRIPTNAME, scriptname );
        mythread=run_script;
      }
    }
    if (pID ==p1h && rID == P1_RUNSCRIPT      ) mythread=run_script;
    if (pID ==p3h && rID == P3_DAQ            ) mythread=daq_scanpar;
    if (pID ==p4h && rID == P4_DAQ            ) mythread=V729_daq;
    if (mythread!=NULL) {
      sa02Printf("New Thread panel=%d button=%d\n", pID, rID);
      ctrl_c=0;
      daq_on = 1;
      SetDimming(1);
      if (mode){
        CmtScheduleThreadPoolFunctionAdv (poolHandle, mythread, &rID,
                                        DEFAULT_THREAD_PRIORITY,
                                        EndOfThread,
                                        EVENT_TP_THREAD_FUNCTION_END,
                                        NULL, RUN_IN_SCHEDULED_THREAD,
                                        &tfID);
      } else {
        mythread(NULL);
      }  
    }

    if ( pID==p1h && rID == P1_SLOWC ) {
      uint32_t board;
      GetCtrlVal(p1h,P1_BOARDNUMBER, &board);
      SlowControl(board, NULL);
    }
    // if ( pID==p1h && rID == P1_STEPONE )       StepOne();
    if ( pID==p1h && rID == P1_FEBTESTANA ) FebTestAna();
    if ( pID==p1h && rID == P1_TEST )       FebTest();
    if ( pID==p1h && rID == P1_MODULETEST ) ModuleTest();

    if ( pID==p1h && rID == P1_GET_FPGA_SERIAL ) {
      int ison=0;
      GetCtrlVal(p1h,P1_BOARDTYPE,&sa02BoardType);
      for (int board=0; board<4; board++) {
        char saddress[0xff]="";
        GetCtrlVal(p1h, hapd_onoff[board], &ison);
        sa02GetSerial(board, saddress);
        sa02Printf("SERIAL FPGA = %s \n", saddress);
        SetCtrlVal(p1h,fpga_serials[board],saddress);
      }
    };

    if ( ( pID==p1h && rID == P1_STOP )
         || ( pID==p2h && rID == P2_STOP )
         || ( pID==p3h && rID == P3_STOP )  
         || ( pID==p6h && rID == MINIRICH_STOP )  
         || ( pID==p4h && rID == P4_STOP ) ) {
      sa02Printf("Stopping the  Thread %d\n", tfID);
      ctrl_c=1;
    }
    if (pID ==p5h) {
      if (rID == P5_SET_DAC_HV_ON) set_dac(1);
      if (rID == P5_SET_DAC_HV_OFF) set_dac(0);
      if (rID == P5_SET_HV_ON) set_hv(1);
      if (rID == P5_SET_HV_OFF) set_hv(0);
    }
    return 0;
}



void CVICALLBACK QueueUserEventCallback (CmtTSQHandle queueHandle, unsigned int event, int value, void *callbackData) {
  //int *data= (int *)  callbackData;
  int mdata[2];
  CmtReadTSQData (queueHandle, mdata, 1, 0, 0);
  sa02Printf("QueueUserEvent --->TSQ  %d %d\n", mdata[0],mdata[1]);
  QueueUserEvent (1001, mdata[0], mdata[1]);
}

/*************************** MAIN ***************************/

int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       LPSTR lpszCmdLine, int nCmdShow) {

  char title[0xFF];
  char saddress[0xff]="";
  //uint32_t board;
  int i;
  int status=0;

  if (InitCVIRTE (hInstance, 0, 0) == 0) {
    return -1;  /* out of memory */
  }

  SetSleepPolicy(VAL_SLEEP_MORE);
  CmtNewThreadPool (MAX_THREADS,  &poolHandle);

  if ( (status = CmtNewTSQ (1, 2*sizeof(int), OPT_TSQ_AUTO_FLUSH_ALL, &pTSQ)) <0)
    printf("CmtNewTSQ cannot be installed\n");
  if ( (status = CmtInstallTSQCallback (pTSQ, EVENT_TSQ_ITEMS_IN_QUEUE, EVENT_TSQ_QUEUE_SIZE,
                                       QueueUserEventCallback, pTSQData, CmtGetCurrentThreadID(), NULL))  <0)
    printf("CmtInstallTSQCallback cannot be installed\n");  ;

  SetStdioPort (CVI_STDIO_WINDOW );

  readIni("febdaq.ini");

  VME_START(gVME_CONTROLLER);
  if ( gCAEN_V288 ) {
    V288_Map(0,gCAEN_V288);
    V288_Init(0);
  }

  if (gMIKRO_PORT) {
    MIKRO_Open (gMIKRO_PORT);
    if (gMIKRO_X) MIKRO_Init (gMIKRO_X,0);
    if (gMIKRO_Y) MIKRO_Init (gMIKRO_Y,0);
    if (gMIKRO_Z) MIKRO_Init (gMIKRO_Z,0);
  }

  if ((p1h = LoadPanel (0, "sa02_CVI.uir", P1)) < 0) return -1;
  if ((p2h = LoadPanel (0, "sa02_CVI.uir", P2)) < 0) return -1;
  if ((p3h = LoadPanel (0, "sa02_CVI.uir", P3)) < 0) return -1;
  if ((p4h = V729_LoadPanel (0, "CAEN_V729\\CAEN_V729_CVI.uir", P4)) < 0) return -1;
  if ((p5h = LoadPanel (0, "sa02_CVI.uir", P5)) < 0) return -1;
  if ((p6h = LoadPanel (0, "ICFA\\minirich.uir", MINIRICH)) < 0) return -1;
  if ((pm1 = LoadMenuBar (p1h, "sa02_CVI.uir", MENU)) < 0)  return -1;

  SetPanelMenuBar(p1h, pm1);
  DisplayPanel (p1h);

  LoadUirHeader("sa02_CVI.h");
  LoadUirHeader("CAEN_V729\\CAEN_V729_CVI.h");

  SetCtrlVal(p2h,P2_XC,gCENTER_X);
  SetCtrlVal(p2h,P2_YC,gCENTER_Y);

  SetCtrlVal(p3h, P3_INPUTFILE,gFEBParam);
  SetParametersFromFile(gFEBParam);

  SetCtrlAttribute (p1h, P1_GRAPH2D, ATTR_CALLBACK_DATA, (void *)integer_val);
  SetCtrlAttribute (p1h, P1_SLIY, ATTR_CALLBACK_DATA, (void *)integer_val);
  SetCtrlAttribute (p1h, P1_SLIX, ATTR_CALLBACK_DATA, (void *)integer_val);
  SetCtrlAttribute (p1h, P1_NSLIY, ATTR_CALLBACK_DATA, (void *)integer_val);
  SetCtrlAttribute (p1h, P1_NSLIX, ATTR_CALLBACK_DATA, (void *)integer_val);

  for (i=0; i<12; i++) {
    SetTraceAttributeEx (p1h, chart_control[0], i+1, ATTR_TRACE_LG_TEXT, (char *) slowcname[i]);
  }

  GetPanelAttribute (p1h, ATTR_TITLE, title );
  if (gVME_CONTROLLER == WIENER_VMEMM) sprintf( title, "%s + WIENER_VMEMM", title );
  if (gVME_CONTROLLER == WIENER_VMUSB) sprintf( title, "%s + WIENER_VMUSB", title );
  if (gVME_CONTROLLER == CAEN_V1718) sprintf( title, "%s + CAEN_V1718", title );
  if (gCAEN_V1495) sprintf( title, "%s + CAEN_V1495", title );
  if (gCAEN_V288 ) sprintf( title, "%s + CAEN_V288", title );

  if (gBELLEPTS) {
    sprintf( title, "%s + BELLEPTS", title );
    sprintf(saddress,"0x%08x", gBELLEPTS );
    SetCtrlVal(p3h,P3_ADDRESS,saddress );
  }
  if (gMIKRO_PORT)
    sprintf( title, "%s + USE_MIKRO", title );
  else
    sprintf( title, "%s + MIKRO not used", title );
  SetPanelAttribute (p1h, ATTR_TITLE, title );

  for (i=0; i<4; i++)
    SetCtrlVal(p1h,hapd_onoff[i],gFEBMask&(1<<i));
  SetCtrlVal(p1h,P1_SENDSWTRIG,gTriggerType);
  SetCtrlVal(p1h,P1_TPENB,CHECK_BIT(uInterf,0));

  sa02SetAddress(strtoul (saddress,NULL,0));

  LedCB(p1h,P1_PTSLED,EVENT_COMMIT, NULL,0,0);


  StdIo2FileCB (p1h, P1_STDIOLOG, EVENT_COMMIT, NULL,0,0);
  InitColors();
  sa02Printf("Panels=%d %d %d %d\n", p1h, p2h,p3h,p4h);
  GetCtrlVal(p1h,P1_VERBOSE,&sa02Verbose);

  LoadElectronicMap("eid2hapdxy.map");
  icfa_Init();
 
 
  loop_on=1;
  do {
    GetUserEvent (1, &pID, &rID);  
    ProcessUserEvent(pID,rID,1);
  } while (loop_on);

  CmtDiscardThreadPool (poolHandle);
  DiscardPanel (p4h);
  DiscardPanel (p3h);
  DiscardPanel (p2h);
  DiscardPanel (p1h);

  if (gMIKRO_PORT) MIKRO_Close ();


  VME_STOP();
  return 0;
}

int CVICALLBACK ResetStdOut (int panel, int control, int event,
                             void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      ResetTextBox (p1h,P1_STDIO,"");
      break;
  }
  return 0;
}

int CVICALLBACK TrgHvMon (int panel, int control, int event,
                          void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_TIMER_TICK:
      hvmon=1;
      break;
  }
  return 0;
}


//---------------------------------------------------------------------

int Pts_write(uint32_t addr, uint32_t data ) {
  VME_A32D32_W(addr,data);
  return 0;
}

int Pts_Mwrite(uint32_t addr, uint32_t data ) {
  VME_MW(VME_A32, VME_D32, addr,data);
  return 0;
}

int Pts_read(uint32_t addr, uint32_t *data ) {
  VME_A32D32_R(addr,data);
  return 0;
}

int Pts_Mread(uint32_t addr, uint32_t *data ) {
  VME_MRRST();
  VME_MR(VME_A32, VME_D32,addr, data);
  VME_MREXEC(data);
  return 0;
}


int Pts_erase( uint32_t addr, int verbose ) {
  uint32_t dum;

  Pts_write( addr + ADR_CSR1, 0 );
  Delay(0.1);
  Pts_read( addr +ADR_CSR1, &dum);
  if( verbose ) {
    sa02Printf( "CSR1(0x%02x) = 0x%04x\n", ADR_CSR1,dum & 0xffff );

  }
  Pts_write( addr +ADR_CSR1, CSR1_PROGRAM_ );
  Delay(0.1);
  Pts_read( addr +ADR_CSR1, &dum);
  if( verbose ) {
    sa02Printf( "CSR1(0x%02x) = 0x%04x\n", ADR_CSR1, dum & 0xffff );

  }
  return 1;
}

int Pts_configure_bit(uint32_t addr, const char *filename, int mode, int verbose ) {
  int c,j;
  int dummyword;
  FILE *fp;
  const long byte_per_dot = BYTE_PER_DOT;
  unsigned long nchar = 0;

  fp = fopen(filename, "rb");
  if( fp == NULL ) {
    if( verbose ) {
      sa02Printf(  "cannot open \"%s\"\n", filename );
    }
    return -1;
  }
  if(verbose) sa02Printf(  "file \"%s\" opened.\n", filename );

  /* ------------------------------------------------------------ *\
    The data for the configuration start from 0xffff_ffff_aa99_aa66
    ( cf. xapp138; we don't know the definition of the BIT file )
  \* ------------------------------------------------------------ */

  dummyword = 0;
  do {
    if( (c = getc( fp )) == EOF ) {
      if(verbose) {
        sa02Printf( "EOF detected. Exit.\n");


      }
      return -1;
    }
    (c == 0xff) ? dummyword++ : (dummyword=0);
  } while( dummyword < 4 );

  if( mode == SLAVESERIAL_MODE ) {
    if(verbose)  sa02Printf("slave serial mode");
    Pts_write( addr +ADR_MODE, mode );
    Pts_erase( addr, verbose );
    for( j=0; j<32; j++ ) Pts_write( addr + ADR_CFG, 0x1 );
    while( (c=getc(fp))!=EOF ) {
      for( j=0; j<8; j++ ) Pts_write( addr + ADR_CFG, (c>>(7-j))&0x1 );
      nchar++;
      if( verbose && nchar%byte_per_dot==0 ) {
        sa02Printf( "#");
      }
    }
  } else if( mode == SELECTMAP_MODE ) {
    if( verbose ) sa02Printf("select map mode\n");
    Pts_write( addr + ADR_MODE, SELECTMAP_MODE );
    Pts_erase( addr, verbose );
    VME_MWRST();
    for( j=0; j<4; j++ ) Pts_Mwrite( addr + ADR_CFG, 0xff );
    VME_MWEXEC();

    VME_MWRST();
    while( (c=getc(fp))!=EOF ) {
      int cc = 0;
      for(j=0; j<8; j++) cc |= ((c&(1<<j))>>j)<<(7-j);
      Pts_Mwrite( addr + ADR_CFG, cc );
      nchar++;
      if( verbose && nchar%byte_per_dot==0 ) {
        VME_MWEXEC();
        VME_MWRST();
        sa02Printf( "#");

      }
    }
    VME_MWEXEC();
  } else {
    if(verbose) {
      sa02Printf( "\nIllegal mode\n");

    }
    return -1;
  }
  if(verbose) {
    sa02Printf("\ntotal %ld bits\n", nchar);
  }
  fclose(fp);
  return Pts_check_configure( addr, verbose );
}

int Pts_check_configure( uint32_t addr ,int verbose ) {
  uint32_t csr1_value;
  Pts_read(addr + ADR_CSR1,&csr1_value);
  if(verbose) {
    sa02Printf("CSR1(0x%02x)=0x%04x\n",ADR_CSR1,csr1_value&0xffff);
  }
  if(csr1_value&CSR1_DONE) {
    if(verbose) sa02Printf("configure complete.\n");
    return 1;
  } else {
    if(verbose)  sa02Printf("configure not complete.");
    return -1;
  }
}


int CVICALLBACK PtsDownloadCB (int panel, int control, int event,
                               void *callbackData, int eventData1, int eventData2) {
  char filename[254];
  int mode=0;
  char saddress[0xFF];
  uint32_t addr;


  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal(p3h,P3_ADDRESS, saddress);
      addr=  strtoul (saddress,NULL,0);
      GetCtrlVal(p3h,P3_PTSFIRMWARE,filename);
      GetCtrlVal(p3h,P3_PTSMODE,&mode);
      if(VME_CONNECTED() >=0 ) {
        Pts_configure_bit( addr , filename, mode,  1 );
      } else {
        MessagePopup ("Warning", "Connect VME!!");
      }
      break;
  }
  return 0;
}



int CVICALLBACK SelectPtsOutputCB (int panel, int control, int event,
                                   void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT: {
      unsigned short value;
      GetCtrlVal(panel,control,&value);
      sa02Printf("Selecting Pts Output Channel %d\n",value);
      Sa02SetPtsOutput(value);
      break;
    }
  }
  return 0;
}

int CVICALLBACK SendTriggerTypeCB (int panel, int control, int event,
                                   void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT: {
      int trglen, trg;
      uint16_t mask;
      //int ison;
      GetCtrlVal(p1h,P1_SENDSWTRIG,&trg);
      GetCtrlVal(p1h,P1_INTTRGLEN, &trglen);
      mask=GetConnectedFebMask();
      sa02Printf("Selecting Trigger %d length of the internal triger %d mask =%04x\n", trg, trglen);
      Sa02SelectTriggerWithMaskAndLength (trg, mask, trglen);

      break;
    }
  }
  return 0;
}

int CVICALLBACK StdIo2FileCB (int panel, int control, int event,
                              void *callbackData, int eventData1, int eventData2) {
  switch (event) {
    case EVENT_COMMIT:
      GetCtrlVal(p1h,P1_STDIOLOG, &gLog);
      break;
  }
  return 0;
}